summaryrefslogtreecommitdiffstats
path: root/llvm/lib
diff options
context:
space:
mode:
authorReid Kleckner <reid@kleckner.net>2015-01-29 00:41:44 +0000
committerReid Kleckner <reid@kleckner.net>2015-01-29 00:41:44 +0000
commit1185fced3de79e47c14183f8b00dd8e620559da5 (patch)
tree81a9285231fb68b2bf7a5ca4f4b4c6804f650841 /llvm/lib
parentef61def9d57c10ad5efb38ce6e6bc5b9d3fcba72 (diff)
downloadbcm5719-llvm-1185fced3de79e47c14183f8b00dd8e620559da5.tar.gz
bcm5719-llvm-1185fced3de79e47c14183f8b00dd8e620559da5.zip
Add a Windows EH preparation pass that zaps resumes
If the personality is not a recognized MSVC personality function, this pass delegates to the dwarf EH preparation pass. This chaining supports people on *-windows-itanium or *-windows-gnu targets. Currently this recognizes some personalities used by MSVC and turns resume instructions into traps to avoid link errors. Even if cleanups are not used in the source program, LLVM requires the frontend to emit a code path that resumes unwinding after an exception. Clang does this, and we get unreachable resume instructions. PR20300 covers cleaning up these unreachable calls to resume. Reviewers: majnemer Differential Revision: http://reviews.llvm.org/D7216 llvm-svn: 227405
Diffstat (limited to 'llvm/lib')
-rw-r--r--llvm/lib/CodeGen/CMakeLists.txt1
-rw-r--r--llvm/lib/CodeGen/Passes.cpp4
-rw-r--r--llvm/lib/CodeGen/WinEHPrepare.cpp106
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);
+}
OpenPOWER on IntegriCloud