#ifndef wasm_abi_stack_h
#define wasm_abi_stack_h
#include "asmjs/shared-constants.h"
#include "ir/find_all.h"
#include "ir/global-utils.h"
#include "shared-constants.h"
#include "wasm-builder.h"
#include "wasm-emscripten.h"
#include "wasm.h"
namespace wasm {
namespace ABI {
enum { StackAlign = 16 };
inline Index stackAlign(Index size) {
return (size + StackAlign - 1) & -StackAlign;
}
inline void
getStackSpace(Index local, Function* func, Index size, Module& wasm) {
auto* stackPointer = getStackPointerGlobal(wasm);
if (!stackPointer) {
Fatal() << "getStackSpace: failed to find the stack pointer";
}
size = stackAlign(size);
auto pointerType =
!wasm.memories.empty() ? wasm.memories[0]->indexType : Type::i32;
Builder builder(wasm);
auto* block = builder.makeBlock();
Expression* added;
if (pointerType == Type::i32) {
added =
builder.makeBinary(SubInt32,
builder.makeGlobalGet(stackPointer->name, pointerType),
builder.makeConst(int32_t(size)));
} else {
WASM_UNREACHABLE("unhandled pointerType");
}
block->list.push_back(builder.makeGlobalSet(
stackPointer->name, builder.makeLocalTee(local, added, pointerType)));
auto makeStackRestore = [&]() {
return builder.makeGlobalSet(
stackPointer->name,
builder.makeBinary(AddInt32,
builder.makeLocalGet(local, pointerType),
builder.makeConst(int32_t(size))));
};
FindAllPointers<Return> finder(func->body);
for (auto** ptr : finder.list) {
auto* ret = (*ptr)->cast<Return>();
if (ret->value && ret->value->type != Type::unreachable) {
auto* block = builder.makeBlock();
auto temp = builder.addVar(func, ret->value->type);
block->list.push_back(builder.makeLocalSet(temp, ret->value));
block->list.push_back(makeStackRestore());
block->list.push_back(
builder.makeReturn(builder.makeLocalGet(temp, ret->value->type)));
block->finalize();
*ptr = block;
} else {
*ptr = builder.makeSequence(makeStackRestore(), ret);
}
}
if (func->body->type == Type::none) {
block->list.push_back(func->body);
block->list.push_back(makeStackRestore());
} else if (func->body->type == Type::unreachable) {
block->list.push_back(func->body);
} else {
auto temp = builder.addVar(func, func->getResults());
block->list.push_back(builder.makeLocalSet(temp, func->body));
block->list.push_back(makeStackRestore());
block->list.push_back(builder.makeLocalGet(temp, func->getResults()));
}
block->finalize();
func->body = block;
}
}
}
#endif