https://github.com/arsenm updated 
https://github.com/llvm/llvm-project/pull/221443

>From 89e13008600307db52c421ab59c0e98ea2508518 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Sat, 5 Sep 2026 12:19:03 +0200
Subject: [PATCH 1/2] clang/WebAssembly: Add -femscripten-exceptions driver
 flag

Add a proper -femscripten-exceptions driver flag for Emscripten
exception handling, parallel to -fwasm-exceptions. Previously the only way
to select Emscripten EH was to pass the backend implementation detail
-mllvm -enable-emscripten-cxx-exceptions.

This drives the existing cl::opt mechanism, but in the future this will
change the emitted exception model module flag.

Co-authored-by: Claude (Claude-Opus-4.8) <[email protected]>
---
 clang/include/clang/Options/Options.td      |  3 +++
 clang/lib/Driver/ToolChains/WebAssembly.cpp | 18 +++++++++++++++---
 clang/test/Driver/wasm-toolchain.c          | 21 ++++++++++++++++++++-
 3 files changed, 38 insertions(+), 4 deletions(-)

diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 37e5c3199a003..2f2ab2f2ba6d8 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2454,6 +2454,9 @@ def fseh_exceptions : Flag<["-"], "fseh-exceptions">, 
Group<f_Group>,
   HelpText<"Use SEH style exceptions">;
 def fwasm_exceptions : Flag<["-"], "fwasm-exceptions">, Group<f_Group>,
   HelpText<"Use WebAssembly style exceptions">;
