[llvm-commits] [llvm] r45575 - in /llvm/trunk: include/llvm/CodeGen/MachineRelocation.h include/llvm/Target/TargetJITInfo.h lib/ExecutionEngine/JIT/JITEmitter.cpp lib/Target/X86/X86CodeEmitter.cpp lib/Target/X86/X86JITInfo.cpp lib/Target/X86/X86JITInfo.h

Evan Cheng evan.cheng at apple.com
Fri Jan 4 02:46:53 PST 2008


Author: evancheng
Date: Fri Jan  4 04:46:51 2008
New Revision: 45575

URL: http://llvm.org/viewvc/llvm-project?rev=45575&view=rev
Log:
X86 PIC JIT support fixes: encoding bugs, add lazy pointer stubs support.

Modified:
    llvm/trunk/include/llvm/CodeGen/MachineRelocation.h
    llvm/trunk/include/llvm/Target/TargetJITInfo.h
    llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp
    llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp
    llvm/trunk/lib/Target/X86/X86JITInfo.cpp
    llvm/trunk/lib/Target/X86/X86JITInfo.h

Modified: llvm/trunk/include/llvm/CodeGen/MachineRelocation.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/MachineRelocation.h?rev=45575&r1=45574&r2=45575&view=diff

==============================================================================
--- llvm/trunk/include/llvm/CodeGen/MachineRelocation.h (original)
+++ llvm/trunk/include/llvm/CodeGen/MachineRelocation.h Fri Jan  4 04:46:51 2008
@@ -39,6 +39,7 @@
   enum AddressType {
     isResult,         // Relocation has be transformed into its result pointer.
     isGV,             // The Target.GV field is valid.
+    isGVLazyPtr,      // Relocation of a lazily resolved GV address.
     isBB,             // Relocation of BB address.
     isExtSym,         // The Target.ExtSym field is valid.
     isConstPool,      // Relocation of constant pool address.
@@ -55,7 +56,7 @@
 
   union {
     void *Result;           // If this has been resolved to a resolved pointer
-    GlobalValue *GV;        // If this is a pointer to an LLVM global
+    GlobalValue *GV;        // If this is a pointer to a GV or a GV lazy ptr
     MachineBasicBlock *MBB; // If this is a pointer to a LLVM BB
     const char *ExtSym;     // If this is a pointer to a named symbol
     unsigned Index;         // Constant pool / jump table index
@@ -93,6 +94,25 @@
     return Result;
   }
 
+  /// MachineRelocation::getGVLazyPtr - Return a relocation entry for a
+  /// lazily resolved GlobalValue address.
+  static MachineRelocation getGVLazyPtr(intptr_t offset,
+                                 unsigned RelocationType, 
+                                 GlobalValue *GV, intptr_t cst = 0,
+                                 bool NeedStub = 0,
+                                 bool GOTrelative = 0) {
+    assert((RelocationType & ~63) == 0 && "Relocation type too large!");
+    MachineRelocation Result;
+    Result.Offset = offset;
+    Result.ConstantVal = cst;
+    Result.TargetReloType = RelocationType;
+    Result.AddrType = isGVLazyPtr;
+    Result.NeedStub = NeedStub;
+    Result.GOTRelative = GOTrelative;
+    Result.Target.GV = GV;
+    return Result;
+  }
+
   /// MachineRelocation::getBB - Return a relocation entry for a BB.
   ///
   static MachineRelocation getBB(intptr_t offset,unsigned RelocationType,
@@ -193,6 +213,12 @@
     return AddrType == isGV;
   }
 
+  /// isGlobalValueVLazyPtr - Return true if this relocation is the address
+  /// of a lazily resolved GlobalValue.
+  bool isGlobalValueLazyPtr() const {
+    return AddrType == isGVLazyPtr;
+  }
+
   /// isBasicBlock - Return true if this relocation is a basic block reference.
   ///
   bool isBasicBlock() const {
@@ -234,7 +260,8 @@
   /// getGlobalValue - If this is a global value reference, return the
   /// referenced global.
   GlobalValue *getGlobalValue() const {
-    assert(isGlobalValue() && "This is not a global value reference!");
+    assert((isGlobalValue() || isGlobalValueLazyPtr()) &&
+           "This is not a global value reference!");
     return Target.GV;
   }
 

Modified: llvm/trunk/include/llvm/Target/TargetJITInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Target/TargetJITInfo.h?rev=45575&r1=45574&r2=45575&view=diff

==============================================================================
--- llvm/trunk/include/llvm/Target/TargetJITInfo.h (original)
+++ llvm/trunk/include/llvm/Target/TargetJITInfo.h Fri Jan  4 04:46:51 2008
@@ -40,6 +40,13 @@
     ///
     virtual void replaceMachineCodeForFunction(void *Old, void *New) = 0;
 
+    /// emitGlobalValueLazyPtr - Use the specified MachineCodeEmitter object to
+    /// emit a lazy pointer which contains the address of the specified GV.
+    virtual void *emitGlobalValueLazyPtr(void *GV, MachineCodeEmitter &MCE) {
+      assert(0 && "This target doesn't implement emitGlobalValueLazyPtr!");
+      return 0;
+    }
+
     /// emitFunctionStub - Use the specified MachineCodeEmitter object to emit a
     /// small native function that simply calls the function at the specified
     /// address.  Return the address of the resultant function.

Modified: llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp?rev=45575&r1=45574&r2=45575&view=diff

==============================================================================
--- llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp (original)
+++ llvm/trunk/lib/ExecutionEngine/JIT/JITEmitter.cpp Fri Jan  4 04:46:51 2008
@@ -52,6 +52,10 @@
     /// corresponds to.
     std::map<void*, Function*> StubToFunctionMap;
 
+    /// GlobalToLazyPtrMap - Keep track of the lazy pointer created for a
+    /// particular GlobalVariable so that we can reuse them if necessary.
+    std::map<GlobalValue*, void*> GlobalToLazyPtrMap;
+
   public:
     std::map<Function*, void*>& getFunctionToStubMap(const MutexGuard& locked) {
       assert(locked.holds(TheJIT->lock));
@@ -62,6 +66,12 @@
       assert(locked.holds(TheJIT->lock));
       return StubToFunctionMap;
     }
+
+    std::map<GlobalValue*, void*>&
+    getGlobalToLazyPtrMap(const MutexGuard& locked) {
+      assert(locked.holds(TheJIT->lock));
+      return GlobalToLazyPtrMap;
+    }
   };
 
   /// JITResolver - Keep track of, and resolve, call sites for functions that
@@ -103,6 +113,10 @@
     /// specified address, created lazily on demand.
     void *getExternalFunctionStub(void *FnAddr);
 
+    /// getGlobalValueLazyPtr - Return a lazy pointer containing the specified
+    /// GV address.
+    void *getGlobalValueLazyPtr(GlobalValue *V, void *GVAddress);
+
     /// AddCallbackAtLocation - If the target is capable of rewriting an
     /// instruction without the use of a stub, record the location of the use so
     /// we know which function is being used at the location.
@@ -181,6 +195,25 @@
   return Stub;
 }
 
