From 8528e4dc997f892b0132d227d64f43d60f7abd52 Mon Sep 17 00:00:00 2001 From: Anton Korobeynikov Date: Mon, 8 Sep 2008 14:21:53 +0000 Subject: [PATCH] First draft of EH support on x86/64-linux llvm-svn: 55899 --- include/llvm/Intrinsics.td | 4 +-- lib/Target/X86/X86ISelLowering.cpp | 23 ++++++------ lib/Target/X86/X86Instr64bit.td | 11 ++++++ lib/Target/X86/X86RegisterInfo.cpp | 58 +++++++++++++++++++----------- 4 files changed, 62 insertions(+), 34 deletions(-) diff --git a/include/llvm/Intrinsics.td b/include/llvm/Intrinsics.td index 5dd1d6116df..36d8337aabc 100644 --- a/include/llvm/Intrinsics.td +++ b/include/llvm/Intrinsics.td @@ -255,8 +255,8 @@ def int_eh_selector_i64 : Intrinsic<[llvm_i64_ty, llvm_ptr_ty, llvm_ptr_ty, def int_eh_typeid_for_i32 : Intrinsic<[llvm_i32_ty, llvm_ptr_ty]>; def int_eh_typeid_for_i64 : Intrinsic<[llvm_i64_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_return_i32 : Intrinsic<[llvm_void_ty, llvm_i32_ty, llvm_ptr_ty]>; +def int_eh_return_i64 : Intrinsic<[llvm_void_ty, llvm_i64_ty, llvm_ptr_ty]>; def int_eh_unwind_init: Intrinsic<[llvm_void_ty]>, GCCBuiltin<"__builtin_unwind_init">; diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 93ffb410151..0fd7e68c5d7 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -316,7 +316,6 @@ X86TargetLowering::X86TargetLowering(X86TargetMachine &TM) setOperationAction(ISD::EXCEPTIONADDR, MVT::i32, Expand); setOperationAction(ISD::EHSELECTION, MVT::i32, Expand); if (Subtarget->is64Bit()) { - // FIXME: Verify setExceptionPointerRegister(X86::RAX); setExceptionSelectorRegister(X86::RDX); } else { @@ -5596,7 +5595,7 @@ SDValue X86TargetLowering::LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) { SDValue RetAddrFI = getReturnAddressFrameIndex(DAG); return DAG.getNode(ISD::SUB, getPointerTy(), RetAddrFI, - DAG.getIntPtrConstant(!Subtarget->is64Bit() ? 4 : 8)); + DAG.getIntPtrConstant(Subtarget->is64Bit() ? 8 : 4)); } SDValue X86TargetLowering::LowerFRAME_TO_ARGS_OFFSET(SDValue Op, @@ -5606,26 +5605,26 @@ SDValue X86TargetLowering::LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) { - assert(!Subtarget->is64Bit() && - "Lowering of eh_return builtin is not supported yet on x86-64"); - MachineFunction &MF = DAG.getMachineFunction(); SDValue Chain = Op.getOperand(0); SDValue Offset = Op.getOperand(1); SDValue Handler = Op.getOperand(2); - SDValue Frame = DAG.getRegister(RegInfo->getFrameRegister(MF), - getPointerTy()); + SDValue Frame = DAG.getRegister(Subtarget->is64Bit() ? X86::RBP : X86::EBP, + getPointerTy()); + unsigned StoreAddrReg = (Subtarget->is64Bit() ? X86::RCX : X86::ECX); SDValue StoreAddr = DAG.getNode(ISD::SUB, getPointerTy(), Frame, - DAG.getIntPtrConstant(-4UL)); + DAG.getIntPtrConstant(Subtarget->is64Bit() ? + -8UL: -4UL)); StoreAddr = DAG.getNode(ISD::ADD, getPointerTy(), StoreAddr, Offset); Chain = DAG.getStore(Chain, Handler, StoreAddr, NULL, 0); - Chain = DAG.getCopyToReg(Chain, X86::ECX, StoreAddr); - MF.getRegInfo().addLiveOut(X86::ECX); + Chain = DAG.getCopyToReg(Chain, StoreAddrReg, StoreAddr); + MF.getRegInfo().addLiveOut(StoreAddrReg); - return DAG.getNode(X86ISD::EH_RETURN, MVT::Other, - Chain, DAG.getRegister(X86::ECX, getPointerTy())); + return DAG.getNode(X86ISD::EH_RETURN, + MVT::Other, + Chain, DAG.getRegister(StoreAddrReg, getPointerTy())); } SDValue X86TargetLowering::LowerTRAMPOLINE(SDValue Op, diff --git a/lib/Target/X86/X86Instr64bit.td b/lib/Target/X86/X86Instr64bit.td index 1bffac9c804..29066b50447 100644 --- a/lib/Target/X86/X86Instr64bit.td +++ b/lib/Target/X86/X86Instr64bit.td @@ -129,6 +129,17 @@ let isBranch = 1, isTerminator = 1, isBarrier = 1, isIndirectBranch = 1 in { [(brind (loadi64 addr:$dst))]>; } +//===----------------------------------------------------------------------===// +// EH Pseudo Instructions +// +let isTerminator = 1, isReturn = 1, isBarrier = 1, + hasCtrlDep = 1 in { +def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr), + "ret\t#eh_return, addr: $addr", + [(X86ehret GR64:$addr)]>; + +} + //===----------------------------------------------------------------------===// // Miscellaneous Instructions... // diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index d7bf93974e6..3a8209ae7fd 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -159,6 +159,14 @@ X86RegisterInfo::getCrossCopyRegClass(const TargetRegisterClass *RC) const { const unsigned * X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { + bool callsEHReturn = false; + + if (MF) { + const MachineFrameInfo *MFI = MF->getFrameInfo(); + const MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + callsEHReturn = (MMI ? MMI->callsEHReturn() : false); + } + static const unsigned CalleeSavedRegs32Bit[] = { X86::ESI, X86::EDI, X86::EBX, X86::EBP, 0 }; @@ -171,6 +179,11 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { X86::RBX, X86::R12, X86::R13, X86::R14, X86::R15, X86::RBP, 0 }; + static const unsigned CalleeSavedRegs64EHRet[] = { + X86::RAX, X86::RDX, X86::RBX, X86::R12, + X86::R13, X86::R14, X86::R15, X86::RBP, 0 + }; + static const unsigned CalleeSavedRegsWin64[] = { X86::RBX, X86::RBP, X86::RDI, X86::RSI, X86::R12, X86::R13, X86::R14, X86::R15, 0 @@ -180,20 +193,22 @@ X86RegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const { if (IsWin64) return CalleeSavedRegsWin64; else - return CalleeSavedRegs64Bit; + return (callsEHReturn ? CalleeSavedRegs64EHRet : CalleeSavedRegs64Bit); } else { - if (MF) { - const MachineFrameInfo *MFI = MF->getFrameInfo(); - const MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); - if (MMI && MMI->callsEHReturn()) - return CalleeSavedRegs32EHRet; - } - return CalleeSavedRegs32Bit; + return (callsEHReturn ? CalleeSavedRegs32EHRet : CalleeSavedRegs32Bit); } } const TargetRegisterClass* const* X86RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { + bool callsEHReturn = false; + + if (MF) { + const MachineFrameInfo *MFI = MF->getFrameInfo(); + const MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); + callsEHReturn = (MMI ? MMI->callsEHReturn() : false); + } + static const TargetRegisterClass * const CalleeSavedRegClasses32Bit[] = { &X86::GR32RegClass, &X86::GR32RegClass, &X86::GR32RegClass, &X86::GR32RegClass, 0 @@ -208,6 +223,12 @@ X86RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { &X86::GR64RegClass, &X86::GR64RegClass, &X86::GR64RegClass, &X86::GR64RegClass, 0 }; + static const TargetRegisterClass * const CalleeSavedRegClasses64EHRet[] = { + &X86::GR64RegClass, &X86::GR64RegClass, + &X86::GR64RegClass, &X86::GR64RegClass, + &X86::GR64RegClass, &X86::GR64RegClass, + &X86::GR64RegClass, &X86::GR64RegClass, 0 + }; static const TargetRegisterClass * const CalleeSavedRegClassesWin64[] = { &X86::GR64RegClass, &X86::GR64RegClass, &X86::GR64RegClass, &X86::GR64RegClass, @@ -219,17 +240,12 @@ X86RegisterInfo::getCalleeSavedRegClasses(const MachineFunction *MF) const { if (IsWin64) return CalleeSavedRegClassesWin64; else - return CalleeSavedRegClasses64Bit; + return (callsEHReturn ? + CalleeSavedRegClasses64EHRet : CalleeSavedRegClasses64Bit); } else { - if (MF) { - const MachineFrameInfo *MFI = MF->getFrameInfo(); - const MachineModuleInfo *MMI = MFI->getMachineModuleInfo(); - if (MMI && MMI->callsEHReturn()) - return CalleeSavedRegClasses32EHRet; - } - return CalleeSavedRegClasses32Bit; + return (callsEHReturn ? + CalleeSavedRegClasses32EHRet : CalleeSavedRegClasses32Bit); } - } BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { @@ -787,6 +803,7 @@ void X86RegisterInfo::emitEpilogue(MachineFunction &MF, case X86::TCRETURNri64: case X86::TCRETURNdi64: case X86::EH_RETURN: + case X86::EH_RETURN64: case X86::TAILJMPd: case X86::TAILJMPr: case X86::TAILJMPm: break; // These are ok @@ -860,12 +877,13 @@ void X86RegisterInfo::emitEpilogue(MachineFunction &MF, } // We're returning from function via eh_return. - if (RetOpcode == X86::EH_RETURN) { + if (RetOpcode == X86::EH_RETURN || RetOpcode == X86::EH_RETURN64) { MBBI = prior(MBB.end()); MachineOperand &DestAddr = MBBI->getOperand(0); assert(DestAddr.isRegister() && "Offset should be in register!"); - BuildMI(MBB, MBBI, TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr),StackPtr). - addReg(DestAddr.getReg()); + BuildMI(MBB, MBBI, + TII.get(Is64Bit ? X86::MOV64rr : X86::MOV32rr), + StackPtr).addReg(DestAddr.getReg()); // Tail call return: adjust the stack pointer and jump to callee } else if (RetOpcode == X86::TCRETURNri || RetOpcode == X86::TCRETURNdi || RetOpcode== X86::TCRETURNri64 || RetOpcode == X86::TCRETURNdi64) {