* Rename existing relocations to be more specific
authorChris Lattner <sabre@nondot.org>
Wed, 24 Nov 2004 22:30:08 +0000 (22:30 +0000)
committerChris Lattner <sabre@nondot.org>
Wed, 24 Nov 2004 22:30:08 +0000 (22:30 +0000)
* Add relocations for refernces to non-lazy darwin stubs and implement
  them correctly.

With this change, we can correctly references external globals, and now
all but two UnitTests and all but 1 Regression/C tests pass.

More importantly, bugpoint-jit will start giving us useful testcases,
instead of always telling us that references to external globals don't
work :)

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@18222 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Target/PowerPC/PPCCodeEmitter.cpp
lib/Target/PowerPC/PPCJITInfo.cpp
lib/Target/PowerPC/PPCRelocations.h

index 2b0c0cfa73f568a01f6c542c318acdccacaf54e0..733618160ac8b35fe9a121bda61ec4ccc3d02f75 100644 (file)
@@ -189,21 +189,36 @@ int PPC32CodeEmitter::getMachineOpValue(MachineInstr &MI, MachineOperand &MO) {
   } else if (MO.isImmediate()) {
     rv = MO.getImmedValue();
   } else if (MO.isGlobalAddress()) {
+    GlobalValue *GV = MO.getGlobal();
     unsigned Reloc = 0;
     int Offset = 0;
     if (MI.getOpcode() == PPC::CALLpcrel)
       Reloc = PPC::reloc_pcrel_bx;
-    else if (MI.getOpcode() == PPC::LOADHiAddr) {
+    else {
       assert(MovePCtoLROffset && "MovePCtoLR not seen yet?");
-      Reloc = PPC::reloc_absolute_loadhi;
       Offset = -((intptr_t)MovePCtoLROffset+4);
-    } else if (MI.getOpcode() == PPC::LA || MI.getOpcode() == PPC::LWZ ||
-               MI.getOpcode() == PPC::LFS || MI.getOpcode() == PPC::LFD) {
-      assert(MovePCtoLROffset && "MovePCtoLR not seen yet?");
-      Reloc = PPC::reloc_absolute_la;
-      Offset = -((intptr_t)MovePCtoLROffset+4);
-    } else {
-      assert(0 && "Unknown instruction for relocation!");
+
+      if (MI.getOpcode() == PPC::LOADHiAddr) {
+        if (GV->hasWeakLinkage() || GV->isExternal() || isa<Function>(GV))
+          Reloc = PPC::reloc_absolute_ptr_high;   // Pointer to stub
+        else
+          Reloc = PPC::reloc_absolute_high;       // Pointer to symbol
+
+      } else if (MI.getOpcode() == PPC::LA) {
+        assert(!(GV->hasWeakLinkage() || GV->isExternal() || isa<Function>(GV))
+               && "Something in the ISEL changed\n");
+
+        Reloc = PPC::reloc_absolute_low;
+      } else if (MI.getOpcode() == PPC::LWZ) {
+        Reloc = PPC::reloc_absolute_ptr_low;
+
+        assert((GV->hasWeakLinkage() || GV->isExternal() || isa<Function>(GV))&&
+               "Something in the ISEL changed\n");
+      } else {
+        // These don't show up for global value references AFAIK, only for
+        // constant pool refs: PPC::LFS, PPC::LFD
+        assert(0 && "Unknown instruction for relocation!");
+      }
     }
     MCE.addRelocation(MachineRelocation(MCE.getCurrentPCOffset(),
                                         Reloc, MO.getGlobal(), Offset));
index 5ee16178c607b1ea8273b29bb1942e7409d49e51..15b2aa1bddf4af7b2c674e56fd0fd4423ab90bc9 100644 (file)
@@ -16,6 +16,7 @@
 #include "PPC32Relocations.h"
 #include "llvm/CodeGen/MachineCodeEmitter.h"
 #include "llvm/Config/alloca.h"
+#include <map>
 using namespace llvm;
 
 static TargetJITInfo::JITCompilerFn JITCompilerFunction;
@@ -195,11 +196,28 @@ void PPC32JITInfo::relocate(void *Function, MachineRelocation *MR,
              "Relocation out of range!");
       *RelocPos |= (ResultPtr & ((1 << 24)-1))  << 2;
       break;
-    case PPC::reloc_absolute_loadhi:   // Relocate high bits into addis
-    case PPC::reloc_absolute_la:       // Relocate low bits into addi
+
+    case PPC::reloc_absolute_ptr_high: // Pointer relocations.
+    case PPC::reloc_absolute_ptr_low: {
+      // Pointer relocations are used for the PPC external stubs and lazy
+      // resolver pointers that the Darwin ABI likes to use.  Basically, the
+      // address of the global is actually stored in memory, and the address of
+      // the pointer is relocated into instructions instead of the pointer
+      // itself.  Because we have to keep the mapping anyway, we just return
+      // pointers to the values in the map as our new location.
+      static std::map<void*,void*> Pointers;
+      void *&Ptr = Pointers[(void*)ResultPtr];
+      Ptr = (void*)ResultPtr;
+      ResultPtr = (intptr_t)&Ptr;
+    }
+      // FALL THROUGH
+    case PPC::reloc_absolute_high:     // high bits of ref -> low 16 of instr
+    case PPC::reloc_absolute_low:      // low bits of ref  -> low 16 of instr
       ResultPtr += MR->getConstantVal();
 
-      if (MR->getRelocationType() == PPC::reloc_absolute_loadhi) {
+      // If this is a high-part access, get the high-part.
+      if (MR->getRelocationType() == PPC::reloc_absolute_high ||
+          MR->getRelocationType() == PPC::reloc_absolute_ptr_high) {
         // If the low part will have a carry (really a borrow) from the low
         // 16-bits into the high 16, add a bit to borrow from.
         if (((int)ResultPtr << 16) < 0)
index 54de9a6fa292398702a5e05df96b87d7d3738c16..a3eb7600438d58f2437f1177cd8ec91d48ced8c7 100644 (file)
@@ -22,15 +22,29 @@ namespace llvm {
       // reloc_pcrel_bx - PC relative relocation, for the b or bl instructions.
       reloc_pcrel_bx,
 
-      // reloc_absolute_loadhi - Absolute relocation, for the loadhi instruction
+      // reloc_absolute_high - Absolute relocation, for the loadhi instruction
       // (which is really addis).  Add the high 16-bits of the specified global
-      // address into the immediate field of the addis.
-      reloc_absolute_loadhi,
+      // address into the low 16-bits of the instruction.
+      reloc_absolute_high,
 
-      // reloc_absolute_la - Absolute relocation, for the la instruction (which
+      // reloc_absolute_low - Absolute relocation, for the la instruction (which
       // is really an addi).  Add the low 16-bits of teh specified global
-      // address into the immediate field of the addi.
-      reloc_absolute_la,
+      // address into the low 16-bits of the instruction.
+      reloc_absolute_low,
+
+      // reloc_absolute_ptr_high - Absolute relocation for references to lazy
+      // pointer stubs.  In this case, the relocated instruction should be
+      // relocated to point to a POINTER to the indicated global.  The low-16
+      // bits of the instruction are rewritten with the high 16-bits of the
+      // address of the pointer.
+      reloc_absolute_ptr_high,
+
+      // reloc_absolute_ptr_low - Absolute relocation for references to lazy
+      // pointer stubs.  In this case, the relocated instruction should be
+      // relocated to point to a POINTER to the indicated global.  The low-16
+      // bits of the instruction are rewritten with the low 16-bits of the
+      // address of the pointer.
+      reloc_absolute_ptr_low,
     };
   }
 }