From 7dedaabcaecc7d413804591bd7f0dcff1669da33 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Thu, 12 Mar 2015 00:36:20 +0000 Subject: [PATCH] Stop calling DwarfEHPrepare from WinEHPrepare Instead, run both EH preparation passes, and have them both ignore functions with unrecognized EH personalities. Pass delegation involved some hacky code for creating an AnalysisResolver that we don't need now. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@231995 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/llvm/Analysis/LibCallSemantics.h | 26 ++++++++++++- lib/Analysis/LibCallSemantics.cpp | 12 ------ lib/CodeGen/DwarfEHPrepare.cpp | 13 ++++++- lib/CodeGen/Passes.cpp | 4 ++ lib/CodeGen/WinEHPrepare.cpp | 47 ++++-------------------- test/CodeGen/X86/win_eh_prepare.ll | 2 +- 6 files changed, 50 insertions(+), 54 deletions(-) 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.