[WinEH] Use operand bundles to describe call sites
authorDavid Majnemer <david.majnemer@gmail.com>
Tue, 15 Dec 2015 21:27:27 +0000 (21:27 +0000)
committerDavid Majnemer <david.majnemer@gmail.com>
Tue, 15 Dec 2015 21:27:27 +0000 (21:27 +0000)
SimplifyCFG allows tail merging with code which terminates in
unreachable which, in turn, makes it possible for an invoke to end up in
a funclet which it was not originally part of.

Using operand bundles on invokes allows us to determine whether or not
an invoke was part of a funclet in the source program.

Furthermore, it allows us to unambiguously answer questions about the
legality of inlining into call sites which the personality may have
trouble with.

Differential Revision: http://reviews.llvm.org/D15517

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@255674 91177308-0d34-0410-b5e6-96231b3b80d8

36 files changed:
docs/LangRef.rst
include/llvm/IR/InstrTypes.h
include/llvm/IR/LLVMContext.h
include/llvm/Transforms/Utils/Local.h
lib/CodeGen/WinEHPrepare.cpp
lib/IR/LLVMContext.cpp
lib/IR/Verifier.cpp
lib/Transforms/Utils/InlineFunction.cpp
lib/Transforms/Utils/Local.cpp
test/CodeGen/WinEH/wineh-cloning.ll
test/CodeGen/WinEH/wineh-demotion.ll
test/CodeGen/WinEH/wineh-no-demotion.ll
test/CodeGen/X86/catchpad-weight.ll
test/CodeGen/X86/cleanuppad-inalloca.ll
test/CodeGen/X86/cleanuppad-large-codemodel.ll
test/CodeGen/X86/cleanuppad-realign.ll
test/CodeGen/X86/funclet-layout.ll
test/CodeGen/X86/seh-catch-all-win32.ll
test/CodeGen/X86/seh-catch-all.ll
test/CodeGen/X86/seh-catchpad.ll
test/CodeGen/X86/seh-except-finally.ll
test/CodeGen/X86/seh-finally.ll
test/CodeGen/X86/seh-safe-div-win32.ll
test/CodeGen/X86/seh-safe-div.ll
test/CodeGen/X86/seh-stack-realign.ll
test/CodeGen/X86/win-catchpad-csrs.ll
test/CodeGen/X86/win-catchpad-nested-cxx.ll
test/CodeGen/X86/win-catchpad-nested.ll
test/CodeGen/X86/win-catchpad.ll
test/CodeGen/X86/win-cleanuppad.ll
test/CodeGen/X86/win-funclet-cfi.ll
test/CodeGen/X86/win32-eh-states.ll
test/CodeGen/X86/win32-seh-catchpad.ll
test/CodeGen/X86/win32-seh-nested-finally.ll
test/CodeGen/X86/wineh-coreclr.ll
test/CodeGen/X86/wineh-exceptionpointer.ll

index 21ca7ec0c30203985ea4945dcf304b5c210edb91..72c0a319dfab26546f6ea55987aa405bbb772ccd 100644 (file)
@@ -1571,6 +1571,15 @@ caller's deoptimization state to the callee's deoptimization state is
 semantically equivalent to composing the caller's deoptimization
 continuation after the callee's deoptimization continuation.
 
 semantically equivalent to composing the caller's deoptimization
 continuation after the callee's deoptimization continuation.
 
+Funclet Operand Bundles
+^^^^^^^^^^^^^^^^^^^^^^^
+
+Funclet operand bundles are characterized by the ``"funclet"``
+operand bundle tag.  These operand bundles indicate that a call site
+is within a particular funclet.  There can be at most one
+``"funclet"`` operand bundle attached to a call site and it must have
+exactly one bundle operand.
+
 .. _moduleasm:
 
 Module-Level Inline Assembly
 .. _moduleasm:
 
 Module-Level Inline Assembly
index 242da30c52f4e823853368d28c9ff4a55ceb5906..5091bb4078336a659a8edab75b5078611f8e759a 100644 (file)
@@ -1219,6 +1219,11 @@ struct OperandBundleUse {
     return getTagID() == LLVMContext::OB_deopt;
   }
 
     return getTagID() == LLVMContext::OB_deopt;
   }
 
+  /// \brief Return true if this is a "funclet" operand bundle.
+  bool isFuncletOperandBundle() const {
+    return getTagID() == LLVMContext::OB_funclet;
+  }
+
 private:
   /// \brief Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag.
   StringMapEntry<uint32_t> *Tag;
 private:
   /// \brief Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag.
   StringMapEntry<uint32_t> *Tag;