+def femscripten_exceptions : Flag<["-"], "femscripten-exceptions">,
+  Group<f_Group>,
+  HelpText<"Use Emscripten JavaScript-based C++ exceptions">;
 def exception_model : Separate<["-"], "exception-model">,
   Visibility<[CC1Option]>, HelpText<"The exception model">,
   Values<"dwarf,sjlj,seh,wasm,none">,
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp 
b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 7d5d406df2399..0d3271d31a0b7 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -423,6 +423,10 @@ void WebAssembly::addClangTargetOptions(const ArgList 
&DriverArgs,
       getDriver().Diag(diag::err_drv_argument_not_allowed_with)
           << CurOption << "-mno-reference-types";
 
+    if (DriverArgs.hasArg(options::OPT_femscripten_exceptions))
+      getDriver().Diag(diag::err_drv_argument_not_allowed_with)
+          << CurOption << "-femscripten-exceptions";
+
     for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
       for (const auto *Option :
            {"-enable-emscripten-cxx-exceptions", "-enable-emscripten-sjlj",
@@ -458,12 +462,20 @@ void WebAssembly::addClangTargetOptions(const ArgList 
&DriverArgs,
     CC1Args.push_back("-wasm-enable-eh");
   }
 
+  if (DriverArgs.getLastArg(options::OPT_femscripten_exceptions)) {
+    // Backend needs -enable-emscripten-cxx-exceptions to enable Emscripten EH
+    CC1Args.push_back("-mllvm");
+    CC1Args.push_back("-enable-emscripten-cxx-exceptions");
+  }
+
   for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
     StringRef Opt = A->getValue(0);
     if (Opt.starts_with("-emscripten-cxx-exceptions-allowed")) {
       // '-mllvm -emscripten-cxx-exceptions-allowed' should be used with
-      // '-mllvm -enable-emscripten-cxx-exceptions'
-      bool EmEHArgExists = false;
+      // '-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;
@@ -473,7 +485,7 @@ void WebAssembly::addClangTargetOptions(const ArgList 
&DriverArgs,
       if (!EmEHArgExists)
         getDriver().Diag(diag::err_drv_argument_only_allowed_with)
             << "-mllvm -emscripten-cxx-exceptions-allowed"
-            << "-mllvm -enable-emscripten-cxx-exceptions";
+            << "-femscripten-exceptions";
 
       // Prevent functions specified in -emscripten-cxx-exceptions-allowed list
       // from being inlined before reaching the wasm backend.
diff --git a/clang/test/Driver/wasm-toolchain.c 
b/clang/test/Driver/wasm-toolchain.c
index 467d79e57aff1..083773e8e8197 100644
--- a/clang/test/Driver/wasm-toolchain.c
+++ b/clang/test/Driver/wasm-toolchain.c
@@ -133,7 +133,26 @@
 // 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
-// EMSCRIPTEN_EH_ALLOWED_WO_ENABLE: invalid argument '-mllvm 
-emscripten-cxx-exceptions-allowed' only allowed with '-mllvm 
-enable-emscripten-cxx-exceptions'
+// EMSCRIPTEN_EH_ALLOWED_WO_ENABLE: invalid argument '-mllvm 
-emscripten-cxx-exceptions-allowed' only allowed with '-femscripten-exceptions'
+
+// '-femscripten-exceptions' sets '-mllvm -enable-emscripten-cxx-exceptions'
+// RUN: %clang -### --target=wasm32-unknown-unknown \
+// RUN:    --sysroot=/foo %s -femscripten-exceptions 2>&1 \
+// RUN:  | FileCheck -check-prefix=EMSCRIPTEN_EXCEPTIONS %s
+// EMSCRIPTEN_EXCEPTIONS: "-cc1" {{.*}} "-mllvm" 
"-enable-emscripten-cxx-exceptions"
+
+// '-femscripten-exceptions' satisfies the '-emscripten-cxx-exceptions-allowed'
+// companion requirement.
+// RUN: %clang -### --target=wasm32-unknown-unknown \
+// RUN:    --sysroot=/foo %s -femscripten-exceptions \
+// RUN:    -mllvm -emscripten-cxx-exceptions-allowed=foo,bar 2>&1 \
+// RUN:  | FileCheck -check-prefix=EMSCRIPTEN_EH_ALLOWED_NOINLINE %s
+
+// '-fwasm-exceptions' not allowed with '-femscripten-exceptions'
+// RUN: not %clang -### --target=wasm32-unknown-unknown \
+// RUN:     --sysroot=/foo %s -fwasm-exceptions -femscripten-exceptions 2>&1 \
+// RUN:   | FileCheck -check-prefix=WASM_EXCEPTIONS_FEMSCRIPTEN_EH %s
+// WASM_EXCEPTIONS_FEMSCRIPTEN_EH: invalid argument '-fwasm-exceptions' not 
allowed with '-femscripten-exceptions'
 
 // '-fwasm-exceptions' sets +exception-handling, -multivalue, -reference-types,
 // "-exception-model=wasm", and '-mllvm -wasm-enable-eh'

>From 6143832401f0f3afa86b8f82748867178bf02129 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <[email protected]>
Date: Sat, 5 Sep 2026 15:24:05 +0200
Subject: [PATCH 2/2] WebAssembly: Introduce ExceptionHandling::EmscriptenEH
 model

Add a dedicated EmscriptenEH exception model so the control uses
the standard exception model control, instead of relying on a backend
specific cl::opt. This will later migrate to a module flag and
remove -enable-emscripten-cxx-exceptions

Co-authored-by: Claude (Claude-Opus-4.8) <[email protected]>
---
 clang/include/clang/Basic/CodeGenOptions.h    | 13 +++++++-
 .../clang/Basic/DiagnosticFrontendKinds.td    |  2 +-
 clang/include/clang/Options/Options.td        |  4 +--
 clang/lib/CodeGen/BackendUtil.cpp             |  2 ++
 clang/lib/Driver/ToolChains/Clang.cpp         |  5 ++-
 clang/lib/Driver/ToolChains/WebAssembly.cpp   |  6 ----
 ...asm-exception-model-flag-parse-ir-input.ll |  2 +-
 clang/test/Driver/ir-exception-model.c        |  2 ++
 clang/test/Driver/wasm-toolchain.c            |  6 ++--
 llvm/include/llvm/Support/CodeGen.h           | 15 +++++----
 llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp    |  2 ++
 llvm/lib/CodeGen/CommandFlags.cpp             |  4 ++-
 llvm/lib/CodeGen/TargetPassConfig.cpp         |  3 ++
 llvm/lib/Passes/CodeGenPassBuilder.cpp        |  3 ++
 llvm/lib/Target/WebAssembly/WebAssembly.h     |  6 +++-
 .../WebAssembly/WebAssemblyAsmPrinter.cpp     |  1 +
 .../WebAssemblyCodeGenPassBuilder.cpp         |  9 ++++--
 .../WebAssemblyLowerEmscriptenEHSjLj.cpp      | 17 ++++++----
 .../WebAssembly/WebAssemblyTargetMachine.cpp  | 32 ++++++++++++-------
 .../CodeGen/WebAssembly/eh-option-errors.ll   | 13 +++-----
 20 files changed, 94 insertions(+), 53 deletions(-)

diff --git a/clang/include/clang/Basic/CodeGenOptions.h 
b/clang/include/clang/Basic/CodeGenOptions.h
index 17f367bc02607..8b65a5bc920a5 100644
--- a/clang/include/clang/Basic/CodeGenOptions.h
+++ b/clang/include/clang/Basic/CodeGenOptions.h
@@ -199,7 +199,14 @@ class CodeGenOptions : public CodeGenOptionsBase {
   }
 
   /// Possible exception handling behavior.
-  enum class ExceptionHandlingKind { None, SjLj, WinEH, DwarfCFI, Wasm };
+  enum class ExceptionHandlingKind {
+    None,
+    SjLj,
+    WinEH,
+    DwarfCFI,
+    Wasm,
+    EmscriptenEH
+  };
 
   enum class SwiftAsyncFramePointerKind {
     Auto, // Choose Swift async extended frame info based on deployment target.
@@ -634,6 +641,10 @@ class CodeGenOptions : public CodeGenOptionsBase {
     return getExceptionHandling() == ExceptionHandlingKind::Wasm;
   }
 
+  bool hasEmscriptenExceptions() const {
+    return getExceptionHandling() == ExceptionHandlingKind::EmscriptenEH;
+  }
+
   /// Check if Clang profile instrumenation is on.
   bool hasProfileClangInstr() const {
     return getProfileInstr() ==
diff --git a/clang/include/clang/Basic/DiagnosticFrontendKinds.td 
b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
index a10f10502a702..de38915bd8985 100644
--- a/clang/include/clang/Basic/DiagnosticFrontendKinds.td
+++ b/clang/include/clang/Basic/DiagnosticFrontendKinds.td
@@ -151,7 +151,7 @@ def err_fe_invalid_multiple_actions : Error<
 def err_fe_invalid_alignment : Error<
     "invalid value '%1' in '%0'; alignment must be a power of 2">;
 def err_fe_invalid_exception_model
-   : Error<"invalid exception model '%select{none|sjlj|seh|dwarf|wasm}0' for 
target '%1'">;
+   : Error<"invalid exception model 
'%select{none|sjlj|seh|dwarf|wasm|emscripten}0' for target '%1'">;
 def err_fe_invalid_source_date_epoch : Error<
     "environment variable 'SOURCE_DATE_EPOCH' ('%0') must be a non-negative 
decimal integer <= %1">;
 
diff --git a/clang/include/clang/Options/Options.td 
b/clang/include/clang/Options/Options.td
index 2f2ab2f2ba6d8..60d511c5a71e5 100644
--- a/clang/include/clang/Options/Options.td
+++ b/clang/include/clang/Options/Options.td
@@ -2459,9 +2459,9 @@ def femscripten_exceptions : Flag<["-"], 
"femscripten-exceptions">,
   HelpText<"Use Emscripten JavaScript-based C++ exceptions">;
 def exception_model : Separate<["-"], "exception-model">,
   Visibility<[CC1Option]>, HelpText<"The exception model">,
-  Values<"dwarf,sjlj,seh,wasm,none">,
+  Values<"dwarf,sjlj,seh,wasm,emscripten,none">,
   NormalizedValuesScope<"CodeGenOptions::ExceptionHandlingKind">,
-  NormalizedValues<["DwarfCFI", "SjLj", "WinEH", "Wasm", "None"]>,
+  NormalizedValues<["DwarfCFI", "SjLj", "WinEH", "Wasm", "EmscriptenEH", 
"None"]>,
   MarshallingInfoEnum<CodeGenOpts<"ExceptionHandling">, "None">;
 def exception_model_EQ : Joined<["-"], "exception-model=">,
   Visibility<[CC1Option]>, Alias<exception_model>;
diff --git a/clang/lib/CodeGen/BackendUtil.cpp 
b/clang/lib/CodeGen/BackendUtil.cpp
index ed369d360c48b..d73d1fb497d07 100644
--- a/clang/lib/CodeGen/BackendUtil.cpp
+++ b/clang/lib/CodeGen/BackendUtil.cpp
@@ -419,6 +419,8 @@ static bool initTargetOptions(const CompilerInstance &CI,
     Options.ExceptionModel = llvm::ExceptionHandling::DwarfCFI;
   if (CodeGenOpts.hasWasmExceptions())
     Options.ExceptionModel = llvm::ExceptionHandling::Wasm;
+  if (CodeGenOpts.hasEmscriptenExceptions())
+    Options.ExceptionModel = llvm::ExceptionHandling::EmscriptenEH;
 
   Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS;
 
diff --git a/clang/lib/Driver/ToolChains/Clang.cpp 
b/clang/lib/Driver/ToolChains/Clang.cpp
index ab852bf0e0043..9f426a0f17fcc 100644
--- a/clang/lib/Driver/ToolChains/Clang.cpp
+++ b/clang/lib/Driver/ToolChains/Clang.cpp
@@ -7891,7 +7891,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
   // Handle exception personalities
   Arg *A = Args.getLastArg(
       options::OPT_fsjlj_exceptions, options::OPT_fseh_exceptions,
-      options::OPT_fdwarf_exceptions, options::OPT_fwasm_exceptions);
+      options::OPT_fdwarf_exceptions, options::OPT_fwasm_exceptions,
+      options::OPT_femscripten_exceptions);
   if (A) {
     const Option &Opt = A->getOption();
     if (Opt.matches(options::OPT_fsjlj_exceptions))
@@ -7902,6 +7903,8 @@ void Clang::ConstructJob(Compilation &C, const JobAction 
&JA,
       CmdArgs.push_back("-exception-model=dwarf");
     if (Opt.matches(options::OPT_fwasm_exceptions))
       CmdArgs.push_back("-exception-model=wasm");
+    if (Opt.matches(options::OPT_femscripten_exceptions))
+      CmdArgs.push_back("-exception-model=emscripten");
   } else {
     switch (TC.GetExceptionModel(Args)) {
     default:
diff --git a/clang/lib/Driver/ToolChains/WebAssembly.cpp 
b/clang/lib/Driver/ToolChains/WebAssembly.cpp
index 0d3271d31a0b7..2880f03057ba6 100644
--- a/clang/lib/Driver/ToolChains/WebAssembly.cpp
+++ b/clang/lib/Driver/ToolChains/WebAssembly.cpp
@@ -462,12 +462,6 @@ void WebAssembly::addClangTargetOptions(const ArgList 
&DriverArgs,
     CC1Args.push_back("-wasm-enable-eh");
   }
 
-  if (DriverArgs.getLastArg(options::OPT_femscripten_exceptions)) {
-    // Backend needs -enable-emscripten-cxx-exceptions to enable Emscripten EH
-    CC1Args.push_back("-mllvm");
-    CC1Args.push_back("-enable-emscripten-cxx-exceptions");
-  }
-
   for (const Arg *A : DriverArgs.filtered(options::OPT_mllvm)) {
     StringRef Opt = A->getValue(0);
     if (Opt.starts_with("-emscripten-cxx-exceptions-allowed")) {
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
index 85bfc7f74daed..8263c98670aab 100644
--- 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
@@ -11,7 +11,7 @@
 ; CHECK-LABEL: define void @test(
 
 ; ERR: error: invalid value 'invalid' in '-exception-model=invalid'
-; ERR-BE: fatal error: error in backend: -exception-model should be either 
'none' or 'wasm'
+; ERR-BE: fatal error: error in backend: -exception-model should be either 
'none', 'wasm', or 'emscripten'
 define void @test() {
   ret void
 }
diff --git a/clang/test/Driver/ir-exception-model.c 
b/clang/test/Driver/ir-exception-model.c
index 9e8f998de0d6b..b5d68c644e1b7 100644
--- a/clang/test/Driver/ir-exception-model.c
+++ b/clang/test/Driver/ir-exception-model.c
@@ -1,5 +1,6 @@
 // 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-emscripten -femscripten-exceptions 
-c -S -o - %S/Inputs/file.ll 2>&1 | FileCheck -check-prefix=EMSCRIPTEN %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
@@ -8,6 +9,7 @@
 // Check that -fwasm-exceptions propagates -exception-model to cc1
 
 // CHECK: "-exception-model=wasm"
+// EMSCRIPTEN: "-exception-model=emscripten"
 // DWARF: "-exception-model=dwarf"
 // SJLJ: "-exception-model=sjlj"
 // WINEH: "-exception-model=wineh"
diff --git a/clang/test/Driver/wasm-toolchain.c 
b/clang/test/Driver/wasm-toolchain.c
index 083773e8e8197..665cf4d1a667b 100644
--- a/clang/test/Driver/wasm-toolchain.c
+++ b/clang/test/Driver/wasm-toolchain.c
@@ -123,7 +123,7 @@
 // '-mllvm -emscripten-cxx-exceptions-allowed=foo,bar' sets
 // '-mllvm --force-attribute=foo:noinline -mllvm 
--force-attribute=bar:noinline'
 // RUN: %clang -### --target=wasm32-unknown-unknown \
-// RUN:    --sysroot=/foo %s -mllvm -enable-emscripten-cxx-exceptions \
+// RUN:    --sysroot=/foo %s -femscripten-exceptions \
 // RUN:    -mllvm -emscripten-cxx-exceptions-allowed=foo,bar 2>&1 \
 // RUN:  | FileCheck -check-prefix=EMSCRIPTEN_EH_ALLOWED_NOINLINE %s
 // EMSCRIPTEN_EH_ALLOWED_NOINLINE: "-cc1" {{.*}} "-mllvm" 
"--force-attribute=foo:noinline" "-mllvm" "--force-attribute=bar:noinline"
@@ -135,11 +135,11 @@
 // RUN:   | FileCheck -check-prefix=EMSCRIPTEN_EH_ALLOWED_WO_ENABLE %s
 // EMSCRIPTEN_EH_ALLOWED_WO_ENABLE: invalid argument '-mllvm 
-emscripten-cxx-exceptions-allowed' only allowed with '-femscripten-exceptions'
 
-// '-femscripten-exceptions' sets '-mllvm -enable-emscripten-cxx-exceptions'
+// '-femscripten-exceptions' sets '-exception-model=emscripten'
 // RUN: %clang -### --target=wasm32-unknown-unknown \
 // RUN:    --sysroot=/foo %s -femscripten-exceptions 2>&1 \
 // RUN:  | FileCheck -check-prefix=EMSCRIPTEN_EXCEPTIONS %s
-// EMSCRIPTEN_EXCEPTIONS: "-cc1" {{.*}} "-mllvm" 
"-enable-emscripten-cxx-exceptions"
+// EMSCRIPTEN_EXCEPTIONS: "-cc1" {{.*}} "-exception-model=emscripten"
 
 // '-femscripten-exceptions' satisfies the '-emscripten-cxx-exceptions-allowed'
 // companion requirement.
diff --git a/llvm/include/llvm/Support/CodeGen.h 
b/llvm/include/llvm/Support/CodeGen.h
index e61a36ed42d96..6b1929ebb5c71 100644
--- a/llvm/include/llvm/Support/CodeGen.h
+++ b/llvm/include/llvm/Support/CodeGen.h
@@ -52,13 +52,14 @@ namespace llvm {
   }
 
   enum class ExceptionHandling : int {
-    None,     ///< No exception support
-    DwarfCFI, ///< DWARF-like instruction based exceptions
-    SjLj,     ///< setjmp/longjmp based exceptions
-    ARM,      ///< ARM EHABI
-    WinEH,    ///< Windows Exception Handling
-    Wasm,     ///< WebAssembly Exception Handling
-    AIX,      ///< AIX Exception Handling
+    None,         ///< No exception support
+    DwarfCFI,     ///< DWARF-like instruction based exceptions
+    SjLj,         ///< setjmp/longjmp based exceptions
+    ARM,          ///< ARM EHABI
+    WinEH,        ///< Windows Exception Handling
+    Wasm,         ///< WebAssembly Exception Handling
+    EmscriptenEH, ///< Emscripten JavaScript-based C++ exception handling
+    AIX,          ///< AIX Exception Handling
     ZOS, ///< z/OS MVS Exception Handling. Very similar to DwarfCFI, but the
          ///< PPA1 is used instead of an .eh_frame section.
   };
diff --git a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp 
b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
index 3d06677d1706b..a535d4bb473cc 100644
--- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
+++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp
@@ -669,6 +669,8 @@ bool AsmPrinter::doInitialization(Module &M) {
   EHStreamer *ES = nullptr;
   switch (MAI.getExceptionHandlingType()) {
   case ExceptionHandling::None:
+  case ExceptionHandling::EmscriptenEH:
+    // Emscripten EH is handled in JS glue code and emits no EH tables here.
     if (!usesCFIWithoutEH())
       break;
     [[fallthrough]];
diff --git a/llvm/lib/CodeGen/CommandFlags.cpp 
b/llvm/lib/CodeGen/CommandFlags.cpp
index db149dd938203..6de05e3469cca 100644
--- a/llvm/lib/CodeGen/CommandFlags.cpp
+++ b/llvm/lib/CodeGen/CommandFlags.cpp
@@ -198,7 +198,9 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() {
           clEnumValN(ExceptionHandling::WinEH, "wineh",
                      "Windows exception model"),
           clEnumValN(ExceptionHandling::Wasm, "wasm",
-                     "WebAssembly exception handling")));
+                     "WebAssembly exception handling"),
+          clEnumValN(ExceptionHandling::EmscriptenEH, "emscripten",
+                     "Emscripten JavaScript-based C++ exception handling")));
   CGBINDOPT(ExceptionModel);
 
   static cl::opt<CodeGenFileType> FileType(
diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp 
b/llvm/lib/CodeGen/TargetPassConfig.cpp
index e390db16aa63d..3d8883a8a2049 100644
--- a/llvm/lib/CodeGen/TargetPassConfig.cpp
+++ b/llvm/lib/CodeGen/TargetPassConfig.cpp
@@ -961,6 +961,9 @@ void TargetPassConfig::addPassesToHandleExceptions() {
     addPass(createWasmEHPass());
     break;
   case ExceptionHandling::None:
+  case ExceptionHandling::EmscriptenEH:
+    // Emscripten EH is lowered earlier by WebAssemblyLowerEmscriptenEHSjLj, so
+    // by this point it needs no generic EH preparation, like the None case.
     addPass(createLowerInvokePass());
 
     // The lower invoke pass may create unreachable code. Remove it.
diff --git a/llvm/lib/Passes/CodeGenPassBuilder.cpp 
b/llvm/lib/Passes/CodeGenPassBuilder.cpp
index 63e161965820e..57d4b74c4e24c 100644
--- a/llvm/lib/Passes/CodeGenPassBuilder.cpp
+++ b/llvm/lib/Passes/CodeGenPassBuilder.cpp
@@ -473,6 +473,9 @@ void 
CodeGenPassBuilder::addPassesToHandleExceptions(PassManagerWrapper &PMW) {
     addFunctionPass(WasmEHPreparePass(), PMW);
     break;
   case ExceptionHandling::None:
+  case ExceptionHandling::EmscriptenEH:
+    // Emscripten EH is lowered earlier by WebAssemblyLowerEmscriptenEHSjLj, so
+    // by this point it needs no generic EH preparation, like the None case.
     addFunctionPass(LowerInvokePass(), PMW);
 
     // The lower invoke pass may create unreachable code. Remove it.
diff --git a/llvm/lib/Target/WebAssembly/WebAssembly.h 
b/llvm/lib/Target/WebAssembly/WebAssembly.h
index 94628d0944f8d..e6aefc2ba43e9 100644
--- a/llvm/lib/Target/WebAssembly/WebAssembly.h
+++ b/llvm/lib/Target/WebAssembly/WebAssembly.h
@@ -35,11 +35,15 @@ class FunctionPass;
 // LLVM IR passes.
 class WebAssemblyLowerEmscriptenEHSjLjPass
     : public RequiredPassInfoMixin<WebAssemblyLowerEmscriptenEHSjLjPass> {
+  bool EnableEmEH;
+
 public:
+  WebAssemblyLowerEmscriptenEHSjLjPass(bool EnableEmEH = false)
+      : EnableEmEH(EnableEmEH) {}
   PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
 };
 
-ModulePass *createWebAssemblyLowerEmscriptenEHSjLjLegacyPass();
+ModulePass *createWebAssemblyLowerEmscriptenEHSjLjLegacyPass(bool EnableEmEH);
 
 class WebAssemblyAddMissingPrototypesPass
     : public RequiredPassInfoMixin<WebAssemblyAddMissingPrototypesPass> {
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
index 69a0f97253f3e..d64f03c24b11c 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp
@@ -166,6 +166,7 @@ MCSymbolWasm *WebAssemblyAsmPrinter::getMCSymbolForFunction(
   MCSymbolWasm *WasmSym = nullptr;
 
   const bool EnableEmEH =
+      TM.Options.ExceptionModel == ExceptionHandling::EmscriptenEH ||
       WebAssembly::WasmEnableEmEH || WebAssembly::WasmEnableEmSjLj;
   if (EnableEmEH && isEmscriptenInvokeName(F->getName())) {
     assert(Sig);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
index 7fecb163625cf..653080fd81582 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp
@@ -127,7 +127,10 @@ 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.
-  if (!WasmEnableEmEH && !WasmEnableEH) {
+  bool EnableEmEH =
+      TM.Options.ExceptionModel == ExceptionHandling::EmscriptenEH ||
+      WasmEnableEmEH;
+  if (!EnableEmEH && !WasmEnableEH) {
     addFunctionPass(LowerInvokePass(), PMW);
     // The lower invoke pass may create unreachable code. Remove it in order 
not
     // to process dead blocks in setjmp/longjmp handling.
@@ -138,9 +141,9 @@ void 
WebAssemblyCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) {
   // done in WasmEHPrepare pass, Wasm SjLj preparation shares libraries and
   // transformation algorithms with Emscripten SjLj, so we run
   // LowerEmscriptenEHSjLj pass also when Wasm SjLj is enabled.
-  if (WasmEnableEmEH || WasmEnableEmSjLj || WasmEnableSjLj) {
+  if (EnableEmEH || WasmEnableEmSjLj || WasmEnableSjLj) {
     flushFPMsToMPM(PMW);
-    addModulePass(WebAssemblyLowerEmscriptenEHSjLjPass(), PMW);
+    addModulePass(WebAssemblyLowerEmscriptenEHSjLjPass(EnableEmEH), PMW);
   }
 
   // Expand indirectbr instructions to switches.
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
index cd1ce993a16ed..5894e9b09ffdc 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp
@@ -359,8 +359,9 @@ class WebAssemblyLowerEmscriptenEHSjLjImpl {
 
 public:
   WebAssemblyLowerEmscriptenEHSjLjImpl(
+      bool EnableEmEH,
       std::function<DominatorTree &(Function &F)> GetDominatorTree)
-      : EnableEmEH(WebAssembly::WasmEnableEmEH),
+      : EnableEmEH(EnableEmEH || WebAssembly::WasmEnableEmEH),
         EnableEmSjLj(WebAssembly::WasmEnableEmSjLj),
         EnableWasmSjLj(WebAssembly::WasmEnableSjLj),
         GetDominatorTree(GetDominatorTree) {
@@ -375,6 +376,8 @@ class WebAssemblyLowerEmscriptenEHSjLjImpl {
 };
 
 class WebAssemblyLowerEmscriptenEHSjLjLegacy final : public ModulePass {
+  bool EnableEmEH;
+
   StringRef getPassName() const override {
     return "WebAssembly Lower Emscripten Exceptions";
   }
@@ -382,7 +385,8 @@ class WebAssemblyLowerEmscriptenEHSjLjLegacy final : public 
ModulePass {
 public:
   static char ID;
 
-  WebAssemblyLowerEmscriptenEHSjLjLegacy() : ModulePass(ID) {}
+  WebAssemblyLowerEmscriptenEHSjLjLegacy(bool EnableEmEH = false)
+      : ModulePass(ID), EnableEmEH(EnableEmEH) {}
   bool runOnModule(Module &M) override;
 
   void getAnalysisUsage(AnalysisUsage &AU) const override {
@@ -396,8 +400,9 @@ INITIALIZE_PASS(WebAssemblyLowerEmscriptenEHSjLjLegacy, 
DEBUG_TYPE,
                 "WebAssembly Lower Emscripten Exceptions / Setjmp / Longjmp",
                 false, false)
 
-ModulePass *llvm::createWebAssemblyLowerEmscriptenEHSjLjLegacyPass() {
-  return new WebAssemblyLowerEmscriptenEHSjLjLegacy();
+ModulePass *
+llvm::createWebAssemblyLowerEmscriptenEHSjLjLegacyPass(bool EnableEmEH) {
+  return new WebAssemblyLowerEmscriptenEHSjLjLegacy(EnableEmEH);
 }
 
 static bool canThrow(const Value *V) {
@@ -1871,7 +1876,7 @@ void 
WebAssemblyLowerEmscriptenEHSjLjImpl::handleLongjmpableCallsForWasmSjLj(
 
 bool WebAssemblyLowerEmscriptenEHSjLjLegacy::runOnModule(Module &M) {
   WebAssemblyLowerEmscriptenEHSjLjImpl Impl(
-      [&](Function &F) -> DominatorTree & {
+      EnableEmEH, [&](Function &F) -> DominatorTree & {
         return getAnalysis<DominatorTreeWrapperPass>(F).getDomTree();
       });
   return Impl.runOnModule(M);
@@ -1881,7 +1886,7 @@ PreservedAnalyses
 WebAssemblyLowerEmscriptenEHSjLjPass::run(Module &M,
                                           ModuleAnalysisManager &MAM) {
   WebAssemblyLowerEmscriptenEHSjLjImpl Impl(
-      [&](Function &F) -> DominatorTree & {
+      EnableEmEH, [&](Function &F) -> DominatorTree & {
         return MAM.getResult<FunctionAnalysisManagerModuleProxy>(M)
             .getManager()
             .getResult<DominatorTreeAnalysis>(F);
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp 
b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index 964b67edde3e0..a9a905b6698c0 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -141,18 +141,24 @@ 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::EmscriptenEH ||
+      WasmEnableEmEH;
+
   // You can't enable two modes of EH at the same time
-  if (WasmEnableEmEH && WasmEnableEH)
+  if (EnableEmEH && WasmEnableEH)
     report_fatal_error(
-        "-enable-emscripten-cxx-exceptions not allowed with -wasm-enable-eh");
+        "-exception-model=emscripten not allowed with -wasm-enable-eh");
   // You can't enable two modes of SjLj at the same time
   if (WasmEnableEmSjLj && WasmEnableSjLj)
     report_fatal_error(
         "-enable-emscripten-sjlj not allowed with -wasm-enable-sjlj");
   // You can't mix Emscripten EH with Wasm SjLj.
-  if (WasmEnableEmEH && WasmEnableSjLj)
+  if (EnableEmEH && WasmEnableSjLj)
     report_fatal_error(
-        "-enable-emscripten-cxx-exceptions not allowed with 
-wasm-enable-sjlj");
+        "-exception-model=emscripten not allowed with -wasm-enable-sjlj");
 
   if (TM->Options.ExceptionModel == ExceptionHandling::None) {
     // FIXME: These flags should be removed in favor of directly using the
@@ -163,11 +169,10 @@ static void basicCheckForEHAndSjLj(TargetMachine *TM) {
 
   // Basic Correctness checking related to -exception-model
   if (TM->Options.ExceptionModel != ExceptionHandling::None &&
-      TM->Options.ExceptionModel != ExceptionHandling::Wasm)
-    report_fatal_error("-exception-model should be either 'none' or 'wasm'");
-  if (WasmEnableEmEH && TM->Options.ExceptionModel == ExceptionHandling::Wasm)
-    report_fatal_error("-exception-model=wasm not allowed with "
-                       "-enable-emscripten-cxx-exceptions");
+      TM->Options.ExceptionModel != ExceptionHandling::Wasm &&
+      TM->Options.ExceptionModel != ExceptionHandling::EmscriptenEH)
+    report_fatal_error(
+        "-exception-model should be either 'none', 'wasm', or 'emscripten'");
   if (WasmEnableEH && TM->Options.ExceptionModel != ExceptionHandling::Wasm)
     report_fatal_error(
         "-wasm-enable-eh only allowed with -exception-model=wasm");
@@ -337,7 +342,10 @@ void WebAssemblyPassConfig::addIRPasses() {
   // TargetPassConfig::addPassesToHandleExceptions, but that runs after these 
IR
   // passes and Emscripten SjLj handling expects all invokes to be lowered
   // before.
-  if (!WasmEnableEmEH && !WasmEnableEH) {
+  bool EnableEmEH =
+      TM->Options.ExceptionModel == ExceptionHandling::EmscriptenEH ||
+      WasmEnableEmEH;
+  if (!EnableEmEH && !WasmEnableEH) {
     addPass(createLowerInvokePass());
     // The lower invoke pass may create unreachable code. Remove it in order 
not
     // to process dead blocks in setjmp/longjmp handling.
@@ -348,8 +356,8 @@ void WebAssemblyPassConfig::addIRPasses() {
   // done in WasmEHPrepare pass, Wasm SjLj preparation shares libraries and
   // transformation algorithms with Emscripten SjLj, so we run
   // LowerEmscriptenEHSjLj pass also when Wasm SjLj is enabled.
-  if (WasmEnableEmEH || WasmEnableEmSjLj || WasmEnableSjLj)
-    addPass(createWebAssemblyLowerEmscriptenEHSjLjLegacyPass());
+  if (EnableEmEH || WasmEnableEmSjLj || WasmEnableSjLj)
+    addPass(createWebAssemblyLowerEmscriptenEHSjLjLegacyPass(EnableEmEH));
 
   // Expand indirectbr instructions to switches.
   addPass(createIndirectBrExpandPass());
diff --git a/llvm/test/CodeGen/WebAssembly/eh-option-errors.ll 
b/llvm/test/CodeGen/WebAssembly/eh-option-errors.ll
index 74d02ddc405d3..010c06a2283d5 100644
--- a/llvm/test/CodeGen/WebAssembly/eh-option-errors.ll
+++ b/llvm/test/CodeGen/WebAssembly/eh-option-errors.ll
@@ -1,19 +1,16 @@
 target triple = "wasm32-unknown-unknown"
 
-; RUN: not --crash llc < %s -enable-emscripten-cxx-exceptions -wasm-enable-eh 
2>&1 | FileCheck %s --check-prefix=EM_EH_W_WASM_EH
-; EM_EH_W_WASM_EH: LLVM ERROR: -enable-emscripten-cxx-exceptions not allowed 
with -wasm-enable-eh
+; RUN: not --crash llc < %s -exception-model=emscripten -wasm-enable-eh 2>&1 | 
FileCheck %s --check-prefix=EM_EH_W_WASM_EH
+; EM_EH_W_WASM_EH: LLVM ERROR: -exception-model=emscripten not allowed with 
-wasm-enable-eh
 
 ; RUN: not --crash llc < %s -enable-emscripten-sjlj -wasm-enable-sjlj 2>&1 | 
FileCheck %s --check-prefix=EM_SJLJ_W_WASM_SJLJ
 ; EM_SJLJ_W_WASM_SJLJ: LLVM ERROR: -enable-emscripten-sjlj not allowed with 
-wasm-enable-sjlj
 
-; RUN: not --crash llc < %s -enable-emscripten-cxx-exceptions 
-wasm-enable-sjlj 2>&1 | FileCheck %s --check-prefix=EM_EH_W_WASM_SJLJ
-; EM_EH_W_WASM_SJLJ: LLVM ERROR: -enable-emscripten-cxx-exceptions not allowed 
with -wasm-enable-sjlj
+; RUN: not --crash llc < %s -exception-model=emscripten -wasm-enable-sjlj 2>&1 
| FileCheck %s --check-prefix=EM_EH_W_WASM_SJLJ
+; EM_EH_W_WASM_SJLJ: LLVM ERROR: -exception-model=emscripten not allowed with 
-wasm-enable-sjlj
 
 ; RUN: not --crash llc < %s -wasm-enable-eh -exception-model=dwarf 2>&1 | 
FileCheck %s --check-prefix=EH_MODEL_DWARF
-; EH_MODEL_DWARF: LLVM ERROR: -exception-model should be either 'none' or 
'wasm'
-
-; RUN: not --crash llc < %s -enable-emscripten-cxx-exceptions 
-exception-model=wasm 2>&1 | FileCheck %s --check-prefix=EM_EH_W_MODEL_WASM
-; EM_EH_W_MODEL_WASM: LLVM ERROR: -exception-model=wasm not allowed with 
-enable-emscripten-cxx-exceptions
+; EH_MODEL_DWARF: LLVM ERROR: -exception-model should be either 'none', 
'wasm', or 'emscripten'
 
 ; RUN: not --crash llc < %s -exception-model=wasm 2>&1 | FileCheck %s 
--check-prefix=MODEL_WASM_WO_WASM_EH_SJLJ
 ; MODEL_WASM_WO_WASM_EH_SJLJ: LLVM ERROR: -exception-model=wasm only allowed 
with at least one of -wasm-enable-eh or -wasm-enable-sjlj

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to