mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-01-08 03:30:22 +00:00
1) Proper emit displacements for x86, using absolute relocations where necessary
for ELF to work. 2) RIP addressing: Use SIB bytes for absolute relocations where RegBase=0, IndexReg=0. 3) The JIT can get the real address of cstpools and jmptables during code emission, fix that for object code emission git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@78129 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
339685269f
commit
e55fef36a9
@ -289,6 +289,13 @@ public:
|
||||
return CurBufferPtr-BufferBegin;
|
||||
}
|
||||
|
||||
/// earlyResolveAddresses - True if the code emitter can use symbol addresses
|
||||
/// during code emission time. The JIT is capable of doing this because it
|
||||
/// creates jump tables or constant pools in memory on the fly while the
|
||||
/// object code emitters rely on a linker to have real addresses and should
|
||||
/// use relocations instead.
|
||||
bool earlyResolveAddresses() const { return true; }
|
||||
|
||||
/// addRelocation - Whenever a relocatable address is needed, it should be
|
||||
/// noted with this interface.
|
||||
virtual void addRelocation(const MachineRelocation &MR) = 0;
|
||||
|
@ -280,6 +280,13 @@ public:
|
||||
return CurBufferPtr-BufferBegin;
|
||||
}
|
||||
|
||||
/// earlyResolveAddresses - True if the code emitter can use symbol addresses
|
||||
/// during code emission time. The JIT is capable of doing this because it
|
||||
/// creates jump tables or constant pools in memory on the fly while the
|
||||
/// object code emitters rely on a linker to have real addresses and should
|
||||
/// use relocations instead.
|
||||
virtual bool earlyResolveAddresses() const = 0;
|
||||
|
||||
/// addRelocation - Whenever a relocatable address is needed, it should be
|
||||
/// noted with this interface.
|
||||
virtual void addRelocation(const MachineRelocation &MR) = 0;
|
||||
|
@ -109,6 +109,13 @@ public:
|
||||
/// noted with this interface.
|
||||
void addRelocation(const MachineRelocation& relocation);
|
||||
|
||||
/// earlyResolveAddresses - True if the code emitter can use symbol addresses
|
||||
/// during code emission time. The JIT is capable of doing this because it
|
||||
/// creates jump tables or constant pools in memory on the fly while the
|
||||
/// object code emitters rely on a linker to have real addresses and should
|
||||
/// use relocations instead.
|
||||
bool earlyResolveAddresses() const { return false; }
|
||||
|
||||
/// startFunction - This callback is invoked when the specified function is
|
||||
/// about to be code generated. This initializes the BufferBegin/End/Ptr
|
||||
/// fields.
|
||||
|
@ -87,7 +87,7 @@ template<class CodeEmitter>
|
||||
intptr_t PCAdj = 0);
|
||||
|
||||
void emitDisplacementField(const MachineOperand *RelocOp, int DispVal,
|
||||
intptr_t PCAdj = 0);
|
||||
intptr_t Adj = 0, bool IsPCRel = true);
|
||||
|
||||
void emitRegModRMByte(unsigned ModRMReg, unsigned RegOpcodeField);
|
||||
void emitRegModRMByte(unsigned RegOpcodeField);
|
||||
@ -175,7 +175,7 @@ void Emitter<CodeEmitter>::emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
|
||||
intptr_t PCAdj /* = 0 */,
|
||||
bool NeedStub /* = false */,
|
||||
bool Indirect /* = false */) {
|
||||
intptr_t RelocCST = 0;
|
||||
intptr_t RelocCST = Disp;
|
||||
if (Reloc == X86::reloc_picrel_word)
|
||||
RelocCST = PICBaseOffset;
|
||||
else if (Reloc == X86::reloc_pcrel_word)
|
||||
@ -309,34 +309,42 @@ static bool gvNeedsNonLazyPtr(const MachineOperand &GVOp,
|
||||
|
||||
template<class CodeEmitter>
|
||||
void Emitter<CodeEmitter>::emitDisplacementField(const MachineOperand *RelocOp,
|
||||
int DispVal, intptr_t PCAdj) {
|
||||
int DispVal,
|
||||
intptr_t Adj /* = 0 */,
|
||||
bool IsPCRel /* = true */) {
|
||||
// If this is a simple integer displacement that doesn't require a relocation,
|
||||
// emit it now.
|
||||
if (!RelocOp) {
|
||||
emitConstant(DispVal, 4);
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// Otherwise, this is something that requires a relocation. Emit it as such
|
||||
// now.
|
||||
if (RelocOp->isGlobal()) {
|
||||
// In 64-bit static small code model, we could potentially emit absolute.
|
||||
// But it's probably not beneficial.
|
||||
// But it's probably not beneficial. If the MCE supports using RIP directly
|
||||
// do it, otherwise fallback to absolute (this is determined by IsPCRel).
|
||||
// 89 05 00 00 00 00 mov %eax,0(%rip) # PC-relative
|
||||
// 89 04 25 00 00 00 00 mov %eax,0x0 # Absolute
|
||||
unsigned rt = Is64BitMode ? X86::reloc_pcrel_word
|
||||
unsigned rt = Is64BitMode ?
|
||||
(IsPCRel ? X86::reloc_pcrel_word : X86::reloc_absolute_word_sext)
|
||||
: (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word);
|
||||
bool NeedStub = isa<Function>(RelocOp->getGlobal());
|
||||
bool Indirect = gvNeedsNonLazyPtr(*RelocOp, TM);
|
||||
emitGlobalAddress(RelocOp->getGlobal(), rt, RelocOp->getOffset(),
|
||||
PCAdj, NeedStub, Indirect);
|
||||
Adj, NeedStub, Indirect);
|
||||
} else if (RelocOp->isCPI()) {
|
||||
unsigned rt = Is64BitMode ? X86::reloc_pcrel_word : X86::reloc_picrel_word;
|
||||
unsigned rt = Is64BitMode ?
|
||||
(IsPCRel ? X86::reloc_pcrel_word : X86::reloc_absolute_word_sext)
|
||||
: (IsPCRel ? X86::reloc_picrel_word : X86::reloc_absolute_word);
|
||||
emitConstPoolAddress(RelocOp->getIndex(), rt,
|
||||
RelocOp->getOffset(), PCAdj);
|
||||
RelocOp->getOffset(), Adj);
|
||||
} else if (RelocOp->isJTI()) {
|
||||
unsigned rt = Is64BitMode ? X86::reloc_pcrel_word : X86::reloc_picrel_word;
|
||||
emitJumpTableAddress(RelocOp->getIndex(), rt, PCAdj);
|
||||
unsigned rt = Is64BitMode ?
|
||||
(IsPCRel ? X86::reloc_pcrel_word : X86::reloc_absolute_word_sext)
|
||||
: (IsPCRel ? X86::reloc_picrel_word : X86::reloc_absolute_word);
|
||||
emitJumpTableAddress(RelocOp->getIndex(), rt, Adj);
|
||||
} else {
|
||||
llvm_unreachable("Unknown value to relocate!");
|
||||
}
|
||||
@ -354,14 +362,14 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI,
|
||||
if (Op3.isGlobal()) {
|
||||
DispForReloc = &Op3;
|
||||
} else if (Op3.isCPI()) {
|
||||
if (Is64BitMode || IsPIC) {
|
||||
if (!MCE.earlyResolveAddresses() || Is64BitMode || IsPIC) {
|
||||
DispForReloc = &Op3;
|
||||
} else {
|
||||
DispVal += MCE.getConstantPoolEntryAddress(Op3.getIndex());
|
||||
DispVal += Op3.getOffset();
|
||||
}
|
||||
} else if (Op3.isJTI()) {
|
||||
if (Is64BitMode || IsPIC) {
|
||||
if (!MCE.earlyResolveAddresses() || Is64BitMode || IsPIC) {
|
||||
DispForReloc = &Op3;
|
||||
} else {
|
||||
DispVal += MCE.getJumpTableEntryAddress(Op3.getIndex());
|
||||
@ -376,17 +384,23 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI,
|
||||
|
||||
unsigned BaseReg = Base.getReg();
|
||||
|
||||
// Indicate that the displacement will use an pcrel or absolute reference
|
||||
// by default. MCEs able to resolve addresses on-the-fly use pcrel by default
|
||||
// while others, unless explicit asked to use RIP, use absolute references.
|
||||
bool IsPCRel = MCE.earlyResolveAddresses() ? true : false;
|
||||
|
||||
// Is a SIB byte needed?
|
||||
// If no BaseReg, issue a RIP relative instruction only if the MCE can
|
||||
// resolve addresses on-the-fly, otherwise use SIB (Intel Manual 2A, table
|
||||
// 2-7) and absolute references.
|
||||
if ((!Is64BitMode || DispForReloc || BaseReg != 0) &&
|
||||
IndexReg.getReg() == 0 &&
|
||||
(BaseReg == 0 || BaseReg == X86::RIP ||
|
||||
getX86RegNum(BaseReg) != N86::ESP)) {
|
||||
if (BaseReg == 0 ||
|
||||
BaseReg == X86::RIP) { // Just a displacement?
|
||||
IndexReg.getReg() == 0 &&
|
||||
((BaseReg == 0 && MCE.earlyResolveAddresses()) || BaseReg == X86::RIP ||
|
||||
(BaseReg != 0 && getX86RegNum(BaseReg) != N86::ESP))) {
|
||||
if (BaseReg == 0 || BaseReg == X86::RIP) { // Just a displacement?
|
||||
// Emit special case [disp32] encoding
|
||||
MCE.emitByte(ModRMByte(0, RegOpcodeField, 5));
|
||||
|
||||
emitDisplacementField(DispForReloc, DispVal, PCAdj);
|
||||
emitDisplacementField(DispForReloc, DispVal, PCAdj, true);
|
||||
} else {
|
||||
unsigned BaseRegNo = getX86RegNum(BaseReg);
|
||||
if (!DispForReloc && DispVal == 0 && BaseRegNo != N86::EBP) {
|
||||
@ -399,7 +413,7 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI,
|
||||
} else {
|
||||
// Emit the most general non-SIB encoding: [REG+disp32]
|
||||
MCE.emitByte(ModRMByte(2, RegOpcodeField, BaseRegNo));
|
||||
emitDisplacementField(DispForReloc, DispVal, PCAdj);
|
||||
emitDisplacementField(DispForReloc, DispVal, PCAdj, IsPCRel);
|
||||
}
|
||||
}
|
||||
|
||||
@ -435,13 +449,13 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI,
|
||||
unsigned SS = SSTable[Scale.getImm()];
|
||||
|
||||
if (BaseReg == 0) {
|
||||
// Handle the SIB byte for the case where there is no base. The
|
||||
// displacement has already been output.
|
||||
// Handle the SIB byte for the case where there is no base, see Intel
|
||||
// Manual 2A, table 2-7. The displacement has already been output.
|
||||
unsigned IndexRegNo;
|
||||
if (IndexReg.getReg())
|
||||
IndexRegNo = getX86RegNum(IndexReg.getReg());
|
||||
else
|
||||
IndexRegNo = 4; // For example [ESP+1*<noreg>+4]
|
||||
else // Examples: [ESP+1*<noreg>+4] or [scaled idx]+disp32 (MOD=0,BASE=5)
|
||||
IndexRegNo = 4;
|
||||
emitSIBByte(SS, IndexRegNo, 5);
|
||||
} else {
|
||||
unsigned BaseRegNo = getX86RegNum(BaseReg);
|
||||
@ -457,7 +471,7 @@ void Emitter<CodeEmitter>::emitMemModRMByte(const MachineInstr &MI,
|
||||
if (ForceDisp8) {
|
||||
emitConstant(DispVal, 1);
|
||||
} else if (DispVal != 0 || ForceDisp32) {
|
||||
emitDisplacementField(DispForReloc, DispVal, PCAdj);
|
||||
emitDisplacementField(DispForReloc, DispVal, PCAdj, IsPCRel);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -538,6 +538,7 @@ void X86JITInfo::relocate(void *Function, MachineRelocation *MR,
|
||||
break;
|
||||
}
|
||||
case X86::reloc_absolute_word:
|
||||
case X86::reloc_absolute_word_sext:
|
||||
// Absolute relocation, just add the relocated value to the value already
|
||||
// in memory.
|
||||
*((unsigned*)RelocPos) += (unsigned)ResultPtr;
|
||||
|
@ -20,7 +20,9 @@ namespace llvm {
|
||||
namespace X86 {
|
||||
/// RelocationType - An enum for the x86 relocation codes. Note that
|
||||
/// the terminology here doesn't follow x86 convention - word means
|
||||
/// 32-bit and dword means 64-bit.
|
||||
/// 32-bit and dword means 64-bit. The relocations will be treated
|
||||
/// by JIT or ObjectCode emitters, this is transparent to the x86 code
|
||||
/// emitter but JIT and ObjectCode will treat them differently
|
||||
enum RelocationType {
|
||||
/// reloc_pcrel_word - PC relative relocation, add the relocated value to
|
||||
/// the value already in memory, after we adjust it for where the PC is.
|
||||
@ -30,11 +32,19 @@ namespace llvm {
|
||||
/// value to the value already in memory, after we adjust it for where the
|
||||
/// PIC base is.
|
||||
reloc_picrel_word = 1,
|
||||
|
||||
/// reloc_absolute_word, reloc_absolute_dword - Absolute relocation, just
|
||||
/// add the relocated value to the value already in memory.
|
||||
|
||||
/// reloc_absolute_word - absolute relocation, just add the relocated
|
||||
/// value to the value already in memory.
|
||||
reloc_absolute_word = 2,
|
||||
reloc_absolute_dword = 3
|
||||
|
||||
/// reloc_absolute_word_sext - absolute relocation, just add the relocated
|
||||
/// value to the value already in memory. In object files, it represents a
|
||||
/// value which must be sign-extended when resolving the relocation.
|
||||
reloc_absolute_word_sext = 3,
|
||||
|
||||
/// reloc_absolute_dword - absolute relocation, just add the relocated
|
||||
/// value to the value already in memory.
|
||||
reloc_absolute_dword = 4
|
||||
};
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user