LLVM  14.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"
15 #include "llvm/ADT/SmallVector.h"
16 #include "llvm/ADT/Statistic.h"
17 #include "llvm/Analysis/CFG.h"
25 #include "llvm/IR/BasicBlock.h"
26 #include "llvm/IR/Constants.h"
27 #include "llvm/IR/DerivedTypes.h"
28 #include "llvm/IR/Dominators.h"
29 #include "llvm/IR/Function.h"
30 #include "llvm/IR/Instructions.h"
31 #include "llvm/IR/Module.h"
32 #include "llvm/IR/Type.h"
33 #include "llvm/InitializePasses.h"
34 #include "llvm/Pass.h"
35 #include "llvm/Support/Casting.h"
38 #include <cstddef>
39 
40 using namespace llvm;
41 
42 #define DEBUG_TYPE "dwarfehprepare"
43 
44 STATISTIC(NumResumesLowered, "Number of resume calls lowered");
45 STATISTIC(NumCleanupLandingPadsUnreachable,
46  "Number of cleanup landing pads found unreachable");
47 STATISTIC(NumCleanupLandingPadsRemaining,
48  "Number of cleanup landing pads remaining");
49 STATISTIC(NumNoUnwind, "Number of functions with nounwind");
50 STATISTIC(NumUnwind, "Number of functions with unwind");
51 
52 namespace {
53 
54 class DwarfEHPrepare {
55  CodeGenOpt::Level OptLevel;
56 
57  // RewindFunction - _Unwind_Resume or the target equivalent.
58  FunctionCallee &RewindFunction;
59 
60  Function &F;
61  const TargetLowering &TLI;
62  DomTreeUpdater *DTU;
63  const TargetTransformInfo *TTI;
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,
74  SmallVectorImpl<LandingPadInst *> &CleanupLPads);
75 
76  /// Convert the ResumeInsts that are still present
77  /// into calls to the appropriate _Unwind_Resume function.
78  bool InsertUnwindResumeCalls();
79 
80 public:
81  DwarfEHPrepare(CodeGenOpt::Level OptLevel_, FunctionCallee &RewindFunction_,
82  Function &F_, const TargetLowering &TLI_, DomTreeUpdater *DTU_,
83  const TargetTransformInfo *TTI_)
84  : OptLevel(OptLevel_), RewindFunction(RewindFunction_), F(F_), TLI(TLI_),
85  DTU(DTU_), TTI(TTI_) {}
86 
87  bool run();
88 };
89 
90 } // namespace
91 
92 Value *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 
129 size_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 
169 bool 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  // Find the rewind function if we didn't already.
215  if (!RewindFunction) {
216  FunctionType *FTy =
218  const char *RewindName = TLI.getLibcallName(RTLIB::UNWIND_RESUME);
219  RewindFunction = F.getParent()->getOrInsertFunction(RewindName, FTy);
220  }
221 
222  // Create the basic block where the _Unwind_Resume call will live.
223  if (ResumesLeft == 1) {
224  // Instead of creating a new BB and PHI node, just append the call to
225  // _Unwind_Resume to the end of the single resume block.
226  ResumeInst *RI = Resumes.front();
227  BasicBlock *UnwindBB = RI->getParent();
228  Value *ExnObj = GetExceptionObject(RI);
229 
230  // Call the _Unwind_Resume function.
231  CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB);
232  CI->setCallingConv(TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME));
233 
234  // We never expect _Unwind_Resume to return.
235  CI->setDoesNotReturn();
236  new UnreachableInst(Ctx, UnwindBB);
237  return true;
238  }
239 
240  std::vector<DominatorTree::UpdateType> Updates;
241  Updates.reserve(Resumes.size());
242 
243  BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &F);
244  PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft, "exn.obj",
245  UnwindBB);
246 
247  // Extract the exception object from the ResumeInst and add it to the PHI node
248  // that feeds the _Unwind_Resume call.
249  for (ResumeInst *RI : Resumes) {
250  BasicBlock *Parent = RI->getParent();
251  BranchInst::Create(UnwindBB, Parent);
252  Updates.push_back({DominatorTree::Insert, Parent, UnwindBB});
253 
254  Value *ExnObj = GetExceptionObject(RI);
255  PN->addIncoming(ExnObj, Parent);
256 
257  ++NumResumesLowered;
258  }
259 
260  // Call the function.
261  CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB);
262  CI->setCallingConv(TLI.getLibcallCallingConv(RTLIB::UNWIND_RESUME));
263 
264  // We never expect _Unwind_Resume to return.
265  CI->setDoesNotReturn();
266  new UnreachableInst(Ctx, UnwindBB);
267 
268  if (DTU)
269  DTU->applyUpdates(Updates);
270 
271  return true;
272 }
273 
274 bool DwarfEHPrepare::run() {
275  bool Changed = InsertUnwindResumeCalls();
276 
277  return Changed;
278 }
279 
280 static bool prepareDwarfEH(CodeGenOpt::Level OptLevel,
281  FunctionCallee &RewindFunction, Function &F,
282  const TargetLowering &TLI, DominatorTree *DT,
283  const TargetTransformInfo *TTI) {
285 
286  return DwarfEHPrepare(OptLevel, RewindFunction, F, TLI, DT ? &DTU : nullptr,
287  TTI)
288  .run();
289 }
290 
291 namespace {
292 
293 class DwarfEHPrepareLegacyPass : public FunctionPass {
294  // RewindFunction - _Unwind_Resume or the target equivalent.
295  FunctionCallee RewindFunction = nullptr;
296 
297  CodeGenOpt::Level OptLevel;
298 
299 public:
300  static char ID; // Pass identification, replacement for typeid.
301 
302  DwarfEHPrepareLegacyPass(CodeGenOpt::Level OptLevel = CodeGenOpt::Default)
303  : FunctionPass(ID), OptLevel(OptLevel) {}
304 
305  bool runOnFunction(Function &F) override {
306  const TargetMachine &TM =
307  getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
308  const TargetLowering &TLI = *TM.getSubtargetImpl(F)->getTargetLowering();
309  DominatorTree *DT = nullptr;
310  const TargetTransformInfo *TTI = nullptr;
311  if (auto *DTWP = getAnalysisIfAvailable<DominatorTreeWrapperPass>())
312  DT = &DTWP->getDomTree();
313  if (OptLevel != CodeGenOpt::None) {
314  if (!DT)
315  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
316  TTI = &getAnalysis<TargetTransformInfoWrapperPass>().getTTI(F);
317  }
318  return prepareDwarfEH(OptLevel, RewindFunction, F, TLI, DT, TTI);
319  }
320 
321  bool doFinalization(Module &M) override {
322  RewindFunction = nullptr;
323  return false;
324  }
325 
326  void getAnalysisUsage(AnalysisUsage &AU) const override {
329  if (OptLevel != CodeGenOpt::None) {
332  }
334  }
335 
336  StringRef getPassName() const override {
337  return "Exception handling preparation";
338  }
339 };
340 
341 } // end anonymous namespace
342 
344 
345 INITIALIZE_PASS_BEGIN(DwarfEHPrepareLegacyPass, DEBUG_TYPE,
346  "Prepare DWARF exceptions", false, false)
350 INITIALIZE_PASS_END(DwarfEHPrepareLegacyPass, DEBUG_TYPE,
351  "Prepare DWARF exceptions", false, false)
352 
353 FunctionPass *llvm::createDwarfEHPass(CodeGenOpt::Level OptLevel) {
354  return new DwarfEHPrepareLegacyPass(OptLevel);
355 }
llvm
This file implements support for optimizing divisions by a constant.
Definition: AllocatorList.h:23
llvm::Type::getInt8PtrTy
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:293
llvm::Function
Definition: Function.h:62
Pass.h
llvm::SmallVector
This is a 'vector' (really, a variable-sized array), optimized for the case when the array is small.
Definition: SmallVector.h:1168
Statistic.h
llvm::TargetTransformInfo
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
Definition: TargetTransformInfo.h:168
DomTreeUpdater.h
llvm::FunctionType::get
static FunctionType * get(Type *Result, ArrayRef< Type * > Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:363
Local.h
llvm::DominatorTree
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree.
Definition: Dominators.h:151
Module.h
llvm::DominatorTreeBase< BasicBlock, false >::Insert
static constexpr UpdateKind Insert
Definition: GenericDomTree.h:242
EHPersonalities.h
F
#define F(x, y, z)
Definition: MD5.cpp:56
llvm::DomTreeUpdater::UpdateStrategy::Lazy
@ Lazy
llvm::BasicBlock
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
llvm::classifyEHPersonality
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
Definition: EHPersonalities.cpp:21
TargetLowering.h
llvm::createDwarfEHPass
FunctionPass * createDwarfEHPass(CodeGenOpt::Level OptLevel)
createDwarfEHPass - This pass mulches exception handling code into a form adapted to code generation.
Definition: DwarfEHPrepare.cpp:353
llvm::CallBase::setDoesNotReturn
void setDoesNotReturn()
Definition: InstrTypes.h:1843
TargetMachine.h
Constants.h
E
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
llvm::TargetLowering
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
Definition: TargetLowering.h:3189
exceptions
Prepare DWARF exceptions
Definition: DwarfEHPrepare.cpp:351
llvm::CallInst::Create
static CallInst * Create(FunctionType *Ty, Value *F, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Definition: Instructions.h:1518
llvm::AnalysisUsage
Represent the analysis usage information of a pass.
Definition: PassAnalysisSupport.h:47
false
Definition: StackSlotColoring.cpp:142
llvm::isPotentiallyReachable
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:236
llvm::DominatorTreeWrapperPass
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:287
llvm::STATISTIC
STATISTIC(NumFunctions, "Total number of functions")
llvm::DomTreeUpdater
Definition: DomTreeUpdater.h:28
BitVector.h
llvm::BitVector
Definition: BitVector.h:74
llvm::Value::use_empty
bool use_empty() const
Definition: Value.h:345
Type.h
INITIALIZE_PASS_END
#define INITIALIZE_PASS_END(passName, arg, name, cfg, analysis)
Definition: PassSupport.h:58
llvm::TargetPassConfig
Target-Independent Code Generator Pass Configuration Options.
Definition: TargetPassConfig.h:84
BasicBlock.h
llvm::Instruction::eraseFromParent
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
Definition: Instruction.cpp:78
llvm::CodeGenOpt::Default
@ Default
Definition: CodeGen.h:55
llvm::InsertValueInst::getNumIndices
unsigned getNumIndices() const
Definition: Instructions.h:2579
llvm::ExtractValueInst::Create
static ExtractValueInst * Create(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
Definition: Instructions.h:2406
RuntimeLibcalls.h
llvm::TargetTransformInfoWrapperPass
Wrapper pass for TargetTransformInfo.
Definition: TargetTransformInfo.h:2387
DEBUG_TYPE
#define DEBUG_TYPE
Definition: DwarfEHPrepare.cpp:42
INITIALIZE_PASS_DEPENDENCY
INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass)
llvm::PHINode::addIncoming
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
Definition: Instructions.h:2783
llvm::LLVMContext
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:68
llvm::BranchInst::Create
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
Definition: Instructions.h:3124
I
#define I(x, y, z)
Definition: MD5.cpp:59
llvm::isScopedEHPersonality
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch,...
Definition: EHPersonalities.h:80
TargetPassConfig.h
llvm::InsertValueInst::idx_begin
idx_iterator idx_begin() const
Definition: Instructions.h:2549
assert
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
llvm::TargetMachine
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:79
llvm::TTI
TargetTransformInfo TTI
Definition: TargetTransformInfo.h:163
llvm::Module
A Module instance is used to store all the information related to an LLVM module.
Definition: Module.h:67
llvm::simplifyCFG
bool simplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, DomTreeUpdater *DTU=nullptr, const SimplifyCFGOptions &Options={}, ArrayRef< WeakVH > LoopHeaders={})
Definition: SimplifyCFG.cpp:6784
llvm::CodeGenOpt::None
@ None
Definition: CodeGen.h:53
CFG.h
llvm::StringRef
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:58
prepareDwarfEH
static bool prepareDwarfEH(CodeGenOpt::Level OptLevel, FunctionCallee &RewindFunction, Function &F, const TargetLowering &TLI, DominatorTree *DT, const TargetTransformInfo *TTI)
Definition: DwarfEHPrepare.cpp:280
llvm::AnalysisUsage::addPreserved
AnalysisUsage & addPreserved()
Add the specified Pass class to the set of analyses preserved by this pass.
Definition: PassAnalysisSupport.h:98
llvm::BasicBlock::Create
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:100
TargetSubtargetInfo.h
llvm::PICLevel::Level
Level
Definition: CodeGen.h:33
llvm::CodeGenOpt::Level
Level
Definition: CodeGen.h:52
llvm::LoadInst
An instruction for reading from memory.
Definition: Instructions.h:175
llvm::EHPersonality
EHPersonality
Definition: EHPersonalities.h:22
runOnFunction
static bool runOnFunction(Function &F, bool PostInlining)
Definition: EntryExitInstrumenter.cpp:69
llvm::ResumeInst
Resume the propagation of an exception.
Definition: Instructions.h:4197
llvm::PHINode::Create
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...
Definition: Instructions.h:2675
Casting.h
Function.h
llvm::Type::getVoidTy
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:224
INITIALIZE_PASS_BEGIN
INITIALIZE_PASS_BEGIN(DwarfEHPrepareLegacyPass, DEBUG_TYPE, "Prepare DWARF exceptions", false, false) INITIALIZE_PASS_END(DwarfEHPrepareLegacyPass
Instructions.h
SmallVector.h
Dominators.h
llvm::Instruction::getParent
const BasicBlock * getParent() const
Definition: Instruction.h:94
TargetTransformInfo.h
llvm::FunctionCallee
A handy container for a FunctionType+Callee-pointer pair, which can be passed around as a single enti...
Definition: DerivedTypes.h:165
llvm::PHINode
Definition: Instructions.h:2633
llvm::SmallVectorImpl
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:43
DerivedTypes.h
TM
const char LLVMTargetMachineRef TM
Definition: PassBuilderBindings.cpp:47
llvm::FunctionPass
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:298
llvm::CallInst
This class represents a function call, abstracting a target machine's calling convention.
Definition: Instructions.h:1475
BB
Common register allocation spilling lr str ldr sxth r3 ldr mla r4 can lr mov lr str ldr sxth r3 mla r4 and then merge mul and lr str ldr sxth r3 mla r4 It also increase the likelihood the store may become dead bb27 Successors according to LLVM BB
Definition: README.txt:39
llvm::UnreachableInst
This function has undefined behavior.
Definition: Instructions.h:4713
llvm::AnalysisUsage::addRequired
AnalysisUsage & addRequired()
Definition: PassAnalysisSupport.h:75
llvm::User::getOperand
Value * getOperand(unsigned i) const
Definition: User.h:169
llvm::InsertValueInst
This instruction inserts a struct field of array element value into an aggregate value.
Definition: Instructions.h:2491
InitializePasses.h
llvm::Value
LLVM Value Representation.
Definition: Value.h:75
llvm::CallBase::setCallingConv
void setCallingConv(CallingConv::ID CC)
Definition: InstrTypes.h:1443
llvm::FunctionType
Class to represent function types.
Definition: DerivedTypes.h:103
llvm::Intrinsic::ID
unsigned ID
Definition: TargetTransformInfo.h:37