summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/passes/CMakeLists.txt1
-rw-r--r--src/passes/ReplaceStackPointer.cpp103
-rw-r--r--src/passes/pass.cpp4
-rw-r--r--src/passes/passes.h1
-rw-r--r--src/tools/wasm-emscripten-finalize.cpp4
-rw-r--r--src/wasm-emscripten.h4
-rw-r--r--src/wasm/wasm-emscripten.cpp57
7 files changed, 112 insertions, 62 deletions
diff --git a/src/passes/CMakeLists.txt b/src/passes/CMakeLists.txt
index 654c1c797..a3eede8ff 100644
--- a/src/passes/CMakeLists.txt
+++ b/src/passes/CMakeLists.txt
@@ -61,6 +61,7 @@ set(passes_SOURCES
RemoveImports.cpp
RemoveMemory.cpp
RemoveNonJSOps.cpp
+ ReplaceStackPointer.cpp
RemoveUnusedBrs.cpp
RemoveUnusedNames.cpp
RemoveUnusedModuleElements.cpp
diff --git a/src/passes/ReplaceStackPointer.cpp b/src/passes/ReplaceStackPointer.cpp
new file mode 100644
index 000000000..d6a85c3e2
--- /dev/null
+++ b/src/passes/ReplaceStackPointer.cpp
@@ -0,0 +1,103 @@
+/*
+ * Copyright 2020 WebAssembly Community Group participants
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//
+// Convert llvm's stack pointer usage from from global.get/global.set into
+// cals to external stackSave/stackRestore.
+// This is needed to emscripten SIDE_MODULE code where mutable global imports
+// are not yet permitted by default.
+//
+
+#include "abi/js.h"
+#include "ir/import-utils.h"
+#include "pass.h"
+#include "support/debug.h"
+#include "wasm-emscripten.h"
+
+#define DEBUG_TYPE "binary"
+
+namespace wasm {
+
+static Name STACK_SAVE("stackSave");
+static Name STACK_RESTORE("stackRestore");
+
+struct ReplaceStackPointer
+ : public WalkerPass<PostWalker<ReplaceStackPointer>> {
+ void visitGlobalGet(GlobalGet* curr) {
+ if (getModule()->getGlobalOrNull(curr->name) == stackPointer) {
+ needStackSave = true;
+ if (!builder) {
+ builder = make_unique<Builder>(*getModule());
+ }
+ replaceCurrent(builder->makeCall(STACK_SAVE, {}, Type::i32));
+ }
+ }
+
+ void visitGlobalSet(GlobalSet* curr) {
+ if (getModule()->getGlobalOrNull(curr->name) == stackPointer) {
+ needStackRestore = true;
+ if (!builder) {
+ builder = make_unique<Builder>(*getModule());
+ }
+ replaceCurrent(
+ builder->makeCall(STACK_RESTORE, {curr->value}, Type::none));
+ }
+ }
+
+ void doWalkModule(Module* module) {
+ stackPointer = getStackPointerGlobal(*module);
+ if (!stackPointer) {
+ BYN_DEBUG(std::cerr << "no stack pointer found\n");
+ return;
+ }
+ BYN_DEBUG(std::cerr << "stack pointer found\n");
+ super::doWalkModule(module);
+ if (needStackSave) {
+ ensureFunctionImport(
+ module, STACK_SAVE, Signature(Type::none, Type::i32));
+ }
+ if (needStackRestore) {
+ ensureFunctionImport(
+ module, STACK_RESTORE, Signature(Type::i32, Type::none));
+ }
+ // Finally remove the stack pointer global itself. This avoids importing
+ // a mutable global.
+ module->removeGlobal(stackPointer->name);
+ }
+
+ void ensureFunctionImport(Module* module, Name name, Signature sig) {
+ ImportInfo info(*module);
+ if (info.getImportedFunction(ENV, name)) {
+ return;
+ }
+ auto import = new Function;
+ import->name = name;
+ import->module = ENV;
+ import->base = name;
+ import->sig = sig;
+ module->addFunction(import);
+ }
+
+private:
+ std::unique_ptr<Builder> builder;
+ Global* stackPointer = nullptr;
+ bool needStackSave = false;
+ bool needStackRestore = false;
+};
+
+Pass* createReplaceStackPointerPass() { return new ReplaceStackPointer; }
+
+} // namespace wasm
diff --git a/src/passes/pass.cpp b/src/passes/pass.cpp
index 4b023a46e..78717568e 100644
--- a/src/passes/pass.cpp
+++ b/src/passes/pass.cpp
@@ -285,6 +285,10 @@ void PassRegistry::registerPasses() {
registerPass("rereloop",
"re-optimize control flow using the relooper algorithm",
createReReloopPass);
+ registerPass("replace-stack-pointer",
+ "Replace llvm-generated stack pointer global with calls with "
+ "imported functions.",
+ createReplaceStackPointerPass);
registerPass(
"rse", "remove redundant local.sets", createRedundantSetEliminationPass);
registerPass("roundtrip",
diff --git a/src/passes/passes.h b/src/passes/passes.h
index 7683bf8c6..c844b5acc 100644
--- a/src/passes/passes.h
+++ b/src/passes/passes.h
@@ -95,6 +95,7 @@ Pass* createRemoveUnusedNonFunctionModuleElementsPass();
Pass* createRemoveUnusedNamesPass();
Pass* createReorderFunctionsPass();
Pass* createReorderLocalsPass();
+Pass* createReplaceStackPointerPass();
Pass* createReReloopPass();
Pass* createRedundantSetEliminationPass();
Pass* createRoundTripPass();
diff --git a/src/tools/wasm-emscripten-finalize.cpp b/src/tools/wasm-emscripten-finalize.cpp
index c01fb00bf..a92b0806b 100644
--- a/src/tools/wasm-emscripten-finalize.cpp
+++ b/src/tools/wasm-emscripten-finalize.cpp
@@ -247,7 +247,9 @@ int main(int argc, const char* argv[]) {
if (sideModule) {
BYN_TRACE("finalizing as side module\n");
- generator.replaceStackPointerGlobal();
+ PassRunner passRunner(&wasm);
+ passRunner.add("replace-stack-pointer");
+ passRunner.run();
generator.generatePostInstantiateFunction();
} else {
BYN_TRACE("finalizing as regular module\n");
diff --git a/src/wasm-emscripten.h b/src/wasm-emscripten.h
index 6343c13d7..b541e60b4 100644
--- a/src/wasm-emscripten.h
+++ b/src/wasm-emscripten.h
@@ -44,10 +44,6 @@ public:
// signature in the indirect function table.
void generateDynCallThunks();
- // Convert stack pointer access from global.get/global.set to calling save
- // and restore functions.
- void replaceStackPointerGlobal();
-
// Remove the import of a mutable __stack_pointer and instead initialize the
// stack pointer from an immutable import.
void internalizeStackPointerGlobal();
diff --git a/src/wasm/wasm-emscripten.cpp b/src/wasm/wasm-emscripten.cpp
index 2fcabb3b2..8e0c15aeb 100644
--- a/src/wasm/wasm-emscripten.cpp
+++ b/src/wasm/wasm-emscripten.cpp
@@ -37,8 +37,6 @@ namespace wasm {
cashew::IString EM_ASM_PREFIX("emscripten_asm_const");
cashew::IString EM_JS_PREFIX("__em_js__");
-static Name STACK_SAVE("stackSave");
-static Name STACK_RESTORE("stackRestore");
static Name STACK_INIT("stack$init");
static Name STACK_LIMIT("__stack_limit");
static Name SET_STACK_LIMIT("__set_stack_limit");
@@ -361,47 +359,6 @@ void EmscriptenGlueGenerator::generateDynCallThunks() {
}
}
-struct RemoveStackPointer : public PostWalker<RemoveStackPointer> {
- RemoveStackPointer(Global* stackPointer) : stackPointer(stackPointer) {}
-
- void visitGlobalGet(GlobalGet* curr) {
- if (getModule()->getGlobalOrNull(curr->name) == stackPointer) {
- needStackSave = true;
- if (!builder) {
- builder = make_unique<Builder>(*getModule());
- }
- replaceCurrent(builder->makeCall(STACK_SAVE, {}, Type::i32));
- }
- }
-
- void visitGlobalSet(GlobalSet* curr) {
- if (getModule()->getGlobalOrNull(curr->name) == stackPointer) {
- needStackRestore = true;
- if (!builder) {
- builder = make_unique<Builder>(*getModule());
- }
- replaceCurrent(
- builder->makeCall(STACK_RESTORE, {curr->value}, Type::none));
- }
- }
-
- void visitModule(Module* curr) {
- if (needStackSave) {
- ensureFunctionImport(curr, STACK_SAVE, Signature(Type::none, Type::i32));
- }
- if (needStackRestore) {
- ensureFunctionImport(
- curr, STACK_RESTORE, Signature(Type::i32, Type::none));
- }
- }
-
-private:
- std::unique_ptr<Builder> builder;
- Global* stackPointer;
- bool needStackSave = false;
- bool needStackRestore = false;
-};
-
// lld can sometimes produce a build with an imported mutable __stack_pointer
// (i.e. when linking with -fpie). This method internalizes the
// __stack_pointer and initializes it from an immutable global instead.
@@ -428,20 +385,6 @@ void EmscriptenGlueGenerator::internalizeStackPointerGlobal() {
wasm.addGlobal(sp);
}
-void EmscriptenGlueGenerator::replaceStackPointerGlobal() {
- Global* stackPointer = getStackPointerGlobal(wasm);
- if (!stackPointer) {
- return;
- }
-
- // Replace all uses of stack pointer global
- RemoveStackPointer(stackPointer).walkModule(&wasm);
-
- // Finally remove the stack pointer global itself. This avoids importing
- // a mutable global.
- wasm.removeGlobal(stackPointer->name);
-}
-
struct StackLimitEnforcer : public WalkerPass<PostWalker<StackLimitEnforcer>> {
StackLimitEnforcer(Global* stackPointer,
Global* stackLimit,