Add a Windows EH preparation pass that zaps resumes
[oota-llvm.git] / lib / CodeGen / WinEHPrepare.cpp
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/Instructions.h"
21 #include "llvm/IR/Intrinsics.h"
22 #include "llvm/Pass.h"
23 #include "llvm/Target/TargetLowering.h"
24 using namespace llvm;
25
26 #define DEBUG_TYPE "winehprepare"
27
28 namespace {
29 class WinEHPrepare : public FunctionPass {
30   const TargetMachine *TM;
31   FunctionPass *DwarfPrepare;
32
33 public:
34   static char ID; // Pass identification, replacement for typeid.
35   WinEHPrepare(const TargetMachine *TM = nullptr)
36       : FunctionPass(ID), TM(TM), DwarfPrepare(createDwarfEHPass(TM)) {
37     initializeDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry());
38   }
39
40   bool runOnFunction(Function &Fn) override;
41
42   bool doFinalization(Module &M) override;
43
44   void getAnalysisUsage(AnalysisUsage &AU) const override;
45
46   const char *getPassName() const override {
47     return "Windows exception handling preparation";
48   }
49 };
50 } // end anonymous namespace
51
52 char WinEHPrepare::ID = 0;
53 INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare",
54                    "Prepare Windows exceptions", false, false)
55
56 FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
57   return new WinEHPrepare(TM);
58 }
59
60 static bool isMSVCPersonality(EHPersonality Pers) {
61   return Pers == EHPersonality::MSVC_Win64SEH ||
62          Pers == EHPersonality::MSVC_CXX;
63 }
64
65 bool WinEHPrepare::runOnFunction(Function &Fn) {
66   SmallVector<LandingPadInst *, 4> LPads;
67   SmallVector<ResumeInst *, 4> Resumes;
68   for (BasicBlock &BB : Fn) {
69     if (auto *LP = BB.getLandingPadInst())
70       LPads.push_back(LP);
71     if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator()))
72       Resumes.push_back(Resume);
73   }
74
75   // No need to prepare functions that lack landing pads.
76   if (LPads.empty())
77     return false;
78
79   // Classify the personality to see what kind of preparation we need.
80   EHPersonality Pers = ClassifyEHPersonality(LPads.back()->getPersonalityFn());
81
82   // Delegate through to the DWARF pass if this is unrecognized.
83   if (!isMSVCPersonality(Pers))
84     return DwarfPrepare->runOnFunction(Fn);
85
86   // FIXME: Cleanups are unimplemented. Replace them with calls to @llvm.trap.
87   if (Resumes.empty())
88     return false;
89
90   Function *Trap =
91       Intrinsic::getDeclaration(Fn.getParent(), Intrinsic::trap, None);
92   for (ResumeInst *Resume : Resumes) {
93     IRBuilder<>(Resume).CreateUnreachable();
94     Resume->eraseFromParent();
95   }
96
97   return true;
98 }
99
100 bool WinEHPrepare::doFinalization(Module &M) {
101   return DwarfPrepare->doFinalization(M);
102 }
103
104 void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
105   DwarfPrepare->getAnalysisUsage(AU);
106 }