+/// getGlobalValueLazyPtr - Return a lazy pointer containing the specified
+/// GV address.
+void *JITResolver::getGlobalValueLazyPtr(GlobalValue *GV, void *GVAddress) {
+  MutexGuard locked(TheJIT->lock);
+
+  // If we already have a stub for this global variable, recycle it.
+  void *&LazyPtr = state.getGlobalToLazyPtrMap(locked)[GV];
+  if (LazyPtr) return LazyPtr;
+
+  // Otherwise, codegen a new lazy pointer.
+  LazyPtr = TheJIT->getJITInfo().emitGlobalValueLazyPtr(GVAddress,
+                                                    *TheJIT->getCodeEmitter());
+
+  DOUT << "JIT: Stub emitted at [" << LazyPtr << "] for GV '"
+       << GV->getName() << "'\n";
+
+  return LazyPtr;
+}
+
 /// getExternalFunctionStub - Return a stub for the function at the
 /// specified address, created lazily on demand.
 void *JITResolver::getExternalFunctionStub(void *FnAddr) {
@@ -361,6 +394,8 @@
     }
   private:
     void *getPointerToGlobal(GlobalValue *GV, void *Reference, bool NoNeedStub);
+    void *getPointerToGVLazyPtr(GlobalValue *V, void *Reference,
+                                bool NoNeedStub);
   };
 }
 
@@ -396,6 +431,16 @@
   return Resolver.getFunctionStub(F);
 }
 
