Line data Source code
1 : //===- DwarfEHPrepare - Prepare exception handling for code generation ----===//
2 : //
3 : // The LLVM Compiler Infrastructure
4 : //
5 : // This file is distributed under the University of Illinois Open Source
6 : // License. See LICENSE.TXT for details.
7 : //
8 : //===----------------------------------------------------------------------===//
9 : //
10 : // This pass mulches exception handling code into a form adapted to code
11 : // generation. Required if using dwarf exception handling.
12 : //
13 : //===----------------------------------------------------------------------===//
14 :
15 : #include "llvm/ADT/BitVector.h"
16 : #include "llvm/ADT/SmallVector.h"
17 : #include "llvm/ADT/Statistic.h"
18 : #include "llvm/Analysis/CFG.h"
19 : #include "llvm/Analysis/EHPersonalities.h"
20 : #include "llvm/Analysis/TargetTransformInfo.h"
21 : #include "llvm/Transforms/Utils/Local.h"
22 : #include "llvm/CodeGen/RuntimeLibcalls.h"
23 : #include "llvm/CodeGen/TargetLowering.h"
24 : #include "llvm/CodeGen/TargetPassConfig.h"
25 : #include "llvm/CodeGen/TargetSubtargetInfo.h"
26 : #include "llvm/IR/BasicBlock.h"
27 : #include "llvm/IR/Constants.h"
28 : #include "llvm/IR/DerivedTypes.h"
29 : #include "llvm/IR/Dominators.h"
30 : #include "llvm/IR/Function.h"
31 : #include "llvm/IR/Instructions.h"
32 : #include "llvm/IR/Module.h"
33 : #include "llvm/IR/Type.h"
34 : #include "llvm/Pass.h"
35 : #include "llvm/Support/Casting.h"
36 : #include "llvm/Target/TargetMachine.h"
37 : #include <cstddef>
38 :
39 : using namespace llvm;
40 :
41 : #define DEBUG_TYPE "dwarfehprepare"
42 :
43 : STATISTIC(NumResumesLowered, "Number of resume calls lowered");
44 :
45 : namespace {
46 :
47 : class DwarfEHPrepare : public FunctionPass {
48 : // RewindFunction - _Unwind_Resume or the target equivalent.
49 : Constant *RewindFunction = nullptr;
50 :
51 : DominatorTree *DT = nullptr;
52 : const TargetLowering *TLI = nullptr;
53 :
54 : bool InsertUnwindResumeCalls(Function &Fn);
55 : Value *GetExceptionObject(ResumeInst *RI);
56 : size_t
57 : pruneUnreachableResumes(Function &Fn,
58 : SmallVectorImpl<ResumeInst *> &Resumes,
59 : SmallVectorImpl<LandingPadInst *> &CleanupLPads);
60 :
61 : public:
62 : static char ID; // Pass identification, replacement for typeid.
63 :
64 49028 : DwarfEHPrepare() : FunctionPass(ID) {}
65 :
66 : bool runOnFunction(Function &Fn) override;
67 :
68 24275 : bool doFinalization(Module &M) override {
69 24275 : RewindFunction = nullptr;
70 24275 : return false;
71 : }
72 :
73 : void getAnalysisUsage(AnalysisUsage &AU) const override;
74 :
75 20 : StringRef getPassName() const override {
76 20 : return "Exception handling preparation";
77 : }
78 : };
79 :
80 : } // end anonymous namespace
81 :
82 : char DwarfEHPrepare::ID = 0;
83 :
84 39044 : INITIALIZE_PASS_BEGIN(DwarfEHPrepare, DEBUG_TYPE,
85 : "Prepare DWARF exceptions", false, false)
86 39044 : INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
87 39044 : INITIALIZE_PASS_DEPENDENCY(TargetPassConfig)
88 39044 : INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass)
89 103150 : INITIALIZE_PASS_END(DwarfEHPrepare, DEBUG_TYPE,
90 : "Prepare DWARF exceptions", false, false)
91 :
92 24512 : FunctionPass *llvm::createDwarfEHPass() { return new DwarfEHPrepare(); }
93 :
94 24394 : void DwarfEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
95 : AU.addRequired<TargetPassConfig>();
96 : AU.addRequired<TargetTransformInfoWrapperPass>();
97 : AU.addRequired<DominatorTreeWrapperPass>();
98 24394 : }
99 :
100 : /// GetExceptionObject - Return the exception object from the value passed into
101 : /// the 'resume' instruction (typically an aggregate). Clean up any dead
102 : /// instructions, including the 'resume' instruction.
103 0 : Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
104 : Value *V = RI->getOperand(0);
105 : Value *ExnObj = nullptr;
106 : InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
107 : LoadInst *SelLoad = nullptr;
108 : InsertValueInst *ExcIVI = nullptr;
109 : bool EraseIVIs = false;
110 :
111 : if (SelIVI) {
112 0 : if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
113 : ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
114 0 : if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
115 0 : ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
116 : ExnObj = ExcIVI->getOperand(1);
117 : SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
118 : EraseIVIs = true;
119 : }
120 : }
121 : }
122 :
123 0 : if (!ExnObj)
124 0 : ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
125 :
126 0 : RI->eraseFromParent();
127 :
128 0 : if (EraseIVIs) {
129 0 : if (SelIVI->use_empty())
130 0 : SelIVI->eraseFromParent();
131 0 : if (ExcIVI->use_empty())
132 0 : ExcIVI->eraseFromParent();
133 0 : if (SelLoad && SelLoad->use_empty())
134 0 : SelLoad->eraseFromParent();
135 : }
136 :
137 0 : return ExnObj;
138 : }
139 :
140 : /// Replace resumes that are not reachable from a cleanup landing pad with
141 : /// unreachable and then simplify those blocks.
142 38448 : size_t DwarfEHPrepare::pruneUnreachableResumes(
143 : Function &Fn, SmallVectorImpl<ResumeInst *> &Resumes,
144 : SmallVectorImpl<LandingPadInst *> &CleanupLPads) {
145 38448 : BitVector ResumeReachable(Resumes.size());
146 : size_t ResumeIndex = 0;
147 83011 : for (auto *RI : Resumes) {
148 77962 : for (auto *LP : CleanupLPads) {
149 77517 : if (isPotentiallyReachable(LP, RI, DT)) {
150 44118 : ResumeReachable.set(ResumeIndex);
151 : break;
152 : }
153 : }
154 44563 : ++ResumeIndex;
155 : }
156 :
157 : // If everything is reachable, there is no change.
158 38448 : if (ResumeReachable.all())
159 76006 : return Resumes.size();
160 :
161 : const TargetTransformInfo &TTI =
162 445 : getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn);
163 445 : LLVMContext &Ctx = Fn.getContext();
164 :
165 : // Otherwise, insert unreachable instructions and call simplifycfg.
166 : size_t ResumesLeft = 0;
167 890 : for (size_t I = 0, E = Resumes.size(); I < E; ++I) {
168 445 : ResumeInst *RI = Resumes[I];
169 890 : if (ResumeReachable[I]) {
170 0 : Resumes[ResumesLeft++] = RI;
171 : } else {
172 445 : BasicBlock *BB = RI->getParent();
173 445 : new UnreachableInst(Ctx, RI);
174 445 : RI->eraseFromParent();
175 445 : simplifyCFG(BB, TTI);
176 : }
177 : }
178 445 : Resumes.resize(ResumesLeft);
179 445 : return ResumesLeft;
180 : }
181 :
182 : /// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present
183 : /// into calls to the appropriate _Unwind_Resume function.
184 379199 : bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
185 : SmallVector<ResumeInst*, 16> Resumes;
186 : SmallVector<LandingPadInst*, 16> CleanupLPads;
187 3563737 : for (BasicBlock &BB : Fn) {
188 3184538 : if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator()))
189 44563 : Resumes.push_back(RI);
190 3184538 : if (auto *LP = BB.getLandingPadInst())
191 338190 : if (LP->isCleanup())
192 254905 : CleanupLPads.push_back(LP);
193 : }
194 :
195 379199 : if (Resumes.empty())
196 : return false;
197 :
198 : // Check the personality, don't do anything if it's scope-based.
199 38448 : EHPersonality Pers = classifyEHPersonality(Fn.getPersonalityFn());
200 : if (isScopedEHPersonality(Pers))
201 : return false;
202 :
203 38448 : LLVMContext &Ctx = Fn.getContext();
204 :
205 38448 : size_t ResumesLeft = pruneUnreachableResumes(Fn, Resumes, CleanupLPads);
206 38448 : if (ResumesLeft == 0)
207 : return true; // We pruned them all.
208 :
209 : // Find the rewind function if we didn't already.
210 38003 : if (!RewindFunction) {
211 2882 : FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx),
212 2882 : Type::getInt8PtrTy(Ctx), false);
213 2882 : const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME);
214 5764 : RewindFunction = Fn.getParent()->getOrInsertFunction(RewindName, FTy);
215 : }
216 :
217 : // Create the basic block where the _Unwind_Resume call will live.
218 38003 : if (ResumesLeft == 1) {
219 : // Instead of creating a new BB and PHI node, just append the call to
220 : // _Unwind_Resume to the end of the single resume block.
221 35289 : ResumeInst *RI = Resumes.front();
222 35289 : BasicBlock *UnwindBB = RI->getParent();
223 35289 : Value *ExnObj = GetExceptionObject(RI);
224 :
225 : // Call the _Unwind_Resume function.
226 35289 : CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB);
227 35289 : CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
228 :
229 : // We never expect _Unwind_Resume to return.
230 35289 : new UnreachableInst(Ctx, UnwindBB);
231 : return true;
232 : }
233 :
234 2714 : BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn);
235 5428 : PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft,
236 : "exn.obj", UnwindBB);
237 :
238 : // Extract the exception object from the ResumeInst and add it to the PHI node
239 : // that feeds the _Unwind_Resume call.
240 11543 : for (ResumeInst *RI : Resumes) {
241 8829 : BasicBlock *Parent = RI->getParent();
242 8829 : BranchInst::Create(UnwindBB, Parent);
243 :
244 8829 : Value *ExnObj = GetExceptionObject(RI);
245 8829 : PN->addIncoming(ExnObj, Parent);
246 :
247 : ++NumResumesLowered;
248 : }
249 :
250 : // Call the function.
251 5428 : CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB);
252 2714 : CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
253 :
254 : // We never expect _Unwind_Resume to return.
255 2714 : new UnreachableInst(Ctx, UnwindBB);
256 2714 : return true;
257 : }
258 :
259 379199 : bool DwarfEHPrepare::runOnFunction(Function &Fn) {
260 : const TargetMachine &TM =
261 379199 : getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
262 379199 : DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
263 379199 : TLI = TM.getSubtargetImpl(Fn)->getTargetLowering();
264 379199 : bool Changed = InsertUnwindResumeCalls(Fn);
265 379199 : DT = nullptr;
266 379199 : TLI = nullptr;
267 379199 : return Changed;
268 : }
|