[WinEH] Make funclet return instrs pseudo instrs
authorReid Kleckner <rnk@google.com>
Thu, 17 Sep 2015 20:43:47 +0000 (20:43 +0000)
committerReid Kleckner <rnk@google.com>
Thu, 17 Sep 2015 20:43:47 +0000 (20:43 +0000)
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

13 files changed:
include/llvm/Target/TargetSelectionDAG.td
lib/Target/X86/X86ExpandPseudo.cpp
lib/Target/X86/X86FrameLowering.cpp
lib/Target/X86/X86FrameLowering.h
lib/Target/X86/X86ISelLowering.cpp
lib/Target/X86/X86ISelLowering.h
lib/Target/X86/X86InstrCompiler.td
lib/Target/X86/X86InstrInfo.td
lib/Target/X86/X86MCInstLower.cpp
lib/Target/X86/X86WinEHState.cpp
test/CodeGen/X86/win-catchpad-csrs.ll
test/CodeGen/X86/win-catchpad.ll
test/CodeGen/X86/win-cleanuppad.ll

index 7432cde7a2eab09ef71dc4a2fa7cd9e8aa1bd0cb..d2b3a32a2de51c66de580d7a1add7912f99a1e63 100644 (file)
@@ -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]>;
index 6a5a28e546f2b2ad464ea06d1f33980605709df0..c9441bd0c2f1394ecd13ae318be838bfa497c6f4 100644 (file)
@@ -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?");
 }
index 489ab1a94a05ac806a58198f3678d9acd4f89b9a..e4c35b115e0e08c827f542c27a576809f176b94e 100644 (file)
@@ -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;
index 7cbd18bd4d03632edfa6c8b03b1e131bdc920ad5..94b80613c35bf9780b8e536676794eac6a2db99b 100644 (file)
@@ -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
index dc5c0d1e352bd31c4517e400d089c4d91471f3d1..cda055438a11c8dcf6b5f63450a9934fef3862d3 100644 (file)
@@ -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<BasicBlockSDNode>(Dest)->getBasicBlock();
-  BlockAddress *BA =
-      BlockAddress::get(const_cast<Function *>(MF.getFunction()),
-                        const_cast<BasicBlock *>(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";
index edd59ccac1539fb3fffc6d829eff538295c807e7..de9b4cf5023f5d9b4309a00e45618a2ec1895c97 100644 (file)
@@ -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;
index ea8fb20f1d4b983e6d1cbeba40711734cdadd940..8d94aaa0eaca009ecefe6c78ff04fff6e887a36e 100644 (file)
@@ -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,
index 005c3d518f774d844acdf289c6efddf0c6e5d671..d92a23afdee4cd16178801eb32fa1a736d013d46 100644 (file)
@@ -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>]>,
index 88a6d00f4ccb75c26f6101f5abad60a198db898f..c61dc125ebc89b91eb4ce04baa5d71320d114baa 100644 (file)
@@ -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:
index d148be618edc721a8f6808fc30252192a4e38d14..3a73338284c6381b3e16fb3a0acb8358d3b64bfb 100644 (file)
@@ -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<CatchReturnInst>(BB.getTerminator()))
-      insertRestoreFrame(Personality == EHPersonality::MSVC_X86SEH
-                             ? CR->getParent()
-                             : CR->getSuccessor());
   }
 }
 
index 20968cc47390266209683cbc5a3e5dd164f1d742..97d86603ee6af7e86011ec4faf50a0d7ca2712ff 100644 (file)
@@ -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:
index 690e8ba3ea8a821d00ff38c716f07b55e2423ca2..c63907a470af98dab0ae041e65e93d8512bf7348 100644 (file)
@@ -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
index b369e8ce6b149ff66350a58abfdd5f502609f0eb..808e322751d161834eb9bed556ee5d0d21bef1e2 100644 (file)
@@ -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