llvm.org GIT mirror llvm / 0595a97
[WinEH] Split blocks at calls to llvm.eh.begincatch Differential Revision: http://reviews.llvm.org/D9311 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@236046 91177308-0d34-0410-b5e6-96231b3b80d8 Andrew Kaylor 5 years ago
6 changed file(s) with 206 addition(s) and 36 deletion(s). Raw diff Collapse all Expand all
8888 void promoteLandingPadValues(LandingPadInst *LPad);
8989 void demoteValuesLiveAcrossHandlers(Function &F,
9090 SmallVectorImpl &LPads);
91 void findSEHEHReturnPoints(Function &F,
92 SetVector &EHReturnBlocks);
93 void findCXXEHReturnPoints(Function &F,
94 SetVector &EHReturnBlocks);
9195 void completeNestedLandingPad(Function *ParentFn,
9296 LandingPadInst *OutlinedLPad,
9397 const LandingPadInst *OriginalLPad,
391395 }
392396 }
393397
398 // Attempt to find an instruction where a block can be split before
399 // a call to llvm.eh.begincatch and its operands. If the block
400 // begins with the begincatch call or one of its adjacent operands
401 // the block will not be split.
402 static Instruction *findBeginCatchSplitPoint(BasicBlock *BB,
403 IntrinsicInst *II) {
404 // If the begincatch call is already the first instruction in the block,
405 // don't split.
406 Instruction *FirstNonPHI = BB->getFirstNonPHI();
407 if (II == FirstNonPHI)
408 return nullptr;
409
410 // If either operand is in the same basic block as the instruction and
411 // isn't used by another instruction before the begincatch call, include it
412 // in the split block.
413 auto *Op0 = dyn_cast(II->getOperand(0));
414 auto *Op1 = dyn_cast(II->getOperand(1));
415
416 Instruction *I = II->getPrevNode();
417 Instruction *LastI = II;
418
419 while (I == Op0 || I == Op1) {
420 // If the block begins with one of the operands and there are no other
421 // instructions between the operand and the begincatch call, don't split.
422 if (I == FirstNonPHI)
423 return nullptr;
424
425 LastI = I;
426 I = I->getPrevNode();
427 }
428
429 // If there is at least one instruction in the block before the begincatch
430 // call and its operands, split the block at either the begincatch or
431 // its operand.
432 return LastI;
433 }
434
394435 /// Find all points where exceptional control rejoins normal control flow via
395436 /// llvm.eh.endcatch. Add them to the normal bb reachability worklist.
396 static void findCXXEHReturnPoints(Function &F,
397 SetVector &EHReturnBlocks) {
437 void WinEHPrepare::findCXXEHReturnPoints(
438 Function &F, SetVector &EHReturnBlocks) {
398439 for (auto BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) {
399440 BasicBlock *BB = BBI;
400441 for (Instruction &I : *BB) {
442 if (match(&I, m_Intrinsic())) {
443 Instruction *SplitPt =
444 findBeginCatchSplitPoint(BB, cast(&I));
445 if (SplitPt) {
446 // Split the block before the llvm.eh.begincatch call to allow
447 // cleanup and catch code to be distinguished later.
448 // Do not update BBI because we still need to process the
449 // portion of the block that we are splitting off.
450 SplitBlock(BB, &I, DT);
451 break;
452 }
453 }
401454 if (match(&I, m_Intrinsic())) {
402455 // Split the block after the call to llvm.eh.endcatch if there is
403456 // anything other than an unconditional branch, or if the successor
407460 isa(Br->getSuccessor(0)->begin())) {
408461 DEBUG(dbgs() << "splitting block " << BB->getName()
409462 << " with llvm.eh.endcatch\n");
410 BBI = BB->splitBasicBlock(I.getNextNode(), "ehreturn");
463 BBI = SplitBlock(BB, I.getNextNode(), DT);
411464 }
412465 // The next BB is normal control flow.
413466 EHReturnBlocks.insert(BB->getTerminator()->getSuccessor(0));
428481
429482 /// Find all points where exceptions control rejoins normal control flow via
430483 /// selector dispatch.
431 static void findSEHEHReturnPoints(Function &F,
432 SetVector &EHReturnBlocks) {
484 void WinEHPrepare::findSEHEHReturnPoints(
485 Function &F, SetVector &EHReturnBlocks) {
433486 for (auto BBI = F.begin(), BBE = F.end(); BBI != BBE; ++BBI) {
434487 BasicBlock *BB = BBI;
435488 // If the landingpad is a catch-all, treat the whole lpad as if it is
681734 // Split the block after the landingpad instruction so that it is just a
682735 // call to llvm.eh.actions followed by indirectbr.
683736 assert(!isa(LPadBB->begin()) && "lpad phi not removed");
684 LPadBB->splitBasicBlock(LPad->getNextNode(),
685 LPadBB->getName() + ".prepsplit");
737 SplitBlock(LPadBB, LPad->getNextNode(), DT);
686738 // Erase the branch inserted by the split so we can insert indirectbr.
687739 LPadBB->getTerminator()->eraseFromParent();
688740
10841136 else
10851137 Term = Unreached;
10861138 BasicBlock *OldRetBB = Term->getParent();
1087 BasicBlock *NewRetBB = SplitBlock(OldRetBB, Term);
1139 BasicBlock *NewRetBB = SplitBlock(OldRetBB, Term, DT);
10881140 // SplitBlock adds an unconditional branch instruction at the end of the
10891141 // parent block. We want to replace that with an invoke call, so we can
10901142 // erase it now.
12561308 } else {
12571309 // This must be a catch-all. Split the block after the landingpad.
12581310 assert(CatchAction->getSelector()->isNullValue() && "expected catch-all");
1259 HandlerBB =
1260 StartBB->splitBasicBlock(StartBB->getFirstInsertionPt(), "catch.all");
1311 HandlerBB = SplitBlock(StartBB, StartBB->getFirstInsertionPt(), DT);
12611312 }
12621313 IRBuilder<> Builder(HandlerBB->getFirstInsertionPt());
12631314 Function *EHCodeFn = Intrinsic::getDeclaration(
17171768 BB = NextBB;
17181769 }
17191770
1720 // For C++ EH, check if there is any interesting cleanup code before we
1721 // begin the catch. This is important because cleanups cannot rethrow
1722 // exceptions but code called from catches can. For SEH, it isn't
1723 // important if some finally code before a catch-all is executed out of
1724 // line or after recovering from the exception.
1725 if (Personality == EHPersonality::MSVC_CXX)
1726 findCleanupHandlers(Actions, BB, BB);
1727
17281771 // Add the catch handler to the action list.
17291772 CatchHandler *Action = nullptr;
17301773 if (CatchHandlerMap.count(BB) && CatchHandlerMap[BB] != nullptr) {
17321775 Action = CatchHandlerMap[BB];
17331776 assert(Action->getSelector() == ExpectedSelector);
17341777 } else {
1735 // Since this is a catch-all handler, the selector won't actually appear
1736 // in the code anywhere. ExpectedSelector here is the constant null ptr
1737 // that we got from the landing pad instruction.
1738 Action = new CatchHandler(BB, ExpectedSelector, nullptr);
1739 CatchHandlerMap[BB] = Action;
1778 // We don't expect a selector dispatch, but there may be a call to
1779 // llvm.eh.begincatch, which separates catch handling code from
1780 // cleanup code in the same control flow. This call looks for the
1781 // begincatch intrinsic.
1782 Action = findCatchHandler(BB, NextBB, VisitedBlocks);
1783 if (Action) {
1784 // For C++ EH, check if there is any interesting cleanup code before
1785 // we begin the catch. This is important because cleanups cannot
1786 // rethrow exceptions but code called from catches can. For SEH, it
1787 // isn't important if some finally code before a catch-all is executed
1788 // out of line or after recovering from the exception.
1789 if (Personality == EHPersonality::MSVC_CXX)
1790 findCleanupHandlers(Actions, BB, BB);
1791 } else {
1792 // If an action was not found, it means that the control flows
1793 // directly into the catch-all handler and there is no cleanup code.
1794 // That's an expected situation and we must create a catch action.
1795 // Since this is a catch-all handler, the selector won't actually
1796 // appear in the code anywhere. ExpectedSelector here is the constant
1797 // null ptr that we got from the landing pad instruction.
1798 Action = new CatchHandler(BB, ExpectedSelector, nullptr);
1799 CatchHandlerMap[BB] = Action;
1800 }
17401801 }
17411802 Actions.insertCatchHandler(Action);
17421803 DEBUG(dbgs() << " Catch all handler at block " << BB->getName() << "\n");
20582119 // for finally calls in the normal successor block.
20592120 BasicBlock *SuccBB = BB;
20602121 if (FinallyCall.getInstruction() != BB->getTerminator() &&
2061 FinallyCall.getInstruction()->getNextNode() != BB->getTerminator()) {
2062 SuccBB = BB->splitBasicBlock(FinallyCall.getInstruction()->getNextNode());
2122 FinallyCall.getInstruction()->getNextNode() !=
2123 BB->getTerminator()) {
2124 SuccBB =
2125 SplitBlock(BB, FinallyCall.getInstruction()->getNextNode(), DT);
20632126 } else {
20642127 if (FinallyCall.isInvoke()) {
2065 SuccBB = cast(FinallyCall.getInstruction())->getNormalDest();
2128 SuccBB =
2129 cast(FinallyCall.getInstruction())->getNormalDest();
20662130 } else {
20672131 SuccBB = BB->getUniqueSuccessor();
20682132 assert(SuccBB && "splitOutlinedFinallyCalls didn't insert a branch");
5454 ; CHECK: invoke void @might_throw()
5555 ;
5656 ; CHECK: landingpad
57 ; CHECK: indirectbr i8* {{.*}}, [label %ehreturn]
57 ; CHECK: indirectbr i8* {{.*}}, [label %catchit.split]
5858 ;
59 ; CHECK: ehreturn:
59 ; CHECK: catchit.split:
6060 ; CHECK: load i32, i32* %val.lpad.reg2mem
6161 ; CHECK: br label %ret
6262 ;
6363 ; CHECK: ret:
64 ; CHECK: %rv = phi i32 [ {{.*}}, %entry ], [ {{.*}}, %ehreturn ]
64 ; CHECK: %rv = phi i32 [ {{.*}}, %entry ], [ {{.*}}, %catchit.split ]
6565 ; CHECK: ret i32
6666
6767 ; CHECK-LABEL: define internal i8* @liveout_catch.catch(i8*, i8*)
6868 ; CHECK: %[[val:[^ ]*]] = load i32, i32*
6969 ; CHECK-NEXT: %[[val_lpad:[^ ]*]] = add i32 %[[val]], 1
7070 ; CHECK-NEXT: store i32 %[[val_lpad]], i32*
71 ; CHECK: ret i8* blockaddress(@liveout_catch, %ehreturn)
71 ; CHECK: ret i8* blockaddress(@liveout_catch, %catchit.split)
0 ; RUN: opt -mtriple=x86_64-pc-windows-msvc -winehprepare -S -o - < %s | FileCheck %s
1
2 ; This test is based on the following code:
3 ;
4 ; void test()
5 ; {
6 ; try {
7 ; Obj o;
8 ; may_throw();
9 ; } catch (...) {
10 ; }
11 ; }
12 ;
13 ; The purpose of this test is to verify that we create separate catch and
14 ; cleanup handlers. When compiling for the C++ 11 standard, this isn't
15 ; strictly necessary, since calling the destructor from the catch handler
16 ; would be logically equivalent to calling it from a cleanup handler.
17 ; However, if the -std=c++98 option is used, an exception in the cleanup
18 ; code should terminate the process (the MSVCRT runtime will do that) but
19 ; if the destructor is called from the catch handler, it wouldn't terminate
20 ; the process
21
22
23 ; ModuleID = 'cppeh-mixed-catch-and-cleanup.cpp'
24 target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
25 target triple = "x86_64-pc-windows-msvc"
26
27 %class.Obj = type { i8 }
28
29 ; This just verifies that the function was processed by WinEHPrepare.
30 ;
31 ; CHECK-LABEL: define void @"\01?test@@YAXXZ"()
32 ; CHECK: entry:
33 ; CHECK: call void (...) @llvm.frameescape
34 ; CHECK: }
35
36 ; Function Attrs: nounwind uwtable
37 define void @"\01?test@@YAXXZ"() #0 {
38 entry:
39 %o = alloca %class.Obj, align 1
40 %exn.slot = alloca i8*
41 %ehselector.slot = alloca i32
42 invoke void @"\01?may_throw@@YAXXZ"()
43 to label %invoke.cont unwind label %lpad
44
45 invoke.cont: ; preds = %entry
46 call void @"\01??1Obj@@QEAA@XZ"(%class.Obj* %o) #3
47 br label %try.cont
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 store i8* %1, i8** %exn.slot
54 %2 = extractvalue { i8*, i32 } %0, 1
55 store i32 %2, i32* %ehselector.slot
56 call void @"\01??1Obj@@QEAA@XZ"(%class.Obj* %o) #3
57 %exn = load i8*, i8** %exn.slot
58 call void @llvm.eh.begincatch(i8* %exn, i8* null) #3
59 call void @llvm.eh.endcatch() #3
60 br label %try.cont
61
62 try.cont: ; preds = %catch, %invoke.cont
63 ret void
64 }
65
66 ; Verify that a cleanup handler was created and that it calls ~Obj().
67 ; CHECK-LABEL: define internal void @"\01?test@@YAXXZ.cleanup"(i8*, i8*)
68 ; CHECK: entry:
69 ; CHECK: @llvm.framerecover(i8* bitcast (void ()* @"\01?test@@YAXXZ" to i8*), i8* %1, i32 0)
70 ; CHECK: call void @"\01??1Obj@@QEAA@XZ"
71 ; CHECK: ret void
72 ; CHECK: }
73
74 ; Verify that a catch handler was created and that it does not call ~Obj().
75 ; CHECK-LABEL: define internal i8* @"\01?test@@YAXXZ.catch"(i8*, i8*)
76 ; CHECK: entry:
77 ; CHECK-NOT: call void @"\01??1Obj@@QEAA@XZ"
78 ; CHECK: ret i8* blockaddress(@"\01?test@@YAXXZ", %try.cont)
79 ; CHECK: }
80
81
82
83 declare void @"\01?may_throw@@YAXXZ"() #1
84
85 declare i32 @__CxxFrameHandler3(...)
86
87 ; Function Attrs: nounwind
88 declare void @"\01??1Obj@@QEAA@XZ"(%class.Obj*) #2
89
90 ; Function Attrs: nounwind
91 declare void @llvm.eh.begincatch(i8* nocapture, i8* nocapture) #3
92
93 ; Function Attrs: nounwind
94 declare void @llvm.eh.endcatch() #3
95
96 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" "unsafe-fp-math"="false" "use-soft-float"="false" }
97 attributes #1 = { "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" "unsafe-fp-math"="false" "use-soft-float"="false" }
98 attributes #2 = { 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" "unsafe-fp-math"="false" "use-soft-float"="false" }
99 attributes #3 = { nounwind }
100
101 !llvm.module.flags = !{!0}
102 !llvm.ident = !{!1}
103
104 !0 = !{i32 1, !"PIC Level", i32 2}
105 !1 = !{!"clang version 3.7.0 (trunk 235779) (llvm/trunk 235769)"}
5858 ; CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__CxxFrameHandler3 to i8*)
5959 ; CHECK-NEXT: catch %eh.CatchHandlerType* @llvm.eh.handlertype.H.0
6060 ; 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")
61 ; CHECK-NEXT: [[RECOVER:\%.+]] = call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* (i8*, i8*)* @"\01?f@@YAXXZ.catch")
6262 ; CHECK-NEXT: indirectbr i8* [[RECOVER]], [label %try.cont4]
6363
6464 lpad1: ; preds = %invoke.cont
5050 ; CHECK-LABEL: define void @seh_catch_all()
5151 ; CHECK: landingpad
5252 ; CHECK-NEXT: catch i8* null
53 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@seh_catch_all, %catch.all))
53 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@seh_catch_all, %lpad.split))
5454 ; CHECK-NEXT: indirectbr
5555 ;
56 ; CHECK: catch.all:
56 ; CHECK: lpad.split:
5757 ; CHECK-NOT: extractvalue
5858 ; CHECK: call i32 @puts
6262 ; CHECK-LABEL: define i32 @catch_all()
6363 ; CHECK: landingpad { i8*, i32 }
6464 ; CHECK-NEXT: catch i8* null
65 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@catch_all, %catch.all))
66 ; CHECK-NEXT: indirectbr {{.*}} [label %catch.all]
65 ; CHECK-NEXT: call i8* (...) @llvm.eh.actions(i32 1, i8* null, i32 -1, i8* blockaddress(@catch_all, %lpad.split))
66 ; CHECK-NEXT: indirectbr {{.*}} [label %lpad.split]
6767 ;
68 ; CHECK: catch.all:
68 ; CHECK: lpad.split:
6969 ; CHECK: store i32 1, i32* %retval
7070
7171