@@ -1237,6 +1242,8 @@ template <typename InputTy> class OperandBundleDefT {
 public:
   explicit OperandBundleDefT(std::string Tag, std::vector<InputTy> Inputs)
       : Tag(std::move(Tag)), Inputs(std::move(Inputs)) {}
 public:
   explicit OperandBundleDefT(std::string Tag, std::vector<InputTy> Inputs)
       : Tag(std::move(Tag)), Inputs(std::move(Inputs)) {}
+  explicit OperandBundleDefT(std::string Tag, ArrayRef<InputTy> Inputs)
+      : Tag(std::move(Tag)), Inputs(Inputs) {}
 
   explicit OperandBundleDefT(const OperandBundleUse &OBU) {
     Tag = OBU.getTagName();
 
   explicit OperandBundleDefT(const OperandBundleUse &OBU) {
     Tag = OBU.getTagName();
@@ -1430,11 +1437,12 @@ public:
   /// may write to the heap.
   bool hasClobberingOperandBundles() const {
     for (auto &BOI : bundle_op_infos()) {
   /// may write to the heap.
   bool hasClobberingOperandBundles() const {
     for (auto &BOI : bundle_op_infos()) {
-      if (BOI.Tag->second == LLVMContext::OB_deopt)
+      if (BOI.Tag->second == LLVMContext::OB_deopt ||
+          BOI.Tag->second == LLVMContext::OB_funclet)
         continue;
 
         continue;
 
-      // This instruction has an operand bundle that is not a "deopt" operand
-      // bundle.  Assume the worst.
+      // This instruction has an operand bundle that is not known to us.
+      // Assume the worst.
       return true;
     }
 
       return true;
     }
 
index c00e3052b592d4033bcc61642b20e6cd773a5c68..e99f02420efc78e6067a8b4115cca17047524540 100644 (file)
@@ -72,7 +72,8 @@ public:
   /// Additionally, this scheme allows LLVM to efficiently check for specific
   /// operand bundle tags without comparing strings.
   enum {
   /// Additionally, this scheme allows LLVM to efficiently check for specific
   /// operand bundle tags without comparing strings.
   enum {
-    OB_deopt = 0,  // "deopt"
+    OB_deopt = 0,   // "deopt"
+    OB_funclet = 1, // "funclet"
   };
 
   /// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
   };
 
   /// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
index 81598a3dddf28b48d00f8d1477a4d9c7bb68bca4..81b376f0c212cf445ecd2d8ade9d28a8db4ca3a8 100644 (file)
@@ -288,6 +288,10 @@ bool replaceDbgDeclare(Value *Address, Value *NewAddress,
 bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
                                 DIBuilder &Builder, bool Deref, int Offset = 0);
 
 bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
                                 DIBuilder &Builder, bool Deref, int Offset = 0);
 
+/// \brief Insert an unreachable instruction before the specified
+/// instruction, making it and the rest of the code in the block dead.
+void changeToUnreachable(Instruction *I, bool UseLLVMTrap);
+
 /// Replace 'BB's terminator with one that does not have an unwind successor
 /// block.  Rewrites `invoke` to `call`, etc.  Updates any PHIs in unwind
 /// successor.
 /// Replace 'BB's terminator with one that does not have an unwind successor
 /// block.  Rewrites `invoke` to `call`, etc.  Updates any PHIs in unwind
 /// successor.
index 3ac5d8a7c3bae50797ea6440469dcd3df30969a5..3b076b65e693da4430a967abf353dd228673e1af 100644 (file)
@@ -74,7 +74,7 @@ private:
 
   void demotePHIsOnFunclets(Function &F);
   void cloneCommonBlocks(Function &F);
 
   void demotePHIsOnFunclets(Function &F);
   void cloneCommonBlocks(Function &F);
-  void removeImplausibleTerminators(Function &F);
+  void removeImplausibleInstructions(Function &F);
   void cleanupPreparedFunclets(Function &F);
   void verifyPreparedFunclets(Function &F);
 
   void cleanupPreparedFunclets(Function &F);
   void verifyPreparedFunclets(Function &F);
 
@@ -765,19 +765,56 @@ void WinEHPrepare::cloneCommonBlocks(Function &F) {
   }
 }
 
   }
 }
 
-void WinEHPrepare::removeImplausibleTerminators(Function &F) {
+void WinEHPrepare::removeImplausibleInstructions(Function &F) {
   // Remove implausible terminators and replace them with UnreachableInst.
   for (auto &Funclet : FuncletBlocks) {
     BasicBlock *FuncletPadBB = Funclet.first;
     std::vector<BasicBlock *> &BlocksInFunclet = Funclet.second;
   // Remove implausible terminators and replace them with UnreachableInst.
   for (auto &Funclet : FuncletBlocks) {
     BasicBlock *FuncletPadBB = Funclet.first;
     std::vector<BasicBlock *> &BlocksInFunclet = Funclet.second;
-    Instruction *FuncletPadInst = FuncletPadBB->getFirstNonPHI();
-    auto *CatchPad = dyn_cast<CatchPadInst>(FuncletPadInst);
-    auto *CleanupPad = dyn_cast<CleanupPadInst>(FuncletPadInst);
+    Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
+    auto *FuncletPad = dyn_cast<FuncletPadInst>(FirstNonPHI);
+    auto *CatchPad = dyn_cast_or_null<CatchPadInst>(FuncletPad);
+    auto *CleanupPad = dyn_cast_or_null<CleanupPadInst>(FuncletPad);
 
     for (BasicBlock *BB : BlocksInFunclet) {
 
     for (BasicBlock *BB : BlocksInFunclet) {
+      for (Instruction &I : *BB) {
+        CallSite CS(&I);
+        if (!CS)
+          continue;
+
+        Value *FuncletBundleOperand = nullptr;
+        if (auto BU = CS.getOperandBundle(LLVMContext::OB_funclet))
+          FuncletBundleOperand = BU->Inputs.front();
+
+        if (FuncletBundleOperand == FuncletPad)
+          continue;
+
+        // Skip call sites which are nounwind intrinsics.
+        auto *CalledFn =
+            dyn_cast<Function>(CS.getCalledValue()->stripPointerCasts());
+        if (CalledFn && CalledFn->isIntrinsic() && CS.doesNotThrow())
+          continue;
+
+        // This call site was not part of this funclet, remove it.
+        if (CS.isInvoke()) {
+          // Remove the unwind edge if it was an invoke.
+          removeUnwindEdge(BB);
+          // Get a pointer to the new call.
+          BasicBlock::iterator CallI =
+              std::prev(BB->getTerminator()->getIterator());
+          auto *CI = cast<CallInst>(&*CallI);
+          changeToUnreachable(CI, /*UseLLVMTrap=*/false);
+        } else {
+          changeToUnreachable(&I, /*UseLLVMTrap=*/false);
+        }
+
+        // There are no more instructions in the block (except for unreachable),
+        // we are done.
+        break;
+      }
+
       TerminatorInst *TI = BB->getTerminator();
       // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst.
       TerminatorInst *TI = BB->getTerminator();
       // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst.
-      bool IsUnreachableRet = isa<ReturnInst>(TI) && (CatchPad || CleanupPad);
+      bool IsUnreachableRet = isa<ReturnInst>(TI) && FuncletPad;
       // The token consumed by a CatchReturnInst must match the funclet token.
       bool IsUnreachableCatchret = false;
       if (auto *CRI = dyn_cast<CatchReturnInst>(TI))
       // The token consumed by a CatchReturnInst must match the funclet token.
       bool IsUnreachableCatchret = false;
       if (auto *CRI = dyn_cast<CatchReturnInst>(TI))
@@ -788,19 +825,14 @@ void WinEHPrepare::removeImplausibleTerminators(Function &F) {
         IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
       if (IsUnreachableRet || IsUnreachableCatchret ||
           IsUnreachableCleanupret) {
         IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
       if (IsUnreachableRet || IsUnreachableCatchret ||
           IsUnreachableCleanupret) {
-        // Loop through all of our successors and make sure they know that one
-        // of their predecessors is going away.
-        for (BasicBlock *SuccBB : TI->successors())
-          SuccBB->removePredecessor(BB);
-
-        new UnreachableInst(BB->getContext(), TI);
-        TI->eraseFromParent();
+        changeToUnreachable(TI, /*UseLLVMTrap=*/false);
       } else if (isa<InvokeInst>(TI)) {
       } else if (isa<InvokeInst>(TI)) {
-        // Invokes within a cleanuppad for the MSVC++ personality never
-        // transfer control to their unwind edge: the personality will
-        // terminate the program.
-        if (Personality == EHPersonality::MSVC_CXX && CleanupPad)
+        if (Personality == EHPersonality::MSVC_CXX && CleanupPad) {
+          // Invokes within a cleanuppad for the MSVC++ personality never
+          // transfer control to their unwind edge: the personality will
+          // terminate the program.
           removeUnwindEdge(BB);
           removeUnwindEdge(BB);
+        }
       }
     }
   }
       }
     }
   }
@@ -854,7 +886,7 @@ bool WinEHPrepare::prepareExplicitEH(Function &F) {
     demotePHIsOnFunclets(F);
 
   if (!DisableCleanups) {
     demotePHIsOnFunclets(F);
 
   if (!DisableCleanups) {
-    removeImplausibleTerminators(F);
+    removeImplausibleInstructions(F);
 
     cleanupPreparedFunclets(F);
   }
 
     cleanupPreparedFunclets(F);
   }
index af998c861357121ee5732cdcc3395dd714bda180..8848bcb7147770ea141869fedae0b96dcaa14bcd 100644 (file)
@@ -132,6 +132,11 @@ LLVMContext::LLVMContext() : pImpl(new LLVMContextImpl(*this)) {
   assert(DeoptEntry->second == LLVMContext::OB_deopt &&
          "deopt operand bundle id drifted!");
   (void)DeoptEntry;
   assert(DeoptEntry->second == LLVMContext::OB_deopt &&
          "deopt operand bundle id drifted!");
   (void)DeoptEntry;
+
+  auto *FuncletEntry = pImpl->getOrInsertBundleTag("funclet");
+  assert(FuncletEntry->second == LLVMContext::OB_funclet &&
+         "funclet operand bundle id drifted!");
+  (void)FuncletEntry;
 }
 LLVMContext::~LLVMContext() { delete pImpl; }
 
 }
 LLVMContext::~LLVMContext() { delete pImpl; }
 
index 234ab29d8ed1e5f4012022c94928b8fe40a84a95..32646cf79996f9ed7178e7e8d039ab841d4a8d03 100644 (file)
@@ -2381,13 +2381,25 @@ void Verifier::VerifyCallSite(CallSite CS) {
     if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
       visitIntrinsicCallSite(ID, CS);
 
     if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
       visitIntrinsicCallSite(ID, CS);
 
-  // Verify that a callsite has at most one "deopt" operand bundle.
-  bool FoundDeoptBundle = false;
+  // Verify that a callsite has at most one "deopt" and one "funclet" operand
+  // bundle.
+  bool FoundDeoptBundle = false, FoundFuncletBundle = false;
   for (unsigned i = 0, e = CS.getNumOperandBundles(); i < e; ++i) {
   for (unsigned i = 0, e = CS.getNumOperandBundles(); i < e; ++i) {
-    if (CS.getOperandBundleAt(i).getTagID() == LLVMContext::OB_deopt) {
+    OperandBundleUse BU = CS.getOperandBundleAt(i);
+    uint32_t Tag = BU.getTagID();
+    if (Tag == LLVMContext::OB_deopt) {
       Assert(!FoundDeoptBundle, "Multiple deopt operand bundles", I);
       FoundDeoptBundle = true;
     }
       Assert(!FoundDeoptBundle, "Multiple deopt operand bundles", I);
       FoundDeoptBundle = true;
     }
+    if (Tag == LLVMContext::OB_funclet) {
+      Assert(!FoundFuncletBundle, "Multiple funclet operand bundles", I);
+      FoundFuncletBundle = true;
+      Assert(BU.Inputs.size() == 1,
+             "Expected exactly one funclet bundle operand", I);
+      Assert(isa<FuncletPadInst>(BU.Inputs.front()),
+             "Funclet bundle operands should correspond to a FuncletPadInst",
+             I);
+    }
   }
 
   visitInstruction(*I);
   }
 
   visitInstruction(*I);
@@ -3002,6 +3014,8 @@ void Verifier::visitCleanupPadInst(CleanupPadInst &CPI) {
       UnwindDest = CRI->getUnwindDest();
     } else if (isa<CleanupPadInst>(U) || isa<CatchSwitchInst>(U)) {
       continue;
       UnwindDest = CRI->getUnwindDest();
     } else if (isa<CleanupPadInst>(U) || isa<CatchSwitchInst>(U)) {
       continue;
+    } else if (CallSite(U)) {
+      continue;
     } else {
       Assert(false, "bogus cleanuppad use", &CPI);
     }
     } else {
       Assert(false, "bogus cleanuppad use", &CPI);
     }
index b0d99a8e830a5ce821e5a9412b7affe6c11a7d8e..db2cacd4739ed272fe394f76376eaf7dddb5033a 100644 (file)
@@ -1035,12 +1035,17 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
   // The inliner does not know how to inline through calls with operand bundles
   // in general ...
   if (CS.hasOperandBundles()) {
   // The inliner does not know how to inline through calls with operand bundles
   // in general ...
   if (CS.hasOperandBundles()) {
-    // ... but it knows how to inline through "deopt" operand bundles.
-    bool CanInline =
-        CS.getNumOperandBundles() == 1 &&
-        CS.getOperandBundleAt(0).getTagID() == LLVMContext::OB_deopt;
-    if (!CanInline)
+    for (int i = 0, e = CS.getNumOperandBundles(); i != e; ++i) {
+      uint32_t Tag = CS.getOperandBundleAt(i).getTagID();
+      // ... but it knows how to inline through "deopt" operand bundles ...
+      if (Tag == LLVMContext::OB_deopt)
+        continue;
+      // ... and "funclet" operand bundles.
+      if (Tag == LLVMContext::OB_funclet)
+        continue;
+
       return false;
       return false;
+    }
   }
 
   // If the call to the callee cannot throw, set the 'nounwind' flag on any
   }
 
   // If the call to the callee cannot throw, set the 'nounwind' flag on any
@@ -1088,23 +1093,13 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
   // We need to figure out which funclet the callsite was in so that we may
   // properly nest the callee.
   Instruction *CallSiteEHPad = nullptr;
   // We need to figure out which funclet the callsite was in so that we may
   // properly nest the callee.
   Instruction *CallSiteEHPad = nullptr;
-  if (CalledPersonality && CallerPersonality) {
-    EHPersonality Personality = classifyEHPersonality(CalledPersonality);
+  if (CallerPersonality) {
+    EHPersonality Personality = classifyEHPersonality(CallerPersonality);
     if (isFuncletEHPersonality(Personality)) {
     if (isFuncletEHPersonality(Personality)) {
-      DenseMap<BasicBlock *, ColorVector> CallerBlockColors =
-          colorEHFunclets(*Caller);
-      ColorVector &CallSiteColors = CallerBlockColors[OrigBB];
-      size_t NumColors = CallSiteColors.size();
-      // There is no single parent, inlining will not succeed.
-      if (NumColors > 1)
-        return false;
-      if (NumColors == 1) {
-        BasicBlock *CallSiteFuncletBB = CallSiteColors.front();
-        if (CallSiteFuncletBB != Caller->begin()) {
-          CallSiteEHPad = CallSiteFuncletBB->getFirstNonPHI();
-          assert(CallSiteEHPad->isEHPad() && "Expected an EHPad!");
-        }
-      }
+      Optional<OperandBundleUse> ParentFunclet =
+          CS.getOperandBundle(LLVMContext::OB_funclet);
+      if (ParentFunclet)
+        CallSiteEHPad = cast<FuncletPadInst>(ParentFunclet->Inputs.front());
 
       // OK, the inlining site is legal.  What about the target function?
 
 
       // OK, the inlining site is legal.  What about the target function?
 
@@ -1116,7 +1111,7 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
             // Ok, the call site is within a cleanuppad.  Let's check the callee
             // for catchpads.
             for (const BasicBlock &CalledBB : *CalledFunc) {
             // Ok, the call site is within a cleanuppad.  Let's check the callee
             // for catchpads.
             for (const BasicBlock &CalledBB : *CalledFunc) {
-              if (isa<CatchPadInst>(CalledBB.getFirstNonPHI()))
+              if (isa<CatchSwitchInst>(CalledBB.getFirstNonPHI()))
                 return false;
             }
           }
                 return false;
             }
           }
@@ -1195,11 +1190,9 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
       HandleByValArgumentInit(Init.first, Init.second, Caller->getParent(),
                               &*FirstNewBlock, IFI);
 
       HandleByValArgumentInit(Init.first, Init.second, Caller->getParent(),
                               &*FirstNewBlock, IFI);
 
-    if (CS.hasOperandBundles()) {
-      auto ParentDeopt = CS.getOperandBundleAt(0);
-      assert(ParentDeopt.getTagID() == LLVMContext::OB_deopt &&
-             "Checked on entry!");
-
+    Optional<OperandBundleUse> ParentDeopt =
+        CS.getOperandBundle(LLVMContext::OB_deopt);
+    if (ParentDeopt) {
       SmallVector<OperandBundleDef, 2> OpDefs;
 
       for (auto &VH : InlinedFunctionInfo.OperandBundleCallSites) {
       SmallVector<OperandBundleDef, 2> OpDefs;
 
       for (auto &VH : InlinedFunctionInfo.OperandBundleCallSites) {
@@ -1225,12 +1218,12 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
           // Prepend the parent's deoptimization continuation to the newly
           // inlined call's deoptimization continuation.
           std::vector<Value *> MergedDeoptArgs;
           // Prepend the parent's deoptimization continuation to the newly
           // inlined call's deoptimization continuation.
           std::vector<Value *> MergedDeoptArgs;
-          MergedDeoptArgs.reserve(ParentDeopt.Inputs.size() +
+          MergedDeoptArgs.reserve(ParentDeopt->Inputs.size() +
                                   ChildOB.Inputs.size());
 
           MergedDeoptArgs.insert(MergedDeoptArgs.end(),
                                   ChildOB.Inputs.size());
 
           MergedDeoptArgs.insert(MergedDeoptArgs.end(),
-                                 ParentDeopt.Inputs.begin(),
-                                 ParentDeopt.Inputs.end());
+                                 ParentDeopt->Inputs.begin(),
+                                 ParentDeopt->Inputs.end());
           MergedDeoptArgs.insert(MergedDeoptArgs.end(), ChildOB.Inputs.begin(),
                                  ChildOB.Inputs.end());
 
           MergedDeoptArgs.insert(MergedDeoptArgs.end(), ChildOB.Inputs.begin(),
                                  ChildOB.Inputs.end());
 
@@ -1423,12 +1416,48 @@ bool llvm::InlineFunction(CallSite CS, InlineFunctionInfo &IFI,
     }
   }
 
     }
   }
 
-  // Update the lexical scopes of the new funclets.  Anything that had 'none' as
-  // its parent is now nested inside the callsite's EHPad.
+  // Update the lexical scopes of the new funclets and callsites.
+  // Anything that had 'none' as its parent is now nested inside the callsite's
+  // EHPad.
+
   if (CallSiteEHPad) {
     for (Function::iterator BB = FirstNewBlock->getIterator(),
                             E = Caller->end();
          BB != E; ++BB) {
   if (CallSiteEHPad) {
     for (Function::iterator BB = FirstNewBlock->getIterator(),
                             E = Caller->end();
          BB != E; ++BB) {
+      // Add bundle operands to any top-level call sites.
+      SmallVector<OperandBundleDef, 1> OpBundles;
+      for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E;) {
+        Instruction *I = &*BBI++;
+        CallSite CS(I);
+        if (!CS)
+          continue;
+
+        // Skip call sites which are nounwind intrinsics.
+        auto *CalledFn =
+            dyn_cast<Function>(CS.getCalledValue()->stripPointerCasts());
+        if (CalledFn && CalledFn->isIntrinsic() && CS.doesNotThrow())
+          continue;
+
+        // Skip call sites which already have a "funclet" bundle.
+        if (CS.getOperandBundle(LLVMContext::OB_funclet))
+          continue;
+
+        CS.getOperandBundlesAsDefs(OpBundles);
+        OpBundles.emplace_back("funclet", CallSiteEHPad);
+
+        Instruction *NewInst;
+        if (CS.isCall())
+          NewInst = CallInst::Create(cast<CallInst>(I), OpBundles, I);
+        else
+          NewInst = InvokeInst::Create(cast<InvokeInst>(I), OpBundles, I);
+        NewInst->setDebugLoc(I->getDebugLoc());
+        NewInst->takeName(I);
+        I->replaceAllUsesWith(NewInst);
+        I->eraseFromParent();
+
+        OpBundles.clear();
+      }
+
       Instruction *I = BB->getFirstNonPHI();
       if (!I->isEHPad())
         continue;
       Instruction *I = BB->getFirstNonPHI();
       if (!I->isEHPad())
         continue;
index 24f88179c9036d6e472b74549d3fdc582ccf6cfb..31039816e14a957d3d41ce6dd7cbb0eb5b3202f8 100644 (file)
@@ -1180,9 +1180,7 @@ bool llvm::replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
                            Deref, Offset);
 }
 
                            Deref, Offset);
 }
 
-/// changeToUnreachable - Insert an unreachable instruction before the specified
-/// instruction, making it and the rest of the code in the block dead.
-static void changeToUnreachable(Instruction *I, bool UseLLVMTrap) {
+void llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap) {
   BasicBlock *BB = I->getParent();
   // Loop over all of the successors, removing BB's entry from any PHI
   // nodes.
   BasicBlock *BB = I->getParent();
   // Loop over all of the successors, removing BB's entry from any PHI
   // nodes.
index 66a9132980fcbf1f22a47b46d81015f811d35097..c13e0a163641e9c261fa943db8ba12d350e81cc4 100644 (file)
@@ -4,25 +4,26 @@ declare i32 @__CxxFrameHandler3(...)
 declare i32 @__C_specific_handler(...)
 
 declare void @f()
 declare i32 @__C_specific_handler(...)
 
 declare void @f()
-declare i32 @g()
-declare void @h(i32)
-declare i1 @b()
 
 
+declare void @llvm.foo(i32) nounwind
+declare void @llvm.bar() nounwind
+declare i32 @llvm.qux() nounwind
+declare i1 @llvm.baz() nounwind
 
 define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
 entry:
   ; %x def colors: {entry} subset of use colors; must spill
 
 define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
 entry:
   ; %x def colors: {entry} subset of use colors; must spill
-  %x = call i32 @g()
+  %x = call i32 @llvm.qux()
   invoke void @f()
     to label %noreturn unwind label %catch.switch
 catch.switch:
   %cs = catchswitch within none [label %catch] unwind to caller
 catch:
   invoke void @f()
     to label %noreturn unwind label %catch.switch
 catch.switch:
   %cs = catchswitch within none [label %catch] unwind to caller
 catch:
-  catchpad within %cs []
+  %cp = catchpad within %cs []
   br label %noreturn
 noreturn:
   ; %x use colors: {entry, cleanup}
   br label %noreturn
 noreturn:
   ; %x use colors: {entry, cleanup}
-  call void @h(i32 %x)
+  call void @llvm.foo(i32 %x)
   unreachable
 }
 ; Need two copies of the call to @h, one under entry and one under catch.
   unreachable
 }
 ; Need two copies of the call to @h, one under entry and one under catch.
@@ -30,16 +31,16 @@ noreturn:
 ; for the use in entry's copy.
 ; CHECK-LABEL: define void @test1(
 ; CHECK: entry:
 ; for the use in entry's copy.
 ; CHECK-LABEL: define void @test1(
 ; CHECK: entry:
-; CHECK:   %x = call i32 @g()
+; CHECK:   %x = call i32 @llvm.qux()
 ; CHECK:   invoke void @f()
 ; CHECK:     to label %[[EntryCopy:[^ ]+]] unwind label %catch
 ; CHECK: catch.switch:
 ; CHECK:   %cs = catchswitch within none [label %catch] unwind to caller
 ; CHECK: catch:
 ; CHECK:   catchpad within %cs []
 ; CHECK:   invoke void @f()
 ; CHECK:     to label %[[EntryCopy:[^ ]+]] unwind label %catch
 ; CHECK: catch.switch:
 ; CHECK:   %cs = catchswitch within none [label %catch] unwind to caller
 ; CHECK: catch:
 ; CHECK:   catchpad within %cs []
-; CHECK-NEXT: call void @h(i32 %x)
+; CHECK-NEXT: call void @llvm.foo(i32 %x)
 ; CHECK: [[EntryCopy]]:
 ; CHECK: [[EntryCopy]]:
-; CHECK:   call void @h(i32 %x)
+; CHECK:   call void @llvm.foo(i32 %x)
 
 
 define void @test2() personality i32 (...)* @__CxxFrameHandler3 {
 
 
 define void @test2() personality i32 (...)* @__CxxFrameHandler3 {
@@ -50,7 +51,7 @@ cleanup:
   cleanuppad within none []
   br label %exit
 exit:
   cleanuppad within none []
   br label %exit
 exit:
-  call void @f()
+  call void @llvm.bar()
   ret void
 }
 ; Need two copies of %exit's call to @f -- the subsequent ret is only
   ret void
 }
 ; Need two copies of %exit's call to @f -- the subsequent ret is only
@@ -62,10 +63,10 @@ exit:
 ; CHECK:     to label %[[exit:[^ ]+]] unwind label %cleanup
 ; CHECK: cleanup:
 ; CHECK:   cleanuppad within none []
 ; CHECK:     to label %[[exit:[^ ]+]] unwind label %cleanup
 ; CHECK: cleanup:
 ; CHECK:   cleanuppad within none []
-; CHECK:   call void @f()
+; CHECK:   call void @llvm.bar()
 ; CHECK-NEXT: unreachable
 ; CHECK: [[exit]]:
 ; CHECK-NEXT: unreachable
 ; CHECK: [[exit]]:
-; CHECK:   call void @f()
+; CHECK:   call void @llvm.bar()
 ; CHECK-NEXT: ret void
 
 
 ; CHECK-NEXT: ret void
 
 
@@ -85,7 +86,7 @@ cleanup:
   cleanuppad within none []
   br label %shared
 shared:
   cleanuppad within none []
   br label %shared
 shared:
-  call void @f()
+  call void @llvm.bar()
   br label %exit
 exit:
   ret void
   br label %exit
 exit:
   ret void
@@ -98,11 +99,11 @@ exit:
 ; CHECK:     to label %[[exit:[^ ]+]] unwind
 ; CHECK: catch:
 ; CHECK:   catchpad within %cs []
 ; CHECK:     to label %[[exit:[^ ]+]] unwind
 ; CHECK: catch:
 ; CHECK:   catchpad within %cs []
-; CHECK-NEXT: call void @f()
+; CHECK-NEXT: call void @llvm.bar()
 ; CHECK-NEXT: unreachable
 ; CHECK: cleanup:
 ; CHECK:   cleanuppad within none []
 ; CHECK-NEXT: unreachable
 ; CHECK: cleanup:
 ; CHECK:   cleanuppad within none []
-; CHECK:   call void @f()
+; CHECK:   call void @llvm.bar()
 ; CHECK-NEXT: unreachable
 ; CHECK: [[exit]]:
 ; CHECK:   ret void
 ; CHECK-NEXT: unreachable
 ; CHECK: [[exit]]:
 ; CHECK:   ret void
@@ -118,26 +119,26 @@ catch:
   catchpad within %cs []
   br label %shared
 shared:
   catchpad within %cs []
   br label %shared
 shared:
-  %x = call i32 @g()
-  %i = call i32 @g()
+  %x = call i32 @llvm.qux()
+  %i = call i32 @llvm.qux()
   %zero.trip = icmp eq i32 %i, 0
   br i1 %zero.trip, label %exit, label %loop
 loop:
   %i.loop = phi i32 [ %i, %shared ], [ %i.dec, %loop.tail ]
   %zero.trip = icmp eq i32 %i, 0
   br i1 %zero.trip, label %exit, label %loop
 loop:
   %i.loop = phi i32 [ %i, %shared ], [ %i.dec, %loop.tail ]
-  %b = call i1 @b()
+  %b = call i1 @llvm.baz()
   br i1 %b, label %left, label %right
 left:
   br i1 %b, label %left, label %right
 left:
-  %y = call i32 @g()
+  %y = call i32 @llvm.qux()
   br label %loop.tail
 right:
   br label %loop.tail
 right:
-  call void @h(i32 %x)
+  call void @llvm.foo(i32 %x)
   br label %loop.tail
 loop.tail:
   %i.dec = sub i32 %i.loop, 1
   %done = icmp eq i32 %i.dec, 0
   br i1 %done, label %exit, label %loop
 exit:
   br label %loop.tail
 loop.tail:
   %i.dec = sub i32 %i.loop, 1
   %done = icmp eq i32 %i.dec, 0
   br i1 %done, label %exit, label %loop
 exit:
-  call void @h(i32 %x)
+  call void @llvm.foo(i32 %x)
   unreachable
 }
 ; Make sure we can clone regions that have internal control
   unreachable
 }
 ; Make sure we can clone regions that have internal control
@@ -148,34 +149,34 @@ exit:
 ; CHECK:    to label %[[shared_E:[^ ]+]] unwind label %catch.switch
 ; CHECK:  catch:
 ; CHECK:    catchpad within %cs []
 ; CHECK:    to label %[[shared_E:[^ ]+]] unwind label %catch.switch
 ; CHECK:  catch:
 ; CHECK:    catchpad within %cs []
-; CHECK:    [[x_C:%[^ ]+]] = call i32 @g()
-; CHECK:    [[i_C:%[^ ]+]] = call i32 @g()
+; CHECK:    [[x_C:%[^ ]+]] = call i32 @llvm.qux()
+; CHECK:    [[i_C:%[^ ]+]] = call i32 @llvm.qux()
 ; CHECK:    [[zt_C:%[^ ]+]] = icmp eq i32 [[i_C]], 0
 ; CHECK:    br i1 [[zt_C]], label %[[exit_C:[^ ]+]], label %[[loop_C:[^ ]+]]
 ; CHECK:  [[shared_E]]:
 ; CHECK:    [[zt_C:%[^ ]+]] = icmp eq i32 [[i_C]], 0
 ; CHECK:    br i1 [[zt_C]], label %[[exit_C:[^ ]+]], label %[[loop_C:[^ ]+]]
 ; CHECK:  [[shared_E]]:
-; CHECK:    [[x_E:%[^ ]+]] = call i32 @g()
-; CHECK:    [[i_E:%[^ ]+]] = call i32 @g()
+; CHECK:    [[x_E:%[^ ]+]] = call i32 @llvm.qux()
+; CHECK:    [[i_E:%[^ ]+]] = call i32 @llvm.qux()
 ; CHECK:    [[zt_E:%[^ ]+]] = icmp eq i32 [[i_E]], 0
 ; CHECK:    br i1 [[zt_E]], label %[[exit_E:[^ ]+]], label %[[loop_E:[^ ]+]]
 ; CHECK:  [[loop_C]]:
 ; CHECK:    [[iloop_C:%[^ ]+]] = phi i32 [ [[i_C]], %catch ], [ [[idec_C:%[^ ]+]], %[[looptail_C:[^ ]+]] ]
 ; CHECK:    [[zt_E:%[^ ]+]] = icmp eq i32 [[i_E]], 0
 ; CHECK:    br i1 [[zt_E]], label %[[exit_E:[^ ]+]], label %[[loop_E:[^ ]+]]
 ; CHECK:  [[loop_C]]:
 ; CHECK:    [[iloop_C:%[^ ]+]] = phi i32 [ [[i_C]], %catch ], [ [[idec_C:%[^ ]+]], %[[looptail_C:[^ ]+]] ]
-; CHECK:    [[b_C:%[^ ]+]] = call i1 @b()
+; CHECK:    [[b_C:%[^ ]+]] = call i1 @llvm.baz()
 ; CHECK:    br i1 [[b_C]], label %[[left_C:[^ ]+]], label %[[right_C:[^ ]+]]
 ; CHECK:  [[loop_E]]:
 ; CHECK:    [[iloop_E:%[^ ]+]] = phi i32 [ [[i_E]], %[[shared_E]] ], [ [[idec_E:%[^ ]+]], %[[looptail_E:[^ ]+]] ]
 ; CHECK:    br i1 [[b_C]], label %[[left_C:[^ ]+]], label %[[right_C:[^ ]+]]
 ; CHECK:  [[loop_E]]:
 ; CHECK:    [[iloop_E:%[^ ]+]] = phi i32 [ [[i_E]], %[[shared_E]] ], [ [[idec_E:%[^ ]+]], %[[looptail_E:[^ ]+]] ]
-; CHECK:    [[b_E:%[^ ]+]] = call i1 @b()
+; CHECK:    [[b_E:%[^ ]+]] = call i1 @llvm.baz()
 ; CHECK:    br i1 [[b_E]], label %[[left_E:[^ ]+]], label %[[right_E:[^ ]+]]
 ; CHECK:  [[left_C]]:
 ; CHECK:    br i1 [[b_E]], label %[[left_E:[^ ]+]], label %[[right_E:[^ ]+]]
 ; CHECK:  [[left_C]]:
-; CHECK:    [[y_C:%[^ ]+]] = call i32 @g()
+; CHECK:    [[y_C:%[^ ]+]] = call i32 @llvm.qux()
 ; CHECK:    br label %[[looptail_C]]
 ; CHECK:  [[left_E]]:
 ; CHECK:    br label %[[looptail_C]]
 ; CHECK:  [[left_E]]:
-; CHECK:    [[y_E:%[^ ]+]] = call i32 @g()
+; CHECK:    [[y_E:%[^ ]+]] = call i32 @llvm.qux()
 ; CHECK:    br label %[[looptail_E]]
 ; CHECK:  [[right_C]]:
 ; CHECK:    br label %[[looptail_E]]
 ; CHECK:  [[right_C]]:
-; CHECK:    call void @h(i32 [[x_C]])
+; CHECK:    call void @llvm.foo(i32 [[x_C]])
 ; CHECK:    br label %[[looptail_C]]
 ; CHECK:  [[right_E]]:
 ; CHECK:    br label %[[looptail_C]]
 ; CHECK:  [[right_E]]:
-; CHECK:    call void @h(i32 [[x_E]])
+; CHECK:    call void @llvm.foo(i32 [[x_E]])
 ; CHECK:    br label %[[looptail_E]]
 ; CHECK:  [[looptail_C]]:
 ; CHECK:    [[idec_C]] = sub i32 [[iloop_C]], 1
 ; CHECK:    br label %[[looptail_E]]
 ; CHECK:  [[looptail_C]]:
 ; CHECK:    [[idec_C]] = sub i32 [[iloop_C]], 1
@@ -186,10 +187,10 @@ exit:
 ; CHECK:    [[done_E:%[^ ]+]] = icmp eq i32 [[idec_E]], 0
 ; CHECK:    br i1 [[done_E]], label %[[exit_E]], label %[[loop_E]]
 ; CHECK:  [[exit_C]]:
 ; CHECK:    [[done_E:%[^ ]+]] = icmp eq i32 [[idec_E]], 0
 ; CHECK:    br i1 [[done_E]], label %[[exit_E]], label %[[loop_E]]
 ; CHECK:  [[exit_C]]:
-; CHECK:    call void @h(i32 [[x_C]])
+; CHECK:    call void @llvm.foo(i32 [[x_C]])
 ; CHECK:    unreachable
 ; CHECK:  [[exit_E]]:
 ; CHECK:    unreachable
 ; CHECK:  [[exit_E]]:
-; CHECK:    call void @h(i32 [[x_E]])
+; CHECK:    call void @llvm.foo(i32 [[x_E]])
 ; CHECK:    unreachable
 
 
 ; CHECK:    unreachable
 
 
@@ -199,8 +200,8 @@ entry:
     to label %exit unwind label %outer
 outer:
   %o = cleanuppad within none []
     to label %exit unwind label %outer
 outer:
   %o = cleanuppad within none []
-  %x = call i32 @g()
-  invoke void @f()
+  %x = call i32 @llvm.qux()
+  invoke void @f() [ "funclet"(token %o) ]
     to label %outer.ret unwind label %catch.switch
 catch.switch:
   %cs = catchswitch within %o [label %inner] unwind to caller
     to label %outer.ret unwind label %catch.switch
 catch.switch:
   %cs = catchswitch within %o [label %inner] unwind to caller
@@ -208,7 +209,7 @@ inner:
   %i = catchpad within %cs []
   catchret from %i to label %outer.post-inner
 outer.post-inner:
   %i = catchpad within %cs []
   catchret from %i to label %outer.post-inner
 outer.post-inner:
-  call void @h(i32 %x)
+  call void @llvm.foo(i32 %x)
   br label %outer.ret
 outer.ret:
   cleanupret from %o unwind to caller
   br label %outer.ret
 outer.ret:
   cleanupret from %o unwind to caller
@@ -220,64 +221,17 @@ exit:
 ; and so don't need to be spilled.
 ; CHECK-LABEL: define void @test5(
 ; CHECK:      outer:
 ; and so don't need to be spilled.
 ; CHECK-LABEL: define void @test5(
 ; CHECK:      outer:
-; CHECK:        %x = call i32 @g()
+; CHECK:        %x = call i32 @llvm.qux()
 ; CHECK-NEXT:   invoke void @f()
 ; CHECK-NEXT:     to label %outer.ret unwind label %catch.switch
 ; CHECK:      inner:
 ; CHECK-NEXT:   %i = catchpad within %cs []
 ; CHECK-NEXT:   catchret from %i to label %outer.post-inner
 ; CHECK:      outer.post-inner:
 ; CHECK-NEXT:   invoke void @f()
 ; CHECK-NEXT:     to label %outer.ret unwind label %catch.switch
 ; CHECK:      inner:
 ; CHECK-NEXT:   %i = catchpad within %cs []
 ; CHECK-NEXT:   catchret from %i to label %outer.post-inner
 ; CHECK:      outer.post-inner:
-; CHECK-NEXT:   call void @h(i32 %x)
+; CHECK-NEXT:   call void @llvm.foo(i32 %x)
 ; CHECK-NEXT:   br label %outer.ret
 
 
 ; CHECK-NEXT:   br label %outer.ret
 
 
-define void @test6() personality i32 (...)* @__C_specific_handler {
-entry:
-  invoke void @f()
-    to label %invoke.cont unwind label %left
-invoke.cont:
-  invoke void @f()
-    to label %exit unwind label %right
-left:
-  cleanuppad within none []
-  br label %shared
-right:
-  %cs = catchswitch within none [label %right.catch] unwind to caller
-right.catch:
-  catchpad within %cs []
-  br label %shared
-shared:
-  %x = call i32 @g()
-  invoke void @f()
-    to label %shared.cont unwind label %inner
-shared.cont:
-  unreachable
-inner:
-  %i = cleanuppad within none []
-  call void @h(i32 %x)
-  cleanupret from %i unwind to caller
-exit:
-  ret void
-}
-; CHECK-LABEL: define void @test6(
-; CHECK:     left:
-; CHECK:       %x.for.left = call i32 @g()
-; CHECK:       invoke void @f()
-; CHECK:           to label %shared.cont.for.left unwind label %inner
-; CHECK:     right.catch:
-; CHECK:       catchpad
-; CHECK:       %x = call i32 @g()
-; CHECK:           to label %shared.cont unwind label %inner
-; CHECK:     shared.cont:
-; CHECK:       unreachable
-; CHECK:     shared.cont.for.left:
-; CHECK:       unreachable
-; CHECK:     inner:
-; CHECK:       %i = cleanuppad within none []
-; CHECK:       call void @h(i32 %x1.wineh.reload)
-; CHECK:       cleanupret from %i unwind to caller
-
-
 define void @test9() personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
 define void @test9() personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
@@ -286,14 +240,14 @@ invoke.cont:
   invoke void @f()
     to label %unreachable unwind label %right
 left:
   invoke void @f()
     to label %unreachable unwind label %right
 left:
-  cleanuppad within none []
-  call void @h(i32 1)
-  invoke void @f()
+  %cp.left = cleanuppad within none []
+  call void @llvm.foo(i32 1)
+  invoke void @f() [ "funclet"(token %cp.left) ]
     to label %unreachable unwind label %right
 right:
     to label %unreachable unwind label %right
 right:
-  cleanuppad within none []
-  call void @h(i32 2)
-  invoke void @f()
+  %cp.right = cleanuppad within none []
+  call void @llvm.foo(i32 2)
+  invoke void @f() [ "funclet"(token %cp.right) ]
     to label %unreachable unwind label %left
 unreachable:
   unreachable
     to label %unreachable unwind label %left
 unreachable:
   unreachable
@@ -305,11 +259,11 @@ unreachable:
 ; CHECK:     invoke.cont:
 ; CHECK:               to label %[[UNREACHABLE_ENTRY:.+]] unwind label %[[RIGHT:.+]]
 ; CHECK:     [[LEFT]]:
 ; CHECK:     invoke.cont:
 ; CHECK:               to label %[[UNREACHABLE_ENTRY:.+]] unwind label %[[RIGHT:.+]]
 ; CHECK:     [[LEFT]]:
-; CHECK:       call void @h(i32 1)
+; CHECK:       call void @llvm.foo(i32 1)
 ; CHECK:       invoke void @f()
 ; CHECK:               to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[RIGHT]]
 ; CHECK:     [[RIGHT]]:
 ; CHECK:       invoke void @f()
 ; CHECK:               to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[RIGHT]]
 ; CHECK:     [[RIGHT]]:
-; CHECK:       call void @h(i32 2)
+; CHECK:       call void @llvm.foo(i32 2)
 ; CHECK:       invoke void @f()
 ; CHECK:               to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[LEFT]]
 ; CHECK:     [[UNREACHABLE_RIGHT]]:
 ; CHECK:       invoke void @f()
 ; CHECK:               to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[LEFT]]
 ; CHECK:     [[UNREACHABLE_RIGHT]]:
@@ -361,7 +315,7 @@ entry:
     to label %exit unwind label %cleanup.outer
 cleanup.outer:
   %outer = cleanuppad within none []
     to label %exit unwind label %cleanup.outer
 cleanup.outer:
   %outer = cleanuppad within none []
-  invoke void @f()
+  invoke void @f() [ "funclet"(token %outer) ]
     to label %outer.cont unwind label %cleanup.inner
 outer.cont:
   br label %merge
     to label %outer.cont unwind label %cleanup.inner
 outer.cont:
   br label %merge
@@ -369,7 +323,7 @@ cleanup.inner:
   %inner = cleanuppad within %outer []
   br label %merge
 merge:
   %inner = cleanuppad within %outer []
   br label %merge
 merge:
-  call void @f()
+  call void @llvm.bar()
   unreachable
 exit:
   ret void
   unreachable
 exit:
   ret void
@@ -379,7 +333,7 @@ exit:
 ; rewritten to call @f()
 ; CHECK-LABEL: define void @test11()
 ; CHECK:      %inner = cleanuppad within %outer []
 ; rewritten to call @f()
 ; CHECK-LABEL: define void @test11()
 ; CHECK:      %inner = cleanuppad within %outer []
-; CHECK-NEXT: call void @f()
+; CHECK-NEXT: call void @llvm.bar()
 ; CHECK-NEXT: unreachable
 
 define void @test12() personality i32 (...)* @__CxxFrameHandler3 !dbg !5 {
 ; CHECK-NEXT: unreachable
 
 define void @test12() personality i32 (...)* @__CxxFrameHandler3 !dbg !5 {
@@ -398,7 +352,7 @@ right:
 join:
   ; This call will get cloned; make sure we can handle cloning
   ; instructions with debug metadata attached.
 join:
   ; This call will get cloned; make sure we can handle cloning
   ; instructions with debug metadata attached.
-  call void @f(), !dbg !9
+  call void @llvm.bar(), !dbg !9
   unreachable
 exit:
   ret void
   unreachable
 exit:
   ret void
index bd239133ea878388c8f64858fd06b70089298cf4..411952d84bb6ce3ff3c077641f55e0c0092fc5b8 100644 (file)
@@ -10,6 +10,8 @@ declare void @h(i32)
 
 declare i1 @i()
 
 
 declare i1 @i()
 
+declare void @llvm.bar() nounwind
+
 ; CHECK-LABEL: @test1(
 define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
 entry:
 ; CHECK-LABEL: @test1(
 define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
 entry:
@@ -43,7 +45,7 @@ catch:
   ; CHECK: catch:
   ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
   ; CHECK-NEXT: call void @h(i32 [[Reload]])
   ; CHECK: catch:
   ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
   ; CHECK-NEXT: call void @h(i32 [[Reload]])
-  call void @h(i32 %phi)
+  call void @h(i32 %phi) [ "funclet"(token %cp) ]
   catchret from %cp to label %exit
 
 exit:
   catchret from %cp to label %exit
 
 exit:
@@ -81,10 +83,10 @@ catch.inner:
   %cpinner = catchpad within %cs1 []
   ; Need just one store here because only %y is affected
   ; CHECK: catch.inner:
   %cpinner = catchpad within %cs1 []
   ; Need just one store here because only %y is affected
   ; CHECK: catch.inner:
-  %z = call i32 @g()
+  %z = call i32 @g() [ "funclet"(token %cpinner) ]
   ; CHECK:   store i32 %z
   ; CHECK-NEXT: invoke void @f
   ; CHECK:   store i32 %z
   ; CHECK-NEXT: invoke void @f
-  invoke void @f()
+  invoke void @f() [ "funclet"(token %cpinner) ]
           to label %catchret.inner unwind label %merge.outer
 
 catchret.inner:
           to label %catchret.inner unwind label %merge.outer
 
 catchret.inner:
@@ -106,8 +108,8 @@ catch.outer:
   ; CHECK-DAG: load i32, i32* [[Slot1]]
   ; CHECK-DAG: load i32, i32* [[Slot2]]
   ; CHECK: catchret from [[CatchPad]] to label
   ; CHECK-DAG: load i32, i32* [[Slot1]]
   ; CHECK-DAG: load i32, i32* [[Slot2]]
   ; CHECK: catchret from [[CatchPad]] to label
-  call void @h(i32 %x)
-  call void @h(i32 %y)
+  call void @h(i32 %x) [ "funclet"(token %cpouter) ]
+  call void @h(i32 %y) [ "funclet"(token %cpouter) ]
   catchret from %cpouter to label %exit
 
 exit:
   catchret from %cpouter to label %exit
 
 exit:
@@ -166,7 +168,7 @@ catch.outer:
    ; CHECK:   [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
    ; CHECK:   call void @h(i32 [[Reload]])
    %cp2 = catchpad within %cs2 []
    ; CHECK:   [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
    ; CHECK:   call void @h(i32 [[Reload]])
    %cp2 = catchpad within %cs2 []
-   call void @h(i32 %phi.outer)
+   call void @h(i32 %phi.outer) [ "funclet"(token %cp2) ]
    catchret from %cp2 to label %exit
 exit:
    ret void
    catchret from %cp2 to label %exit
 exit:
    ret void
@@ -197,19 +199,19 @@ cleanup:
   ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
   %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
   %cp = cleanuppad within none []
   ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
   %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
   %cp = cleanuppad within none []
-  %b = call i1 @i()
+  %b = call i1 @i() [ "funclet"(token %cp) ]
   br i1 %b, label %left, label %right
 
 left:
   ; CHECK: left:
   ; CHECK:   call void @h(i32 [[CleanupReload]]
   br i1 %b, label %left, label %right
 
 left:
   ; CHECK: left:
   ; CHECK:   call void @h(i32 [[CleanupReload]]
-  call void @h(i32 %phi.cleanup)
+  call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
   br label %merge
 
 right:
   ; CHECK: right:
   ; CHECK:   call void @h(i32 [[CleanupReload]]
   br label %merge
 
 right:
   ; CHECK: right:
   ; CHECK:   call void @h(i32 [[CleanupReload]]
-  call void @h(i32 %phi.cleanup)
+  call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
   br label %merge
 
 merge:
   br label %merge
 
 merge:
@@ -239,7 +241,7 @@ catch:
   ; CHECK:   [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
   ; CHECK:   call void @h(i32 [[CatchReload]]
   %cp2 = catchpad within %cs1 []
   ; CHECK:   [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
   ; CHECK:   call void @h(i32 [[CatchReload]]
   %cp2 = catchpad within %cs1 []
-  call void @h(i32 %phi.catch)
+  call void @h(i32 %phi.catch) [ "funclet"(token %cp2) ]
   catchret from %cp2 to label %exit
 
 exit:
   catchret from %cp2 to label %exit
 
 exit:
@@ -265,7 +267,7 @@ cleanup:
   ; CHECK: cleanup:
   ; CHECK:   call void @h(i32 %x)
   %cp2 = cleanuppad within none []
   ; CHECK: cleanup:
   ; CHECK:   call void @h(i32 %x)
   %cp2 = cleanuppad within none []
-  call void @h(i32 %x)
+  call void @h(i32 %x) [ "funclet"(token %cp2) ]
   cleanupret from %cp2 unwind to caller
 }
 
   cleanupret from %cp2 unwind to caller
 }
 
@@ -295,7 +297,7 @@ catch:
   ; CHECK: catch:
   ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad within %cs1 []
   %cp = catchpad within %cs1 []
   ; CHECK: catch:
   ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad within %cs1 []
   %cp = catchpad within %cs1 []
-  %b = call i1 @i()
+  %b = call i1 @i() [ "funclet"(token %cp) ]
   br i1 %b, label %left, label %right
 left:
   ; Edge from %left to %join needs to be split so that
   br i1 %b, label %left, label %right
 left:
   ; Edge from %left to %join needs to be split so that
@@ -312,7 +314,7 @@ right:
   ; CHECK: right:
   ; CHECK:   %y = call i32 @g()
   ; CHECK:   catchret from %[[CatchPad]] to label %join
   ; CHECK: right:
   ; CHECK:   %y = call i32 @g()
   ; CHECK:   catchret from %[[CatchPad]] to label %join
-  %y = call i32 @g()
+  %y = call i32 @g() [ "funclet"(token %cp) ]
   catchret from %cp to label %join
 join:
   ; CHECK: join:
   catchret from %cp to label %join
 join:
   ; CHECK: join:
@@ -336,19 +338,19 @@ done:
 
 cleanup1:
   ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none []
 
 cleanup1:
   ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none []
-  ; CHECK-NEXT: call void @f()
+  ; CHECK-NEXT: call void @llvm.bar()
   ; CHECK-NEXT: cleanupret from [[CleanupPad1]]
   %cp0 = cleanuppad within none []
   br label %cleanupexit
 
 cleanup2:
   ; CHECK: cleanuppad within none []
   ; CHECK-NEXT: cleanupret from [[CleanupPad1]]
   %cp0 = cleanuppad within none []
   br label %cleanupexit
 
 cleanup2:
   ; CHECK: cleanuppad within none []
-  ; CHECK-NEXT: call void @f()
+  ; CHECK-NEXT: call void @llvm.bar()
   ; CHECK-NEXT: unreachable
   %cp1 = cleanuppad within none []
   br label %cleanupexit
 
 cleanupexit:
   ; CHECK-NEXT: unreachable
   %cp1 = cleanuppad within none []
   br label %cleanupexit
 
 cleanupexit:
-  call void @f()
+  call void @llvm.bar()
   cleanupret from %cp0 unwind label %cleanup2
 }
   cleanupret from %cp0 unwind label %cleanup2
 }
index ab094aeebf520751fbf8ffc470463e606e3cb2c5..4fb84db890930e6a35f159ae7017165f0c3eebbc 100644 (file)
@@ -1,4 +1,4 @@
-; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare -disable-demotion < %s | FileCheck %s
+; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare -disable-demotion -disable-cleanups < %s | FileCheck %s
 
 declare i32 @__CxxFrameHandler3(...)
 
 
 declare i32 @__CxxFrameHandler3(...)
 
@@ -11,22 +11,21 @@ declare i32 @g()
 declare void @h(i32)
 
 ; CHECK-LABEL: @test1(
 declare void @h(i32)
 
 ; CHECK-LABEL: @test1(
-define void @test1() personality i32 (...)* @__C_specific_handler {
+define void @test1(i1 %bool) personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
 entry:
   invoke void @f()
-          to label %invoke.cont1 unwind label %left
-
-invoke.cont1:
-  invoke void @f()
-          to label %invoke.cont2 unwind label %right
+          to label %invoke.cont unwind label %left
 
 
-invoke.cont2:
+invoke.cont:
   invoke void @f()
           to label %exit unwind label %inner
 
 left:
   %0 = cleanuppad within none []
   invoke void @f()
           to label %exit unwind label %inner
 
 left:
   %0 = cleanuppad within none []
-  br label %shared
+  br i1 %bool, label %shared, label %cleanupret
+
+cleanupret:
+  cleanupret from %0 unwind label %right
 
 right:
   %1 = cleanuppad within none []
 
 right:
   %1 = cleanuppad within none []
@@ -34,19 +33,19 @@ right:
 
 shared:
   %x = call i32 @g()
 
 shared:
   %x = call i32 @g()
-  invoke void @f()
+  invoke void @f() [ "funclet"(token %0) ]
           to label %shared.cont unwind label %inner
 
 shared.cont:
   unreachable
 
 inner:
           to label %shared.cont unwind label %inner
 
 shared.cont:
   unreachable
 
 inner:
-  %phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont2 ]
+  %phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont ]
   %i = cleanuppad within none []
   call void @h(i32 %phi)
   unreachable
 
   %i = cleanuppad within none []
   call void @h(i32 %phi)
   unreachable
 
-; CHECK: %phi = phi i32 [ %x, %right ], [ 0, %invoke.cont2 ], [ %x.for.left, %left ]
+; CHECK: %phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont ], [ %x.for.left, %shared.for.left ]
 ; CHECK: %i = cleanuppad within none []
 ; CHECK: call void @h(i32 %phi)
 
 ; CHECK: %i = cleanuppad within none []
 ; CHECK: call void @h(i32 %phi)
 
@@ -55,26 +54,25 @@ exit:
 }
 
 ; CHECK-LABEL: @test2(
 }
 
 ; CHECK-LABEL: @test2(
-define void @test2() personality i32 (...)* @__C_specific_handler {
+define void @test2(i1 %bool) personality i32 (...)* @__C_specific_handler {
 entry:
   invoke void @f()
 entry:
   invoke void @f()
-          to label %invoke.cont unwind label %left
-
-invoke.cont:
-  invoke void @f()
-          to label %exit unwind label %right
+          to label %shared.cont unwind label %left
 
 left:
 
 left:
-  cleanuppad within none []
-  br label %shared
+  %0 = cleanuppad within none []
+  br i1 %bool, label %shared, label %cleanupret
+
+cleanupret:
+  cleanupret from %0 unwind label %right
 
 right:
 
 right:
-  cleanuppad within none []
+  %1 = cleanuppad within none []
   br label %shared
 
 shared:
   %x = call i32 @g()
   br label %shared
 
 shared:
   %x = call i32 @g()
-  invoke void @f()
+  invoke void @f() [ "funclet"(token %0) ]
           to label %shared.cont unwind label %inner
 
 shared.cont:
           to label %shared.cont unwind label %inner
 
 shared.cont:
@@ -85,9 +83,9 @@ inner:
   call void @h(i32 %x)
   unreachable
 
   call void @h(i32 %x)
   unreachable
 
-; CHECK:  %x1 = phi i32 [ %x.for.left, %left ], [ %x, %right ]
-; CHECK:  %i = cleanuppad within none []
-; CHECK:  call void @h(i32 %x1)
+; CHECK: %x1 = phi i32 [ %x.for.left, %shared.for.left ], [ %x, %shared ]
+; CHECK: %i = cleanuppad within none []
+; CHECK: call void @h(i32 %x1)
 
 exit:
   unreachable
 
 exit:
   unreachable
@@ -119,13 +117,12 @@ shared:
   call void @h(i32 %phi)
   unreachable
 
   call void @h(i32 %phi)
   unreachable
 
-; CHECK: %0 = cleanuppad within none []
-; CHECK: call void @h(i32 1)
-
-; CHECK: %1 = cleanuppad within none []
 ; CHECK: %phi = phi i32 [ 0, %right ], [ -1, %right.other ]
 ; CHECK: call void @h(i32 %phi)
 
 ; CHECK: %phi = phi i32 [ 0, %right ], [ -1, %right.other ]
 ; CHECK: call void @h(i32 %phi)
 
+; CHECK: %phi.for.left = phi i32 [ 1, %left ]
+; CHECK: call void @h(i32 %phi.for.left)
+
 exit:
   unreachable
 }
 exit:
   unreachable
 }
index 1abcd03ac64ffa61cf5281008c176a12f5462537..60939bc6b03ee3da12f91affbccb9f6650c53fdf 100644 (file)
@@ -58,7 +58,7 @@ catch:                                            ; preds = %catch.dispatch.2
 
 ehcleanup:                                        ; preds = %catchendblock
   %4 = cleanuppad within none []
 
 ehcleanup:                                        ; preds = %catchendblock
   %4 = cleanuppad within none []
-  call void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* nonnull %o) #4
+  call void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* nonnull %o) #4 [ "funclet"(token %4) ]
   cleanupret from %4 unwind to caller
 }
 
   cleanupret from %4 unwind to caller
 }
 
index 294ef3abc46236068f0b87f810b7c4e3b8804e8e..2e34ada52e6b9b3c23b06b585f7267af988524d6 100644 (file)
@@ -30,7 +30,7 @@ invoke.cont:                                      ; preds = %entry
 
 ehcleanup:                                        ; preds = %entry
   %2 = cleanuppad within none []
 
 ehcleanup:                                        ; preds = %entry
   %2 = cleanuppad within none []
-  call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %0)
+  call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %0) [ "funclet"(token %2) ]
   cleanupret from %2 unwind to caller
 }
 
   cleanupret from %2 unwind to caller
 }
 
index e32cdbed73fb2dcbaa9d97ff987a2915e9e41010..8ffb97d8dd68717e146ca9b352c67c929f64d744 100644 (file)
@@ -10,7 +10,7 @@ entry:
     to label %exit unwind label %cleanup
 cleanup:
   %c = cleanuppad within none []
     to label %exit unwind label %cleanup
 cleanup:
   %c = cleanuppad within none []
-  call void @bar()
+  call void @bar() [ "funclet"(token %c) ]
   cleanupret from %c unwind to caller
 exit:
   ret void
   cleanupret from %c unwind to caller
 exit:
   ret void
index d322932da4c1bf2c1f6c543addfc7bb80604a7a9..5a565cc1570f176d326327a4fe8f3e69cca6edb5 100644 (file)
@@ -18,7 +18,7 @@ invoke.cont:                                      ; preds = %entry
 
 ehcleanup:                                        ; preds = %entry
   %0 = cleanuppad within none []
 
 ehcleanup:                                        ; preds = %entry
   %0 = cleanuppad within none []
-  call void @Dtor(i64* %o)
+  call void @Dtor(i64* %o) [ "funclet"(token %0) ]
   cleanupret from %0 unwind to caller
 }
 
   cleanupret from %0 unwind to caller
 }
 
index b5972df43cc95851d43e37c9f2a37ef7da0ab848..0942645cf5a40e5f491896659adfed2ca49ef578 100644 (file)
@@ -59,7 +59,7 @@ catch.dispatch:                                   ; preds = %entry
 
 catch:                                            ; preds = %catch.dispatch
   %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
 
 catch:                                            ; preds = %catch.dispatch
   %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
-  invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1
+  invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1 ["funclet"(token %0)]
           to label %unreachable unwind label %catch.dispatch.1
 
 catch.dispatch.1:                                 ; preds = %catch
           to label %unreachable unwind label %catch.dispatch.1
 
 catch.dispatch.1:                                 ; preds = %catch
@@ -110,7 +110,7 @@ catch.dispatch:                                   ; preds = %entry
 
 catch.2:                                          ; preds = %catch.dispatch
   %0 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
 
 catch.2:                                          ; preds = %catch.dispatch
   %0 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-  tail call void @exit(i32 0) #2
+  tail call void @exit(i32 0) #2 [ "funclet"(token %0) ]
   unreachable
 
 catch.dispatch.1:                                 ; preds = %catch.dispatch
   unreachable
 
 catch.dispatch.1:                                 ; preds = %catch.dispatch
@@ -118,7 +118,7 @@ catch.dispatch.1:                                 ; preds = %catch.dispatch
 
 catch:                                            ; preds = %catch.dispatch.1
   %1 = catchpad within %cs2 [i8* null, i32 64, i8* null]
 
 catch:                                            ; preds = %catch.dispatch.1
   %1 = catchpad within %cs2 [i8* null, i32 64, i8* null]
-  tail call void @exit(i32 0) #2
+  tail call void @exit(i32 0) #2 [ "funclet"(token %1) ]
   unreachable
 
 try.cont:                                         ; preds = %entry
   unreachable
 
 try.cont:                                         ; preds = %entry
index 69afb1b9d9c63c90bf0da7b38d6c3f137694993c..e8da7ab971b13070e139da6567434a77b9f46ed3 100644 (file)
@@ -27,7 +27,7 @@ lpad:                                             ; preds = %entry
 __except:                                         ; preds = %lpad
   %p = catchpad within %cs1 [i8* bitcast (i32 ()* @"filt$main" to i8*)]
   %code = load i32, i32* %__exceptioncode, align 4
 __except:                                         ; preds = %lpad
   %p = catchpad within %cs1 [i8* bitcast (i32 ()* @"filt$main" to i8*)]
   %code = load i32, i32* %__exceptioncode, align 4
-  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4
+  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4 [ "funclet"(token %p) ]
   catchret from %p to label %__try.cont
 
 __try.cont:                                       ; preds = %entry, %__except
   catchret from %p to label %__try.cont
 
 __try.cont:                                       ; preds = %entry, %__except
index 4463485f2093fc4eb5e9dc825dde52579b9e90c8..76823bd476b1c957b80c631b990f154bc65e9a76 100644 (file)
@@ -21,7 +21,7 @@ lpad:
 catchall:
   %p = catchpad within %cs1 [i8* null, i32 64, i8* null]
   %code = call i32 @llvm.eh.exceptioncode(token %p)
 catchall:
   %p = catchpad within %cs1 [i8* null, i32 64, i8* null]
   %code = call i32 @llvm.eh.exceptioncode(token %p)
-  call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i64 0, i64 0), i32 %code)
+  call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i64 0, i64 0), i32 %code) [ "funclet"(token %p) ]
   catchret from %p to label %__try.cont
 }
 
   catchret from %p to label %__try.cont
 }
 
