Index: cfe/trunk/include/clang/Basic/LangOptions.def =================================================================== --- cfe/trunk/include/clang/Basic/LangOptions.def +++ cfe/trunk/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") Index: cfe/trunk/include/clang/Driver/Options.td =================================================================== --- cfe/trunk/include/clang/Driver/Options.td +++ cfe/trunk/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; Index: cfe/trunk/lib/CodeGen/BackendUtil.cpp =================================================================== --- cfe/trunk/lib/CodeGen/BackendUtil.cpp +++ cfe/trunk/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; Index: cfe/trunk/lib/CodeGen/CGException.cpp =================================================================== --- cfe/trunk/lib/CodeGen/CGException.cpp +++ cfe/trunk/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; } Index: cfe/trunk/lib/Driver/ToolChains/Clang.cpp =================================================================== --- cfe/trunk/lib/Driver/ToolChains/Clang.cpp +++ cfe/trunk/lib/Driver/ToolChains/Clang.cpp @@ -4981,9 +4981,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)) @@ -4992,6 +4992,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: Index: cfe/trunk/lib/Driver/ToolChains/WebAssembly.cpp =================================================================== --- cfe/trunk/lib/Driver/ToolChains/WebAssembly.cpp +++ cfe/trunk/lib/Driver/ToolChains/WebAssembly.cpp @@ -166,6 +166,26 @@ CC1Args.push_back("-target-feature"); CC1Args.push_back("+mutable-globals"); } + + if (DriverArgs.getLastArg(options::OPT_fwasm_exceptions)) { + // '-fwasm-exceptions' is not compatible with '-mno-exception-handling' + 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"; + // '-fwasm-exceptions' is not compatible with + // '-mllvm -enable-emscripten-cxx-exceptions' + for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) { + if (StringRef(A->getValue(0)) == "-enable-emscripten-cxx-exceptions") + getDriver().Diag(diag::err_drv_argument_not_allowed_with) + << "-fwasm-exceptions" + << "-mllvm -enable-emscripten-cxx-exceptions"; + } + // '-fwasm-exceptions' implies exception-handling + CC1Args.push_back("-target-feature"); + CC1Args.push_back("+exception-handling"); + } } ToolChain::RuntimeLibType WebAssembly::GetDefaultRuntimeLibType() const { Index: cfe/trunk/lib/Frontend/CompilerInvocation.cpp =================================================================== --- cfe/trunk/lib/Frontend/CompilerInvocation.cpp +++ cfe/trunk/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); Index: cfe/trunk/test/CodeGenCXX/wasm-eh.cpp =================================================================== --- cfe/trunk/test/CodeGenCXX/wasm-eh.cpp +++ cfe/trunk/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,11 @@ // 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 Index: cfe/trunk/test/Driver/wasm-toolchain.c =================================================================== --- cfe/trunk/test/Driver/wasm-toolchain.c +++ cfe/trunk/test/Driver/wasm-toolchain.c @@ -73,6 +73,25 @@ // 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' + +// '-fwasm-exceptions' not allowed with +// '-mllvm -enable-emscripten-cxx-exceptions' +// RUN: %clang -### -no-canonical-prefixes -target wasm32-unknown-unknown \ +// RUN: --sysroot=/foo %s -fwasm-exceptions -mllvm -enable-emscripten-cxx-exceptions 2>&1 \ +// RUN: | FileCheck -check-prefix=WASM_EXCEPTIONS_EMSCRIPTEN_EH %s +// WASM_EXCEPTIONS_EMSCRIPTEN_EH: invalid argument '-fwasm-exceptions' not allowed with '-mllvm -enable-emscripten-cxx-exceptions' + // 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"