diff --git a/include/llvm/CodeGen/MachineModuleInfo.h b/include/llvm/CodeGen/MachineModuleInfo.h index 1f9decf574c..778b75c899b 100644 --- a/include/llvm/CodeGen/MachineModuleInfo.h +++ b/include/llvm/CodeGen/MachineModuleInfo.h @@ -1030,6 +1030,9 @@ private: // Personalities - Vector of all personality functions ever seen. Used to emit // common EH frames. std::vector Personalities; + + bool CallsEHReturn; + bool CallsUnwindInit; public: static char ID; // Pass identification, replacement for typeid @@ -1072,6 +1075,12 @@ public: /// needsFrameInfo - Returns true if we need to gather callee-saved register /// move info for the frame. bool needsFrameInfo() const; + + bool callsEHReturn() const { return CallsEHReturn; } + void setCallsEHReturn(bool b) { CallsEHReturn = b; } + + bool callsUnwindInit() const { return CallsUnwindInit; } + void setCallsUnwindInit(bool b) { CallsUnwindInit = b; } /// NextLabelID - Return the next unique label id. /// diff --git a/include/llvm/CodeGen/SelectionDAGNodes.h b/include/llvm/CodeGen/SelectionDAGNodes.h index 316b02af39e..c96d516eca1 100644 --- a/include/llvm/CodeGen/SelectionDAGNodes.h +++ b/include/llvm/CodeGen/SelectionDAGNodes.h @@ -110,6 +110,11 @@ namespace ISD { // to the current function's frame or return address, an index of one to the // parent's frame or return address, and so on. FRAMEADDR, RETURNADDR, + + // FRAME_TO_ARGS_OFFSET - This node represents offset from frame pointer to + // first (possible) on-stack argument. This is needed for correct stack + // adjustment during unwind. + FRAME_TO_ARGS_OFFSET, // RESULT, OUTCHAIN = EXCEPTIONADDR(INCHAIN) - This node represents the // address of the exception block on entry to an landing pad block. @@ -119,6 +124,12 @@ namespace ISD { // the selection index of the exception thrown. EHSELECTION, + // OUTCHAIN = EH_RETURN(INCHAIN, OFFSET, HANDLER) - This node represents + // 'eh_return' gcc dwarf builtin, which is used to return from + // exception. The general meaning is: adjust stack by OFFSET and pass + // execution to HANDLER. Many platform-related details also :) + EH_RETURN, + // TargetConstant* - Like Constant*, but the DAG does not do any folding or // simplification of the constant. TargetConstant, diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index df3afde9ed2..e5bb2f62134 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -233,6 +233,14 @@ def int_eh_selector : Intrinsic<[llvm_i32_ty, llvm_ptr_ty, llvm_ptr_ty, llvm_vararg_ty]>; def int_eh_typeid_for : Intrinsic<[llvm_i32_ty, llvm_ptr_ty]>; +def int_eh_return : Intrinsic<[llvm_void_ty, llvm_i32_ty, llvm_ptr_ty]>, + GCCBuiltin<"__builtin_eh_return">; + +def int_eh_unwind_init: Intrinsic<[llvm_void_ty]>, + GCCBuiltin<"__builtin_unwind_init">; + +def int_eh_dwarf_cfa : Intrinsic<[llvm_ptr_ty, llvm_i32_ty]>; + //===---------------- Generic Variable Attribute Intrinsics----------------===// // def int_var_annotation : Intrinsic<[llvm_void_ty, llvm_ptr_ty, llvm_ptr_ty, diff --git a/include/llvm/Target/MRegisterInfo.h b/include/llvm/Target/MRegisterInfo.h index ecfe1ec38a3..d2b76b8d853 100644 --- a/include/llvm/Target/MRegisterInfo.h +++ b/include/llvm/Target/MRegisterInfo.h @@ -396,12 +396,14 @@ public: /// callee saved registers on this target. The register should be in the /// order of desired callee-save stack frame offset. The first register is /// closed to the incoming stack pointer if stack grows down, and vice versa. - virtual const unsigned* getCalleeSavedRegs() const = 0; + virtual const unsigned* getCalleeSavedRegs(const MachineFunction *MF = 0) + const = 0; /// getCalleeSavedRegClasses - Return a null-terminated list of the preferred /// register classes to spill each callee saved register with. The order and /// length of this list match the getCalleeSaveRegs() list. - virtual const TargetRegisterClass* const *getCalleeSavedRegClasses() const =0; + virtual const TargetRegisterClass* const *getCalleeSavedRegClasses( + const MachineFunction *MF) const =0; /// getReservedRegs - Returns a bitset indexed by physical register number /// indicating if a register is a special register that has particular uses and diff --git a/lib/CodeGen/MachineModuleInfo.cpp b/lib/CodeGen/MachineModuleInfo.cpp index 88d85074250..77fb643b650 100644 --- a/lib/CodeGen/MachineModuleInfo.cpp +++ b/lib/CodeGen/MachineModuleInfo.cpp @@ -1476,6 +1476,8 @@ MachineModuleInfo::MachineModuleInfo() , FrameMoves() , LandingPads() , Personalities() +, CallsEHReturn(0) +, CallsUnwindInit(0) { // Always emit "no personality" info Personalities.push_back(NULL); @@ -1523,6 +1525,8 @@ void MachineModuleInfo::EndFunction() { TypeInfos.clear(); FilterIds.clear(); FilterEnds.clear(); + CallsEHReturn = 0; + CallsUnwindInit = 0; } /// getDescFor - Convert a Value to a debug information descriptor. diff --git a/lib/CodeGen/PrologEpilogInserter.cpp b/lib/CodeGen/PrologEpilogInserter.cpp index 0658ad23c8d..882c6a74404 100644 --- a/lib/CodeGen/PrologEpilogInserter.cpp +++ b/lib/CodeGen/PrologEpilogInserter.cpp @@ -121,7 +121,7 @@ void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) { const TargetFrameInfo *TFI = Fn.getTarget().getFrameInfo(); // Get the callee saved register list... - const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(); + const unsigned *CSRegs = RegInfo->getCalleeSavedRegs(&Fn); // Get the function call frame set-up and tear-down instruction opcode int FrameSetupOpcode = RegInfo->getCallFrameSetupOpcode(); @@ -170,7 +170,7 @@ void PEI::calculateCalleeSavedRegisters(MachineFunction &Fn) { // function, thus needing to be saved and restored in the prolog/epilog. // const TargetRegisterClass* const *CSRegClasses = - RegInfo->getCalleeSavedRegClasses(); + RegInfo->getCalleeSavedRegClasses(&Fn); std::vector CSI; for (unsigned i = 0; CSRegs[i]; ++i) { unsigned Reg = CSRegs[i]; diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index a5146bd4529..8b82b62b652 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -640,6 +640,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { break; case ISD::FRAMEADDR: case ISD::RETURNADDR: + case ISD::FRAME_TO_ARGS_OFFSET: // The only option for these nodes is to custom lower them. If the target // does not custom lower them, then return zero. Tmp1 = TLI.LowerOperation(Op, DAG); @@ -695,6 +696,21 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { } } break; + case ISD::EH_RETURN: + MVT::ValueType VT = Node->getValueType(0); + // The only "good" option for this node is to custom lower it. + switch (TLI.getOperationAction(Node->getOpcode(), VT)) { + default: assert(0 && "This action is not supported at all!"); + case TargetLowering::Custom: + Result = TLI.LowerOperation(Op, DAG); + if (Result.Val) break; + // Fall Thru + case TargetLowering::Legal: + // Target does not know, how to lower this, lower to noop + Result = LegalizeOp(Node->getOperand(0)); + break; + } + break; case ISD::AssertSext: case ISD::AssertZext: Tmp1 = LegalizeOp(Node->getOperand(0)); diff --git a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp index dc23151bddd..9803ab87e25 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAG.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAG.cpp @@ -3369,8 +3369,10 @@ std::string SDNode::getOperationName(const SelectionDAG *G) const { case ISD::GLOBAL_OFFSET_TABLE: return "GLOBAL_OFFSET_TABLE"; case ISD::RETURNADDR: return "RETURNADDR"; case ISD::FRAMEADDR: return "FRAMEADDR"; + case ISD::FRAME_TO_ARGS_OFFSET: return "FRAME_TO_ARGS_OFFSET"; case ISD::EXCEPTIONADDR: return "EXCEPTIONADDR"; case ISD::EHSELECTION: return "EHSELECTION"; + case ISD::EH_RETURN: return "EH_RETURN"; case ISD::ConstantPool: return "ConstantPool"; case ISD::ExternalSymbol: return "ExternalSymbol"; case ISD::INTRINSIC_WO_CHAIN: { diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp index 87bf2497640..8a2f7b1f5fa 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGISel.cpp @@ -2721,6 +2721,53 @@ SelectionDAGLowering::visitIntrinsicCall(CallInst &I, unsigned Intrinsic) { return 0; } + case Intrinsic::eh_return: { + MachineModuleInfo *MMI = DAG.getMachineModuleInfo(); + + if (MMI && ExceptionHandling) { + MMI->setCallsEHReturn(true); + DAG.setRoot(DAG.getNode(ISD::EH_RETURN, + MVT::Other, + getRoot(), + getValue(I.getOperand(1)), + getValue(I.getOperand(2)))); + } else { + setValue(&I, DAG.getConstant(0, TLI.getPointerTy())); + } + + return 0; + } + + case Intrinsic::eh_unwind_init: { + if (MachineModuleInfo *MMI = DAG.getMachineModuleInfo()) { + MMI->setCallsUnwindInit(true); + } + + return 0; + } + + case Intrinsic::eh_dwarf_cfa: { + if (ExceptionHandling) { + MVT::ValueType VT = getValue(I.getOperand(1)).getValueType(); + SDOperand Offset = DAG.getNode(ISD::ADD, + TLI.getPointerTy(), + DAG.getNode(ISD::FRAME_TO_ARGS_OFFSET, + VT), + getValue(I.getOperand(1))); + setValue(&I, DAG.getNode(ISD::ADD, + TLI.getPointerTy(), + DAG.getNode(ISD::FRAMEADDR, + TLI.getPointerTy(), + DAG.getConstant(0, + TLI.getPointerTy())), + Offset)); + } else { + setValue(&I, DAG.getConstant(0, TLI.getPointerTy())); + } + + return 0; + } + case Intrinsic::sqrt_f32: case Intrinsic::sqrt_f64: setValue(&I, DAG.getNode(ISD::FSQRT, diff --git a/lib/Target/ARM/ARMRegisterInfo.cpp b/lib/Target/ARM/ARMRegisterInfo.cpp index 05458e59f37..f8e10deeb15 100644 --- a/lib/Target/ARM/ARMRegisterInfo.cpp +++ b/lib/Target/ARM/ARMRegisterInfo.cpp @@ -327,7 +327,8 @@ MachineInstr *ARMRegisterInfo::foldMemoryOperand(MachineInstr *MI, return NewMI; } -const unsigned* ARMRegisterInfo::getCalleeSavedRegs() const { +const unsigned* ARMRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) + const { static const unsigned CalleeSavedRegs[] = { ARM::LR, ARM::R11, ARM::R10, ARM::R9, ARM::R8, ARM::R7, ARM::R6, ARM::R5, ARM::R4, @@ -349,7 +350,7 @@ const unsigned* ARMRegisterInfo::getCalleeSavedRegs() const { } const TargetRegisterClass* const * -ARMRegisterInfo::getCalleeSavedRegClasses() const { +ARMRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { static const TargetRegisterClass * const CalleeSavedRegClasses[] = { &ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass, &ARM::GPRRegClass, diff --git a/lib/Target/ARM/ARMRegisterInfo.h b/lib/Target/ARM/ARMRegisterInfo.h index 261cc8837bc..3db1d89403e 100644 --- a/lib/Target/ARM/ARMRegisterInfo.h +++ b/lib/Target/ARM/ARMRegisterInfo.h @@ -66,9 +66,10 @@ public: MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FrameIndex) const; - const unsigned *getCalleeSavedRegs() const; + const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const; - const TargetRegisterClass* const* getCalleeSavedRegClasses() const; + const TargetRegisterClass* const* getCalleeSavedRegClasses( + const MachineFunction *MF = 0) const; BitVector getReservedRegs(const MachineFunction &MF) const; diff --git a/lib/Target/Alpha/AlphaRegisterInfo.cpp b/lib/Target/Alpha/AlphaRegisterInfo.cpp index 72a84072c27..59d3e817d9b 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.cpp +++ b/lib/Target/Alpha/AlphaRegisterInfo.cpp @@ -164,7 +164,8 @@ void AlphaRegisterInfo::reMaterialize(MachineBasicBlock &MBB, MBB.insert(I, MI); } -const unsigned* AlphaRegisterInfo::getCalleeSavedRegs() const { +const unsigned* AlphaRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) + const { static const unsigned CalleeSavedRegs[] = { Alpha::R9, Alpha::R10, Alpha::R11, Alpha::R12, @@ -178,7 +179,7 @@ const unsigned* AlphaRegisterInfo::getCalleeSavedRegs() const { } const TargetRegisterClass* const* -AlphaRegisterInfo::getCalleeSavedRegClasses() const { +AlphaRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { static const TargetRegisterClass * const CalleeSavedRegClasses[] = { &Alpha::GPRCRegClass, &Alpha::GPRCRegClass, &Alpha::GPRCRegClass, &Alpha::GPRCRegClass, diff --git a/lib/Target/Alpha/AlphaRegisterInfo.h b/lib/Target/Alpha/AlphaRegisterInfo.h index 07fea9eebea..2872e595bb0 100644 --- a/lib/Target/Alpha/AlphaRegisterInfo.h +++ b/lib/Target/Alpha/AlphaRegisterInfo.h @@ -48,9 +48,10 @@ struct AlphaRegisterInfo : public AlphaGenRegisterInfo { void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, const MachineInstr *Orig) const; - const unsigned *getCalleeSavedRegs() const; + const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const; - const TargetRegisterClass* const* getCalleeSavedRegClasses() const; + const TargetRegisterClass* const* getCalleeSavedRegClasses( + const MachineFunction *MF = 0) const; BitVector getReservedRegs(const MachineFunction &MF) const; diff --git a/lib/Target/IA64/IA64RegisterInfo.cpp b/lib/Target/IA64/IA64RegisterInfo.cpp index 41a15fdc5e8..08327f2efb2 100644 --- a/lib/Target/IA64/IA64RegisterInfo.cpp +++ b/lib/Target/IA64/IA64RegisterInfo.cpp @@ -102,7 +102,8 @@ void IA64RegisterInfo::reMaterialize(MachineBasicBlock &MBB, MBB.insert(I, MI); } -const unsigned* IA64RegisterInfo::getCalleeSavedRegs() const { +const unsigned* IA64RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) + const { static const unsigned CalleeSavedRegs[] = { IA64::r5, 0 }; @@ -110,7 +111,7 @@ const unsigned* IA64RegisterInfo::getCalleeSavedRegs() const { } const TargetRegisterClass* const* -IA64RegisterInfo::getCalleeSavedRegClasses() const { +IA64RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { static const TargetRegisterClass * const CalleeSavedRegClasses[] = { &IA64::GRRegClass, 0 }; diff --git a/lib/Target/IA64/IA64RegisterInfo.h b/lib/Target/IA64/IA64RegisterInfo.h index d90f3211eb8..162ad5ae425 100644 --- a/lib/Target/IA64/IA64RegisterInfo.h +++ b/lib/Target/IA64/IA64RegisterInfo.h @@ -47,9 +47,10 @@ struct IA64RegisterInfo : public IA64GenRegisterInfo { void reMaterialize(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, unsigned DestReg, const MachineInstr *Orig) const; - const unsigned *getCalleeSavedRegs() const; + const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const; - const TargetRegisterClass* const* getCalleeSavedRegClasses() const; + const TargetRegisterClass* const* getCalleeSavedRegClasses( + const MachineFunction *MF = 0) const; BitVector getReservedRegs(const MachineFunction &MF) const; diff --git a/lib/Target/PowerPC/PPCRegisterInfo.cpp b/lib/Target/PowerPC/PPCRegisterInfo.cpp index a788a75da5e..19780a8bf49 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.cpp +++ b/lib/Target/PowerPC/PPCRegisterInfo.cpp @@ -248,7 +248,8 @@ void PPCRegisterInfo::reMaterialize(MachineBasicBlock &MBB, MBB.insert(I, MI); } -const unsigned* PPCRegisterInfo::getCalleeSavedRegs() const { +const unsigned* PPCRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) + const { // 32-bit Darwin calling convention. static const unsigned Macho32_CalleeSavedRegs[] = { PPC::R13, PPC::R14, PPC::R15, @@ -324,7 +325,7 @@ const unsigned* PPCRegisterInfo::getCalleeSavedRegs() const { } const TargetRegisterClass* const* -PPCRegisterInfo::getCalleeSavedRegClasses() const { +PPCRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { // 32-bit Macho calling convention. static const TargetRegisterClass * const Macho32_CalleeSavedRegClasses[] = { &PPC::GPRCRegClass,&PPC::GPRCRegClass,&PPC::GPRCRegClass, diff --git a/lib/Target/PowerPC/PPCRegisterInfo.h b/lib/Target/PowerPC/PPCRegisterInfo.h index 0caf1065d03..4112034aac8 100644 --- a/lib/Target/PowerPC/PPCRegisterInfo.h +++ b/lib/Target/PowerPC/PPCRegisterInfo.h @@ -57,9 +57,10 @@ public: virtual MachineInstr* foldMemoryOperand(MachineInstr* MI, unsigned OpNum, int FrameIndex) const; - const unsigned *getCalleeSavedRegs() const; + const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const; - const TargetRegisterClass* const* getCalleeSavedRegClasses() const; + const TargetRegisterClass* const* getCalleeSavedRegClasses( + const MachineFunction *MF = 0) const; BitVector getReservedRegs(const MachineFunction &MF) const; diff --git a/lib/Target/Sparc/SparcRegisterInfo.cpp b/lib/Target/Sparc/SparcRegisterInfo.cpp index ded1bcd836a..1981b4fe30b 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.cpp +++ b/lib/Target/Sparc/SparcRegisterInfo.cpp @@ -121,7 +121,8 @@ MachineInstr *SparcRegisterInfo::foldMemoryOperand(MachineInstr* MI, return NewMI; } -const unsigned* SparcRegisterInfo::getCalleeSavedRegs() const { +const unsigned* SparcRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) + const { static const unsigned CalleeSavedRegs[] = { 0 }; return CalleeSavedRegs; } @@ -143,7 +144,7 @@ BitVector SparcRegisterInfo::getReservedRegs(const MachineFunction &MF) const { const TargetRegisterClass* const* -SparcRegisterInfo::getCalleeSavedRegClasses() const { +SparcRegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { static const TargetRegisterClass * const CalleeSavedRegClasses[] = { 0 }; return CalleeSavedRegClasses; } diff --git a/lib/Target/Sparc/SparcRegisterInfo.h b/lib/Target/Sparc/SparcRegisterInfo.h index b7ea4d6f4c9..451964b2f75 100644 --- a/lib/Target/Sparc/SparcRegisterInfo.h +++ b/lib/Target/Sparc/SparcRegisterInfo.h @@ -51,9 +51,10 @@ struct SparcRegisterInfo : public SparcGenRegisterInfo { unsigned OpNum, int FrameIndex) const; - const unsigned *getCalleeSavedRegs() const; + const unsigned *getCalleeSavedRegs(const MachineFunction *MF = 0) const; - const TargetRegisterClass* const* getCalleeSavedRegClasses() const; + const TargetRegisterClass* const* getCalleeSavedRegClasses( + const MachineFunction *MF = 0) const; BitVector getReservedRegs(const MachineFunction &MF) const; diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 3bf2b9f6c5d..37dea796cd6 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -42,6 +42,8 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) X86ScalarSSE = Subtarget->hasSSE2(); X86StackPtr = Subtarget->is64Bit() ? X86::RSP : X86::ESP; + RegInfo = TM.getRegisterInfo(); + // Set up the TargetLowering object. // X86 is weird, it always uses i8 for shift amounts and setcc results. @@ -197,6 +199,9 @@ X86TargetLowering::X86TargetLowering(TargetMachine &TM) } // X86 ret instruction may pop stack. setOperationAction(ISD::RET , MVT::Other, Custom); + if (!Subtarget->is64Bit()) + setOperationAction(ISD::EH_RETURN , MVT::Other, Custom); + // Darwin ABI issue. setOperationAction(ISD::ConstantPool , MVT::i32 , Custom); setOperationAction(ISD::JumpTable , MVT::i32 , Custom); @@ -4226,6 +4231,39 @@ SDOperand X86TargetLowering::LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG) { DAG.getConstant(4, getPointerTy())); } +SDOperand X86TargetLowering::LowerFRAME_TO_ARGS_OFFSET(SDOperand Op, + SelectionDAG &DAG) { + // Is not yet supported on x86-64 + if (Subtarget->is64Bit()) + return SDOperand(); + + return DAG.getConstant(8, getPointerTy()); +} + +SDOperand X86TargetLowering::LowerEH_RETURN(SDOperand Op, SelectionDAG &DAG) +{ + assert(!Subtarget->is64Bit() && + "Lowering of eh_return builtin is not supported yet on x86-64"); + + MachineFunction &MF = DAG.getMachineFunction(); + SDOperand Chain = Op.getOperand(0); + SDOperand Offset = Op.getOperand(1); + SDOperand Handler = Op.getOperand(2); + + SDOperand Frame = DAG.getRegister(RegInfo->getFrameRegister(MF), + getPointerTy()); + + SDOperand StoreAddr = DAG.getNode(ISD::SUB, getPointerTy(), Frame, + DAG.getConstant(-4UL, getPointerTy())); + StoreAddr = DAG.getNode(ISD::ADD, getPointerTy(), StoreAddr, Offset); + Chain = DAG.getStore(Chain, Handler, StoreAddr, NULL, 0); + Chain = DAG.getCopyToReg(Chain, X86::ECX, StoreAddr); + MF.addLiveOut(X86::ECX); + + return DAG.getNode(X86ISD::EH_RETURN, MVT::Other, + Chain, DAG.getRegister(X86::ECX, getPointerTy())); +} + /// LowerOperation - Provide custom lowering hooks for some operations. /// SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { @@ -4263,7 +4301,10 @@ SDOperand X86TargetLowering::LowerOperation(SDOperand Op, SelectionDAG &DAG) { case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG); case ISD::RETURNADDR: return LowerRETURNADDR(Op, DAG); case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG); + case ISD::FRAME_TO_ARGS_OFFSET: + return LowerFRAME_TO_ARGS_OFFSET(Op, DAG); case ISD::DYNAMIC_STACKALLOC: return LowerDYNAMIC_STACKALLOC(Op, DAG); + case ISD::EH_RETURN: return LowerEH_RETURN(Op, DAG); } return SDOperand(); } @@ -4311,6 +4352,7 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::FRCP: return "X86ISD::FRCP"; case X86ISD::TLSADDR: return "X86ISD::TLSADDR"; case X86ISD::THREAD_POINTER: return "X86ISD::THREAD_POINTER"; + case X86ISD::EH_RETURN: return "X86ISD::EH_RETURN"; } } diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index b9aaefa5c87..07a96d35691 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -16,6 +16,7 @@ #define X86ISELLOWERING_H #include "X86Subtarget.h" +#include "X86RegisterInfo.h" #include "llvm/Target/TargetLowering.h" #include "llvm/CodeGen/SelectionDAG.h" @@ -184,7 +185,10 @@ namespace llvm { FRSQRT, FRCP, // Thread Local Storage - TLSADDR, THREAD_POINTER + TLSADDR, THREAD_POINTER, + + // Exception Handling helpers + EH_RETURN }; } @@ -370,6 +374,7 @@ namespace llvm { /// Subtarget - Keep a pointer to the X86Subtarget around so that we can /// make the right decision when generating code for different targets. const X86Subtarget *Subtarget; + const MRegisterInfo *RegInfo; /// X86StackPtr - X86 physical register used as stack ptr. unsigned X86StackPtr; @@ -424,6 +429,8 @@ namespace llvm { SDOperand LowerINTRINSIC_WO_CHAIN(SDOperand Op, SelectionDAG &DAG); SDOperand LowerRETURNADDR(SDOperand Op, SelectionDAG &DAG); SDOperand LowerFRAMEADDR(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerFRAME_TO_ARGS_OFFSET(SDOperand Op, SelectionDAG &DAG); + SDOperand LowerEH_RETURN(SDOperand Op, SelectionDAG &DAG); }; } diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index f8eac7e7049..b24f6442074 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -51,6 +51,8 @@ def SDT_X86TLSADDR : SDTypeProfile<1, 1, [SDTCisPtrTy<0>, SDTCisInt<1>]>; def SDT_X86TLSTP : SDTypeProfile<1, 0, [SDTCisPtrTy<0>]>; +def SDT_X86EHRET : SDTypeProfile<0, 1, [SDTCisInt<0>]>; + def X86shld : SDNode<"X86ISD::SHLD", SDTIntShiftDOp>; def X86shrd : SDNode<"X86ISD::SHRD", SDTIntShiftDOp>; @@ -95,6 +97,9 @@ def X86tlsaddr : SDNode<"X86ISD::TLSADDR", SDT_X86TLSADDR, [SDNPHasChain, SDNPInFlag, SDNPOutFlag]>; def X86TLStp : SDNode<"X86ISD::THREAD_POINTER", SDT_X86TLSTP, []>; +def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET, + [SDNPHasChain]>; + //===----------------------------------------------------------------------===// // X86 Operand Definitions. @@ -2491,6 +2496,17 @@ def DWARF_LOC : I<0, Pseudo, (ops i32imm:$line, i32imm:$col, i32imm:$file), [(dwarf_loc (i32 imm:$line), (i32 imm:$col), (i32 imm:$file))]>; +//===----------------------------------------------------------------------===// +// EH Pseudo Instructions +// +let isTerminator = 1, isReturn = 1, isBarrier = 1, + hasCtrlDep = 1, noResults = 1 in { +def EH_RETURN : I<0xC3, RawFrm, (ops GR32:$addr), + "ret #eh_return, addr: $addr", + [(X86ehret GR32:$addr)]>; + +} + //===----------------------------------------------------------------------===// // Non-Instruction Patterns //===----------------------------------------------------------------------===// diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 3ea437fe1e8..9dc3dd12a02 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -903,30 +903,62 @@ MachineInstr* X86RegisterInfo::foldMemoryOperand(MachineInstr *MI, } -const unsigned *X86RegisterInfo::getCalleeSavedRegs() const { +const unsigned *X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) + const { static const unsigned CalleeSavedRegs32Bit[] = { X86::ESI, X86::EDI, X86::EBX, X86::EBP, 0 }; + + static const unsigned CalleeSavedRegs32EHRet[] = { + X86::EAX, X86::EDX, X86::ESI, X86::EDI, X86::EBX, X86::EBP, 0 + }; + static const unsigned CalleeSavedRegs64Bit[] = { X86::RBX, X86::R12, X86::R13, X86::R14, X86::R15, X86::RBP, 0 }; - return Is64Bit ? CalleeSavedRegs64Bit : CalleeSavedRegs32Bit; + if (Is64Bit) + return CalleeSavedRegs64Bit; + else { + if (MF) { + MachineFrameInfo *MFI = MF->getFrameInfo(); + MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + if (MMI && MMI->callsEHReturn()) + return CalleeSavedRegs32EHRet; + } + return CalleeSavedRegs32Bit; + } } const TargetRegisterClass* const* -X86RegisterInfo::getCalleeSavedRegClasses() const { +X86RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { static const TargetRegisterClass * const CalleeSavedRegClasses32Bit[] = { &X86::GR32RegClass, &X86::GR32RegClass, &X86::GR32RegClass, &X86::GR32RegClass, 0 }; + static const TargetRegisterClass * const CalleeSavedRegClasses32EHRet[] = { + &X86::GR32RegClass, &X86::GR32RegClass, + &X86::GR32RegClass, &X86::GR32RegClass, + &X86::GR32RegClass, &X86::GR32RegClass, 0 + }; static const TargetRegisterClass * const CalleeSavedRegClasses64Bit[] = { &X86::GR64RegClass, &X86::GR64RegClass, &X86::GR64RegClass, &X86::GR64RegClass, &X86::GR64RegClass, &X86::GR64RegClass, 0 }; - return Is64Bit ? CalleeSavedRegClasses64Bit : CalleeSavedRegClasses32Bit; + if (Is64Bit) + return CalleeSavedRegClasses64Bit; + else { + if (MF) { + MachineFrameInfo *MFI = MF->getFrameInfo(); + MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + if (MMI && MMI->callsEHReturn()) + return CalleeSavedRegClasses32EHRet; + } + return CalleeSavedRegClasses32Bit; + } + } BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { @@ -953,9 +985,13 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { // if frame pointer elimination is disabled. // bool X86RegisterInfo::hasFP(const MachineFunction &MF) const { + MachineFrameInfo *MFI = MF.getFrameInfo(); + MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + return (NoFramePointerElim || MF.getFrameInfo()->hasVarSizedObjects() || - MF.getInfo()->getForceFramePointer()); + MF.getInfo()->getForceFramePointer() || + (MMI && MMI->callsUnwindInit())); } void X86RegisterInfo:: @@ -1243,10 +1279,12 @@ void X86RegisterInfo::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { const MachineFrameInfo *MFI = MF.getFrameInfo(); MachineBasicBlock::iterator MBBI = prior(MBB.end()); + unsigned RetOpcode = MBBI->getOpcode(); - switch (MBBI->getOpcode()) { + switch (RetOpcode) { case X86::RET: case X86::RETI: + case X86::EH_RETURN: case X86::TAILJMPd: case X86::TAILJMPr: case X86::TAILJMPm: break; // These are ok @@ -1288,6 +1326,14 @@ void X86RegisterInfo::emitEpilogue(MachineFunction &MF, emitSPUpdate(MBB, MBBI, StackPtr, NumBytes, Is64Bit, TII); } } + + // We're returning from function via eh_return. + if (RetOpcode == X86::EH_RETURN) { + MachineOperand &DestAddr = MBBI->getOperand(0); + assert(DestAddr.isReg() && "Offset should be in register!"); + BuildMI(MBB, MBBI, TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr),StackPtr). + addReg(DestAddr.getReg()); + } } unsigned X86RegisterInfo::getRARegister() const { diff --git a/lib/Target/X86/X86RegisterInfo.h b/lib/Target/X86/X86RegisterInfo.h index cf83f99963d..7f18b562f47 100644 --- a/lib/Target/X86/X86RegisterInfo.h +++ b/lib/Target/X86/X86RegisterInfo.h @@ -74,12 +74,13 @@ public: /// getCalleeSavedRegs - Return a null-terminated list of all of the /// callee-save registers on this target. - const unsigned *getCalleeSavedRegs() const; + const unsigned *getCalleeSavedRegs(const MachineFunction* MF = 0) const; /// getCalleeSavedRegClasses - Return a null-terminated list of the preferred /// register classes to spill each callee-saved register with. The order and /// length of this list match the getCalleeSavedRegs() list. - const TargetRegisterClass* const* getCalleeSavedRegClasses() const; + const TargetRegisterClass* const* getCalleeSavedRegClasses( + const MachineFunction *MF = 0) const; /// getReservedRegs - Returns a bitset indexed by physical register number /// indicating if a register is a special register that has particular uses and diff --git a/lib/Target/X86/X86TargetAsmInfo.cpp b/lib/Target/X86/X86TargetAsmInfo.cpp index dbf202cb3b5..4bb854efe95 100644 --- a/lib/Target/X86/X86TargetAsmInfo.cpp +++ b/lib/Target/X86/X86TargetAsmInfo.cpp @@ -124,8 +124,9 @@ X86TargetAsmInfo::X86TargetAsmInfo(const X86TargetMachine &TM) { DwarfARangesSection = "\t.section\t.debug_aranges,\"\",@progbits"; DwarfRangesSection = "\t.section\t.debug_ranges,\"\",@progbits"; DwarfMacInfoSection = "\t.section\t.debug_macinfo,\"\",@progbits"; - - SupportsExceptionHandling = true; + + if (!Subtarget->is64Bit()) + SupportsExceptionHandling = true; DwarfEHFrameSection = "\t.section\t.eh_frame,\"aw\",@progbits"; DwarfExceptionSection = "\t.section\t.gcc_except_table,\"a\",@progbits"; break;