[WebAssembly] Add -fwasm-exceptions for wasm EH

Summary:
This adds `-fwasm-exceptions` (in similar fashion with
`-fdwarf-exceptions` or `-fsjlj-exceptions`) that turns on everything
with wasm exception handling from the frontend to the backend.

We currently have `-mexception-handling` in clang frontend, but this is
only about the architecture capability and does not turn on other
necessary options such as the exception model in the backend. (This can
be turned on with `llc -exception-model=wasm`, but llc is not invoked
separately as a command line tool, so this option has to be transferred
from clang.)

Turning on `-fwasm-exceptions` in clang also turns on
`-mexception-handling` if not specified, and will error out if
`-mno-exception-handling` is specified.

Reviewers: dschuff, tlively, sbc100

Subscribers: aprantl, jgravelle-google, sunfish, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D67208

llvm-svn: 371708
This commit is contained in:
Heejin Ahn 2019-09-12 04:01:37 +00:00
parent bdfe84ad11
commit e8b2b8868d
9 changed files with 65 additions and 12 deletions

View File

@ -128,6 +128,7 @@ LANGOPT(CXXExceptions , 1, 0, "C++ exceptions")
LANGOPT(DWARFExceptions , 1, 0, "dwarf exception handling") LANGOPT(DWARFExceptions , 1, 0, "dwarf exception handling")
LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling") LANGOPT(SjLjExceptions , 1, 0, "setjmp-longjump exception handling")
LANGOPT(SEHExceptions , 1, 0, "SEH .xdata 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(ExternCNoUnwind , 1, 0, "Assume extern C functions don't unwind")
LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation") LANGOPT(TraditionalCPP , 1, 0, "traditional CPP emulation")
LANGOPT(RTTI , 1, 1, "run-time type information") LANGOPT(RTTI , 1, 1, "run-time type information")

View File

@ -904,6 +904,8 @@ def fsjlj_exceptions : Flag<["-"], "fsjlj-exceptions">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Use SjLj style exceptions">; Flags<[CC1Option]>, HelpText<"Use SjLj style exceptions">;
def fseh_exceptions : Flag<["-"], "fseh-exceptions">, Group<f_Group>, def fseh_exceptions : Flag<["-"], "fseh-exceptions">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Use SEH style exceptions">; Flags<[CC1Option]>, HelpText<"Use SEH style exceptions">;
def fwasm_exceptions : Flag<["-"], "fwasm-exceptions">, Group<f_Group>,
Flags<[CC1Option]>, HelpText<"Use WebAssembly style exceptions">;
def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">, def fexcess_precision_EQ : Joined<["-"], "fexcess-precision=">,
Group<clang_ignored_gcc_optimization_f_Group>; Group<clang_ignored_gcc_optimization_f_Group>;
def : Flag<["-"], "fexpensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>; def : Flag<["-"], "fexpensive-optimizations">, Group<clang_ignored_gcc_optimization_f_Group>;

View File

@ -468,6 +468,8 @@ static void initTargetOptions(llvm::TargetOptions &Options,
Options.ExceptionModel = llvm::ExceptionHandling::WinEH; Options.ExceptionModel = llvm::ExceptionHandling::WinEH;
if (LangOpts.DWARFExceptions) if (LangOpts.DWARFExceptions)
Options.ExceptionModel = llvm::ExceptionHandling::DwarfCFI; Options.ExceptionModel = llvm::ExceptionHandling::DwarfCFI;
if (LangOpts.WasmExceptions)
Options.ExceptionModel = llvm::ExceptionHandling::Wasm;
Options.NoInfsFPMath = CodeGenOpts.NoInfsFPMath; Options.NoInfsFPMath = CodeGenOpts.NoInfsFPMath;
Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath; Options.NoNaNsFPMath = CodeGenOpts.NoNaNsFPMath;

View File

@ -165,10 +165,7 @@ static const EHPersonality &getCXXPersonality(const TargetInfo &Target,
return EHPersonality::GNU_CPlusPlus; return EHPersonality::GNU_CPlusPlus;
if (L.SEHExceptions) if (L.SEHExceptions)
return EHPersonality::GNU_CPlusPlus_SEH; return EHPersonality::GNU_CPlusPlus_SEH;
// Wasm EH is a non-MVP feature for now. if (L.WasmExceptions)
if (Target.hasFeature("exception-handling") &&
(T.getArch() == llvm::Triple::wasm32 ||
T.getArch() == llvm::Triple::wasm64))
return EHPersonality::GNU_Wasm_CPlusPlus; return EHPersonality::GNU_Wasm_CPlusPlus;
return EHPersonality::GNU_CPlusPlus; return EHPersonality::GNU_CPlusPlus;
} }

View File

@ -4981,9 +4981,9 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
addExceptionArgs(Args, InputType, TC, KernelOrKext, Runtime, CmdArgs); addExceptionArgs(Args, InputType, TC, KernelOrKext, Runtime, CmdArgs);
// Handle exception personalities // Handle exception personalities
Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, Arg *A = Args.getLastArg(
options::OPT_fseh_exceptions, options::OPT_fsjlj_exceptions, options::OPT_fseh_exceptions,
options::OPT_fdwarf_exceptions); options::OPT_fdwarf_exceptions, options::OPT_fwasm_exceptions);
if (A) { if (A) {
const Option &Opt = A->getOption(); const Option &Opt = A->getOption();
if (Opt.matches(options::OPT_fsjlj_exceptions)) if (Opt.matches(options::OPT_fsjlj_exceptions))
@ -4992,6 +4992,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA,
CmdArgs.push_back("-fseh-exceptions"); CmdArgs.push_back("-fseh-exceptions");
if (Opt.matches(options::OPT_fdwarf_exceptions)) if (Opt.matches(options::OPT_fdwarf_exceptions))
CmdArgs.push_back("-fdwarf-exceptions"); CmdArgs.push_back("-fdwarf-exceptions");
if (Opt.matches(options::OPT_fwasm_exceptions))
CmdArgs.push_back("-fwasm-exceptions");
} else { } else {
switch (TC.GetExceptionModel(Args)) { switch (TC.GetExceptionModel(Args)) {
default: default:

View File

@ -166,6 +166,26 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
CC1Args.push_back("-target-feature"); CC1Args.push_back("-target-feature");
CC1Args.push_back("+mutable-globals"); 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 { ToolChain::RuntimeLibType WebAssembly::GetDefaultRuntimeLibType() const {

View File

@ -2686,9 +2686,9 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.FixedPoint; Opts.FixedPoint;
// Handle exception personalities // Handle exception personalities
Arg *A = Args.getLastArg(options::OPT_fsjlj_exceptions, Arg *A = Args.getLastArg(
options::OPT_fseh_exceptions, options::OPT_fsjlj_exceptions, options::OPT_fseh_exceptions,
options::OPT_fdwarf_exceptions); options::OPT_fdwarf_exceptions, options::OPT_fwasm_exceptions);
if (A) { if (A) {
const Option &Opt = A->getOption(); const Option &Opt = A->getOption();
llvm::Triple T(TargetOpts.Triple); llvm::Triple T(TargetOpts.Triple);
@ -2699,6 +2699,7 @@ static void ParseLangArgs(LangOptions &Opts, ArgList &Args, InputKind IK,
Opts.SjLjExceptions = Opt.matches(options::OPT_fsjlj_exceptions); Opts.SjLjExceptions = Opt.matches(options::OPT_fsjlj_exceptions);
Opts.SEHExceptions = Opt.matches(options::OPT_fseh_exceptions); Opts.SEHExceptions = Opt.matches(options::OPT_fseh_exceptions);
Opts.DWARFExceptions = Opt.matches(options::OPT_fdwarf_exceptions); Opts.DWARFExceptions = Opt.matches(options::OPT_fdwarf_exceptions);
Opts.WasmExceptions = Opt.matches(options::OPT_fwasm_exceptions);
} }
Opts.ExternCNoUnwind = Args.hasArg(OPT_fexternc_nounwind); Opts.ExternCNoUnwind = Args.hasArg(OPT_fexternc_nounwind);

View File

@ -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 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 -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 may_throw();
void dont_throw() noexcept; void dont_throw() noexcept;
@ -382,3 +383,11 @@ void test8() {
// CHECK: cleanupret from %[[CLEANUPPAD1]] unwind to caller // CHECK: cleanupret from %[[CLEANUPPAD1]] unwind to caller
// CHECK: unreachable // 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

View File

@ -73,6 +73,25 @@
// RUN: | FileCheck -check-prefix=PTHREAD_NO_MUT_GLOBALS %s // RUN: | FileCheck -check-prefix=PTHREAD_NO_MUT_GLOBALS %s
// PTHREAD_NO_MUT_GLOBALS: invalid argument '-pthread' not allowed with '-mno-mutable-globals' // 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 // 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"
// CHECK-ASAN-EMSCRIPTEN: "-fsanitize-address-globals-dead-stripping" // CHECK-ASAN-EMSCRIPTEN: "-fsanitize-address-globals-dead-stripping"