#include "PPCJITInfo.h"
#include "PPCRelocations.h"
#include "PPCTargetMachine.h"
-#include "llvm/CodeGen/MachineCodeEmitter.h"
-#include "llvm/Config/alloca.h"
+#include "llvm/Function.h"
+#include "llvm/System/Memory.h"
#include "llvm/Support/Debug.h"
-#include <set>
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
using namespace llvm;
static TargetJITInfo::JITCompilerFn JITCompilerFunction;
extern "C" void PPC64CompilationCallback();
#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
- !defined(__ppc64__)
+ !(defined(__ppc64__) || defined(__FreeBSD__))
// CompilationCallback stub - We can't use a C function with inline assembly in
// it, because we the prolog/epilog inserted by GCC won't work for us. Instead,
// write our own wrapper, which does things our way, so we have complete control
);
#elif defined(__PPC__) && !defined(__ppc64__)
-// Linux/PPC support
+// Linux & FreeBSD / PPC 32 support
// CompilationCallback stub - We can't use a C function with inline assembly in
// it, because we the prolog/epilog inserted by GCC won't work for us. Instead,
);
#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
);
#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
return is64Bit ? PPC64CompilationCallback : PPC32CompilationCallback;
}
-void *PPCJITInfo::emitFunctionStub(void *Fn, MachineCodeEmitter &MCE) {
+#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
+defined(__APPLE__)
+extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
+#endif
+
+void *PPCJITInfo::emitFunctionStub(const Function* F, void *Fn,
+ 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(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);
+ JCE.startGVStub(F, 7*4);
+ intptr_t Addr = (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(Addr, (intptr_t)Fn, false, is64Bit);
- return MCE.finishFunctionStub(0);
+ sys::Memory::InvalidateInstructionCache((void*)Addr, 7*4);
+ return JCE.finishGVStub(F);
}
- MCE.startFunctionStub(10*4);
+ JCE.startGVStub(F, 10*4);
+ intptr_t Addr = (intptr_t)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 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, true, is64Bit);
- return MCE.finishFunctionStub(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);
+ sys::Memory::InvalidateInstructionCache((void*)Addr, 10*4);
+ return JCE.finishGVStub(F);
}
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;