[clang] [llvm] WebAssembly: Drive Emscripten EH from the exception model, drop the cl::opt (PR #223972)
Matt Arsenault via cfe-commits
cfe-commits at lists.llvm.org
Wed Sep 16 23:14:47 PDT 2026
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/223972
>From 162929df3e93f7755fa15405477f494de5f1c583 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Fri, 4 Sep 2026 16:51:41 +0200
Subject: [PATCH] WebAssembly: Drive Emscripten EH from the exception model,
drop the cl::opt
Remove the deprecated -enable-emscripten-cxx-exceptions flag. This should now
be driven by the generic exception-model mechanisms. There was also some special
case handling of the -mllvm flag in the clang driver which also needed removal.
Co-authored-by: Claude (Claude-Opus-4.8) <noreply at anthropic.com>
---
clang/lib/Driver/ToolChains/WebAssembly.cpp | 16 +++---------
clang/test/Driver/wasm-toolchain.c | 26 +------------------
.../WebAssembly/WebAssemblyAsmPrinter.cpp | 7 +++--
.../WebAssemblyCodeGenPassBuilder.cpp | 6 +----
.../WebAssemblyLowerEmscriptenEHSjLj.cpp | 3 +--
.../WebAssembly/WebAssemblyTargetMachine.cpp | 16 ++----------
.../WebAssembly/WebAssemblyTargetMachine.h | 1 -
7 files changed, 13 insertions(+), 62 deletions(-)
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index b683fcd506a44..b28154772f9f9 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -429,8 +429,7 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
for (const auto *Option :
- {"-enable-emscripten-cxx-exceptions", "-enable-emscripten-sjlj",
- "-emscripten-cxx-exceptions-allowed"}) {
+ {"-enable-emscripten-sjlj", "-emscripten-cxx-exceptions-allowed"}) {
if (StringRef(A->getValue(0)) == Option)
getDriver().Diag(diag::err_drv_argument_not_allowed_with)
<< CurOption << Option;
@@ -466,17 +465,8 @@ void WebAssembly::addClangTargetOptions(const ArgList &DriverArgs,
StringRef Opt = A->getValue(0);
if (Opt.starts_with("-emscripten-cxx-exceptions-allowed")) {
// '-mllvm -emscripten-cxx-exceptions-allowed' should be used with
- // '-femscripten-exceptions' (or the underlying
- // '-mllvm -enable-emscripten-cxx-exceptions').
- bool EmEHArgExists =
- DriverArgs.hasArg(options::OPT_femscripten_exceptions);
- for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
- if (StringRef(A->getValue(0)) == "-enable-emscripten-cxx-exceptions") {
- EmEHArgExists = true;
- break;
- }
- }
- if (!EmEHArgExists)
+ // '-femscripten-exceptions'.
+ if (!DriverArgs.hasArg(options::OPT_femscripten_exceptions))
getDriver().Diag(diag::err_drv_argument_only_allowed_with)
<< "-mllvm -emscripten-cxx-exceptions-allowed"
<< "-femscripten-exceptions";
diff --git a/clang/test/Driver/wasm-toolchain.c b/clang/test/Driver/wasm-toolchain.c
index 665cf4d1a667b..7a36440494f42 100644
--- a/clang/test/Driver/wasm-toolchain.c
+++ b/clang/test/Driver/wasm-toolchain.c
@@ -129,7 +129,7 @@
// EMSCRIPTEN_EH_ALLOWED_NOINLINE: "-cc1" {{.*}} "-mllvm" "--force-attribute=foo:noinline" "-mllvm" "--force-attribute=bar:noinline"
// '-mllvm -emscripten-cxx-exceptions-allowed' only allowed with
-// '-mllvm -enable-emscripten-cxx-exceptions'
+// '-femscripten-exceptions'
// RUN: not %clang -### --target=wasm32-unknown-unknown \
// RUN: --sysroot=/foo %s -mllvm -emscripten-cxx-exceptions-allowed 2>&1 \
// RUN: | FileCheck -check-prefix=EMSCRIPTEN_EH_ALLOWED_WO_ENABLE %s
@@ -161,14 +161,6 @@
// RUN: | FileCheck -check-prefix=WASM_EXCEPTIONS %s
// WASM_EXCEPTIONS: "-cc1" {{.*}} "-target-feature" "+exception-handling" "-target-feature" "+multivalue" "-target-feature" "+reference-types" "-exception-model=wasm" "-mllvm" "-wasm-enable-eh"
-// '-fwasm-exceptions' not allowed with
-// '-mllvm -enable-emscripten-cxx-exceptions'
-// RUN: not %clang -### --target=wasm32-unknown-unknown \
-// RUN: --sysroot=/foo %s -fwasm-exceptions \
-// RUN: -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 '-enable-emscripten-cxx-exceptions'
-
// '-fwasm-exceptions' not allowed with '-mllvm -enable-emscripten-sjlj'
// RUN: not %clang -### --target=wasm32-unknown-unknown \
// RUN: --sysroot=/foo %s -fwasm-exceptions \
@@ -201,14 +193,6 @@
// RUN: | FileCheck -check-prefix=WASM_SJLJ %s
// WASM_SJLJ: "-cc1" {{.*}} "-target-feature" "+exception-handling" "-target-feature" "+multivalue" "-target-feature" "+reference-types" "-exception-model=wasm"
-// '-mllvm -wasm-enable-sjlj' not allowed with
-// '-mllvm -enable-emscripten-cxx-exceptions'
-// RUN: not %clang -### --target=wasm32-unknown-unknown \
-// RUN: --sysroot=/foo %s -mllvm -wasm-enable-sjlj \
-// RUN: -mllvm -enable-emscripten-cxx-exceptions 2>&1 \
-// RUN: | FileCheck -check-prefix=WASM_SJLJ_EMSCRIPTEN_EH %s
-// WASM_SJLJ_EMSCRIPTEN_EH: invalid argument '-wasm-enable-sjlj' not allowed with '-enable-emscripten-cxx-exceptions'
-
// '-mllvm -wasm-enable-sjlj' not allowed with '-mllvm -enable-emscripten-sjlj'
// RUN: not %clang -### --target=wasm32-unknown-unknown \
// RUN: --sysroot=/foo %s -mllvm -wasm-enable-sjlj \
@@ -236,14 +220,6 @@
// RUN: | FileCheck -check-prefix=WASM_SJLJ_NO_REFERENCE_TYPES %s
// WASM_SJLJ_NO_REFERENCE_TYPES: invalid argument '-wasm-enable-sjlj' not allowed with '-mno-reference-types'
-// '-mllvm -wasm-use-legacy-eh' not allowed with
-// '-mllvm -enable-emscripten-cxx-exceptions'
-// RUN: not %clang -### --target=wasm32-unknown-unknown \
-// RUN: --sysroot=/foo %s -mllvm -wasm-use-legacy-eh \
-// RUN: -mllvm -enable-emscripten-cxx-exceptions 2>&1 \
-// RUN: | FileCheck -check-prefix=WASM_LEGACY_EH_EMSCRIPTEN_EH %s
-// WASM_LEGACY_EH_EMSCRIPTEN_EH: invalid argument '-wasm-use-legacy-eh' not allowed with '-enable-emscripten-cxx-exceptions'
-
// '-mllvm -wasm-use-legacy-eh' not allowed with '-mllvm -enable-emscripten-sjlj'
// RUN: not %clang -### --target=wasm32-unknown-unknown \
// RUN: --sysroot=/foo %s -mllvm -wasm-use-legacy-eh \
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 5929b0f77359c..0d5d0ae04fa2d 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -165,9 +165,12 @@ MCSymbolWasm *WebAssemblyAsmPrinter::getMCSymbolForFunction(
const Function *F, wasm::WasmSignature *Sig, bool &InvokeDetected) {
MCSymbolWasm *WasmSym = nullptr;
+ // Prefer the "exception-model" module flag, else the TargetOptions default.
+ ExceptionHandling EM = F->getParent()->getExceptionModel();
+ if (EM == ExceptionHandling::Default)
+ EM = TM.getExceptionModel();
const bool EnableEmEH =
- TM.Options.ExceptionModel == ExceptionHandling::Emscripten ||
- WebAssembly::WasmEnableEmEH || WebAssembly::WasmEnableEmSjLj;
+ EM == ExceptionHandling::Emscripten || WebAssembly::WasmEnableEmSjLj;
if (EnableEmEH && isEmscriptenInvokeName(F->getName())) {
assert(Sig);
InvokeDetected = true;
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
index 82f7fdd2b7079..c53072764bc82 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
@@ -42,14 +42,12 @@ using namespace llvm;
namespace WebAssembly {
extern cl::opt<bool> WasmDisableExplicitLocals;
extern cl::opt<bool> WasmEnableEH;
-extern cl::opt<bool> WasmEnableEmEH;
extern cl::opt<bool> WasmEnableEmSjLj;
extern cl::opt<bool> WasmEnableSjLj;
} // namespace WebAssembly
using llvm::WebAssembly::WasmDisableExplicitLocals;
using llvm::WebAssembly::WasmEnableEH;
-using llvm::WebAssembly::WasmEnableEmEH;
using llvm::WebAssembly::WasmEnableEmSjLj;
using llvm::WebAssembly::WasmEnableSjLj;
@@ -127,9 +125,7 @@ void WebAssemblyCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) {
// TargetPassConfig::addPassesToHandleExceptions, but that runs after these IR
// passes and Emscripten SjLj handling expects all invokes to be lowered
// before.
- bool EnableEmEH =
- TM.Options.ExceptionModel == ExceptionHandling::Emscripten ||
- WasmEnableEmEH;
+ bool EnableEmEH = TM.Options.ExceptionModel == ExceptionHandling::Emscripten;
if (!EnableEmEH && !WasmEnableEH) {
addFunctionPass(LowerInvokePass(), PMW);
// The lower invoke pass may create unreachable code. Remove it in order not
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
index de43564c3f2c5..0ee7731f8e4f5 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
@@ -361,8 +361,7 @@ class WebAssemblyLowerEmscriptenEHSjLjImpl {
WebAssemblyLowerEmscriptenEHSjLjImpl(
bool EnableEmEH,
std::function<DominatorTree &(Function &F)> GetDominatorTree)
- : EnableEmEH(EnableEmEH || WebAssembly::WasmEnableEmEH),
- EnableEmSjLj(WebAssembly::WasmEnableEmSjLj),
+ : EnableEmEH(EnableEmEH), EnableEmSjLj(WebAssembly::WasmEnableEmSjLj),
EnableWasmSjLj(WebAssembly::WasmEnableSjLj),
GetDominatorTree(GetDominatorTree) {
assert(!(EnableEmSjLj && EnableWasmSjLj) &&
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index 7cfc7a3c9c983..3b054f80027c5 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -52,11 +52,6 @@ cl::opt<bool> WebAssembly::WasmDisableExplicitLocals(
// Exception handling & setjmp-longjmp handling related options.
-// Emscripten's asm.js-style exception handling
-cl::opt<bool> WebAssembly::WasmEnableEmEH(
- "enable-emscripten-cxx-exceptions",
- cl::desc("WebAssembly Emscripten-style exception handling"),
- cl::init(false));
// Emscripten's asm.js-style setjmp/longjmp handling
cl::opt<bool> WebAssembly::WasmEnableEmSjLj(
"enable-emscripten-sjlj",
@@ -135,17 +130,12 @@ static Reloc::Model getEffectiveRelocModel(std::optional<Reloc::Model> RM) {
using WebAssembly::WasmDisableExplicitLocals;
using WebAssembly::WasmEnableEH;
-using WebAssembly::WasmEnableEmEH;
using WebAssembly::WasmEnableEmSjLj;
using WebAssembly::WasmEnableSjLj;
static void basicCheckForEHAndSjLj(TargetMachine *TM) {
- // Emscripten EH is selected by the exception model. WasmEnableEmEH is a
- // deprecated cl::opt alias, OR-ed in here until it is removed.
- bool EnableEmEH =
- TM->Options.ExceptionModel == ExceptionHandling::Emscripten ||
- WasmEnableEmEH;
+ bool EnableEmEH = TM->Options.ExceptionModel == ExceptionHandling::Emscripten;
// You can't enable two modes of EH at the same time
if (EnableEmEH && WasmEnableEH)
@@ -343,9 +333,7 @@ void WebAssemblyPassConfig::addIRPasses() {
// TargetPassConfig::addPassesToHandleExceptions, but that runs after these IR
// passes and Emscripten SjLj handling expects all invokes to be lowered
// before.
- bool EnableEmEH =
- TM->Options.ExceptionModel == ExceptionHandling::Emscripten ||
- WasmEnableEmEH;
+ bool EnableEmEH = TM->Options.ExceptionModel == ExceptionHandling::Emscripten;
if (!EnableEmEH && !WasmEnableEH) {
addPass(createLowerInvokePass());
// The lower invoke pass may create unreachable code. Remove it in order not
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
index 55f8898e387da..cff4d345b8516 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h
@@ -24,7 +24,6 @@ namespace llvm {
namespace WebAssembly {
// Exception handling / setjmp-longjmp handling command-line options
extern cl::opt<bool> WasmDisableExplicitLocals;
-extern cl::opt<bool> WasmEnableEmEH; // asm.js-style EH
extern cl::opt<bool> WasmEnableEmSjLj; // asm.js-style SjLJ
extern cl::opt<bool> WasmEnableEH; // EH using Wasm EH instructions
extern cl::opt<bool> WasmEnableSjLj; // SjLj using Wasm EH instructions
More information about the cfe-commits
mailing list