llvm.org GIT mirror llvm / aeeca67
[WinEH] Update exception numbering to give handlers their own base state. Differential Revision: http://reviews.llvm.org/D9512 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@237014 91177308-0d34-0410-b5e6-96231b3b80d8 Andrew Kaylor 5 years ago
7 changed file(s) with 388 addition(s) and 19 deletion(s). Raw diff Collapse all Expand all
135135 DenseMap CatchHandlerParentFrameObjIdx;
136136 DenseMap CatchHandlerParentFrameObjOffset;
137137 DenseMap CatchHandlerMaxState;
138 DenseMap HandlerBaseState;
138139 SmallVector UnwindMap;
139140 SmallVector TryBlockMap;
140141 SmallVector, 4> IPToStateList;
298298
299299 // The parent function and the catch handlers contribute to the 'ip2state'
300300 // table.
301
302 // Include ip2state entries for the beginning of the main function and
303 // for catch handler functions.
304 if (F == ParentF) {
305 FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
306 LastEHState = -1;
307 } else if (FuncInfo.HandlerBaseState.count(F)) {
308 FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel,
309 FuncInfo.HandlerBaseState[F]));
310 LastEHState = FuncInfo.HandlerBaseState[F];
311 }
301312 for (const auto &MBB : *MF) {
302313 for (const auto &MI : MBB) {
303314 if (!MI.isEHLabel()) {
322333 assert(BeginLabel == LandingPad->BeginLabels[P.RangeIndex] &&
323334 "Inconsistent landing pad map!");
324335
325 if (SawPotentiallyThrowing) {
336 // FIXME: Should this be using FuncInfo.HandlerBaseState?
337 if (SawPotentiallyThrowing && LastEHState != -1) {
326338 FuncInfo.IPToStateList.push_back(std::make_pair(LastLabel, -1));
327339 SawPotentiallyThrowing = false;
328340 LastEHState = -1;
8181
8282 namespace {
8383 struct WinEHNumbering {
84 WinEHNumbering(WinEHFuncInfo &FuncInfo) : FuncInfo(FuncInfo), NextState(0) {}
84 WinEHNumbering(WinEHFuncInfo &FuncInfo) : FuncInfo(FuncInfo),
85 CurrentBaseState(-1), NextState(0) {}
8586
8687 WinEHFuncInfo &FuncInfo;
88 int CurrentBaseState;
8789 int NextState;
8890
8991 SmallVector HandlerStack;
9092 SmallPtrSet VisitedHandlers;
9193
9294 int currentEHNumber() const {
93 return HandlerStack.empty() ? -1 : HandlerStack.back()->getEHState();
95 return HandlerStack.empty() ? CurrentBaseState : HandlerStack.back()->getEHState();
9496 }
9597
9698 void createUnwindMapEntry(int ToState, ActionHandler *AH);
400402
401403 void WinEHNumbering::processCallSite(ArrayRef Actions,
402404 ImmutableCallSite CS) {
405 DEBUG(dbgs() << "processCallSite (EH state = " << currentEHNumber()
406 << ") for: ");
407 print_name(CS ? CS.getCalledValue() : nullptr);
408 DEBUG(dbgs() << '\n');
409
410 DEBUG(dbgs() << "HandlerStack: \n");
411 for (int I = 0, E = HandlerStack.size(); I < E; ++I) {
412 DEBUG(dbgs() << " ");
413 print_name(HandlerStack[I]->getHandlerBlockOrFunc());
414 DEBUG(dbgs() << '\n');
415 }
416 DEBUG(dbgs() << "Actions: \n");
417 for (int I = 0, E = Actions.size(); I < E; ++I) {
418 DEBUG(dbgs() << " ");
419 print_name(Actions[I]->getHandlerBlockOrFunc());
420 DEBUG(dbgs() << '\n');
421 }
403422 int FirstMismatch = 0;
404423 for (int E = std::min(HandlerStack.size(), Actions.size()); FirstMismatch < E;
405424 ++FirstMismatch) {
406425 if (HandlerStack[FirstMismatch]->getHandlerBlockOrFunc() !=
407426 Actions[FirstMismatch]->getHandlerBlockOrFunc())
408427 break;
428 // Delete any actions that are already represented on the handler stack.
409429 delete Actions[FirstMismatch];
410430 }
411
412 bool EnteringScope = (int)Actions.size() > FirstMismatch;
413431
414432 // Don't recurse while we are looping over the handler stack. Instead, defer
415433 // the numbering of the catch handlers until we are done popping.
424442 HandlerStack.pop_back();
425443 }
426444
427 // We need to create a new state number if we are exiting a try scope and we
428 // will not push any more actions.
429445 int TryHigh = NextState - 1;
430 if (!EnteringScope && !PoppedCatches.empty()) {
431 createUnwindMapEntry(currentEHNumber(), nullptr);
432 ++NextState;
433 }
434
435446 int LastTryLowIdx = 0;
436447 for (int I = 0, E = PoppedCatches.size(); I != E; ++I) {
437448 CatchHandler *CH = PoppedCatches[I];
449 DEBUG(dbgs() << "Popped handler with state " << CH->getEHState() << "\n");
438450 if (I + 1 == E || CH->getEHState() != PoppedCatches[I + 1]->getEHState()) {
439451 int TryLow = CH->getEHState();
440452 auto Handlers =
441453 makeArrayRef(&PoppedCatches[LastTryLowIdx], I - LastTryLowIdx + 1);
454 DEBUG(dbgs() << "createTryBlockMapEntry(" << TryLow << ", " << TryHigh);
455 for (int J = 0; J < Handlers.size(); ++J) {
456 DEBUG(dbgs() << ", ");
457 print_name(Handlers[J]->getHandlerBlockOrFunc());
458 }
459 DEBUG(dbgs() << ")\n");
442460 createTryBlockMapEntry(TryLow, TryHigh, Handlers);
443461 LastTryLowIdx = I + 1;
444462 }
445463 }
446464
447465 for (CatchHandler *CH : PoppedCatches) {
448 if (auto *F = dyn_cast(CH->getHandlerBlockOrFunc()))
466 if (auto *F = dyn_cast(CH->getHandlerBlockOrFunc())) {
467 DEBUG(dbgs() << "Assigning base state " << NextState << " to ");
468 print_name(F);
469 DEBUG(dbgs() << '\n');
470 FuncInfo.HandlerBaseState[F] = NextState;
471 DEBUG(dbgs() << "createUnwindMapEntry(" << currentEHNumber()
472 << ", null)\n");
473 createUnwindMapEntry(currentEHNumber(), nullptr);
474 ++NextState;
449475 calculateStateNumbers(*F);
476 }
450477 delete CH;
451478 }
479
480 // The handler functions may have pushed actions onto the handler stack
481 // that we expected to push here. Compare the handler stack to our
482 // actions again to check for that possibility.
483 if (HandlerStack.size() > FirstMismatch) {
484 for (int E = std::min(HandlerStack.size(), Actions.size());
485 FirstMismatch < E; ++FirstMismatch) {
486 if (HandlerStack[FirstMismatch]->getHandlerBlockOrFunc() !=
487 Actions[FirstMismatch]->getHandlerBlockOrFunc())
488 break;
489 delete Actions[FirstMismatch];
490 }
491 }
492
493 DEBUG(dbgs() << "Pushing actions for CallSite: ");
494 print_name(CS ? CS.getCalledValue() : nullptr);
495 DEBUG(dbgs() << '\n');
452496
453497 bool LastActionWasCatch = false;
454498 for (size_t I = FirstMismatch; I != Actions.size(); ++I) {
456500 bool CurrActionIsCatch = isa(Actions[I]);
457501 // FIXME: Reenable this optimization!
458502 if (CurrActionIsCatch && LastActionWasCatch && false) {
503 DEBUG(dbgs() << "setEHState for handler to " << currentEHNumber()
504 << "\n");
459505 Actions[I]->setEHState(currentEHNumber());
460506 } else {
507 DEBUG(dbgs() << "createUnwindMapEntry(" << currentEHNumber() << ", ");
508 print_name(Actions[I]->getHandlerBlockOrFunc());
509 DEBUG(dbgs() << ")\n");
461510 createUnwindMapEntry(currentEHNumber(), Actions[I]);
511 DEBUG(dbgs() << "setEHState for handler to " << NextState << "\n");
462512 Actions[I]->setEHState(NextState);
463513 NextState++;
464 DEBUG(dbgs() << "Creating unwind map entry for: (");
465 print_name(Actions[I]->getHandlerBlockOrFunc());
466 DEBUG(dbgs() << ", " << currentEHNumber() << ")\n");
467514 }
468515 HandlerStack.push_back(Actions[I]);
469516 LastActionWasCatch = CurrActionIsCatch;
478525 auto I = VisitedHandlers.insert(&F);
479526 if (!I.second)
480527 return; // We've already visited this handler, don't renumber it.
528
529 int OldBaseState = CurrentBaseState;
530 if (FuncInfo.HandlerBaseState.count(&F)) {
531 CurrentBaseState = FuncInfo.HandlerBaseState[&F];
532 }
481533
482534 DEBUG(dbgs() << "Calculating state numbers for: " << F.getName() << '\n');
483535 SmallVector ActionList;
497549 continue;
498550 assert(ActionsCall->getIntrinsicID() == Intrinsic::eh_actions);
499551 parseEHActions(ActionsCall, ActionList);
552 if (ActionList.empty())
553 continue;
500554 processCallSite(ActionList, II);
501555 ActionList.clear();
502556 FuncInfo.LandingPadStateMap[LPI] = currentEHNumber();
557 DEBUG(dbgs() << "Assigning state " << currentEHNumber()
558 << " to landing pad at " << LPI->getParent()->getName()
559 << '\n');
503560 }
504561
505562 FuncInfo.CatchHandlerMaxState[&F] = NextState - 1;
563
564 CurrentBaseState = OldBaseState;
506565 }
507566
508567 /// clear - Clear out all the function-specific state. This returns this
119119 ; CHECK-NEXT: .long ($stateUnwindMap$main)@IMGREL
120120 ; CHECK-NEXT: .long 1
121121 ; CHECK-NEXT: .long ($tryMap$main)@IMGREL
122 ; CHECK-NEXT: .long 1
122 ; CHECK-NEXT: .long 3
123123 ; CHECK-NEXT: .long ($ip2state$main)@IMGREL
124124 ; CHECK-NEXT: .long 40
125125 ; CHECK-NEXT: .long 0
126126 ; CHECK-NEXT: .long ("$stateUnwindMap$?f@@YAXXZ")@IMGREL
127127 ; CHECK-NEXT: .long 2
128128 ; CHECK-NEXT: .long ("$tryMap$?f@@YAXXZ")@IMGREL
129 ; CHECK-NEXT: .long 3
129 ; CHECK-NEXT: .long 6
130130 ; CHECK-NEXT: .long ("$ip2state$?f@@YAXXZ")@IMGREL
131131 ; CHECK-NEXT: .long 32
132132 ; CHECK-NEXT: .long 0
164164 ; CHECK-NEXT: .long "?f@@YAXXZ.catch1"@IMGREL
165165 ; CHECK-NEXT: .long ".L?f@@YAXXZ.catch1$parent_frame_offset"
166166 ; CHECK-NEXT:"$ip2state$?f@@YAXXZ":
167 ; CHECK-NEXT: .long .Lfunc_begin0@IMGREL
168 ; CHECK-NEXT: .long 2
167169 ; CHECK-NEXT: .long .Ltmp0@IMGREL
168170 ; CHECK-NEXT: .long 0
171 ; CHECK-NEXT: .long .Lfunc_begin1@IMGREL
172 ; CHECK-NEXT: .long 3
173 ; CHECK-NEXT: .long .Lfunc_begin2@IMGREL
174 ; CHECK-NEXT: .long -1
169175 ; CHECK-NEXT: .long .Ltmp13@IMGREL
170176 ; CHECK-NEXT: .long 1
171177 ; CHECK-NEXT: .long .Ltmp16@IMGREL
3535 ; CHECK-NEXT: .long ("$stateUnwindMap$?test1@@YAXXZ")@IMGREL
3636 ; CHECK-NEXT: .long 0
3737 ; CHECK-NEXT: .long 0
38 ; CHECK-NEXT: .long 1
38 ; CHECK-NEXT: .long 2
3939 ; CHECK-NEXT: .long ("$ip2state$?test1@@YAXXZ")@IMGREL
4040 ; CHECK-NEXT: .long 32
4141 ; CHECK-NEXT: .long 0
4444 ; CHECK-NEXT: .long -1
4545 ; CHECK-NEXT: .long "?test1@@YAXXZ.cleanup"@IMGREL
4646 ; CHECK-NEXT:"$ip2state$?test1@@YAXXZ":
47 ; CHECK-NEXT: .long .Lfunc_begin0@IMGREL
48 ; CHECK-NEXT: .long -1
4749 ; CHECK-NEXT: .long .Ltmp0@IMGREL
4850 ; CHECK-NEXT: .long 0
4951
0 ; RUN: llc < %s | FileCheck %s
1
2 ; This test was generated from the following code.
3 ;
4 ; void test() {
5 ; try {
6 ; try {
7 ; try {
8 ; two();
9 ; throw 2;
10 ; } catch (int x) {
11 ; catch_two();
12 ; }
13 ; a();
14 ; throw 'a';
15 ; } catch (char c) {
16 ; catch_a();
17 ; }
18 ; one();
19 ; throw 1;
20 ; } catch(int x) {
21 ; catch_one();
22 ; } catch(...) {
23 ; catch_all();
24 ; }
25 ; }
26 ;
27 ; The function calls before the throws were declared as 'noexcept' and are
28 ; just here to make blocks easier to identify in the IR.
29
30 ; ModuleID = ''
31 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
32 target triple = "x86_64-pc-windows-msvc"
33
34 %rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
35 %eh.CatchHandlerType = type { i32, i8* }
36 %eh.CatchableType = type { i32, i32, i32, i32, i32, i32, i32 }
37 %eh.CatchableTypeArray.1 = type { i32, [1 x i32] }
38 %eh.ThrowInfo = type { i32, i32, i32, i32 }
39
40 $"\01??_R0H@8" = comdat any
41
42 $"\01??_R0D@8" = comdat any
43
44 $"_CT??_R0H@84" = comdat any
45
46 $_CTA1H = comdat any
47
48 $_TI1H = comdat any
49
50 $"_CT??_R0D@81" = comdat any
51
52 $_CTA1D = comdat any
53
54 $_TI1D = comdat any
55
56 @"\01??_7type_info@@6B@" = external constant i8*
57 @"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
58 @llvm.eh.handlertype.H.0 = private unnamed_addr constant %eh.CatchHandlerType { i32 0, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i8*) }, section "llvm.metadata"
59 @"\01??_R0D@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".D\00" }, comdat
60 @llvm.eh.handlertype.D.0 = private unnamed_addr constant %eh.CatchHandlerType { i32 0, i8* bitcast (%rtti.TypeDescriptor2* @"\01??_R0D@8" to i8*) }, section "llvm.metadata"
61 @__ImageBase = external constant i8
62 @"_CT??_R0H@84" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor2* @"\01??_R0H@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 -1, i32 0, i32 4, i32 0 }, section ".xdata", comdat
63 @_CTA1H = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableType* @"_CT??_R0H@84" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32)] }, section ".xdata", comdat
64 @_TI1H = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableTypeArray.1* @_CTA1H to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, section ".xdata", comdat
65 @"_CT??_R0D@81" = linkonce_odr unnamed_addr constant %eh.CatchableType { i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor2* @"\01??_R0D@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 -1, i32 0, i32 1, i32 0 }, section ".xdata", comdat
66 @_CTA1D = linkonce_odr unnamed_addr constant %eh.CatchableTypeArray.1 { i32 1, [1 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableType* @"_CT??_R0D@81" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32)] }, section ".xdata", comdat
67 @_TI1D = linkonce_odr unnamed_addr constant %eh.ThrowInfo { i32 0, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%eh.CatchableTypeArray.1* @_CTA1D to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, section ".xdata", comdat
68
69 ; Function Attrs: nounwind uwtable
70 define void @"\01?test@@YAXXZ"() #0 {
71 entry:
72 %tmp = alloca i32, align 4
73 %x = alloca i32, align 4
74 %tmp2 = alloca i8, align 1
75 %c = alloca i8, align 1
76 %tmp11 = alloca i32, align 4
77 %x21 = alloca i32, align 4
78 call void @"\01?two@@YAXXZ"() #3
79 store i32 2, i32* %tmp
80 %0 = bitcast i32* %tmp to i8*
81 call void (...) @llvm.frameescape(i32* %x, i8* %c, i32* %x21)
82 invoke void @_CxxThrowException(i8* %0, %eh.ThrowInfo* @_TI1H) #5
83 to label %unreachable unwind label %lpad
84
85 lpad: ; preds = %entry
86 %1 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
87 catch i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*)
88 catch %eh.CatchHandlerType* @llvm.eh.handlertype.D.0
89 catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0
90 catch i8* null
91 %recover = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*), i32 0, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch", i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.D.0 to i8*), i32 1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch1", i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch2", i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch3")
92 indirectbr i8* %recover, [label %try.cont, label %try.cont10, label %try.cont22]
93
94 try.cont: ; preds = %lpad
95 call void @"\01?a@@YAXXZ"() #3
96 store i8 97, i8* %tmp2
97 invoke void @_CxxThrowException(i8* %tmp2, %eh.ThrowInfo* @_TI1D) #5
98 to label %unreachable unwind label %lpad3
99
100 lpad3: ; preds = %try.cont
101 %2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
102 catch %eh.CatchHandlerType* @llvm.eh.handlertype.D.0
103 catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0
104 catch i8* null
105 %recover1 = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.D.0 to i8*), i32 1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch1", i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch2", i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch3")
106 indirectbr i8* %recover1, [label %try.cont10, label %try.cont22]
107
108 try.cont10: ; preds = %lpad3, %lpad
109 call void @"\01?one@@YAXXZ"() #3
110 store i32 1, i32* %tmp11
111 %3 = bitcast i32* %tmp11 to i8*
112 invoke void @_CxxThrowException(i8* %3, %eh.ThrowInfo* @_TI1H) #5
113 to label %unreachable unwind label %lpad12
114
115 lpad12: ; preds = %try.cont10
116 %4 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
117 catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0
118 catch i8* null
119 %recover2 = call i8* (...) @llvm.eh.actions(i32 1, i8* bitcast (%eh.CatchHandlerType* @llvm.eh.handlertype.H.0 to i8*), i32 2, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch2", i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @"\01?test@@YAXXZ.catch3")
120 indirectbr i8* %recover2, [label %try.cont22]
121
122 try.cont22: ; preds = %lpad12, %lpad3, %lpad
123 ret void
124
125 unreachable: ; preds = %try.cont10, %try.cont, %entry
126 unreachable
127 }
128
129 ; Function Attrs: nounwind
130 declare void @"\01?two@@YAXXZ"() #1
131
132 declare void @_CxxThrowException(i8*, %eh.ThrowInfo*)
133
134 declare i32 @__CxxFrameHandler3(...)
135
136 ; Function Attrs: nounwind readnone
137 declare i32 @llvm.eh.typeid.for(i8*) #2
138
139 ; Function Attrs: nounwind
140 declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #3
141
142 ; Function Attrs: nounwind
143 declare void @"\01?catch_two@@YAXXZ"() #1
144
145 ; Function Attrs: nounwind
146 declare void @llvm.eh.endcatch() #3
147
148 ; Function Attrs: nounwind
149 declare void @"\01?a@@YAXXZ"() #1
150
151 ; Function Attrs: nounwind
152 declare void @"\01?catch_a@@YAXXZ"() #1
153
154 ; Function Attrs: nounwind
155 declare void @"\01?one@@YAXXZ"() #1
156
157 ; Function Attrs: nounwind
158 declare void @"\01?catch_all@@YAXXZ"() #1
159
160 ; Function Attrs: nounwind
161 declare void @"\01?catch_one@@YAXXZ"() #1
162
163 ; Function Attrs: nounwind
164 declare i8* @llvm.eh.actions(...) #3
165
166 define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*) #4 {
167 entry:
168 %x.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0)
169 %x = bitcast i8* %x.i8 to i32*
170 %2 = bitcast i32* %x to i8*
171 call void @"\01?catch_two@@YAXXZ"() #3
172 invoke void @llvm.donothing()
173 to label %entry.split unwind label %stub
174
175 entry.split: ; preds = %entry
176 ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont)
177
178 stub: ; preds = %entry
179 %3 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
180 cleanup
181 %recover = call i8* (...) @llvm.eh.actions()
182 unreachable
183 }
184
185 ; Function Attrs: nounwind readnone
186 declare void @llvm.donothing() #2
187
188 define internal i8* @"\01?test@@YAXXZ.catch1"(i8*, i8*) #4 {
189 entry:
190 call void @"\01?catch_a@@YAXXZ"() #3
191 invoke void @llvm.donothing()
192 to label %entry.split unwind label %stub
193
194 entry.split: ; preds = %entry
195 ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont10)
196
197 stub: ; preds = %entry
198 %2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
199 cleanup
200 %recover = call i8* (...) @llvm.eh.actions()
201 unreachable
202 }
203
204 define internal i8* @"\01?test@@YAXXZ.catch2"(i8*, i8*) #4 {
205 entry:
206 %x21.i8 = call i8* @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 2)
207 %x21 = bitcast i8* %x21.i8 to i32*
208 %2 = bitcast i32* %x21 to i8*
209 call void @"\01?catch_one@@YAXXZ"() #3
210 invoke void @llvm.donothing()
211 to label %entry.split unwind label %stub
212
213 entry.split: ; preds = %entry
214 ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont22)
215
216 stub: ; preds = %entry
217 %3 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
218 cleanup
219 %recover = call i8* (...) @llvm.eh.actions()
220 unreachable
221 }
222
223 define internal i8* @"\01?test@@YAXXZ.catch3"(i8*, i8*) #4 {
224 entry:
225 call void @"\01?catch_all@@YAXXZ"() #3
226 invoke void @llvm.donothing()
227 to label %entry.split unwind label %stub
228
229 entry.split: ; preds = %entry
230 ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont22)
231
232 stub: ; preds = %entry
233 %2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
234 cleanup
235 %recover = call i8* (...) @llvm.eh.actions()
236 unreachable
237 }
238
239 ; Function Attrs: nounwind
240 declare void @llvm.frameescape(...) #3
241
242 ; Function Attrs: nounwind readnone
243 declare i8* @llvm.framerecover(i8*, i8*, i32) #2
244
245 attributes #0 = { nounwind uwtable "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" "wineh-parent"="?test@@YAXXZ" }
246 attributes #1 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+sse,+sse2" "unsafe-fp-math"="false" "use-soft-float"="false" }
247 attributes #2 = { nounwind readnone }
248 attributes #3 = { nounwind }
249 attributes #4 = { "wineh-parent"="?test@@YAXXZ" }
250 attributes #5 = { noreturn }
251
252 !llvm.module.flags = !{!0}
253 !llvm.ident = !{!1}
254
255 !0 = !{i32 1, !"PIC Level", i32 2}
256 !1 = !{!"clang version 3.7.0 (trunk 236059)"}
257
258 ; CHECK-LABEL: "$cppxdata$?test@@YAXXZ":
259 ; CHECK-NEXT: .long 429065506
260 ; CHECK-NEXT: .long
261 ; CHECK-NEXT: .long ("$stateUnwindMap$?test@@YAXXZ")@IMGREL
262 ; CHECK-NEXT: .long
263 ; CHECK-NEXT: .long ("$tryMap$?test@@YAXXZ")@IMGREL
264 ; CHECK-NEXT: .long
265 ; CHECK-NEXT: .long ("$ip2state$?test@@YAXXZ")@IMGREL
266 ; CHECK-NEXT: .long 40
267 ; CHECK-NEXT: .long 0
268 ; CHECK-NEXT: .long 1
269 ; CHECK: "$stateUnwindMap$?test@@YAXXZ":
270 ; CHECK: "$tryMap$?test@@YAXXZ":
271 ; CHECK: "$handlerMap$0$?test@@YAXXZ":
272 ; CHECK: "$ip2state$?test@@YAXXZ":
273 ; CHECK-NEXT: .long .Lfunc_begin0@IMGREL
274 ; CHECK-NEXT: .long -1
275 ; CHECK-NEXT: .long .Ltmp0@IMGREL
276 ; CHECK-NEXT: .long 3
277 ; CHECK-NEXT: .long .Ltmp3@IMGREL
278 ; CHECK-NEXT: .long 2
279 ; CHECK-NEXT: .long .Ltmp6@IMGREL
280 ; CHECK-NEXT: .long 1
281 ; CHECK-NEXT: .long .Lfunc_begin1@IMGREL
282 ; CHECK-NEXT: .long 4
283 ; CHECK-NEXT: .long .Lfunc_begin2@IMGREL
284 ; CHECK-NEXT: .long 5
285 ; CHECK-NEXT: .long .Lfunc_begin3@IMGREL
286 ; CHECK-NEXT: .long 6
287 ; CHECK-NEXT: .long .Lfunc_begin4@IMGREL
288 ; CHECK-NEXT: .long 7