[MIPS] ORC JIT support

This patch adds support for ORC JIT for mips/mips64 architecture.
In common code $static is changed to __ORCstatic because on MIPS
architecture "$" is a reserved character.

Patch by Luka Ercegovcevic

Differential Revision: https://reviews.llvm.org/D49665

llvm-svn: 341934
This commit is contained in:
Petar Jovanovic 2018-09-11 13:10:04 +00:00
parent 32979413eb
commit fed72984cb
5 changed files with 565 additions and 5 deletions

View File

@ -238,7 +238,78 @@ public:
unsigned MinStubs, void *InitialPtrVal);
};
} // end namespace orc
} // end namespace llvm
// @brief Mips32 support.
//
// Mips32 supports lazy JITing.
class OrcMips32_Base {
public:
static const unsigned PointerSize = 4;
static const unsigned TrampolineSize = 20;
static const unsigned ResolverCodeSize = 0xfc;
using IndirectStubsInfo = GenericIndirectStubsInfo<16>;
using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
void *TrampolineId);
/// @brief Write the requsted number of trampolines into the given memory,
/// which must be big enough to hold 1 pointer, plus NumTrampolines
/// trampolines.
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
/// @brief Write the resolver code into the given memory. The user is be
/// responsible for allocating the memory and setting permissions.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr, bool isBigEndian);
/// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
/// the nearest page size.
///
/// E.g. Asking for 4 stubs on Mips32, where stubs are 8-bytes, with 4k
/// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
/// will return a block of 1024 (2-pages worth).
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal);
};
class OrcMips32Le : public OrcMips32_Base {
public:
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
{ OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, false); }
};
class OrcMips32Be : public OrcMips32_Base {
public:
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr)
{ OrcMips32_Base::writeResolverCode(ResolveMem, Reentry, CallbackMgr, true); }
};
// @brief Mips64 support.
//
// Mips64 supports lazy JITing.
class OrcMips64 {
public:
static const unsigned PointerSize = 8;
static const unsigned TrampolineSize = 40;
static const unsigned ResolverCodeSize = 0x11C;
using IndirectStubsInfo = GenericIndirectStubsInfo<32>;
using JITReentryFn = JITTargetAddress (*)(void *CallbackMgr,
void *TrampolineId);
/// @brief Write the resolver code into the given memory. The user is be
/// responsible for allocating the memory and setting permissions.
static void writeResolverCode(uint8_t *ResolveMem, JITReentryFn Reentry,void *CallbackMgr);
/// @brief Write the requsted number of trampolines into the given memory,
/// which must be big enough to hold 1 pointer, plus NumTrampolines
/// trampolines.
static void writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,unsigned NumTrampolines);
/// @brief Emit at least MinStubs worth of indirect call stubs, rounded out to
/// the nearest page size.
///
/// E.g. Asking for 4 stubs on Mips64, where stubs are 8-bytes, with 4k
/// pages will return a block of 512 stubs (4096 / 8 = 512). Asking for 513
/// will return a block of 1024 (2-pages worth).
static Error emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,unsigned MinStubs, void *InitialPtrVal);
};
} // end namespace orc
} // end namespace llvm
#endif // LLVM_EXECUTIONENGINE_ORC_ORCABISUPPORT_H

View File