index a8be4ec14500c07ddace91b3846b252ca181b5eb..321d3a70cf8afbdbe464aa58afeb657bd1c5b440 100644 (file)
@@ -69,7 +69,7 @@ __except:                                         ; preds = %catch.dispatch
 
 ehcleanup:                                        ; preds = %__except.2
   %cp2 = cleanuppad within none []
 
 ehcleanup:                                        ; preds = %__except.2
   %cp2 = cleanuppad within none []
-  invoke fastcc void @"\01?fin$0@0@main@@"() #4
+  invoke fastcc void @"\01?fin$0@0@main@@"() #4 [ "funclet"(token %cp2) ]
           to label %invoke.cont.6 unwind label %catch.dispatch.7
 
 invoke.cont.6:                                    ; preds = %ehcleanup
           to label %invoke.cont.6 unwind label %catch.dispatch.7
 
 invoke.cont.6:                                    ; preds = %ehcleanup
index b252b5b124848c21dcee2e6d50a4e2c2a258ee77..c15ecfcd77b261e8cdd39e381dba98e0524c7716 100644 (file)
@@ -51,7 +51,7 @@ invoke.cont2:                                     ; preds = %invoke.cont
 __finally:                                             ; preds = %entry
   %cleanuppad = cleanuppad within none []
   %locals = call i8* @llvm.localaddress()
 __finally:                                             ; preds = %entry
   %cleanuppad = cleanuppad within none []
   %locals = call i8* @llvm.localaddress()
