diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm-s-parser.h | 53 | ||||
-rw-r--r-- | src/wasm.h | 8 |
2 files changed, 49 insertions, 12 deletions
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h index 8f62c8af8..750d485fb 100644 --- a/src/wasm-s-parser.h +++ b/src/wasm-s-parser.h @@ -312,21 +312,49 @@ private: } functionNames.push_back(name); functionCounter++; + FunctionType* type = nullptr; + functionTypes[name] = none; + std::vector<WasmType> params; for (;i < s.size(); i++) { Element& curr = *s[i]; IString id = curr[0]->str(); if (id == RESULT) { functionTypes[name] = stringToWasmType(curr[1]->str()); - return; } else if (id == TYPE) { Name typeName = curr[1]->str(); if (!wasm.checkFunctionType(typeName)) throw ParseException("unknown function"); - FunctionType* type = wasm.getFunctionType(typeName); + type = wasm.getFunctionType(typeName); functionTypes[name] = type->result; - return; + } else if (id == PARAM && curr.size() > 1) { + Index j = 1; + if (curr[j]->dollared()) { + // dollared input symbols cannot be types + params.push_back(stringToWasmType(curr[j + 1]->str(), true)); + } else { + while (j < curr.size()) { + params.push_back(stringToWasmType(curr[j++]->str(), true)); + } + } + } + } + if (!type) { + // if no function type provided, generate one, but reuse a previous one with the + // right structure if there is one. + // see https://github.com/WebAssembly/spec/pull/301 + bool need = true; + std::unique_ptr<FunctionType> functionType = make_unique<FunctionType>(); + functionType->result = functionTypes[name]; + functionType->params = std::move(params); + for (auto& existing : wasm.functionTypes) { + if (existing->structuralComparison(*functionType)) { + need = false; + break; + } + } + if (need) { + wasm.addFunctionType(functionType.release()); } } - functionTypes[name] = none; } void preParseImports(Element& curr) { @@ -500,16 +528,21 @@ private: body = allocator.alloc<Nop>(); } if (currFunction->result != result) throw ParseException("bad func declaration", s.line, s.col); - /* TODO: spec in flux, https://github.com/WebAssembly/spec/pull/301 + // see https://github.com/WebAssembly/spec/pull/301 if (type.isNull()) { - // if no function type provided, generate a private one for this function - auto* functionType = sigToFunctionType(getSig(currFunction.get())); - wasm.addFunctionType(functionType); - type = functionType->name; + // if no function type name provided, then we generated one + std::unique_ptr<FunctionType> functionType = std::unique_ptr<FunctionType>(sigToFunctionType(getSig(currFunction.get()))); + for (auto& existing : wasm.functionTypes) { + if (existing->structuralComparison(*functionType)) { + type = existing->name; + break; + } + } + if (!type.is()) throw ParseException("no function type [internal error?]", s.line, s.col); } - */ currFunction->body = body; currFunction->type = type; + wasm.addFunction(currFunction.release()); currLocalTypes.clear(); labelStack.clear(); diff --git a/src/wasm.h b/src/wasm.h index 5c1baaf09..38a030e1a 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1065,8 +1065,7 @@ public: FunctionType() : result(none) {} - bool operator==(FunctionType& b) { - if (name != b.name) return false; // XXX + bool structuralComparison(FunctionType& b) { if (result != b.result) return false; if (params.size() != b.params.size()) return false; for (size_t i = 0; i < params.size(); i++) { @@ -1074,6 +1073,11 @@ public: } return true; } + + bool operator==(FunctionType& b) { + if (name != b.name) return false; + return structuralComparison(b); + } bool operator!=(FunctionType& b) { return !(*this == b); } |