From 8f45c9cc6232e5b841bc92b7f2ea9a792574c317 Mon Sep 17 00:00:00 2001 From: Reid Kleckner Date: Mon, 15 Sep 2014 17:19:16 +0000 Subject: [PATCH] Add -fseh-exceptions for MinGW-w64 This adds a flag called -fseh-exceptions that uses the native Windows .pdata and .xdata unwind mechanism to throw exceptions. The other EH possibilities are DWARF and SJLJ exceptions. Patch by Martell Malone! Reviewed By: asl, rnk Differential Revision: http://reviews.llvm.org/D3419 llvm-svn: 217790 --- clang/include/clang/Basic/LangOptions.def | 1 + clang/include/clang/Driver/CC1Options.td | 2 ++ clang/include/clang/Driver/ToolChain.h | 3 +++ clang/lib/CodeGen/CGException.cpp | 10 ++++++++++ clang/lib/Driver/Tools.cpp | 2 ++ clang/lib/Frontend/CompilerInvocation.cpp | 1 + clang/lib/Frontend/InitPreprocessor.cpp | 2 ++ .../CodeGenCXX/mingw-w64-seh-exceptions.cpp | 19 +++++++++++++++++++ 8 files changed, 40 insertions(+) create mode 100644 clang/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def index b84b9ac49b2f..ec451e16e1e4 100644 --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -82,6 +82,7 @@ LANGOPT(Exceptions , 1, 0, "exception handling") LANGOPT(ObjCExceptions , 1, 0, "Objective-C exceptions") LANGOPT(CXXExceptions , 1, 0, "C++ exceptions") LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling") +LANGOPT(SEHExceptions , 1, 0, "SEH exception handling") LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation") LANGOPT(RTTI , 1, 1, "run-time type information") LANGOPT(RTTIData , 1, 1, "emit run-time type information data") diff --git a/clang/include/clang/Driver/CC1Options.td b/clang/include/clang/Driver/CC1Options.td index a1842d0efce0..8d477cc9d931 100644 --- a/clang/include/clang/Driver/CC1Options.td +++ b/clang/include/clang/Driver/CC1Options.td @@ -435,6 +435,8 @@ def fblocks_runtime_optional : Flag<["-"], "fblocks-runtime-optional">, HelpText<"Weakly link in the blocks runtime">; def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">, HelpText<"Use SjLj style exceptions">; +def fseh_exceptions : Flag<["-"], "fseh-exceptions">, + HelpText<"Use SEH style exceptions">; def split_dwarf_file : Separate<["-"], "split-dwarf-file">, HelpText<"File name to use for split dwarf debug info output">; def fno_wchar : Flag<["-"], "fno-wchar">, diff --git a/clang/include/clang/Driver/ToolChain.h b/clang/include/clang/Driver/ToolChain.h index ea3863fee04a..e9fbe6cd77f4 100644 --- a/clang/include/clang/Driver/ToolChain.h +++ b/clang/include/clang/Driver/ToolChain.h @@ -248,6 +248,9 @@ public: /// UseSjLjExceptions - Does this tool chain use SjLj exceptions. virtual bool UseSjLjExceptions() const { return false; } + /// UseSEHExceptions - Does this tool chain use SEH exceptions. + virtual bool UseSEHExceptions() const { return false; } + /// ComputeLLVMTriple - Return the LLVM target triple to use, after taking /// command line arguments into account. virtual std::string diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp index 05eb6ebca30b..0b7e57a3c5f5 100644 --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -137,12 +137,14 @@ namespace { static const EHPersonality &get(const LangOptions &Lang); static const EHPersonality GNU_C; static const EHPersonality GNU_C_SJLJ; + static const EHPersonality GNU_C_SEH; static const EHPersonality GNU_ObjC; static const EHPersonality GNUstep_ObjC; static const EHPersonality GNU_ObjCXX; static const EHPersonality NeXT_ObjC; static const EHPersonality GNU_CPlusPlus; static const EHPersonality GNU_CPlusPlus_SJLJ; + static const EHPersonality GNU_CPlusPlus_SEH; }; } @@ -150,12 +152,16 @@ const EHPersonality EHPersonality::GNU_C = { "__gcc_personality_v0", nullptr }; const EHPersonality EHPersonality::GNU_C_SJLJ = { "__gcc_personality_sj0", nullptr }; const EHPersonality +EHPersonality::GNU_C_SEH = { "__gcc_personality_seh0", nullptr }; +const EHPersonality EHPersonality::NeXT_ObjC = { "__objc_personality_v0", nullptr }; const EHPersonality EHPersonality::GNU_CPlusPlus = { "__gxx_personality_v0", nullptr }; const EHPersonality EHPersonality::GNU_CPlusPlus_SJLJ = { "__gxx_personality_sj0", nullptr }; const EHPersonality +EHPersonality::GNU_CPlusPlus_SEH = { "__gxx_personality_seh0", nullptr }; +const EHPersonality EHPersonality::GNU_ObjC = {"__gnu_objc_personality_v0", "objc_exception_throw"}; const EHPersonality EHPersonality::GNU_ObjCXX = { "__gnustep_objcxx_personality_v0", nullptr }; @@ -165,6 +171,8 @@ EHPersonality::GNUstep_ObjC = { "__gnustep_objc_personality_v0", nullptr }; static const EHPersonality &getCPersonality(const LangOptions &L) { if (L.SjLjExceptions) return EHPersonality::GNU_C_SJLJ; + if (L.SEHExceptions) + return EHPersonality::GNU_C_SEH; return EHPersonality::GNU_C; } @@ -189,6 +197,8 @@ static const EHPersonality &getObjCPersonality(const LangOptions &L) { static const EHPersonality &getCXXPersonality(const LangOptions &L) { if (L.SjLjExceptions) return EHPersonality::GNU_CPlusPlus_SJLJ; + else if (L.SEHExceptions) + return EHPersonality::GNU_CPlusPlus_SEH; else return EHPersonality::GNU_CPlusPlus; } diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 0e1dea2a97f6..6be498eef572 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -4112,6 +4112,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, if (getToolChain().UseSjLjExceptions()) CmdArgs.push_back("-fsjlj-exceptions"); + else if (getToolChain().UseSEHExceptions()) + CmdArgs.push_back("-fseh-exceptions"); // C++ "sane" operator new. if (!Args.hasFlag(options::OPT_fassume_sane_operator_new, diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index a8bb13181dcb..0dde41acf2e5 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -1431,6 +1431,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK, Opts.ObjCExceptions = Args.hasArg(OPT_fobjc_exceptions); Opts.CXXExceptions = Args.hasArg(OPT_fcxx_exceptions); Opts.SjLjExceptions = Args.hasArg(OPT_fsjlj_exceptions); + Opts.SEHExceptions = Args.hasArg(OPT_fseh_exceptions); Opts.TraditionalCPP = Args.hasArg(OPT_traditional_cpp); Opts.RTTI = !Args.hasArg(OPT_fno_rtti); diff --git a/clang/lib/Frontend/InitPreprocessor.cpp b/clang/lib/Frontend/InitPreprocessor.cpp index d691d19730b6..daff9ce9114c 100644 --- a/clang/lib/Frontend/InitPreprocessor.cpp +++ b/clang/lib/Frontend/InitPreprocessor.cpp @@ -556,6 +556,8 @@ static void InitializePredefinedMacros(const TargetInfo &TI, Builder.defineMacro("__GXX_RTTI"); if (LangOpts.SjLjExceptions) Builder.defineMacro("__USING_SJLJ_EXCEPTIONS__"); + if (LangOpts.SEHExceptions) + Builder.defineMacro("__SEH__"); if (LangOpts.Deprecated) Builder.defineMacro("__DEPRECATED"); diff --git a/clang/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp b/clang/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp new file mode 100644 index 000000000000..f247e9973986 --- /dev/null +++ b/clang/test/CodeGenCXX/mingw-w64-seh-exceptions.cpp @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 %s -fexceptions -fseh-exceptions -emit-llvm -triple x86_64-w64-windows-gnu -o - | FileCheck %s + +extern "C" void foo(); +extern "C" void bar(); + +struct Cleanup { + ~Cleanup() { + bar(); + } +}; + +extern "C" void test() { + Cleanup x; + foo(); +} + +// CHECK: define void @test() +// CHECK: invoke void @foo() +// CHECK: landingpad { i8*, i32 } personality i8* bitcast (i32 (...)* @__gxx_personality_seh0 to i8*)