1 //===-- WinEHPrepare - 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 lowers LLVM IR exception handling into something closer to what the 11 // backend wants. It snifs the personality function to see which kind of 12 // preparation is necessary. If the personality function uses the Itanium LSDA, 13 // this pass delegates to the DWARF EH preparation pass. 14 // 15 //===----------------------------------------------------------------------===// 16 17 #include "llvm/CodeGen/Passes.h" 18 #include "llvm/Analysis/LibCallSemantics.h" 19 #include "llvm/IR/Function.h" 20 #include "llvm/IR/IRBuilder.h" 21 #include "llvm/IR/Instructions.h" 22 #include "llvm/Pass.h" 23 #include <memory> 24 25 using namespace llvm; 26 27 #define DEBUG_TYPE "winehprepare" 28 29 namespace { 30 class WinEHPrepare : public FunctionPass { 31 std::unique_ptr<FunctionPass> DwarfPrepare; 32 33 public: 34 static char ID; // Pass identification, replacement for typeid. 35 WinEHPrepare(const TargetMachine *TM = nullptr) 36 : FunctionPass(ID), DwarfPrepare(createDwarfEHPass(TM)) {} 37 38 bool runOnFunction(Function &Fn) override; 39 40 bool doFinalization(Module &M) override; 41 42 void getAnalysisUsage(AnalysisUsage &AU) const override; 43 44 const char *getPassName() const override { 45 return "Windows exception handling preparation"; 46 } 47 }; 48 } // end anonymous namespace 49 50 char WinEHPrepare::ID = 0; 51 INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare", 52 "Prepare Windows exceptions", false, false) 53 54 FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) { 55 return new WinEHPrepare(TM); 56 } 57 58 static bool isMSVCPersonality(EHPersonality Pers) { 59 return Pers == EHPersonality::MSVC_Win64SEH || 60 Pers == EHPersonality::MSVC_CXX; 61 } 62 63 bool WinEHPrepare::runOnFunction(Function &Fn) { 64 SmallVector<LandingPadInst *, 4> LPads; 65 SmallVector<ResumeInst *, 4> Resumes; 66 for (BasicBlock &BB : Fn) { 67 if (auto *LP = BB.getLandingPadInst()) 68 LPads.push_back(LP); 69 if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator())) 70 Resumes.push_back(Resume); 71 } 72 73 // No need to prepare functions that lack landing pads. 74 if (LPads.empty()) 75 return false; 76 77 // Classify the personality to see what kind of preparation we need. 78 EHPersonality Pers = ClassifyEHPersonality(LPads.back()->getPersonalityFn()); 79 80 // Delegate through to the DWARF pass if this is unrecognized. 81 if (!isMSVCPersonality(Pers)) 82 return DwarfPrepare->runOnFunction(Fn); 83 84 // FIXME: Cleanups are unimplemented. Replace them with unreachable. 85 if (Resumes.empty()) 86 return false; 87 88 for (ResumeInst *Resume : Resumes) { 89 IRBuilder<>(Resume).CreateUnreachable(); 90 Resume->eraseFromParent(); 91 } 92 93 return true; 94 } 95 96 bool WinEHPrepare::doFinalization(Module &M) { 97 return DwarfPrepare->doFinalization(M); 98 } 99 100 void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const { 101 DwarfPrepare->getAnalysisUsage(AU); 102 } 103