@ -123,6 +123,21 @@ createLocalCompileCallbackManager(const Triple &T, ExecutionSession &ES,
return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
}
case Triple::mips: {
typedef orc::LocalJITCompileCallbackManager<orc::OrcMips32Be> CCMgrT;
return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
}
case Triple::mipsel: {
typedef orc::LocalJITCompileCallbackManager<orc::OrcMips32Le> CCMgrT;
return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
}
case Triple::mips64:
case Triple::mips64el: {
typedef orc::LocalJITCompileCallbackManager<orc::OrcMips64> CCMgrT;
return llvm::make_unique<CCMgrT>(ES, ErrorHandlerAddress);
}
case Triple::x86_64: {
if ( T.getOS() == Triple::OSType::Win32 ) {
typedef orc::LocalJITCompileCallbackManager<orc::OrcX86_64_Win32> CCMgrT;
@ -157,6 +172,25 @@ createLocalIndirectStubsManagerBuilder(const Triple &T) {
orc::LocalIndirectStubsManager<orc::OrcI386>>();
};
case Triple::mips:
return [](){
return llvm::make_unique<
orc::LocalIndirectStubsManager<orc::OrcMips32Be>>();
};
case Triple::mipsel:
return [](){
return llvm::make_unique<
orc::LocalIndirectStubsManager<orc::OrcMips32Le>>();
};
case Triple::mips64:
case Triple::mips64el:
return [](){
return llvm::make_unique<
orc::LocalIndirectStubsManager<orc::OrcMips64>>();
};
case Triple::x86_64:
if (T.getOS() == Triple::OSType::Win32) {
return [](){

View File

@ -537,5 +537,460 @@ Error OrcI386::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
return Error::success();
}
void OrcMips32_Base::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn,
void *CallbackMgr, bool isBigEndian) {
const uint32_t ResolverCode[] = {
// resolver_entry:
0x27bdff98, // 0x00: addiu $sp,$sp,-104
0xafa20000, // 0x04: sw $v0,0($sp)
0xafa30004, // 0x08: sw $v1,4($sp)
0xafa40008, // 0x0c: sw $a0,8($sp)
0xafa5000c, // 0x10: sw $a1,12($sp)
0xafa60010, // 0x14: sw $a2,16($sp)
0xafa70014, // 0x18: sw $a3,20($sp)
0xafb00018, // 0x1c: sw $s0,24($sp)
0xafb1001c, // 0x20: sw $s1,28($sp)
0xafb20020, // 0x24: sw $s2,32($sp)
0xafb30024, // 0x28: sw $s3,36($sp)
0xafb40028, // 0x2c: sw $s4,40($sp)
0xafb5002c, // 0x30: sw $s5,44($sp)
0xafb60030, // 0x34: sw $s6,48($sp)
0xafb70034, // 0x38: sw $s7,52($sp)
0xafa80038, // 0x3c: sw $t0,56($sp)
0xafa9003c, // 0x40: sw $t1,60($sp)
0xafaa0040, // 0x44: sw $t2,64($sp)
0xafab0044, // 0x48: sw $t3,68($sp)
0xafac0048, // 0x4c: sw $t4,72($sp)
0xafad004c, // 0x50: sw $t5,76($sp)
0xafae0050, // 0x54: sw $t6,80($sp)
0xafaf0054, // 0x58: sw $t7,84($sp)
0xafb80058, // 0x5c: sw $t8,88($sp)
0xafb9005c, // 0x60: sw $t9,92($sp)
0xafbe0060, // 0x64: sw $fp,96($sp)
0xafbf0064, // 0x68: sw $ra,100($sp)
// Callback manager addr.
0x00000000, // 0x6c: lui $a0,callbackmgr
0x00000000, // 0x70: addiu $a0,$a0,callbackmgr
0x03e02825, // 0x74: move $a1, $ra
0x24a5ffec, // 0x78: addiu $a1,$a1,-20
// JIT re-entry fn addr:
0x00000000, // 0x7c: lui $t9,reentry
0x00000000, // 0x80: addiu $t9,$t9,reentry
0x0320f809, // 0x84: jalr $t9
0x00000000, // 0x88: nop
0x8fbf0064, // 0x8c: lw $ra,100($sp)
0x8fbe0060, // 0x90: lw $fp,96($sp)
0x8fb9005c, // 0x94: lw $t9,92($sp)
0x8fb80058, // 0x98: lw $t8,88($sp)
0x8faf0054, // 0x9c: lw $t7,84($sp)
0x8fae0050, // 0xa0: lw $t6,80($sp)
0x8fad004c, // 0xa4: lw $t5,76($sp)
0x8fac0048, // 0xa8: lw $t4,72($sp)
0x8fab0044, // 0xac: lw $t3,68($sp)
0x8faa0040, // 0xb0: lw $t2,64($sp)
0x8fa9003c, // 0xb4: lw $t1,60($sp)
0x8fa80038, // 0xb8: lw $t0,56($sp)
0x8fb70034, // 0xbc: lw $s7,52($sp)
0x8fb60030, // 0xc0: lw $s6,48($sp)
0x8fb5002c, // 0xc4: lw $s5,44($sp)
0x8fb40028, // 0xc8: lw $s4,40($sp)
0x8fb30024, // 0xcc: lw $s3,36($sp)
0x8fb20020, // 0xd0: lw $s2,32($sp)
0x8fb1001c, // 0xd4: lw $s1,28($sp)
0x8fb00018, // 0xd8: lw $s0,24($sp)
0x8fa70014, // 0xdc: lw $a3,20($sp)
0x8fa70014, // 0xe0: lw $a3,20($sp)
0x8fa60010, // 0xe4: lw $a2,16($sp)
0x8fa5000c, // 0xe8: lw $a1,12($sp)
0x8fa40008, // 0xec: lw $a0,8($sp)
0x27bd0068, // 0xf4: addiu $sp,$sp,104
0x0300f825, // 0xf8: move $ra, $t8
0x00000000 // 0xfc: jr $v0/v1
};
const unsigned ReentryFnAddrOffset = 0x7c; // JIT re-entry fn addr lui
const unsigned CallbackMgrAddrOffset = 0x6c; // Callback manager addr lui
const unsigned offsett = 0xfc;
memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode));
//Depending on endian return value will be in v0 or v1.
uint32_t JumpV0 = 0x00400008;
uint32_t JumpV1 = 0x00600008;
if(isBigEndian == true)
memcpy(ResolverMem + offsett, &JumpV1,
sizeof(JumpV1));
else
memcpy(ResolverMem + offsett, &JumpV0,
sizeof(JumpV0));
uint64_t CallMgrAddr = reinterpret_cast<uint64_t>(CallbackMgr);
uint32_t CallMgrLUi = 0x3c040000 | (((CallMgrAddr + 0x8000) >> 16) & 0xFFFF);
uint32_t CallMgrADDiu = 0x24840000 | ((CallMgrAddr) & 0xFFFF);
memcpy(ResolverMem + CallbackMgrAddrOffset, &CallMgrLUi,
sizeof(CallMgrLUi));
memcpy(ResolverMem + (CallbackMgrAddrOffset + 4), &CallMgrADDiu,
sizeof(CallMgrADDiu));
uint64_t ReentryAddr = reinterpret_cast<uint64_t>(ReentryFn);
uint32_t ReentryLUi = 0x3c190000 | (((ReentryAddr + 0x8000) >> 16) & 0xFFFF);
uint32_t ReentryADDiu = 0x27390000 | ((ReentryAddr) & 0xFFFF);
memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryLUi,
sizeof(ReentryLUi));
memcpy(ResolverMem + (ReentryFnAddrOffset + 4), &ReentryADDiu,
sizeof(ReentryADDiu));
}
void OrcMips32_Base::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
unsigned NumTrampolines) {
uint32_t *Trampolines = reinterpret_cast<uint32_t *>(TrampolineMem);
uint64_t ResolveAddr = reinterpret_cast<uint64_t>(ResolverAddr);
uint32_t RHiAddr = ((ResolveAddr + 0x8000) >> 16);
for (unsigned I = 0; I < NumTrampolines; ++I) {
Trampolines[5 * I + 0] = 0x03e0c025; // move $t8,$ra
Trampolines[5 * I + 1] = 0x3c190000 | (RHiAddr & 0xFFFF); // lui $t9,resolveAddr
Trampolines[5 * I + 2] = 0x27390000 | (ResolveAddr & 0xFFFF); // addiu $t9,$t9,resolveAddr
Trampolines[5 * I + 3] = 0x0320f809; // jalr $t9
Trampolines[5 * I + 4] = 0x00000000; // nop
}
}
Error OrcMips32_Base::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
unsigned MinStubs,
void *InitialPtrVal) {
// Stub format is:
//
// .section __orc_stubs
// stub1:
// lui $t9, ptr1
// lw $t9, %lo(ptr1)($t9)
// jr $t9
// stub2:
// lui $t9, ptr2
// lw $t9,%lo(ptr1)($t9)
// jr $t9
//
// ...
//
// .section __orc_ptrs
// ptr1:
// .word 0x0
// ptr2:
// .word 0x0
//
// ...
const unsigned StubSize = IndirectStubsInfo::StubSize;
// Emit at least MinStubs, rounded up to fill the pages allocated.
unsigned PageSize = sys::Process::getPageSize();
unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
unsigned NumStubs = (NumPages * PageSize) / StubSize;
// Allocate memory for stubs and pointers in one call.
std::error_code EC;
auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
2 * NumPages * PageSize, nullptr,
sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
if (EC)
return errorCodeToError(EC);
// Create separate MemoryBlocks representing the stubs and pointers.
sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize);
sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) +
NumPages * PageSize,
NumPages * PageSize);
// Populate the stubs page stubs and mark it executable.
uint32_t *Stub = reinterpret_cast<uint32_t *>(StubsBlock.base());
uint64_t PtrAddr = reinterpret_cast<uint64_t>(Stub) + NumPages * PageSize;
for (unsigned I = 0; I < NumStubs; ++I) {
uint32_t HiAddr = ((PtrAddr + 0x8000) >> 16);
Stub[4 * I + 0] = 0x3c190000 | (HiAddr & 0xFFFF); // lui $t9,ptr1
Stub[4 * I + 1] = 0x8f390000 | (PtrAddr & 0xFFFF); // lw $t9,%lo(ptr1)($t9)
Stub[4 * I + 2] = 0x03200008; // jr $t9
Stub[4 * I + 3] = 0x00000000; // nop
PtrAddr += 4;
}
if (auto EC = sys::Memory::protectMappedMemory(
StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC))
return errorCodeToError(EC);
// Initialize all pointers to point at FailureAddress.
void **Ptr = reinterpret_cast<void **>(PtrsBlock.base());
for (unsigned I = 0; I < NumStubs; ++I)
Ptr[I] = InitialPtrVal;
StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem));
return Error::success();
}
void OrcMips64::writeResolverCode(uint8_t *ResolverMem, JITReentryFn ReentryFn,
void *CallbackMgr) {
const uint32_t ResolverCode[] = {
//resolver_entry:
0x67bdff30, // 0x00: daddiu $sp,$sp,-208
0xffa20000, // 0x04: sd v0,0(sp)
0xffa30008, // 0x08: sd v1,8(sp)
0xffa40010, // 0x0c: sd a0,16(sp)
0xffa50018, // 0x10: sd a1,24(sp)
0xffa60020, // 0x14: sd a2,32(sp)
0xffa70028, // 0x18: sd a3,40(sp)
0xffa80030, // 0x1c: sd a4,48(sp)
0xffa90038, // 0x20: sd a5,56(sp)
0xffaa0040, // 0x24: sd a6,64(sp)
0xffab0048, // 0x28: sd a7,72(sp)
0xffac0050, // 0x2c: sd t0,80(sp)
0xffad0058, // 0x30: sd t1,88(sp)
0xffae0060, // 0x34: sd t2,96(sp)
0xffaf0068, // 0x38: sd t3,104(sp)
0xffb00070, // 0x3c: sd s0,112(sp)
0xffb10078, // 0x40: sd s1,120(sp)
0xffb20080, // 0x44: sd s2,128(sp)
0xffb30088, // 0x48: sd s3,136(sp)
0xffb40090, // 0x4c: sd s4,144(sp)
0xffb50098, // 0x50: sd s5,152(sp)
0xffb600a0, // 0x54: sd s6,160(sp)
0xffb700a8, // 0x58: sd s7,168(sp)
0xffb800b0, // 0x5c: sd t8,176(sp)
0xffb900b8, // 0x60: sd t9,184(sp)
0xffbe00c0, // 0x64: sd s8,192(sp)
0xffbf00c8, // 0x68: sd ra,200(sp)
// Callback manager addr.
0x00000000, // 0x6c: lui $a0,heighest(callbackmgr)
0x00000000, // 0x70: daddiu $a0,$a0,heigher(callbackmgr)
0x00000000, // 0x74: dsll $a0,$a0,16
0x00000000, // 0x78: daddiu $a0,$a0,hi(callbackmgr)
0x00000000, // 0x7c: dsll $a0,$a0,16
0x00000000, // 0x80: daddiu $a0,$a0,lo(callbackmgr)
0x03e02825, // 0x84: move $a1, $ra
0x64a5ffdc, // 0x88: daddiu $a1,$a1,-36
// JIT re-entry fn addr:
0x00000000, // 0x8c: lui $t9,reentry
0x00000000, // 0x90: daddiu $t9,$t9,reentry
0x00000000, // 0x94: dsll $t9,$t9,
0x00000000, // 0x98: daddiu $t9,$t9,
0x00000000, // 0x9c: dsll $t9,$t9,
0x00000000, // 0xa0: daddiu $t9,$t9,
0x0320f809, // 0xa4: jalr $t9
0x00000000, // 0xa8: nop
0xdfbf00c8, // 0xac: ld ra, 200(sp)
0xdfbe00c0, // 0xb0: ld s8, 192(sp)
0xdfb900b8, // 0xb4: ld t9, 184(sp)
0xdfb800b0, // 0xb8: ld t8, 176(sp)
0xdfb700a8, // 0xbc: ld s7, 168(sp)
0xdfb600a0, // 0xc0: ld s6, 160(sp)
0xdfb50098, // 0xc4: ld s5, 152(sp)
0xdfb40090, // 0xc8: ld s4, 144(sp)
0xdfb30088, // 0xcc: ld s3, 136(sp)
0xdfb20080, // 0xd0: ld s2, 128(sp)
0xdfb10078, // 0xd4: ld s1, 120(sp)
0xdfb00070, // 0xd8: ld s0, 112(sp)
0xdfaf0068, // 0xdc: ld t3, 104(sp)
0xdfae0060, // 0xe0: ld t2, 96(sp)
0xdfad0058, // 0xe4: ld t1, 88(sp)
0xdfac0050, // 0xe8: ld t0, 80(sp)
0xdfab0048, // 0xec: ld a7, 72(sp)
0xdfaa0040, // 0xf0: ld a6, 64(sp)
0xdfa90038, // 0xf4: ld a5, 56(sp)
0xdfa80030, // 0xf8: ld a4, 48(sp)
0xdfa70028, // 0xfc: ld a3, 40(sp)
0xdfa60020, // 0x100: ld a2, 32(sp)
0xdfa50018, // 0x104: ld a1, 24(sp)
0xdfa40010, // 0x108: ld a0, 16(sp)
0xdfa30008, // 0x10c: ld v1, 8(sp)
0x67bd00d0, // 0x110: daddiu $sp,$sp,208
0x0300f825, // 0x114: move $ra, $t8
0x00400008 // 0x118: jr $v0
};
const unsigned ReentryFnAddrOffset = 0x8c; // JIT re-entry fn addr lui
const unsigned CallbackMgrAddrOffset = 0x6c; // Callback manager addr lui
memcpy(ResolverMem, ResolverCode, sizeof(ResolverCode));
uint64_t CallMgrAddr = reinterpret_cast<uint64_t>(CallbackMgr);
uint32_t CallMgrLUi =
0x3c040000 | (((CallMgrAddr + 0x800080008000) >> 48) & 0xFFFF);
uint32_t CallMgrDADDiu =
0x64840000 | (((CallMgrAddr + 0x80008000) >> 32) & 0xFFFF);
uint32_t CallMgrDSLL = 0x00042438;
uint32_t CallMgrDADDiu2 =
0x64840000 | ((((CallMgrAddr + 0x8000) >> 16) & 0xFFFF));
uint32_t CallMgrDSLL2 = 0x00042438;
uint32_t CallMgrDADDiu3 = 0x64840000 | ((CallMgrAddr) & 0xFFFF);
memcpy(ResolverMem + CallbackMgrAddrOffset, &CallMgrLUi,
sizeof(CallMgrLUi));
memcpy(ResolverMem + (CallbackMgrAddrOffset + 4), &CallMgrDADDiu,
sizeof(CallMgrDADDiu));
memcpy(ResolverMem + (CallbackMgrAddrOffset + 8), &CallMgrDSLL,
sizeof(CallMgrDSLL));
memcpy(ResolverMem + (CallbackMgrAddrOffset + 12), &CallMgrDADDiu2,
sizeof(CallMgrDADDiu2));
memcpy(ResolverMem + (CallbackMgrAddrOffset + 16), &CallMgrDSLL2,
sizeof(CallMgrDSLL2));
memcpy(ResolverMem + (CallbackMgrAddrOffset + 20), &CallMgrDADDiu3,
sizeof(CallMgrDADDiu3));
uint64_t ReentryAddr = reinterpret_cast<uint64_t>(ReentryFn);
uint32_t ReentryLUi =
0x3c190000 | (((ReentryAddr + 0x800080008000) >> 48) & 0xFFFF);
uint32_t ReentryDADDiu =
0x67390000 | (((ReentryAddr + 0x80008000) >> 32) & 0xFFFF);
uint32_t ReentryDSLL = 0x0019cc38;
uint32_t ReentryDADDiu2 =
0x67390000 | (((ReentryAddr + 0x8000) >> 16) & 0xFFFF);
uint32_t ReentryDSLL2 = 0x0019cc38;
uint32_t ReentryDADDiu3 = 0x67390000 | ((ReentryAddr) & 0xFFFF);
memcpy(ResolverMem + ReentryFnAddrOffset, &ReentryLUi,
sizeof(ReentryLUi));
memcpy(ResolverMem + (ReentryFnAddrOffset + 4), &ReentryDADDiu,
sizeof(ReentryDADDiu));
memcpy(ResolverMem + (ReentryFnAddrOffset + 8), &ReentryDSLL,
sizeof(ReentryDSLL));
memcpy(ResolverMem + (ReentryFnAddrOffset + 12), &ReentryDADDiu2,
sizeof(ReentryDADDiu2));
memcpy(ResolverMem + (ReentryFnAddrOffset + 16), &ReentryDSLL2,
sizeof(ReentryDSLL2));
memcpy(ResolverMem + (ReentryFnAddrOffset + 20), &ReentryDADDiu3,
sizeof(ReentryDADDiu3));
}
void OrcMips64::writeTrampolines(uint8_t *TrampolineMem, void *ResolverAddr,
unsigned NumTrampolines) {
uint32_t *Trampolines = reinterpret_cast<uint32_t *>(TrampolineMem);
uint64_t ResolveAddr = reinterpret_cast<uint64_t>(ResolverAddr);
uint64_t HeighestAddr = ((ResolveAddr + 0x800080008000) >> 48);
uint64_t HeigherAddr = ((ResolveAddr + 0x80008000) >> 32);
uint64_t HiAddr = ((ResolveAddr + 0x8000) >> 16);
for (unsigned I = 0; I < NumTrampolines; ++I) {
Trampolines[10 * I + 0] = 0x03e0c025; // move $t8,$ra
Trampolines[10 * I + 1] = 0x3c190000 | (HeighestAddr & 0xFFFF); // lui $t9,resolveAddr
Trampolines[10 * I + 2] = 0x67390000 | (HeigherAddr & 0xFFFF); // daddiu $t9,$t9,%higher(resolveAddr)
Trampolines[10 * I + 3] = 0x0019cc38; // dsll $t9,$t9,16
Trampolines[10 * I + 4] = 0x67390000 | (HiAddr & 0xFFFF); // daddiu $t9,$t9,%hi(ptr)
Trampolines[10 * I + 5] = 0x0019cc38; // dsll $t9,$t9,16
Trampolines[10 * I + 6] = 0x67390000 | (ResolveAddr & 0xFFFF); // daddiu $t9,$t9,%lo(ptr)
Trampolines[10 * I + 7] = 0x0320f809; // jalr $t9
Trampolines[10 * I + 8] = 0x00000000; // nop
Trampolines[10 * I + 9] = 0x00000000; // nop
}
}
Error OrcMips64::emitIndirectStubsBlock(IndirectStubsInfo &StubsInfo,
unsigned MinStubs,
void *InitialPtrVal) {
// Stub format is:
//
// .section __orc_stubs
// stub1:
// lui $t9,ptr1
// dsll $t9,$t9,16
// daddiu $t9,$t9,%hi(ptr)
// dsll $t9,$t9,16
// ld $t9,%lo(ptr)
// jr $t9
// stub2:
// lui $t9,ptr1
// dsll $t9,$t9,16
// daddiu $t9,$t9,%hi(ptr)
// dsll $t9,$t9,16
// ld $t9,%lo(ptr)
// jr $t9
//
// ...
//
// .section __orc_ptrs
// ptr1:
// .dword 0x0
// ptr2:
// .dword 0x0
//
// ...
const unsigned StubSize = IndirectStubsInfo::StubSize;
// Emit at least MinStubs, rounded up to fill the pages allocated.
unsigned PageSize = sys::Process::getPageSize();
unsigned NumPages = ((MinStubs * StubSize) + (PageSize - 1)) / PageSize;
unsigned NumStubs = (NumPages * PageSize) / StubSize;
// Allocate memory for stubs and pointers in one call.
std::error_code EC;
auto StubsMem = sys::OwningMemoryBlock(sys::Memory::allocateMappedMemory(
2 * NumPages * PageSize, nullptr,
sys::Memory::MF_READ | sys::Memory::MF_WRITE, EC));
if (EC)
return errorCodeToError(EC);
// Create separate MemoryBlocks representing the stubs and pointers.
sys::MemoryBlock StubsBlock(StubsMem.base(), NumPages * PageSize);
sys::MemoryBlock PtrsBlock(static_cast<char *>(StubsMem.base()) +
NumPages * PageSize,
NumPages * PageSize);
// Populate the stubs page stubs and mark it executable.
uint32_t *Stub = reinterpret_cast<uint32_t *>(StubsBlock.base());
uint64_t PtrAddr = reinterpret_cast<uint64_t>(PtrsBlock.base());
for (unsigned I = 0; I < NumStubs; ++I, PtrAddr += 8) {
uint64_t HeighestAddr = ((PtrAddr + 0x800080008000) >> 48);
uint64_t HeigherAddr = ((PtrAddr + 0x80008000) >> 32);
uint64_t HiAddr = ((PtrAddr + 0x8000) >> 16);
Stub[8 * I + 0] = 0x3c190000 | (HeighestAddr & 0xFFFF); // lui $t9,ptr1
Stub[8 * I + 1] = 0x67390000 | (HeigherAddr & 0xFFFF); // daddiu $t9,$t9,%higher(ptr)
Stub[8 * I + 2] = 0x0019cc38; // dsll $t9,$t9,16
Stub[8 * I + 3] = 0x67390000 | (HiAddr & 0xFFFF); // daddiu $t9,$t9,%hi(ptr)
Stub[8 * I + 4] = 0x0019cc38; // dsll $t9,$t9,16
Stub[8 * I + 5] = 0xdf390000 | (PtrAddr & 0xFFFF); // ld $t9,%lo(ptr)
Stub[8 * I + 6] = 0x03200008; // jr $t9
Stub[8 * I + 7] = 0x00000000; // nop
}
if (auto EC = sys::Memory::protectMappedMemory(
StubsBlock, sys::Memory::MF_READ | sys::Memory::MF_EXEC))
return errorCodeToError(EC);
// Initialize all pointers to point at FailureAddress.
void **Ptr = reinterpret_cast<void **>(PtrsBlock.base());
for (unsigned I = 0; I < NumStubs; ++I)
Ptr[I] = InitialPtrVal;
StubsInfo = IndirectStubsInfo(NumStubs, std::move(StubsMem));
return Error::success();
}
} // End namespace orc.
} // End namespace llvm.