+void *JITEmitter::getPointerToGVLazyPtr(GlobalValue *V, void *Reference,
+                                        bool DoesntNeedStub) {
+  // Make sure GV is emitted first.
+  // FIXME: For now, if the GV is an external function we force the JIT to
+  // compile it so the lazy pointer will contain the fully resolved address.
+  void *GVAddress = getPointerToGlobal(V, Reference, true);
+  return Resolver.getGlobalValueLazyPtr(V, GVAddress);
+}
+
+
 void JITEmitter::startFunction(MachineFunction &F) {
   uintptr_t ActualSize;
   BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
@@ -450,6 +495,10 @@
         ResultPtr = getPointerToGlobal(MR.getGlobalValue(),
                                        BufferBegin+MR.getMachineCodeOffset(),
                                        MR.doesntNeedStub());
+      } else if (MR.isGlobalValueLazyPtr()) {
+        ResultPtr = getPointerToGVLazyPtr(MR.getGlobalValue(),
+                                          BufferBegin+MR.getMachineCodeOffset(),
+                                          MR.doesntNeedStub());
       } else if (MR.isBasicBlock()) {
         ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock());
       } else if (MR.isConstantPoolIndex()) {

Modified: llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp?rev=45575&r1=45574&r2=45575&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86CodeEmitter.cpp Fri Jan  4 04:46:51 2008
@@ -40,20 +40,17 @@
     intptr_t PICBase;
     bool Is64BitMode;
     bool IsPIC;
-    bool IsStatic;
   public:
     static char ID;
     explicit Emitter(TargetMachine &tm, MachineCodeEmitter &mce)
       : MachineFunctionPass((intptr_t)&ID), II(0), TD(0), TM(tm), 
       MCE(mce), PICBase(0), Is64BitMode(false),
-      IsPIC(TM.getRelocationModel() == Reloc::PIC_),
-      IsStatic(TM.getRelocationModel() == Reloc::Static) {}
+      IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
     Emitter(TargetMachine &tm, MachineCodeEmitter &mce,
             const X86InstrInfo &ii, const TargetData &td, bool is64)
       : MachineFunctionPass((intptr_t)&ID), II(&ii), TD(&td), TM(tm), 
       MCE(mce), PICBase(0), Is64BitMode(is64),
-      IsPIC(TM.getRelocationModel() == Reloc::PIC_),
-      IsStatic(TM.getRelocationModel() == Reloc::Static) {}
+      IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
 
     bool runOnMachineFunction(MachineFunction &MF);
 
@@ -67,7 +64,7 @@
     void emitPCRelativeBlockAddress(MachineBasicBlock *MBB);
     void emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
                            int Disp = 0, intptr_t PCAdj = 0,
-                           bool NeedStub = false);
+                           bool NeedStub = false, bool IsLazy = false);
     void emitExternalSymbolAddress(const char *ES, unsigned Reloc);
     void emitConstPoolAddress(unsigned CPI, unsigned Reloc, int Disp = 0,
                               intptr_t PCAdj = 0);
@@ -88,6 +85,8 @@
     unsigned getX86RegNum(unsigned RegNo);
     bool isX86_64ExtendedReg(const MachineOperand &MO);
     unsigned determineREX(const MachineInstr &MI);
+
+    bool gvNeedsLazyPtr(const GlobalValue *GV);
   };
   char Emitter::ID = 0;
 }
@@ -103,10 +102,9 @@
   assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
           MF.getTarget().getRelocationModel() != Reloc::Static) &&
          "JIT relocation model must be set to static or default!");
-  II = ((X86TargetMachine&)MF.getTarget()).getInstrInfo();
-  TD = ((X86TargetMachine&)MF.getTarget()).getTargetData();
-  Is64BitMode =
-    ((X86TargetMachine&)MF.getTarget()).getSubtarget<X86Subtarget>().is64Bit();
+  II = ((X86TargetMachine&)TM).getInstrInfo();
+  TD = ((X86TargetMachine&)TM).getTargetData();
+  Is64BitMode = TM.getSubtarget<X86Subtarget>().is64Bit();
 
   do {
     MCE.startFunction(MF);
@@ -139,11 +137,19 @@
 ///
 void Emitter::emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
                                 int Disp /* = 0 */, intptr_t PCAdj /* = 0 */,
-                                bool NeedStub /* = false */) {
+                                bool NeedStub /* = false */,
+                                bool isLazy /* = false */) {
+  intptr_t RelocCST = 0;
   if (Reloc == X86::reloc_picrel_word)
-    PCAdj += PICBase;
-  MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
-                                             GV, PCAdj, NeedStub));
+    RelocCST = PICBase;
+  else if (Reloc == X86::reloc_pcrel_word)
+    RelocCST = PCAdj;
+  MachineRelocation MR = isLazy 
+    ? MachineRelocation::getGVLazyPtr(MCE.getCurrentPCOffset(), Reloc,
+                                      GV, RelocCST, NeedStub)
+    : MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
+                               GV, RelocCST, NeedStub);
+  MCE.addRelocation(MR);
   if (Reloc == X86::reloc_absolute_dword)
     MCE.emitWordLE(0);
   MCE.emitWordLE(Disp); // The relocated value will be added to the displacement
