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 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(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().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(Callee)) - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType()); - else if (ExternalSymbolSDNode *S = dyn_cast(Callee)) - Callee = DAG.getTargetExternalSymbol(S->getSymbol(), Callee.getValueType()); - else if (SDNode *Dest = isBLACompatibleAddress(Callee, DAG)) + //if (GlobalAddressSDNode *G = dyn_cast(Callee)) + // Callee = DAG.getTargetGlobalAddress(G->getGlobal(), Callee.getValueType()); + //if (ExternalSymbolSDNode *S = dyn_cast(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);