View File

@ -275,14 +275,14 @@ public:
{
unsigned CtorId = 0, DtorId = 0;
for (auto Ctor : orc::getConstructors(*M)) {
std::string NewCtorName = ("$static_ctor." + Twine(CtorId++)).str();
std::string NewCtorName = ("__ORCstatic_ctor." + Twine(CtorId++)).str();
Ctor.Func->setName(NewCtorName);
Ctor.Func->setLinkage(GlobalValue::ExternalLinkage);
Ctor.Func->setVisibility(GlobalValue::HiddenVisibility);
CtorNames.push_back(mangle(NewCtorName));
}
for (auto Dtor : orc::getDestructors(*M)) {
std::string NewDtorName = ("$static_dtor." + Twine(DtorId++)).str();
std::string NewDtorName = ("__ORCstatic_dtor." + Twine(DtorId++)).str();
dbgs() << "Found dtor: " << NewDtorName << "\n";
Dtor.Func->setName(NewDtorName);
Dtor.Func->setLinkage(GlobalValue::ExternalLinkage);

View File

@ -1,6 +1,6 @@
import sys
if config.root.host_arch not in ['i386', 'x86', 'x86_64', 'AMD64']:
if config.root.host_arch not in ['i386', 'x86', 'x86_64', 'AMD64', 'mips', 'mipsel', 'mips64', 'mips64el']:
config.unsupported = True
# FIXME: These tests don't pass with the COFF rtld.