-  invoke void @"\01?fin$0@0@use_both@@"(i1 zeroext true, i8* %locals) #5
+  invoke void @"\01?fin$0@0@use_both@@"(i1 zeroext true, i8* %locals) #5 [ "funclet"(token %cleanuppad) ]
           to label %invoke.cont3 unwind label %catch.dispatch
 
 invoke.cont3:                                     ; preds = %__finally
           to label %invoke.cont3 unwind label %catch.dispatch
 
 invoke.cont3:                                     ; preds = %__finally
@@ -62,7 +62,7 @@ catch.dispatch:                                   ; preds = %invoke.cont3, %lpad
 
 __except:                                         ; preds = %catch.dispatch
   %catchpad = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_both@@" to i8*)]
 
 __except:                                         ; preds = %catch.dispatch
   %catchpad = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_both@@" to i8*)]
-  %call = call i32 @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01??_C@_08MLCMLGHM@__except?$AA@", i32 0, i32 0))
+  %call = call i32 @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01??_C@_08MLCMLGHM@__except?$AA@", i32 0, i32 0)) [ "funclet"(token %catchpad) ]
   catchret from %catchpad to label %__try.cont
 
 __try.cont:                                       ; preds = %__except, %invoke.cont2
   catchret from %catchpad to label %__try.cont
 
 __try.cont:                                       ; preds = %__except, %invoke.cont2
