LLVM 17.0.0git
DwarfEHPrepare.cpp
Go to the documentation of this file.
1//===- DwarfEHPrepare - Prepare exception handling for code generation ----===//
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// This pass mulches exception handling code into a form adapted to code
10// generation. Required if using dwarf exception handling.
11//
12//===----------------------------------------------------------------------===//
13
14#include "llvm/ADT/BitVector.h"
16#include "llvm/ADT/Statistic.h"
17#include "llvm/Analysis/CFG.h"
24#include "llvm/IR/BasicBlock.h"
25#include "llvm/IR/Constants.h"
28#include "llvm/IR/Dominators.h"
30#include "llvm/IR/Function.h"
32#include "llvm/IR/Module.h"
33#include "llvm/IR/Type.h"
35#include "llvm/Pass.h"
40#include <cstddef>
41
42using namespace llvm;
43
44#define DEBUG_TYPE "dwarfehprepare"
45
46STATISTIC(NumResumesLowered, "Number of resume calls lowered");
47STATISTIC(NumCleanupLandingPadsUnreachable,
48 "Number of cleanup landing pads found unreachable");
49STATISTIC(NumCleanupLandingPadsRemaining,
50 "Number of cleanup landing pads remaining");
51STATISTIC(NumNoUnwind, "Number of functions with nounwind");
52STATISTIC(NumUnwind, "Number of functions with unwind");
53
54namespace {
55
56class DwarfEHPrepare {
57 CodeGenOpt::Level OptLevel;
58
59 Function &F;
60 const TargetLowering &TLI;
61 DomTreeUpdater *DTU;
63 const Triple &TargetTriple;
64
65 /// Return the exception object from the value passed into
66 /// the 'resume' instruction (typically an aggregate). Clean up any dead
67 /// instructions, including the 'resume' instruction.
68 Value *GetExceptionObject(ResumeInst *RI);
69
70 /// Replace resumes that are not reachable from a cleanup landing pad with
71 /// unreachable and then simplify those blocks.
72 size_t
73 pruneUnreachableResumes(SmallVectorImpl<ResumeInst *> &Resumes,
75
76 /// Convert the ResumeInsts that are still present
77 /// into calls to the appropriate _Unwind_Resume function.
78 bool InsertUnwindResumeCalls();
79
80public:
81 DwarfEHPrepare(CodeGenOpt::Level OptLevel_, Function &F_,
82 const TargetLowering &TLI_, DomTreeUpdater *DTU_,
83 const TargetTransformInfo *TTI_, const Triple &TargetTriple_)
84 : OptLevel(OptLevel_), F(F_), TLI(TLI_), DTU(DTU_), TTI(TTI_),
85 TargetTriple(TargetTriple_) {}
86
87 bool run();
88};
89
90} // namespace
91
92Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
93 Value *V = RI->getOperand(0);
94 Value *ExnObj = nullptr;
95 InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V);
96 LoadInst *SelLoad = nullptr;
97 InsertValueInst *ExcIVI = nullptr;
98 bool EraseIVIs = false;
99
100 if (SelIVI) {
101 if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
102 ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
103 if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
104 ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
105 ExnObj = ExcIVI->getOperand(1);
106 SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
107 EraseIVIs = true;
108 }
109 }
110 }
111
112 if (!ExnObj)
113 ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
114
115 RI->eraseFromParent();
116
117 if (EraseIVIs) {
118 if (SelIVI->use_empty())
119 SelIVI->eraseFromParent();
120 if (ExcIVI->use_empty())
121 ExcIVI->eraseFromParent();
122 if (SelLoad && SelLoad->use_empty())
123 SelLoad->eraseFromParent();
124 }
125
126 return ExnObj;
127}
128
129size_t DwarfEHPrepare::pruneUnreachableResumes(
131 SmallVectorImpl<LandingPadInst *> &CleanupLPads) {
132 assert(DTU && "Should have DomTreeUpdater here.");
133
134 BitVector ResumeReachable(Resumes.size());
135 size_t ResumeIndex = 0;
136 for (auto *RI : Resumes) {
137 for (auto *LP : CleanupLPads) {
138 if (isPotentiallyReachable(LP, RI, nullptr, &DTU->getDomTree())) {
139 ResumeReachable.set(ResumeIndex);
140 break;
141 }
142 }
143 ++ResumeIndex;
144 }
145
146 // If everything is reachable, there is no change.
147 if (ResumeReachable.all())
148 return Resumes.size();
149
150 LLVMContext &Ctx = F.getContext();
151
152 // Otherwise, insert unreachable instructions and call simplifycfg.
153 size_t ResumesLeft = 0;
154 for (size_t I = 0, E = Resumes.size(); I < E; ++I) {
155 ResumeInst *RI = Resumes[I];
156 if (ResumeReachable[I]) {
157 Resumes[ResumesLeft++] = RI;
158 } else {
159 BasicBlock *BB = RI->getParent();
160 new UnreachableInst(Ctx, RI);
161 RI->eraseFromParent();
162 simplifyCFG(BB, *TTI, DTU);
163 }
164 }
165 Resumes.resize(ResumesLeft);
166 return ResumesLeft;
167}
168
169bool DwarfEHPrepare::InsertUnwindResumeCalls() {
172 if (F.doesNotThrow())
173 NumNoUnwind++;
174 else
175 NumUnwind++;
176 for (BasicBlock &BB : F) {
177 if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator()))
178 Resumes.push_back(RI);
179 if (auto *LP = BB.getLandingPadInst())
180 if (LP->isCleanup())
181 CleanupLPads.push_back(LP);
182 }
183
184 NumCleanupLandingPadsRemaining += CleanupLPads.size();
185
186 if (Resumes.empty())
187 return false;
188
189 // Check the personality, don't do anything if it's scope-based.
190 EHPersonality Pers = classifyEHPersonality(F.getPersonalityFn());
191 if (isScopedEHPersonality(Pers))
192 return false;
193
194 LLVMContext &Ctx = F.getContext();
195
196 size_t ResumesLeft = Resumes.size();
197 if (OptLevel != CodeGenOpt::None) {
198 ResumesLeft = pruneUnreachableResumes(Resumes, CleanupLPads);
199#if LLVM_ENABLE_STATS
200 unsigned NumRemainingLPs = 0;
201 for (BasicBlock &BB : F) {
202 if (auto *LP = BB.getLandingPadInst())
203 if (LP->isCleanup())
204 NumRemainingLPs++;
205 }
206 NumCleanupLandingPadsUnreachable += CleanupLPads.size() - NumRemainingLPs;
207 NumCleanupLandingPadsRemaining -= CleanupLPads.size() - NumRemainingLPs;
208#endif
209 }
210
211 if (ResumesLeft == 0)
212 return true; // We pruned them all.
213
214 // RewindFunction - _Unwind_Resume or the target equivalent.
215 FunctionCallee RewindFunction;
216 CallingConv::ID RewindFunctionCallingConv;
217 FunctionType *FTy;
218 const char *RewindName;
219 bool DoesRewindFunctionNeedExceptionObject;
220
221 if ((Pers == EHPersonality::GNU_CXX || Pers == EHPersonality::GNU_CXX_SjLj) &&
222 TargetTriple.isTargetEHABICompatible()) {
223 RewindName = TLI.getLibcallName(RTLIB::CXA_END_CLEANUP);
224 FTy = FunctionType::get(Type::getVoidTy(Ctx), false);
225 RewindFunctionCallingConv =
226 TLI.getLibcallCallingConv(RTLIB::CXA_END_CLEANUP);
227 DoesRewindFunctionNeedExceptionObject = false;
228 } else {
229 RewindName = TLI.getLibcallName(RTLIB::UNWIND_RESUME);
230 FTy =
231 FunctionType::get(Type::getVoidTy(Ctx), Type::getInt8PtrTy(Ctx), false);
232 RewindFunctionCallingConv = TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME);
233 DoesRewindFunctionNeedExceptionObject = true;
234 }
235 RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy);
236
237 // Create the basic block where the _Unwind_Resume call will live.
238 if (ResumesLeft == 1) {
239 // Instead of creating a new BB and PHI node, just append the call to
240 // _Unwind_Resume to the end of the single resume block.
241 ResumeInst *RI = Resumes.front();
242 BasicBlock *UnwindBB = RI->getParent();
243 Value *ExnObj = GetExceptionObject(RI);
244 llvm::SmallVector<Value *, 1> RewindFunctionArgs;
245 if (DoesRewindFunctionNeedExceptionObject)
246 RewindFunctionArgs.push_back(ExnObj);
247
248 // Call the rewind function.
249 CallInst *CI =
250 CallInst::Create(RewindFunction, RewindFunctionArgs, "", UnwindBB);
251 // The verifier requires that all calls of debug-info-bearing functions
252 // from debug-info-bearing functions have a debug location (for inlining
253 // purposes). Assign a dummy location to satisfy the constraint.
254 Function *RewindFn = dyn_cast<Function>(RewindFunction.getCallee());
255 if (RewindFn && RewindFn->getSubprogram())
256 if (DISubprogram *SP = F.getSubprogram())
257 CI->setDebugLoc(DILocation::get(SP->getContext(), 0, 0, SP));
258 CI->setCallingConv(RewindFunctionCallingConv);
259
260 // We never expect _Unwind_Resume to return.
261 CI->setDoesNotReturn();
262 new UnreachableInst(Ctx, UnwindBB);
263 return true;
264 }
265
266 std::vector<DominatorTree::UpdateType> Updates;
267 Updates.reserve(Resumes.size());
268
269 llvm::SmallVector<Value *, 1> RewindFunctionArgs;
270
271 BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &F);
272 PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft, "exn.obj",
273 UnwindBB);
274
275 // Extract the exception object from the ResumeInst and add it to the PHI node
276 // that feeds the _Unwind_Resume call.
277 for (ResumeInst *RI : Resumes) {
278 BasicBlock *Parent = RI->getParent();
279 BranchInst::Create(UnwindBB, Parent);
280 Updates.push_back({DominatorTree::Insert, Parent, UnwindBB});
281
282 Value *ExnObj = GetExceptionObject(RI);
283 PN->addIncoming(ExnObj, Parent);
284
285 ++NumResumesLowered;
286 }
287
288 if (DoesRewindFunctionNeedExceptionObject)
289 RewindFunctionArgs.push_back(PN);
290
291 // Call the function.
292 CallInst *CI =
293 CallInst::Create(RewindFunction, RewindFunctionArgs, "", UnwindBB);
294 CI->setCallingConv(RewindFunctionCallingConv);
295
296 // We never expect _Unwind_Resume to return.
297 CI->setDoesNotReturn();
298 new UnreachableInst(Ctx, UnwindBB);
299
300 if (DTU)
301 DTU->applyUpdates(Updates);
302
303 return true;
304}
305
306bool DwarfEHPrepare::run() {
307 bool Changed = InsertUnwindResumeCalls();
308
309 return Changed;
310}
311
313 const TargetLowering &TLI, DominatorTree *DT,
315 const Triple &TargetTriple) {
316 DomTreeUpdater DTU(DT, DomTreeUpdater::UpdateStrategy::Lazy);
317
318 return DwarfEHPrepare(OptLevel, F, TLI, DT ? &DTU : nullptr, TTI,
319 TargetTriple)
320 .run();
321}
322
323namespace {
324
325class DwarfEHPrepareLegacyPass : public FunctionPass {
326
327 CodeGenOpt::Level OptLevel;
328
329public:
330 static char ID; // Pass identification, replacement for typeid.
331
332 DwarfEHPrepareLegacyPass(CodeGenOpt::Level OptLevel = CodeGenOpt::Default)
333 : FunctionPass(ID), OptLevel(OptLevel) {}
334
335 bool runOnFunction(Function &F) override {
336 const TargetMachine &TM =
337 getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
338 const TargetLowering &TLI = *TM.getSubtargetImpl(F)->getTargetLowering();
339 DominatorTree *DT = nullptr;
340 const TargetTransformInfo *TTI = nullptr;
341 if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
342 DT = &DTWP->getDomTree();
343 if (OptLevel != CodeGenOpt::None) {
344 if (!DT)
345 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
346 TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
347 }
348 return prepareDwarfEH(OptLevel, F, TLI, DT, TTI, TM.getTargetTriple());
349 }
350
351 void getAnalysisUsage(AnalysisUsage &AU) const override {
354 if (OptLevel != CodeGenOpt::None) {
357 }
359 }
360
361 StringRef getPassName() const override {
362 return "Exception handling preparation";
363 }
364};
365
366} // end anonymous namespace
367
368char DwarfEHPrepareLegacyPass::ID = 0;
369
370INITIALIZE_PASS_BEGIN(DwarfEHPrepareLegacyPass, DEBUG_TYPE,
371 "Prepare DWARF exceptions", false, false)
375INITIALIZE_PASS_END(DwarfEHPrepareLegacyPass, DEBUG_TYPE,
376 "Prepare DWARF exceptions", false, false)
377
378FunctionPass *llvm::createDwarfEHPass(CodeGenOpt::Level OptLevel) {
379 return new DwarfEHPrepareLegacyPass(OptLevel);
380}
This file implements the BitVector class.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Prepare DWARF exceptions
static bool prepareDwarfEH(CodeGenOpt::Level OptLevel, Function &F, const TargetLowering &TLI, DominatorTree *DT, const TargetTransformInfo *TTI, const Triple &TargetTriple)
#define DEBUG_TYPE
#define F(x, y, z)
Definition: MD5.cpp:55
#define I(x, y, z)
Definition: MD5.cpp:58
Module.h This file contains the declarations for the Module class.
const char LLVMTargetMachineRef TM
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:55
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:59
#define INITIALIZE_PASS_BEGIN(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:52
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
This file defines the SmallVector class.
This file defines the 'Statistic' class, which is designed to be an easy way to expose various metric...
#define STATISTIC(VARNAME, DESC)
Definition: Statistic.h:167
This file describes how to lower LLVM code to machine code.
Target-Independent Code Generator Pass Configuration Options pass.
This pass exposes codegen information to IR-level passes.
Represent the analysis usage information of a pass.
AnalysisUsage & addRequired()
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
LLVM Basic Block Representation.
Definition: BasicBlock.h:56
const LandingPadInst * getLandingPadInst() const
Return the landingpad instruction associated with the landing pad.
Definition: BasicBlock.cpp:525
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:105
const Instruction * getTerminator() const LLVM_READONLY
Returns the terminator instruction if the block is well formed or null if the block is not well forme...
Definition: BasicBlock.h:127
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
void setCallingConv(CallingConv::ID CC)
Definition: InstrTypes.h:1475
void setDoesNotReturn()
Definition: InstrTypes.h:1921
This class represents a function call, abstracting a target machine's calling convention.
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Subprogram description.
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:314
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:166
static ExtractValueInst * Create(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Definition: DerivedTypes.h:165
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:311
virtual bool runOnFunction(Function &F)=0
runOnFunction - Virtual method overriden by subclasses to do the per-function processing of the pass.
DISubprogram * getSubprogram() const
Get the attached subprogram.
Definition: Metadata.cpp:1725
This instruction inserts a struct field of array element value into an aggregate value.
unsigned getNumIndices() const
idx_iterator idx_begin() const
const BasicBlock * getParent() const
Definition: Instruction.h:90
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:82
void setDebugLoc(DebugLoc Loc)
Set the debug location information for this instruction.
Definition: Instruction.h:362
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:67
An instruction for reading from memory.
Definition: Instructions.h:177
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
static PHINode * Create(Type *Ty, unsigned NumReservedValues, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Constructors - NumReservedValues is a hint for the number of incoming edges that this phi node will h...
virtual void getAnalysisUsage(AnalysisUsage &) const
getAnalysisUsage - This function should be overriden by passes that need analysis information to do t...
Definition: Pass.cpp:98
virtual StringRef getPassName() const
getPassName - Return a nice clean name for a pass.
Definition: Pass.cpp:81
Resume the propagation of an exception.
bool empty() const
Definition: SmallVector.h:94
size_t size() const
Definition: SmallVector.h:91
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: SmallVector.h:577
void push_back(const T &Elt)
Definition: SmallVector.h:416
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1200
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:50
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:78
Target-Independent Code Generator Pass Configuration Options.
Wrapper pass for TargetTransformInfo.
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:44
static Type * getVoidTy(LLVMContext &C)
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
This function has undefined behavior.
Value * getOperand(unsigned i) const
Definition: User.h:169
LLVM Value Representation.
Definition: Value.h:74
bool use_empty() const
Definition: Value.h:344
unsigned ID
LLVM IR allows to use arbitrary numbers as calling convention identifiers.
Definition: CallingConv.h:24
Level
Code generation optimization level.
Definition: CodeGen.h:57
@ Default
-O2, -Os
Definition: CodeGen.h:60
PointerTypeMap run(const Module &M)
Compute the PointerTypeMap for the module M.
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch,...
FunctionPass * createDwarfEHPass(CodeGenOpt::Level OptLevel)
createDwarfEHPass - This pass mulches exception handling code into a form adapted to code generation.
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
bool simplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, DomTreeUpdater *DTU=nullptr, const SimplifyCFGOptions &Options={}, ArrayRef< WeakVH > LoopHeaders={})
bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock * > *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether instruction 'To' is reachable from 'From', without passing through any blocks in Ex...
Definition: CFG.cpp:231