[WinEH] Don't emit CATCHRET from visitCatchPad
authorDavid Majnemer <david.majnemer@gmail.com>
Mon, 9 Nov 2015 23:07:48 +0000 (23:07 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Mon, 9 Nov 2015 23:07:48 +0000 (23:07 +0000)
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
include/llvm/Target/TargetSelectionDAG.td
lib/CodeGen/SelectionDAG/SelectionDAGBuilder.cpp
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
lib/Target/X86/X86InstrCompiler.td
test/CodeGen/X86/seh-catch-all.ll
test/CodeGen/X86/seh-catchpad.ll
test/CodeGen/X86/seh-exception-code.ll
test/CodeGen/X86/win32-seh-catchpad-realign.ll
test/CodeGen/X86/win32-seh-catchpad.ll

index c28802c34b2fd89a6e7eed4b484b5e135693b5cd..4ca73914b7283112d1fbc8f7517b441a5c44fbc9 100644 (file)
@@ -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.
index 7a73a0ff6b4009b995179517f9bfec202c43604b..d83311f22fe1f423a78a6caf983339e7b42ffa05 100644 (file)
@@ -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]>;
index 60b06b4ab0e3b177d3d9ecfe8a480f50ac83f683..5090bfbfb1437eda0b8a9c22c53449d9d6c300a5 100644 (file)
@@ -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) {
index 8d7712d3cd07a4de22e5ceba0e14417afdc838af..f5b38b396965671b64b26433ca8ab67083a78d19 100644 (file)
@@ -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);
index e7dbaa995c8f7cc5d78b3a2b4f6d81e5cf71c47d..c800f16489b50f64d0bbf06aadaf84d05ed79c0a 100644 (file)
@@ -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;
 
index f35fd5c138896fa071388dae698348f4793f93e2..e6141ade92b8e175d263ba93d68c4f315efc9be9 100644 (file)
@@ -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
index 0c4f33f6300f96b2112f275e8571be454c01a744..aa1b6e040ff98ebd7c475c802cabf568f2f4ae25 100644 (file)
@@ -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
index b59aa8d4c78f4ee4147f7acffade8c74d90de4ee..93775b6aadaa105c281ee7d5c5eb969936aefc00 100644 (file)
@@ -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)
index 3a314553ca126977dbfc0337fb1d5dc1c92cc7a2..e481a8e308c3c3284e71b003e321d0a474b5af5a 100644 (file)
@@ -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
index 9cc9118965cb9e9ef36cae94b8fb221d9ea2b271..24db1649eb8724170f7879c43144d39a3ef626c9 100644 (file)
@@ -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
index dd14f2df6899eb4aa0559eca9bc8451ec6ae8714..4e373af23e4416ab0cd9173a6d427be41a81e824 100644 (file)
@@ -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