blob: a01adcd43d05ab34e7c28ee038683783547d4c63 [file] [log] [blame]
Reid Kleckner1185fce2015-01-29 00:41:44 +00001//===-- 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"
24using namespace llvm;
25
26#define DEBUG_TYPE "winehprepare"
27
28namespace {
29class WinEHPrepare : public FunctionPass {
30 const TargetMachine *TM;
31 FunctionPass *DwarfPrepare;
32
33public:
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
52char WinEHPrepare::ID = 0;
53INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare",
54 "Prepare Windows exceptions", false, false)
55
56FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
57 return new WinEHPrepare(TM);
58}
59
60static bool isMSVCPersonality(EHPersonality Pers) {
61 return Pers == EHPersonality::MSVC_Win64SEH ||
62 Pers == EHPersonality::MSVC_CXX;
63}
64
65bool 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
100bool WinEHPrepare::doFinalization(Module &M) {
101 return DwarfPrepare->doFinalization(M);
102}
103
104void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
105 DwarfPrepare->getAnalysisUsage(AU);
106}