Skip to content

clang: Forward exception_model flag for bitcode inputs #146342

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 38 additions & 0 deletions clang/lib/Frontend/CompilerInvocation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3679,6 +3679,22 @@ static StringRef GetInputKindName(InputKind IK) {
llvm_unreachable("unknown input language");
}

static StringRef getExceptionHandlingName(unsigned EHK) {
switch (static_cast<LangOptions::ExceptionHandlingKind>(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");
Comment on lines +3694 to +3695
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is unreachable necessary here? The compiler is smart enough to know that this function always has a return value I think.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm pretty sure you need it to keep the full set of compilers happy. I think MSVC is the annoying one

}

void CompilerInvocationBase::GenerateLangArgs(const LangOptions &Opts,
ArgumentConsumer Consumer,
const llvm::Triple &T,
Expand All @@ -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));
}
Comment on lines +3713 to +3716
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (Opts.ExceptionHandling) {
GenerateArg(Consumer, OPT_exception_model,
getExceptionHandlingName(Opts.ExceptionHandling));
}
if (Opts.ExceptionHandling)
GenerateArg(Consumer, OPT_exception_model,
getExceptionHandlingName(Opts.ExceptionHandling));

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto


return;
}
Expand Down Expand Up @@ -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<LangOptions::ExceptionHandlingKind> EMValue =
llvm::StringSwitch<std::optional<LangOptions::ExceptionHandlingKind>>(
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<unsigned>(*EMValue);
} else {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
}
Comment on lines +4035 to +4040
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if (EMValue) {
Opts.ExceptionHandling = static_cast<unsigned>(*EMValue);
} else {
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();
}
if (EMValue)
Opts.ExceptionHandling = static_cast<unsigned>(*EMValue);
else
Diags.Report(diag::err_drv_invalid_value)
<< A->getAsString(Args) << A->getValue();

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Multiple lines implies braces, and then keep on all if one does

}

return Diags.getNumErrors() == NumErrorsBefore;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -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
Comment on lines +4 to +7
Copy link
Member

@aheejin aheejin Jul 1, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that modes other than none/wasm do not make any sense in Wasm, what's the point of testing them? (Also #146343 somehow seems to remove them?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They still should parse. The other patch also doesn't remove them, just changes the error


; 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
}
Original file line number Diff line number Diff line change
@@ -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"
14 changes: 14 additions & 0 deletions clang/test/Driver/ir-exception-model.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// RUN: %clang -### -target wasm32-unknown-unknown -fwasm-exceptions -c -S -o - %S/Inputs/file.ll 2>&1 | FileCheck %s
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto here

// 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"
Loading