diff options
-rw-r--r-- | src/wasm-s-parser.h | 10 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 27 | ||||
-rw-r--r-- | test/heap-types.wast | 10 | ||||
-rw-r--r-- | test/heap-types.wast.from-wast | 5 | ||||
-rw-r--r-- | test/heap-types.wast.fromBinary | 5 | ||||
-rw-r--r-- | test/heap-types.wast.fromBinary.noDebugInfo | 5 |
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) ) |