aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp')
-rw-r--r--llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp100
1 files changed, 80 insertions, 20 deletions
diff --git a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
index 746a7599c58c..80abccd74782 100644
--- a/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
+++ b/llvm/lib/Target/WebAssembly/WebAssemblyTargetMachine.cpp
@@ -24,7 +24,7 @@
#include "llvm/CodeGen/RegAllocRegistry.h"
#include "llvm/CodeGen/TargetPassConfig.h"
#include "llvm/IR/Function.h"
-#include "llvm/Support/TargetRegistry.h"
+#include "llvm/MC/TargetRegistry.h"
#include "llvm/Target/TargetOptions.h"
#include "llvm/Transforms/Scalar.h"
#include "llvm/Transforms/Scalar/LowerAtomic.h"
@@ -34,17 +34,27 @@ using namespace llvm;
#define DEBUG_TYPE "wasm"
// Emscripten's asm.js-style exception handling
-cl::opt<bool> EnableEmException(
- "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> EnableEmSjLj(
+cl::opt<bool> WasmEnableEmSjLj(
"enable-emscripten-sjlj",
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
@@ -123,12 +133,14 @@ WebAssemblyTargetMachine::WebAssemblyTargetMachine(
: LLVMTargetMachine(
T,
TT.isArch64Bit()
- ? (TT.isOSEmscripten()
- ? "e-m:e-p:64:64-i64:64-f128:64-n32:64-S128-ni:1:10:20"
- : "e-m:e-p:64:64-i64:64-n32:64-S128-ni:1:10:20")
- : (TT.isOSEmscripten()
- ? "e-m:e-p:32:32-i64:64-f128:64-n32:64-S128-ni:1:10:20"
- : "e-m:e-p:32:32-i64:64-n32:64-S128-ni:1:10:20"),
+ ? (TT.isOSEmscripten() ? "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-"
+ "f128:64-n32:64-S128-ni:1:10:20"
+ : "e-m:e-p:64:64-p10:8:8-p20:8:8-i64:64-"
+ "n32:64-S128-ni:1:10:20")
+ : (TT.isOSEmscripten() ? "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-"
+ "f128:64-n32:64-S128-ni:1:10:20"
+ : "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-"
+ "n32:64-S128-ni:1:10:20"),
TT, CPU, FS, Options, getEffectiveRelocModel(RM, TT),
getEffectiveCodeModel(CM, CodeModel::Large), OL),
TLOF(new WebAssemblyTargetObjectFile()) {
@@ -332,6 +344,7 @@ public:
void addPostRegAlloc() override;
bool addGCPasses() override { return false; }
void addPreEmitPass() override;
+ bool addPreISel() override;
// No reg alloc
bool addRegAssignAndRewriteFast() override { return false; }
@@ -355,6 +368,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.
@@ -381,23 +431,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 (!EnableEmException &&
- 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 (EnableEmException || EnableEmSjLj)
- addPass(createWebAssemblyLowerEmscriptenEHSjLj(EnableEmException,
- EnableEmSjLj));
+ // 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());
@@ -518,6 +572,12 @@ void WebAssemblyPassConfig::addPreEmitPass() {
addPass(createWebAssemblyMCLowerPrePass());
}
+bool WebAssemblyPassConfig::addPreISel() {
+ TargetPassConfig::addPreISel();
+ addPass(createWebAssemblyLowerRefTypesIntPtrConv());
+ return false;
+}
+
yaml::MachineFunctionInfo *
WebAssemblyTargetMachine::createDefaultFuncInfoYAML() const {
return new yaml::WebAssemblyFunctionInfo();