index 67bce81a66ad31d8bee9cec79c38285df70a37ed..8405d200776d74bfc693c98e23693b13c0b4ab2a 100644 (file)
@@ -18,7 +18,7 @@ invoke.cont:                                      ; preds = %entry
 
 lpad:                                             ; preds = %entry
   %p = cleanuppad within none []
 
 lpad:                                             ; preds = %entry
   %p = cleanuppad within none []
-  %call2 = call i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str_recovered, i64 0, i64 0))
+  %call2 = call i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str_recovered, i64 0, i64 0)) [ "funclet"(token %p) ]
   cleanupret from %p unwind to caller
 }
 
   cleanupret from %p unwind to caller
 }
 
index 3f88696fe602f36ed22df576d57889e0f04b8162..643af3a472fb4e23277c6d021def1118d865287e 100644 (file)
@@ -35,7 +35,7 @@ lpad0:
 
 handler0:
   %p0 = catchpad within %cs0 [i8* bitcast (i32 ()* @safe_div_filt0 to i8*)]
 
 handler0:
   %p0 = catchpad within %cs0 [i8* bitcast (i32 ()* @safe_div_filt0 to i8*)]
-  call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0))
+  call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0)) [ "funclet"(token %p0) ]
   store i32 -1, i32* %r, align 4
   catchret from %p0 to label %__try.cont
 
   store i32 -1, i32* %r, align 4
   catchret from %p0 to label %__try.cont
 
