diff options
author | Chris Lattner <sabre@nondot.org> | 2004-11-24 22:30:08 +0000 |
---|---|---|
committer | Chris Lattner <sabre@nondot.org> | 2004-11-24 22:30:08 +0000 |
commit | 5efb75daed48edfeb03ba62f3f0afe81b86f5d7f (patch) | |
tree | 7c99314e1f98ec1f73650c060d51ed9cf85133fd /lib/Target/PowerPC | |
parent | 53e4aa57c6bdc9bc99d7d8843e1b2b693a16fbfa (diff) | |
download | external_llvm-5efb75daed48edfeb03ba62f3f0afe81b86f5d7f.zip external_llvm-5efb75daed48edfeb03ba62f3f0afe81b86f5d7f.tar.gz external_llvm-5efb75daed48edfeb03ba62f3f0afe81b86f5d7f.tar.bz2 |
* Rename existing relocations to be more specific
* 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
Diffstat (limited to 'lib/Target/PowerPC')
-rw-r--r-- | lib/Target/PowerPC/PPCCodeEmitter.cpp | 33 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCJITInfo.cpp | 24 | ||||
-rw-r--r-- | lib/Target/PowerPC/PPCRelocations.h | 26 |
3 files changed, 65 insertions, 18 deletions
diff --git a/lib/Target/PowerPC/PPCCodeEmitter.cpp b/lib/Target/PowerPC/PPCCodeEmitter.cpp index 2b0c0cf..7336181 100644 --- a/lib/Target/PowerPC/PPCCodeEmitter.cpp +++ b/lib/Target/PowerPC/PPCCodeEmitter.cpp @@ -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)); diff --git a/lib/Target/PowerPC/PPCJITInfo.cpp b/lib/Target/PowerPC/PPCJITInfo.cpp index 5ee1617..15b2aa1 100644 --- a/lib/Target/PowerPC/PPCJITInfo.cpp +++ b/lib/Target/PowerPC/PPCJITInfo.cpp @@ -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) diff --git a/lib/Target/PowerPC/PPCRelocations.h b/lib/Target/PowerPC/PPCRelocations.h index 54de9a6..a3eb760 100644 --- a/lib/Target/PowerPC/PPCRelocations.h +++ b/lib/Target/PowerPC/PPCRelocations.h @@ -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, }; } } |