https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/221443
>From c90321a6400d1eb168fc2ba03abe0dcd5f11c9ac Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Sat, 5 Sep 2026 15:24:05 +0200 Subject: [PATCH 1/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 32b12beba880b..c0c89c691683a 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -2460,9 +2460,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 9d8fd319f6f17..dcc77f7aa4d58 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -404,6 +404,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 e445e61f8a23f..9009ce7ec9556 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 23ae184105f8d..b683fcd506a44 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 22b168597be99..a6c276a6a15b2 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 5440e1a3cdbae..ef0f74a1cf802 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 8410c10843bd4..56f191a5972e6 100644 --- a/llvm/lib/CodeGen/CommandFlags.cpp +++ b/llvm/lib/CodeGen/CommandFlags.cpp @@ -195,7 +195,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 c21d6386ea15d..eb58ff53bee4b 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) { @@ -1868,7 +1873,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); @@ -1878,7 +1883,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 >From 178e6dd3fe35dc2143de18dca4de651f5e578b46 Mon Sep 17 00:00:00 2001 From: Matt Arsenault <[email protected]> Date: Mon, 14 Sep 2026 14:35:57 +0200 Subject: [PATCH 2/2] Rename enum --- clang/include/clang/Basic/CodeGenOptions.h | 4 ++-- clang/include/clang/Options/Options.td | 2 +- clang/lib/CodeGen/BackendUtil.cpp | 2 +- llvm/include/llvm/Support/CodeGen.h | 2 +- llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp | 2 +- llvm/lib/CodeGen/CommandFlags.cpp | 4 ++-- llvm/lib/CodeGen/TargetPassConfig.cpp | 2 +- llvm/lib/Passes/CodeGenPassBuilder.cpp | 2 +- llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp | 2 +- .../Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp | 2 +- llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp | 6 +++--- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/clang/include/clang/Basic/CodeGenOptions.h b/clang/include/clang/Basic/CodeGenOptions.h index 8b65a5bc920a5..4632d79cd551a 100644 --- a/clang/include/clang/Basic/CodeGenOptions.h +++ b/clang/include/clang/Basic/CodeGenOptions.h @@ -205,7 +205,7 @@ class CodeGenOptions : public CodeGenOptionsBase { WinEH, DwarfCFI, Wasm, - EmscriptenEH + Emscripten }; enum class SwiftAsyncFramePointerKind { @@ -642,7 +642,7 @@ class CodeGenOptions : public CodeGenOptionsBase { } bool hasEmscriptenExceptions() const { - return getExceptionHandling() == ExceptionHandlingKind::EmscriptenEH; + return getExceptionHandling() == ExceptionHandlingKind::Emscripten; } /// Check if Clang profile instrumenation is on. diff --git a/clang/include/clang/Options/Options.td b/clang/include/clang/Options/Options.td index c0c89c691683a..c109b385350f3 100644 --- a/clang/include/clang/Options/Options.td +++ b/clang/include/clang/Options/Options.td @@ -2462,7 +2462,7 @@ def exception_model : Separate<["-"], "exception-model">, Visibility<[CC1Option]>, HelpText<"The exception model">, Values<"dwarf,sjlj,seh,wasm,emscripten,none">, NormalizedValuesScope<"CodeGenOptions::ExceptionHandlingKind">, - NormalizedValues<["DwarfCFI", "SjLj", "WinEH", "Wasm", "EmscriptenEH", "None"]>, + NormalizedValues<["DwarfCFI", "SjLj", "WinEH", "Wasm", "Emscripten", "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 dcc77f7aa4d58..fc6ff147a41a4 100644 --- a/clang/lib/CodeGen/BackendUtil.cpp +++ b/clang/lib/CodeGen/BackendUtil.cpp @@ -405,7 +405,7 @@ static bool initTargetOptions(const CompilerInstance &CI, if (CodeGenOpts.hasWasmExceptions()) Options.ExceptionModel = llvm::ExceptionHandling::Wasm; if (CodeGenOpts.hasEmscriptenExceptions()) - Options.ExceptionModel = llvm::ExceptionHandling::EmscriptenEH; + Options.ExceptionModel = llvm::ExceptionHandling::Emscripten; Options.NoZerosInBSS = CodeGenOpts.NoZeroInitializedInBSS; diff --git a/llvm/include/llvm/Support/CodeGen.h b/llvm/include/llvm/Support/CodeGen.h index a6c276a6a15b2..40b4dc98d19ba 100644 --- a/llvm/include/llvm/Support/CodeGen.h +++ b/llvm/include/llvm/Support/CodeGen.h @@ -58,7 +58,7 @@ namespace llvm { ARM, ///< ARM EHABI WinEH, ///< Windows Exception Handling Wasm, ///< WebAssembly Exception Handling - EmscriptenEH, ///< Emscripten JavaScript-based C++ exception handling + Emscripten, ///< Emscripten JavaScript-based 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 ef0f74a1cf802..5ca684a2c016c 100644 --- a/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp +++ b/llvm/lib/CodeGen/AsmPrinter/AsmPrinter.cpp @@ -669,7 +669,7 @@ bool AsmPrinter::doInitialization(Module &M) { EHStreamer *ES = nullptr; switch (MAI.getExceptionHandlingType()) { case ExceptionHandling::None: - case ExceptionHandling::EmscriptenEH: + case ExceptionHandling::Emscripten: // Emscripten EH is handled in JS glue code and emits no EH tables here. if (!usesCFIWithoutEH()) break; diff --git a/llvm/lib/CodeGen/CommandFlags.cpp b/llvm/lib/CodeGen/CommandFlags.cpp index 56f191a5972e6..cdd286b562163 100644 --- a/llvm/lib/CodeGen/CommandFlags.cpp +++ b/llvm/lib/CodeGen/CommandFlags.cpp @@ -196,8 +196,8 @@ codegen::RegisterCodeGenFlags::RegisterCodeGenFlags() { "Windows exception model"), clEnumValN(ExceptionHandling::Wasm, "wasm", "WebAssembly exception handling"), - clEnumValN(ExceptionHandling::EmscriptenEH, "emscripten", - "Emscripten JavaScript-based C++ exception handling"))); + clEnumValN(ExceptionHandling::Emscripten, "emscripten", + "Emscripten JavaScript-based exception handling"))); CGBINDOPT(ExceptionModel); static cl::opt<CodeGenFileType> FileType( diff --git a/llvm/lib/CodeGen/TargetPassConfig.cpp b/llvm/lib/CodeGen/TargetPassConfig.cpp index 3d8883a8a2049..75fba01042c8d 100644 --- a/llvm/lib/CodeGen/TargetPassConfig.cpp +++ b/llvm/lib/CodeGen/TargetPassConfig.cpp @@ -961,7 +961,7 @@ void TargetPassConfig::addPassesToHandleExceptions() { addPass(createWasmEHPass()); break; case ExceptionHandling::None: - case ExceptionHandling::EmscriptenEH: + case ExceptionHandling::Emscripten: // Emscripten EH is lowered earlier by WebAssemblyLowerEmscriptenEHSjLj, so // by this point it needs no generic EH preparation, like the None case. addPass(createLowerInvokePass()); diff --git a/llvm/lib/Passes/CodeGenPassBuilder.cpp b/llvm/lib/Passes/CodeGenPassBuilder.cpp index 57d4b74c4e24c..e67377d7c6b3d 100644 --- a/llvm/lib/Passes/CodeGenPassBuilder.cpp +++ b/llvm/lib/Passes/CodeGenPassBuilder.cpp @@ -473,7 +473,7 @@ void CodeGenPassBuilder::addPassesToHandleExceptions(PassManagerWrapper &PMW) { addFunctionPass(WasmEHPreparePass(), PMW); break; case ExceptionHandling::None: - case ExceptionHandling::EmscriptenEH: + case ExceptionHandling::Emscripten: // Emscripten EH is lowered earlier by WebAssemblyLowerEmscriptenEHSjLj, so // by this point it needs no generic EH preparation, like the None case. addFunctionPass(LowerInvokePass(), PMW); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index d64f03c24b11c..5929b0f77359c 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -166,7 +166,7 @@ MCSymbolWasm *WebAssemblyAsmPrinter::getMCSymbolForFunction( MCSymbolWasm *WasmSym = nullptr; const bool EnableEmEH = - TM.Options.ExceptionModel == ExceptionHandling::EmscriptenEH || + TM.Options.ExceptionModel == ExceptionHandling::Emscripten || 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 653080fd81582..82f7fdd2b7079 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyCodeGenPassBuilder.cpp @@ -128,7 +128,7 @@ void WebAssemblyCodeGenPassBuilder::addIRPasses(PassManagerWrapper &PMW) { // passes and Emscripten SjLj handling expects all invokes to be lowered // before. bool EnableEmEH = - TM.Options.ExceptionModel == ExceptionHandling::EmscriptenEH || + TM.Options.ExceptionModel == ExceptionHandling::Emscripten || WasmEnableEmEH; if (!EnableEmEH && !WasmEnableEH) { addFunctionPass(LowerInvokePass(), PMW); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp index a9a905b6698c0..61a14c852ca4b 100644 --- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -144,7 +144,7 @@ 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 || + TM->Options.ExceptionModel == ExceptionHandling::Emscripten || WasmEnableEmEH; // You can't enable two modes of EH at the same time @@ -170,7 +170,7 @@ static void basicCheckForEHAndSjLj(TargetMachine *TM) { // Basic Correctness checking related to -exception-model if (TM->Options.ExceptionModel != ExceptionHandling::None && TM->Options.ExceptionModel != ExceptionHandling::Wasm && - TM->Options.ExceptionModel != ExceptionHandling::EmscriptenEH) + TM->Options.ExceptionModel != ExceptionHandling::Emscripten) report_fatal_error( "-exception-model should be either 'none', 'wasm', or 'emscripten'"); if (WasmEnableEH && TM->Options.ExceptionModel != ExceptionHandling::Wasm) @@ -343,7 +343,7 @@ void WebAssemblyPassConfig::addIRPasses() { // passes and Emscripten SjLj handling expects all invokes to be lowered // before. bool EnableEmEH = - TM->Options.ExceptionModel == ExceptionHandling::EmscriptenEH || + TM->Options.ExceptionModel == ExceptionHandling::Emscripten || WasmEnableEmEH; if (!EnableEmEH && !WasmEnableEH) { addPass(createLowerInvokePass()); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
