LLVM  10.0.0svn
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/Pass.h"
34 #include "llvm/Support/Casting.h"
36 #include <cstddef>
37 
38 using namespace llvm;
39 
40 #define DEBUG_TYPE "dwarfehprepare"
41 
42 STATISTIC(NumResumesLowered, "Number of resume calls lowered");
43 
44 namespace {
45 
46  class DwarfEHPrepare : public FunctionPass {
47  // RewindFunction - _Unwind_Resume or the target equivalent.
48  FunctionCallee RewindFunction = nullptr;
49 
50  DominatorTree *DT = nullptr;
51  const TargetLowering *TLI = nullptr;
52 
53  bool InsertUnwindResumeCalls(Function &Fn);
54  Value *GetExceptionObject(ResumeInst *RI);
55  size_t
56  pruneUnreachableResumes(Function &Fn,
58  SmallVectorImpl<LandingPadInst *> &CleanupLPads);
59 
60  public:
61  static char ID; // Pass identification, replacement for typeid.
62 
63  DwarfEHPrepare() : FunctionPass(ID) {}
64 
65  bool runOnFunction(Function &Fn) override;
66 
67  bool doFinalization(Module &M) override {
68  RewindFunction = nullptr;
69  return false;
70  }
71 
72  void getAnalysisUsage(AnalysisUsage &AU) const override;
73 
74  StringRef getPassName() const override {
75  return "Exception handling preparation";
76  }
77  };
78 
79 } // end anonymous namespace
80 
81 char DwarfEHPrepare::ID = 0;
82 
83 INITIALIZE_PASS_BEGIN(DwarfEHPrepare, DEBUG_TYPE,
84  "Prepare DWARF exceptions", false, false)
89  "Prepare DWARF exceptions", false, false)
90 
91 FunctionPass *llvm::createDwarfEHPass() { return new DwarfEHPrepare(); }
92 
93 void DwarfEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
97 }
98 
99 /// GetExceptionObject - Return the exception object from the value passed into
100 /// the 'resume' instruction (typically an aggregate). Clean up any dead
101 /// instructions, including the 'resume' instruction.
102 Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
103  Value *V = RI->getOperand(0);
104  Value *ExnObj = nullptr;
106  LoadInst *SelLoad = nullptr;
107  InsertValueInst *ExcIVI = nullptr;
108  bool EraseIVIs = false;
109 
110  if (SelIVI) {
111  if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
112  ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
113  if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
114  ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) {
115  ExnObj = ExcIVI->getOperand(1);
116  SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1));
117  EraseIVIs = true;
118  }
119  }
120  }
121 
122  if (!ExnObj)
123  ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
124 
125  RI->eraseFromParent();
126 
127  if (EraseIVIs) {
128  if (SelIVI->use_empty())
129  SelIVI->eraseFromParent();
130  if (ExcIVI->use_empty())
131  ExcIVI->eraseFromParent();
132  if (SelLoad && SelLoad->use_empty())
133  SelLoad->eraseFromParent();
134  }
135 
136  return ExnObj;
137 }
138 
139 /// Replace resumes that are not reachable from a cleanup landing pad with
140 /// unreachable and then simplify those blocks.
141 size_t DwarfEHPrepare::pruneUnreachableResumes(
143  SmallVectorImpl<LandingPadInst *> &CleanupLPads) {
144  BitVector ResumeReachable(Resumes.size());
145  size_t ResumeIndex = 0;
146  for (auto *RI : Resumes) {
147  for (auto *LP : CleanupLPads) {
148  if (isPotentiallyReachable(LP, RI, nullptr, DT)) {
149  ResumeReachable.set(ResumeIndex);
150  break;
151  }
152  }
153  ++ResumeIndex;
154  }
155 
156  // If everything is reachable, there is no change.
157  if (ResumeReachable.all())
158  return Resumes.size();
159 
160  const TargetTransformInfo &TTI =
161  getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn);
162  LLVMContext &Ctx = Fn.getContext();
163 
164  // Otherwise, insert unreachable instructions and call simplifycfg.
165  size_t ResumesLeft = 0;
166  for (size_t I = 0, E = Resumes.size(); I < E; ++I) {
167  ResumeInst *RI = Resumes[I];
168  if (ResumeReachable[I]) {
169  Resumes[ResumesLeft++] = RI;
170  } else {
171  BasicBlock *BB = RI->getParent();
172  new UnreachableInst(Ctx, RI);
173  RI->eraseFromParent();
174  simplifyCFG(BB, TTI);
175  }
176  }
177  Resumes.resize(ResumesLeft);
178  return ResumesLeft;
179 }
180 
181 /// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present
182 /// into calls to the appropriate _Unwind_Resume function.
183 bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
186  for (BasicBlock &BB : Fn) {
187  if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator()))
188  Resumes.push_back(RI);
189  if (auto *LP = BB.getLandingPadInst())
190  if (LP->isCleanup())
191  CleanupLPads.push_back(LP);
192  }
193 
194  if (Resumes.empty())
195  return false;
196 
197  // Check the personality, don't do anything if it's scope-based.
198  EHPersonality Pers = classifyEHPersonality(Fn.getPersonalityFn());
199  if (isScopedEHPersonality(Pers))
200  return false;
201 
202  LLVMContext &Ctx = Fn.getContext();
203 
204  size_t ResumesLeft = pruneUnreachableResumes(Fn, Resumes, CleanupLPads);
205  if (ResumesLeft == 0)
206  return true; // We pruned them all.
207 
208  // Find the rewind function if we didn't already.
209  if (!RewindFunction) {
211  Type::getInt8PtrTy(Ctx), false);
212  const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME);
213  RewindFunction = Fn.getParent()->getOrInsertFunction(RewindName, FTy);
214  }
215 
216  // Create the basic block where the _Unwind_Resume call will live.
217  if (ResumesLeft == 1) {
218  // Instead of creating a new BB and PHI node, just append the call to
219  // _Unwind_Resume to the end of the single resume block.
220  ResumeInst *RI = Resumes.front();
221  BasicBlock *UnwindBB = RI->getParent();
222  Value *ExnObj = GetExceptionObject(RI);
223 
224  // Call the _Unwind_Resume function.
225  CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB);
226  CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
227 
228  // We never expect _Unwind_Resume to return.
229  new UnreachableInst(Ctx, UnwindBB);
230  return true;
231  }
232 
233  BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn);
234  PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft,
235  "exn.obj", UnwindBB);
236 
237  // Extract the exception object from the ResumeInst and add it to the PHI node
238  // that feeds the _Unwind_Resume call.
239  for (ResumeInst *RI : Resumes) {
240  BasicBlock *Parent = RI->getParent();
241  BranchInst::Create(UnwindBB, Parent);
242 
243  Value *ExnObj = GetExceptionObject(RI);
244  PN->addIncoming(ExnObj, Parent);
245 
246  ++NumResumesLowered;
247  }
248 
249  // Call the function.
250  CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB);
251  CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
252 
253  // We never expect _Unwind_Resume to return.
254  new UnreachableInst(Ctx, UnwindBB);
255  return true;
256 }
257 
259  const TargetMachine &TM =
260  getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
261  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
262  TLI = TM.getSubtargetImpl(Fn)->getTargetLowering();
263  bool Changed = InsertUnwindResumeCalls(Fn);
264  DT = nullptr;
265  TLI = nullptr;
266  return Changed;
267 }
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks &#39;this&#39; from the containing basic block and deletes it.
Definition: Instruction.cpp:67
BitVector & set()
Definition: BitVector.h:397
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
This class represents lattice values for constants.
Definition: AllocatorList.h:23
unsigned getNumIndices() const
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:66
bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const SmallPtrSetImpl< BasicBlock *> *ExclusionSet=nullptr, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether instruction &#39;To&#39; is reachable from &#39;From&#39;, without passing through any blocks in Ex...
Definition: CFG.cpp:218
INITIALIZE_PASS_BEGIN(DwarfEHPrepare, DEBUG_TYPE, "Prepare DWARF exceptions", false, false) INITIALIZE_PASS_END(DwarfEHPrepare
static CallInst * Create(FunctionType *Ty, Value *F, 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:170
#define DEBUG_TYPE
This class represents a function call, abstracting a target machine&#39;s calling convention.
virtual const TargetLowering * getTargetLowering() const
STATISTIC(NumFunctions, "Total number of functions")
An instruction for reading from memory.
Definition: Instructions.h:169
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:50
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:41
Target-Independent Code Generator Pass Configuration Options.
This class defines information used to lower LLVM code to legal SelectionDAG operators that the targe...
bool isScopedEHPersonality(EHPersonality Pers)
Returns true if this personality uses scope-style EH IR instructions: catchswitch, catchpad/ret, and cleanuppad/ret.
Class to represent function types.
Definition: DerivedTypes.h:108
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Definition: Dominators.h:144
Value * getOperand(unsigned i) const
Definition: User.h:169
static bool runOnFunction(Function &F, bool PostInlining)
Wrapper pass for TargetTransformInfo.
LLVM Basic Block Representation.
Definition: BasicBlock.h:57
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:64
static ExtractValueInst * Create(Value *Agg, ArrayRef< unsigned > Idxs, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
This function has undefined behavior.
static GCRegistry::Add< CoreCLRGC > E("coreclr", "CoreCLR-compatible GC")
Resume the propagation of an exception.
This file contains the declarations for the subclasses of Constant, which represent the different fla...
EHPersonality classifyEHPersonality(const Value *Pers)
See if the given exception handling personality function is one that we understand.
Represent the analysis usage information of a pass.
static Type * getVoidTy(LLVMContext &C)
Definition: Type.cpp:165
void setCallingConv(CallingConv::ID CC)
Definition: InstrTypes.h:1348
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:284
static FunctionType * get(Type *Result, ArrayRef< Type *> Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:301
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:99
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:205
size_t size() const
Definition: SmallVector.h:52
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:224
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
idx_iterator idx_begin() const
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:837
Module.h This file contains the declarations for the Module class.
Prepare DWARF exceptions
static BranchInst * Create(BasicBlock *IfTrue, Instruction *InsertBefore=nullptr)
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 const TargetSubtargetInfo * getSubtargetImpl(const Function &) const
Virtual method implemented by subclasses that returns a reference to that target&#39;s TargetSubtargetInf...
LLVM_NODISCARD bool empty() const
Definition: SmallVector.h:55
#define I(x, y, z)
Definition: MD5.cpp:58
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
Definition: Casting.h:332
size_type size() const
size - Returns the number of bits in this bitvector.
Definition: BitVector.h:169
LLVM Value Representation.
Definition: Value.h:74
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:65
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:48
bool simplifyCFG(BasicBlock *BB, const TargetTransformInfo &TTI, const SimplifyCFGOptions &Options={}, SmallPtrSetImpl< BasicBlock *> *LoopHeaders=nullptr)
This function is used to do simplification of a CFG.
Legacy analysis pass which computes a DominatorTree.
Definition: Dominators.h:259
This pass exposes codegen information to IR-level passes.
bool use_empty() const
Definition: Value.h:343
This file describes how to lower LLVM code to machine code.
const BasicBlock * getParent() const
Definition: Instruction.h:66
This instruction inserts a struct field of array element value into an aggregate value.
FunctionPass * createDwarfEHPass()
createDwarfEHPass - This pass mulches exception handling code into a form adapted to code generation...