summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-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)
)