blob: a5f0cadcf7c8dc3563f62f823306d5b9ef29e9d1 [file] [log] [blame]
Index: PPCInstrInfo.td
===================================================================
--- PPCInstrInfo.td (revision 50006)
+++ PPCInstrInfo.td (working copy)
@@ -1212,6 +1212,8 @@
(BL_ELF texternalsym:$dst)>;
// Hi and Lo for Darwin Global Addresses.
+def : Pat<(PPChi texternalsym:$in, 0), (LIS texternalsym:$in)>;
+def : Pat<(PPClo texternalsym:$in, 0), (LI texternalsym:$in)>;
def : Pat<(PPChi tglobaladdr:$in, 0), (LIS tglobaladdr:$in)>;
def : Pat<(PPClo tglobaladdr:$in, 0), (LI tglobaladdr:$in)>;
def : Pat<(PPChi tconstpool:$in, 0), (LIS tconstpool:$in)>;
Index: PPCJITInfo.cpp
===================================================================
--- PPCJITInfo.cpp (revision 50006)
+++ PPCJITInfo.cpp (working copy)
@@ -13,12 +13,16 @@
#define DEBUG_TYPE "jit"
#include "PPCJITInfo.h"
+#include "PPCRegisterInfo.h"
#include "PPCRelocations.h"
#include "PPCTargetMachine.h"
#include "llvm/Function.h"
#include "llvm/CodeGen/MachineCodeEmitter.h"
#include "llvm/Config/alloca.h"
+#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/Support/Debug.h"
+#include "llvm/Support/Dwarf.h"
+#include "llvm/Target/TargetOptions.h"
#include <set>
using namespace llvm;
@@ -53,24 +57,27 @@
if (Offset >= -(1 << 23) && Offset < (1 << 23)) { // In range?
AtI[0] = BUILD_B(Offset, isCall); // b/bl target
} else if (!is64Bit) {
- AtI[0] = BUILD_LIS(12, To >> 16); // lis r12, hi16(address)
+ AtI[0] = BUILD_B(0, false); // thread safety
AtI[1] = BUILD_ORI(12, 12, To); // ori r12, r12, lo16(address)
AtI[2] = BUILD_MTCTR(12); // mtctr r12
AtI[3] = BUILD_BCTR(isCall); // bctr/bctrl
+ AtI[0] = BUILD_LIS(12, To >> 16); // lis r12, hi16(address)
} else {
- AtI[0] = BUILD_LIS(12, To >> 48); // lis r12, hi16(address)
+ AtI[0] = BUILD_B(0, false); // thread safety
AtI[1] = BUILD_ORI(12, 12, To >> 32); // ori r12, r12, lo16(address)
AtI[2] = BUILD_SLDI(12, 12, 32); // sldi r12, r12, 32
AtI[3] = BUILD_ORIS(12, 12, To >> 16); // oris r12, r12, hi16(address)
AtI[4] = BUILD_ORI(12, 12, To); // ori r12, r12, lo16(address)
AtI[5] = BUILD_MTCTR(12); // mtctr r12
AtI[6] = BUILD_BCTR(isCall); // bctr/bctrl
+ AtI[0] = BUILD_LIS(12, To >> 48); // lis r12, hi16(address)
}
}
extern "C" void PPC32CompilationCallback();
extern "C" void PPC64CompilationCallback();
+
#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
!defined(__ppc64__)
// CompilationCallback stub - We can't use a C function with inline assembly in
@@ -144,6 +151,9 @@
// 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
// over register saving and restoring.
+
+# define CFI(x) x
+
asm(
".text\n"
".align 2\n"
@@ -156,19 +166,29 @@
// FIXME Layout
// 8 double registers - 64 bytes
// 8 int registers - 32 bytes
+ CFI(".cfi_startproc\n")
+ "stwu 1, -104(1)\n"
+ CFI(".cfi_adjust_cfa_offset 104\n")
"mflr 0\n"
- "stw 0, 4(1)\n"
- "stwu 1, -104(1)\n"
+ "stw 0, 108(1)\n"
+ CFI(".cfi_offset lr, 4\n")
// Save all int arg registers
- "stw 10, 100(1)\n" "stw 9, 96(1)\n"
- "stw 8, 92(1)\n" "stw 7, 88(1)\n"
- "stw 6, 84(1)\n" "stw 5, 80(1)\n"
- "stw 4, 76(1)\n" "stw 3, 72(1)\n"
+ "stw 10, 100(1)\n"
+ "stw 9, 96(1)\n"
+ "stw 8, 92(1)\n"
+ "stw 7, 88(1)\n"
+ "stw 6, 84(1)\n"
+ "stw 5, 80(1)\n"
+ "stw 4, 76(1)\n"
+ "stw 3, 72(1)\n"
// Save all call-clobbered FP regs.
"stfd 8, 64(1)\n"
- "stfd 7, 56(1)\n" "stfd 6, 48(1)\n"
- "stfd 5, 40(1)\n" "stfd 4, 32(1)\n"
- "stfd 3, 24(1)\n" "stfd 2, 16(1)\n"
+ "stfd 7, 56(1)\n"
+ "stfd 6, 48(1)\n"
+ "stfd 5, 40(1)\n"
+ "stfd 4, 32(1)\n"
+ "stfd 3, 24(1)\n"
+ "stfd 2, 16(1)\n"
"stfd 1, 8(1)\n"
// Arguments to Compilation Callback:
// r3 - our lr (address of the call instruction in stub plus 4)
@@ -181,21 +201,29 @@
"bl PPCCompilationCallbackC\n"
"mtctr 3\n"
// Restore all int arg registers
- "lwz 10, 100(1)\n" "lwz 9, 96(1)\n"
- "lwz 8, 92(1)\n" "lwz 7, 88(1)\n"
- "lwz 6, 84(1)\n" "lwz 5, 80(1)\n"
- "lwz 4, 76(1)\n" "lwz 3, 72(1)\n"
+ "lwz 10, 100(1)\n"
+ "lwz 9, 96(1)\n"
+ "lwz 8, 92(1)\n"
+ "lwz 7, 88(1)\n"
+ "lwz 6, 84(1)\n"
+ "lwz 5, 80(1)\n"
+ "lwz 4, 76(1)\n"
+ "lwz 3, 72(1)\n"
// Restore all FP arg registers
"lfd 8, 64(1)\n"
- "lfd 7, 56(1)\n" "lfd 6, 48(1)\n"
- "lfd 5, 40(1)\n" "lfd 4, 32(1)\n"
- "lfd 3, 24(1)\n" "lfd 2, 16(1)\n"
+ "lfd 7, 56(1)\n"
+ "lfd 6, 48(1)\n"
+ "lfd 5, 40(1)\n"
+ "lfd 4, 32(1)\n"
+ "lfd 3, 24(1)\n"
+ "lfd 2, 16(1)\n"
"lfd 1, 8(1)\n"
// Pop 3 frames off the stack and branch to target
"lwz 1, 104(1)\n"
"lwz 0, 4(1)\n"
"mtlr 0\n"
"bctr\n"
+ CFI(".cfi_endproc\n")
);
#else
void PPC32CompilationCallback() {
@@ -325,6 +353,31 @@
return is64Bit ? PPC64CompilationCallback : PPC32CompilationCallback;
}
+static const char* GetCommonFrame32() {
+ /*
+ // Size of common frame
+ MCE.emitWordBE(16);
+ // Common frame
+ MCE.emitWordBE(0);
+ MCE.emitByte(1);
+ MCE.emitByte('z');
+ MCE.emitByte('R');
+ MCE.emitByte(0);
+ MCE.emitByte(1);
+ MCE.emitByte(-4 & 0x7f);
+ MCE.emitByte(0x41);
+ MCE.emitByte(1);
+ MCE.emitByte(16);
+ MCE.emitByte(0xc);
+ MCE.emitByte(1);
+ MCE.emitByte(0);*/
+ static const char CF[] = {
+ 0, 0, 0, 16, 0, 0, 0, 0, 1, 'z', 'R', 0, 1, -4 & 0x7f,
+ 0x41, 1, 16, 0xc, 1, 0
+ };
+ return CF;
+}
+
#if (defined(__POWERPC__) || defined (__ppc__) || defined(_POWER)) && \
defined(__APPLE__)
extern "C" void sys_icache_invalidate(const void *Addr, size_t len);
@@ -358,21 +411,26 @@
SyncICache((void*)Addr, 7*4);
return MCE.finishFunctionStub(F);
}
-
- MCE.startFunctionStub(F, 10*4);
+
+ if (ExceptionHandling && !is64Bit) {
+ MCE.startFunctionStub(F, 10*4 + 44);
+ } else {
+ MCE.startFunctionStub(F, 10*4);
+ }
+
intptr_t Addr = (intptr_t)MCE.getCurrentPCValue();
if (is64Bit) {
+ MCE.emitWordBE(0x7d6802a6); // mflr r11
+ MCE.emitWordBE(0xf9610010); // std r11, 16(r1)
MCE.emitWordBE(0xf821ffb1); // stdu r1,-80(r1)
+ } else if (TM.getSubtargetImpl()->isMachoABI()){
MCE.emitWordBE(0x7d6802a6); // mflr r11
- MCE.emitWordBE(0xf9610060); // std r11, 96(r1)
- } else if (TM.getSubtargetImpl()->isMachoABI()){
+ MCE.emitWordBE(0x91610008); // stw r11, 8(r1)
MCE.emitWordBE(0x9421ffe0); // stwu r1,-32(r1)
+ } else {
MCE.emitWordBE(0x7d6802a6); // mflr r11
- MCE.emitWordBE(0x91610028); // stw r11, 40(r1)
- } else {
+ MCE.emitWordBE(0x91610004); // stw r11, 4(r1)
MCE.emitWordBE(0x9421ffe0); // stwu r1,-32(r1)
- MCE.emitWordBE(0x7d6802a6); // mflr r11
- MCE.emitWordBE(0x91610024); // stw r11, 36(r1)
}
intptr_t BranchAddr = (intptr_t)MCE.getCurrentPCValue();
MCE.emitWordBE(0);
@@ -384,6 +442,42 @@
MCE.emitWordBE(0);
EmitBranchToAt(BranchAddr, (intptr_t)Fn, true, is64Bit);
SyncICache((void*)Addr, 10*4);
+ intptr_t EndAddr = (intptr_t)MCE.getCurrentPCValue();
+
+ if (ExceptionHandling && !is64Bit) {
+ // Size of Eh section
+ MCE.emitWordBE(32);
+ // Eh section
+ MCE.emitWordBE(MCE.getCurrentPCValue() - (intptr_t)GetCommonFrame32());
+ MCE.emitWordBE(Addr - MCE.getCurrentPCValue());
+ MCE.emitWordBE(EndAddr - Addr);
+ MCE.emitByte(0);
+ MCE.emitByte(dwarf::DW_CFA_advance_loc4);
+ MCE.emitWordBE(8);
+ MCE.emitByte(dwarf::DW_CFA_def_cfa_offset);
+ MCE.emitByte(32);
+ MCE.emitByte(dwarf::DW_CFA_offset_extended_sf);
+ MCE.emitByte(TM.getRegisterInfo()->getDwarfRegNum(PPC::LR, true));
+ if (TM.getSubtargetImpl()->isMachoABI()){
+ MCE.emitByte(-2 & 0x7f);
+ } else {
+ MCE.emitByte(-1 & 0x7f);
+ }
+ MCE.emitByte(dwarf::DW_CFA_advance_loc4);
+ MCE.emitWordBE(4);
+ MCE.emitByte(dwarf::DW_CFA_def_cfa_register);
+ MCE.emitByte(1);
+ // Alignment
+ MCE.emitByte(0);
+ MCE.emitByte(0);
+
+ // Two zero for the unwind runtime
+ MCE.emitWordBE(0);
+ MCE.emitWordBE(0);
+
+ SyncICache((void*)EndAddr, 44);
+ ExecutionEngine::RegisterTable((void*)EndAddr);
+ }
return MCE.finishFunctionStub(F);
}
Index: PPCISelLowering.cpp
===================================================================
--- PPCISelLowering.cpp (revision 50006)
+++ PPCISelLowering.cpp (working copy)
@@ -175,10 +175,12 @@
// We want to legalize GlobalAddress and ConstantPool nodes into the
// appropriate instructions to materialize the address.
setOperationAction(ISD::GlobalAddress, MVT::i32, Custom);
+ setOperationAction(ISD::ExternalSymbol , MVT::i32 , Custom);
setOperationAction(ISD::GlobalTLSAddress, MVT::i32, Custom);
setOperationAction(ISD::ConstantPool, MVT::i32, Custom);
setOperationAction(ISD::JumpTable, MVT::i32, Custom);
setOperationAction(ISD::GlobalAddress, MVT::i64, Custom);
+ setOperationAction(ISD::ExternalSymbol , MVT::i64 , Custom);
setOperationAction(ISD::GlobalTLSAddress, MVT::i64, Custom);
setOperationAction(ISD::ConstantPool, MVT::i64, Custom);
setOperationAction(ISD::JumpTable, MVT::i64, Custom);
@@ -745,6 +747,36 @@
return isIntS16Immediate(Op.Val, Imm);
}
+ static SDOperand LowerExternalSymbol(SDOperand Op, SelectionDAG &DAG) {
+ MVT::ValueType PtrVT = Op.getValueType();
+ ExternalSymbolSDNode *GSDB = dyn_cast<ExternalSymbolSDNode>(Op);
+ SDOperand GA = DAG.getTargetExternalSymbol(GSDB->getSymbol(), PtrVT);
+ SDOperand Zero = DAG.getConstant(0, PtrVT);
+
+ const TargetMachine &TM = DAG.getTarget();
+
+ SDOperand Hi = DAG.getNode(PPCISD::Hi, PtrVT, GA, Zero);
+ SDOperand Lo = DAG.getNode(PPCISD::Lo, PtrVT, GA, Zero);
+
+ // If this is a non-darwin platform, we don't support non-static relo models
+ // yet.
+ if (TM.getRelocationModel() == Reloc::Static ||
+ !TM.getSubtarget<PPCSubtarget>().isDarwin()) {
+ // Generate non-pic code that has direct accesses to globals.
+ // The address of the global is just (hi(&g)+lo(&g)).
+ return DAG.getNode(ISD::ADD, PtrVT, Hi, Lo);
+ }
+
+ if (TM.getRelocationModel() == Reloc::PIC_) {
+ // With PIC, the first instruction is actually "GR+hi(&G)".
+ Hi = DAG.getNode(ISD::ADD, PtrVT,
+ DAG.getNode(PPCISD::GlobalBaseReg, PtrVT), Hi);
+ }
+
+ Lo = DAG.getNode(ISD::ADD, PtrVT, Hi, Lo);
+
+ return Lo;
+ }
/// SelectAddressRegReg - Given the specified addressed, check to see if it
/// can be represented as an indexed [r+r] operation. Returns false if it
@@ -2130,11 +2162,11 @@
// If the callee is a GlobalAddress/ExternalSymbol node (quite common, every
// direct call is) turn it into a TargetGlobalAddress/TargetExternalSymbol
// node so that legalize doesn't hack it.
- if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
- Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
- else if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
- Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType());
- else if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG))
+ //if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee))
+ // Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType());
+ //if (ExternalSymbolSDNode *S = dyn_cast<ExternalSymbolSDNode>(Callee))
+ // Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType());
+ if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG))
// If this is an absolute destination address, use the munged value.
Callee = SDOperand(Dest, 0);
else {
@@ -3506,6 +3538,7 @@
default: assert(0 && "Wasn't expecting to be able to lower this!");
case ISD::ConstantPool: return LowerConstantPool(Op, DAG);
case ISD::GlobalAddress: return LowerGlobalAddress(Op, DAG);
+ case ISD::ExternalSymbol: return LowerExternalSymbol(Op, DAG);
case ISD::GlobalTLSAddress: return LowerGlobalTLSAddress(Op, DAG);
case ISD::JumpTable: return LowerJumpTable(Op, DAG);
case ISD::SETCC: return LowerSETCC(Op, DAG);