mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-09-26 09:18:56 +00:00
X86 PIC JIT support fixes: encoding bugs, add lazy pointer stubs support.
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@45575 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -39,6 +39,7 @@ class MachineRelocation {
|
|||||||
enum AddressType {
|
enum AddressType {
|
||||||
isResult, // Relocation has be transformed into its result pointer.
|
isResult, // Relocation has be transformed into its result pointer.
|
||||||
isGV, // The Target.GV field is valid.
|
isGV, // The Target.GV field is valid.
|
||||||
|
isGVLazyPtr, // Relocation of a lazily resolved GV address.
|
||||||
isBB, // Relocation of BB address.
|
isBB, // Relocation of BB address.
|
||||||
isExtSym, // The Target.ExtSym field is valid.
|
isExtSym, // The Target.ExtSym field is valid.
|
||||||
isConstPool, // Relocation of constant pool address.
|
isConstPool, // Relocation of constant pool address.
|
||||||
@@ -55,7 +56,7 @@ class MachineRelocation {
|
|||||||
|
|
||||||
union {
|
union {
|
||||||
void *Result; // If this has been resolved to a resolved pointer
|
void *Result; // If this has been resolved to a resolved pointer
|
||||||
GlobalValue *GV; // If this is a pointer to an LLVM global
|
GlobalValue *GV; // If this is a pointer to a GV or a GV lazy ptr
|
||||||
MachineBasicBlock *MBB; // If this is a pointer to a LLVM BB
|
MachineBasicBlock *MBB; // If this is a pointer to a LLVM BB
|
||||||
const char *ExtSym; // If this is a pointer to a named symbol
|
const char *ExtSym; // If this is a pointer to a named symbol
|
||||||
unsigned Index; // Constant pool / jump table index
|
unsigned Index; // Constant pool / jump table index
|
||||||
@@ -93,6 +94,25 @@ public:
|
|||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// MachineRelocation::getGVLazyPtr - Return a relocation entry for a
|
||||||
|
/// lazily resolved GlobalValue address.
|
||||||
|
static MachineRelocation getGVLazyPtr(intptr_t offset,
|
||||||
|
unsigned RelocationType,
|
||||||
|
GlobalValue *GV, intptr_t cst = 0,
|
||||||
|
bool NeedStub = 0,
|
||||||
|
bool GOTrelative = 0) {
|
||||||
|
assert((RelocationType & ~63) == 0 && "Relocation type too large!");
|
||||||
|
MachineRelocation Result;
|
||||||
|
Result.Offset = offset;
|
||||||
|
Result.ConstantVal = cst;
|
||||||
|
Result.TargetReloType = RelocationType;
|
||||||
|
Result.AddrType = isGVLazyPtr;
|
||||||
|
Result.NeedStub = NeedStub;
|
||||||
|
Result.GOTRelative = GOTrelative;
|
||||||
|
Result.Target.GV = GV;
|
||||||
|
return Result;
|
||||||
|
}
|
||||||
|
|
||||||
/// MachineRelocation::getBB - Return a relocation entry for a BB.
|
/// MachineRelocation::getBB - Return a relocation entry for a BB.
|
||||||
///
|
///
|
||||||
static MachineRelocation getBB(intptr_t offset,unsigned RelocationType,
|
static MachineRelocation getBB(intptr_t offset,unsigned RelocationType,
|
||||||
@@ -193,6 +213,12 @@ public:
|
|||||||
return AddrType == isGV;
|
return AddrType == isGV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// isGlobalValueVLazyPtr - Return true if this relocation is the address
|
||||||
|
/// of a lazily resolved GlobalValue.
|
||||||
|
bool isGlobalValueLazyPtr() const {
|
||||||
|
return AddrType == isGVLazyPtr;
|
||||||
|
}
|
||||||
|
|
||||||
/// isBasicBlock - Return true if this relocation is a basic block reference.
|
/// isBasicBlock - Return true if this relocation is a basic block reference.
|
||||||
///
|
///
|
||||||
bool isBasicBlock() const {
|
bool isBasicBlock() const {
|
||||||
@@ -234,7 +260,8 @@ public:
|
|||||||
/// getGlobalValue - If this is a global value reference, return the
|
/// getGlobalValue - If this is a global value reference, return the
|
||||||
/// referenced global.
|
/// referenced global.
|
||||||
GlobalValue *getGlobalValue() const {
|
GlobalValue *getGlobalValue() const {
|
||||||
assert(isGlobalValue() && "This is not a global value reference!");
|
assert((isGlobalValue() || isGlobalValueLazyPtr()) &&
|
||||||
|
"This is not a global value reference!");
|
||||||
return Target.GV;
|
return Target.GV;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -40,6 +40,13 @@ namespace llvm {
|
|||||||
///
|
///
|
||||||
virtual void replaceMachineCodeForFunction(void *Old, void *New) = 0;
|
virtual void replaceMachineCodeForFunction(void *Old, void *New) = 0;
|
||||||
|
|
||||||
|
/// emitGlobalValueLazyPtr - Use the specified MachineCodeEmitter object to
|
||||||
|
/// emit a lazy pointer which contains the address of the specified GV.
|
||||||
|
virtual void *emitGlobalValueLazyPtr(void *GV, MachineCodeEmitter &MCE) {
|
||||||
|
assert(0 && "This target doesn't implement emitGlobalValueLazyPtr!");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/// emitFunctionStub - Use the specified MachineCodeEmitter object to emit a
|
/// emitFunctionStub - Use the specified MachineCodeEmitter object to emit a
|
||||||
/// small native function that simply calls the function at the specified
|
/// small native function that simply calls the function at the specified
|
||||||
/// address. Return the address of the resultant function.
|
/// address. Return the address of the resultant function.
|
||||||
|
@@ -52,6 +52,10 @@ namespace {
|
|||||||
/// corresponds to.
|
/// corresponds to.
|
||||||
std::map<void*, Function*> StubToFunctionMap;
|
std::map<void*, Function*> StubToFunctionMap;
|
||||||
|
|
||||||
|
/// GlobalToLazyPtrMap - Keep track of the lazy pointer created for a
|
||||||
|
/// particular GlobalVariable so that we can reuse them if necessary.
|
||||||
|
std::map<GlobalValue*, void*> GlobalToLazyPtrMap;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
std::map<Function*, void*>& getFunctionToStubMap(const MutexGuard& locked) {
|
std::map<Function*, void*>& getFunctionToStubMap(const MutexGuard& locked) {
|
||||||
assert(locked.holds(TheJIT->lock));
|
assert(locked.holds(TheJIT->lock));
|
||||||
@@ -62,6 +66,12 @@ namespace {
|
|||||||
assert(locked.holds(TheJIT->lock));
|
assert(locked.holds(TheJIT->lock));
|
||||||
return StubToFunctionMap;
|
return StubToFunctionMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::map<GlobalValue*, void*>&
|
||||||
|
getGlobalToLazyPtrMap(const MutexGuard& locked) {
|
||||||
|
assert(locked.holds(TheJIT->lock));
|
||||||
|
return GlobalToLazyPtrMap;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// JITResolver - Keep track of, and resolve, call sites for functions that
|
/// JITResolver - Keep track of, and resolve, call sites for functions that
|
||||||
@@ -103,6 +113,10 @@ namespace {
|
|||||||
/// specified address, created lazily on demand.
|
/// specified address, created lazily on demand.
|
||||||
void *getExternalFunctionStub(void *FnAddr);
|
void *getExternalFunctionStub(void *FnAddr);
|
||||||
|
|
||||||
|
/// getGlobalValueLazyPtr - Return a lazy pointer containing the specified
|
||||||
|
/// GV address.
|
||||||
|
void *getGlobalValueLazyPtr(GlobalValue *V, void *GVAddress);
|
||||||
|
|
||||||
/// AddCallbackAtLocation - If the target is capable of rewriting an
|
/// AddCallbackAtLocation - If the target is capable of rewriting an
|
||||||
/// instruction without the use of a stub, record the location of the use so
|
/// instruction without the use of a stub, record the location of the use so
|
||||||
/// we know which function is being used at the location.
|
/// we know which function is being used at the location.
|
||||||
@@ -181,6 +195,25 @@ void *JITResolver::getFunctionStub(Function *F) {
|
|||||||
return Stub;
|
return Stub;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// getGlobalValueLazyPtr - Return a lazy pointer containing the specified
|
||||||
|
/// GV address.
|
||||||
|
void *JITResolver::getGlobalValueLazyPtr(GlobalValue *GV, void *GVAddress) {
|
||||||
|
MutexGuard locked(TheJIT->lock);
|
||||||
|
|
||||||
|
// If we already have a stub for this global variable, recycle it.
|
||||||
|
void *&LazyPtr = state.getGlobalToLazyPtrMap(locked)[GV];
|
||||||
|
if (LazyPtr) return LazyPtr;
|
||||||
|
|
||||||
|
// Otherwise, codegen a new lazy pointer.
|
||||||
|
LazyPtr = TheJIT->getJITInfo().emitGlobalValueLazyPtr(GVAddress,
|
||||||
|
*TheJIT->getCodeEmitter());
|
||||||
|
|
||||||
|
DOUT << "JIT: Stub emitted at [" << LazyPtr << "] for GV '"
|
||||||
|
<< GV->getName() << "'\n";
|
||||||
|
|
||||||
|
return LazyPtr;
|
||||||
|
}
|
||||||
|
|
||||||
/// getExternalFunctionStub - Return a stub for the function at the
|
/// getExternalFunctionStub - Return a stub for the function at the
|
||||||
/// specified address, created lazily on demand.
|
/// specified address, created lazily on demand.
|
||||||
void *JITResolver::getExternalFunctionStub(void *FnAddr) {
|
void *JITResolver::getExternalFunctionStub(void *FnAddr) {
|
||||||
@@ -361,6 +394,8 @@ namespace {
|
|||||||
}
|
}
|
||||||
private:
|
private:
|
||||||
void *getPointerToGlobal(GlobalValue *GV, void *Reference, bool NoNeedStub);
|
void *getPointerToGlobal(GlobalValue *GV, void *Reference, bool NoNeedStub);
|
||||||
|
void *getPointerToGVLazyPtr(GlobalValue *V, void *Reference,
|
||||||
|
bool NoNeedStub);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -396,6 +431,16 @@ void *JITEmitter::getPointerToGlobal(GlobalValue *V, void *Reference,
|
|||||||
return Resolver.getFunctionStub(F);
|
return Resolver.getFunctionStub(F);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *JITEmitter::getPointerToGVLazyPtr(GlobalValue *V, void *Reference,
|
||||||
|
bool DoesntNeedStub) {
|
||||||
|
// Make sure GV is emitted first.
|
||||||
|
// FIXME: For now, if the GV is an external function we force the JIT to
|
||||||
|
// compile it so the lazy pointer will contain the fully resolved address.
|
||||||
|
void *GVAddress = getPointerToGlobal(V, Reference, true);
|
||||||
|
return Resolver.getGlobalValueLazyPtr(V, GVAddress);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void JITEmitter::startFunction(MachineFunction &F) {
|
void JITEmitter::startFunction(MachineFunction &F) {
|
||||||
uintptr_t ActualSize;
|
uintptr_t ActualSize;
|
||||||
BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
|
BufferBegin = CurBufferPtr = MemMgr->startFunctionBody(F.getFunction(),
|
||||||
@@ -450,6 +495,10 @@ bool JITEmitter::finishFunction(MachineFunction &F) {
|
|||||||
ResultPtr = getPointerToGlobal(MR.getGlobalValue(),
|
ResultPtr = getPointerToGlobal(MR.getGlobalValue(),
|
||||||
BufferBegin+MR.getMachineCodeOffset(),
|
BufferBegin+MR.getMachineCodeOffset(),
|
||||||
MR.doesntNeedStub());
|
MR.doesntNeedStub());
|
||||||
|
} else if (MR.isGlobalValueLazyPtr()) {
|
||||||
|
ResultPtr = getPointerToGVLazyPtr(MR.getGlobalValue(),
|
||||||
|
BufferBegin+MR.getMachineCodeOffset(),
|
||||||
|
MR.doesntNeedStub());
|
||||||
} else if (MR.isBasicBlock()) {
|
} else if (MR.isBasicBlock()) {
|
||||||
ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock());
|
ResultPtr = (void*)getMachineBasicBlockAddress(MR.getBasicBlock());
|
||||||
} else if (MR.isConstantPoolIndex()) {
|
} else if (MR.isConstantPoolIndex()) {
|
||||||
|
@@ -40,20 +40,17 @@ namespace {
|
|||||||
intptr_t PICBase;
|
intptr_t PICBase;
|
||||||
bool Is64BitMode;
|
bool Is64BitMode;
|
||||||
bool IsPIC;
|
bool IsPIC;
|
||||||
bool IsStatic;
|
|
||||||
public:
|
public:
|
||||||
static char ID;
|
static char ID;
|
||||||
explicit Emitter(TargetMachine &tm, MachineCodeEmitter &mce)
|
explicit Emitter(TargetMachine &tm, MachineCodeEmitter &mce)
|
||||||
: MachineFunctionPass((intptr_t)&ID), II(0), TD(0), TM(tm),
|
: MachineFunctionPass((intptr_t)&ID), II(0), TD(0), TM(tm),
|
||||||
MCE(mce), PICBase(0), Is64BitMode(false),
|
MCE(mce), PICBase(0), Is64BitMode(false),
|
||||||
IsPIC(TM.getRelocationModel() == Reloc::PIC_),
|
IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
|
||||||
IsStatic(TM.getRelocationModel() == Reloc::Static) {}
|
|
||||||
Emitter(TargetMachine &tm, MachineCodeEmitter &mce,
|
Emitter(TargetMachine &tm, MachineCodeEmitter &mce,
|
||||||
const X86InstrInfo &ii, const TargetData &td, bool is64)
|
const X86InstrInfo &ii, const TargetData &td, bool is64)
|
||||||
: MachineFunctionPass((intptr_t)&ID), II(&ii), TD(&td), TM(tm),
|
: MachineFunctionPass((intptr_t)&ID), II(&ii), TD(&td), TM(tm),
|
||||||
MCE(mce), PICBase(0), Is64BitMode(is64),
|
MCE(mce), PICBase(0), Is64BitMode(is64),
|
||||||
IsPIC(TM.getRelocationModel() == Reloc::PIC_),
|
IsPIC(TM.getRelocationModel() == Reloc::PIC_) {}
|
||||||
IsStatic(TM.getRelocationModel() == Reloc::Static) {}
|
|
||||||
|
|
||||||
bool runOnMachineFunction(MachineFunction &MF);
|
bool runOnMachineFunction(MachineFunction &MF);
|
||||||
|
|
||||||
@@ -67,7 +64,7 @@ namespace {
|
|||||||
void emitPCRelativeBlockAddress(MachineBasicBlock *MBB);
|
void emitPCRelativeBlockAddress(MachineBasicBlock *MBB);
|
||||||
void emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
|
void emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
|
||||||
int Disp = 0, intptr_t PCAdj = 0,
|
int Disp = 0, intptr_t PCAdj = 0,
|
||||||
bool NeedStub = false);
|
bool NeedStub = false, bool IsLazy = false);
|
||||||
void emitExternalSymbolAddress(const char *ES, unsigned Reloc);
|
void emitExternalSymbolAddress(const char *ES, unsigned Reloc);
|
||||||
void emitConstPoolAddress(unsigned CPI, unsigned Reloc, int Disp = 0,
|
void emitConstPoolAddress(unsigned CPI, unsigned Reloc, int Disp = 0,
|
||||||
intptr_t PCAdj = 0);
|
intptr_t PCAdj = 0);
|
||||||
@@ -88,6 +85,8 @@ namespace {
|
|||||||
unsigned getX86RegNum(unsigned RegNo);
|
unsigned getX86RegNum(unsigned RegNo);
|
||||||
bool isX86_64ExtendedReg(const MachineOperand &MO);
|
bool isX86_64ExtendedReg(const MachineOperand &MO);
|
||||||
unsigned determineREX(const MachineInstr &MI);
|
unsigned determineREX(const MachineInstr &MI);
|
||||||
|
|
||||||
|
bool gvNeedsLazyPtr(const GlobalValue *GV);
|
||||||
};
|
};
|
||||||
char Emitter::ID = 0;
|
char Emitter::ID = 0;
|
||||||
}
|
}
|
||||||
@@ -103,10 +102,9 @@ bool Emitter::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
|
assert((MF.getTarget().getRelocationModel() != Reloc::Default ||
|
||||||
MF.getTarget().getRelocationModel() != Reloc::Static) &&
|
MF.getTarget().getRelocationModel() != Reloc::Static) &&
|
||||||
"JIT relocation model must be set to static or default!");
|
"JIT relocation model must be set to static or default!");
|
||||||
II = ((X86TargetMachine&)MF.getTarget()).getInstrInfo();
|
II = ((X86TargetMachine&)TM).getInstrInfo();
|
||||||
TD = ((X86TargetMachine&)MF.getTarget()).getTargetData();
|
TD = ((X86TargetMachine&)TM).getTargetData();
|
||||||
Is64BitMode =
|
Is64BitMode = TM.getSubtarget<X86Subtarget>().is64Bit();
|
||||||
((X86TargetMachine&)MF.getTarget()).getSubtarget<X86Subtarget>().is64Bit();
|
|
||||||
|
|
||||||
do {
|
do {
|
||||||
MCE.startFunction(MF);
|
MCE.startFunction(MF);
|
||||||
@@ -139,11 +137,19 @@ void Emitter::emitPCRelativeBlockAddress(MachineBasicBlock *MBB) {
|
|||||||
///
|
///
|
||||||
void Emitter::emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
|
void Emitter::emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
|
||||||
int Disp /* = 0 */, intptr_t PCAdj /* = 0 */,
|
int Disp /* = 0 */, intptr_t PCAdj /* = 0 */,
|
||||||
bool NeedStub /* = false */) {
|
bool NeedStub /* = false */,
|
||||||
|
bool isLazy /* = false */) {
|
||||||
|
intptr_t RelocCST = 0;
|
||||||
if (Reloc == X86::reloc_picrel_word)
|
if (Reloc == X86::reloc_picrel_word)
|
||||||
PCAdj += PICBase;
|
RelocCST = PICBase;
|
||||||
MCE.addRelocation(MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
|
else if (Reloc == X86::reloc_pcrel_word)
|
||||||
GV, PCAdj, NeedStub));
|
RelocCST = PCAdj;
|
||||||
|
MachineRelocation MR = isLazy
|
||||||
|
? MachineRelocation::getGVLazyPtr(MCE.getCurrentPCOffset(), Reloc,
|
||||||
|
GV, RelocCST, NeedStub)
|
||||||
|
: MachineRelocation::getGV(MCE.getCurrentPCOffset(), Reloc,
|
||||||
|
GV, RelocCST, NeedStub);
|
||||||
|
MCE.addRelocation(MR);
|
||||||
if (Reloc == X86::reloc_absolute_dword)
|
if (Reloc == X86::reloc_absolute_dword)
|
||||||
MCE.emitWordLE(0);
|
MCE.emitWordLE(0);
|
||||||
MCE.emitWordLE(Disp); // The relocated value will be added to the displacement
|
MCE.emitWordLE(Disp); // The relocated value will be added to the displacement
|
||||||
@@ -153,9 +159,9 @@ void Emitter::emitGlobalAddress(GlobalValue *GV, unsigned Reloc,
|
|||||||
/// be emitted to the current location in the function, and allow it to be PC
|
/// be emitted to the current location in the function, and allow it to be PC
|
||||||
/// relative.
|
/// relative.
|
||||||
void Emitter::emitExternalSymbolAddress(const char *ES, unsigned Reloc) {
|
void Emitter::emitExternalSymbolAddress(const char *ES, unsigned Reloc) {
|
||||||
intptr_t PCAdj = (Reloc == X86::reloc_picrel_word) ? PICBase : 0;
|
intptr_t RelocCST = (Reloc == X86::reloc_picrel_word) ? PICBase : 0;
|
||||||
MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
|
MCE.addRelocation(MachineRelocation::getExtSym(MCE.getCurrentPCOffset(),
|
||||||
Reloc, ES, PCAdj));
|
Reloc, ES, RelocCST));
|
||||||
if (Reloc == X86::reloc_absolute_dword)
|
if (Reloc == X86::reloc_absolute_dword)
|
||||||
MCE.emitWordLE(0);
|
MCE.emitWordLE(0);
|
||||||
MCE.emitWordLE(0);
|
MCE.emitWordLE(0);
|
||||||
@@ -167,10 +173,13 @@ void Emitter::emitExternalSymbolAddress(const char *ES, unsigned Reloc) {
|
|||||||
void Emitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc,
|
void Emitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc,
|
||||||
int Disp /* = 0 */,
|
int Disp /* = 0 */,
|
||||||
intptr_t PCAdj /* = 0 */) {
|
intptr_t PCAdj /* = 0 */) {
|
||||||
|
intptr_t RelocCST = 0;
|
||||||
if (Reloc == X86::reloc_picrel_word)
|
if (Reloc == X86::reloc_picrel_word)
|
||||||
PCAdj += PICBase;
|
RelocCST = PICBase;
|
||||||
|
else if (Reloc == X86::reloc_pcrel_word)
|
||||||
|
RelocCST = PCAdj;
|
||||||
MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
|
MCE.addRelocation(MachineRelocation::getConstPool(MCE.getCurrentPCOffset(),
|
||||||
Reloc, CPI, PCAdj));
|
Reloc, CPI, RelocCST));
|
||||||
if (Reloc == X86::reloc_absolute_dword)
|
if (Reloc == X86::reloc_absolute_dword)
|
||||||
MCE.emitWordLE(0);
|
MCE.emitWordLE(0);
|
||||||
MCE.emitWordLE(Disp); // The relocated value will be added to the displacement
|
MCE.emitWordLE(Disp); // The relocated value will be added to the displacement
|
||||||
@@ -181,10 +190,13 @@ void Emitter::emitConstPoolAddress(unsigned CPI, unsigned Reloc,
|
|||||||
/// relative.
|
/// relative.
|
||||||
void Emitter::emitJumpTableAddress(unsigned JTI, unsigned Reloc,
|
void Emitter::emitJumpTableAddress(unsigned JTI, unsigned Reloc,
|
||||||
intptr_t PCAdj /* = 0 */) {
|
intptr_t PCAdj /* = 0 */) {
|
||||||
|
intptr_t RelocCST = 0;
|
||||||
if (Reloc == X86::reloc_picrel_word)
|
if (Reloc == X86::reloc_picrel_word)
|
||||||
PCAdj += PICBase;
|
RelocCST = PICBase;
|
||||||
|
else if (Reloc == X86::reloc_pcrel_word)
|
||||||
|
RelocCST = PCAdj;
|
||||||
MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
|
MCE.addRelocation(MachineRelocation::getJumpTable(MCE.getCurrentPCOffset(),
|
||||||
Reloc, JTI, PCAdj));
|
Reloc, JTI, RelocCST));
|
||||||
if (Reloc == X86::reloc_absolute_dword)
|
if (Reloc == X86::reloc_absolute_dword)
|
||||||
MCE.emitWordLE(0);
|
MCE.emitWordLE(0);
|
||||||
MCE.emitWordLE(0); // The relocated value will be added to the displacement
|
MCE.emitWordLE(0); // The relocated value will be added to the displacement
|
||||||
@@ -223,6 +235,11 @@ static bool isDisp8(int Value) {
|
|||||||
return Value == (signed char)Value;
|
return Value == (signed char)Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Emitter::gvNeedsLazyPtr(const GlobalValue *GV) {
|
||||||
|
return !Is64BitMode &&
|
||||||
|
TM.getSubtarget<X86Subtarget>().GVRequiresExtraLoad(GV, TM, false);
|
||||||
|
}
|
||||||
|
|
||||||
void Emitter::emitDisplacementField(const MachineOperand *RelocOp,
|
void Emitter::emitDisplacementField(const MachineOperand *RelocOp,
|
||||||
int DispVal, intptr_t PCAdj) {
|
int DispVal, intptr_t PCAdj) {
|
||||||
// If this is a simple integer displacement that doesn't require a relocation,
|
// If this is a simple integer displacement that doesn't require a relocation,
|
||||||
@@ -241,9 +258,10 @@ void Emitter::emitDisplacementField(const MachineOperand *RelocOp,
|
|||||||
// 89 04 25 00 00 00 00 mov %eax,0x0 # Absolute
|
// 89 04 25 00 00 00 00 mov %eax,0x0 # Absolute
|
||||||
unsigned rt = Is64BitMode ? X86::reloc_pcrel_word
|
unsigned rt = Is64BitMode ? X86::reloc_pcrel_word
|
||||||
: (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word);
|
: (IsPIC ? X86::reloc_picrel_word : X86::reloc_absolute_word);
|
||||||
bool NeedStub = !IsStatic || isa<Function>(RelocOp->getGlobal());
|
bool NeedStub = isa<Function>(RelocOp->getGlobal());
|
||||||
|
bool isLazy = gvNeedsLazyPtr(RelocOp->getGlobal());
|
||||||
emitGlobalAddress(RelocOp->getGlobal(), rt, RelocOp->getOffset(),
|
emitGlobalAddress(RelocOp->getGlobal(), rt, RelocOp->getOffset(),
|
||||||
PCAdj, NeedStub);
|
PCAdj, NeedStub, isLazy);
|
||||||
} else if (RelocOp->isConstantPoolIndex()) {
|
} else if (RelocOp->isConstantPoolIndex()) {
|
||||||
unsigned rt = Is64BitMode ? X86::reloc_pcrel_word : X86::reloc_picrel_word;
|
unsigned rt = Is64BitMode ? X86::reloc_pcrel_word : X86::reloc_picrel_word;
|
||||||
emitConstPoolAddress(RelocOp->getIndex(), rt,
|
emitConstPoolAddress(RelocOp->getIndex(), rt,
|
||||||
@@ -601,8 +619,7 @@ void Emitter::emitInstruction(const MachineInstr &MI) {
|
|||||||
if (MO.isMachineBasicBlock()) {
|
if (MO.isMachineBasicBlock()) {
|
||||||
emitPCRelativeBlockAddress(MO.getMBB());
|
emitPCRelativeBlockAddress(MO.getMBB());
|
||||||
} else if (MO.isGlobalAddress()) {
|
} else if (MO.isGlobalAddress()) {
|
||||||
bool NeedStub = !IsStatic ||
|
bool NeedStub = Is64BitMode && TM.getCodeModel() == CodeModel::Large;
|
||||||
(Is64BitMode && TM.getCodeModel() == CodeModel::Large);
|
|
||||||
emitGlobalAddress(MO.getGlobal(), X86::reloc_pcrel_word,
|
emitGlobalAddress(MO.getGlobal(), X86::reloc_pcrel_word,
|
||||||
0, 0, NeedStub);
|
0, 0, NeedStub);
|
||||||
} else if (MO.isExternalSymbol()) {
|
} else if (MO.isExternalSymbol()) {
|
||||||
@@ -634,8 +651,10 @@ void Emitter::emitInstruction(const MachineInstr &MI) {
|
|||||||
if (Opcode == X86::MOV64ri)
|
if (Opcode == X86::MOV64ri)
|
||||||
rt = X86::reloc_absolute_dword; // FIXME: add X86II flag?
|
rt = X86::reloc_absolute_dword; // FIXME: add X86II flag?
|
||||||
if (MO1.isGlobalAddress()) {
|
if (MO1.isGlobalAddress()) {
|
||||||
bool NeedStub = !IsStatic || isa<Function>(MO1.getGlobal());
|
bool NeedStub = isa<Function>(MO1.getGlobal());
|
||||||
emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0, NeedStub);
|
bool isLazy = gvNeedsLazyPtr(MO1.getGlobal());
|
||||||
|
emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0,
|
||||||
|
NeedStub, isLazy);
|
||||||
} else if (MO1.isExternalSymbol())
|
} else if (MO1.isExternalSymbol())
|
||||||
emitExternalSymbolAddress(MO1.getSymbolName(), rt);
|
emitExternalSymbolAddress(MO1.getSymbolName(), rt);
|
||||||
else if (MO1.isConstantPoolIndex())
|
else if (MO1.isConstantPoolIndex())
|
||||||
@@ -704,8 +723,10 @@ void Emitter::emitInstruction(const MachineInstr &MI) {
|
|||||||
if (Opcode == X86::MOV64ri32)
|
if (Opcode == X86::MOV64ri32)
|
||||||
rt = X86::reloc_absolute_word; // FIXME: add X86II flag?
|
rt = X86::reloc_absolute_word; // FIXME: add X86II flag?
|
||||||
if (MO1.isGlobalAddress()) {
|
if (MO1.isGlobalAddress()) {
|
||||||
bool NeedStub = !IsStatic || isa<Function>(MO1.getGlobal());
|
bool NeedStub = isa<Function>(MO1.getGlobal());
|
||||||
emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0, NeedStub);
|
bool isLazy = gvNeedsLazyPtr(MO1.getGlobal());
|
||||||
|
emitGlobalAddress(MO1.getGlobal(), rt, MO1.getOffset(), 0,
|
||||||
|
NeedStub, isLazy);
|
||||||
} else if (MO1.isExternalSymbol())
|
} else if (MO1.isExternalSymbol())
|
||||||
emitExternalSymbolAddress(MO1.getSymbolName(), rt);
|
emitExternalSymbolAddress(MO1.getSymbolName(), rt);
|
||||||
else if (MO1.isConstantPoolIndex())
|
else if (MO1.isConstantPoolIndex())
|
||||||
@@ -739,8 +760,10 @@ void Emitter::emitInstruction(const MachineInstr &MI) {
|
|||||||
if (Opcode == X86::MOV64mi32)
|
if (Opcode == X86::MOV64mi32)
|
||||||
rt = X86::reloc_absolute_word; // FIXME: add X86II flag?
|
rt = X86::reloc_absolute_word; // FIXME: add X86II flag?
|
||||||
if (MO.isGlobalAddress()) {
|
if (MO.isGlobalAddress()) {
|
||||||
bool NeedStub = !IsStatic || isa<Function>(MO.getGlobal());
|
bool NeedStub = isa<Function>(MO.getGlobal());
|
||||||
emitGlobalAddress(MO.getGlobal(), rt, MO.getOffset(), 0, NeedStub);
|
bool isLazy = gvNeedsLazyPtr(MO.getGlobal());
|
||||||
|
emitGlobalAddress(MO.getGlobal(), rt, MO.getOffset(), 0,
|
||||||
|
NeedStub, isLazy);
|
||||||
} else if (MO.isExternalSymbol())
|
} else if (MO.isExternalSymbol())
|
||||||
emitExternalSymbolAddress(MO.getSymbolName(), rt);
|
emitExternalSymbolAddress(MO.getSymbolName(), rt);
|
||||||
else if (MO.isConstantPoolIndex())
|
else if (MO.isConstantPoolIndex())
|
||||||
|
@@ -380,6 +380,18 @@ X86JITInfo::getLazyResolverFunction(JITCompilerFn F) {
|
|||||||
return X86CompilationCallback;
|
return X86CompilationCallback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void *X86JITInfo::emitGlobalValueLazyPtr(void *GV, MachineCodeEmitter &MCE) {
|
||||||
|
#ifdef __x86_64__
|
||||||
|
MCE.startFunctionStub(8, 8);
|
||||||
|
MCE.emitWordLE(((unsigned *)&GV)[0]);
|
||||||
|
MCE.emitWordLE(((unsigned *)&GV)[1]);
|
||||||
|
#else
|
||||||
|
MCE.startFunctionStub(4, 4);
|
||||||
|
MCE.emitWordLE((unsigned)GV);
|
||||||
|
#endif
|
||||||
|
return MCE.finishFunctionStub(0);
|
||||||
|
}
|
||||||
|
|
||||||
void *X86JITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) {
|
void *X86JITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) {
|
||||||
// Note, we cast to intptr_t here to silence a -pedantic warning that
|
// Note, we cast to intptr_t here to silence a -pedantic warning that
|
||||||
// complains about casting a function pointer to a normal pointer.
|
// complains about casting a function pointer to a normal pointer.
|
||||||
|
@@ -31,6 +31,10 @@ namespace llvm {
|
|||||||
///
|
///
|
||||||
virtual void replaceMachineCodeForFunction(void *Old, void *New);
|
virtual void replaceMachineCodeForFunction(void *Old, void *New);
|
||||||
|
|
||||||
|
/// emitGlobalValueLazyPtr - Use the specified MachineCodeEmitter object to
|
||||||
|
/// emit a lazy pointer which contains the address of the specified GV.
|
||||||
|
virtual void *emitGlobalValueLazyPtr(void *GV, MachineCodeEmitter &MCE);
|
||||||
|
|
||||||
/// emitFunctionStub - Use the specified MachineCodeEmitter object to emit a
|
/// emitFunctionStub - Use the specified MachineCodeEmitter object to emit a
|
||||||
/// small native function that simply calls the function at the specified
|
/// small native function that simply calls the function at the specified
|
||||||
/// address.
|
/// address.
|
||||||
|
Reference in New Issue
Block a user