diff --git a/llvm/lib/Target/WebAssembly/WebAssembly.h b/llvm/lib/Target/WebAssembly/WebAssembly.h --- a/llvm/lib/Target/WebAssembly/WebAssembly.h +++ b/llvm/lib/Target/WebAssembly/WebAssembly.h @@ -25,8 +25,7 @@ class FunctionPass; // LLVM IR passes. -ModulePass *createWebAssemblyLowerEmscriptenEHSjLj(bool EnableEH, - bool EnableSjLj); +ModulePass *createWebAssemblyLowerEmscriptenEHSjLj(); ModulePass *createWebAssemblyLowerGlobalDtors(); ModulePass *createWebAssemblyAddMissingPrototypes(); ModulePass *createWebAssemblyFixFunctionBitcasts(); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyLowerEmscriptenEHSjLj.cpp @@ -205,6 +205,13 @@ #define DEBUG_TYPE "wasm-lower-em-ehsjlj" +// Emscripten's asm.js-style exception handling +extern cl::opt WasmEnableEmException; +// Emscripten's asm.js-style setjmp/longjmp handling +extern cl::opt WasmEnableEmSjLj; +// Wasm setjmp/longjmp handling using wasm EH +extern cl::opt WasmEnableSjLj; + static cl::list EHAllowlist("emscripten-cxx-exceptions-allowed", cl::desc("The list of function names in which Emscripten-style " @@ -214,9 +221,10 @@ namespace { class WebAssemblyLowerEmscriptenEHSjLj final : public ModulePass { - bool EnableEmEH; // Enable Emscripten exception handling - bool EnableEmSjLj; // Enable Emscripten setjmp/longjmp handling - bool DoSjLj; // Whether we actually perform setjmp/longjmp handling + bool EnableEmEH; // Enable Emscripten exception handling + bool EnableEmSjLj; // Enable Emscripten setjmp/longjmp handling + bool EnableWasmSjLj; // Enable Wasm setjmp/longjmp handling + bool DoSjLj; // Whether we actually perform setjmp/longjmp handling GlobalVariable *ThrewGV = nullptr; // __THREW__ (Emscripten) GlobalVariable *ThrewValueGV = nullptr; // __threwValue (Emscripten) @@ -263,9 +271,13 @@ public: static char ID; - WebAssemblyLowerEmscriptenEHSjLj(bool EnableEmEH = true, - bool EnableEmSjLj = true) - : ModulePass(ID), EnableEmEH(EnableEmEH), EnableEmSjLj(EnableEmSjLj) { + WebAssemblyLowerEmscriptenEHSjLj() + : ModulePass(ID), EnableEmEH(WasmEnableEmException), + EnableEmSjLj(WasmEnableEmSjLj), EnableWasmSjLj(WasmEnableSjLj) { + // Two SjLj modes cannot be turned on at the same time + assert(!(EnableEmSjLj && EnableWasmSjLj)); + // Wasm SjLj should be only used with Wasm EH + assert(!(EnableEmEH && EnableWasmSjLj)); EHAllowlistSet.insert(EHAllowlist.begin(), EHAllowlist.end()); } bool runOnModule(Module &M) override; @@ -281,9 +293,8 @@ "WebAssembly Lower Emscripten Exceptions / Setjmp / Longjmp", false, false) -ModulePass *llvm::createWebAssemblyLowerEmscriptenEHSjLj(bool EnableEmEH, - bool EnableEmSjLj) { - return new WebAssemblyLowerEmscriptenEHSjLj(EnableEmEH, EnableEmSjLj); +ModulePass *llvm::createWebAssemblyLowerEmscriptenEHSjLj() { + return new WebAssemblyLowerEmscriptenEHSjLj(); } static bool canThrow(const Value *V) { @@ -709,10 +720,6 @@ assert(TPC && "Expected a TargetPassConfig"); auto &TM = TPC->getTM(); - if (EnableEmEH && TM.Options.ExceptionModel == ExceptionHandling::Wasm) - report_fatal_error("-exception-model=wasm not allowed with " - "-enable-emscripten-cxx-exceptions"); - // Declare (or get) global variables __THREW__, __threwValue, and // getTempRet0/setTempRet0 function which are used in common for both // exception handling and setjmp/longjmp handling @@ -759,6 +766,7 @@ // Function registration and data pre-gathering for setjmp/longjmp handling if (DoSjLj) { + assert(EnableEmSjLj || EnableWasmSjLj); // Register emscripten_longjmp function FunctionType *FTy = FunctionType::get( IRB.getVoidTy(), {getAddrIntType(&M), IRB.getInt32Ty()}, false); @@ -1010,6 +1018,7 @@ } bool WebAssemblyLowerEmscriptenEHSjLj::runSjLjOnFunction(Function &F) { + assert(EnableEmSjLj || EnableWasmSjLj); Module &M = *F.getParent(); LLVMContext &C = F.getContext(); IRBuilder<> IRB(C); diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp --- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp +++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp @@ -45,6 +45,11 @@ cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"), cl::init(false)); +// Wasm setjmp/longjmp handling using wasm EH +cl::opt WasmEnableSjLj("wasm-enable-sjlj", + cl::desc("WebAssembly setjmp/longjmp handling"), + cl::init(false)); + // A command-line option to keep implicit locals // for the purpose of testing with lit/llc ONLY. // This produces output which is not valid WebAssembly, and is not supported @@ -382,6 +387,21 @@ if (getOptLevel() != CodeGenOpt::None) addPass(createWebAssemblyOptimizeReturned()); + // Exception & setjmp/longjmp options sanity check + if (TM->Options.ExceptionModel != ExceptionHandling::None && + TM->Options.ExceptionModel != ExceptionHandling::Wasm) + report_fatal_error("-exception-model should be either 'none' of 'wasm'"); + if (WasmEnableEmException && + TM->Options.ExceptionModel == ExceptionHandling::Wasm) + report_fatal_error("-exception-model=wasm not allowed with " + "-enable-emscripten-cxx-exceptions"); + if (WasmEnableEmSjLj && WasmEnableSjLj) + report_fatal_error( + "-enable-emscripten-sjlj not allowed with -wasm-enable-sjlj"); + if (WasmEnableSjLj && TM->Options.ExceptionModel != ExceptionHandling::Wasm) + report_fatal_error( + "-wasm-enable-sjlj only allowed with -exception-model=wasm"); + // If exception handling is not enabled and setjmp/longjmp handling is // enabled, we lower invokes into calls and delete unreachable landingpad // blocks. Lowering invokes when there is no EH support is done in @@ -396,9 +416,8 @@ } // Handle exceptions and setjmp/longjmp if enabled. - if (WasmEnableEmException || WasmEnableEmSjLj) - addPass(createWebAssemblyLowerEmscriptenEHSjLj(WasmEnableEmException, - WasmEnableEmSjLj)); + if (WasmEnableEmException || WasmEnableEmSjLj || WasmEnableSjLj) + addPass(createWebAssemblyLowerEmscriptenEHSjLj()); // Expand indirectbr instructions to switches. addPass(createIndirectBrExpandPass()); diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll --- a/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-ehsjlj.ll @@ -1,5 +1,5 @@ -; RUN: opt < %s -wasm-lower-em-ehsjlj -S | FileCheck %s -; RUN: llc < %s -verify-machineinstrs +; RUN: opt < %s -wasm-lower-em-ehsjlj -enable-emscripten-cxx-exceptions -enable-emscripten-sjlj -S | FileCheck %s +; RUN: llc < %s -enable-emscripten-cxx-exceptions -enable-emscripten-sjlj -verify-machineinstrs ; Tests for cases when exception handling and setjmp/longjmp handling are mixed. diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-exceptions-allowed.ll b/llvm/test/CodeGen/WebAssembly/lower-em-exceptions-allowed.ll --- a/llvm/test/CodeGen/WebAssembly/lower-em-exceptions-allowed.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-exceptions-allowed.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -wasm-lower-em-ehsjlj -emscripten-cxx-exceptions-allowed=do_catch -S | FileCheck %s +; RUN: opt < %s -wasm-lower-em-ehsjlj -enable-emscripten-cxx-exceptions -emscripten-cxx-exceptions-allowed=do_catch -S | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-exceptions-resume-only.ll b/llvm/test/CodeGen/WebAssembly/lower-em-exceptions-resume-only.ll --- a/llvm/test/CodeGen/WebAssembly/lower-em-exceptions-resume-only.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-exceptions-resume-only.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -wasm-lower-em-ehsjlj -S | FileCheck %s +; RUN: opt < %s -wasm-lower-em-ehsjlj -enable-emscripten-cxx-exceptions -S | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll b/llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll --- a/llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-exceptions.ll @@ -1,6 +1,6 @@ -; RUN: opt < %s -wasm-lower-em-ehsjlj -S | FileCheck %s --check-prefixes=CHECK,NO-TLS -DPTR=i32 -; RUN: opt < %s -wasm-lower-em-ehsjlj -S --mattr=+atomics,+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS -DPTR=i32 -; RUN: opt < %s -wasm-lower-em-ehsjlj --mtriple=wasm64-unknown-unknown -data-layout="e-m:e-p:64:64-i64:64-n32:64-S128" -S | FileCheck %s --check-prefixes=CHECK -DPTR=i64 +; RUN: opt < %s -wasm-lower-em-ehsjlj -enable-emscripten-cxx-exceptions -S | FileCheck %s --check-prefixes=CHECK,NO-TLS -DPTR=i32 +; RUN: opt < %s -wasm-lower-em-ehsjlj -enable-emscripten-cxx-exceptions -S --mattr=+atomics,+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS -DPTR=i32 +; RUN: opt < %s -wasm-lower-em-ehsjlj -enable-emscripten-cxx-exceptions --mtriple=wasm64-unknown-unknown -data-layout="e-m:e-p:64:64-i64:64-n32:64-S128" -S | FileCheck %s --check-prefixes=CHECK -DPTR=i64 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll --- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-alias.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -wasm-lower-em-ehsjlj -S | FileCheck %s +; RUN: opt < %s -wasm-lower-em-ehsjlj -enable-emscripten-sjlj -S | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-emscripten" diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll --- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj-debuginfo.ll @@ -1,4 +1,4 @@ -; RUN: opt < %s -wasm-lower-em-ehsjlj -S | FileCheck %s +; RUN: opt < %s -wasm-lower-em-ehsjlj -enable-emscripten-sjlj -S | FileCheck %s target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" diff --git a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll --- a/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll +++ b/llvm/test/CodeGen/WebAssembly/lower-em-sjlj.ll @@ -1,6 +1,6 @@ -; RUN: opt < %s -wasm-lower-em-ehsjlj -S | FileCheck %s --check-prefixes=CHECK,NO-TLS -DPTR=i32 -; RUN: opt < %s -wasm-lower-em-ehsjlj -S --mattr=+atomics,+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS -DPTR=i32 -; RUN: opt < %s -wasm-lower-em-ehsjlj --mtriple=wasm64-unknown-unknown -data-layout="e-m:e-p:64:64-i64:64-n32:64-S128" -S | FileCheck %s --check-prefixes=CHECK -DPTR=i64 +; RUN: opt < %s -wasm-lower-em-ehsjlj -enable-emscripten-sjlj -S | FileCheck %s --check-prefixes=CHECK,NO-TLS -DPTR=i32 +; RUN: opt < %s -wasm-lower-em-ehsjlj -enable-emscripten-sjlj -S --mattr=+atomics,+bulk-memory | FileCheck %s --check-prefixes=CHECK,TLS -DPTR=i32 +; RUN: opt < %s -wasm-lower-em-ehsjlj -enable-emscripten-sjlj --mtriple=wasm64-unknown-unknown -data-layout="e-m:e-p:64:64-i64:64-n32:64-S128" -S | FileCheck %s --check-prefixes=CHECK -DPTR=i64 target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" target triple = "wasm32-unknown-unknown" @@ -279,10 +279,7 @@ attributes #3 = { allocsize(0) } ; CHECK-DAG: attributes #{{[0-9]+}} = { nounwind "wasm-import-module"="env" "wasm-import-name"="getTempRet0" } ; CHECK-DAG: attributes #{{[0-9]+}} = { nounwind "wasm-import-module"="env" "wasm-import-name"="setTempRet0" } -; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="__resumeException" } -; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="llvm_eh_typeid_for" } ; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="__invoke_void" } -; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="__cxa_find_matching_catch_2" } ; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="saveSetjmp" } ; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="testSetjmp" } ; CHECK-DAG: attributes #{{[0-9]+}} = { "wasm-import-module"="env" "wasm-import-name"="emscripten_longjmp" }