summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/tools/wasm-emscripten-finalize.cpp2
-rw-r--r--src/wasm-emscripten.h3
-rw-r--r--src/wasm/wasm-emscripten.cpp22
3 files changed, 22 insertions, 5 deletions
diff --git a/src/tools/wasm-emscripten-finalize.cpp b/src/tools/wasm-emscripten-finalize.cpp
index f569b54cb..b45b61b8f 100644
--- a/src/tools/wasm-emscripten-finalize.cpp
+++ b/src/tools/wasm-emscripten-finalize.cpp
@@ -207,6 +207,8 @@ int main(int argc, const char* argv[]) {
}
EmscriptenGlueGenerator generator(wasm);
+ generator.setStandalone(standaloneWasm);
+
generator.fixInvokeFunctionNames();
std::vector<Name> initializerFunctions;
diff --git a/src/wasm-emscripten.h b/src/wasm-emscripten.h
index 8aa911ef9..c7689b4bc 100644
--- a/src/wasm-emscripten.h
+++ b/src/wasm-emscripten.h
@@ -31,6 +31,8 @@ public:
: wasm(wasm), builder(wasm), stackPointerOffset(stackPointerOffset),
useStackPointerGlobal(stackPointerOffset == 0) {}
+ void setStandalone(bool standalone_) { standalone = standalone_; }
+
void generateRuntimeFunctions();
Function* generateMemoryGrowthFunction();
Function* generateAssignGOTEntriesFunction();
@@ -69,6 +71,7 @@ private:
Builder builder;
Address stackPointerOffset;
bool useStackPointerGlobal;
+ bool standalone;
// Used by generateDynCallThunk to track all the dynCall functions created
// so far.
std::unordered_set<Signature> sigs;
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index be4e51b9e..f069e558d 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -103,18 +103,25 @@ inline Expression* stackBoundsCheck(Builder& builder,
Expression* value,
Global* stackPointer,
Global* stackLimit,
- Name handler) {
+ Name handlerName) {
// Add a local to store the value of the expression. We need the value twice:
// once to check if it has overflowed, and again to assign to store it.
auto newSP = Builder::addVar(func, stackPointer->type);
+ // If we imported a handler, call it. That can show a nice error in JS.
+ // Otherwise, just trap.
+ Expression* handler;
+ if (handlerName.is()) {
+ handler = builder.makeCall(handlerName, {}, none);
+ } else {
+ handler = builder.makeUnreachable();
+ }
// (if (i32.lt_u (local.tee $newSP (...value...)) (global.get $__stack_limit))
- // (call $handler))
auto check =
builder.makeIf(builder.makeBinary(
BinaryOp::LtUInt32,
builder.makeLocalTee(newSP, value, stackPointer->type),
builder.makeGlobalGet(stackLimit->name, stackLimit->type)),
- builder.makeCall(handler, {}, none));
+ handler);
// (global.set $__stack_pointer (local.get $newSP))
auto newSet = builder.makeGlobalSet(
stackPointer->name, builder.makeLocalGet(newSP, stackPointer->type));
@@ -530,8 +537,7 @@ void EmscriptenGlueGenerator::enforceStackLimit() {
Builder::Mutable);
wasm.addGlobal(stackLimit);
- auto handler = importStackOverflowHandler();
-
+ Name handler = importStackOverflowHandler();
StackLimitEnforcer walker(stackPointer, stackLimit, builder, handler);
PassRunner runner(&wasm);
walker.run(&runner, &wasm);
@@ -549,6 +555,12 @@ void EmscriptenGlueGenerator::generateSetStackLimitFunction() {
}
Name EmscriptenGlueGenerator::importStackOverflowHandler() {
+ // We can call an import to handle stack overflows normally, but not in
+ // standalone mode, where we can't import from JS.
+ if (standalone) {
+ return Name();
+ }
+
ImportInfo info(wasm);
if (auto* existing = info.getImportedFunction(ENV, STACK_OVERFLOW_IMPORT)) {