LLVM  7.0.0svn
DwarfEHPrepare.cpp
Go to the documentation of this file.
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"
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"
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,
59  SmallVectorImpl<LandingPadInst *> &CleanupLPads);
60 
61  public:
62  static char ID; // Pass identification, replacement for typeid.
63 
64  DwarfEHPrepare() : FunctionPass(ID) {}
65 
66  bool runOnFunction(Function &Fn) override;
67 
68  bool doFinalization(Module &M) override {
69  RewindFunction = nullptr;
70  return false;
71  }
72 
73  void getAnalysisUsage(AnalysisUsage &AU) const override;
74 
75  StringRef getPassName() const override {
76  return "Exception handling preparation";
77  }
78  };
79 
80 } // end anonymous namespace
81 
82 char DwarfEHPrepare::ID = 0;
83 
84 INITIALIZE_PASS_BEGIN(DwarfEHPrepare, DEBUG_TYPE,
85  "Prepare DWARF exceptions", false, false)
90  "Prepare DWARF exceptions", false, false)
91 
92 FunctionPass *llvm::createDwarfEHPass() { return new DwarfEHPrepare(); }
93 
94 void DwarfEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
98 }
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 Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) {
104  Value *V = RI->getOperand(0);
105  Value *ExnObj = nullptr;
107  LoadInst *SelLoad = nullptr;
108  InsertValueInst *ExcIVI = nullptr;
109  bool EraseIVIs = false;
110 
111  if (SelIVI) {
112  if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) {
113  ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0));
114  if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) &&
115  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  if (!ExnObj)
124  ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI);
125 
126  RI->eraseFromParent();
127 
128  if (EraseIVIs) {
129  if (SelIVI->use_empty())
130  SelIVI->eraseFromParent();
131  if (ExcIVI->use_empty())
132  ExcIVI->eraseFromParent();
133  if (SelLoad && SelLoad->use_empty())
134  SelLoad->eraseFromParent();
135  }
136 
137  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 size_t DwarfEHPrepare::pruneUnreachableResumes(
144  SmallVectorImpl<LandingPadInst *> &CleanupLPads) {
145  BitVector ResumeReachable(Resumes.size());
146  size_t ResumeIndex = 0;
147  for (auto *RI : Resumes) {
148  for (auto *LP : CleanupLPads) {
149  if (isPotentiallyReachable(LP, RI, DT)) {
150  ResumeReachable.set(ResumeIndex);
151  break;
152  }
153  }
154  ++ResumeIndex;
155  }
156 
157  // If everything is reachable, there is no change.
158  if (ResumeReachable.all())
159  return Resumes.size();
160 
161  const TargetTransformInfo &TTI =
162  getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn);
163  LLVMContext &Ctx = Fn.getContext();
164 
165  // Otherwise, insert unreachable instructions and call simplifycfg.
166  size_t ResumesLeft = 0;
167  for (size_t I = 0, E = Resumes.size(); I < E; ++I) {
168  ResumeInst *RI = Resumes[I];
169  if (ResumeReachable[I]) {
170  Resumes[ResumesLeft++] = RI;
171  } else {
172  BasicBlock *BB = RI->getParent();
173  new UnreachableInst(Ctx, RI);
174  RI->eraseFromParent();
175  simplifyCFG(BB, TTI);
176  }
177  }
178  Resumes.resize(ResumesLeft);
179  return ResumesLeft;
180 }
181 
182 /// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present
183 /// into calls to the appropriate _Unwind_Resume function.
184 bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) {
187  for (BasicBlock &BB : Fn) {
188  if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator()))
189  Resumes.push_back(RI);
190  if (auto *LP = BB.getLandingPadInst())
191  if (LP->isCleanup())
192  CleanupLPads.push_back(LP);
193  }
194 
195  if (Resumes.empty())
196  return false;
197 
198  // Check the personality, don't do anything if it's scope-based.
199  EHPersonality Pers = classifyEHPersonality(Fn.getPersonalityFn());
200  if (isScopedEHPersonality(Pers))
201  return false;
202 
203  LLVMContext &Ctx = Fn.getContext();
204 
205  size_t ResumesLeft = pruneUnreachableResumes(Fn, Resumes, CleanupLPads);
206  if (ResumesLeft == 0)
207  return true; // We pruned them all.
208 
209  // Find the rewind function if we didn't already.
210  if (!RewindFunction) {
212  Type::getInt8PtrTy(Ctx), false);
213  const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME);
214  RewindFunction = Fn.getParent()->getOrInsertFunction(RewindName, FTy);
215  }
216 
217  // Create the basic block where the _Unwind_Resume call will live.
218  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  ResumeInst *RI = Resumes.front();
222  BasicBlock *UnwindBB = RI->getParent();
223  Value *ExnObj = GetExceptionObject(RI);
224 
225  // Call the _Unwind_Resume function.
226  CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB);
227  CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
228 
229  // We never expect _Unwind_Resume to return.
230  new UnreachableInst(Ctx, UnwindBB);
231  return true;
232  }
233 
234  BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn);
235  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  for (ResumeInst *RI : Resumes) {
241  BasicBlock *Parent = RI->getParent();
242  BranchInst::Create(UnwindBB, Parent);
243 
244  Value *ExnObj = GetExceptionObject(RI);
245  PN->addIncoming(ExnObj, Parent);
246 
247  ++NumResumesLowered;
248  }
249 
250  // Call the function.
251  CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB);
252  CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME));
253 
254  // We never expect _Unwind_Resume to return.
255  new UnreachableInst(Ctx, UnwindBB);
256  return true;
257 }
258 
260  const TargetMachine &TM =
261  getAnalysis<TargetPassConfig>().getTM<TargetMachine>();
262  DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree();
263  TLI = TM.getSubtargetImpl(Fn)->getTargetLowering();
264  bool Changed = InsertUnwindResumeCalls(Fn);
265  DT = nullptr;
266  TLI = nullptr;
267  return Changed;
268 }
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks &#39;this&#39; from the containing basic block and deletes it.
Definition: Instruction.cpp:68
BitVector & set()
Definition: BitVector.h:398
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
Compute iterated dominance frontiers using a linear time algorithm.
Definition: AllocatorList.h:24
unsigned getNumIndices() const
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:63
LLVM_ATTRIBUTE_ALWAYS_INLINE size_type size() const
Definition: SmallVector.h:137
INITIALIZE_PASS_BEGIN(DwarfEHPrepare, DEBUG_TYPE, "Prepare DWARF exceptions", false, false) INITIALIZE_PASS_END(DwarfEHPrepare
#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")
static CallInst * Create(Value *Func, ArrayRef< Value *> Args, ArrayRef< OperandBundleDef > Bundles=None, const Twine &NameStr="", Instruction *InsertBefore=nullptr)
An instruction for reading from memory.
Definition: Instructions.h:168
AnalysisUsage & addRequired()
#define INITIALIZE_PASS_DEPENDENCY(depName)
Definition: PassSupport.h:51
This class consists of common code factored out of the SmallVector class to reduce code duplication b...
Definition: APFloat.h:42
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:103
Concrete subclass of DominatorTreeBase that is used to compute a normal dominator tree...
Definition: Dominators.h:142
Value * getOperand(unsigned i) const
Definition: User.h:170
static bool runOnFunction(Function &F, bool PostInlining)
Wrapper pass for TargetTransformInfo.
LLVM Basic Block Representation.
Definition: BasicBlock.h:59
This is an important class for using LLVM in a threaded context.
Definition: LLVMContext.h:69
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")
This is an important base class in LLVM.
Definition: Constant.h:42
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:161
FunctionPass class - This class is used to implement most global optimizations.
Definition: Pass.h:285
static FunctionType * get(Type *Result, ArrayRef< Type *> Params, bool isVarArg)
This static method is the primary way of constructing a FunctionType.
Definition: Type.cpp:297
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Definition: BasicBlock.h:101
bool isPotentiallyReachable(const Instruction *From, const Instruction *To, const DominatorTree *DT=nullptr, const LoopInfo *LI=nullptr)
Determine whether instruction &#39;To&#39; is reachable from &#39;From&#39;, returning true if uncertain.
Definition: CFG.cpp:186
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
Definition: Function.cpp:194
static PointerType * getInt8PtrTy(LLVMContext &C, unsigned AS=0)
Definition: Type.cpp:220
INITIALIZE_PASS_END(RegBankSelect, DEBUG_TYPE, "Assign register bank of generic virtual registers", false, false) RegBankSelect
void setCallingConv(CallingConv::ID CC)
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:861
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:62
#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:323
size_type size() const
size - Returns the number of bits in this bitvector.
Definition: BitVector.h:170
LLVM Value Representation.
Definition: Value.h:73
Primary interface to the complete machine description for the target machine.
Definition: TargetMachine.h:59
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:49
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:254
This pass exposes codegen information to IR-level passes.
bool use_empty() const
Definition: Value.h:322
This file describes how to lower LLVM code to machine code.
const BasicBlock * getParent() const
Definition: Instruction.h:67
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...