#include "abi/js.h"
#include "ir/import-utils.h"
#include "pass.h"
#include "support/debug.h"
#include "wasm-emscripten.h"
#define DEBUG_TYPE "replace-stack-pointer"
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));
}
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; }
}