summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-s-parser.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2020-11-24 12:36:11 -0800
committerGitHub <noreply@github.com>2020-11-24 12:36:11 -0800
commit78ccc1976bac069ae65b2ec227e8c2c515a02801 (patch)
treeb875343fa47a62a44db4370811080dc963a91233 /src/wasm/wasm-s-parser.cpp
parentcecff82aff317c3132f80a764dba163bcd852a78 (diff)
downloadbinaryen-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.cpp96
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) {