diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/literal.cpp | 2 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 16 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 10 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 7 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 45 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 34 |
6 files changed, 87 insertions, 27 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 09022eea0..8d60a4829 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -126,6 +126,7 @@ Literal::Literal(const Literal& other) : type(other.type) { case HeapType::eq: case HeapType::func: case HeapType::data: + case HeapType::array: WASM_UNREACHABLE("invalid type"); case HeapType::string: case HeapType::stringview_wtf8: @@ -523,6 +524,7 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { case HeapType::eq: case HeapType::func: case HeapType::data: + case HeapType::array: WASM_UNREACHABLE("invalid type"); case HeapType::string: case HeapType::stringview_wtf8: diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 5d21f5130..13c28f151 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1414,6 +1414,9 @@ void WasmBinaryWriter::writeType(Type type) { case HeapType::data: o << S32LEB(BinaryConsts::EncodedType::dataref); return; + case HeapType::array: + o << S32LEB(BinaryConsts::EncodedType::arrayref); + return; case HeapType::string: o << S32LEB(BinaryConsts::EncodedType::stringref); return; @@ -1520,6 +1523,9 @@ void WasmBinaryWriter::writeHeapType(HeapType type) { case HeapType::data: ret = BinaryConsts::EncodedHeapType::data; break; + case HeapType::array: + ret = BinaryConsts::EncodedHeapType::array; + break; case HeapType::string: ret = BinaryConsts::EncodedHeapType::string; break; @@ -1887,6 +1893,9 @@ bool WasmBinaryBuilder::getBasicType(int32_t code, Type& out) { case BinaryConsts::EncodedType::dataref: out = Type(HeapType::data, Nullable); return true; + case BinaryConsts::EncodedType::arrayref: + out = Type(HeapType::array, Nullable); + return true; case BinaryConsts::EncodedType::stringref: out = Type(HeapType::string, Nullable); return true; @@ -1933,6 +1942,9 @@ bool WasmBinaryBuilder::getBasicHeapType(int64_t code, HeapType& out) { case BinaryConsts::EncodedHeapType::data: out = HeapType::data; return true; + case BinaryConsts::EncodedHeapType::array: + out = HeapType::array; + return true; case BinaryConsts::EncodedHeapType::string: out = HeapType::string; return true; @@ -7102,9 +7114,9 @@ bool WasmBinaryBuilder::maybeVisitArrayLen(Expression*& out, uint32_t code) { if (code != BinaryConsts::ArrayLen) { return false; } - auto heapType = getIndexedHeapType(); + // Ignore the type annotation and don't bother validating it. + getU32LEB(); auto* ref = popNonVoidExpression(); - validateHeapTypeUsingChild(ref, heapType); out = Builder(wasm).makeArrayLen(ref); return true; } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 91d4c129c..41a0619f9 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1194,6 +1194,9 @@ Type SExpressionWasmBuilder::stringToType(std::string_view str, (str.substr(0, 9) == "structref" && (prefix || str.size() == 9))) { return Type(HeapType::data, Nullable); } + if (str.substr(0, 8) == "arrayref" && (prefix || str.size() == 8)) { + return Type(HeapType::array, Nullable); + } if (str.substr(0, 9) == "stringref" && (prefix || str.size() == 9)) { return Type(HeapType::string, Nullable); } @@ -1243,6 +1246,9 @@ HeapType SExpressionWasmBuilder::stringToHeapType(std::string_view str, (str.substr(0, 6) == "struct" && (prefix || str.size() == 6))) { return HeapType::data; } + if (str.substr(0, 5) == "array" && (prefix || str.size() == 5)) { + return HeapType::array; + } if (str.substr(0, 6) == "string" && (prefix || str.size() == 6)) { return HeapType::string; } @@ -3021,9 +3027,9 @@ Expression* SExpressionWasmBuilder::makeArraySet(Element& s) { } Expression* SExpressionWasmBuilder::makeArrayLen(Element& s) { - auto heapType = parseHeapType(*s[1]); + // Ignore the type annotation and don't bother validating it. + parseHeapType(*s[1]); auto ref = parseExpression(*s[2]); - validateHeapTypeUsingChild(ref, heapType, s); return Builder(wasm).makeArrayLen(ref); } diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 13d85d338..7c1c121d5 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2168,12 +2168,9 @@ void BinaryInstWriter::visitArraySet(ArraySet* curr) { } void BinaryInstWriter::visitArrayLen(ArrayLen* curr) { - if (curr->ref->type.isNull()) { - emitUnreachable(); - return; - } o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::ArrayLen); - parent.writeIndexedHeapType(curr->ref->type.getHeapType()); + // Unused type index. + o << U32LEB(0); } void BinaryInstWriter::visitArrayCopy(ArrayCopy* curr) { diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index b2cde6050..4fa7ff9d5 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -567,8 +567,9 @@ HeapType::BasicHeapType getBasicHeapSupertype(HeapType type) { case HeapTypeInfo::SignatureKind: return HeapType::func; case HeapTypeInfo::StructKind: - case HeapTypeInfo::ArrayKind: return HeapType::data; + case HeapTypeInfo::ArrayKind: + return HeapType::array; } WASM_UNREACHABLE("unexpected kind"); }; @@ -598,16 +599,21 @@ std::optional<HeapType> getBasicHeapTypeLUB(HeapType::BasicHeapType a, case HeapType::any: return {HeapType::any}; case HeapType::eq: - if (b == HeapType::i31 || b == HeapType::data) { + if (b == HeapType::i31 || b == HeapType::data || b == HeapType::array) { return {HeapType::eq}; } return {HeapType::any}; case HeapType::i31: - if (b == HeapType::data) { + if (b == HeapType::data || b == HeapType::array) { return {HeapType::eq}; } return {HeapType::any}; case HeapType::data: + if (b == HeapType::array) { + return {HeapType::data}; + } + return {HeapType::any}; + case HeapType::array: case HeapType::string: case HeapType::stringview_wtf8: case HeapType::stringview_wtf16: @@ -1086,13 +1092,14 @@ FeatureSet Type::getFeatures() const { } if (heapType.isBasic()) { switch (heapType.getBasic()) { - case HeapType::BasicHeapType::ext: - case HeapType::BasicHeapType::func: + case HeapType::ext: + case HeapType::func: return FeatureSet::ReferenceTypes; - case HeapType::BasicHeapType::any: - case HeapType::BasicHeapType::eq: - case HeapType::BasicHeapType::i31: - case HeapType::BasicHeapType::data: + case HeapType::any: + case HeapType::eq: + case HeapType::i31: + case HeapType::data: + case HeapType::array: return FeatureSet::ReferenceTypes | FeatureSet::GC; case HeapType::string: case HeapType::stringview_wtf8: @@ -1389,6 +1396,7 @@ bool HeapType::isBottom() const { case eq: case i31: case data: + case array: case string: case stringview_wtf8: case stringview_wtf16: @@ -1441,9 +1449,12 @@ size_t HeapType::getDepth() const { if (!isBasic()) { if (isFunction()) { depth++; - } else if (isData()) { + } else if (isStruct()) { // specific struct types <: data <: eq <: any depth += 3; + } else if (isArray()) { + // specific array types <: array <: data <: eq <: any + depth += 4; } } else { // Some basic types have supers. @@ -1463,6 +1474,9 @@ size_t HeapType::getDepth() const { case HeapType::stringview_iter: depth += 2; break; + case HeapType::array: + depth += 3; + break; case HeapType::none: case HeapType::nofunc: case HeapType::noext: @@ -1484,6 +1498,7 @@ HeapType::BasicHeapType HeapType::getBottom() const { case eq: case i31: case data: + case array: case string: case stringview_wtf8: case stringview_wtf16: @@ -1753,11 +1768,13 @@ bool SubTyper::isSubType(HeapType a, HeapType b) { return a.getBottom() == HeapType::none; case HeapType::eq: return a == HeapType::i31 || a == HeapType::data || - a == HeapType::none || a.isData(); + a == HeapType::array || a == HeapType::none || a.isData(); case HeapType::i31: return a == HeapType::none; case HeapType::data: - return a == HeapType::none || a.isData(); + return a == HeapType::array || a == HeapType::none || a.isData(); + case HeapType::array: + return a == HeapType::none || a.isArray(); case HeapType::string: case HeapType::stringview_wtf8: case HeapType::stringview_wtf16: @@ -2120,6 +2137,8 @@ std::ostream& TypePrinter::print(Type type) { return os << "i31ref"; case HeapType::data: return os << "dataref"; + case HeapType::array: + return os << "arrayref"; case HeapType::string: return os << "stringref"; case HeapType::stringview_wtf8: @@ -2164,6 +2183,8 @@ std::ostream& TypePrinter::print(HeapType type) { return os << "i31"; case HeapType::data: return os << "data"; + case HeapType::array: + return os << "array"; case HeapType::string: return os << "string"; case HeapType::stringview_wtf8: diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 91236fe54..0e7566528 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -2696,9 +2696,8 @@ void FunctionValidator::visitArrayGet(ArrayGet* curr) { if (curr->type == Type::unreachable) { return; } - // TODO: array rather than data once we've implemented that. if (!shouldBeSubType(curr->ref->type, - Type(HeapType::data, Nullable), + Type(HeapType::array, Nullable), curr, "array.get target should be an array reference")) { return; @@ -2707,6 +2706,11 @@ void FunctionValidator::visitArrayGet(ArrayGet* curr) { if (heapType == HeapType::none) { return; } + if (!shouldBeTrue(heapType != HeapType::array, + curr, + "array.get target should be a specific array reference")) { + return; + } const auto& element = heapType.getArray().element; // If the type is not packed, it must be marked internally as unsigned, by // convention. @@ -2725,9 +2729,8 @@ void FunctionValidator::visitArraySet(ArraySet* curr) { if (curr->type == Type::unreachable) { return; } - // TODO: array rather than data once we've implemented that. if (!shouldBeSubType(curr->ref->type, - Type(HeapType::data, Nullable), + Type(HeapType::array, Nullable), curr, "array.set target should be an array reference")) { return; @@ -2736,6 +2739,11 @@ void FunctionValidator::visitArraySet(ArraySet* curr) { if (heapType == HeapType::none) { return; } + if (!shouldBeTrue(heapType != HeapType::array, + curr, + "array.set target should be a specific array reference")) { + return; + } const auto& element = curr->ref->type.getHeapType().getArray().element; shouldBeSubType(curr->value->type, element.type, @@ -2749,6 +2757,10 @@ void FunctionValidator::visitArrayLen(ArrayLen* curr) { getModule()->features.hasGC(), curr, "array.len requires gc to be enabled"); shouldBeEqualOrFirstIsUnreachable( curr->type, Type(Type::i32), curr, "array.len result must be an i32"); + shouldBeSubType(curr->ref->type, + Type(HeapType::array, Nullable), + curr, + "array.len argument must be an array reference"); } void FunctionValidator::visitArrayCopy(ArrayCopy* curr) { @@ -2767,11 +2779,11 @@ void FunctionValidator::visitArrayCopy(ArrayCopy* curr) { return; } if (!shouldBeSubType(curr->srcRef->type, - Type(HeapType::data, Nullable), + Type(HeapType::array, Nullable), curr, "array.copy source should be an array reference") || !shouldBeSubType(curr->destRef->type, - Type(HeapType::data, Nullable), + Type(HeapType::array, Nullable), curr, "array.copy destination should be an array reference")) { return; @@ -2781,6 +2793,16 @@ void FunctionValidator::visitArrayCopy(ArrayCopy* curr) { if (srcHeapType == HeapType::none || destHeapType == HeapType::none) { return; } + if (!shouldBeTrue( + srcHeapType != HeapType::array, + curr, + "array.copy source needs to be a specific array reference") || + !shouldBeTrue( + srcHeapType != HeapType::array, + curr, + "array.copy destination needs to be a specific array reference")) { + return; + } const auto& srcElement = srcHeapType.getArray().element; const auto& destElement = destHeapType.getArray().element; shouldBeSubType(srcElement.type, |