summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlon Zakai <azakai@google.com>2021-03-03 19:53:26 +0000
committerGitHub <noreply@github.com>2021-03-03 11:53:26 -0800
commit11ec03ce930121736655769b9bbccaae0280b64c (patch)
tree969ca4dc33027f8054789103c908906f5c00cf6c
parenta5e5be42cf32e0232ef7a4c3bce67c289623eea6 (diff)
downloadbinaryen-11ec03ce930121736655769b9bbccaae0280b64c.tar.gz
binaryen-11ec03ce930121736655769b9bbccaae0280b64c.tar.bz2
binaryen-11ec03ce930121736655769b9bbccaae0280b64c.zip
[Wasm GC] Parse text field names even of types that end up canonicalized together (#3647)
Names of structurally identical types end up "collapsed" together after the types are canonicalized, but with this PR we can properly read content that has structurally identical types with different names.
-rw-r--r--src/wasm-s-parser.h10
-rw-r--r--src/wasm/wasm-s-parser.cpp27
-rw-r--r--test/heap-types.wast10
-rw-r--r--test/heap-types.wast.from-wast5
-rw-r--r--test/heap-types.wast.fromBinary5
-rw-r--r--test/heap-types.wast.fromBinary.noDebugInfo5
6 files changed, 46 insertions, 16 deletions
diff --git a/src/wasm-s-parser.h b/src/wasm-s-parser.h
index 9fb9d4389..6ccc7c36c 100644
--- a/src/wasm-s-parser.h
+++ b/src/wasm-s-parser.h
@@ -137,6 +137,14 @@ class SExpressionWasmBuilder {
std::map<Name, Signature> functionSignatures;
std::unordered_map<cashew::IString, Index> debugInfoFileIndices;
+ // Maps type indexes to a mapping of field index => name. This is not the same
+ // as the field names stored on the wasm object, as that maps types after
+ // their canonicalization. Canonicalization loses information, which means
+ // that structurally identical types cannot have different names. However,
+ // while parsing the text format we keep this mapping of type indexes to names
+ // which does allow reading such content.
+ std::unordered_map<size_t, std::unordered_map<Index, Name>> fieldNames;
+
public:
// Assumes control of and modifies the input.
SExpressionWasmBuilder(Module& wasm, Element& module, IRProfile profile);
@@ -272,7 +280,7 @@ private:
Expression* makeRttCanon(Element& s);
Expression* makeRttSub(Element& s);
Expression* makeStructNew(Element& s, bool default_);
- Index getStructIndex(const HeapType& type, Element& s);
+ Index getStructIndex(Element& type, Element& field);
Expression* makeStructGet(Element& s, bool signed_ = false);
Expression* makeStructSet(Element& s);
Expression* makeArrayNew(Element& s, bool default_);
diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp
index 0b0f3f407..3baf19063 100644
--- a/src/wasm/wasm-s-parser.cpp
+++ b/src/wasm/wasm-s-parser.cpp
@@ -786,10 +786,6 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) {
builder.getTempTupleType(results));
};
- // Maps type indexes to a mapping of field index => name. We store the data
- // here while parsing as types have not been created yet.
- std::unordered_map<size_t, std::unordered_map<Index, Name>> fieldNames;
-
// Parses a field, and notes the name if one is found.
auto parseField = [&](Element* elem, Name& name) {
Mutability mutable_ = Immutable;
@@ -2610,27 +2606,28 @@ Expression* SExpressionWasmBuilder::makeStructNew(Element& s, bool default_) {
return Builder(wasm).makeStructNew(rtt, operands);
}
-Index SExpressionWasmBuilder::getStructIndex(const HeapType& type, Element& s) {
- if (s.dollared()) {
- auto name = s.str();
- auto struct_ = type.getStruct();
+Index SExpressionWasmBuilder::getStructIndex(Element& type, Element& field) {
+ if (field.dollared()) {
+ auto name = field.str();
+ auto index = typeIndices[type.str().str];
+ auto struct_ = types[index].getStruct();
auto& fields = struct_.fields;
- const auto& fieldNames = wasm.typeNames[type].fieldNames;
+ const auto& names = fieldNames[index];
for (Index i = 0; i < fields.size(); i++) {
- auto it = fieldNames.find(i);
- if (it != fieldNames.end() && it->second == name) {
+ auto it = names.find(i);
+ if (it != names.end() && it->second == name) {
return i;
}
}
- throw ParseException("bad struct field name", s.line, s.col);
+ throw ParseException("bad struct field name", field.line, field.col);
}
// this is a numeric index
- return atoi(s.c_str());
+ return atoi(field.c_str());
}
Expression* SExpressionWasmBuilder::makeStructGet(Element& s, bool signed_) {
auto heapType = parseHeapType(*s[1]);
- auto index = getStructIndex(heapType, *s[2]);
+ auto index = getStructIndex(*s[1], *s[2]);
auto type = heapType.getStruct().fields[index].type;
auto ref = parseExpression(*s[3]);
validateHeapTypeUsingChild(ref, heapType, s);
@@ -2639,7 +2636,7 @@ Expression* SExpressionWasmBuilder::makeStructGet(Element& s, bool signed_) {
Expression* SExpressionWasmBuilder::makeStructSet(Element& s) {
auto heapType = parseHeapType(*s[1]);
- auto index = getStructIndex(heapType, *s[2]);
+ auto index = getStructIndex(*s[1], *s[2]);
auto ref = parseExpression(*s[3]);
validateHeapTypeUsingChild(ref, heapType, s);
auto value = parseExpression(*s[4]);
diff --git a/test/heap-types.wast b/test/heap-types.wast
index 84490d031..364d1b0a3 100644
--- a/test/heap-types.wast
+++ b/test/heap-types.wast
@@ -6,6 +6,13 @@
(field f32)
(field $named f64)
))
+ ;; identical to $struct.A, so will be canonicalized with it, but field names
+ ;; are different
+ (type $struct.A.prime (struct
+ i32
+ (field f32)
+ (field $othername f64)
+ ))
(type $struct.B (struct
(field i8)
(field (mut i16))
@@ -52,6 +59,9 @@
(struct.get $struct.A $named (local.get $x))
)
(drop
+ (struct.get $struct.A.prime $othername (ref.null $struct.A.prime))
+ )
+ (drop
(struct.get_u $struct.B 0 (local.get $tB))
)
(drop
diff --git a/test/heap-types.wast.from-wast b/test/heap-types.wast.from-wast
index d36e31ccb..5835ba7d9 100644
--- a/test/heap-types.wast.from-wast
+++ b/test/heap-types.wast.from-wast
@@ -52,6 +52,11 @@
)
)
(drop
+ (struct.get $struct.A $named
+ (ref.null $struct.A)
+ )
+ )
+ (drop
(struct.get_u $struct.B 0
(local.get $tB)
)
diff --git a/test/heap-types.wast.fromBinary b/test/heap-types.wast.fromBinary
index 62590b5f7..90e129511 100644
--- a/test/heap-types.wast.fromBinary
+++ b/test/heap-types.wast.fromBinary
@@ -52,6 +52,11 @@
)
)
(drop
+ (struct.get $struct.A $named
+ (ref.null $struct.A)
+ )
+ )
+ (drop
(struct.get_u $struct.B 0
(local.get $tB)
)
diff --git a/test/heap-types.wast.fromBinary.noDebugInfo b/test/heap-types.wast.fromBinary.noDebugInfo
index 074f88ff8..e75ddbe26 100644
--- a/test/heap-types.wast.fromBinary.noDebugInfo
+++ b/test/heap-types.wast.fromBinary.noDebugInfo
@@ -52,6 +52,11 @@
)
)
(drop
+ (struct.get ${i32_f32_f64} 2
+ (ref.null ${i32_f32_f64})
+ )
+ )
+ (drop
(struct.get_u ${i8_mut:i16_ref?|{i32_f32_f64}|_mut:ref?|{i32_f32_f64}|} 0
(local.get $2)
)