1 | //===- EscapeEnumerator.cpp -----------------------------------------------===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | // |
9 | // Defines a helper class that enumerates all possible exits from a function, |
10 | // including exception handling. |
11 | // |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/Transforms/Utils/EscapeEnumerator.h" |
15 | #include "llvm/IR/EHPersonalities.h" |
16 | #include "llvm/IR/Module.h" |
17 | #include "llvm/TargetParser/Triple.h" |
18 | #include "llvm/Transforms/Utils/Local.h" |
19 | |
20 | using namespace llvm; |
21 | |
22 | static FunctionCallee getDefaultPersonalityFn(Module *M) { |
23 | LLVMContext &C = M->getContext(); |
24 | Triple T(M->getTargetTriple()); |
25 | EHPersonality Pers = getDefaultEHPersonality(T); |
26 | return M->getOrInsertFunction(Name: getEHPersonalityName(Pers), |
27 | T: FunctionType::get(Result: Type::getInt32Ty(C), isVarArg: true)); |
28 | } |
29 | |
30 | IRBuilder<> *EscapeEnumerator::Next() { |
31 | if (Done) |
32 | return nullptr; |
33 | |
34 | // Find all 'return', 'resume', and 'unwind' instructions. |
35 | while (StateBB != StateE) { |
36 | BasicBlock *CurBB = &*StateBB++; |
37 | |
38 | // Branches and invokes do not escape, only unwind, resume, and return |
39 | // do. |
40 | Instruction *TI = CurBB->getTerminator(); |
41 | if (!isa<ReturnInst>(Val: TI) && !isa<ResumeInst>(Val: TI)) |
42 | continue; |
43 | |
44 | if (CallInst *CI = CurBB->getTerminatingMustTailCall()) |
45 | TI = CI; |
46 | Builder.SetInsertPoint(TI); |
47 | return &Builder; |
48 | } |
49 | |
50 | Done = true; |
51 | |
52 | if (!HandleExceptions) |
53 | return nullptr; |
54 | |
55 | if (F.doesNotThrow()) |
56 | return nullptr; |
57 | |
58 | // Find all 'call' instructions that may throw. |
59 | // We cannot tranform calls with musttail tag. |
60 | SmallVector<Instruction *, 16> Calls; |
61 | for (BasicBlock &BB : F) |
62 | for (Instruction &II : BB) |
63 | if (CallInst *CI = dyn_cast<CallInst>(Val: &II)) |
64 | if (!CI->doesNotThrow() && !CI->isMustTailCall()) |
65 | Calls.push_back(Elt: CI); |
66 | |
67 | if (Calls.empty()) |
68 | return nullptr; |
69 | |
70 | // Create a cleanup block. |
71 | LLVMContext &C = F.getContext(); |
72 | BasicBlock *CleanupBB = BasicBlock::Create(Context&: C, Name: CleanupBBName, Parent: &F); |
73 | Type *ExnTy = StructType::get(elt1: PointerType::getUnqual(C), elts: Type::getInt32Ty(C)); |
74 | if (!F.hasPersonalityFn()) { |
75 | FunctionCallee PersFn = getDefaultPersonalityFn(M: F.getParent()); |
76 | F.setPersonalityFn(cast<Constant>(Val: PersFn.getCallee())); |
77 | } |
78 | |
79 | if (isScopedEHPersonality(Pers: classifyEHPersonality(Pers: F.getPersonalityFn()))) { |
80 | report_fatal_error(reason: "Scoped EH not supported" ); |
81 | } |
82 | |
83 | LandingPadInst *LPad = |
84 | LandingPadInst::Create(RetTy: ExnTy, NumReservedClauses: 1, NameStr: "cleanup.lpad" , InsertBefore: CleanupBB); |
85 | LPad->setCleanup(true); |
86 | ResumeInst *RI = ResumeInst::Create(Exn: LPad, InsertBefore: CleanupBB); |
87 | |
88 | // Transform the 'call' instructions into 'invoke's branching to the |
89 | // cleanup block. Go in reverse order to make prettier BB names. |
90 | SmallVector<Value *, 16> Args; |
91 | for (unsigned I = Calls.size(); I != 0;) { |
92 | CallInst *CI = cast<CallInst>(Val: Calls[--I]); |
93 | changeToInvokeAndSplitBasicBlock(CI, UnwindEdge: CleanupBB, DTU); |
94 | } |
95 | |
96 | Builder.SetInsertPoint(RI); |
97 | return &Builder; |
98 | } |
99 | |