summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/asm_v_wasm.h2
-rw-r--r--src/s2wasm.h53
-rw-r--r--src/wasm-builder.h28
3 files changed, 62 insertions, 21 deletions
diff --git a/src/asm_v_wasm.h b/src/asm_v_wasm.h
index 29344e9bb..6a279a2a7 100644
--- a/src/asm_v_wasm.h
+++ b/src/asm_v_wasm.h
@@ -82,7 +82,7 @@ std::string getSig(CallBase *call) {
return ret;
}
-std::string getSig(WasmType result, ExpressionList& operands) {
+std::string getSig(WasmType result, const ExpressionList& operands) {
std::string ret;
ret += getSig(result);
for (auto operand : operands) {
diff --git a/src/s2wasm.h b/src/s2wasm.h
index 9bdc4961d..2963af2fe 100644
--- a/src/s2wasm.h
+++ b/src/s2wasm.h
@@ -27,6 +27,7 @@
#include "parsing.h"
#include "pass.h"
#include "asm_v_wasm.h"
+#include "wasm-builder.h"
#include "wasm-printing.h"
namespace wasm {
@@ -558,9 +559,11 @@ class S2WasmBuilder {
auto getNextId = [&nextId]() {
return cashew::IString(('$' + std::to_string(nextId++)).c_str(), false);
};
+ wasm::Builder builder(wasm);
+ std::vector<NameType> params;
+ WasmType resultType = none;
+ std::vector<NameType> locals;
- auto func = allocator.alloc<Function>();
- func->name = name;
std::map<Name, WasmType> localTypes;
// params and result
while (1) {
@@ -568,24 +571,26 @@ class S2WasmBuilder {
while (1) {
Name name = getNextId();
WasmType type = getType();
- func->params.emplace_back(name, type);
+ params.emplace_back(name, type);
localTypes[name] = type;
skipWhitespace();
if (!match(",")) break;
}
} else if (match(".result")) {
- func->result = getType();
+ resultType = getType();
} else if (match(".local")) {
while (1) {
Name name = getNextId();
WasmType type = getType();
- func->locals.emplace_back(name, type);
+ locals.emplace_back(name, type);
localTypes[name] = type;
skipWhitespace();
if (!match(",")) break;
}
} else break;
}
+ Function* func = builder.makeFunction(name, std::move(params), resultType, std::move(locals));
+
// parse body
func->body = allocator.alloc<Block>();
std::vector<Expression*> bstack;
@@ -772,17 +777,17 @@ class S2WasmBuilder {
auto makeCall = [&](WasmType type) {
if (match("_indirect")) {
// indirect call
- auto indirect = allocator.alloc<CallIndirect>();
Name assign = getAssign();
int num = getNumInputs();
auto inputs = getInputs(num);
- indirect->target = inputs[0];
- indirect->type = type;
- for (int i = 1; i < num; i++) {
- indirect->operands.push_back(inputs[i]);
- }
+ auto input = inputs.begin();
+ auto* target = *input;
+ std::vector<Expression*> operands(++input, inputs.end());
+ auto* funcType = ensureFunctionType(getSig(type, operands), &wasm, allocator);
+ assert(type == funcType->result);
+ auto* indirect = builder.makeCallIndirect(funcType, target, std::move(operands));
setOutput(indirect, assign);
- indirect->fullType = wasm.getFunctionType(ensureFunctionType(getSig(indirect), &wasm, allocator)->name);
+
} else {
// non-indirect call
CallBase* curr;
@@ -1057,11 +1062,7 @@ class S2WasmBuilder {
curr->type = curr->value->type;
setOutput(curr, assign);
} else if (match("return")) {
- auto curr = allocator.alloc<Return>();
- if (*s == '$') {
- curr->value = getInput();
- }
- addToBlock(curr);
+ addToBlock(builder.makeReturn(*s == '$' ? getInput() : nullptr));
} else if (match("unreachable")) {
addToBlock(allocator.alloc<Unreachable>());
} else if (match("memory_size")) {
@@ -1248,6 +1249,22 @@ class S2WasmBuilder {
wasm.addExport(exp);
}
+ void getDyncallThunk(const std::string& sig) {
+ // hard-code the sig for testing for now. vi is the signature for static destructors
+ assert(sig == "vi");
+ auto* targetType = ensureFunctionType(sig, &wasm, wasm.allocator);
+ wasm::Builder wasmBuilder(wasm);
+ std::vector<NameType> params {{"$0", i32}, {"$1", i32}};
+ Function* f = wasmBuilder.makeFunction(std::string("dynCall_") + sig, std::move(params), none, {});
+ auto* call = wasmBuilder.makeCallIndirect(
+ targetType,
+ wasmBuilder.makeGetLocal(params[0].name, params[0].type),
+ {wasmBuilder.makeGetLocal(params[1].name, params[1].type)});
+ auto* ret = wasmBuilder.makeReturn(call);
+ f->body = ret;
+ wasm.addFunction(f);
+ }
+
void fix() {
// The minimum initial memory size is the amount of static variables we have
// allocated. Round it up to a page, and update the page-increment versions
@@ -1270,7 +1287,7 @@ class S2WasmBuilder {
for (Name name : globls) exportFunction(name, false);
for (Name name : initializerFunctions) exportFunction(name, true);
- auto ensureFunctionIndex = [&](Name name) {
+ auto ensureFunctionIndex = [this](Name name) {
if (functionIndexes.count(name) == 0) {
functionIndexes[name] = wasm.table.names.size();
wasm.table.names.push_back(name);
diff --git a/src/wasm-builder.h b/src/wasm-builder.h
index de3371274..22f713939 100644
--- a/src/wasm-builder.h
+++ b/src/wasm-builder.h
@@ -27,6 +27,18 @@ class Builder {
public:
Builder(AllocatingModule& wasm) : allocator(wasm.allocator) {}
+ Function* makeFunction(Name name,
+ std::vector<NameType>&& params,
+ WasmType resultType,
+ std::vector<NameType>&& locals) {
+ auto* func = allocator.alloc<Function>();
+ func->name = name;
+ func->params = params;
+ func->result = resultType;
+ func->locals = locals;
+ return func;
+ }
+
// Nop TODO: add all the rest
// Block
If* makeIf(Expression* condition, Expression* ifTrue, Expression* ifFalse=nullptr) {
@@ -41,6 +53,15 @@ public:
// CallBase
// Call
// CallImport
+ // Also do a version which takes a sig?
+ CallIndirect* makeCallIndirect(FunctionType* type, Expression* target, std::vector<Expression*>&& args) {
+ auto* call = allocator.alloc<CallIndirect>();
+ call->fullType = type;
+ call->type = type->result;
+ call->target = target;
+ call->operands = args;
+ return call;
+ }
// FunctionType
GetLocal* makeGetLocal(Name name, WasmType type) {
auto* ret = allocator.alloc<GetLocal>();
@@ -104,7 +125,11 @@ public:
return ret;
}
// Select
- // Return
+ Return* makeReturn(Expression *value) {
+ auto* ret = allocator.alloc<Return>();
+ ret->value = value;
+ return ret;
+ }
// Host
// Unreachable
@@ -113,4 +138,3 @@ public:
} // namespace wasm
#endif // wasm_builder_h
-