diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/tools/wasm-emscripten-finalize.cpp | 2 | ||||
-rw-r--r-- | src/wasm-emscripten.h | 3 | ||||
-rw-r--r-- | src/wasm/wasm-emscripten.cpp | 22 |
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)) { |