diff --git a/clang/include/clang/Basic/LangOptions.def b/clang/include/clang/Basic/LangOptions.def --- a/clang/include/clang/Basic/LangOptions.def +++ b/clang/include/clang/Basic/LangOptions.def @@ -128,6 +128,7 @@ LANGOPT(DWARFExceptions , 1, 0, "dwarf exception handling") LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling") LANGOPT(SEHExceptions , 1, 0, "SEH .xdata exception handling") +LANGOPT(WasmExceptions , 1, 0, "WebAssembly exception handling") LANGOPT(ExternCNoUnwind , 1, 0, "Assume extern C functions don't unwind") LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation") LANGOPT(RTTI , 1, 1, "run-time type information") diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -904,6 +904,8 @@ Flags<[CC1Option]>, HelpText<"Use SjLj style exceptions">; def fseh_exceptions : Flag<["-"], "fseh-exceptions">, Group, Flags<[CC1Option]>, HelpText<"Use SEH style exceptions">; +def fwasm_exceptions : Flag<["-"], "fwasm-exceptions">, Group, + Flags<[CC1Option]>, HelpText<"Use WebAssembly style exceptions">; def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, Group; def : Flag<["-"], "fexpensive-optimizations">, Group; diff --git a/clang/lib/CodeGen/BackendUtil.cpp b/clang/lib/CodeGen/BackendUtil.cpp --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -468,6 +468,8 @@ Options.ExceptionModel = llvm::ExceptionHandling::WinEH; if (LangOpts.DWARFExceptions) Options.ExceptionModel = llvm::ExceptionHandling::DwarfCFI; + if (LangOpts.WasmExceptions) + Options.ExceptionModel = llvm::ExceptionHandling::Wasm; Options.NoInfsFPMath = CodeGenOpts.NoInfsFPMath; Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath; diff --git a/clang/lib/CodeGen/CGException.cpp b/clang/lib/CodeGen/CGException.cpp --- a/clang/lib/CodeGen/CGException.cpp +++ b/clang/lib/CodeGen/CGException.cpp @@ -165,10 +165,7 @@ return EHPersonality::GNU_CPlusPlus; if (L.SEHExceptions) return EHPersonality::GNU_CPlusPlus_SEH; - // Wasm EH is a non-MVP feature for now. - if (Target.hasFeature("exception-handling") && - (T.getArch() == llvm::Triple::wasm32 || - T.getArch() == llvm::Triple::wasm64)) + if (L.WasmExceptions) return EHPersonality::GNU_Wasm_CPlusPlus; return EHPersonality::GNU_CPlusPlus; } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/clang/lib/Driver/ToolChains/Clang.cpp @@ -4977,9 +4977,9 @@ addExceptionArgs(Args, InputType, TC, KernelOrKext, Runtime, CmdArgs); // Handle exception personalities - Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, - options::OPT_fseh_exceptions, - options::OPT_fdwarf_exceptions); + Arg *A = Args.getLastArg( + options::OPT_fsjlj_exceptions, options::OPT_fseh_exceptions, + options::OPT_fdwarf_exceptions, options::OPT_fwasm_exceptions); if (A) { const Option &Opt = A->getOption(); if (Opt.matches(options::OPT_fsjlj_exceptions)) @@ -4988,6 +4988,8 @@ CmdArgs.push_back("-fseh-exceptions"); if (Opt.matches(options::OPT_fdwarf_exceptions)) CmdArgs.push_back("-fdwarf-exceptions"); + if (Opt.matches(options::OPT_fwasm_exceptions)) + CmdArgs.push_back("-fwasm-exceptions"); } else { switch (TC.GetExceptionModel(Args)) { default: diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp --- a/clang/lib/Driver/ToolChains/WebAssembly.cpp +++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp @@ -166,6 +166,17 @@ CC1Args.push_back("-target-feature"); CC1Args.push_back("+mutable-globals"); } + + // '-fwasm-exceptions' implies exception-handling + if (DriverArgs.getLastArg(options::OPT_fwasm_exceptions)) { + if (DriverArgs.hasFlag(options::OPT_mno_exception_handing, + options::OPT_mexception_handing, false)) + getDriver().Diag(diag::err_drv_argument_not_allowed_with) + << "-fwasm-exceptions" + << "-mno-exception-handling"; + CC1Args.push_back("-target-feature"); + CC1Args.push_back("+exception-handling"); + } } ToolChain::RuntimeLibType WebAssembly::GetDefaultRuntimeLibType() const { diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -2686,9 +2686,9 @@ Opts.FixedPoint; // Handle exception personalities - Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, - options::OPT_fseh_exceptions, - options::OPT_fdwarf_exceptions); + Arg *A = Args.getLastArg( + options::OPT_fsjlj_exceptions, options::OPT_fseh_exceptions, + options::OPT_fdwarf_exceptions, options::OPT_fwasm_exceptions); if (A) { const Option &Opt = A->getOption(); llvm::Triple T(TargetOpts.Triple); @@ -2699,6 +2699,7 @@ Opts.SjLjExceptions = Opt.matches(options::OPT_fsjlj_exceptions); Opts.SEHExceptions = Opt.matches(options::OPT_fseh_exceptions); Opts.DWARFExceptions = Opt.matches(options::OPT_fdwarf_exceptions); + Opts.WasmExceptions = Opt.matches(options::OPT_fwasm_exceptions); } Opts.ExternCNoUnwind = Args.hasArg(OPT_fexternc_nounwind); diff --git a/clang/test/CodeGenCXX/wasm-eh.cpp b/clang/test/CodeGenCXX/wasm-eh.cpp --- a/clang/test/CodeGenCXX/wasm-eh.cpp +++ b/clang/test/CodeGenCXX/wasm-eh.cpp @@ -1,5 +1,6 @@ -// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -target-feature +exception-handling -emit-llvm -o - -std=c++11 | FileCheck %s -// RUN: %clang_cc1 %s -triple wasm64-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -target-feature +exception-handling -emit-llvm -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -fwasm-exceptions -target-feature +exception-handling -emit-llvm -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 %s -triple wasm64-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -fwasm-exceptions -target-feature +exception-handling -emit-llvm -o - -std=c++11 | FileCheck %s +// RUN: %clang_cc1 %s -triple wasm32-unknown-unknown -fms-extensions -fexceptions -fcxx-exceptions -fwasm-exceptions -target-feature +exception-handling -S -o - -std=c++11 | FileCheck %s --check-prefix=ASSEMBLY void may_throw(); void dont_throw() noexcept; @@ -382,3 +383,12 @@ // CHECK: cleanupret from %[[CLEANUPPAD1]] unwind to caller // CHECK: unreachable + + +// Here we only check if the command enables wasm exception handling in the +// backend so that exception handling instructions can be generated in .s file. + +// ASSEMBLY: try +// ASSEMBLY: catch +// ASSEMBLY: rethrow +// ASSEMBLY: end_try diff --git a/clang/test/Driver/wasm-toolchain.c b/clang/test/Driver/wasm-toolchain.c --- a/clang/test/Driver/wasm-toolchain.c +++ b/clang/test/Driver/wasm-toolchain.c @@ -73,6 +73,18 @@ // RUN: | FileCheck -check-prefix=PTHREAD_NO_MUT_GLOBALS %s // PTHREAD_NO_MUT_GLOBALS: invalid argument '-pthread' not allowed with '-mno-mutable-globals' +// '-fwasm-exceptions' sets +exception-handling +// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown \ +// RUN: --sysroot=/foo %s -fwasm-exceptions 2>&1 \ +// RUN: | FileCheck -check-prefix=WASM_EXCEPTIONS %s +// WASM_EXCEPTIONS: clang{{.*}}" "-cc1" {{.*}} "-target-feature" "+exception-handling" + +// '-fwasm-exceptions' not allowed with '-mno-exception-handling' +// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown \ +// RUN: --sysroot=/foo %s -fwasm-exceptions -mno-exception-handling 2>&1 \ +// RUN: | FileCheck -check-prefix=WASM_EXCEPTIONS_NO_EH %s +// WASM_EXCEPTIONS_NO_EH: invalid argument '-fwasm-exceptions' not allowed with '-mno-exception-handling' + // RUN: %clang %s -### -fsanitize=address -target wasm32-unknown-emscripten 2>&1 | FileCheck -check-prefix=CHECK-ASAN-EMSCRIPTEN %s // CHECK-ASAN-EMSCRIPTEN: "-fsanitize=address" // CHECK-ASAN-EMSCRIPTEN: "-fsanitize-address-globals-dead-stripping"