#include "PPCJITInfo.h"
#include "PPCRelocations.h"
#include "PPCTargetMachine.h"
-#include "llvm/Function.h"
-#include "llvm/CodeGen/MachineCodeEmitter.h"
-#include "llvm/Config/alloca.h"
+#include "llvm/IR/Function.h"
#include "llvm/Support/Debug.h"
-#include <set>
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/Memory.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
static TargetJITInfo::JITCompilerFn JITCompilerFunction;
// FIXME: could shrink frame
// Set up a proper stack frame
// FIXME Layout
- // PowerPC64 ABI linkage - 24 bytes
+ // PowerPC32 ABI linkage - 24 bytes
// parameters - 32 bytes
// 13 double registers - 104 bytes
// 8 int registers - 32 bytes
"lwz r2, 208(r1)\n" // stub's frame
"lwz r4, 8(r2)\n" // stub's lr
"li r5, 0\n" // 0 == 32 bit
- "bl _PPCCompilationCallbackC\n"
+ "bl _LLVMPPCCompilationCallback\n"
"mtctr r3\n"
// Restore all int arg registers
"lwz r10, 204(r1)\n" "lwz r9, 200(r1)\n"
"lwz 5, 104(1)\n" // stub's frame
"lwz 4, 4(5)\n" // stub's lr
"li 5, 0\n" // 0 == 32 bit
- "bl PPCCompilationCallbackC\n"
+ "bl LLVMPPCCompilationCallback\n"
"mtctr 3\n"
// Restore all int arg registers
"lwz 10, 100(1)\n" "lwz 9, 96(1)\n"
);
#else
void PPC32CompilationCallback() {
- assert(0 && "This is not a power pc, you can't execute this!");
- abort();
+ llvm_unreachable("This is not a power pc, you can't execute this!");
}
#endif
#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
defined(__ppc64__)
+#ifdef __ELF__
+asm(
+ ".text\n"
+ ".align 2\n"
+ ".globl PPC64CompilationCallback\n"
+ ".section \".opd\",\"aw\",@progbits\n"
+ ".align 3\n"
+"PPC64CompilationCallback:\n"
+ ".quad .L.PPC64CompilationCallback,.TOC.@tocbase,0\n"
+ ".size PPC64CompilationCallback,24\n"
+ ".previous\n"
+ ".align 4\n"
+ ".type PPC64CompilationCallback,@function\n"
+".L.PPC64CompilationCallback:\n"
+#else
asm(
".text\n"
".align 2\n"
".globl _PPC64CompilationCallback\n"
"_PPC64CompilationCallback:\n"
+#endif
// Make space for 8 ints r[3-10] and 13 doubles f[1-13] and the
// FIXME: need to save v[0-19] for altivec?
// Set up a proper stack frame
// parameters - 64 bytes
// 13 double registers - 104 bytes
// 8 int registers - 64 bytes
- "mflr r0\n"
- "std r0, 16(r1)\n"
- "stdu r1, -280(r1)\n"
+ "mflr 0\n"
+ "std 0, 16(1)\n"
+ "stdu 1, -280(1)\n"
// Save all int arg registers
- "std r10, 272(r1)\n" "std r9, 264(r1)\n"
- "std r8, 256(r1)\n" "std r7, 248(r1)\n"
- "std r6, 240(r1)\n" "std r5, 232(r1)\n"
- "std r4, 224(r1)\n" "std r3, 216(r1)\n"
+ "std 10, 272(1)\n" "std 9, 264(1)\n"
+ "std 8, 256(1)\n" "std 7, 248(1)\n"
+ "std 6, 240(1)\n" "std 5, 232(1)\n"
+ "std 4, 224(1)\n" "std 3, 216(1)\n"
// Save all call-clobbered FP regs.
- "stfd f13, 208(r1)\n" "stfd f12, 200(r1)\n"
- "stfd f11, 192(r1)\n" "stfd f10, 184(r1)\n"
- "stfd f9, 176(r1)\n" "stfd f8, 168(r1)\n"
- "stfd f7, 160(r1)\n" "stfd f6, 152(r1)\n"
- "stfd f5, 144(r1)\n" "stfd f4, 136(r1)\n"
- "stfd f3, 128(r1)\n" "stfd f2, 120(r1)\n"
- "stfd f1, 112(r1)\n"
+ "stfd 13, 208(1)\n" "stfd 12, 200(1)\n"
+ "stfd 11, 192(1)\n" "stfd 10, 184(1)\n"
+ "stfd 9, 176(1)\n" "stfd 8, 168(1)\n"
+ "stfd 7, 160(1)\n" "stfd 6, 152(1)\n"
+ "stfd 5, 144(1)\n" "stfd 4, 136(1)\n"
+ "stfd 3, 128(1)\n" "stfd 2, 120(1)\n"
+ "stfd 1, 112(1)\n"
// Arguments to Compilation Callback:
// r3 - our lr (address of the call instruction in stub plus 4)
// r4 - stub's lr (address of instruction that called the stub plus 4)
// r5 - is64Bit - always 1.
- "mr r3, r0\n"
- "ld r2, 280(r1)\n" // stub's frame
- "ld r4, 16(r2)\n" // stub's lr
- "li r5, 1\n" // 1 == 64 bit
- "bl _PPCCompilationCallbackC\n"
- "mtctr r3\n"
+ "mr 3, 0\n" // return address (still in r0)
+ "ld 5, 280(1)\n" // stub's frame
+ "ld 4, 16(5)\n" // stub's lr
+ "li 5, 1\n" // 1 == 64 bit
+#ifdef __ELF__
+ "bl LLVMPPCCompilationCallback\n"
+ "nop\n"
+#else
+ "bl _LLVMPPCCompilationCallback\n"
+#endif
+ "mtctr 3\n"
// Restore all int arg registers
- "ld r10, 272(r1)\n" "ld r9, 264(r1)\n"
- "ld r8, 256(r1)\n" "ld r7, 248(r1)\n"
- "ld r6, 240(r1)\n" "ld r5, 232(r1)\n"
- "ld r4, 224(r1)\n" "ld r3, 216(r1)\n"
+ "ld 10, 272(1)\n" "ld 9, 264(1)\n"
+ "ld 8, 256(1)\n" "ld 7, 248(1)\n"
+ "ld 6, 240(1)\n" "ld 5, 232(1)\n"
+ "ld 4, 224(1)\n" "ld 3, 216(1)\n"
// Restore all FP arg registers
- "lfd f13, 208(r1)\n" "lfd f12, 200(r1)\n"
- "lfd f11, 192(r1)\n" "lfd f10, 184(r1)\n"
- "lfd f9, 176(r1)\n" "lfd f8, 168(r1)\n"
- "lfd f7, 160(r1)\n" "lfd f6, 152(r1)\n"
- "lfd f5, 144(r1)\n" "lfd f4, 136(r1)\n"
- "lfd f3, 128(r1)\n" "lfd f2, 120(r1)\n"
- "lfd f1, 112(r1)\n"
+ "lfd 13, 208(1)\n" "lfd 12, 200(1)\n"
+ "lfd 11, 192(1)\n" "lfd 10, 184(1)\n"
+ "lfd 9, 176(1)\n" "lfd 8, 168(1)\n"
+ "lfd 7, 160(1)\n" "lfd 6, 152(1)\n"
+ "lfd 5, 144(1)\n" "lfd 4, 136(1)\n"
+ "lfd 3, 128(1)\n" "lfd 2, 120(1)\n"
+ "lfd 1, 112(1)\n"
// Pop 3 frames off the stack and branch to target
- "ld r1, 280(r1)\n"
- "ld r2, 16(r1)\n"
- "mtlr r2\n"
+ "ld 1, 280(1)\n"
+ "ld 0, 16(1)\n"
+ "mtlr 0\n"
+ // XXX: any special TOC handling in the ELF case for JIT?
"bctr\n"
);
#else
void PPC64CompilationCallback() {
- assert(0 && "This is not a power pc, you can't execute this!");
- abort();
+ llvm_unreachable("This is not a power pc, you can't execute this!");
}
#endif
-extern "C" void *PPCCompilationCallbackC(unsigned *StubCallAddrPlus4,
- unsigned *OrigCallAddrPlus4,
- bool is64Bit) {
+extern "C" {
+LLVM_LIBRARY_VISIBILITY void *
+LLVMPPCCompilationCallback(unsigned *StubCallAddrPlus4,
+ unsigned *OrigCallAddrPlus4,
+ bool is64Bit) {
// Adjust the pointer to the address of the call instruction in the stub
// emitted by emitFunctionStub, rather than the instruction after it.
unsigned *StubCallAddr = StubCallAddrPlus4 - 1;
// Rewrite the stub with an unconditional branch to the target, for any users
// who took the address of the stub.
EmitBranchToAt((intptr_t)StubCallAddr, (intptr_t)Target, false, is64Bit);
+ sys::Memory::InvalidateInstructionCache(StubCallAddr, 7*4);
// Put the address of the target function to call and the address to return to
// after calling the target function in a place that is easy to get on the
// stack after we restore all regs.
return Target;
}
+}
return is64Bit ? PPC64CompilationCallback : PPC32CompilationCallback;
}
-#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
-defined(__APPLE__)
-extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
-#endif
+TargetJITInfo::StubLayout PPCJITInfo::getStubLayout() {
+ // The stub contains up to 10 4-byte instructions, aligned at 4 bytes: 3
+ // instructions to save the caller's address if this is a lazy-compilation
+ // stub, plus a 1-, 4-, or 7-instruction sequence to load an arbitrary address
+ // into a register and jump through it.
+ StubLayout Result = {10*4, 4};
+ return Result;
+}
-/// SyncICache - On PPC, the JIT emitted code must be explicitly refetched to
-/// ensure correct execution.
-static void SyncICache(const void *Addr, size_t len) {
#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
defined(__APPLE__)
- sys_icache_invalidate(Addr, len);
+extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
#endif
-}
void *PPCJITInfo::emitFunctionStub(const Function* F, void *Fn,
- MachineCodeEmitter &MCE) {
+ JITCodeEmitter &JCE) {
// If this is just a call to an external function, emit a branch instead of a
// call. The code is the same except for one bit of the last instruction.
if (Fn != (void*)(intptr_t)PPC32CompilationCallback &&
Fn != (void*)(intptr_t)PPC64CompilationCallback) {
- MCE.startFunctionStub(F, 7*4);
- intptr_t Addr = (intptr_t)MCE.getCurrentPCValue();
- MCE.emitWordBE(0);
- MCE.emitWordBE(0);
- MCE.emitWordBE(0);
- MCE.emitWordBE(0);
- MCE.emitWordBE(0);
- MCE.emitWordBE(0);
- MCE.emitWordBE(0);
- EmitBranchToAt(Addr, (intptr_t)Fn, false, is64Bit);
- SyncICache((void*)Addr, 7*4);
- return MCE.finishFunctionStub(F);
+ void *Addr = (void*)JCE.getCurrentPCValue();
+ JCE.emitWordBE(0);
+ JCE.emitWordBE(0);
+ JCE.emitWordBE(0);
+ JCE.emitWordBE(0);
+ JCE.emitWordBE(0);
+ JCE.emitWordBE(0);
+ JCE.emitWordBE(0);
+ EmitBranchToAt((intptr_t)Addr, (intptr_t)Fn, false, is64Bit);
+ sys::Memory::InvalidateInstructionCache(Addr, 7*4);
+ return Addr;
}
- MCE.startFunctionStub(F, 10*4);
- intptr_t Addr = (intptr_t)MCE.getCurrentPCValue();
+ void *Addr = (void*)JCE.getCurrentPCValue();
if (is64Bit) {
- MCE.emitWordBE(0xf821ffb1); // stdu r1,-80(r1)
- MCE.emitWordBE(0x7d6802a6); // mflr r11
- MCE.emitWordBE(0xf9610060); // std r11, 96(r1)
- } else if (TM.getSubtargetImpl()->isMachoABI()){
- MCE.emitWordBE(0x9421ffe0); // stwu r1,-32(r1)
- MCE.emitWordBE(0x7d6802a6); // mflr r11
- MCE.emitWordBE(0x91610028); // stw r11, 40(r1)
+ JCE.emitWordBE(0xf821ffb1); // stdu r1,-80(r1)
+ JCE.emitWordBE(0x7d6802a6); // mflr r11
+ JCE.emitWordBE(0xf9610060); // std r11, 96(r1)
+ } else if (TM.getSubtargetImpl()->isDarwinABI()){
+ JCE.emitWordBE(0x9421ffe0); // stwu r1,-32(r1)
+ JCE.emitWordBE(0x7d6802a6); // mflr r11
+ JCE.emitWordBE(0x91610028); // stw r11, 40(r1)
} else {
- MCE.emitWordBE(0x9421ffe0); // stwu r1,-32(r1)
- MCE.emitWordBE(0x7d6802a6); // mflr r11
- MCE.emitWordBE(0x91610024); // stw r11, 36(r1)
+ JCE.emitWordBE(0x9421ffe0); // stwu r1,-32(r1)
+ JCE.emitWordBE(0x7d6802a6); // mflr r11
+ JCE.emitWordBE(0x91610024); // stw r11, 36(r1)
}
- intptr_t BranchAddr = (intptr_t)MCE.getCurrentPCValue();
- MCE.emitWordBE(0);
- MCE.emitWordBE(0);
- MCE.emitWordBE(0);
- MCE.emitWordBE(0);
- MCE.emitWordBE(0);
- MCE.emitWordBE(0);
- MCE.emitWordBE(0);
+ intptr_t BranchAddr = (intptr_t)JCE.getCurrentPCValue();
+ JCE.emitWordBE(0);
+ JCE.emitWordBE(0);
+ JCE.emitWordBE(0);
+ JCE.emitWordBE(0);
+ JCE.emitWordBE(0);
+ JCE.emitWordBE(0);
+ JCE.emitWordBE(0);
EmitBranchToAt(BranchAddr, (intptr_t)Fn, true, is64Bit);
- SyncICache((void*)Addr, 10*4);
- return MCE.finishFunctionStub(F);
+ sys::Memory::InvalidateInstructionCache(Addr, 10*4);
+ return Addr;
}
unsigned *RelocPos = (unsigned*)Function + MR->getMachineCodeOffset()/4;
intptr_t ResultPtr = (intptr_t)MR->getResultPointer();
switch ((PPC::RelocationType)MR->getRelocationType()) {
- default: assert(0 && "Unknown relocation type!");
+ default: llvm_unreachable("Unknown relocation type!");
case PPC::reloc_pcrel_bx:
// PC-relative relocation for b and bl instructions.
ResultPtr = (ResultPtr-(intptr_t)RelocPos) >> 2;
void PPCJITInfo::replaceMachineCodeForFunction(void *Old, void *New) {
EmitBranchToAt((intptr_t)Old, (intptr_t)New, false, is64Bit);
+ sys::Memory::InvalidateInstructionCache(Old, 7*4);
}