diff options
author | Alon Zakai <azakai@google.com> | 2020-11-24 12:36:11 -0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-11-24 12:36:11 -0800 |
commit | 78ccc1976bac069ae65b2ec227e8c2c515a02801 (patch) | |
tree | b875343fa47a62a44db4370811080dc963a91233 /src/wasm/wasm-s-parser.cpp | |
parent | cecff82aff317c3132f80a764dba163bcd852a78 (diff) | |
download | binaryen-78ccc1976bac069ae65b2ec227e8c2c515a02801.tar.gz binaryen-78ccc1976bac069ae65b2ec227e8c2c515a02801.tar.bz2 binaryen-78ccc1976bac069ae65b2ec227e8c2c515a02801.zip |
[TypedFunctionReferences] Implement call_ref (#3396)
Includes minimal support in various passes. Also includes actual optimization
work in Directize, which was easy to add.
Almost has fuzzer support, but the actual makeCallRef is just a stub so far.
Includes s-parser support for parsing typed function references types.
Diffstat (limited to 'src/wasm/wasm-s-parser.cpp')
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 96 |
1 files changed, 79 insertions, 17 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 6286ae090..d8d9fa779 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -539,11 +539,11 @@ SExpressionWasmBuilder::parseParamOrLocal(Element& s, size_t& localIndex) { if (s[i]->isStr()) { type = stringToType(s[i]->str()); } else { - if (elementStartsWith(s, PARAM)) { + type = elementToType(*s[i]); + if (elementStartsWith(s, PARAM) && type.isTuple()) { throw ParseException( "params may not have tuple types", s[i]->line, s[i]->col); } - type = elementToType(*s[i]); } namedParams.emplace_back(name, type); } @@ -925,10 +925,48 @@ Type SExpressionWasmBuilder::elementToType(Element& s) { if (s.isStr()) { return stringToType(s.str(), false, false); } - auto& tuple = s.list(); + auto& list = s.list(); + auto size = list.size(); + if (size > 0 && elementStartsWith(s, REF)) { + // It's a reference. It should be in the form + // (ref $name) + // or + // (ref null $name) + // and also $name can be the expanded structure of the type and not a name, + // so something like (ref (func (result i32))), etc. + if (size != 2 && size != 3) { + throw ParseException( + std::string("invalid reference type size"), s.line, s.col); + } + if (size == 3 && *list[1] != NULL_) { + throw ParseException( + std::string("invalid reference type qualifier"), s.line, s.col); + } + bool nullable = false; + size_t i = 1; + if (size == 3) { + nullable = true; + i++; + } + Signature sig; + auto& last = *s[i]; + if (last.isStr()) { + // A string name of a signature. + sig = getFunctionSignature(last); + } else { + // A signature written out in full in-line. + if (*last[0] != FUNC) { + throw ParseException( + std::string("invalid reference type type"), s.line, s.col); + } + sig = parseInlineFunctionSignature(last); + } + return Type(HeapType(sig), nullable); + } + // It's a tuple. std::vector<Type> types; for (size_t i = 0; i < s.size(); ++i) { - types.push_back(stringToType(tuple[i]->str())); + types.push_back(stringToType(list[i]->str())); } return Type(types); } @@ -2026,6 +2064,24 @@ Expression* SExpressionWasmBuilder::makeTupleExtract(Element& s) { return ret; } +Expression* SExpressionWasmBuilder::makeCallRef(Element& s, bool isReturn) { + auto ret = allocator.alloc<CallRef>(); + parseCallOperands(s, 1, s.size() - 1, ret); + ret->target = parseExpression(s[s.size() - 1]); + ret->isReturn = isReturn; + if (!ret->target->type.isRef()) { + throw ParseException("Non-reference type for a call_ref", s.line, s.col); + } + auto heapType = ret->target->type.getHeapType(); + if (!heapType.isSignature()) { + throw ParseException( + "Invalid reference type for a call_ref", s.line, s.col); + } + auto sig = heapType.getSignature(); + ret->finalize(sig.results); + return ret; +} + Expression* SExpressionWasmBuilder::makeI31New(Element& s) { auto ret = allocator.alloc<I31New>(); ret->value = parseExpression(s[1]); @@ -2710,9 +2766,26 @@ void SExpressionWasmBuilder::parseInnerElem(Element& s, wasm.table.segments.push_back(segment); } -void SExpressionWasmBuilder::parseType(Element& s) { +Signature SExpressionWasmBuilder::parseInlineFunctionSignature(Element& s) { + if (*s[0] != FUNC) { + throw ParseException("invalid inline function signature", s.line, s.col); + } std::vector<Type> params; std::vector<Type> results; + for (size_t k = 1; k < s.size(); k++) { + Element& curr = *s[k]; + if (elementStartsWith(curr, PARAM)) { + auto newParams = parseParamOrLocal(curr); + params.insert(params.end(), newParams.begin(), newParams.end()); + } else if (elementStartsWith(curr, RESULT)) { + auto newResults = parseResults(curr); + results.insert(results.end(), newResults.begin(), newResults.end()); + } + } + return Signature(Type(params), Type(results)); +} + +void SExpressionWasmBuilder::parseType(Element& s) { size_t i = 1; if (s[i]->isStr()) { std::string name = s[i]->str().str; @@ -2722,18 +2795,7 @@ void SExpressionWasmBuilder::parseType(Element& s) { signatureIndices[name] = signatures.size(); i++; } - Element& func = *s[i]; - for (size_t k = 1; k < func.size(); k++) { - Element& curr = *func[k]; - if (elementStartsWith(curr, PARAM)) { - auto newParams = parseParamOrLocal(curr); - params.insert(params.end(), newParams.begin(), newParams.end()); - } else if (elementStartsWith(curr, RESULT)) { - auto newResults = parseResults(curr); - results.insert(results.end(), newResults.begin(), newResults.end()); - } - } - signatures.emplace_back(Type(params), Type(results)); + signatures.emplace_back(parseInlineFunctionSignature(*s[i])); } void SExpressionWasmBuilder::parseEvent(Element& s, bool preParseImport) { |