LLVM  6.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"
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"
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 funclet-based.
199  EHPersonality Pers = classifyEHPersonality(Fn.getPersonalityFn());
200  if (isFuncletEHPersonality(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:69
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:136
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:164
void setCallingConv(CallingConv::ID CC)
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...
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:140
Value * getOperand(unsigned i) const
Definition: User.h:154
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
idx_iterator idx_begin() const
This pass provides access to the codegen interfaces that are needed for IR-level transformations.
bool isFuncletEHPersonality(EHPersonality Pers)
Returns true if this is a personality function that invokes handler funclets (which must return to it...
This is a &#39;vector&#39; (really, a variable-sized array), optimized for the case when the array is small...
Definition: SmallVector.h:864
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:61
#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:57
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:267
This pass exposes codegen information to IR-level passes.
bool use_empty() const
Definition: Value.h:328
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...