* 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 :)

llvm-svn: 18222
This commit is contained in:
Chris Lattner 2004-11-24 22:30:08 +00:00
parent e9b752c4e3
commit ebbfaa3db8
3 changed files with 65 additions and 18 deletions

View 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));

View 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)

View 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,
};
}
}