summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-emscripten.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/wasm/wasm-emscripten.cpp')
-rw-r--r--src/wasm/wasm-emscripten.cpp71
1 files changed, 63 insertions, 8 deletions
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index 14104c1eb..a43fc1fe7 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -25,6 +25,7 @@
#include "wasm-traversal.h"
#include "wasm.h"
#include "ir/function-type-utils.h"
+#include "ir/import-utils.h"
#include "ir/module-utils.h"
namespace wasm {
@@ -32,7 +33,10 @@ namespace wasm {
cashew::IString EMSCRIPTEN_ASM_CONST("emscripten_asm_const");
cashew::IString EM_JS_PREFIX("__em_js__");
-static constexpr const char* dummyFunction = "__wasm_nullptr";
+static Name STACK_SAVE("stackSave"),
+ STACK_RESTORE("stackRestore"),
+ STACK_ALLOC("stackAlloc"),
+ DUMMY_FUNC("__wasm_nullptr");
void addExportedFunction(Module& wasm, Function* function) {
wasm.addFunction(function);
@@ -80,10 +84,9 @@ Expression* EmscriptenGlueGenerator::generateStoreStackPointer(Expression* value
}
void EmscriptenGlueGenerator::generateStackSaveFunction() {
- Name name("stackSave");
std::vector<NameType> params { };
Function* function = builder.makeFunction(
- name, std::move(params), i32, {}
+ STACK_SAVE, std::move(params), i32, {}
);
function->body = generateLoadStackPointer();
@@ -92,10 +95,9 @@ void EmscriptenGlueGenerator::generateStackSaveFunction() {
}
void EmscriptenGlueGenerator::generateStackAllocFunction() {
- Name name("stackAlloc");
std::vector<NameType> params { { "0", i32 } };
Function* function = builder.makeFunction(
- name, std::move(params), i32, { { "1", i32 } }
+ STACK_ALLOC, std::move(params), i32, { { "1", i32 } }
);
Expression* loadStack = generateLoadStackPointer();
GetLocal* getSizeArg = builder.makeGetLocal(0, i32);
@@ -118,10 +120,9 @@ void EmscriptenGlueGenerator::generateStackAllocFunction() {
}
void EmscriptenGlueGenerator::generateStackRestoreFunction() {
- Name name("stackRestore");
std::vector<NameType> params { { "0", i32 } };
Function* function = builder.makeFunction(
- name, std::move(params), none, {}
+ STACK_RESTORE, std::move(params), none, {}
);
GetLocal* getArg = builder.makeGetLocal(0, i32);
Expression* store = generateStoreStackPointer(getArg);
@@ -182,7 +183,7 @@ void EmscriptenGlueGenerator::generateDynCallThunks() {
tableSegmentData = wasm.table.segments[0].data;
}
for (const auto& indirectFunc : tableSegmentData) {
- if (indirectFunc == dummyFunction) {
+ if (indirectFunc == DUMMY_FUNC) {
continue;
}
std::string sig = getSig(wasm.getFunction(indirectFunc));
@@ -207,6 +208,60 @@ void EmscriptenGlueGenerator::generateDynCallThunks() {
}
}
+static Function* ensureFunctionImport(Module* module, Name name, std::string sig) {
+ // Then see if its already imported
+ ImportInfo info(*module);
+ if (Function* f = info.getImportedFunction(ENV, name)) {
+ return f;
+ }
+ // Failing that create a new function import.
+ auto import = new Function;
+ import->name = name;
+ import->module = ENV;
+ import->base = name;
+ auto* functionType = ensureFunctionType(sig, module);
+ import->type = functionType->name;
+ FunctionTypeUtils::fillFunction(import, functionType);
+ module->addFunction(import);
+ return import;
+}
+
+struct RemoveStackPointer : public PostWalker<RemoveStackPointer> {
+ RemoveStackPointer(Global* StackPointer) : StackPointer(StackPointer) {}
+
+ void visitGetGlobal(GetGlobal* curr) {
+ if (getModule()->getGlobalOrNull(curr->name) == StackPointer) {
+ ensureFunctionImport(getModule(), STACK_SAVE, "i");
+ if (!builder) builder = make_unique<Builder>(*getModule());
+ replaceCurrent(builder->makeCall(STACK_SAVE, {}, i32));
+ }
+ }
+
+ void visitSetGlobal(SetGlobal* curr) {
+ if (getModule()->getGlobalOrNull(curr->name) == StackPointer) {
+ ensureFunctionImport(getModule(), STACK_RESTORE, "vi");
+ if (!builder) builder = make_unique<Builder>(*getModule());
+ replaceCurrent(builder->makeCall(STACK_RESTORE, {curr->value}, none));
+ }
+ }
+
+private:
+ std::unique_ptr<Builder> builder;
+ Global* StackPointer;
+};
+
+void EmscriptenGlueGenerator::replaceStackPointerGlobal() {
+ Global* stackPointer = getStackPointerGlobal();
+
+ // Replace all uses of stack pointer global
+ RemoveStackPointer walker(stackPointer);
+ walker.walkModule(&wasm);
+
+ // Finally remove the stack pointer global itself. This avoids importing
+ // a mutable global.
+ wasm.removeGlobal(stackPointer->name);
+}
+
struct JSCallWalker : public PostWalker<JSCallWalker> {
Module &wasm;
JSCallWalker(Module &_wasm) : wasm(_wasm) {