diff --git a/include/llvm/Analysis/LibCallSemantics.h b/include/llvm/Analysis/LibCallSemantics.h index e6427a4b2ec..34831b2849d 100644 --- a/include/llvm/Analysis/LibCallSemantics.h +++ b/include/llvm/Analysis/LibCallSemantics.h @@ -181,7 +181,31 @@ class InvokeInst; /// \brief Returns true if this personality function catches asynchronous /// exceptions. - bool isAsynchronousEHPersonality(EHPersonality Pers); + inline bool isAsynchronousEHPersonality(EHPersonality Pers) { + // The two SEH personality functions can catch asynch exceptions. We assume + // unknown personalities don't catch asynch exceptions. + switch (Pers) { + case EHPersonality::MSVC_X86SEH: + case EHPersonality::MSVC_Win64SEH: + return true; + default: return false; + } + llvm_unreachable("invalid enum"); + } + + /// \brief Returns true if this is an MSVC personality function. + inline bool isMSVCEHPersonality(EHPersonality Pers) { + // The two SEH personality functions can catch asynch exceptions. We assume + // unknown personalities don't catch asynch exceptions. + switch (Pers) { + case EHPersonality::MSVC_CXX: + case EHPersonality::MSVC_X86SEH: + case EHPersonality::MSVC_Win64SEH: + return true; + default: return false; + } + llvm_unreachable("invalid enum"); + } bool canSimplifyInvokeNoUnwind(const InvokeInst *II); diff --git a/lib/Analysis/LibCallSemantics.cpp b/lib/Analysis/LibCallSemantics.cpp index cf752dd8e0e..328b186b527 100644 --- a/lib/Analysis/LibCallSemantics.cpp +++ b/lib/Analysis/LibCallSemantics.cpp @@ -80,18 +80,6 @@ EHPersonality llvm::classifyEHPersonality(const Value *Pers) { .Default(EHPersonality::Unknown); } -bool llvm::isAsynchronousEHPersonality(EHPersonality Pers) { - // The two SEH personality functions can catch asynch exceptions. We assume - // unknown personalities don't catch asynch exceptions. - switch (Pers) { - case EHPersonality::MSVC_X86SEH: - case EHPersonality::MSVC_Win64SEH: - return true; - default: return false; - } - llvm_unreachable("invalid enum"); -} - bool llvm::canSimplifyInvokeNoUnwind(const InvokeInst *II) { const LandingPadInst *LP = II->getLandingPadInst(); EHPersonality Personality = classifyEHPersonality(LP->getPersonalityFn()); diff --git a/lib/CodeGen/DwarfEHPrepare.cpp b/lib/CodeGen/DwarfEHPrepare.cpp index f58fb59d060..42656fb08db 100644 --- a/lib/CodeGen/DwarfEHPrepare.cpp +++ b/lib/CodeGen/DwarfEHPrepare.cpp @@ -16,6 +16,7 @@ #include "llvm/ADT/BitVector.h" #include "llvm/ADT/Statistic.h" #include "llvm/Analysis/CFG.h" +#include "llvm/Analysis/LibCallSemantics.h" #include "llvm/Analysis/TargetTransformInfo.h" #include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" @@ -180,12 +181,22 @@ size_t DwarfEHPrepare::pruneUnreachableResumes( bool DwarfEHPrepare::InsertUnwindResumeCalls(Function &Fn) { SmallVector Resumes; SmallVector CleanupLPads; + bool FoundLP = false; for (BasicBlock &BB : Fn) { if (auto *RI = dyn_cast(BB.getTerminator())) Resumes.push_back(RI); - if (auto *LP = BB.getLandingPadInst()) + if (auto *LP = BB.getLandingPadInst()) { if (LP->isCleanup()) CleanupLPads.push_back(LP); + // Check the personality on the first landingpad. Don't do anything if + // it's for MSVC. + if (!FoundLP) { + FoundLP = true; + EHPersonality Pers = classifyEHPersonality(LP->getPersonalityFn()); + if (isMSVCEHPersonality(Pers)) + return false; + } + } } if (Resumes.empty()) diff --git a/lib/CodeGen/Passes.cpp b/lib/CodeGen/Passes.cpp index d692862adf4..4fbc4c97307 100644 --- a/lib/CodeGen/Passes.cpp +++ b/lib/CodeGen/Passes.cpp @@ -422,7 +422,11 @@ void TargetPassConfig::addPassesToHandleExceptions() { addPass(createDwarfEHPass(TM)); break; case ExceptionHandling::WinEH: + // We support using both GCC-style and MSVC-style exceptions on Windows, so + // add both preparation passes. Each pass will only actually run if it + // recognizes the personality function. addPass(createWinEHPass(TM)); + addPass(createDwarfEHPass(TM)); break; case ExceptionHandling::None: addPass(createLowerInvokePass()); diff --git a/lib/CodeGen/WinEHPrepare.cpp b/lib/CodeGen/WinEHPrepare.cpp index 05de6bf39fa..bc3cc6b9b85 100644 --- a/lib/CodeGen/WinEHPrepare.cpp +++ b/lib/CodeGen/WinEHPrepare.cpp @@ -20,8 +20,6 @@ #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/TinyPtrVector.h" #include "llvm/Analysis/LibCallSemantics.h" -#include "llvm/Analysis/TargetTransformInfo.h" -#include "llvm/IR/Dominators.h" #include "llvm/IR/Function.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Instructions.h" @@ -63,12 +61,10 @@ typedef DenseMap CatchHandlerMapTy; typedef DenseMap CleanupHandlerMapTy; class WinEHPrepare : public FunctionPass { - std::unique_ptr DwarfPrepare; - public: static char ID; // Pass identification, replacement for typeid. WinEHPrepare(const TargetMachine *TM = nullptr) - : FunctionPass(ID), DwarfPrepare(createDwarfEHPass(TM)) {} + : FunctionPass(ID) {} bool runOnFunction(Function &Fn) override; @@ -323,23 +319,13 @@ private: } // end anonymous namespace char WinEHPrepare::ID = 0; -INITIALIZE_TM_PASS_BEGIN(WinEHPrepare, "winehprepare", - "Prepare Windows exceptions", false, false) -INITIALIZE_PASS_DEPENDENCY(DwarfEHPrepare) -INITIALIZE_PASS_DEPENDENCY(DominatorTreeWrapperPass) -INITIALIZE_PASS_DEPENDENCY(TargetTransformInfoWrapperPass) -INITIALIZE_TM_PASS_END(WinEHPrepare, "winehprepare", - "Prepare Windows exceptions", false, false) +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 LPads; SmallVector Resumes; @@ -357,24 +343,9 @@ bool WinEHPrepare::runOnFunction(Function &Fn) { // 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)) { - if (!DwarfPrepare->getResolver()) { - // Build an AnalysisResolver with the analyses needed by DwarfEHPrepare. - // It will take ownership of the AnalysisResolver. - assert(getResolver()); - auto *AR = new AnalysisResolver(getResolver()->getPMDataManager()); - AR->addAnalysisImplsPair( - &TargetTransformInfoWrapperPass::ID, - getResolver()->findImplPass(&TargetTransformInfoWrapperPass::ID)); - AR->addAnalysisImplsPair( - &DominatorTreeWrapperPass::ID, - getResolver()->findImplPass(&DominatorTreeWrapperPass::ID)); - DwarfPrepare->setResolver(AR); - } - - return DwarfPrepare->runOnFunction(Fn); - } + // Do nothing if this is not an MSVC personality. + if (!isMSVCEHPersonality(Pers)) + return false; // FIXME: This only returns true if the C++ EH handlers were outlined. // When that code is complete, it should always return whatever @@ -395,12 +366,10 @@ bool WinEHPrepare::runOnFunction(Function &Fn) { } bool WinEHPrepare::doFinalization(Module &M) { - return DwarfPrepare->doFinalization(M); + return false; } -void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const { - DwarfPrepare->getAnalysisUsage(AU); -} +void WinEHPrepare::getAnalysisUsage(AnalysisUsage &AU) const {} bool WinEHPrepare::prepareCPPEHHandlers( Function &F, SmallVectorImpl &LPads) { diff --git a/test/CodeGen/X86/win_eh_prepare.ll b/test/CodeGen/X86/win_eh_prepare.ll index b457a41e452..e5a7d055a78 100644 --- a/test/CodeGen/X86/win_eh_prepare.ll +++ b/test/CodeGen/X86/win_eh_prepare.ll @@ -1,4 +1,4 @@ -; RUN: opt -S -winehprepare -mtriple x86_64-pc-windows-msvc < %s | FileCheck %s +; RUN: opt -S -winehprepare -dwarfehprepare -mtriple x86_64-pc-windows-msvc < %s | FileCheck %s ; FIXME: Add and test outlining here.