summaryrefslogtreecommitdiff
path: root/src/wasm/wasm-s-parser.cpp
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-09-02 09:17:37 -0700
committerGitHub <noreply@github.com>2021-09-02 09:17:37 -0700
commite84980dffb62d672c991960a701a3c7de8f8aa74 (patch)
tree8e130330f04c3cf10702bc24241061f33591b2f9 /src/wasm/wasm-s-parser.cpp
parent4bf2d3bc3da17a28b65222d6e84f6126dcb9c553 (diff)
downloadbinaryen-e84980dffb62d672c991960a701a3c7de8f8aa74.tar.gz
binaryen-e84980dffb62d672c991960a701a3c7de8f8aa74.tar.bz2
binaryen-e84980dffb62d672c991960a701a3c7de8f8aa74.zip
Support specialized function types in element segments (#4109)
Before this, the element segments would be printed as having type funcref, and then if their table had a specialized type, the element type would not be a subtype of the table and validation would fail.
Diffstat (limited to 'src/wasm/wasm-s-parser.cpp')
-rw-r--r--src/wasm/wasm-s-parser.cpp47
1 files changed, 26 insertions, 21 deletions
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index c9c8235e2..c9ca71a6d 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -21,6 +21,7 @@
#include <limits>
#include "ir/branch-utils.h"
+#include "ir/table-utils.h"
#include "shared-constants.h"
#include "support/string.h"
#include "wasm-binary.h"
@@ -3368,6 +3369,11 @@ void SExpressionWasmBuilder::parseElem(Element& s, Table* table) {
segment->table = table->name;
}
+ // We may be post-MVP also due to type reasons or otherwise, as detected by
+ // the utility function for Binaryen IR.
+ usesExpressions =
+ usesExpressions || TableUtils::usesExpressions(segment.get(), &wasm);
+
parseElemFinish(s, segment, i, usesExpressions);
}
@@ -3377,30 +3383,29 @@ ElementSegment* SExpressionWasmBuilder::parseElemFinish(
Index i,
bool usesExpressions) {
- if (usesExpressions) {
- for (; i < s.size(); i++) {
- if (!s[i]->isList()) {
- throw ParseException("expected a ref.* expression.");
- }
- auto& inner = *s[i];
- if (elementStartsWith(inner, ITEM)) {
- if (inner[1]->isList()) {
- // (item (ref.func $f))
- segment->data.push_back(parseExpression(inner[1]));
- } else {
- // (item ref.func $f)
- inner.list().removeAt(0);
- segment->data.push_back(parseExpression(inner));
- }
- } else {
- segment->data.push_back(parseExpression(inner));
- }
- }
- } else {
- for (; i < s.size(); i++) {
+ for (; i < s.size(); i++) {
+ if (!s[i]->isList()) {
+ // An MVP-style declaration: just a function name.
auto func = getFunctionName(*s[i]);
segment->data.push_back(
Builder(wasm).makeRefFunc(func, functionTypes[func]));
+ continue;
+ }
+ if (!usesExpressions) {
+ throw ParseException("expected an MVP-style $funcname in elem.");
+ }
+ auto& inner = *s[i];
+ if (elementStartsWith(inner, ITEM)) {
+ if (inner[1]->isList()) {
+ // (item (ref.func $f))
+ segment->data.push_back(parseExpression(inner[1]));
+ } else {
+ // (item ref.func $f)
+ inner.list().removeAt(0);
+ segment->data.push_back(parseExpression(inner));
+ }
+ } else {
+ segment->data.push_back(parseExpression(inner));
}
}
return wasm.addElementSegment(std::move(segment));