From c30d240fb899bd0ad8295642447f6d48421113d1 Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Mon, 9 Nov 2015 23:07:48 +0000 Subject: [PATCH] [WinEH] Don't emit CATCHRET from visitCatchPad Instead, emit a CATCHPAD node which will get selected to a target specific sequence. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@252528 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/CodeGen/ISDOpcodes.h | 3 ++ include/llvm/Target/TargetSelectionDAG.td | 5 +++- .../SelectionDAG/SelectionDAGBuilder.cpp | 17 ++++------- lib/Target/X86/X86ISelLowering.cpp | 28 +++++++++++++------ lib/Target/X86/X86ISelLowering.h | 3 ++ lib/Target/X86/X86InstrCompiler.td | 6 +++- test/CodeGen/X86/seh-catch-all.ll | 1 - test/CodeGen/X86/seh-catchpad.ll | 10 +++---- test/CodeGen/X86/seh-exception-code.ll | 2 +- .../CodeGen/X86/win32-seh-catchpad-realign.ll | 6 ++-- test/CodeGen/X86/win32-seh-catchpad.ll | 1 - 11 files changed, 47 insertions(+), 35 deletions(-) diff --git a/include/llvm/CodeGen/ISDOpcodes.h b/include/llvm/CodeGen/ISDOpcodes.h index c28802c34b2..4ca73914b72 100644 --- a/include/llvm/CodeGen/ISDOpcodes.h +++ b/include/llvm/CodeGen/ISDOpcodes.h @@ -591,6 +591,9 @@ namespace ISD { /// take a chain as input and return a chain. EH_LABEL, + /// CATCHPAD - Represents a catchpad instruction. + CATCHPAD, + /// CATCHRET - Represents a return from a catch block funclet. Used for /// MSVC compatible exception handling. Takes a chain operand and a /// destination basic block operand. diff --git a/include/llvm/Target/TargetSelectionDAG.td b/include/llvm/Target/TargetSelectionDAG.td index 7a73a0ff6b4..d83311f22fe 100644 --- a/include/llvm/Target/TargetSelectionDAG.td +++ b/include/llvm/Target/TargetSelectionDAG.td @@ -455,8 +455,11 @@ def brcc : SDNode<"ISD::BR_CC" , SDTBrCC, [SDNPHasChain]>; 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" , SDTCatchret, [SDNPHasChain]>; +def catchret : SDNode<"ISD::CATCHRET" , SDTCatchret, + [SDNPHasChain, SDNPSideEffect]>; def cleanupret : SDNode<"ISD::CLEANUPRET" , SDTNone, [SDNPHasChain]>; +def catchpad : SDNode<"ISD::CATCHPAD" , SDTNone, + [SDNPHasChain, SDNPSideEffect]>; def trap : SDNode<"ISD::TRAP" , SDTNone, [SDNPHasChain, SDNPSideEffect]>; diff --git a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp index 60b06b4ab0e..5090bfbfb14 100644 --- a/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp +++ b/lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp @@ -1178,7 +1178,6 @@ SDValue SelectionDAGBuilder::getValueImpl(const Value *V) { void SelectionDAGBuilder::visitCatchPad(const CatchPadInst &I) { auto Pers = classifyEHPersonality(FuncInfo.Fn->getPersonalityFn()); bool IsMSVCCXX = Pers == EHPersonality::MSVC_CXX; - bool IsSEH = isAsynchronousEHPersonality(Pers); bool IsCoreCLR = Pers == EHPersonality::CoreCLR; MachineBasicBlock *CatchPadMBB = FuncInfo.MBB; // In MSVC C++ and CoreCLR, catchblocks are funclets and need prologues. @@ -1190,22 +1189,16 @@ void SelectionDAGBuilder::visitCatchPad(const CatchPadInst &I) { // Update machine-CFG edge. FuncInfo.MBB->addSuccessor(NormalDestMBB); - // CatchPads in SEH are not funclets, they are merely markers which indicate - // where to insert register restoration code. - if (IsSEH) { - DAG.setRoot(DAG.getNode(ISD::CATCHRET, getCurSDLoc(), MVT::Other, - getControlRoot(), DAG.getBasicBlock(NormalDestMBB), - DAG.getBasicBlock(&FuncInfo.MF->front()))); - return; - } + SDValue Chain = + DAG.getNode(ISD::CATCHPAD, getCurSDLoc(), MVT::Other, getControlRoot()); // If this is not a fall-through branch or optimizations are switched off, // emit the branch. if (NormalDestMBB != NextBlock(CatchPadMBB) || TM.getOptLevel() == CodeGenOpt::None) - DAG.setRoot(DAG.getNode(ISD::BR, getCurSDLoc(), MVT::Other, - getControlRoot(), - DAG.getBasicBlock(NormalDestMBB))); + Chain = DAG.getNode(ISD::BR, getCurSDLoc(), MVT::Other, Chain, + DAG.getBasicBlock(NormalDestMBB)); + DAG.setRoot(Chain); } void SelectionDAGBuilder::visitCatchRet(const CatchReturnInst &I) { diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 8d7712d3cd0..f5b38b39696 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -21401,15 +21401,7 @@ X86TargetLowering::EmitLoweredCatchRet(MachineInstr *MI, MachineBasicBlock *TargetMBB = MI->getOperand(0).getMBB(); DebugLoc DL = MI->getDebugLoc(); - // SEH does not outline catch bodies into funclets. Turn CATCHRETs into - // JMP_4s, possibly with some extra restoration code for 32-bit EH. - if (IsSEH) { - if (Subtarget->is32Bit()) - BuildMI(*BB, MI, DL, TII.get(X86::EH_RESTORE)); - BuildMI(*BB, MI, DL, TII.get(X86::JMP_4)).addMBB(TargetMBB); - MI->eraseFromParent(); - return BB; - } + assert(!IsSEH && "SEH does not use catchret!"); // Only 32-bit EH needs to worry about manually restoring stack pointers. if (!Subtarget->is32Bit()) @@ -21431,6 +21423,22 @@ X86TargetLowering::EmitLoweredCatchRet(MachineInstr *MI, return BB; } +MachineBasicBlock * +X86TargetLowering::EmitLoweredCatchPad(MachineInstr *MI, + MachineBasicBlock *BB) const { + MachineFunction *MF = BB->getParent(); + const Constant *PerFn = MF->getFunction()->getPersonalityFn(); + bool IsSEH = isAsynchronousEHPersonality(classifyEHPersonality(PerFn)); + // Only 32-bit SEH requires special handling for catchpad. + if (IsSEH && Subtarget->is32Bit()) { + const TargetInstrInfo &TII = *Subtarget->getInstrInfo(); + DebugLoc DL = MI->getDebugLoc(); + BuildMI(*BB, MI, DL, TII.get(X86::EH_RESTORE)); + } + MI->eraseFromParent(); + return BB; +} + MachineBasicBlock * X86TargetLowering::EmitLoweredTLSCall(MachineInstr *MI, MachineBasicBlock *BB) const { @@ -21813,6 +21821,8 @@ X86TargetLowering::EmitInstrWithCustomInserter(MachineInstr *MI, return EmitLoweredWinAlloca(MI, BB); case X86::CATCHRET: return EmitLoweredCatchRet(MI, BB); + case X86::CATCHPAD: + return EmitLoweredCatchPad(MI, BB); case X86::SEG_ALLOCA_32: case X86::SEG_ALLOCA_64: return EmitLoweredSegAlloca(MI, BB); diff --git a/lib/Target/X86/X86ISelLowering.h b/lib/Target/X86/X86ISelLowering.h index e7dbaa995c8..c800f16489b 100644 --- a/lib/Target/X86/X86ISelLowering.h +++ b/lib/Target/X86/X86ISelLowering.h @@ -1101,6 +1101,9 @@ namespace llvm { MachineBasicBlock *EmitLoweredCatchRet(MachineInstr *MI, MachineBasicBlock *BB) const; + MachineBasicBlock *EmitLoweredCatchPad(MachineInstr *MI, + MachineBasicBlock *BB) const; + MachineBasicBlock *EmitLoweredSegAlloca(MachineInstr *MI, MachineBasicBlock *BB) const; diff --git a/lib/Target/X86/X86InstrCompiler.td b/lib/Target/X86/X86InstrCompiler.td index f35fd5c1388..e6141ade92b 100644 --- a/lib/Target/X86/X86InstrCompiler.td +++ b/lib/Target/X86/X86InstrCompiler.td @@ -156,13 +156,17 @@ let isTerminator = 1, hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1, isCodeGenOnly = 1, isReturn = 1 in { def CLEANUPRET : I<0, Pseudo, (outs), (ins), "# CLEANUPRET", [(cleanupret)]>; - // CATCHRET needs a custom inserter for SEH nonsense. + // CATCHRET needs a custom inserter for SEH. let usesCustomInserter = 1 in def CATCHRET : I<0, Pseudo, (outs), (ins brtarget32:$dst, brtarget32:$from), "# CATCHRET", [(catchret bb:$dst, bb:$from)]>; } +let hasSideEffects = 1, isBarrier = 1, hasCtrlDep = 1, isCodeGenOnly = 1, + usesCustomInserter = 1 in +def CATCHPAD : I<0, Pseudo, (outs), (ins), "# CATCHPAD", [(catchpad)]>; + // This instruction is responsible for re-establishing stack pointers after an // exception has been caught and we are rejoining normal control flow in the // parent function or funclet. It generally sets ESP and EBP, and optionally diff --git a/test/CodeGen/X86/seh-catch-all.ll b/test/CodeGen/X86/seh-catch-all.ll index 0c4f33f6300..aa1b6e040ff 100644 --- a/test/CodeGen/X86/seh-catch-all.ll +++ b/test/CodeGen/X86/seh-catch-all.ll @@ -34,7 +34,6 @@ endpad: ; CHECK: callq crash ; CHECK: retq ; CHECK: .LBB0_2: # %lpad -; CHECK: # %catchall ; CHECK: leaq str(%rip), %rcx ; CHECK: movl %eax, %edx ; CHECK: callq printf diff --git a/test/CodeGen/X86/seh-catchpad.ll b/test/CodeGen/X86/seh-catchpad.ll index b59aa8d4c78..93775b6aada 100644 --- a/test/CodeGen/X86/seh-catchpad.ll +++ b/test/CodeGen/X86/seh-catchpad.ll @@ -121,8 +121,6 @@ ehcleanup.end: ; preds = %ehcleanup ; CHECK: callq "?fin$0@0@main@@" ; CHECK: jmp .LBB1_[[epilogue]] ; CHECK: .LBB1_[[except2bb:[0-9]+]]: # %catch.dispatch.7 -; CHECK: jmp .LBB1_7 -; CHECK: # %__except.9 ; CHECK: leaq "??_C@_06IBDBCMGJ@caught?$AA@"(%rip), %rcx ; CHECK: callq puts ; CHECK: jmp .LBB1_[[epilogue]] @@ -145,18 +143,18 @@ ehcleanup.end: ; preds = %ehcleanup ; CHECK-NEXT: .long .Ltmp2@IMGREL+1 ; CHECK-NEXT: .long .Ltmp3@IMGREL+1 ; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL -; CHECK-NEXT: .long .LBB1_6@IMGREL +; CHECK-NEXT: .long .LBB1_5@IMGREL ; CHECK-NEXT: .long .Ltmp6@IMGREL+1 ; CHECK-NEXT: .long .Ltmp7@IMGREL+1 ; CHECK-NEXT: .long "?filt$0@0@main@@"@IMGREL -; CHECK-NEXT: .long .LBB1_6@IMGREL +; CHECK-NEXT: .long .LBB1_5@IMGREL ; CHECK-NEXT: .Llsda_end0: ; CHECK: .text ; CHECK: .seh_endproc -; CHECK: "?dtor$4@?0?main@4HA": -; CHECK: .seh_proc "?dtor$4@?0?main@4HA" +; CHECK: "?dtor$3@?0?main@4HA": +; CHECK: .seh_proc "?dtor$3@?0?main@4HA" ; CHECK: .seh_handler __C_specific_handler, @unwind, @except ; CHECK: .LBB1_[[finbb]]: # %ehcleanup ; CHECK: movq %rdx, 16(%rsp) diff --git a/test/CodeGen/X86/seh-exception-code.ll b/test/CodeGen/X86/seh-exception-code.ll index 3a314553ca1..e481a8e308c 100644 --- a/test/CodeGen/X86/seh-exception-code.ll +++ b/test/CodeGen/X86/seh-exception-code.ll @@ -36,6 +36,6 @@ catchendblock: ; preds = %catch.dispatch ; CHECK: xorl %ecx, %ecx ; CHECK: callq f -; CHECK: # %__except +; CHECK: # %catch.dispatch ; CHECK: movl %eax, %ecx ; CHECK-NEXT: callq f diff --git a/test/CodeGen/X86/win32-seh-catchpad-realign.ll b/test/CodeGen/X86/win32-seh-catchpad-realign.ll index 9cc9118965c..24db1649eb8 100644 --- a/test/CodeGen/X86/win32-seh-catchpad-realign.ll +++ b/test/CodeGen/X86/win32-seh-catchpad-realign.ll @@ -61,7 +61,7 @@ declare i32 @_except_handler3(...) ; CHECK: calll _useit ; ; Epilogue -; CHECK: LBB0_1: # %__try.cont +; CHECK: LBB0_2: # %__try.cont ; CHECK: leal -12(%ebp), %esp ; CHECK: popl %esi ; CHECK: popl %edi @@ -69,7 +69,7 @@ declare i32 @_except_handler3(...) ; CHECK: popl %ebp ; CHECK: retl ; -; CHECK: LBB0_2: # %catch.dispatch +; CHECK: LBB0_1: # %catch.dispatch ; Restore ESP ; CHECK: movl -24(%ebp), %esp ; Recompute ESI by subtracting 60 from the end of the registration node. @@ -77,4 +77,4 @@ declare i32 @_except_handler3(...) ; Restore EBP ; CHECK: movl 12(%esi), %ebp ; Rejoin normal control flow -; CHECK: jmp LBB0_1 +; CHECK: jmp LBB0_2 diff --git a/test/CodeGen/X86/win32-seh-catchpad.ll b/test/CodeGen/X86/win32-seh-catchpad.ll index dd14f2df689..4e373af23e4 100644 --- a/test/CodeGen/X86/win32-seh-catchpad.ll +++ b/test/CodeGen/X86/win32-seh-catchpad.ll @@ -220,7 +220,6 @@ catchendblock: ; preds = %catch.dispatch ; CHECK: # %catch.dispatch ; CHECK-NEXT: movl -24(%ebp), %esp ; CHECK-NEXT: addl $12, %ebp -; CHECK: # %__except.ret ; CHECK-NEXT: movl $-1, -16(%ebp) ; CHECK-NEXT: movl $2, (%esp) ; CHECK-NEXT: calll _f