diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/asm_v_wasm.h | 2 | ||||
-rw-r--r-- | src/s2wasm.h | 53 | ||||
-rw-r--r-- | src/wasm-builder.h | 28 |
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 - |