From: Reid Kleckner Date: Thu, 17 Sep 2015 20:43:47 +0000 (+0000) Subject: [WinEH] Make funclet return instrs pseudo instrs X-Git-Url: http://plrg.eecs.uci.edu/git/?p=oota-llvm.git;a=commitdiff_plain;h=f946dd04123e27edfcd15dcf0d9de68dcb79be42;hp=9ac4d865671263781325ceeebb5716e4d4b60aea [WinEH] Make funclet return instrs pseudo instrs This makes catchret look more like a branch, and less like a weird use of BlockAddress. It also lets us get away from llvm.x86.seh.restoreframe, which relies on the old parentfpoffset label arithmetic. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@247936 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 7432cde7a2e..d2b3a32a2de 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -452,6 +452,7 @@ def brcond : SDNode<"ISD::BRCOND" , SDTBrcond, [SDNPHasChain]>; def brind : SDNode<"ISD::BRIND" , SDTBrind, [SDNPHasChain]>; def br : SDNode<"ISD::BR" , SDTBr, [SDNPHasChain]>; def catchret : SDNode<"ISD::CATCHRET" , SDTBr, [SDNPHasChain]>; +def cleanupret : SDNode<"ISD::CLEANUPRET" , SDTNone, [SDNPHasChain]>; def trap : SDNode<"ISD::TRAP" , SDTNone, [SDNPHasChain, SDNPSideEffect]>; diff --git a/lib/Target/X86/X86ExpandPseudo.cpp b/lib/Target/X86/X86ExpandPseudo.cpp index 6a5a28e546f..c9441bd0c2f 100644 --- a/lib/Target/X86/X86ExpandPseudo.cpp +++ b/lib/Target/X86/X86ExpandPseudo.cpp @@ -141,6 +141,41 @@ bool X86ExpandPseudo::ExpandMI(MachineBasicBlock &MBB, // The EH_RETURN pseudo is really removed during the MC Lowering. return true; } + + case X86::CLEANUPRET: { + // Replace CATCHRET with the appropriate RET. + unsigned RetOp = STI->is64Bit() ? X86::RETQ : X86::RETL; + BuildMI(MBB, MBBI, DL, TII->get(RetOp)); + MBBI->eraseFromParent(); + return true; + } + + case X86::CATCHRET: { + MachineBasicBlock *TargetMBB = MBBI->getOperand(0).getMBB(); + + // Fill EAX/RAX with the address of the target block. + unsigned ReturnReg = STI->is64Bit() ? X86::RAX : X86::EAX; + unsigned RetOp = STI->is64Bit() ? X86::RETQ : X86::RETL; + if (STI->is64Bit()) { + // LEA64r TargetMBB(%rip), %rax + BuildMI(MBB, MBBI, DL, TII->get(X86::LEA64r), ReturnReg) + .addReg(X86::RIP) + .addImm(0) + .addReg(0) + .addMBB(TargetMBB) + .addReg(0); + } else { + // MOV32ri $TargetMBB, %eax + BuildMI(MBB, MBBI, DL, TII->get(X86::MOV32ri)) + .addReg(ReturnReg) + .addMBB(TargetMBB); + } + + // Replace CATCHRET with the appropriate RET. + BuildMI(MBB, MBBI, DL, TII->get(RetOp)).addReg(ReturnReg); + MBBI->eraseFromParent(); + return true; + } } llvm_unreachable("Previous switch has a fallthrough?"); } diff --git a/lib/Target/X86/X86FrameLowering.cpp b/lib/Target/X86/X86FrameLowering.cpp index 489ab1a94a0..e4c35b115e0 100644 --- a/lib/Target/X86/X86FrameLowering.cpp +++ b/lib/Target/X86/X86FrameLowering.cpp @@ -711,7 +711,7 @@ void X86FrameLowering::emitPrologue(MachineFunction &MF, .addReg(MachineFramePtr, RegState::Kill) .setMIFlag(MachineInstr::FrameSetup); // Reset EBP / ESI to something good. - MBBI = restoreWin32EHFrameAndBasePtr(MBB, MBBI, DL); + MBBI = restoreWin32EHStackPointers(MBB, MBBI, DL); } else { // FIXME: Add SEH directives. NeedsWinCFI = false; @@ -1038,9 +1038,7 @@ bool X86FrameLowering::canUseLEAForSPInEpilogue( static bool isFuncletReturnInstr(MachineInstr *MI) { switch (MI->getOpcode()) { case X86::CATCHRET: - case X86::CATCHRET64: case X86::CLEANUPRET: - case X86::CLEANUPRET64: return true; default: return false; @@ -1073,13 +1071,51 @@ void X86FrameLowering::emitEpilogue(MachineFunction &MF, unsigned CSSize = X86FI->getCalleeSavedFrameSize(); uint64_t NumBytes = 0; - if (isFuncletReturnInstr(MBBI)) { + if (MBBI->getOpcode() == X86::CATCHRET) { NumBytes = MFI->getMaxCallFrameSize(); - assert(hasFP(MF) && "win64 EH funclets without FP not yet implemented"); + assert(hasFP(MF) && "EH funclets without FP not yet implemented"); + MachineBasicBlock *TargetMBB = MBBI->getOperand(0).getMBB(); + + // If this is SEH, this isn't really a funclet return. + bool IsSEH = isAsynchronousEHPersonality( + classifyEHPersonality(MF.getFunction()->getPersonalityFn())); + if (IsSEH) { + if (STI.is32Bit()) + restoreWin32EHStackPointers(MBB, MBBI, DL, /*RestoreSP=*/true); + BuildMI(MBB, MBBI, DL, TII.get(X86::JMP_4)).addMBB(TargetMBB); + MBBI->eraseFromParent(); + return; + } + + // For 32-bit, create a new block for the restore code. + MachineBasicBlock *RestoreMBB = TargetMBB; + if (STI.is32Bit()) { + RestoreMBB = MF.CreateMachineBasicBlock(MBB.getBasicBlock()); + MF.insert(TargetMBB, RestoreMBB); + MBB.transferSuccessors(RestoreMBB); + MBB.addSuccessor(RestoreMBB); + MBBI->getOperand(0).setMBB(RestoreMBB); + } // Pop EBP. BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), - MachineFramePtr).setMIFlag(MachineInstr::FrameDestroy); + MachineFramePtr) + .setMIFlag(MachineInstr::FrameDestroy); + + // Insert frame restoration code in a new block. + if (STI.is32Bit()) { + auto RestoreMBBI = RestoreMBB->begin(); + restoreWin32EHStackPointers(*RestoreMBB, RestoreMBBI, DL, + /*RestoreSP=*/true); + BuildMI(*RestoreMBB, RestoreMBBI, DL, TII.get(X86::JMP_4)) + .addMBB(TargetMBB); + } + } else if (isFuncletReturnInstr(MBBI)) { + NumBytes = MFI->getMaxCallFrameSize(); + assert(hasFP(MF) && "EH funclets without FP not yet implemented"); + BuildMI(MBB, MBBI, DL, TII.get(Is64Bit ? X86::POP64r : X86::POP32r), + MachineFramePtr) + .setMIFlag(MachineInstr::FrameDestroy); } else if (hasFP(MF)) { // Calculate required stack adjustment. uint64_t FrameSize = StackSize - SlotSize; @@ -2067,9 +2103,9 @@ bool X86FrameLowering::canUseAsEpilogue(const MachineBasicBlock &MBB) const { return !terminatorsNeedFlagsAsInput(MBB); } -MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHFrameAndBasePtr( +MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHStackPointers( MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, - DebugLoc DL) const { + DebugLoc DL, bool RestoreSP) const { assert(STI.isTargetWindowsMSVC() && "funclets only supported in MSVC env"); assert(STI.isTargetWin32() && "EBP/ESI restoration only required on win32"); assert(STI.is32Bit() && !Uses64BitFramePtr && @@ -2087,13 +2123,22 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHFrameAndBasePtr( // FIXME: Don't set FrameSetup flag in catchret case. int FI = FuncInfo.EHRegNodeFrameIndex; + int EHRegSize = MFI->getObjectSize(FI); + + if (RestoreSP) { + // MOV32rm -EHRegSize(%ebp), %esp + addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32rm), X86::ESP), + X86::EBP, true, -EHRegSize) + .setMIFlag(MachineInstr::FrameSetup); + } + unsigned UsedReg; int EHRegOffset = getFrameIndexReference(MF, FI, UsedReg); - int EHRegSize = MFI->getObjectSize(FI); int EndOffset = -EHRegOffset - EHRegSize; FuncInfo.EHRegNodeEndOffset = EndOffset; assert(EndOffset >= 0 && "end of registration object above normal EBP position!"); + if (UsedReg == FramePtr) { // ADD $offset, %ebp assert(UsedReg == FramePtr); @@ -2110,14 +2155,13 @@ MachineBasicBlock::iterator X86FrameLowering::restoreWin32EHFrameAndBasePtr( addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::LEA32r), BasePtr), FramePtr, false, EndOffset) .setMIFlag(MachineInstr::FrameSetup); - // MOV32mr SavedEBPOffset(%esi), %ebp + // MOV32rm SavedEBPOffset(%esi), %ebp assert(X86FI->getHasSEHFramePtrSave()); int Offset = getFrameIndexReference(MF, X86FI->getSEHFramePtrSaveIndex(), UsedReg); assert(UsedReg == BasePtr); - addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32mr)), UsedReg, true, - Offset) - .addReg(FramePtr) + addRegOffset(BuildMI(MBB, MBBI, DL, TII.get(X86::MOV32rm), FramePtr), + UsedReg, true, Offset) .setMIFlag(MachineInstr::FrameSetup); } return MBBI; diff --git a/lib/Target/X86/X86FrameLowering.h b/lib/Target/X86/X86FrameLowering.h index 7cbd18bd4d0..94b80613c35 100644 --- a/lib/Target/X86/X86FrameLowering.h +++ b/lib/Target/X86/X86FrameLowering.h @@ -158,9 +158,9 @@ private: /// Sets up EBP and optionally ESI based on the incoming EBP value. Only /// needed for 32-bit. Used in funclet prologues and at catchret destinations. MachineBasicBlock::iterator - restoreWin32EHFrameAndBasePtr(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - DebugLoc DL) const; + restoreWin32EHStackPointers(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, DebugLoc DL, + bool RestoreSP = false) const; }; } // End llvm namespace diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index dc5c0d1e352..cda055438a1 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -417,8 +417,6 @@ X86TargetLowering::X86TargetLowering(const X86TargetMachine &TM, setOperationAction(ISD::SETCC , MVT::i64 , Custom); } setOperationAction(ISD::EH_RETURN , MVT::Other, Custom); - setOperationAction(ISD::CATCHRET , MVT::Other, Custom); - setOperationAction(ISD::CLEANUPRET , MVT::Other, Custom); // NOTE: EH_SJLJ_SETJMP/_LONGJMP supported here is NOT intended to support // SjLj exception handling but a light-weight setjmp/longjmp replacement to // support continuation, user-level threading, and etc.. As a result, no @@ -16922,41 +16920,6 @@ SDValue X86TargetLowering::LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const { DAG.getRegister(StoreAddrReg, PtrVT)); } -SDValue X86TargetLowering::LowerCATCHRET(SDValue Op, SelectionDAG &DAG) const { - SDValue Chain = Op.getOperand(0); - SDValue Dest = Op.getOperand(1); - SDLoc DL(Op); - - MVT PtrVT = getPointerTy(DAG.getDataLayout()); - - MachineFunction &MF = DAG.getMachineFunction(); - if (isAsynchronousEHPersonality( - classifyEHPersonality(MF.getFunction()->getPersonalityFn()))) { - // For SEH, codegen catchret as a branch for now. - // FIXME: Insert something to restore the frame. - return DAG.getNode(ISD::BR, DL, MVT::Other, Chain, Dest); - } - - unsigned ReturnReg = (PtrVT == MVT::i64 ? X86::RAX : X86::EAX); - - // Load the address of the destination block. - // FIXME: Do this without creating a BlockAddress. - MachineBasicBlock *DestMBB = cast(Dest)->getBasicBlock(); - BlockAddress *BA = - BlockAddress::get(const_cast(MF.getFunction()), - const_cast(DestMBB->getBasicBlock())); - DestMBB->setHasAddressTaken(); - SDValue BlockPtr = DAG.getBlockAddress(BA, PtrVT); - Chain = DAG.getCopyToReg(Chain, DL, ReturnReg, BlockPtr); - return DAG.getNode(X86ISD::CATCHRET, DL, MVT::Other, Chain, - DAG.getRegister(ReturnReg, PtrVT)); -} - -SDValue X86TargetLowering::LowerCLEANUPRET(SDValue Op, SelectionDAG &DAG) const { - return DAG.getNode(X86ISD::CLEANUPRET, SDLoc(Op), MVT::Other, - Op.getOperand(0)); -} - SDValue X86TargetLowering::lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); @@ -19198,8 +19161,6 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { 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); - case ISD::CLEANUPRET: return LowerCLEANUPRET(Op, DAG); - case ISD::CATCHRET: return LowerCATCHRET(Op, DAG); case ISD::EH_SJLJ_SETJMP: return lowerEH_SJLJ_SETJMP(Op, DAG); case ISD::EH_SJLJ_LONGJMP: return lowerEH_SJLJ_LONGJMP(Op, DAG); case ISD::INIT_TRAMPOLINE: return LowerINIT_TRAMPOLINE(Op, DAG); @@ -19537,8 +19498,6 @@ const char *X86TargetLowering::getTargetNodeName(unsigned Opcode) const { case X86ISD::EH_SJLJ_SETJMP: return "X86ISD::EH_SJLJ_SETJMP"; case X86ISD::EH_SJLJ_LONGJMP: return "X86ISD::EH_SJLJ_LONGJMP"; case X86ISD::EH_RETURN: return "X86ISD::EH_RETURN"; - case X86ISD::CATCHRET: return "X86ISD::CATCHRET"; - case X86ISD::CLEANUPRET: return "X86ISD::CLEANUPRET"; case X86ISD::TC_RETURN: return "X86ISD::TC_RETURN"; case X86ISD::FNSTCW16m: return "X86ISD::FNSTCW16m"; case X86ISD::FNSTSW16r: return "X86ISD::FNSTSW16r"; diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index edd59ccac15..de9b4cf5023 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -268,14 +268,6 @@ namespace llvm { // Exception Handling helpers. EH_RETURN, - // CATCHRET - Represents a return from a catch block funclet. Used for - // MSVC compatible exception handling. Takes a chain operand and RAX. - CATCHRET, - - // CLEANUPRET - Represents a return from a cleanup block funclet. Used - // for MSVC compatible exception handling. Takes only a chain operand. - CLEANUPRET, - // SjLj exception handling setjmp. EH_SJLJ_SETJMP, @@ -1014,7 +1006,6 @@ namespace llvm { SDValue LowerFRAMEADDR(SDValue Op, SelectionDAG &DAG) const; SDValue LowerFRAME_TO_ARGS_OFFSET(SDValue Op, SelectionDAG &DAG) const; SDValue LowerEH_RETURN(SDValue Op, SelectionDAG &DAG) const; - SDValue LowerCATCHRET(SDValue Op, SelectionDAG &DAG) const; SDValue LowerCLEANUPRET(SDValue Op, SelectionDAG &DAG) const; SDValue lowerEH_SJLJ_SETJMP(SDValue Op, SelectionDAG &DAG) const; SDValue lowerEH_SJLJ_LONGJMP(SDValue Op, SelectionDAG &DAG) const; diff --git a/lib/Target/X86/X86InstrCompiler.td b/lib/Target/X86/X86InstrCompiler.td index ea8fb20f1d4..8d94aaa0eac 100644 --- a/lib/Target/X86/X86InstrCompiler.td +++ b/lib/Target/X86/X86InstrCompiler.td @@ -153,20 +153,10 @@ def EH_RETURN64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr), } let isTerminator = 1, isBarrier = 1, hasCtrlDep = 1, isCodeGenOnly = 1, isReturn = 1 in { -def CATCHRET : I<0xC3, RawFrm, (outs), (ins GR32:$addr), - "ret{l}\t# CATCHRET", - [(X86catchret GR32:$addr)], IIC_RET>, Sched<[WriteJumpLd]>; -def CATCHRET64 : I<0xC3, RawFrm, (outs), (ins GR64:$addr), - "ret{q}\t# CATCHRET", - [(X86catchret GR64:$addr)], IIC_RET>, Sched<[WriteJumpLd]>; -def CLEANUPRET : I<0xC3, RawFrm, (outs), (ins), - "ret{l}\t# CLEANUPRET", - [(X86cleanupret)], IIC_RET>, Sched<[WriteJumpLd]>, - Requires<[Not64BitMode]>; -def CLEANUPRET64 : I<0xC3, RawFrm, (outs), (ins), - "ret{q}\t# CLEANUPRET", - [(X86cleanupret)], IIC_RET>, Sched<[WriteJumpLd]>, - Requires<[In64BitMode]>; +def CATCHRET : I<0, Pseudo, (outs), (ins brtarget32:$dst), + "# CATCHRET", + [(catchret bb:$dst)]>; +def CLEANUPRET : I<0, Pseudo, (outs), (ins), "# CLEANUPRET", [(cleanupret)]>; } let hasSideEffects = 1, isBarrier = 1, isCodeGenOnly = 1, diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index 005c3d518f7..d92a23afdee 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -205,10 +205,6 @@ def X86tlsbaseaddr : SDNode<"X86ISD::TLSBASEADDR", SDT_X86TLSBASEADDR, def X86ehret : SDNode<"X86ISD::EH_RETURN", SDT_X86EHRET, [SDNPHasChain]>; -def X86catchret : SDNode<"X86ISD::CATCHRET", SDT_X86EHRET, [SDNPHasChain]>; - -def X86cleanupret : SDNode<"X86ISD::CLEANUPRET", SDTX86Void, [SDNPHasChain]>; - def X86eh_sjlj_setjmp : SDNode<"X86ISD::EH_SJLJ_SETJMP", SDTypeProfile<1, 1, [SDTCisInt<0>, SDTCisPtrTy<1>]>, diff --git a/lib/Target/X86/X86MCInstLower.cpp b/lib/Target/X86/X86MCInstLower.cpp index 88a6d00f4cc..c61dc125ebc 100644 --- a/lib/Target/X86/X86MCInstLower.cpp +++ b/lib/Target/X86/X86MCInstLower.cpp @@ -531,13 +531,6 @@ ReSimplify: break; } - case X86::CATCHRET: - case X86::CATCHRET64: { - OutMI = MCInst(); - OutMI.setOpcode(getRetOpcode(AsmPrinter.getSubtarget())); - break; - } - // TAILJMPd, TAILJMPd64 - Lower to the correct jump instructions. case X86::TAILJMPr: case X86::TAILJMPd: diff --git a/lib/Target/X86/X86WinEHState.cpp b/lib/Target/X86/X86WinEHState.cpp index d148be618ed..3a73338284c 100644 --- a/lib/Target/X86/X86WinEHState.cpp +++ b/lib/Target/X86/X86WinEHState.cpp @@ -500,15 +500,6 @@ void WinEHStatePass::addStateStoresToFunclet(Value *ParentRegNode, insertStateNumberStore(ParentRegNode, II, State); } } - - // Insert calls to llvm.x86.seh.restoreframe at catchret destinations. In - // SEH, insert them before the catchret. - // FIXME: We should probably do this as part of catchret lowering in the - // DAG. - if (auto *CR = dyn_cast(BB.getTerminator())) - insertRestoreFrame(Personality == EHPersonality::MSVC_X86SEH - ? CR->getParent() - : CR->getSuccessor()); } } diff --git a/test/CodeGen/X86/win-catchpad-csrs.ll b/test/CodeGen/X86/win-catchpad-csrs.ll index 20968cc4739..97d86603ee6 100644 --- a/test/CodeGen/X86/win-catchpad-csrs.ll +++ b/test/CodeGen/X86/win-catchpad-csrs.ll @@ -59,9 +59,7 @@ catchendblock: ; preds = %catch, ; X86: movl $0, -{{[0-9]+}}(%ebp) ; X86: movl $1, (%esp) ; X86: calll _f -; X86: [[contbb:Ltmp[0-9]+]]: # Block address taken -; X86: movl -{{[0-9]+}}(%ebp), %esp -; X86: addl ${{[0-9]+}}, %esp +; X86: [[contbb:LBB0_[0-9]+]]: # %try.cont ; X86: popl %esi ; X86: popl %edi ; X86: popl %ebx @@ -76,11 +74,17 @@ catchendblock: ; preds = %catch, ; X86: movl $1, -{{[0-9]+}}(%ebp) ; X86: movl $2, (%esp) ; X86: calll _f -; X86: movl $[[contbb]], %eax -; X86-NEXT: addl $16, %esp +; X86: addl $16, %esp ; X86-NEXT: popl %ebp +; X86-NEXT: movl $[[restorebb:LBB0_[0-9]+]], %eax ; X86-NEXT: retl +; FIXME: Lay this out in the parent funclet. +; X86: [[restorebb]]: +; X86: movl -16(%ebp), %esp +; X86: addl $12, %ebp +; X86: jmp [[contbb]] + ; X86: L__ehtable$try_catch_catch: ; X86: $handlerMap$0$try_catch_catch: ; X86: .long 0 @@ -108,7 +112,7 @@ catchendblock: ; preds = %catch, ; X64: callq useints ; X64: movl $1, %ecx ; X64: callq f -; X64: [[contbb:.Ltmp[0-9]+]]: # Block address taken +; X64: [[contbb:\.LBB0_[0-9]+]]: # %try.cont ; X64: addq $40, %rsp ; X64: popq %rbp ; X64: retq @@ -120,9 +124,9 @@ catchendblock: ; preds = %catch, ; X64: subq $32, %rsp ; X64: movl $2, %ecx ; X64: callq f -; X64: leaq [[contbb]](%rip), %rax ; X64: addq $32, %rsp ; X64: popq %rbp +; X64: leaq [[contbb]](%rip), %rax ; X64: retq ; X64: $handlerMap$0$try_catch_catch: diff --git a/test/CodeGen/X86/win-catchpad.ll b/test/CodeGen/X86/win-catchpad.ll index 690e8ba3ea8..c63907a470a 100644 --- a/test/CodeGen/X86/win-catchpad.ll +++ b/test/CodeGen/X86/win-catchpad.ll @@ -70,8 +70,7 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X86-DAG: movl %[[addr_reg]], 4(%esp) ; X86-DAG: movl $1, (%esp) ; X86: calll _f -; X86: [[contbb:Ltmp[0-9]+]]: # Block address taken -; X86: movl -{{[0-9]+}}(%ebp), %esp +; X86: [[contbb:LBB0_[0-9]+]]: # %try.cont ; X86: retl ; X86: [[catch1bb:LBB0_[0-9]+]]: # %catch{{$}} @@ -84,9 +83,9 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X86-DAG: movl %[[addr_reg]], 4(%esp) ; X86-DAG: movl %[[e_reg]], (%esp) ; X86: calll _f -; X86: movl $[[contbb]], %eax ; X86-NEXT: addl $8, %esp ; X86-NEXT: popl %ebp +; X86-NEXT: movl $[[restorebb:LBB0_[0-9]+]], %eax ; X86-NEXT: retl ; X86: [[catch2bb:LBB0_[0-9]+]]: # %catch.2{{$}} @@ -98,11 +97,17 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X86-DAG: movl %[[addr_reg]], 4(%esp) ; X86-DAG: movl $3, (%esp) ; X86: calll _f -; X86: movl $[[contbb]], %eax ; X86-NEXT: addl $8, %esp ; X86-NEXT: popl %ebp +; X86-NEXT: movl $[[restorebb]], %eax ; X86-NEXT: retl +; FIXME: We should lay this code out up with the parent function. +; X86: [[restorebb]]: +; X86: movl -16(%ebp), %esp +; X86: addl $12, %ebp +; X86: jmp [[contbb]] + ; X86: L__ehtable$try_catch_catch: ; X86: $handlerMap$0$try_catch_catch: ; X86-NEXT: .long 0 @@ -124,7 +129,7 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X64-DAG: leaq -[[local_offs:[0-9]+]](%rbp), %rdx ; X64-DAG: movl $1, %ecx ; X64: callq f -; X64: [[contbb:.Ltmp[0-9]+]]: # Block address taken +; X64: [[contbb:\.LBB0_[0-9]+]]: # %try.cont ; X64: addq $48, %rsp ; X64: popq %rbp ; X64: retq @@ -137,10 +142,10 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X64-DAG: leaq -[[local_offs]](%rbp), %rdx ; X64-DAG: movl [[e_addr:[-0-9]+]](%rbp), %ecx ; X64: callq f -; X64: leaq [[contbb]](%rip), %rax ; X64: addq $32, %rsp -; X64: popq %rbp -; X64: retq +; X64-NEXT: popq %rbp +; X64-NEXT: leaq [[contbb]](%rip), %rax +; X64-NEXT: retq ; X64: [[catch2bb:\.LBB0_[0-9]+]]: # %catch.2{{$}} ; X64: movq %rdx, 16(%rsp) @@ -150,10 +155,10 @@ catchendblock: ; preds = %catch, %catch.2, %c ; X64-DAG: leaq -[[local_offs]](%rbp), %rdx ; X64-DAG: movl $3, %ecx ; X64: callq f -; X64: leaq [[contbb]](%rip), %rax ; X64: addq $32, %rsp -; X64: popq %rbp -; X64: retq +; X64-NEXT: popq %rbp +; X64-NEXT: leaq [[contbb]](%rip), %rax +; X64-NEXT: retq ; X64: $handlerMap$0$try_catch_catch: ; X64: .long 0 diff --git a/test/CodeGen/X86/win-cleanuppad.ll b/test/CodeGen/X86/win-cleanuppad.ll index b369e8ce6b1..808e322751d 100644 --- a/test/CodeGen/X86/win-cleanuppad.ll +++ b/test/CodeGen/X86/win-cleanuppad.ll @@ -66,14 +66,18 @@ cleanup.outer: ; preds = %invoke.cont.1, %c ; X86: calll _f ; X86: LBB1_[[cleanup_inner:[0-9]+]]: # %cleanup.inner +; X86: pushl %ebp ; X86: leal {{.*}}(%ebp), %ecx ; X86: calll "??1Dtor@@QAE@XZ" -; X86: retl # CLEANUPRET +; X86: popl %ebp +; X86: retl ; X86: LBB1_[[cleanup_outer:[0-9]+]]: # %cleanup.outer +; X86: pushl %ebp ; X86: leal {{.*}}(%ebp), %ecx ; X86: calll "??1Dtor@@QAE@XZ" -; X86: retl # CLEANUPRET +; X86: popl %ebp +; X86: retl ; X86: L__ehtable$nested_cleanup: ; X86: .long 429065506 @@ -100,14 +104,18 @@ cleanup.outer: ; preds = %invoke.cont.1, %c ; X64: callq f ; X64: .LBB1_[[cleanup_inner:[0-9]+]]: # %cleanup.inner +; X64: pushq %rbp ; X64: leaq {{.*}}(%rbp), %rcx ; X64: callq "??1Dtor@@QAE@XZ" -; X64: retq # CLEANUPRET +; X64: popq %rbp +; X64: retq ; X64: .LBB1_[[cleanup_outer:[0-9]+]]: # %cleanup.outer +; X64: pushq %rbp ; X64: leaq {{.*}}(%rbp), %rcx ; X64: callq "??1Dtor@@QAE@XZ" -; X64: retq # CLEANUPRET +; X64: popq %rbp +; X64: retq ; X64: .seh_handlerdata ; X64: .long ($cppxdata$nested_cleanup)@IMGREL