@@ -44,7 +44,7 @@ lpad1:
 
 handler1:
   %p1 = catchpad within %cs1 [i8* bitcast (i32 ()* @safe_div_filt1 to i8*)]
 
 handler1:
   %p1 = catchpad within %cs1 [i8* bitcast (i32 ()* @safe_div_filt1 to i8*)]
-  call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0))
+  call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0)) [ "funclet"(token %p1) ]
   store i32 -2, i32* %r, align 4
   catchret from %p1 to label %__try.cont
 
   store i32 -2, i32* %r, align 4
   catchret from %p1 to label %__try.cont
 
index 3eeeab09ffbb9b01ffc5391e9a88268fbc3f4d4e..dd5752e8a716995acf13e39dec8cc2ed3aa91174 100644 (file)
@@ -34,7 +34,7 @@ lpad0:
 
 handler0:
   %p0 = catchpad within %cs0 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt0 to i8*)]
 
 handler0:
   %p0 = catchpad within %cs0 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt0 to i8*)]
-  call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0))
+  call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0)) [ "funclet"(token %p0) ]
   store i32 -1, i32* %r, align 4
   catchret from %p0 to label %__try.cont
 
   store i32 -1, i32* %r, align 4
   catchret from %p0 to label %__try.cont
 
@@ -43,7 +43,7 @@ lpad1:
 
 handler1:
   %p1 = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*)]
 
 handler1:
   %p1 = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*)]
