[llvm] r227405 - Add a Windows EH preparation pass that zaps resumes
Alexey Samsonov
vonosmas at gmail.com
Thu Jan 29 13:40:42 PST 2015
This change breaks ASan bootstrap of LLVM:
http://lab.llvm.org:8011/builders/sanitizer-x86_64-linux-fast/builds/1113/steps/check-llvm%20asan/logs/stdio
On Wed, Jan 28, 2015 at 4:41 PM, Reid Kleckner <reid at kleckner.net> wrote:
> Author: rnk
> Date: Wed Jan 28 18:41:44 2015
> New Revision: 227405
>
> URL: http://llvm.org/viewvc/llvm-project?rev=227405&view=rev
> Log:
> 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
>
> Added:
> llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
> llvm/trunk/test/CodeGen/X86/win_eh_prepare.ll
> Modified:
> llvm/trunk/include/llvm/CodeGen/Passes.h
> llvm/trunk/include/llvm/InitializePasses.h
> llvm/trunk/lib/CodeGen/CMakeLists.txt
> llvm/trunk/lib/CodeGen/Passes.cpp
> llvm/trunk/test/CodeGen/X86/seh-safe-div.ll
> llvm/trunk/tools/opt/opt.cpp
>
> Modified: llvm/trunk/include/llvm/CodeGen/Passes.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/CodeGen/Passes.h?rev=227405&r1=227404&r2=227405&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/CodeGen/Passes.h (original)
> +++ llvm/trunk/include/llvm/CodeGen/Passes.h Wed Jan 28 18:41:44 2015
> @@ -573,6 +573,10 @@ namespace llvm {
> /// adapted to code generation. Required if using dwarf exception
> handling.
> FunctionPass *createDwarfEHPass(const TargetMachine *TM);
>
> + /// createWinEHPass - Prepares personality functions used by MSVC on
> Windows,
> + /// in addition to the Itanium LSDA based personalities.
> + FunctionPass *createWinEHPass(const TargetMachine *TM);
> +
> /// createSjLjEHPreparePass - This pass adapts exception handling code
> to use
> /// the GCC-style builtin setjmp/longjmp (sjlj) to handling EH control
> flow.
> ///
>
> Modified: llvm/trunk/include/llvm/InitializePasses.h
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/InitializePasses.h?rev=227405&r1=227404&r2=227405&view=diff
>
> ==============================================================================
> --- llvm/trunk/include/llvm/InitializePasses.h (original)
> +++ llvm/trunk/include/llvm/InitializePasses.h Wed Jan 28 18:41:44 2015
> @@ -289,6 +289,7 @@ void initializeStackMapLivenessPass(Pass
> void initializeMachineCombinerPass(PassRegistry &);
> void initializeLoadCombinePass(PassRegistry&);
> void initializeRewriteSymbolsPass(PassRegistry&);
> +void initializeWinEHPreparePass(PassRegistry&);
> }
>
> #endif
>
> Modified: llvm/trunk/lib/CodeGen/CMakeLists.txt
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/CMakeLists.txt?rev=227405&r1=227404&r2=227405&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/CMakeLists.txt (original)
> +++ llvm/trunk/lib/CodeGen/CMakeLists.txt Wed Jan 28 18:41:44 2015
> @@ -118,6 +118,7 @@ add_llvm_library(LLVMCodeGen
> TwoAddressInstructionPass.cpp
> UnreachableBlockElim.cpp
> VirtRegMap.cpp
> + WinEHPrepare.cpp
> )
>
> add_dependencies(LLVMCodeGen intrinsics_gen)
>
> Modified: llvm/trunk/lib/CodeGen/Passes.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/Passes.cpp?rev=227405&r1=227404&r2=227405&view=diff
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/Passes.cpp (original)
> +++ llvm/trunk/lib/CodeGen/Passes.cpp Wed Jan 28 18:41:44 2015
> @@ -450,9 +450,11 @@ void TargetPassConfig::addPassesToHandle
> // 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());
>
>
> Added: llvm/trunk/lib/CodeGen/WinEHPrepare.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/WinEHPrepare.cpp?rev=227405&view=auto
>
> ==============================================================================
> --- llvm/trunk/lib/CodeGen/WinEHPrepare.cpp (added)
> +++ llvm/trunk/lib/CodeGen/WinEHPrepare.cpp Wed Jan 28 18:41:44 2015
> @@ -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;
>
^^
Shouldn't this be a std::unique_ptr?
> +
> +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);
> +}
>
> Modified: llvm/trunk/test/CodeGen/X86/seh-safe-div.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/seh-safe-div.ll?rev=227405&r1=227404&r2=227405&view=diff
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/seh-safe-div.ll (original)
> +++ llvm/trunk/test/CodeGen/X86/seh-safe-div.ll Wed Jan 28 18:41:44 2015
> @@ -96,8 +96,9 @@ __try.cont:
> ; CHECK: movl $-2, [[rloc]]
> ; CHECK: jmp .LBB0_7
>
> -; FIXME: EH preparation should not call _Unwind_Resume.
> -; CHECK: callq _Unwind_Resume
> +; FIXME: EH preparation should eliminate the 'resume' instr and we should
> not do
> +; the previous 'cmp;jeq'.
> +; CHECK-NOT: _Unwind_Resume
> ; CHECK: ud2
>
> ; CHECK: .seh_handlerdata
>
> Added: llvm/trunk/test/CodeGen/X86/win_eh_prepare.ll
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/test/CodeGen/X86/win_eh_prepare.ll?rev=227405&view=auto
>
> ==============================================================================
> --- llvm/trunk/test/CodeGen/X86/win_eh_prepare.ll (added)
> +++ llvm/trunk/test/CodeGen/X86/win_eh_prepare.ll Wed Jan 28 18:41:44 2015
> @@ -0,0 +1,80 @@
> +; RUN: opt -S -winehprepare -mtriple x86_64-pc-windows-msvc < %s |
> FileCheck %s
> +
> +; FIXME: Add and test outlining here.
> +
> +declare void @maybe_throw()
> +
> + at _ZTIi = external constant i8*
> + at g = external global i32
> +
> +declare i32 @__C_specific_handler(...)
> +declare i32 @__gxx_personality_seh0(...)
> +declare i32 @llvm.eh.typeid.for(i8*) readnone nounwind
> +
> +define i32 @use_seh() {
> +entry:
> + invoke void @maybe_throw()
> + to label %cont unwind label %lpad
> +
> +cont:
> + ret i32 0
> +
> +lpad:
> + %ehvals = landingpad { i8*, i32 } personality i32 (...)*
> @__C_specific_handler
> + cleanup
> + catch i8* bitcast (i32 (i8*, i8*)* @filt_g to i8*)
> + %ehsel = extractvalue { i8*, i32 } %ehvals, 1
> + %filt_g_sel = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)*
> @filt_g to i8*))
> + %matches = icmp eq i32 %ehsel, %filt_g_sel
> + br i1 %matches, label %ret1, label %eh.resume
> +
> +ret1:
> + ret i32 1
> +
> +eh.resume:
> + resume { i8*, i32 } %ehvals
> +}
> +
> +define internal i32 @filt_g(i8*, i8*) {
> + %g = load i32* @g
> + ret i32 %g
> +}
> +
> +; CHECK-LABEL: define i32 @use_seh()
> +; CHECK: invoke void @maybe_throw()
> +; CHECK-NEXT: to label %cont unwind label %lpad
> +; CHECK: eh.resume:
> +; CHECK-NEXT: unreachable
> +
> +
> +; A MinGW64-ish EH style. It could happen if a binary uses both MSVC CRT
> and
> +; mingw CRT and is linked with LTO.
> +define i32 @use_gcc() {
> +entry:
> + invoke void @maybe_throw()
> + to label %cont unwind label %lpad
> +
> +cont:
> + ret i32 0
> +
> +lpad:
> + %ehvals = landingpad { i8*, i32 } personality i32 (...)*
> @__gxx_personality_seh0
> + cleanup
> + catch i8* bitcast (i8** @_ZTIi to i8*)
> + %ehsel = extractvalue { i8*, i32 } %ehvals, 1
> + %filt_g_sel = call i32 @llvm.eh.typeid.for(i8* bitcast (i32 (i8*, i8*)*
> @filt_g to i8*))
> + %matches = icmp eq i32 %ehsel, %filt_g_sel
> + br i1 %matches, label %ret1, label %eh.resume
> +
> +ret1:
> + ret i32 1
> +
> +eh.resume:
> + resume { i8*, i32 } %ehvals
> +}
> +
> +; CHECK-LABEL: define i32 @use_gcc()
> +; CHECK: invoke void @maybe_throw()
> +; CHECK-NEXT: to label %cont unwind label %lpad
> +; CHECK: eh.resume:
> +; CHECK: call void @_Unwind_Resume(i8* %exn.obj)
>
> Modified: llvm/trunk/tools/opt/opt.cpp
> URL:
> http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/opt/opt.cpp?rev=227405&r1=227404&r2=227405&view=diff
>
> ==============================================================================
> --- llvm/trunk/tools/opt/opt.cpp (original)
> +++ llvm/trunk/tools/opt/opt.cpp Wed Jan 28 18:41:44 2015
> @@ -322,6 +322,7 @@ int main(int argc, char **argv) {
> initializeCodeGenPreparePass(Registry);
> initializeAtomicExpandPass(Registry);
> initializeRewriteSymbolsPass(Registry);
> + initializeWinEHPreparePass(Registry);
>
> #ifdef LINK_POLLY_INTO_TOOLS
> polly::initializePollyPasses(Registry);
>
>
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
>
--
Alexey Samsonov
vonosmas at gmail.com
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20150129/7d7c9264/attachment.html>
More information about the llvm-commits
mailing list