summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--llvm/include/llvm/Analysis/LibCallSemantics.h26
-rw-r--r--llvm/lib/Analysis/LibCallSemantics.cpp12
-rw-r--r--llvm/lib/CodeGen/DwarfEHPrepare.cpp13
-rw-r--r--llvm/lib/CodeGen/Passes.cpp4
-rw-r--r--llvm/lib/CodeGen/WinEHPrepare.cpp47
-rw-r--r--llvm/test/CodeGen/X86/win_eh_prepare.ll2
6 files changed, 50 insertions, 54 deletions
diff --git a/llvm/include/llvm/Analysis/LibCallSemantics.h b/llvm/include/llvm/Analysis/LibCallSemantics.h
index e6427a4b2ec..34831b2849d 100644
--- a/llvm/include/llvm/Analysis/LibCallSemantics.h
+++ b/llvm/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/llvm/lib/Analysis/LibCallSemantics.cpp b/llvm/lib/Analysis/LibCallSemantics.cpp
index cf752dd8e0e..328b186b527 100644
--- a/llvm/lib/Analysis/LibCallSemantics.cpp
+++ b/llvm/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/llvm/lib/CodeGen/DwarfEHPrepare.cpp b/llvm/lib/CodeGen/DwarfEHPrepare.cpp
index f58fb59d060..42656fb08db 100644
--- a/llvm/lib/CodeGen/DwarfEHPrepare.cpp
+++ b/llvm/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<ResumeInst*, 16> Resumes;
SmallVector<LandingPadInst*, 16> CleanupLPads;
+ bool FoundLP = false;
for (BasicBlock &BB : Fn) {
if (auto *RI = dyn_cast<ResumeInst>(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/llvm/lib/CodeGen/Passes.cpp b/llvm/lib/CodeGen/Passes.cpp
index d692862adf4..4fbc4c97307 100644
--- a/llvm/lib/CodeGen/Passes.cpp
+++ b/llvm/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/llvm/lib/CodeGen/WinEHPrepare.cpp b/llvm/lib/CodeGen/WinEHPrepare.cpp
index 05de6bf39fa..bc3cc6b9b85 100644
--- a/llvm/lib/CodeGen/WinEHPrepare.cpp
+++ b/llvm/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<const BasicBlock *, CatchHandler *> CatchHandlerMapTy;
typedef DenseMap<const BasicBlock *, CleanupHandler *> CleanupHandlerMapTy;
class WinEHPrepare : public FunctionPass {
- std::unique_ptr<FunctionPass> 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<LandingPadInst *, 4> LPads;
SmallVector<ResumeInst *, 4> 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<LandingPadInst *> &LPads) {
diff --git a/llvm/test/CodeGen/X86/win_eh_prepare.ll b/llvm/test/CodeGen/X86/win_eh_prepare.ll
index b457a41e452..e5a7d055a78 100644
--- a/llvm/test/CodeGen/X86/win_eh_prepare.ll
+++ b/llvm/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.
OpenPOWER on IntegriCloud