blob: c608bb0a31e9f235b918cf67acf16af88eba5e73 [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"
Benjamin Kramereb63e4d2015-01-29 13:26:50 +000020#include "llvm/IR/IRBuilder.h"
Reid Kleckner1185fce2015-01-29 00:41:44 +000021#include "llvm/IR/Instructions.h"
Reid Kleckner1185fce2015-01-29 00:41:44 +000022#include "llvm/Pass.h"
Alexey Samsonov964f4db2015-01-30 22:07:05 +000023#include <memory>
24
Reid Kleckner1185fce2015-01-29 00:41:44 +000025using namespace llvm;
26
27#define DEBUG_TYPE "winehprepare"
28
29namespace {
30class WinEHPrepare : public FunctionPass {
Alexey Samsonov964f4db2015-01-30 22:07:05 +000031 std::unique_ptr<FunctionPass> DwarfPrepare;
Reid Kleckner1185fce2015-01-29 00:41:44 +000032
33public:
34 static char ID; // Pass identification, replacement for typeid.
35 WinEHPrepare(const TargetMachine *TM = nullptr)
Benjamin Kramereb63e4d2015-01-29 13:26:50 +000036 : FunctionPass(ID), DwarfPrepare(createDwarfEHPass(TM)) {}
Reid Kleckner1185fce2015-01-29 00:41:44 +000037
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
50char WinEHPrepare::ID = 0;
51INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare",
52 "Prepare Windows exceptions", false, false)
53
54FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) {
55 return new WinEHPrepare(TM);
56}
57
58static bool isMSVCPersonality(EHPersonality Pers) {
59 return Pers == EHPersonality::MSVC_Win64SEH ||
60 Pers == EHPersonality::MSVC_CXX;
61}
62
63bool 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
Reid Kleckner2a223502015-01-29 22:32:26 +000084 // FIXME: Cleanups are unimplemented. Replace them with unreachable.
Reid Kleckner1185fce2015-01-29 00:41:44 +000085 if (Resumes.empty())
86 return false;
87
Reid Kleckner1185fce2015-01-29 00:41:44 +000088 for (ResumeInst *Resume : Resumes) {
89 IRBuilder<>(Resume).CreateUnreachable();
90 Resume->eraseFromParent();
91 }
92
93 return true;
94}
95
96bool WinEHPrepare::doFinalization(Module &M) {
97 return DwarfPrepare->doFinalization(M);
98}
99
100void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {
101 DwarfPrepare->getAnalysisUsage(AU);
102}