83
|
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 }
|