From: Chris Lattner Date: Wed, 24 Nov 2004 22:30:08 +0000 (+0000) Subject: * Rename existing relocations to be more specific X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=5efb75daed48edfeb03ba62f3f0afe81b86f5d7f * 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 --- diff --git a/lib/Target/PowerPC/PPCCodeEmitter.cpp b/lib/Target/PowerPC/PPCCodeEmitter.cpp index 2b0c0cfa73f..733618160ac 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(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(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(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 5ee16178c60..15b2aa1bddf 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 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 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 54de9a6fa29..a3eb7600438 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, }; } }