diff --git a/clang/lib/Frontend/CompilerInvocation.cpp b/clang/lib/Frontend/CompilerInvocation.cpp index f366e90945dac..d8916a6b15f58 100644 --- a/clang/lib/Frontend/CompilerInvocation.cpp +++ b/clang/lib/Frontend/CompilerInvocation.cpp @@ -3679,6 +3679,22 @@ static StringRef GetInputKindName(InputKind IK) { llvm_unreachable("unknown input language"); } +static StringRef getExceptionHandlingName(unsigned EHK) { + switch (static_cast(EHK)) { + case LangOptions::ExceptionHandlingKind::None: + default: + return "none"; + case LangOptions::ExceptionHandlingKind::SjLj: + return "sjlj"; + case LangOptions::ExceptionHandlingKind::DwarfCFI: + return "dwarf"; + case LangOptions::ExceptionHandlingKind::Wasm: + return "wasm"; + } + + llvm_unreachable("covered switch"); +} + void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, ArgumentConsumer Consumer, const llvm::Triple &T, @@ -3694,6 +3710,10 @@ void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts, GenerateArg(Consumer, OPT_pic_is_pie); for (StringRef Sanitizer : serializeSanitizerKinds(Opts.Sanitize)) GenerateArg(Consumer, OPT_fsanitize_EQ, Sanitizer); + if (Opts.ExceptionHandling) { + GenerateArg(Consumer, OPT_exception_model, + getExceptionHandlingName(Opts.ExceptionHandling)); + } return; } @@ -4002,6 +4022,24 @@ bool CompilerInvocation::ParseLangArgs(LangOptions &Opts, ArgList &Args, parseSanitizerKinds("-fsanitize=", Args.getAllArgValues(OPT_fsanitize_EQ), Diags, Opts.Sanitize); + if (const Arg *A = Args.getLastArg(options::OPT_exception_model)) { + std::optional EMValue = + llvm::StringSwitch>( + A->getValue()) + .Case("dwarf", LangOptions::ExceptionHandlingKind::DwarfCFI) + .Case("sjlj", LangOptions::ExceptionHandlingKind::SjLj) + .Case("wineh", LangOptions::ExceptionHandlingKind::WinEH) + .Case("wasm", LangOptions::ExceptionHandlingKind::Wasm) + .Case("none", LangOptions::ExceptionHandlingKind::None) + .Default(std::nullopt); + if (EMValue) { + Opts.ExceptionHandling = static_cast(*EMValue); + } else { + Diags.Report(diag::err_drv_invalid_value) + << A->getAsString(Args) << A->getValue(); + } + } + return Diags.getNumErrors() == NumErrorsBefore; } diff --git a/clang/test/CodeGen/WebAssembly/wasm-exception-model-flag-parse-ir-input.ll b/clang/test/CodeGen/WebAssembly/wasm-exception-model-flag-parse-ir-input.ll new file mode 100644 index 0000000000000..4a7eeece58717 --- /dev/null +++ b/clang/test/CodeGen/WebAssembly/wasm-exception-model-flag-parse-ir-input.ll @@ -0,0 +1,16 @@ +; REQUIRES: webassembly-registered-target + +; Check all the options parse +; RUN: %clang_cc1 -triple wasm32 -o - -emit-llvm -exception-model=none %s | FileCheck %s +; RUN: %clang_cc1 -triple wasm32 -o - -emit-llvm -exception-model=wasm %s | FileCheck %s +; RUN: %clang_cc1 -triple wasm32 -o - -emit-llvm -exception-model=dwarf %s | FileCheck %s +; RUN: %clang_cc1 -triple wasm32 -o - -emit-llvm -exception-model=sjlj %s | FileCheck %s + +; RUN: not %clang_cc1 -triple wasm32 -o - -emit-llvm -exception-model=invalid %s 2>&1 | FileCheck -check-prefix=ERR %s + +; CHECK-LABEL: define void @test( + +; ERR: error: invalid value 'invalid' in '-exception-model=invalid' +define void @test() { + ret void +} diff --git a/clang/test/CodeGen/WebAssembly/wasm-invalid-exception-kinds.ll b/clang/test/CodeGen/WebAssembly/wasm-invalid-exception-kinds.ll new file mode 100644 index 0000000000000..27fb696c92499 --- /dev/null +++ b/clang/test/CodeGen/WebAssembly/wasm-invalid-exception-kinds.ll @@ -0,0 +1,8 @@ +; RUN: not %clang_cc1 -triple wasm32 -exception-model=arst -S %s 2>&1 | FileCheck -check-prefix=INVALID-VALUE %s + +; Make sure invalid values are rejected for -exception-model when the +; input is IR. + +; INVALID-VALUE: error: invalid value 'arst' in '-exception-model=arst' + +target triple = "wasm32" diff --git a/clang/test/Driver/ir-exception-model.c b/clang/test/Driver/ir-exception-model.c new file mode 100644 index 0000000000000..9e8f998de0d6b --- /dev/null +++ b/clang/test/Driver/ir-exception-model.c @@ -0,0 +1,14 @@ +// RUN: %clang -### -target wasm32-unknown-unknown -fwasm-exceptions -c -S -o - %S/Inputs/file.ll 2>&1 | FileCheck %s +// RUN: %clang -### -target wasm32-unknown-unknown -Xclang -exception-model=wasm -c -S -o - %S/Inputs/file.ll 2>&1 | FileCheck %s +// RUN: %clang -### -target wasm32-unknown-unknown -Xclang -exception-model=dwarf -c -S -o - %S/Inputs/file.ll 2>&1 | FileCheck -check-prefix=DWARF %s +// RUN: %clang -### -target wasm32-unknown-unknown -Xclang -exception-model=sjlj -c -S -o - %S/Inputs/file.ll 2>&1 | FileCheck -check-prefix=SJLJ %s +// RUN: %clang -### -target wasm32-unknown-unknown -Xclang -exception-model=wineh -c -S -o - %S/Inputs/file.ll 2>&1 | FileCheck -check-prefix=WINEH %s +// RUN: %clang -### -target wasm32-unknown-unknown -Xclang -exception-model=arst -c -S -o - %S/Inputs/file.ll 2>&1 | FileCheck -check-prefix=INVALID %s + +// Check that -fwasm-exceptions propagates -exception-model to cc1 + +// CHECK: "-exception-model=wasm" +// DWARF: "-exception-model=dwarf" +// SJLJ: "-exception-model=sjlj" +// WINEH: "-exception-model=wineh" +// INVALID: "-exception-model=arst"