LLVM API Documentation
00001 //===-- DwarfEHPrepare - Prepare exception handling for code generation ---===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 // 00010 // This pass mulches exception handling code into a form adapted to code 00011 // generation. Required if using dwarf exception handling. 00012 // 00013 //===----------------------------------------------------------------------===// 00014 00015 #include "llvm/CodeGen/Passes.h" 00016 #include "llvm/ADT/Statistic.h" 00017 #include "llvm/IR/CallSite.h" 00018 #include "llvm/IR/Dominators.h" 00019 #include "llvm/IR/Function.h" 00020 #include "llvm/IR/Instructions.h" 00021 #include "llvm/IR/IntrinsicInst.h" 00022 #include "llvm/IR/Module.h" 00023 #include "llvm/MC/MCAsmInfo.h" 00024 #include "llvm/Pass.h" 00025 #include "llvm/Target/TargetLowering.h" 00026 #include "llvm/Target/TargetSubtargetInfo.h" 00027 #include "llvm/Transforms/Utils/BasicBlockUtils.h" 00028 #include "llvm/Transforms/Utils/SSAUpdater.h" 00029 using namespace llvm; 00030 00031 #define DEBUG_TYPE "dwarfehprepare" 00032 00033 STATISTIC(NumResumesLowered, "Number of resume calls lowered"); 00034 00035 namespace { 00036 class DwarfEHPrepare : public FunctionPass { 00037 const TargetMachine *TM; 00038 00039 // RewindFunction - _Unwind_Resume or the target equivalent. 00040 Constant *RewindFunction; 00041 00042 bool InsertUnwindResumeCalls(Function &Fn); 00043 Value *GetExceptionObject(ResumeInst *RI); 00044 00045 public: 00046 static char ID; // Pass identification, replacement for typeid. 00047 DwarfEHPrepare(const TargetMachine *TM) 00048 : FunctionPass(ID), TM(TM), RewindFunction(nullptr) { 00049 initializeDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry()); 00050 } 00051 00052 bool runOnFunction(Function &Fn) override; 00053 00054 bool doFinalization(Module &M) override { 00055 RewindFunction = nullptr; 00056 return false; 00057 } 00058 00059 void getAnalysisUsage(AnalysisUsage &AU) const override { } 00060 00061 const char *getPassName() const override { 00062 return "Exception handling preparation"; 00063 } 00064 }; 00065 } // end anonymous namespace 00066 00067 char DwarfEHPrepare::ID = 0; 00068 00069 FunctionPass *llvm::createDwarfEHPass(const TargetMachine *TM) { 00070 return new DwarfEHPrepare(TM); 00071 } 00072 00073 /// GetExceptionObject - Return the exception object from the value passed into 00074 /// the 'resume' instruction (typically an aggregate). Clean up any dead 00075 /// instructions, including the 'resume' instruction. 00076 Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) { 00077 Value *V = RI->getOperand(0); 00078 Value *ExnObj = nullptr; 00079 InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V); 00080 LoadInst *SelLoad = nullptr; 00081 InsertValueInst *ExcIVI = nullptr; 00082 bool EraseIVIs = false; 00083 00084 if (SelIVI) { 00085 if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) { 00086 ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0)); 00087 if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) && 00088 ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) { 00089 ExnObj = ExcIVI->getOperand(1); 00090 SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1)); 00091 EraseIVIs = true; 00092 } 00093 } 00094 } 00095 00096 if (!ExnObj) 00097 ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI); 00098 00099 RI->eraseFromParent(); 00100 00101 if (EraseIVIs) { 00102 if (SelIVI->getNumUses() == 0) 00103 SelIVI->eraseFromParent(); 00104 if (ExcIVI->getNumUses() == 0) 00105 ExcIVI->eraseFromParent(); 00106 if (SelLoad && SelLoad->getNumUses() == 0) 00107 SelLoad->eraseFromParent(); 00108 } 00109 00110 return ExnObj; 00111 } 00112 00113 /// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present 00114 /// into calls to the appropriate _Unwind_Resume function. 00115 bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) { 00116 SmallVector<ResumeInst*, 16> Resumes; 00117 for (Function::iterator I = Fn.begin(), E = Fn.end(); I != E; ++I) { 00118 TerminatorInst *TI = I->getTerminator(); 00119 if (ResumeInst *RI = dyn_cast<ResumeInst>(TI)) 00120 Resumes.push_back(RI); 00121 } 00122 00123 if (Resumes.empty()) 00124 return false; 00125 00126 // Find the rewind function if we didn't already. 00127 const TargetLowering *TLI = TM->getSubtargetImpl()->getTargetLowering(); 00128 if (!RewindFunction) { 00129 LLVMContext &Ctx = Resumes[0]->getContext(); 00130 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), 00131 Type::getInt8PtrTy(Ctx), false); 00132 const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME); 00133 RewindFunction = Fn.getParent()->getOrInsertFunction(RewindName, FTy); 00134 } 00135 00136 // Create the basic block where the _Unwind_Resume call will live. 00137 LLVMContext &Ctx = Fn.getContext(); 00138 unsigned ResumesSize = Resumes.size(); 00139 00140 if (ResumesSize == 1) { 00141 // Instead of creating a new BB and PHI node, just append the call to 00142 // _Unwind_Resume to the end of the single resume block. 00143 ResumeInst *RI = Resumes.front(); 00144 BasicBlock *UnwindBB = RI->getParent(); 00145 Value *ExnObj = GetExceptionObject(RI); 00146 00147 // Call the _Unwind_Resume function. 00148 CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB); 00149 CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME)); 00150 00151 // We never expect _Unwind_Resume to return. 00152 new UnreachableInst(Ctx, UnwindBB); 00153 return true; 00154 } 00155 00156 BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn); 00157 PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesSize, 00158 "exn.obj", UnwindBB); 00159 00160 // Extract the exception object from the ResumeInst and add it to the PHI node 00161 // that feeds the _Unwind_Resume call. 00162 for (SmallVectorImpl<ResumeInst*>::iterator 00163 I = Resumes.begin(), E = Resumes.end(); I != E; ++I) { 00164 ResumeInst *RI = *I; 00165 BasicBlock *Parent = RI->getParent(); 00166 BranchInst::Create(UnwindBB, Parent); 00167 00168 Value *ExnObj = GetExceptionObject(RI); 00169 PN->addIncoming(ExnObj, Parent); 00170 00171 ++NumResumesLowered; 00172 } 00173 00174 // Call the function. 00175 CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB); 00176 CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME)); 00177 00178 // We never expect _Unwind_Resume to return. 00179 new UnreachableInst(Ctx, UnwindBB); 00180 return true; 00181 } 00182 00183 bool DwarfEHPrepare::runOnFunction(Function &Fn) { 00184 bool Changed = InsertUnwindResumeCalls(Fn); 00185 return Changed; 00186 }