llvm.org GIT mirror llvm / b46bb54
[WinEH] Use operand bundles to describe call sites 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 David Majnemer 4 years ago
36 changed file(s) with 305 addition(s) and 252 deletion(s). Raw diff Collapse all Expand all
15691569 caller's deoptimization state to the callee's deoptimization state is
15701570 semantically equivalent to composing the caller's deoptimization
15711571 continuation after the callee's deoptimization continuation.
1572
1573 Funclet Operand Bundles
1574 ^^^^^^^^^^^^^^^^^^^^^^^
1575
1576 Funclet operand bundles are characterized by the ``"funclet"``
1577 operand bundle tag. These operand bundles indicate that a call site
1578 is within a particular funclet. There can be at most one
1579 ``"funclet"`` operand bundle attached to a call site and it must have
1580 exactly one bundle operand.
15721581
15731582 .. _moduleasm:
15741583
12181218 return getTagID() == LLVMContext::OB_deopt;
12191219 }
12201220
1221 /// \brief Return true if this is a "funclet" operand bundle.
1222 bool isFuncletOperandBundle() const {
1223 return getTagID() == LLVMContext::OB_funclet;
1224 }
1225
12211226 private:
12221227 /// \brief Pointer to an entry in LLVMContextImpl::getOrInsertBundleTag.
12231228 StringMapEntry *Tag;
12361241 public:
12371242 explicit OperandBundleDefT(std::string Tag, std::vector Inputs)
12381243 : Tag(std::move(Tag)), Inputs(std::move(Inputs)) {}
1244 explicit OperandBundleDefT(std::string Tag, ArrayRef Inputs)
1245 : Tag(std::move(Tag)), Inputs(Inputs) {}
12391246
12401247 explicit OperandBundleDefT(const OperandBundleUse &OBU) {
12411248 Tag = OBU.getTagName();
14291436 /// may write to the heap.
14301437 bool hasClobberingOperandBundles() const {
14311438 for (auto &BOI : bundle_op_infos()) {
1432 if (BOI.Tag->second == LLVMContext::OB_deopt)
1439 if (BOI.Tag->second == LLVMContext::OB_deopt ||
1440 BOI.Tag->second == LLVMContext::OB_funclet)
14331441 continue;
14341442
1435 // This instruction has an operand bundle that is not a "deopt" operand
1436 // bundle. Assume the worst.
1443 // This instruction has an operand bundle that is not known to us.
1444 // Assume the worst.
14371445 return true;
14381446 }
14391447
7171 /// Additionally, this scheme allows LLVM to efficiently check for specific
7272 /// operand bundle tags without comparing strings.
7373 enum {
74 OB_deopt = 0, // "deopt"
74 OB_deopt = 0, // "deopt"
75 OB_funclet = 1, // "funclet"
7576 };
7677
7778 /// getMDKindID - Return a unique non-zero ID for the specified metadata kind.
287287 bool replaceDbgDeclareForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
288288 DIBuilder &Builder, bool Deref, int Offset = 0);
289289
290 /// \brief Insert an unreachable instruction before the specified
291 /// instruction, making it and the rest of the code in the block dead.
292 void changeToUnreachable(Instruction *I, bool UseLLVMTrap);
293
290294 /// Replace 'BB's terminator with one that does not have an unwind successor
291295 /// block. Rewrites `invoke` to `call`, etc. Updates any PHIs in unwind
292296 /// successor.
7373
7474 void demotePHIsOnFunclets(Function &F);
7575 void cloneCommonBlocks(Function &F);
76 void removeImplausibleTerminators(Function &F);
76 void removeImplausibleInstructions(Function &F);
7777 void cleanupPreparedFunclets(Function &F);
7878 void verifyPreparedFunclets(Function &F);
7979
764764 }
765765 }
766766
767 void WinEHPrepare::removeImplausibleTerminators(Function &F) {
767 void WinEHPrepare::removeImplausibleInstructions(Function &F) {
768768 // Remove implausible terminators and replace them with UnreachableInst.
769769 for (auto &Funclet : FuncletBlocks) {
770770 BasicBlock *FuncletPadBB = Funclet.first;
771771 std::vector &BlocksInFunclet = Funclet.second;
772 Instruction *FuncletPadInst = FuncletPadBB->getFirstNonPHI();
773 auto *CatchPad = dyn_cast(FuncletPadInst);
774 auto *CleanupPad = dyn_cast(FuncletPadInst);
772 Instruction *FirstNonPHI = FuncletPadBB->getFirstNonPHI();
773 auto *FuncletPad = dyn_cast(FirstNonPHI);
774 auto *CatchPad = dyn_cast_or_null(FuncletPad);
775 auto *CleanupPad = dyn_cast_or_null(FuncletPad);
775776
776777 for (BasicBlock *BB : BlocksInFunclet) {
778 for (Instruction &I : *BB) {
779 CallSite CS(&I);
780 if (!CS)
781 continue;
782
783 Value *FuncletBundleOperand = nullptr;
784 if (auto BU = CS.getOperandBundle(LLVMContext::OB_funclet))
785 FuncletBundleOperand = BU->Inputs.front();
786
787 if (FuncletBundleOperand == FuncletPad)
788 continue;
789
790 // Skip call sites which are nounwind intrinsics.
791 auto *CalledFn =
792 dyn_cast(CS.getCalledValue()->stripPointerCasts());
793 if (CalledFn && CalledFn->isIntrinsic() && CS.doesNotThrow())
794 continue;
795
796 // This call site was not part of this funclet, remove it.
797 if (CS.isInvoke()) {
798 // Remove the unwind edge if it was an invoke.
799 removeUnwindEdge(BB);
800 // Get a pointer to the new call.
801 BasicBlock::iterator CallI =
802 std::prev(BB->getTerminator()->getIterator());
803 auto *CI = cast(&*CallI);
804 changeToUnreachable(CI, /*UseLLVMTrap=*/false);
805 } else {
806 changeToUnreachable(&I, /*UseLLVMTrap=*/false);
807 }
808
809 // There are no more instructions in the block (except for unreachable),
810 // we are done.
811 break;
812 }
813
777814 TerminatorInst *TI = BB->getTerminator();
778815 // CatchPadInst and CleanupPadInst can't transfer control to a ReturnInst.
779 bool IsUnreachableRet = isa(TI) && (CatchPad || CleanupPad);
816 bool IsUnreachableRet = isa(TI) && FuncletPad;
780817 // The token consumed by a CatchReturnInst must match the funclet token.
781818 bool IsUnreachableCatchret = false;
782819 if (auto *CRI = dyn_cast(TI))
787824 IsUnreachableCleanupret = CRI->getCleanupPad() != CleanupPad;
788825 if (IsUnreachableRet || IsUnreachableCatchret ||
789826 IsUnreachableCleanupret) {
790 // Loop through all of our successors and make sure they know that one
791 // of their predecessors is going away.
792 for (BasicBlock *SuccBB : TI->successors())
793 SuccBB->removePredecessor(BB);
794
795 new UnreachableInst(BB->getContext(), TI);
796 TI->eraseFromParent();
827 changeToUnreachable(TI, /*UseLLVMTrap=*/false);
797828 } else if (isa(TI)) {
798 // Invokes within a cleanuppad for the MSVC++ personality never
799 // transfer control to their unwind edge: the personality will
800 // terminate the program.
801 if (Personality == EHPersonality::MSVC_CXX && CleanupPad)
829 if (Personality == EHPersonality::MSVC_CXX && CleanupPad) {
830 // Invokes within a cleanuppad for the MSVC++ personality never
831 // transfer control to their unwind edge: the personality will
832 // terminate the program.
802833 removeUnwindEdge(BB);
834 }
803835 }
804836 }
805837 }
853885 demotePHIsOnFunclets(F);
854886
855887 if (!DisableCleanups) {
856 removeImplausibleTerminators(F);
888 removeImplausibleInstructions(F);
857889
858890 cleanupPreparedFunclets(F);
859891 }
131131 assert(DeoptEntry->second == LLVMContext::OB_deopt &&
132132 "deopt operand bundle id drifted!");
133133 (void)DeoptEntry;
134
135 auto *FuncletEntry = pImpl->getOrInsertBundleTag("funclet");
136 assert(FuncletEntry->second == LLVMContext::OB_funclet &&
137 "funclet operand bundle id drifted!");
138 (void)FuncletEntry;
134139 }
135140 LLVMContext::~LLVMContext() { delete pImpl; }
136141
23802380 if (Intrinsic::ID ID = (Intrinsic::ID)F->getIntrinsicID())
23812381 visitIntrinsicCallSite(ID, CS);
23822382
2383 // Verify that a callsite has at most one "deopt" operand bundle.
2384 bool FoundDeoptBundle = false;
2383 // Verify that a callsite has at most one "deopt" and one "funclet" operand
2384 // bundle.
2385 bool FoundDeoptBundle = false, FoundFuncletBundle = false;
23852386 for (unsigned i = 0, e = CS.getNumOperandBundles(); i < e; ++i) {
2386 if (CS.getOperandBundleAt(i).getTagID() == LLVMContext::OB_deopt) {
2387 OperandBundleUse BU = CS.getOperandBundleAt(i);
2388 uint32_t Tag = BU.getTagID();
2389 if (Tag == LLVMContext::OB_deopt) {
23872390 Assert(!FoundDeoptBundle, "Multiple deopt operand bundles", I);
23882391 FoundDeoptBundle = true;
2392 }
2393 if (Tag == LLVMContext::OB_funclet) {
2394 Assert(!FoundFuncletBundle, "Multiple funclet operand bundles", I);
2395 FoundFuncletBundle = true;
2396 Assert(BU.Inputs.size() == 1,
2397 "Expected exactly one funclet bundle operand", I);
2398 Assert(isa(BU.Inputs.front()),
2399 "Funclet bundle operands should correspond to a FuncletPadInst",
2400 I);
23892401 }
23902402 }
23912403
30013013 UnwindDest = CRI->getUnwindDest();
30023014 } else if (isa(U) || isa(U)) {
30033015 continue;
3016 } else if (CallSite(U)) {
3017 continue;
30043018 } else {
30053019 Assert(false, "bogus cleanuppad use", &CPI);
30063020 }
10341034 // The inliner does not know how to inline through calls with operand bundles
10351035 // in general ...
10361036 if (CS.hasOperandBundles()) {
1037 // ... but it knows how to inline through "deopt" operand bundles.
1038 bool CanInline =
1039 CS.getNumOperandBundles() == 1 &&
1040 CS.getOperandBundleAt(0).getTagID() == LLVMContext::OB_deopt;
1041 if (!CanInline)
1037 for (int i = 0, e = CS.getNumOperandBundles(); i != e; ++i) {
1038 uint32_t Tag = CS.getOperandBundleAt(i).getTagID();
1039 // ... but it knows how to inline through "deopt" operand bundles ...
1040 if (Tag == LLVMContext::OB_deopt)
1041 continue;
1042 // ... and "funclet" operand bundles.
1043 if (Tag == LLVMContext::OB_funclet)
1044 continue;
1045
10421046 return false;
1047 }
10431048 }
10441049
10451050 // If the call to the callee cannot throw, set the 'nounwind' flag on any
10871092 // We need to figure out which funclet the callsite was in so that we may
10881093 // properly nest the callee.
10891094 Instruction *CallSiteEHPad = nullptr;
1090 if (CalledPersonality && CallerPersonality) {
1091 EHPersonality Personality = classifyEHPersonality(CalledPersonality);
1095 if (CallerPersonality) {
1096 EHPersonality Personality = classifyEHPersonality(CallerPersonality);
10921097 if (isFuncletEHPersonality(Personality)) {
1093 DenseMap CallerBlockColors =
1094 colorEHFunclets(*Caller);
1095 ColorVector &CallSiteColors = CallerBlockColors[OrigBB];
1096 size_t NumColors = CallSiteColors.size();
1097 // There is no single parent, inlining will not succeed.
1098 if (NumColors > 1)
1099 return false;
1100 if (NumColors == 1) {
1101 BasicBlock *CallSiteFuncletBB = CallSiteColors.front();
1102 if (CallSiteFuncletBB != Caller->begin()) {
1103 CallSiteEHPad = CallSiteFuncletBB->getFirstNonPHI();
1104 assert(CallSiteEHPad->isEHPad() && "Expected an EHPad!");
1105 }
1106 }
1098 Optional ParentFunclet =
1099 CS.getOperandBundle(LLVMContext::OB_funclet);
1100 if (ParentFunclet)
1101 CallSiteEHPad = cast(ParentFunclet->Inputs.front());
11071102
11081103 // OK, the inlining site is legal. What about the target function?
11091104
11151110 // Ok, the call site is within a cleanuppad. Let's check the callee
11161111 // for catchpads.
11171112 for (const BasicBlock &CalledBB : *CalledFunc) {
1118 if (isaPadInst>(CalledBB.getFirstNonPHI()))
1113 if (isaSwitchInst>(CalledBB.getFirstNonPHI()))
11191114 return false;
11201115 }
11211116 }
11941189 HandleByValArgumentInit(Init.first, Init.second, Caller->getParent(),
11951190 &*FirstNewBlock, IFI);
11961191
1197 if (CS.hasOperandBundles()) {
1198 auto ParentDeopt = CS.getOperandBundleAt(0);
1199 assert(ParentDeopt.getTagID() == LLVMContext::OB_deopt &&
1200 "Checked on entry!");
1201
1192 Optional ParentDeopt =
1193 CS.getOperandBundle(LLVMContext::OB_deopt);
1194 if (ParentDeopt) {
12021195 SmallVector OpDefs;
12031196
12041197 for (auto &VH : InlinedFunctionInfo.OperandBundleCallSites) {
12241217 // Prepend the parent's deoptimization continuation to the newly
12251218 // inlined call's deoptimization continuation.
12261219 std::vector MergedDeoptArgs;
1227 MergedDeoptArgs.reserve(ParentDeopt.Inputs.size() +
1220 MergedDeoptArgs.reserve(ParentDeopt->Inputs.size() +
12281221 ChildOB.Inputs.size());
12291222
12301223 MergedDeoptArgs.insert(MergedDeoptArgs.end(),
1231 ParentDeopt.Inputs.begin(),
1232 ParentDeopt.Inputs.end());
1224 ParentDeopt->Inputs.begin(),
1225 ParentDeopt->Inputs.end());
12331226 MergedDeoptArgs.insert(MergedDeoptArgs.end(), ChildOB.Inputs.begin(),
12341227 ChildOB.Inputs.end());
12351228
14221415 }
14231416 }
14241417
1425 // Update the lexical scopes of the new funclets. Anything that had 'none' as
1426 // its parent is now nested inside the callsite's EHPad.
1418 // Update the lexical scopes of the new funclets and callsites.
1419 // Anything that had 'none' as its parent is now nested inside the callsite's
1420 // EHPad.
1421
14271422 if (CallSiteEHPad) {
14281423 for (Function::iterator BB = FirstNewBlock->getIterator(),
14291424 E = Caller->end();
14301425 BB != E; ++BB) {
1426 // Add bundle operands to any top-level call sites.
1427 SmallVector OpBundles;
1428 for (BasicBlock::iterator BBI = BB->begin(), E = BB->end(); BBI != E;) {
1429 Instruction *I = &*BBI++;
1430 CallSite CS(I);
1431 if (!CS)
1432 continue;
1433
1434 // Skip call sites which are nounwind intrinsics.
1435 auto *CalledFn =
1436 dyn_cast(CS.getCalledValue()->stripPointerCasts());
1437 if (CalledFn && CalledFn->isIntrinsic() && CS.doesNotThrow())
1438 continue;
1439
1440 // Skip call sites which already have a "funclet" bundle.
1441 if (CS.getOperandBundle(LLVMContext::OB_funclet))
1442 continue;
1443
1444 CS.getOperandBundlesAsDefs(OpBundles);
1445 OpBundles.emplace_back("funclet", CallSiteEHPad);
1446
1447 Instruction *NewInst;
1448 if (CS.isCall())
1449 NewInst = CallInst::Create(cast(I), OpBundles, I);
1450 else
1451 NewInst = InvokeInst::Create(cast(I), OpBundles, I);
1452 NewInst->setDebugLoc(I->getDebugLoc());
1453 NewInst->takeName(I);
1454 I->replaceAllUsesWith(NewInst);
1455 I->eraseFromParent();
1456
1457 OpBundles.clear();
1458 }
1459
14311460 Instruction *I = BB->getFirstNonPHI();
14321461 if (!I->isEHPad())
14331462 continue;
11791179 Deref, Offset);
11801180 }
11811181
1182 /// changeToUnreachable - Insert an unreachable instruction before the specified
1183 /// instruction, making it and the rest of the code in the block dead.
1184 static void changeToUnreachable(Instruction *I, bool UseLLVMTrap) {
1182 void llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap) {
11851183 BasicBlock *BB = I->getParent();
11861184 // Loop over all of the successors, removing BB's entry from any PHI
11871185 // nodes.
33 declare i32 @__C_specific_handler(...)
44
55 declare void @f()
6 declare i32 @g()
7 declare void @h(i32)
8 declare i1 @b()
9
6
7 declare void @llvm.foo(i32) nounwind
8 declare void @llvm.bar() nounwind
9 declare i32 @llvm.qux() nounwind
10 declare i1 @llvm.baz() nounwind
1011
1112 define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
1213 entry:
1314 ; %x def colors: {entry} subset of use colors; must spill
14 %x = call i32 @g()
15 %x = call i32 @llvm.qux()
1516 invoke void @f()
1617 to label %noreturn unwind label %catch.switch
1718 catch.switch:
1819 %cs = catchswitch within none [label %catch] unwind to caller
1920 catch:
20 catchpad within %cs []
21 %cp = catchpad within %cs []
2122 br label %noreturn
2223 noreturn:
2324 ; %x use colors: {entry, cleanup}
24 call void @h(i32 %x)
25 call void @llvm.foo(i32 %x)
2526 unreachable
2627 }
2728 ; Need two copies of the call to @h, one under entry and one under catch.
2930 ; for the use in entry's copy.
3031 ; CHECK-LABEL: define void @test1(
3132 ; CHECK: entry:
32 ; CHECK: %x = call i32 @g()
33 ; CHECK: %x = call i32 @llvm.qux()
3334 ; CHECK: invoke void @f()
3435 ; CHECK: to label %[[EntryCopy:[^ ]+]] unwind label %catch
3536 ; CHECK: catch.switch:
3637 ; CHECK: %cs = catchswitch within none [label %catch] unwind to caller
3738 ; CHECK: catch:
3839 ; CHECK: catchpad within %cs []
39 ; CHECK-NEXT: call void @h(i32 %x)
40 ; CHECK-NEXT: call void @llvm.foo(i32 %x)
4041 ; CHECK: [[EntryCopy]]:
41 ; CHECK: call void @h(i32 %x)
42 ; CHECK: call void @llvm.foo(i32 %x)
4243
4344
4445 define void @test2() personality i32 (...)* @__CxxFrameHandler3 {
4950 cleanuppad within none []
5051 br label %exit
5152 exit:
52 call void @f()
53 call void @llvm.bar()
5354 ret void
5455 }
5556 ; Need two copies of %exit's call to @f -- the subsequent ret is only
6162 ; CHECK: to label %[[exit:[^ ]+]] unwind label %cleanup
6263 ; CHECK: cleanup:
6364 ; CHECK: cleanuppad within none []
64 ; CHECK: call void @f()
65 ; CHECK: call void @llvm.bar()
6566 ; CHECK-NEXT: unreachable
6667 ; CHECK: [[exit]]:
67 ; CHECK: call void @f()
68 ; CHECK: call void @llvm.bar()
6869 ; CHECK-NEXT: ret void
6970
7071
8485 cleanuppad within none []
8586 br label %shared
8687 shared:
87 call void @f()
88 call void @llvm.bar()
8889 br label %exit
8990 exit:
9091 ret void
9798 ; CHECK: to label %[[exit:[^ ]+]] unwind
9899 ; CHECK: catch:
99100 ; CHECK: catchpad within %cs []
100 ; CHECK-NEXT: call void @f()
101 ; CHECK-NEXT: call void @llvm.bar()
101102 ; CHECK-NEXT: unreachable
102103 ; CHECK: cleanup:
103104 ; CHECK: cleanuppad within none []
104 ; CHECK: call void @f()
105 ; CHECK: call void @llvm.bar()
105106 ; CHECK-NEXT: unreachable
106107 ; CHECK: [[exit]]:
107108 ; CHECK: ret void
117118 catchpad within %cs []
118119 br label %shared
119120 shared:
120 %x = call i32 @g()
121 %i = call i32 @g()
121 %x = call i32 @llvm.qux()
122 %i = call i32 @llvm.qux()
122123 %zero.trip = icmp eq i32 %i, 0
123124 br i1 %zero.trip, label %exit, label %loop
124125 loop:
125126 %i.loop = phi i32 [ %i, %shared ], [ %i.dec, %loop.tail ]
126 %b = call i1 @b()
127 %b = call i1 @llvm.baz()
127128 br i1 %b, label %left, label %right
128129 left:
129 %y = call i32 @g()
130 %y = call i32 @llvm.qux()
130131 br label %loop.tail
131132 right:
132 call void @h(i32 %x)
133 call void @llvm.foo(i32 %x)
133134 br label %loop.tail
134135 loop.tail:
135136 %i.dec = sub i32 %i.loop, 1
136137 %done = icmp eq i32 %i.dec, 0
137138 br i1 %done, label %exit, label %loop
138139 exit:
139 call void @h(i32 %x)
140 call void @llvm.foo(i32 %x)
140141 unreachable
141142 }
142143 ; Make sure we can clone regions that have internal control
147148 ; CHECK: to label %[[shared_E:[^ ]+]] unwind label %catch.switch
148149 ; CHECK: catch:
149150 ; CHECK: catchpad within %cs []
150 ; CHECK: [[x_C:%[^ ]+]] = call i32 @g()
151 ; CHECK: [[i_C:%[^ ]+]] = call i32 @g()
151 ; CHECK: [[x_C:%[^ ]+]] = call i32 @llvm.qux()
152 ; CHECK: [[i_C:%[^ ]+]] = call i32 @llvm.qux()
152153 ; CHECK: [[zt_C:%[^ ]+]] = icmp eq i32 [[i_C]], 0
153154 ; CHECK: br i1 [[zt_C]], label %[[exit_C:[^ ]+]], label %[[loop_C:[^ ]+]]
154155 ; CHECK: [[shared_E]]:
155 ; CHECK: [[x_E:%[^ ]+]] = call i32 @g()
156 ; CHECK: [[i_E:%[^ ]+]] = call i32 @g()
156 ; CHECK: [[x_E:%[^ ]+]] = call i32 @llvm.qux()
157 ; CHECK: [[i_E:%[^ ]+]] = call i32 @llvm.qux()
157158 ; CHECK: [[zt_E:%[^ ]+]] = icmp eq i32 [[i_E]], 0
158159 ; CHECK: br i1 [[zt_E]], label %[[exit_E:[^ ]+]], label %[[loop_E:[^ ]+]]
159160 ; CHECK: [[loop_C]]:
160161 ; CHECK: [[iloop_C:%[^ ]+]] = phi i32 [ [[i_C]], %catch ], [ [[idec_C:%[^ ]+]], %[[looptail_C:[^ ]+]] ]
161 ; CHECK: [[b_C:%[^ ]+]] = call i1 @b()
162 ; CHECK: [[b_C:%[^ ]+]] = call i1 @llvm.baz()
162163 ; CHECK: br i1 [[b_C]], label %[[left_C:[^ ]+]], label %[[right_C:[^ ]+]]
163164 ; CHECK: [[loop_E]]:
164165 ; CHECK: [[iloop_E:%[^ ]+]] = phi i32 [ [[i_E]], %[[shared_E]] ], [ [[idec_E:%[^ ]+]], %[[looptail_E:[^ ]+]] ]
165 ; CHECK: [[b_E:%[^ ]+]] = call i1 @b()
166 ; CHECK: [[b_E:%[^ ]+]] = call i1 @llvm.baz()
166167 ; CHECK: br i1 [[b_E]], label %[[left_E:[^ ]+]], label %[[right_E:[^ ]+]]
167168 ; CHECK: [[left_C]]:
168 ; CHECK: [[y_C:%[^ ]+]] = call i32 @g()
169 ; CHECK: [[y_C:%[^ ]+]] = call i32 @llvm.qux()
169170 ; CHECK: br label %[[looptail_C]]
170171 ; CHECK: [[left_E]]:
171 ; CHECK: [[y_E:%[^ ]+]] = call i32 @g()
172 ; CHECK: [[y_E:%[^ ]+]] = call i32 @llvm.qux()
172173 ; CHECK: br label %[[looptail_E]]
173174 ; CHECK: [[right_C]]:
174 ; CHECK: call void @h(i32 [[x_C]])
175 ; CHECK: call void @llvm.foo(i32 [[x_C]])
175176 ; CHECK: br label %[[looptail_C]]
176177 ; CHECK: [[right_E]]:
177 ; CHECK: call void @h(i32 [[x_E]])
178 ; CHECK: call void @llvm.foo(i32 [[x_E]])
178179 ; CHECK: br label %[[looptail_E]]
179180 ; CHECK: [[looptail_C]]:
180181 ; CHECK: [[idec_C]] = sub i32 [[iloop_C]], 1
185186 ; CHECK: [[done_E:%[^ ]+]] = icmp eq i32 [[idec_E]], 0
186187 ; CHECK: br i1 [[done_E]], label %[[exit_E]], label %[[loop_E]]
187188 ; CHECK: [[exit_C]]:
188 ; CHECK: call void @h(i32 [[x_C]])
189 ; CHECK: call void @llvm.foo(i32 [[x_C]])
189190 ; CHECK: unreachable
190191 ; CHECK: [[exit_E]]:
191 ; CHECK: call void @h(i32 [[x_E]])
192 ; CHECK: call void @llvm.foo(i32 [[x_E]])
192193 ; CHECK: unreachable
193194
194195
198199 to label %exit unwind label %outer
199200 outer:
200201 %o = cleanuppad within none []
201 %x = call i32 @g()
202 invoke void @f()
202 %x = call i32 @llvm.qux()
203 invoke void @f() [ "funclet"(token %o) ]
203204 to label %outer.ret unwind label %catch.switch
204205 catch.switch:
205206 %cs = catchswitch within %o [label %inner] unwind to caller
207208 %i = catchpad within %cs []
208209 catchret from %i to label %outer.post-inner
209210 outer.post-inner:
210 call void @h(i32 %x)
211 call void @llvm.foo(i32 %x)
211212 br label %outer.ret
212213 outer.ret:
213214 cleanupret from %o unwind to caller
219220 ; and so don't need to be spilled.
220221 ; CHECK-LABEL: define void @test5(
221222 ; CHECK: outer:
222 ; CHECK: %x = call i32 @g()
223 ; CHECK: %x = call i32 @llvm.qux()
223224 ; CHECK-NEXT: invoke void @f()
224225 ; CHECK-NEXT: to label %outer.ret unwind label %catch.switch
225226 ; CHECK: inner:
226227 ; CHECK-NEXT: %i = catchpad within %cs []
227228 ; CHECK-NEXT: catchret from %i to label %outer.post-inner
228229 ; CHECK: outer.post-inner:
229 ; CHECK-NEXT: call void @h(i32 %x)
230 ; CHECK-NEXT: call void @llvm.foo(i32 %x)
230231 ; CHECK-NEXT: br label %outer.ret
231232
232233
233 define void @test6() personality i32 (...)* @__C_specific_handler {
234 define void @test9() personality i32 (...)* @__C_specific_handler {
234235 entry:
235236 invoke void @f()
236237 to label %invoke.cont unwind label %left
237238 invoke.cont:
238239 invoke void @f()
239 to label %exit unwind label %right
240 left:
241 cleanuppad within none []
242 br label %shared
243 right:
244 %cs = catchswitch within none [label %right.catch] unwind to caller
245 right.catch:
246 catchpad within %cs []
247 br label %shared
248 shared:
249 %x = call i32 @g()
250 invoke void @f()
251 to label %shared.cont unwind label %inner
252 shared.cont:
253 unreachable
254 inner:
255 %i = cleanuppad within none []
256 call void @h(i32 %x)
257 cleanupret from %i unwind to caller
258 exit:
259 ret void
260 }
261 ; CHECK-LABEL: define void @test6(
262 ; CHECK: left:
263 ; CHECK: %x.for.left = call i32 @g()
264 ; CHECK: invoke void @f()
265 ; CHECK: to label %shared.cont.for.left unwind label %inner
266 ; CHECK: right.catch:
267 ; CHECK: catchpad
268 ; CHECK: %x = call i32 @g()
269 ; CHECK: to label %shared.cont unwind label %inner
270 ; CHECK: shared.cont:
271 ; CHECK: unreachable
272 ; CHECK: shared.cont.for.left:
273 ; CHECK: unreachable
274 ; CHECK: inner:
275 ; CHECK: %i = cleanuppad within none []
276 ; CHECK: call void @h(i32 %x1.wineh.reload)
277 ; CHECK: cleanupret from %i unwind to caller
278
279
280 define void @test9() personality i32 (...)* @__C_specific_handler {
281 entry:
282 invoke void @f()
283 to label %invoke.cont unwind label %left
284 invoke.cont:
285 invoke void @f()
286240 to label %unreachable unwind label %right
287241 left:
288 cleanuppad within none []
289 call void @h(i32 1)
290 invoke void @f()
242 %cp.left = cleanuppad within none []
243 call void @llvm.foo(i32 1)
244 invoke void @f() [ "funclet"(token %cp.left) ]
291245 to label %unreachable unwind label %right
292246 right:
293 cleanuppad within none []
294 call void @h(i32 2)
295 invoke void @f()
247 %cp.right = cleanuppad within none []
248 call void @llvm.foo(i32 2)
249 invoke void @f() [ "funclet"(token %cp.right) ]
296250 to label %unreachable unwind label %left
297251 unreachable:
298252 unreachable
304258 ; CHECK: invoke.cont:
305259 ; CHECK: to label %[[UNREACHABLE_ENTRY:.+]] unwind label %[[RIGHT:.+]]
306260 ; CHECK: [[LEFT]]:
307 ; CHECK: call void @h(i32 1)
261 ; CHECK: call void @llvm.foo(i32 1)
308262 ; CHECK: invoke void @f()
309263 ; CHECK: to label %[[UNREACHABLE_LEFT:.+]] unwind label %[[RIGHT]]
310264 ; CHECK: [[RIGHT]]:
311 ; CHECK: call void @h(i32 2)
265 ; CHECK: call void @llvm.foo(i32 2)
312266 ; CHECK: invoke void @f()
313267 ; CHECK: to label %[[UNREACHABLE_RIGHT:.+]] unwind label %[[LEFT]]
314268 ; CHECK: [[UNREACHABLE_RIGHT]]:
360314 to label %exit unwind label %cleanup.outer
361315 cleanup.outer:
362316 %outer = cleanuppad within none []
363 invoke void @f()
317 invoke void @f() [ "funclet"(token %outer) ]
364318 to label %outer.cont unwind label %cleanup.inner
365319 outer.cont:
366320 br label %merge
368322 %inner = cleanuppad within %outer []
369323 br label %merge
370324 merge:
371 call void @f()
325 call void @llvm.bar()
372326 unreachable
373327 exit:
374328 ret void
378332 ; rewritten to call @f()
379333 ; CHECK-LABEL: define void @test11()
380334 ; CHECK: %inner = cleanuppad within %outer []
381 ; CHECK-NEXT: call void @f()
335 ; CHECK-NEXT: call void @llvm.bar()
382336 ; CHECK-NEXT: unreachable
383337
384338 define void @test12() personality i32 (...)* @__CxxFrameHandler3 !dbg !5 {
397351 join:
398352 ; This call will get cloned; make sure we can handle cloning
399353 ; instructions with debug metadata attached.
400 call void @f(), !dbg !9
354 call void @llvm.bar(), !dbg !9
401355 unreachable
402356 exit:
403357 ret void
88 declare void @h(i32)
99
1010 declare i1 @i()
11
12 declare void @llvm.bar() nounwind
1113
1214 ; CHECK-LABEL: @test1(
1315 define void @test1(i1 %B) personality i32 (...)* @__CxxFrameHandler3 {
4244 ; CHECK: catch:
4345 ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
4446 ; CHECK-NEXT: call void @h(i32 [[Reload]])
45 call void @h(i32 %phi)
47 call void @h(i32 %phi) [ "funclet"(token %cp) ]
4648 catchret from %cp to label %exit
4749
4850 exit:
8082 %cpinner = catchpad within %cs1 []
8183 ; Need just one store here because only %y is affected
8284 ; CHECK: catch.inner:
83 %z = call i32 @g()
85 %z = call i32 @g() [ "funclet"(token %cpinner) ]
8486 ; CHECK: store i32 %z
8587 ; CHECK-NEXT: invoke void @f
86 invoke void @f()
88 invoke void @f() [ "funclet"(token %cpinner) ]
8789 to label %catchret.inner unwind label %merge.outer
8890
8991 catchret.inner:
105107 ; CHECK-DAG: load i32, i32* [[Slot1]]
106108 ; CHECK-DAG: load i32, i32* [[Slot2]]
107109 ; CHECK: catchret from [[CatchPad]] to label
108 call void @h(i32 %x)
109 call void @h(i32 %y)
110 call void @h(i32 %x) [ "funclet"(token %cpouter) ]
111 call void @h(i32 %y) [ "funclet"(token %cpouter) ]
110112 catchret from %cpouter to label %exit
111113
112114 exit:
165167 ; CHECK: [[Reload:%[^ ]+]] = load i32, i32* [[Slot]]
166168 ; CHECK: call void @h(i32 [[Reload]])
167169 %cp2 = catchpad within %cs2 []
168 call void @h(i32 %phi.outer)
170 call void @h(i32 %phi.outer) [ "funclet"(token %cp2) ]
169171 catchret from %cp2 to label %exit
170172 exit:
171173 ret void
196198 ; CHECK: [[CleanupReload:%[^ ]+]] = load i32, i32* [[CleanupSlot]]
197199 %phi.cleanup = phi i32 [ 1, %entry ], [ 2, %invoke.cont ]
198200 %cp = cleanuppad within none []
199 %b = call i1 @i()
201 %b = call i1 @i() [ "funclet"(token %cp) ]
200202 br i1 %b, label %left, label %right
201203
202204 left:
203205 ; CHECK: left:
204206 ; CHECK: call void @h(i32 [[CleanupReload]]
205 call void @h(i32 %phi.cleanup)
207 call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
206208 br label %merge
207209
208210 right:
209211 ; CHECK: right:
210212 ; CHECK: call void @h(i32 [[CleanupReload]]
211 call void @h(i32 %phi.cleanup)
213 call void @h(i32 %phi.cleanup) [ "funclet"(token %cp) ]
212214 br label %merge
213215
214216 merge:
238240 ; CHECK: [[CatchReload:%[^ ]+]] = load i32, i32* [[CatchSlot]]
239241 ; CHECK: call void @h(i32 [[CatchReload]]
240242 %cp2 = catchpad within %cs1 []
241 call void @h(i32 %phi.catch)
243 call void @h(i32 %phi.catch) [ "funclet"(token %cp2) ]
242244 catchret from %cp2 to label %exit
243245
244246 exit:
264266 ; CHECK: cleanup:
265267 ; CHECK: call void @h(i32 %x)
266268 %cp2 = cleanuppad within none []
267 call void @h(i32 %x)
269 call void @h(i32 %x) [ "funclet"(token %cp2) ]
268270 cleanupret from %cp2 unwind to caller
269271 }
270272
294296 ; CHECK: catch:
295297 ; CHECK-NEXT: %[[CatchPad:[^ ]+]] = catchpad within %cs1 []
296298 %cp = catchpad within %cs1 []
297 %b = call i1 @i()
299 %b = call i1 @i() [ "funclet"(token %cp) ]
298300 br i1 %b, label %left, label %right
299301 left:
300302 ; Edge from %left to %join needs to be split so that
311313 ; CHECK: right:
312314 ; CHECK: %y = call i32 @g()
313315 ; CHECK: catchret from %[[CatchPad]] to label %join
314 %y = call i32 @g()
316 %y = call i32 @g() [ "funclet"(token %cp) ]
315317 catchret from %cp to label %join
316318 join:
317319 ; CHECK: join:
335337
336338 cleanup1:
337339 ; CHECK: [[CleanupPad1:%[^ ]+]] = cleanuppad within none []
338 ; CHECK-NEXT: call void @f()
340 ; CHECK-NEXT: call void @llvm.bar()
339341 ; CHECK-NEXT: cleanupret from [[CleanupPad1]]
340342 %cp0 = cleanuppad within none []
341343 br label %cleanupexit
342344
343345 cleanup2:
344346 ; CHECK: cleanuppad within none []
345 ; CHECK-NEXT: call void @f()
347 ; CHECK-NEXT: call void @llvm.bar()
346348 ; CHECK-NEXT: unreachable
347349 %cp1 = cleanuppad within none []
348350 br label %cleanupexit
349351
350352 cleanupexit:
351 call void @f()
353 call void @llvm.bar()
352354 cleanupret from %cp0 unwind label %cleanup2
353355 }
None ; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare -disable-demotion < %s | FileCheck %s
0 ; RUN: opt -mtriple=x86_x64-pc-windows-msvc -S -winehprepare -disable-demotion -disable-cleanups < %s | FileCheck %s
11
22 declare i32 @__CxxFrameHandler3(...)
33
1010 declare void @h(i32)
1111
1212 ; CHECK-LABEL: @test1(
13 define void @test1() personality i32 (...)* @__C_specific_handler {
13 define void @test1(i1 %bool) personality i32 (...)* @__C_specific_handler {
1414 entry:
1515 invoke void @f()
16 to label %invoke.cont1 unwind label %left
16 to label %invoke.cont unwind label %left
1717
18 invoke.cont1:
19 invoke void @f()
20 to label %invoke.cont2 unwind label %right
21
22 invoke.cont2:
18 invoke.cont:
2319 invoke void @f()
2420 to label %exit unwind label %inner
2521
2622 left:
2723 %0 = cleanuppad within none []
28 br label %shared
24 br i1 %bool, label %shared, label %cleanupret
25
26 cleanupret:
27 cleanupret from %0 unwind label %right
2928
3029 right:
3130 %1 = cleanuppad within none []
3332
3433 shared:
3534 %x = call i32 @g()
36 invoke void @f()
35 invoke void @f() [ "funclet"(token %0) ]
3736 to label %shared.cont unwind label %inner
3837
3938 shared.cont:
4039 unreachable
4140
4241 inner:
43 %phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont2 ]
42 %phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont ]
4443 %i = cleanuppad within none []
4544 call void @h(i32 %phi)
4645 unreachable
4746
48 ; CHECK: %phi = phi i32 [ %x, %right ], [ 0, %invoke.cont2 ], [ %x.for.left, %left ]
47 ; CHECK: %phi = phi i32 [ %x, %shared ], [ 0, %invoke.cont ], [ %x.for.left, %shared.for.left ]
4948 ; CHECK: %i = cleanuppad within none []
5049 ; CHECK: call void @h(i32 %phi)
5150
5453 }
5554
5655 ; CHECK-LABEL: @test2(
57 define void @test2() personality i32 (...)* @__C_specific_handler {
56 define void @test2(i1 %bool) personality i32 (...)* @__C_specific_handler {
5857 entry:
5958 invoke void @f()
60 to label %invoke.cont unwind label %left
61
62 invoke.cont:
63 invoke void @f()
64 to label %exit unwind label %right
59 to label %shared.cont unwind label %left
6560
6661 left:
67 cleanuppad within none []
68 br label %shared
62 %0 = cleanuppad within none []
63 br i1 %bool, label %shared, label %cleanupret
64
65 cleanupret:
66 cleanupret from %0 unwind label %right
6967
7068 right:
71 cleanuppad within none []
69 %1 = cleanuppad within none []
7270 br label %shared
7371
7472 shared:
7573 %x = call i32 @g()
76 invoke void @f()
74 invoke void @f() [ "funclet"(token %0) ]
7775 to label %shared.cont unwind label %inner
7876
7977 shared.cont:
8482 call void @h(i32 %x)
8583 unreachable
8684
87 ; CHECK: %x1 = phi i32 [ %x.for.left, %left ], [ %x, %right ]
88 ; CHECK: %i = cleanuppad within none []
89 ; CHECK: call void @h(i32 %x1)
85 ; CHECK: %x1 = phi i32 [ %x.for.left, %shared.for.left ], [ %x, %shared ]
86 ; CHECK: %i = cleanuppad within none []
87 ; CHECK: call void @h(i32 %x1)
9088
9189 exit:
9290 unreachable
118116 call void @h(i32 %phi)
119117 unreachable
120118
121 ; CHECK: %0 = cleanuppad within none []
122 ; CHECK: call void @h(i32 1)
123
124 ; CHECK: %1 = cleanuppad within none []
125119 ; CHECK: %phi = phi i32 [ 0, %right ], [ -1, %right.other ]
126120 ; CHECK: call void @h(i32 %phi)
121
122 ; CHECK: %phi.for.left = phi i32 [ 1, %left ]
123 ; CHECK: call void @h(i32 %phi.for.left)
127124
128125 exit:
129126 unreachable
5757
5858 ehcleanup: ; preds = %catchendblock
5959 %4 = cleanuppad within none []
60 call void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* nonnull %o) #4
60 call void @"\01??1HasDtor@@QEAA@XZ"(%struct.HasDtor* nonnull %o) #4 [ "funclet"(token %4) ]
6161 cleanupret from %4 unwind to caller
6262 }
6363
2929
3030 ehcleanup: ; preds = %entry
3131 %2 = cleanuppad within none []
32 call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %0)
32 call x86_thiscallcc void @"\01??1A@@QAE@XZ"(%struct.A* %0) [ "funclet"(token %2) ]
3333 cleanupret from %2 unwind to caller
3434 }
3535
99 to label %exit unwind label %cleanup
1010 cleanup:
1111 %c = cleanuppad within none []
12 call void @bar()
12 call void @bar() [ "funclet"(token %c) ]
1313 cleanupret from %c unwind to caller
1414 exit:
1515 ret void
1717
1818 ehcleanup: ; preds = %entry
1919 %0 = cleanuppad within none []
20 call void @Dtor(i64* %o)
20 call void @Dtor(i64* %o) [ "funclet"(token %0) ]
2121 cleanupret from %0 unwind to caller
2222 }
2323
5858
5959 catch: ; preds = %catch.dispatch
6060 %0 = catchpad within %cs1 [i8* null, i32 64, i8* null]
61 invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1
61 invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #1 ["funclet"(token %0)]
6262 to label %unreachable unwind label %catch.dispatch.1
6363
6464 catch.dispatch.1: ; preds = %catch
109109
110110 catch.2: ; preds = %catch.dispatch
111111 %0 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
112 tail call void @exit(i32 0) #2
112 tail call void @exit(i32 0) #2 [ "funclet"(token %0) ]
113113 unreachable
114114
115115 catch.dispatch.1: ; preds = %catch.dispatch
117117
118118 catch: ; preds = %catch.dispatch.1
119119 %1 = catchpad within %cs2 [i8* null, i32 64, i8* null]
120 tail call void @exit(i32 0) #2
120 tail call void @exit(i32 0) #2 [ "funclet"(token %1) ]
121121 unreachable
122122
123123 try.cont: ; preds = %entry
2626 __except: ; preds = %lpad
2727 %p = catchpad within %cs1 [i8* bitcast (i32 ()* @"filt$main" to i8*)]
2828 %code = load i32, i32* %__exceptioncode, align 4
29 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4
29 %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) ]
3030 catchret from %p to label %__try.cont
3131
3232 __try.cont: ; preds = %entry, %__except
2020 catchall:
2121 %p = catchpad within %cs1 [i8* null, i32 64, i8* null]
2222 %code = call i32 @llvm.eh.exceptioncode(token %p)
23 call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i64 0, i64 0), i32 %code)
23 call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i64 0, i64 0), i32 %code) [ "funclet"(token %p) ]
2424 catchret from %p to label %__try.cont
2525 }
2626
6868
6969 ehcleanup: ; preds = %__except.2
7070 %cp2 = cleanuppad within none []
71 invoke fastcc void @"\01?fin$0@0@main@@"() #4
71 invoke fastcc void @"\01?fin$0@0@main@@"() #4 [ "funclet"(token %cp2) ]
7272 to label %invoke.cont.6 unwind label %catch.dispatch.7
7373
7474 invoke.cont.6: ; preds = %ehcleanup
5050 __finally: ; preds = %entry
5151 %cleanuppad = cleanuppad within none []
5252 %locals = call i8* @llvm.localaddress()
53 invoke void @"\01?fin$0@0@use_both@@"(i1 zeroext true, i8* %locals) #5
53 invoke void @"\01?fin$0@0@use_both@@"(i1 zeroext true, i8* %locals) #5 [ "funclet"(token %cleanuppad) ]
5454 to label %invoke.cont3 unwind label %catch.dispatch
5555
5656 invoke.cont3: ; preds = %__finally
6161
6262 __except: ; preds = %catch.dispatch
6363 %catchpad = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @"\01?filt$0@0@use_both@@" to i8*)]
64 %call = call i32 @puts(i8* getelementptr inbounds ([9 x i8], [9 x i8]* @"\01??_C@_08MLCMLGHM@__except?$AA@", i32 0, i32 0))
64 %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) ]
6565 catchret from %catchpad to label %__try.cont
6666
6767 __try.cont: ; preds = %__except, %invoke.cont2
1717
1818 lpad: ; preds = %entry
1919 %p = cleanuppad within none []
20 %call2 = call i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str_recovered, i64 0, i64 0))
20 %call2 = call i32 @puts(i8* getelementptr inbounds ([10 x i8], [10 x i8]* @str_recovered, i64 0, i64 0)) [ "funclet"(token %p) ]
2121 cleanupret from %p unwind to caller
2222 }
2323
3434
3535 handler0:
3636 %p0 = catchpad within %cs0 [i8* bitcast (i32 ()* @safe_div_filt0 to i8*)]
37 call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0))
37 call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0)) [ "funclet"(token %p0) ]
3838 store i32 -1, i32* %r, align 4
3939 catchret from %p0 to label %__try.cont
4040
4343
4444 handler1:
4545 %p1 = catchpad within %cs1 [i8* bitcast (i32 ()* @safe_div_filt1 to i8*)]
46 call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0))
46 call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0)) [ "funclet"(token %p1) ]
4747 store i32 -2, i32* %r, align 4
4848 catchret from %p1 to label %__try.cont
4949
3333
3434 handler0:
3535 %p0 = catchpad within %cs0 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt0 to i8*)]
36 call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0))
36 call void @puts(i8* getelementptr ([27 x i8], [27 x i8]* @str1, i32 0, i32 0)) [ "funclet"(token %p0) ]
3737 store i32 -1, i32* %r, align 4
3838 catchret from %p0 to label %__try.cont
3939
4242
4343 handler1:
4444 %p1 = catchpad within %cs1 [i8* bitcast (i32 (i8*, i8*)* @safe_div_filt1 to i8*)]
45 call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0))
45 call void @puts(i8* getelementptr ([29 x i8], [29 x i8]* @str2, i32 0, i32 0)) [ "funclet"(token %p1) ]
4646 store i32 -2, i32* %r, align 4
4747 catchret from %p1 to label %__try.cont
4848
2727 __except: ; preds = %lpad
2828 %p = catchpad within %cs1 [i8* bitcast (i32 ()* @"filt$main" to i8*)]
2929 %code = load i32, i32* %__exceptioncode, align 4
30 %call = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([27 x i8], [27 x i8]* @str, i32 0, i32 0), i32 %code) #4
30 %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) ]
3131 catchret from %p to label %__try.cont
3232
3333 __try.cont: ; preds = %entry, %__except
3333
3434 handler1:
3535 %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
36 call void @f(i32 2)
36 call void @f(i32 2) [ "funclet"(token %h1) ]
3737 catchret from %h1 to label %try.cont
3838 }
3939
3030 %cs1 = catchswitch within none [label %handler1] unwind to caller
3131 handler1:
3232 %h1 = catchpad within %cs1 [i8* null, i32 64, i8* null]
33 invoke void @f(i32 2)
33 invoke void @f(i32 2) [ "funclet"(token %h1) ]
3434 to label %catchret1 unwind label %catch.dispatch.2
3535 catchret1:
3636 catchret from %h1 to label %try.cont
1515
1616 outer.catch:
1717 %cp1 = catchpad within %cs1 [i32 1]
18 invoke void @f()
18 invoke void @f() [ "funclet"(token %cp1) ]
1919 to label %outer.ret unwind label %catch.dispatch.2
2020 outer.ret:
2121 catchret from %cp1 to label %exit
4040 handler1:
4141 %h1 = catchpad within %cs [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i32* %e.addr]
4242 %e = load i32, i32* %e.addr
43 call void @f(i32 %e, i32* %local)
43 call void @f(i32 %e, i32* %local) [ "funclet"(token %h1) ]
4444 catchret from %h1 to label %try.cont
4545
4646 handler2:
4747 %h2 = catchpad within %cs [i8* null, i32 64, i8* null]
48 call void @f(i32 3, i32* %local)
48 call void @f(i32 3, i32* %local) [ "funclet"(token %h2) ]
4949 catchret from %h2 to label %try.cont
5050
5151 try.cont:
228228 br label %loop
229229
230230 loop:
231 %V = call i1 @getbool()
231 %V = call i1 @getbool() [ "funclet"(token %cp1) ]
232232 br i1 %V, label %loop, label %catch.done
233233
234234 catch.done:
1414
1515 ehcleanup: ; preds = %entry
1616 %0 = cleanuppad within none []
17 call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o) #2
17 call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o) #2 [ "funclet"(token %0) ]
1818 cleanupret from %0 unwind to caller
1919 }
2020
7777
7878 cleanup.inner: ; preds = %invoke.cont
7979 %0 = cleanuppad within none []
80 call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o2) #2
80 call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o2) #2 [ "funclet"(token %0) ]
8181 cleanupret from %0 unwind label %cleanup.outer
8282
8383 cleanup.outer: ; preds = %invoke.cont.1, %cleanup.inner, %entry
8484 %1 = cleanuppad within none []
85 call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o1) #2
85 call x86_thiscallcc void @"\01??1Dtor@@QAE@XZ"(%struct.Dtor* %o1) #2 [ "funclet"(token %1) ]
8686 cleanupret from %1 unwind to caller
8787 }
8888
99
1010 cleanupblock:
1111 %cleanp = cleanuppad within none []
12 call void @g()
12 call void @g() [ "funclet"(token %cleanp) ]
1313 cleanupret from %cleanp unwind label %catch.dispatch
1414
1515 catch.dispatch:
1717
1818 catch:
1919 %cp = catchpad within %cs1 [i8* null, i32 64, i8* null]
20 call void @g()
20 call void @g() [ "funclet"(token %cp) ]
2121 catchret from %cp to label %try.cont
2222
2323 try.cont:
4747
4848 catch: ; preds = %lpad.1
4949 %p1 = catchpad within %cs1 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
50 invoke void @may_throw(i32 3)
50 invoke void @may_throw(i32 3) [ "funclet"(token %p1) ]
5151 to label %invoke.cont.3 unwind label %lpad.1
5252
5353 invoke.cont.3: ; preds = %catch
5858
5959 catch.7:
6060 %p2 = catchpad within %cs2 [%rtti.TypeDescriptor2* @"\01??_R0H@8", i32 0, i8* null]
61 call void @may_throw(i32 4)
61 call void @may_throw(i32 4) [ "funclet"(token %p2) ]
6262 catchret from %p2 to label %try.cont.9
6363 }
6464
130130
131131 catch: ; preds = %catch.dispatch
132132 %1 = catchpad within %0 [i8* null, i32 64, i8* null]
133 invoke void @may_throw(i32 0)
133 invoke void @may_throw(i32 0) [ "funclet"(token %1) ]
134134 to label %invoke.cont unwind label %ehcleanup5
135135
136136 invoke.cont: ; preds = %catch
137 invoke void @may_throw(i32 1)
137 invoke void @may_throw(i32 1) [ "funclet"(token %1) ]
138138 to label %invoke.cont2 unwind label %ehcleanup
139139
140140 invoke.cont2: ; preds = %invoke.cont
141 invoke void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y)
141 invoke void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y) [ "funclet"(token %1) ]
142142 to label %invoke.cont3 unwind label %ehcleanup5
143143
144144 invoke.cont3: ; preds = %invoke.cont2
145 invoke void @may_throw(i32 2)
145 invoke void @may_throw(i32 2) [ "funclet"(token %1) ]
146146 to label %invoke.cont4 unwind label %ehcleanup5
147147
148148 invoke.cont4: ; preds = %invoke.cont3
154154
155155 ehcleanup: ; preds = %invoke.cont
156156 %2 = cleanuppad within %1 []
157 call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y)
157 call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %y) [ "funclet"(token %2) ]
158158 cleanupret from %2 unwind label %ehcleanup5
159159
160160 ehcleanup5: ; preds = %invoke.cont2, %invoke.cont3, %ehcleanup, %catch, %catch.dispatch
161161 %3 = cleanuppad within none []
162 call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %x)
162 call void @"\01??1S@@QEAA@XZ"(%struct.S* nonnull %x) [ "funclet"(token %3) ]
163163 cleanupret from %3 unwind to caller
164164
165165 unreachable: ; preds = %entry
192192
193193 __except.ret: ; preds = %catch.dispatch
194194 %0 = catchpad within %cs1 [i8* bitcast (i32 ()* @try_except_filter_catchall to i8*)]
195 call void @f(i32 2)
195 call void @f(i32 2) [ "funclet"(token %0) ]
196196 catchret from %0 to label %__except
197197
198198 __except:
1717
1818 ehcleanup: ; preds = %entry
1919 %0 = cleanuppad within none []
20 invoke void @f(i32 2) #3
20 invoke void @f(i32 2) #3 [ "funclet"(token %0) ]
2121 to label %invoke.cont.2 unwind label %ehcleanup.3
2222
2323 invoke.cont.2: ; preds = %ehcleanup
2525
2626 ehcleanup.3: ; preds = %invoke.cont.2, %ehcleanup.end, %invoke.cont
2727 %1 = cleanuppad within none []
28 call void @f(i32 3) #3
28 call void @f(i32 3) #3 [ "funclet"(token %1) ]
2929 cleanupret from %1 unwind to caller
3030 }
3131
6464 ; ^ exception pointer passed in rdx
6565 ; CHECK-NEXT: callq g
6666 %exn1 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch1)
67 call void @g(i8 addrspace(1)* %exn1)
67 call void @g(i8 addrspace(1)* %exn1) [ "funclet"(token %catch1) ]
6868 ; CHECK: [[L_before_f3:.+]]:
6969 ; CHECK-NEXT: movl $3, %ecx
7070 ; CHECK-NEXT: callq f
7171 ; CHECK-NEXT: [[L_after_f3:.+]]:
72 invoke void @f(i32 3)
72 invoke void @f(i32 3) [ "funclet"(token %catch1) ]
7373 to label %catch1.ret unwind label %finally.pad
7474 catch1.ret:
7575 catchret from %catch1 to label %finally.clone
8787 ; ^ exception pointer passed in rdx
8888 ; CHECK-NEXT: callq g
8989 %exn2 = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch2)
90 call void @g(i8 addrspace(1)* %exn2)
90 call void @g(i8 addrspace(1)* %exn2) [ "funclet"(token %catch2) ]
9191 ; CHECK: [[L_before_f4:.+]]:
9292 ; CHECK-NEXT: movl $4, %ecx
9393 ; CHECK-NEXT: callq f
9494 ; CHECK-NEXT: [[L_after_f4:.+]]:
95 invoke void @f(i32 4)
95 invoke void @f(i32 4) [ "funclet"(token %catch2) ]
9696 to label %try_in_catch unwind label %finally.pad
9797 try_in_catch:
9898 ; CHECK: # %try_in_catch
100100 ; CHECK-NEXT: movl $5, %ecx
101101 ; CHECK-NEXT: callq f
102102 ; CHECK-NEXT: [[L_after_f5:.+]]:
103 invoke void @f(i32 5)
103 invoke void @f(i32 5) [ "funclet"(token %catch2) ]
104104 to label %catch2.ret unwind label %fault.pad
105105 fault.pad:
106106 ; CHECK: .seh_proc [[L_fault:[^ ]+]]
116116 ; CHECK-NEXT: movl $6, %ecx
117117 ; CHECK-NEXT: callq f
118118 ; CHECK-NEXT: [[L_after_f6:.+]]:
119 invoke void @f(i32 6)
119 invoke void @f(i32 6) [ "funclet"(token %fault) ]
120120 to label %fault.ret unwind label %finally.pad
121121 fault.ret:
122122 cleanupret from %fault unwind label %finally.pad
137137 ; CHECK: .seh_endprologue
138138 ; CHECK-NEXT: movl $7, %ecx
139139 ; CHECK-NEXT: callq f
140 call void @f(i32 7)
140 call void @f(i32 7) [ "funclet"(token %finally) ]
141141 cleanupret from %finally unwind to caller
142142 tail:
143143 call void @f(i32 8)
1818 %catch = catchpad within %cs1 [i32 5]
1919 %exn = call i8 addrspace(1)* @llvm.eh.exceptionpointer.p1i8(token %catch)
2020 %cast_exn = bitcast i8 addrspace(1)* %exn to i32 addrspace(1)*
21 call void @g(i32 addrspace(1)* %cast_exn)
21 call void @g(i32 addrspace(1)* %cast_exn) [ "funclet"(token %catch) ]
2222 catchret from %catch to label %exit
2323 exit:
2424 ret void