@@ -153,9 +159,9 @@
 /// be emitted to the current location in the function, and allow it to be PC
 /// relative.
 void Emitter::emitExternalSymbolAddress(const char *ES, unsigned Reloc) {
-  intptr_t PCAdj = (Reloc == X86::reloc_picrel_word) ? PICBase : 0;
+  intptr_t RelocCST = (Reloc == X86::reloc_picrel_word) ? PICBase : 0;
   MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
-                                                 Reloc, ES, PCAdj));
+                                                 Reloc, ES, RelocCST));
   if (Reloc == X86::reloc_absolute_dword)
     MCE.emitWordLE(0);
   MCE.emitWordLE(0);
@@ -167,10 +173,13 @@
 void Emitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc,
                                    int Disp /* = 0 */,
                                    intptr_t PCAdj /* = 0 */) {
+  intptr_t RelocCST = 0;
   if (Reloc == X86::reloc_picrel_word)
-    PCAdj += PICBase;
+    RelocCST = PICBase;
+  else if (Reloc == X86::reloc_pcrel_word)
+    RelocCST = PCAdj;
   MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
-                                                    Reloc, CPI, PCAdj));
+                                                    Reloc, CPI, RelocCST));
   if (Reloc == X86::reloc_absolute_dword)
     MCE.emitWordLE(0);
   MCE.emitWordLE(Disp); // The relocated value will be added to the displacement
@@ -181,10 +190,13 @@
 /// relative.
 void Emitter::emitJumpTableAddress(unsigned JTI, unsigned Reloc,
                                    intptr_t PCAdj /* = 0 */) {
+  intptr_t RelocCST = 0;
   if (Reloc == X86::reloc_picrel_word)
-    PCAdj += PICBase;
+    RelocCST = PICBase;
+  else if (Reloc == X86::reloc_pcrel_word)
+    RelocCST = PCAdj;
   MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
-                                                    Reloc, JTI, PCAdj));
+                                                    Reloc, JTI, RelocCST));
   if (Reloc == X86::reloc_absolute_dword)
     MCE.emitWordLE(0);
   MCE.emitWordLE(0); // The relocated value will be added to the displacement
@@ -223,6 +235,11 @@
   return Value == (signed char)Value;
 }
 
+bool Emitter::gvNeedsLazyPtr(const GlobalValue *GV) {
+  return !Is64BitMode && 
+    TM.getSubtarget<X86Subtarget>().GVRequiresExtraLoad(GV, TM, false);
+}
+
 void Emitter::emitDisplacementField(const MachineOperand *RelocOp,
                                     int DispVal, intptr_t PCAdj) {
   // If this is a simple integer displacement that doesn't require a relocation,
@@ -241,9 +258,10 @@
     //	89 04 25 00 00 00 00 	mov    %eax,0x0      # Absolute
     unsigned rt = Is64BitMode ? X86::reloc_pcrel_word
       : (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word);
-    bool NeedStub = !IsStatic || isa<Function>(RelocOp->getGlobal());
+    bool NeedStub = isa<Function>(RelocOp->getGlobal());
+    bool isLazy = gvNeedsLazyPtr(RelocOp->getGlobal());
     emitGlobalAddress(RelocOp->getGlobal(), rt, RelocOp->getOffset(),
-                      PCAdj, NeedStub);
+                      PCAdj, NeedStub, isLazy);
   } else if (RelocOp->isConstantPoolIndex()) {
     unsigned rt = Is64BitMode ? X86::reloc_pcrel_word : X86::reloc_picrel_word;
     emitConstPoolAddress(RelocOp->getIndex(), rt,
@@ -601,8 +619,7 @@
       if (MO.isMachineBasicBlock()) {
         emitPCRelativeBlockAddress(MO.getMBB());
       } else if (MO.isGlobalAddress()) {
-        bool NeedStub = !IsStatic ||
-          (Is64BitMode && TM.getCodeModel() == CodeModel::Large);
+        bool NeedStub = Is64BitMode && TM.getCodeModel() == CodeModel::Large;
         emitGlobalAddress(MO.getGlobal(), X86::reloc_pcrel_word,
                           0, 0, NeedStub);
       } else if (MO.isExternalSymbol()) {
@@ -634,8 +651,10 @@
         if (Opcode == X86::MOV64ri)
           rt = X86::reloc_absolute_dword;  // FIXME: add X86II flag?
         if (MO1.isGlobalAddress()) {
-          bool NeedStub = !IsStatic || isa<Function>(MO1.getGlobal());
-          emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0, NeedStub);
+          bool NeedStub = isa<Function>(MO1.getGlobal());
+          bool isLazy = gvNeedsLazyPtr(MO1.getGlobal());
+          emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0,
+                            NeedStub, isLazy);
         } else if (MO1.isExternalSymbol())
           emitExternalSymbolAddress(MO1.getSymbolName(), rt);
         else if (MO1.isConstantPoolIndex())
@@ -704,8 +723,10 @@
         if (Opcode == X86::MOV64ri32)
           rt = X86::reloc_absolute_word;  // FIXME: add X86II flag?
         if (MO1.isGlobalAddress()) {
-          bool NeedStub = !IsStatic || isa<Function>(MO1.getGlobal());
-          emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0, NeedStub);
+          bool NeedStub = isa<Function>(MO1.getGlobal());
+          bool isLazy = gvNeedsLazyPtr(MO1.getGlobal());
+          emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0,
+                            NeedStub, isLazy);
         } else if (MO1.isExternalSymbol())
           emitExternalSymbolAddress(MO1.getSymbolName(), rt);
         else if (MO1.isConstantPoolIndex())
