aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
diff options
context:
space:
mode:
authorHeejin Ahn <aheejin@gmail.com>2021-08-06 19:35:18 -0700
committerHeejin Ahn <aheejin@gmail.com>2021-08-24 17:54:39 -0700
commit77b921b870aacfd531ff449166937e0de6a377bc (patch)
tree9cc289af8baa3b712d88906092bc1eb1db0b9447 /llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
parentcea5ab090b5e4e8ee06a9230b73e74c1230c1c54 (diff)
downloadllvm-77b921b870aacfd531ff449166937e0de6a377bc.zip
llvm-77b921b870aacfd531ff449166937e0de6a377bc.tar.gz
llvm-77b921b870aacfd531ff449166937e0de6a377bc.tar.bz2
[WebAssembly] Tidy up EH/SjLj options
This CL is small, but the description can be a little long because I'm trying to sum up the status quo for Emscripten/Wasm EH/SjLj options. First, this CL adds an option for Wasm SjLj (`-wasm-enable-sjlj`), which handles SjLj using Wasm EH. The implementation for this will be added as a followup CL, but this adds the option first to do error checking. This also adds an option for Wasm EH (`-wasm-enable-eh`), which has been already implemented. Before we used `-exception-model=wasm` as the same meaning as enabling Wasm EH, but after we add Wasm SjLj, it will be possible to use Wasm EH instructions for Wasm SjLj while not enabling EH, so going forward, to use Wasm EH, `opt` and `llc` will need this option. This only affects `opt` and `llc` command lines and does not affect Emscripten user interface. Now we have two modes of EH (Emscripten/Wasm) and also two modes of SjLj (also Emscripten/Wasm). The options corresponding to each of are: - Emscripten EH: `-enable-emscripten-cxx-exceptions` - Emscripten SjLj: `-enable-emscripten-sjlj` - Wasm EH: `-wasm-enable-eh -exception-model=wasm` `-mattr=+exception-handling` - Wasm SjLj: `-wasm-enable-sjlj -exception-model=wasm` `-mattr=+exception-handling` The reason Wasm EH/SjLj's options are a little complicated are `-exception-model` and `-mattr` are common LLVM options ane not under our control. (`-mattr` can be omitted if it is embedded within the bitcode file.) And we have the following rules of the option composition: - Emscripten EH and Wasm EH cannot be turned on at the same itme - Emscripten SjLj and Wasm SjLj cannot be turned on at the same time - Wasm SjLj should be used with Wasm EH Which means we now allow these combinations: - Emscripten EH + Emscripten SjLj: the current default in `emcc` - Wasm EH + Emscripten SjLj: This is allowed, but only as an interim step in which we are testing Wasm EH but not yet have a working implementation of Wasm SjLj. This will error out (D107687) in compile time if `setjmp` is called in a function in which Wasm exception is used. - Wasm EH + Wasm SjLj: This will be the default mode later when using Wasm EH. Currently Wasm SjLj implementation doesn't exist, so it doesn't work. - Emscripten EH + Wasm SjLj will not work. This CL moves these error checking routines to `WebAssemblyPassConfig::addIRPasses`. Not sure if this is an ideal place to do this, but I couldn't find elsewhere. Currently some checking is done within LowerEmscriptenEHSjLj, but these checks only run if LowerEmscriptenEHSjLj runs so it may not run when Wasm EH is used. This moves that to `addIRPasses` and adds some more checks. Currently LowerEmscriptenEHSjLj pass is responsible for Emscripten EH and Emscripten SjLj. Wasm EH transformations are done in multiple places, including WasmEHPrepare, LateEHPrepare, and CFGStackify. But in the followup CL, LowerEmscriptenEHSjLj pass will be also responsible for a part of Wasm SjLj transformation, because WasmSjLj will also be using several Emscripten library functions, and we will be sharing more than half of the transformation to do that between Emscripten SjLj and Wasm SjLj. Currently we have `-enable-emscripten-cxx-exceptions` and `-enable-emscripten-sjlj` but these only work for `llc`, because for `llc` we feed these options to the pass but when we run the pass using `opt` the pass will be created with no options and the default options will be used, which turns both Emscripten EH and Emscripten SjLj on. Now we have one more SjLj option to care for, LowerEmscriptenEHSjLj pass needs a finer way to control these options. This CL removes those default parameters and make LowerEmscriptenEHSjLj pass read directly from command line options specified. So if we only run `opt -wasm-lower-em-ehsjlj`, currently both Emscripten EH and Emscripten SjLj will run, but with this CL, none will run unless we additionally pass `-enable-emscripten-cxx-exceptions` or `-enable-emscripten-sjlj`, or both. This does not affect users; this only affects our `opt` tests because `emcc` will not call either `opt` or `llc`. As a result of this, our existing Emscripten EH/SjLj tests gained one or both of those options in their `RUN` lines. Reviewed By: dschuff Differential Revision: https://reviews.llvm.org/D107685
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp75
1 files changed, 63 insertions, 12 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index f98e9bf0..01b7aad 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -34,10 +34,10 @@ using namespace llvm;
#define DEBUG_TYPE "wasm"
// Emscripten's asm.js-style exception handling
-cl::opt<bool> WasmEnableEmException(
- "enable-emscripten-cxx-exceptions",
- cl::desc("WebAssembly Emscripten-style exception handling"),
- cl::init(false));
+cl::opt<bool>
+ 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> WasmEnableEmSjLj(
@@ -45,6 +45,16 @@ cl::opt<bool> WasmEnableEmSjLj(
cl::desc("WebAssembly Emscripten-style setjmp/longjmp handling"),
cl::init(false));
+// Exception handling using wasm EH instructions
+cl::opt<bool> WasmEnableEH("wasm-enable-eh",
+ cl::desc("WebAssembly exception handling"),
+ cl::init(false));
+
+// setjmp/longjmp handling using wasm EH instrutions
+cl::opt<bool> 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
@@ -356,6 +366,43 @@ FunctionPass *WebAssemblyPassConfig::createTargetRegisterAllocator(bool) {
return nullptr; // No reg alloc
}
+static void checkSanityForEHAndSjLj(const TargetMachine *TM) {
+ // Sanity 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");
+ if (WasmEnableEH && TM->Options.ExceptionModel != ExceptionHandling::Wasm)
+ report_fatal_error(
+ "-wasm-enable-eh only allowed with -exception-model=wasm");
+ if (WasmEnableSjLj && TM->Options.ExceptionModel != ExceptionHandling::Wasm)
+ report_fatal_error(
+ "-wasm-enable-sjlj only allowed with -exception-model=wasm");
+ if ((!WasmEnableEH && !WasmEnableSjLj) &&
+ TM->Options.ExceptionModel == ExceptionHandling::Wasm)
+ report_fatal_error(
+ "-exception-model=wasm only allowed with at least one of "
+ "-wasm-enable-eh or -wasm-enable-sjj");
+
+ // You can't enable two modes of EH at the same time
+ if (WasmEnableEmEH && WasmEnableEH)
+ report_fatal_error(
+ "-enable-emscripten-cxx-exceptions 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)
+ report_fatal_error(
+ "-enable-emscripten-cxx-exceptions not allowed with -wasm-enable-sjlj");
+ // Currently it is allowed to mix Wasm EH with Emscripten SjLj as an interim
+ // measure, but some code will error out at compile time in this combination.
+ // See WebAssemblyLowerEmscriptenEHSjLj pass for details.
+}
+
//===----------------------------------------------------------------------===//
// The following functions are called from lib/CodeGen/Passes.cpp to modify
// the CodeGen pass sequence.
@@ -382,23 +429,27 @@ void WebAssemblyPassConfig::addIRPasses() {
if (getOptLevel() != CodeGenOpt::None)
addPass(createWebAssemblyOptimizeReturned());
+ checkSanityForEHAndSjLj(TM);
+
// 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
- // TargetPassConfig::addPassesToHandleExceptions, but this runs after this
- // function and SjLj handling expects all invokes to be lowered before.
- if (!WasmEnableEmException &&
- TM->Options.ExceptionModel == ExceptionHandling::None) {
+ // TargetPassConfig::addPassesToHandleExceptions, but that runs after these IR
+ // passes and Emscripten SjLj handling expects all invokes to be lowered
+ // before.
+ if (!WasmEnableEmEH && !WasmEnableEH) {
addPass(createLowerInvokePass());
// The lower invoke pass may create unreachable code. Remove it in order not
// to process dead blocks in setjmp/longjmp handling.
addPass(createUnreachableBlockEliminationPass());
}
- // Handle exceptions and setjmp/longjmp if enabled.
- if (WasmEnableEmException || WasmEnableEmSjLj)
- addPass(createWebAssemblyLowerEmscriptenEHSjLj(WasmEnableEmException,
- WasmEnableEmSjLj));
+ // Handle exceptions and setjmp/longjmp if enabled. Unlike Wasm EH preparation
+ // 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(createWebAssemblyLowerEmscriptenEHSjLj());
// Expand indirectbr instructions to switches.
addPass(createIndirectBrExpandPass());