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/CodeGen/Passes.h" 16 #include "llvm/ADT/BitVector.h" 17 #include "llvm/ADT/Statistic.h" 18 #include "llvm/Analysis/CFG.h" 19 #include "llvm/Analysis/LibCallSemantics.h" 20 #include "llvm/Analysis/TargetTransformInfo.h" 21 #include "llvm/IR/Dominators.h" 22 #include "llvm/IR/Function.h" 23 #include "llvm/IR/Instructions.h" 24 #include "llvm/IR/Module.h" 25 #include "llvm/Pass.h" 26 #include "llvm/Target/TargetLowering.h" 27 #include "llvm/Target/TargetSubtargetInfo.h" 28 #include "llvm/Transforms/Utils/Local.h" 29 using namespace llvm; 30 31 #define DEBUG_TYPE "dwarfehprepare" 32 33 STATISTIC(NumResumesLowered, "Number of resume calls lowered"); 34 35 namespace { 36 class DwarfEHPrepare : public FunctionPass { 37 const TargetMachine *TM; 38 39 // RewindFunction - _Unwind_Resume or the target equivalent. 40 Constant *RewindFunction; 41 42 DominatorTree *DT; 43 const TargetLowering *TLI; 44 45 bool InsertUnwindResumeCalls(Function &Fn); 46 Value *GetExceptionObject(ResumeInst *RI); 47 size_t 48 pruneUnreachableResumes(Function &Fn, 49 SmallVectorImpl<ResumeInst *> &Resumes, 50 SmallVectorImpl<LandingPadInst *> &CleanupLPads); 51 52 public: 53 static char ID; // Pass identification, replacement for typeid. 54 55 // INITIALIZE_TM_PASS requires a default constructor, but it isn't used in 56 // practice. 57 DwarfEHPrepare() 58 : FunctionPass(ID), TM(nullptr), RewindFunction(nullptr), DT(nullptr), 59 TLI(nullptr) {} 60 61 DwarfEHPrepare(const TargetMachine *TM) 62 : FunctionPass(ID), TM(TM), RewindFunction(nullptr), DT(nullptr), 63 TLI(nullptr) {} 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 const char *getPassName() const override { 75 return "Exception handling preparation"; 76 } 77 }; 78 } // end anonymous namespace 79 80 char DwarfEHPrepare::ID = 0; 81 INITIALIZE_TM_PASS_BEGIN(DwarfEHPrepare, "dwarfehprepare", 82 "Prepare DWARF exceptions", false, false) 83 INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) 84 INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) 85 INITIALIZE_TM_PASS_END(DwarfEHPrepare, "dwarfehprepare", 86 "Prepare DWARF exceptions", false, false) 87 88 FunctionPass *llvm::createDwarfEHPass(const TargetMachine *TM) { 89 return new DwarfEHPrepare(TM); 90 } 91 92 void DwarfEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const { 93 AU.addRequired<TargetTransformInfoWrapperPass>(); 94 AU.addRequired<DominatorTreeWrapperPass>(); 95 } 96 97 /// GetExceptionObject - Return the exception object from the value passed into 98 /// the 'resume' instruction (typically an aggregate). Clean up any dead 99 /// instructions, including the 'resume' instruction. 100 Value *DwarfEHPrepare::GetExceptionObject(ResumeInst *RI) { 101 Value *V = RI->getOperand(0); 102 Value *ExnObj = nullptr; 103 InsertValueInst *SelIVI = dyn_cast<InsertValueInst>(V); 104 LoadInst *SelLoad = nullptr; 105 InsertValueInst *ExcIVI = nullptr; 106 bool EraseIVIs = false; 107 108 if (SelIVI) { 109 if (SelIVI->getNumIndices() == 1 && *SelIVI->idx_begin() == 1) { 110 ExcIVI = dyn_cast<InsertValueInst>(SelIVI->getOperand(0)); 111 if (ExcIVI && isa<UndefValue>(ExcIVI->getOperand(0)) && 112 ExcIVI->getNumIndices() == 1 && *ExcIVI->idx_begin() == 0) { 113 ExnObj = ExcIVI->getOperand(1); 114 SelLoad = dyn_cast<LoadInst>(SelIVI->getOperand(1)); 115 EraseIVIs = true; 116 } 117 } 118 } 119 120 if (!ExnObj) 121 ExnObj = ExtractValueInst::Create(RI->getOperand(0), 0, "exn.obj", RI); 122 123 RI->eraseFromParent(); 124 125 if (EraseIVIs) { 126 if (SelIVI->use_empty()) 127 SelIVI->eraseFromParent(); 128 if (ExcIVI->use_empty()) 129 ExcIVI->eraseFromParent(); 130 if (SelLoad && SelLoad->use_empty()) 131 SelLoad->eraseFromParent(); 132 } 133 134 return ExnObj; 135 } 136 137 /// Replace resumes that are not reachable from a cleanup landing pad with 138 /// unreachable and then simplify those blocks. 139 size_t DwarfEHPrepare::pruneUnreachableResumes( 140 Function &Fn, SmallVectorImpl<ResumeInst *> &Resumes, 141 SmallVectorImpl<LandingPadInst *> &CleanupLPads) { 142 BitVector ResumeReachable(Resumes.size()); 143 size_t ResumeIndex = 0; 144 for (auto *RI : Resumes) { 145 for (auto *LP : CleanupLPads) { 146 if (isPotentiallyReachable(LP, RI, DT)) { 147 ResumeReachable.set(ResumeIndex); 148 break; 149 } 150 } 151 ++ResumeIndex; 152 } 153 154 // If everything is reachable, there is no change. 155 if (ResumeReachable.all()) 156 return Resumes.size(); 157 158 const TargetTransformInfo &TTI = 159 getAnalysis<TargetTransformInfoWrapperPass>().getTTI(Fn); 160 LLVMContext &Ctx = Fn.getContext(); 161 162 // Otherwise, insert unreachable instructions and call simplifycfg. 163 size_t ResumesLeft = 0; 164 for (size_t I = 0, E = Resumes.size(); I < E; ++I) { 165 ResumeInst *RI = Resumes[I]; 166 if (ResumeReachable[I]) { 167 Resumes[ResumesLeft++] = RI; 168 } else { 169 BasicBlock *BB = RI->getParent(); 170 new UnreachableInst(Ctx, RI); 171 RI->eraseFromParent(); 172 SimplifyCFG(BB, TTI, 1); 173 } 174 } 175 Resumes.resize(ResumesLeft); 176 return ResumesLeft; 177 } 178 179 /// InsertUnwindResumeCalls - Convert the ResumeInsts that are still present 180 /// into calls to the appropriate _Unwind_Resume function. 181 bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) { 182 SmallVector<ResumeInst*, 16> Resumes; 183 SmallVector<LandingPadInst*, 16> CleanupLPads; 184 bool FoundLP = false; 185 for (BasicBlock &BB : Fn) { 186 if (auto *RI = dyn_cast<ResumeInst>(BB.getTerminator())) 187 Resumes.push_back(RI); 188 if (auto *LP = BB.getLandingPadInst()) { 189 if (LP->isCleanup()) 190 CleanupLPads.push_back(LP); 191 // Check the personality on the first landingpad. Don't do anything if 192 // it's for MSVC. 193 if (!FoundLP) { 194 FoundLP = true; 195 EHPersonality Pers = classifyEHPersonality(LP->getPersonalityFn()); 196 if (isMSVCEHPersonality(Pers)) 197 return false; 198 } 199 } 200 } 201 202 if (Resumes.empty()) 203 return false; 204 205 LLVMContext &Ctx = Fn.getContext(); 206 207 size_t ResumesLeft = pruneUnreachableResumes(Fn, Resumes, CleanupLPads); 208 if (ResumesLeft == 0) 209 return true; // We pruned them all. 210 211 // Find the rewind function if we didn't already. 212 if (!RewindFunction) { 213 FunctionType *FTy = FunctionType::get(Type::getVoidTy(Ctx), 214 Type::getInt8PtrTy(Ctx), false); 215 const char *RewindName = TLI->getLibcallName(RTLIB::UNWIND_RESUME); 216 RewindFunction = Fn.getParent()->getOrInsertFunction(RewindName, FTy); 217 } 218 219 // Create the basic block where the _Unwind_Resume call will live. 220 if (ResumesLeft == 1) { 221 // Instead of creating a new BB and PHI node, just append the call to 222 // _Unwind_Resume to the end of the single resume block. 223 ResumeInst *RI = Resumes.front(); 224 BasicBlock *UnwindBB = RI->getParent(); 225 Value *ExnObj = GetExceptionObject(RI); 226 227 // Call the _Unwind_Resume function. 228 CallInst *CI = CallInst::Create(RewindFunction, ExnObj, "", UnwindBB); 229 CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME)); 230 231 // We never expect _Unwind_Resume to return. 232 new UnreachableInst(Ctx, UnwindBB); 233 return true; 234 } 235 236 BasicBlock *UnwindBB = BasicBlock::Create(Ctx, "unwind_resume", &Fn); 237 PHINode *PN = PHINode::Create(Type::getInt8PtrTy(Ctx), ResumesLeft, 238 "exn.obj", UnwindBB); 239 240 // Extract the exception object from the ResumeInst and add it to the PHI node 241 // that feeds the _Unwind_Resume call. 242 for (ResumeInst *RI : Resumes) { 243 BasicBlock *Parent = RI->getParent(); 244 BranchInst::Create(UnwindBB, Parent); 245 246 Value *ExnObj = GetExceptionObject(RI); 247 PN->addIncoming(ExnObj, Parent); 248 249 ++NumResumesLowered; 250 } 251 252 // Call the function. 253 CallInst *CI = CallInst::Create(RewindFunction, PN, "", UnwindBB); 254 CI->setCallingConv(TLI->getLibcallCallingConv(RTLIB::UNWIND_RESUME)); 255 256 // We never expect _Unwind_Resume to return. 257 new UnreachableInst(Ctx, UnwindBB); 258 return true; 259 } 260 261 bool DwarfEHPrepare::runOnFunction(Function &Fn) { 262 assert(TM && "DWARF EH preparation requires a target machine"); 263 DT = &getAnalysis<DominatorTreeWrapperPass>().getDomTree(); 264 TLI = TM->getSubtargetImpl(Fn)->getTargetLowering(); 265 bool Changed = InsertUnwindResumeCalls(Fn); 266 DT = nullptr; 267 TLI = nullptr; 268 return Changed; 269 } 270