[llvm-branch-commits] [clang] [llvm] WebAssembly: Drive Emscripten EH from the exception model, drop the cl::opt (PR #223972)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Wed Sep 16 03:44:24 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-clang-driver

Author: Matt Arsenault (arsenm)

<details>
<summary>Changes</summary>

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.

Also reverts the test change in b6912258891caefffbf15edb1bceff3724b75af5 now that
the backend doesn't need to be built to test the flag behavior.

Co-authored-by: Claude (Claude-Opus-4.8) <noreply@<!-- -->anthropic.com>

---
Full diff: https://github.com/llvm/llvm-project/pull/223972.diff


9 Files Affected:

- (modified) clang/lib/Driver/ToolChains/WebAssembly.cpp (+3-13) 
- (removed) clang/test/CodeGen/WebAssembly/exception-model-flag.c (-16) 
- (modified) clang/test/CodeGen/exception-model-flag.c (+8) 
- (modified) clang/test/Driver/wasm-toolchain.c (+1-25) 
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp (+5-2) 
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp (+1-5) 
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp (+1-2) 
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp (+2-14) 
- (modified) llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.h (-1) 


``````````diff
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/CodeGen/WebAssembly/exception-model-flag.c b/clang/test/CodeGen/WebAssembly/exception-model-flag.c
deleted file mode 100644
index 35b56db409b0b..0000000000000
--- a/clang/test/CodeGen/WebAssembly/exception-model-flag.c
+++ /dev/null
@@ -1,16 +0,0 @@
-// REQUIRES: webassembly-registered-target
-
-// Verify clang records the "exception-model" module flag for the WebAssembly
-// exception models. The target-independent models are covered in
-// exception-model-flag.c.
-
-// Wasm EH (needs the backend enable flag) records the "wasm" model.
-// RUN: %clang_cc1 -triple wasm32-unknown-unknown -fexceptions -exception-model=wasm -mllvm -wasm-enable-eh -emit-llvm %s -o - | FileCheck %s --check-prefix=WASM
-
-// Emscripten EH records the "emscripten" model.
-// RUN: %clang_cc1 -triple wasm32-unknown-emscripten -fexceptions -exception-model=emscripten -emit-llvm %s -o - | FileCheck %s --check-prefix=EMSCRIPTEN
-
-void f(void) {}
-
-// WASM: !{i32 1, !"exception-model", !"wasm"}
-// EMSCRIPTEN: !{i32 1, !"exception-model", !"emscripten"}
diff --git a/clang/test/CodeGen/exception-model-flag.c b/clang/test/CodeGen/exception-model-flag.c
index f9713d88df592..3a3fc8a469c94 100644
--- a/clang/test/CodeGen/exception-model-flag.c
+++ b/clang/test/CodeGen/exception-model-flag.c
@@ -13,6 +13,12 @@
 // SEH maps to the "wineh" spelling regardless of the requesting triple.
 // RUN: %clang_cc1 -triple i686-unknown-windows-gnu -fexceptions -exception-model=seh -emit-llvm %s -o - | FileCheck %s --check-prefix=WINEH
 
+// Wasm EH (needs the backend enable flag) records the "wasm" model.
+// RUN: %clang_cc1 -triple wasm32-unknown-unknown -fexceptions -exception-model=wasm -mllvm -wasm-enable-eh -emit-llvm %s -o - | FileCheck %s --check-prefix=WASM
+
+// Emscripten EH records the "emscripten" model.
+// RUN: %clang_cc1 -triple wasm32-unknown-emscripten -fexceptions -exception-model=emscripten -emit-llvm %s -o - | FileCheck %s --check-prefix=EMSCRIPTEN
+
 // A requested model that matches the target default is still recorded, so that
 // the flag's absence always means "unspecified".
 // RUN: %clang_cc1 -triple i686-unknown-linux-gnu -fexceptions -exception-model=dwarf -emit-llvm %s -o - | FileCheck %s --check-prefix=DWARF
@@ -30,6 +36,8 @@ void f(void) {}
 
 // SJLJ: !{i32 1, !"exception-model", !"sjlj"}
 // WINEH: !{i32 1, !"exception-model", !"wineh"}
+// WASM: !{i32 1, !"exception-model", !"wasm"}
+// EMSCRIPTEN: !{i32 1, !"exception-model", !"emscripten"}
 // DWARF: !{i32 1, !"exception-model", !"dwarf"}
 // NONE: !{i32 1, !"exception-model", !"none"}
 // UNSPEC-NOT: "exception-model"
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

``````````

</details>


https://github.com/llvm/llvm-project/pull/223972


More information about the llvm-branch-commits mailing list