diff options
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r-- | llvm/lib/CodeGen/CMakeLists.txt | 1 | ||||
-rw-r--r-- | llvm/lib/CodeGen/Passes.cpp | 4 | ||||
-rw-r--r-- | llvm/lib/CodeGen/WinEHPrepare.cpp | 106 |
3 files changed, 110 insertions, 1 deletions
diff --git a/llvm/lib/CodeGen/CMakeLists.txt b/llvm/lib/CodeGen/CMakeLists.txt index 8df2042d68b..417da69f543 100644 --- a/llvm/lib/CodeGen/CMakeLists.txt +++ b/llvm/lib/CodeGen/CMakeLists.txt @@ -118,6 +118,7 @@ add_llvm_library(LLVMCodeGen TwoAddressInstructionPass.cpp UnreachableBlockElim.cpp VirtRegMap.cpp + WinEHPrepare.cpp ) add_dependencies(LLVMCodeGen intrinsics_gen) diff --git a/llvm/lib/CodeGen/Passes.cpp b/llvm/lib/CodeGen/Passes.cpp index c66d2131f8f..b9dd0f78c81 100644 --- a/llvm/lib/CodeGen/Passes.cpp +++ b/llvm/lib/CodeGen/Passes.cpp @@ -450,9 +450,11 @@ void TargetPassConfig::addPassesToHandleExceptions() { // FALLTHROUGH case ExceptionHandling::DwarfCFI: case ExceptionHandling::ARM: - case ExceptionHandling::WinEH: addPass(createDwarfEHPass(TM)); break; + case ExceptionHandling::WinEH: + addPass(createWinEHPass(TM)); + break; case ExceptionHandling::None: addPass(createLowerInvokePass()); diff --git a/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp new file mode 100644 index 00000000000..a01adcd43d0 --- /dev/null +++ b/llvm/lib/CodeGen/WinEHPrepare.cpp @@ -0,0 +1,106 @@ +//===-- WinEHPrepare - Prepare exception handling for code generation ---===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// +// +// This pass lowers LLVM IR exception handling into something closer to what the +// backend wants. It snifs the personality function to see which kind of +// preparation is necessary. If the personality function uses the Itanium LSDA, +// this pass delegates to the DWARF EH preparation pass. +// +//===----------------------------------------------------------------------===// + +#include "llvm/CodeGen/Passes.h" +#include "llvm/Analysis/LibCallSemantics.h" +#include "llvm/IR/Function.h" +#include "llvm/IR/Instructions.h" +#include "llvm/IR/Intrinsics.h" +#include "llvm/Pass.h" +#include "llvm/Target/TargetLowering.h" +using namespace llvm; + +#define DEBUG_TYPE "winehprepare" + +namespace { +class WinEHPrepare : public FunctionPass { + const TargetMachine *TM; + FunctionPass *DwarfPrepare; + +public: + static char ID; // Pass identification, replacement for typeid. + WinEHPrepare(const TargetMachine *TM = nullptr) + : FunctionPass(ID), TM(TM), DwarfPrepare(createDwarfEHPass(TM)) { + initializeDominatorTreeWrapperPassPass(*PassRegistry::getPassRegistry()); + } + + bool runOnFunction(Function &Fn) override; + + bool doFinalization(Module &M) override; + + void getAnalysisUsage(AnalysisUsage &AU) const override; + + const char *getPassName() const override { + return "Windows exception handling preparation"; + } +}; +} // end anonymous namespace + +char WinEHPrepare::ID = 0; +INITIALIZE_TM_PASS(WinEHPrepare, "winehprepare", + "Prepare Windows exceptions", false, false) + +FunctionPass *llvm::createWinEHPass(const TargetMachine *TM) { + return new WinEHPrepare(TM); +} + +static bool isMSVCPersonality(EHPersonality Pers) { + return Pers == EHPersonality::MSVC_Win64SEH || + Pers == EHPersonality::MSVC_CXX; +} + +bool WinEHPrepare::runOnFunction(Function &Fn) { + SmallVector<LandingPadInst *, 4> LPads; + SmallVector<ResumeInst *, 4> Resumes; + for (BasicBlock &BB : Fn) { + if (auto *LP = BB.getLandingPadInst()) + LPads.push_back(LP); + if (auto *Resume = dyn_cast<ResumeInst>(BB.getTerminator())) + Resumes.push_back(Resume); + } + + // No need to prepare functions that lack landing pads. + if (LPads.empty()) + return false; + + // Classify the personality to see what kind of preparation we need. + EHPersonality Pers = ClassifyEHPersonality(LPads.back()->getPersonalityFn()); + + // Delegate through to the DWARF pass if this is unrecognized. + if (!isMSVCPersonality(Pers)) + return DwarfPrepare->runOnFunction(Fn); + + // FIXME: Cleanups are unimplemented. Replace them with calls to @llvm.trap. + if (Resumes.empty()) + return false; + + Function *Trap = + Intrinsic::getDeclaration(Fn.getParent(), Intrinsic::trap, None); + for (ResumeInst *Resume : Resumes) { + IRBuilder<>(Resume).CreateUnreachable(); + Resume->eraseFromParent(); + } + + return true; +} + +bool WinEHPrepare::doFinalization(Module &M) { + return DwarfPrepare->doFinalization(M); +} + +void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const { + DwarfPrepare->getAnalysisUsage(AU); +} |