mirror of
https://github.com/RPCSX/llvm.git
synced 2024-12-11 05:35:11 +00:00
* 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
This commit is contained in:
parent
53e4aa57c6
commit
5efb75daed
@ -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));
|
||||
|
@ -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)
|
||||
|
@ -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,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user