-  call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0))
+  call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0)) [ "funclet"(token %p1) ]
   store i32 -2, i32* %r, align 4
   catchret from %p1 to label %__try.cont
 
   store i32 -2, i32* %r, align 4
   catchret from %p1 to label %__try.cont
 
index 880533b43925375aef1dd83b0ee4f115e22bc46f..654cad347f6b46a163d1c7dc242f0c81fd5f4a0f 100644 (file)
@@ -28,7 +28,7 @@ lpad:                                             ; preds = %entry
 __except:                                         ; preds = %lpad
   %p = catchpad within %cs1 [i8* bitcast (i32 ()* @"filt$main" to i8*)]
   %code = load i32, i32* %__exceptioncode, align 4
 __except:                                         ; preds = %lpad
   %p = catchpad within %cs1 [i8* bitcast (i32 ()* @"filt$main" to i8*)]
   %code = load i32, i32* %__exceptioncode, align 4
-  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4
+  %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4 [ "funclet"(token %p) ]
   catchret from %p to label %__try.cont
 
 __try.cont:                                       ; preds = %entry, %__except
   catchret from %p to label %__try.cont
 
 __try.cont:                                       ; preds = %entry, %__except
index 9f7a49536caa86b4558d95fe2a90185cc866321a..327ee45b4326d022e68ccb4c14ab4aaad971ac15 100644 (file)
@@ -34,7 +34,7 @@ catch.dispatch:
 
 handler1:
   %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
 
 handler1:
   %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-  call void @f(i32 2)
+  call void @f(i32 2) [ "funclet"(token %h1) ]
   catchret from %h1 to label %try.cont
 }
 
   catchret from %h1 to label %try.cont
 }
 
index 22ce7e5cd87956c80fe7c7200549d854c794f724..ac4598385cd1f155da351f6c30f840f9780fb6de 100644 (file)
@@ -31,7 +31,7 @@ catch.dispatch.1:
   %cs1 = catchswitch within none [label %handler1] unwind to caller
 handler1:
   %h1 = catchpad within %cs1 [i8* null, i32 64, i8* null]
   %cs1 = catchswitch within none [label %handler1] unwind to caller
 handler1:
   %h1 = catchpad within %cs1 [i8* null, i32 64, i8* null]
-  invoke void @f(i32 2)
+  invoke void @f(i32 2) [ "funclet"(token %h1) ]
           to label %catchret1 unwind label %catch.dispatch.2
 catchret1:
   catchret from %h1 to label %try.cont
           to label %catchret1 unwind label %catch.dispatch.2
 catchret1:
   catchret from %h1 to label %try.cont
index d20f9f69a5ee2646c1772578a7d4fa884acb2dd4..7afcd9cc1f3e1fbee2c9c993fbc49b0c91c7e801 100644 (file)
@@ -16,7 +16,7 @@ catch.dispatch.1:
 
 outer.catch:
   %cp1 = catchpad within %cs1 [i32 1]
 
 outer.catch:
   %cp1 = catchpad within %cs1 [i32 1]
-  invoke void @f()
+  invoke void @f() [ "funclet"(token %cp1) ]
           to label %outer.ret unwind label %catch.dispatch.2
 outer.ret:
   catchret from %cp1 to label %exit
           to label %outer.ret unwind label %catch.dispatch.2
 outer.ret:
   catchret from %cp1 to label %exit
index 5bd250461302477bbfdf938cda20e39e0bddc308..836c53bda8e686d69334038e820e0ed6a05b9378 100644 (file)
@@ -41,12 +41,12 @@ catch.dispatch:                                   ; preds = %entry
 handler1:
   %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e.addr]
   %e = load i32, i32* %e.addr
 handler1:
   %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e.addr]
   %e = load i32, i32* %e.addr
-  call void @f(i32 %e, i32* %local)
+  call void @f(i32 %e, i32* %local) [ "funclet"(token %h1) ]
   catchret from %h1 to label %try.cont
 
 handler2:
   %h2 = catchpad within %cs [i8* null, i32 64, i8* null]
   catchret from %h1 to label %try.cont
 
 handler2:
   %h2 = catchpad within %cs [i8* null, i32 64, i8* null]
-  call void @f(i32 3, i32* %local)
+  call void @f(i32 3, i32* %local) [ "funclet"(token %h2) ]
   catchret from %h2 to label %try.cont
 
 try.cont:
   catchret from %h2 to label %try.cont
 
 try.cont:
@@ -229,7 +229,7 @@ catch:
   br label %loop
 
 loop:
   br label %loop
 
 loop:
-  %V = call i1 @getbool()
+  %V = call i1 @getbool() [ "funclet"(token %cp1) ]
   br i1 %V, label %loop, label %catch.done
 
 catch.done:
   br i1 %V, label %loop, label %catch.done
 
 catch.done:
index 37090c2f6bccb7678c2966edf8c6fa907767997c..4b0a543a876a755fdb18b36ddabf696ad038580e 100644 (file)
@@ -15,7 +15,7 @@ invoke.cont:                                      ; preds = %entry
 
 ehcleanup:                                        ; preds = %entry
   %0 = cleanuppad within none []
 
 ehcleanup:                                        ; preds = %entry
   %0 = cleanuppad within none []
-  call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o) #2
+  call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o) #2 [ "funclet"(token %0) ]
   cleanupret from %0 unwind to caller
 }
 
   cleanupret from %0 unwind to caller
 }
 
@@ -78,12 +78,12 @@ invoke.cont.2:                                    ; preds = %invoke.cont.1
 
 cleanup.inner:                                        ; preds = %invoke.cont
   %0 = cleanuppad within none []
 
 cleanup.inner:                                        ; preds = %invoke.cont
   %0 = cleanuppad within none []
-  call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o2) #2
+  call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o2) #2 [ "funclet"(token %0) ]
   cleanupret from %0 unwind label %cleanup.outer
 
 cleanup.outer:                                      ; preds = %invoke.cont.1, %cleanup.inner, %entry
   %1 = cleanuppad within none []
   cleanupret from %0 unwind label %cleanup.outer
 
 cleanup.outer:                                      ; preds = %invoke.cont.1, %cleanup.inner, %entry
   %1 = cleanuppad within none []
-  call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o1) #2
+  call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o1) #2 [ "funclet"(token %1) ]
   cleanupret from %1 unwind to caller
 }
 
   cleanupret from %1 unwind to caller
 }
 
index 95afa75a709a541e973a31969b7ed3c8153b6dce..2151cdc7bb4b3ee361aa2f9e7f33f9fd8cc2c6da 100644 (file)
@@ -10,7 +10,7 @@ entry:
 
 cleanupblock:
   %cleanp = cleanuppad within none []
 
 cleanupblock:
   %cleanp = cleanuppad within none []
-  call void @g()
+  call void @g() [ "funclet"(token %cleanp) ]
   cleanupret from %cleanp unwind label %catch.dispatch
 
 catch.dispatch:
   cleanupret from %cleanp unwind label %catch.dispatch
 
 catch.dispatch:
@@ -18,7 +18,7 @@ catch.dispatch:
 
 catch:
   %cp = catchpad within %cs1 [i8* null, i32 64, i8* null]
 
 catch:
   %cp = catchpad within %cs1 [i8* null, i32 64, i8* null]
-  call void @g()
+  call void @g() [ "funclet"(token %cp) ]
   catchret from %cp to label %try.cont
 
 try.cont:
   catchret from %cp to label %try.cont
 
 try.cont:
index fe3639b97a4557666c3ff1148a32c86f4f536837..2777d6644e6a3f0bec18918d27ab29c53b7306a4 100644 (file)
@@ -48,7 +48,7 @@ lpad:                                             ; preds = %catch, %entry
 
 catch:                                            ; preds = %lpad.1
   %p1 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
 
 catch:                                            ; preds = %lpad.1
   %p1 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-  invoke void @may_throw(i32 3)
+  invoke void @may_throw(i32 3) [ "funclet"(token %p1) ]
           to label %invoke.cont.3 unwind label %lpad.1
 
 invoke.cont.3:                                    ; preds = %catch
           to label %invoke.cont.3 unwind label %lpad.1
 
 invoke.cont.3:                                    ; preds = %catch
@@ -59,7 +59,7 @@ lpad.1:                                           ; preds = %invoke.cont
 
 catch.7:
   %p2 = catchpad within %cs2 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
 
 catch.7:
   %p2 = catchpad within %cs2 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
-  call void @may_throw(i32 4)
+  call void @may_throw(i32 4) [ "funclet"(token %p2) ]
   catchret from %p2 to label %try.cont.9
 }
 
   catchret from %p2 to label %try.cont.9
 }
 
@@ -131,19 +131,19 @@ catch.dispatch:                                   ; preds = %entry
 
 catch:                                            ; preds = %catch.dispatch
   %1 = catchpad within %0 [i8* null, i32 64, i8* null]
 
 catch:                                            ; preds = %catch.dispatch
   %1 = catchpad within %0 [i8* null, i32 64, i8* null]
-  invoke void @may_throw(i32 0)
+  invoke void @may_throw(i32 0) [ "funclet"(token %1) ]
           to label %invoke.cont unwind label %ehcleanup5
 
 invoke.cont:                                      ; preds = %catch
           to label %invoke.cont unwind label %ehcleanup5
 
 invoke.cont:                                      ; preds = %catch
-  invoke void @may_throw(i32 1)
+  invoke void @may_throw(i32 1) [ "funclet"(token %1) ]
           to label %invoke.cont2 unwind label %ehcleanup
 
 invoke.cont2:                                     ; preds = %invoke.cont
           to label %invoke.cont2 unwind label %ehcleanup
 
 invoke.cont2:                                     ; preds = %invoke.cont
-  invoke void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y)
+  invoke void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y) [ "funclet"(token %1) ]
           to label %invoke.cont3 unwind label %ehcleanup5
 
 invoke.cont3:                                     ; preds = %invoke.cont2
           to label %invoke.cont3 unwind label %ehcleanup5
 
 invoke.cont3:                                     ; preds = %invoke.cont2
-  invoke void @may_throw(i32 2)
+  invoke void @may_throw(i32 2) [ "funclet"(token %1) ]
           to label %invoke.cont4 unwind label %ehcleanup5
 
 invoke.cont4:                                     ; preds = %invoke.cont3
           to label %invoke.cont4 unwind label %ehcleanup5
 
 invoke.cont4:                                     ; preds = %invoke.cont3
@@ -155,12 +155,12 @@ try.cont:                                         ; preds = %invoke.cont4
 
 ehcleanup:                                        ; preds = %invoke.cont
   %2 = cleanuppad within %1 []
 
 ehcleanup:                                        ; preds = %invoke.cont
   %2 = cleanuppad within %1 []
-  call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y)
+  call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y) [ "funclet"(token %2) ]
   cleanupret from %2 unwind label %ehcleanup5
 
 ehcleanup5:                                       ; preds = %invoke.cont2, %invoke.cont3, %ehcleanup, %catch, %catch.dispatch
   %3 = cleanuppad within none []
   cleanupret from %2 unwind label %ehcleanup5
 
 ehcleanup5:                                       ; preds = %invoke.cont2, %invoke.cont3, %ehcleanup, %catch, %catch.dispatch
   %3 = cleanuppad within none []
-  call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %x)
+  call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %x) [ "funclet"(token %3) ]
   cleanupret from %3 unwind to caller
 
 unreachable:                                      ; preds = %entry
   cleanupret from %3 unwind to caller
 
 unreachable:                                      ; preds = %entry
index 88dea3675725be7198547f17fc1f3546b87833bf..6c25161ec8ca05edba12336dd234925d8326b25c 100644 (file)
@@ -193,7 +193,7 @@ catch.dispatch:                                   ; preds = %entry
 
 __except.ret:                                     ; preds = %catch.dispatch
   %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
 
 __except.ret:                                     ; preds = %catch.dispatch
   %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
-  call void @f(i32 2)
+  call void @f(i32 2) [ "funclet"(token %0) ]
   catchret from %0 to label %__except
 
 __except:
   catchret from %0 to label %__except
 
 __except:
index c91a14278ec70d3923f24d05b6f010ae1f84cbe3..61bf79a76f878ba5af471d2f69f1a5a98f08856f 100644 (file)
@@ -18,7 +18,7 @@ invoke.cont.1:                                    ; preds = %invoke.cont
 
 ehcleanup:                                        ; preds = %entry
   %0 = cleanuppad within none []
 
 ehcleanup:                                        ; preds = %entry
   %0 = cleanuppad within none []
-  invoke void @f(i32 2) #3
+  invoke void @f(i32 2) #3 [ "funclet"(token %0) ]
           to label %invoke.cont.2 unwind label %ehcleanup.3
 
 invoke.cont.2:                                    ; preds = %ehcleanup
           to label %invoke.cont.2 unwind label %ehcleanup.3
 
 invoke.cont.2:                                    ; preds = %ehcleanup
@@ -26,7 +26,7 @@ invoke.cont.2:                                    ; preds = %ehcleanup
 
 ehcleanup.3:                                      ; preds = %invoke.cont.2, %ehcleanup.end, %invoke.cont
   %1 = cleanuppad within none []
 
 ehcleanup.3:                                      ; preds = %invoke.cont.2, %ehcleanup.end, %invoke.cont
   %1 = cleanuppad within none []
-  call void @f(i32 3) #3
+  call void @f(i32 3) #3 [ "funclet"(token %1) ]
   cleanupret from %1 unwind to caller
 }
 
   cleanupret from %1 unwind to caller
 }
 
index 7bbc64ece8ede5684c65ae68d59f37cc7fdc7d4f..b61876827cac89e9aa0fcbe7ed4cb9cc9c9e8a87 100644 (file)
@@ -65,12 +65,12 @@ catch1.body:
 ;             ^ exception pointer passed in rdx
 ; CHECK-NEXT: callq g
   %exn1 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch1)
 ;             ^ exception pointer passed in rdx
 ; CHECK-NEXT: callq g
   %exn1 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch1)
-  call void @g(i8 addrspace(1)* %exn1)
+  call void @g(i8 addrspace(1)* %exn1) [ "funclet"(token %catch1) ]
 ; CHECK: [[L_before_f3:.+]]:
 ; CHECK-NEXT: movl $3, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f3:.+]]:
 ; CHECK: [[L_before_f3:.+]]:
 ; CHECK-NEXT: movl $3, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f3:.+]]:
-  invoke void @f(i32 3)
+  invoke void @f(i32 3) [ "funclet"(token %catch1) ]
     to label %catch1.ret unwind label %finally.pad
 catch1.ret:
   catchret from %catch1 to label %finally.clone
     to label %catch1.ret unwind label %finally.pad
 catch1.ret:
   catchret from %catch1 to label %finally.clone
@@ -88,12 +88,12 @@ catch2.body:
 ;             ^ exception pointer passed in rdx
 ; CHECK-NEXT: callq g
   %exn2 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch2)
 ;             ^ exception pointer passed in rdx
 ; CHECK-NEXT: callq g
   %exn2 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch2)
-  call void @g(i8 addrspace(1)* %exn2)
+  call void @g(i8 addrspace(1)* %exn2) [ "funclet"(token %catch2) ]
 ; CHECK: [[L_before_f4:.+]]:
 ; CHECK-NEXT: movl $4, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f4:.+]]:
 ; CHECK: [[L_before_f4:.+]]:
 ; CHECK-NEXT: movl $4, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f4:.+]]:
-  invoke void @f(i32 4)
+  invoke void @f(i32 4) [ "funclet"(token %catch2) ]
     to label %try_in_catch unwind label %finally.pad
 try_in_catch:
 ; CHECK: # %try_in_catch
     to label %try_in_catch unwind label %finally.pad
 try_in_catch:
 ; CHECK: # %try_in_catch
@@ -101,7 +101,7 @@ try_in_catch:
 ; CHECK-NEXT: movl $5, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f5:.+]]:
 ; CHECK-NEXT: movl $5, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f5:.+]]:
-  invoke void @f(i32 5)
+  invoke void @f(i32 5) [ "funclet"(token %catch2) ]
     to label %catch2.ret unwind label %fault.pad
 fault.pad:
 ; CHECK: .seh_proc [[L_fault:[^ ]+]]
     to label %catch2.ret unwind label %fault.pad
 fault.pad:
 ; CHECK: .seh_proc [[L_fault:[^ ]+]]
@@ -117,7 +117,7 @@ fault.pad:
 ; CHECK-NEXT: movl $6, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f6:.+]]:
 ; CHECK-NEXT: movl $6, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK-NEXT: [[L_after_f6:.+]]:
-  invoke void @f(i32 6)
+  invoke void @f(i32 6) [ "funclet"(token %fault) ]
     to label %fault.ret unwind label %finally.pad
 fault.ret:
   cleanupret from %fault unwind label %finally.pad
     to label %fault.ret unwind label %finally.pad
 fault.ret:
   cleanupret from %fault unwind label %finally.pad
@@ -138,7 +138,7 @@ finally.pad:
 ; CHECK: .seh_endprologue
 ; CHECK-NEXT: movl $7, %ecx
 ; CHECK-NEXT: callq f
 ; CHECK: .seh_endprologue
 ; CHECK-NEXT: movl $7, %ecx
 ; CHECK-NEXT: callq f
-  call void @f(i32 7)
+  call void @f(i32 7) [ "funclet"(token %finally) ]
   cleanupret from %finally unwind to caller
 tail:
   call void @f(i32 8)
   cleanupret from %finally unwind to caller
 tail:
   call void @f(i32 8)
index 9c1f0aaf3de37fcdaa56b06ec35247a0faf4c07d..f6fd4fe7c525689d4d4599900b7796177d65c046 100644 (file)
@@ -19,7 +19,7 @@ catch.body:
   %catch = catchpad within %cs1 [i32 5]
   %exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch)
   %cast_exn = bitcast i8 addrspace(1)* %exn to i32 addrspace(1)*
   %catch = catchpad within %cs1 [i32 5]
   %exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch)
   %cast_exn = bitcast i8 addrspace(1)* %exn to i32 addrspace(1)*
-  call void @g(i32 addrspace(1)* %cast_exn)
+  call void @g(i32 addrspace(1)* %cast_exn) [ "funclet"(token %catch) ]
   catchret from %catch to label %exit
 exit:
   ret void
   catchret from %catch to label %exit
 exit:
   ret void