llvm.org GIT mirror llvm / e0d6a5c
[WinEH] Fix problem with mapping shared empty handler blocks. Differential Revision: http://reviews.llvm.org/D9125 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@235354 91177308-0d34-0410-b5e6-96231b3b80d8 Andrew Kaylor 5 years ago
2 changed file(s) with 148 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
769769 return false;
770770 }
771771
772 static bool isCatchBlock(BasicBlock *BB) {
773 for (BasicBlock::iterator II = BB->getFirstNonPHIOrDbg(), IE = BB->end();
774 II != IE; ++II) {
775 if (match(cast(II), m_Intrinsic()))
776 return true;
777 }
778 return false;
779 }
780
772781 static BasicBlock *createStubLandingPad(Function *Handler,
773782 Value *PersonalityFn) {
774783 // FIXME: Finish this!
14461455 }
14471456
14481457 CatchHandler *CatchAction = findCatchHandler(BB, NextBB, VisitedBlocks);
1458 assert(CatchAction);
1459
14491460 // See if there is any interesting code executed before the dispatch.
14501461 findCleanupHandlers(Actions, BB, CatchAction->getStartBlock());
1451
1452 assert(CatchAction);
14531462
14541463 // When the source program contains multiple nested try blocks the catch
14551464 // handlers can get strung together in such a way that we can encounter
14621471 << CatchAction->getStartBlock()->getName() << "\n");
14631472 Actions.insertCatchHandler(CatchAction);
14641473 } else {
1474 // Under some circumstances optimized IR will flow unconditionally into a
1475 // handler block without checking the selector. This can only happen if
1476 // the landing pad has a catch-all handler and the handler for the
1477 // preceeding catch clause is identical to the catch-call handler
1478 // (typically an empty catch). In this case, the handler must be shared
1479 // by all remaining clauses.
1480 if (isa(
1481 CatchAction->getSelector()->stripPointerCasts())) {
1482 DEBUG(dbgs() << " Applying early catch-all handler in block "
1483 << CatchAction->getStartBlock()->getName()
1484 << " to all remaining clauses.\n");
1485 Actions.insertCatchHandler(CatchAction);
1486 return;
1487 }
1488
14651489 DEBUG(dbgs() << " Found extra catch dispatch in block "
14661490 << CatchAction->getStartBlock()->getName() << "\n");
14671491 }
15131537 if (!CatchHandlerMap.count(BB)) {
15141538 if (isSelectorDispatch(BB, CatchBlock, Selector, NextBB)) {
15151539 CatchHandler *Action = new CatchHandler(BB, Selector, NextBB);
1540 CatchHandlerMap[BB] = Action;
1541 return Action;
1542 }
1543 // If we encounter a block containing an llvm.eh.begincatch before we
1544 // find a selector dispatch block, the handler is assumed to be
1545 // reached unconditionally. This happens for catch-all blocks, but
1546 // it can also happen for other catch handlers that have been combined
1547 // with the catch-all handler during optimization.
1548 if (isCatchBlock(BB)) {
1549 PointerType *Int8PtrTy = Type::getInt8PtrTy(BB->getContext());
1550 Constant *NullSelector = ConstantPointerNull::get(Int8PtrTy);
1551 CatchHandler *Action = new CatchHandler(BB, NullSelector, nullptr);
15161552 CatchHandlerMap[BB] = Action;
15171553 return Action;
15181554 }
0 ; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s
1
2 ; This test is based on the following source, built with -O2
3 ;
4 ; void f() {
5 ; try {
6 ; g();
7 ; try {
8 ; throw;
9 ; } catch (int) {
10 ; }
11 ; } catch (...) {
12 ; }
13 ; }
14 ;
15
16 ; ModuleID = ''
17 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
18 target triple = "x86_64-pc-windows-msvc"
19
20 %rtti.TypeDescriptor2 = type { i8**, i8*, [3 x i8] }
21 %eh.CatchHandlerType = type { i32, i8* }
22 %eh.ThrowInfo = type { i32, i32, i32, i32 }
23
24 $"\01??_R0H@8" = comdat any
25
26 @"\01??_7type_info@@6B@" = external constant i8*
27 @"\01??_R0H@8" = linkonce_odr global %rtti.TypeDescriptor2 { i8** @"\01??_7type_info@@6B@", i8* null, [3 x i8] c".H\00" }, comdat
28 @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"
29
30 ; CHECK-LABEL: define void @"\01?f@@YAXXZ"()
31 ; CHECK: entry:
32 ; CHECK: call void (...) @llvm.frameescape()
33 ; CHECK: invoke void @"\01?g@@YAXXZ"()
34
35 ; Function Attrs: nounwind
36 define void @"\01?f@@YAXXZ"() #0 {
37 entry:
38 invoke void @"\01?g@@YAXXZ"()
39 to label %invoke.cont unwind label %lpad
40
41 ; CHECK-LABEL: invoke.cont:
42 ; CHECK: invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null)
43 ; CHECK: to label %unreachable unwind label %[[LPAD1_LABEL:lpad[0-9]+]]
44
45 invoke.cont: ; preds = %entry
46 invoke void @_CxxThrowException(i8* null, %eh.ThrowInfo* null) #4
47 to label %unreachable unwind label %lpad1
48
49 lpad: ; preds = %entry
50 %0 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
51 catch i8* null
52 %1 = extractvalue { i8*, i32 } %0, 0
53 br label %catch2
54
55 ; Note: Even though this landing pad has two catch clauses, it only has one action because both
56 ; handlers do the same thing.
57 ; CHECK: [[LPAD1_LABEL]]:
58 ; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
59 ; CHECK-NEXT: catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0
60 ; CHECK-NEXT: catch i8* null
61 ; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @"\01?f@@YAXXZ.catch1")
62 ; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont4]
63
64 lpad1: ; preds = %invoke.cont
65 %2 = landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
66 catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0
67 catch i8* null
68 %3 = extractvalue { i8*, i32 } %2, 0
69 br label %catch2
70
71 catch2: ; preds = %lpad1, %lpad
72 %exn.slot.0 = phi i8* [ %3, %lpad1 ], [ %1, %lpad ]
73 tail call void @llvm.eh.begincatch(i8* %exn.slot.0, i8* null) #3
74 tail call void @llvm.eh.endcatch() #3
75 br label %try.cont4
76
77 try.cont4: ; preds = %catch, %catch2
78 ret void
79
80 unreachable: ; preds = %invoke.cont
81 unreachable
82
83 ; CHECK: }
84 }
85
86 declare void @"\01?g@@YAXXZ"() #1
87
88 declare i32 @__CxxFrameHandler3(...)
89
90 declare void @_CxxThrowException(i8*, %eh.ThrowInfo*)
91
92 ; Function Attrs: nounwind readnone
93 declare i32 @llvm.eh.typeid.for(i8*) #2
94
95 ; Function Attrs: nounwind
96 declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #3
97
98 ; Function Attrs: nounwind
99 declare void @llvm.eh.endcatch() #3
100
101 attributes #0 = { nounwind "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
102 attributes #1 = { "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-nans-fp-math"="false" "no-realign-stack" "stack-protector-buffer-size"="8" "unsafe-fp-math"="false" "use-soft-float"="false" }
103 attributes #2 = { nounwind readnone }
104 attributes #3 = { nounwind }
105 attributes #4 = { noreturn }
106
107 !llvm.ident = !{!0}
108
109 !0 = !{!"clang version 3.7.0 (trunk 235112) (llvm/trunk 235121)"}