@@ -739,8 +760,10 @@
         if (Opcode == X86::MOV64mi32)
           rt = X86::reloc_absolute_word;  // FIXME: add X86II flag?
         if (MO.isGlobalAddress()) {
-          bool NeedStub = !IsStatic || isa<Function>(MO.getGlobal());
-          emitGlobalAddress(MO.getGlobal(), rt, MO.getOffset(), 0, NeedStub);
+          bool NeedStub = isa<Function>(MO.getGlobal());
+          bool isLazy = gvNeedsLazyPtr(MO.getGlobal());
+          emitGlobalAddress(MO.getGlobal(), rt, MO.getOffset(), 0,
+                            NeedStub, isLazy);
         } else if (MO.isExternalSymbol())
           emitExternalSymbolAddress(MO.getSymbolName(), rt);
         else if (MO.isConstantPoolIndex())

Modified: llvm/trunk/lib/Target/X86/X86JITInfo.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86JITInfo.cpp?rev=45575&r1=45574&r2=45575&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86JITInfo.cpp (original)
+++ llvm/trunk/lib/Target/X86/X86JITInfo.cpp Fri Jan  4 04:46:51 2008
@@ -380,6 +380,18 @@
   return X86CompilationCallback;
 }
 
+void *X86JITInfo::emitGlobalValueLazyPtr(void *GV, MachineCodeEmitter &MCE) {
+#ifdef __x86_64__
+  MCE.startFunctionStub(8, 8);
+  MCE.emitWordLE(((unsigned *)&GV)[0]);
+  MCE.emitWordLE(((unsigned *)&GV)[1]);
+#else
+  MCE.startFunctionStub(4, 4);
+  MCE.emitWordLE((unsigned)GV);
+#endif
+  return MCE.finishFunctionStub(0);
+}
+
 void *X86JITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) {
   // Note, we cast to intptr_t here to silence a -pedantic warning that 
   // complains about casting a function pointer to a normal pointer.

Modified: llvm/trunk/lib/Target/X86/X86JITInfo.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Target/X86/X86JITInfo.h?rev=45575&r1=45574&r2=45575&view=diff

==============================================================================
--- llvm/trunk/lib/Target/X86/X86JITInfo.h (original)
+++ llvm/trunk/lib/Target/X86/X86JITInfo.h Fri Jan  4 04:46:51 2008
@@ -31,6 +31,10 @@
     ///
     virtual void replaceMachineCodeForFunction(void *Old, void *New);
 
+    /// emitGlobalValueLazyPtr - Use the specified MachineCodeEmitter object to
+    /// emit a lazy pointer which contains the address of the specified GV.
+    virtual void *emitGlobalValueLazyPtr(void *GV, MachineCodeEmitter &MCE);
+
     /// emitFunctionStub - Use the specified MachineCodeEmitter object to emit a
     /// small native function that simply calls the function at the specified
     /// address.





More information about the llvm-commits mailing list