diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/literal.cpp | 98 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 55 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 15 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 15 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 118 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 28 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 12 | ||||
-rw-r--r-- | src/wasm/wat-parser.cpp | 5 |
8 files changed, 106 insertions, 240 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index 6c7689990..85e93f912 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -46,11 +46,6 @@ Literal::Literal(Type type) : type(type) { case Type::none: return; case Type::unreachable: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: break; } } @@ -100,11 +95,6 @@ Literal::Literal(const Literal& other) : type(other.type) { case Type::none: return; case Type::unreachable: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: break; } } @@ -239,7 +229,7 @@ Literals Literal::makeNegOnes(Type type) { Literal Literal::makeZero(Type type) { assert(type.isSingle()); if (type.isRef()) { - if (type == Type::i31ref) { + if (type.getHeapType() == HeapType::i31) { return makeI31(0); } else { return makeNull(type.getHeapType()); @@ -355,11 +345,6 @@ void Literal::getBits(uint8_t (&buf)[16]) const { break; case Type::none: case Type::unreachable: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: WASM_UNREACHABLE("invalid type"); } } @@ -373,43 +358,37 @@ bool Literal::operator==(const Literal& other) const { if (type != other.type) { return false; } - auto compareRef = [&]() { - assert(type.isRef()); - // Note that we've already handled nulls earlier. - if (type.isFunction()) { - assert(func.is() && other.func.is()); - return func == other.func; - } - if (type.isData()) { - return gcData == other.gcData; - } - // other non-null reference type literals cannot represent concrete values, - // i.e. there is no concrete anyref or eqref other than null. - WASM_UNREACHABLE("unexpected type"); - }; if (type.isBasic()) { switch (type.getBasic()) { case Type::none: return true; // special voided literal case Type::i32: case Type::f32: - case Type::i31ref: return i32 == other.i32; case Type::i64: case Type::f64: return i64 == other.i64; case Type::v128: return memcmp(v128, other.v128, 16) == 0; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::dataref: - return compareRef(); case Type::unreachable: break; } } else if (type.isRef()) { - return compareRef(); + assert(type.isRef()); + // Note that we've already handled nulls earlier. + if (type.isFunction()) { + assert(func.is() && other.func.is()); + return func == other.func; + } + if (type.isData()) { + return gcData == other.gcData; + } + if (type.getHeapType() == HeapType::i31) { + return i32 == other.i32; + } + // other non-null reference type literals cannot represent concrete values, + // i.e. there is no concrete anyref or eqref other than null. + WASM_UNREACHABLE("unexpected type"); } else if (type.isRtt()) { return *rttSupers == *other.rttSupers; } @@ -578,11 +557,6 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { o << "i32x4 "; literal.printVec128(o, literal.getv128()); break; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); } @@ -801,11 +775,6 @@ Literal Literal::eqz() const { case Type::f64: return eq(Literal(double(0))); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -824,11 +793,6 @@ Literal Literal::neg() const { case Type::f64: return Literal(int64_t(i64 ^ 0x8000000000000000ULL)).castToF64(); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -847,11 +811,6 @@ Literal Literal::abs() const { case Type::f64: return Literal(int64_t(i64 & 0x7fffffffffffffffULL)).castToF64(); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -987,11 +946,6 @@ Literal Literal::add(const Literal& other) const { case Type::f64: return standardizeNaN(getf64() + other.getf64()); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1010,11 +964,6 @@ Literal Literal::sub(const Literal& other) const { case Type::f64: return standardizeNaN(getf64() - other.getf64()); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1112,11 +1061,6 @@ Literal Literal::mul(const Literal& other) const { case Type::f64: return standardizeNaN(getf64() * other.getf64()); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1347,11 +1291,6 @@ Literal Literal::eq(const Literal& other) const { case Type::f64: return Literal(getf64() == other.getf64()); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -1370,11 +1309,6 @@ Literal Literal::ne(const Literal& other) const { case Type::f64: return Literal(getf64() != other.getf64()); case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index e2588422c..5427deea1 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -693,6 +693,7 @@ void WasmBinaryWriter::writeElementSegments() { auto start = startSection(BinaryConsts::Section::Element); o << U32LEB(elemCount); + Type funcref = Type(HeapType::func, Nullable); for (auto& segment : wasm->elementSegments) { Index tableIdx = 0; @@ -708,7 +709,7 @@ void WasmBinaryWriter::writeElementSegments() { if (!isPassive) { tableIdx = getTableIndex(segment->table); hasTableIndex = - tableIdx > 0 || wasm->getTable(segment->table)->type != Type::funcref; + tableIdx > 0 || wasm->getTable(segment->table)->type != funcref; } uint32_t flags = 0; @@ -1339,7 +1340,36 @@ void WasmBinaryWriter::writeInlineBuffer(const char* data, size_t size) { } void WasmBinaryWriter::writeType(Type type) { - if (type.isRef() && !type.isBasic()) { + if (type.isRef()) { + auto heapType = type.getHeapType(); + if (heapType.isBasic()) { + if (type.isNullable()) { + switch (heapType.getBasic()) { + case HeapType::any: + o << S32LEB(BinaryConsts::EncodedType::anyref); + return; + case HeapType::func: + o << S32LEB(BinaryConsts::EncodedType::funcref); + return; + case HeapType::eq: + o << S32LEB(BinaryConsts::EncodedType::eqref); + return; + default: + break; + } + } else { + switch (heapType.getBasic()) { + case HeapType::i31: + o << S32LEB(BinaryConsts::EncodedType::i31ref); + return; + case HeapType::data: + o << S32LEB(BinaryConsts::EncodedType::dataref); + return; + default: + break; + } + } + } if (type.isNullable()) { o << S32LEB(BinaryConsts::EncodedType::nullable); } else { @@ -1381,21 +1411,6 @@ void WasmBinaryWriter::writeType(Type type) { case Type::v128: ret = BinaryConsts::EncodedType::v128; break; - case Type::funcref: - ret = BinaryConsts::EncodedType::funcref; - break; - case Type::anyref: - ret = BinaryConsts::EncodedType::anyref; - break; - case Type::eqref: - ret = BinaryConsts::EncodedType::eqref; - break; - case Type::i31ref: - ret = BinaryConsts::EncodedType::i31ref; - break; - case Type::dataref: - ret = BinaryConsts::EncodedType::dataref; - break; default: WASM_UNREACHABLE("unexpected type"); } @@ -1774,13 +1789,13 @@ bool WasmBinaryBuilder::getBasicType(int32_t code, Type& out) { out = Type::v128; return true; case BinaryConsts::EncodedType::funcref: - out = Type::funcref; + out = Type(HeapType::func, Nullable); return true; case BinaryConsts::EncodedType::anyref: - out = Type::anyref; + out = Type(HeapType::any, Nullable); return true; case BinaryConsts::EncodedType::eqref: - out = Type::eqref; + out = Type(HeapType::eq, Nullable); return true; case BinaryConsts::EncodedType::i31ref: out = Type(HeapType::i31, NonNullable); diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index bfe09280d..97a25d2c4 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -1169,20 +1169,20 @@ Type SExpressionWasmBuilder::stringToType(const char* str, } } if (strncmp(str, "funcref", 7) == 0 && (prefix || str[7] == 0)) { - return Type::funcref; + return Type(HeapType::func, Nullable); } if ((strncmp(str, "externref", 9) == 0 && (prefix || str[9] == 0)) || (strncmp(str, "anyref", 6) == 0 && (prefix || str[6] == 0))) { - return Type::anyref; + return Type(HeapType::any, Nullable); } if (strncmp(str, "eqref", 5) == 0 && (prefix || str[5] == 0)) { - return Type::eqref; + return Type(HeapType::eq, Nullable); } if (strncmp(str, "i31ref", 6) == 0 && (prefix || str[6] == 0)) { - return Type::i31ref; + return Type(HeapType::i31, NonNullable); } if (strncmp(str, "dataref", 7) == 0 && (prefix || str[7] == 0)) { - return Type::dataref; + return Type(HeapType::data, NonNullable); } if (strncmp(str, "stringref", 9) == 0 && (prefix || str[9] == 0)) { return Type(HeapType::string, Nullable); @@ -1763,11 +1763,6 @@ parseConst(cashew::IString s, Type type, MixedArena& allocator) { break; } case Type::v128: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: WASM_UNREACHABLE("unexpected const type"); case Type::none: case Type::unreachable: { diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 28472aebd..c980d896b 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -187,11 +187,6 @@ void BinaryInstWriter::visitLoad(Load* curr) { // the pointer is unreachable, so we are never reached; just don't emit // a load return; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: WASM_UNREACHABLE("unexpected type"); } @@ -290,11 +285,6 @@ void BinaryInstWriter::visitStore(Store* curr) { o << int8_t(BinaryConsts::SIMDPrefix) << U32LEB(BinaryConsts::V128Store); break; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); @@ -742,11 +732,6 @@ void BinaryInstWriter::visitConst(Const* curr) { } break; } - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: WASM_UNREACHABLE("unexpected type"); diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index b13b1ecd7..84b11000f 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -567,19 +567,6 @@ Type asCanonical(Type type) { } } -// Given a HeapType that may or may not be backed by the simplest possible -// representation, return the equivalent type that is definitely backed by the -// simplest possible representation. -HeapType asCanonical(HeapType type) { - if (type.isBasic()) { - return type; - } else if (auto canon = getHeapTypeInfo(type)->getCanonical()) { - return *canon; - } else { - return type; - } -} - HeapType::BasicHeapType getBasicHeapSupertype(HeapType type) { if (type.isBasic()) { return type.getBasic(); @@ -670,35 +657,6 @@ std::optional<Type> TypeInfo::getCanonical() const { return tuple.types[0]; } } - if (isRef()) { - HeapType basic = asCanonical(ref.heapType); - if (basic.isBasic()) { - if (ref.nullable) { - switch (basic.getBasic()) { - case HeapType::func: - return Type::funcref; - case HeapType::any: - return Type::anyref; - case HeapType::eq: - return Type::eqref; - case HeapType::i31: - case HeapType::data: - case HeapType::string: - case HeapType::stringview_wtf8: - case HeapType::stringview_wtf16: - case HeapType::stringview_iter: - break; - } - } else { - if (basic == HeapType::i31) { - return Type::i31ref; - } - if (basic == HeapType::data) { - return Type::dataref; - } - } - } - } return {}; } @@ -1004,7 +962,7 @@ bool Type::isTuple() const { bool Type::isRef() const { if (isBasic()) { - return id >= funcref && id <= _last_basic_type; + return false; } else { return getTypeInfo(*this)->isRef(); } @@ -1012,7 +970,7 @@ bool Type::isRef() const { bool Type::isFunction() const { if (isBasic()) { - return id == funcref; + return false; } else { auto* info = getTypeInfo(*this); return info->isRef() && info->ref.heapType.isFunction(); @@ -1021,7 +979,7 @@ bool Type::isFunction() const { bool Type::isData() const { if (isBasic()) { - return id == dataref; + return false; } else { auto* info = getTypeInfo(*this); return info->isRef() && info->ref.heapType.isData(); @@ -1030,7 +988,7 @@ bool Type::isData() const { bool Type::isNullable() const { if (isBasic()) { - return id >= funcref && id <= eqref; // except i31ref and dataref + return false; } else { return getTypeInfo(*this)->isNullable(); } @@ -1099,11 +1057,6 @@ unsigned Type::getByteSize() const { return 8; case Type::v128: return 16; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: case Type::unreachable: break; @@ -1217,16 +1170,6 @@ HeapType Type::getHeapType() const { case Type::f64: case Type::v128: break; - case Type::funcref: - return HeapType::func; - case Type::anyref: - return HeapType::any; - case Type::eqref: - return HeapType::eq; - case Type::i31ref: - return HeapType::i31; - case Type::dataref: - return HeapType::data; } WASM_UNREACHABLE("Unexpected type"); } else { @@ -2086,16 +2029,6 @@ std::ostream& TypePrinter::print(Type type) { return os << "f64"; case Type::v128: return os << "v128"; - case Type::funcref: - return os << "funcref"; - case Type::anyref: - return os << "anyref"; - case Type::eqref: - return os << "eqref"; - case Type::i31ref: - return os << "i31ref"; - case Type::dataref: - return os << "dataref"; } } @@ -2109,19 +2042,36 @@ std::ostream& TypePrinter::print(Type type) { print(type.getTuple()); } else if (type.isRef()) { auto heapType = type.getHeapType(); - if (type.isNullable() && heapType.isBasic()) { - // Print shorthands for certain nullable basic heap types. - switch (heapType.getBasic()) { - case HeapType::string: - return os << "stringref"; - case HeapType::stringview_wtf8: - return os << "stringview_wtf8"; - case HeapType::stringview_wtf16: - return os << "stringview_wtf16"; - case HeapType::stringview_iter: - return os << "stringview_iter"; - default: - break; + if (heapType.isBasic()) { + // Print shorthands for certain basic heap types. + if (type.isNullable()) { + switch (heapType.getBasic()) { + case HeapType::func: + return os << "funcref"; + case HeapType::any: + return os << "anyref"; + case HeapType::eq: + return os << "eqref"; + case HeapType::string: + return os << "stringref"; + case HeapType::stringview_wtf8: + return os << "stringview_wtf8"; + case HeapType::stringview_wtf16: + return os << "stringview_wtf16"; + case HeapType::stringview_iter: + return os << "stringview_iter"; + default: + break; + } + } else { + switch (heapType.getBasic()) { + case HeapType::i31: + return os << "i31ref"; + case HeapType::data: + return os << "dataref"; + default: + break; + } } } os << "(ref "; diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 4c6e8e929..65a910747 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -1399,11 +1399,6 @@ void FunctionValidator::validateMemBytes(uint8_t bytes, break; case Type::unreachable: break; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: WASM_UNREACHABLE("unexpected type"); } @@ -2044,14 +2039,15 @@ void FunctionValidator::visitRefFunc(RefFunc* curr) { } void FunctionValidator::visitRefEq(RefEq* curr) { + Type eqref = Type(HeapType::eq, Nullable); shouldBeTrue( getModule()->features.hasGC(), curr, "ref.eq requires gc to be enabled"); shouldBeSubType(curr->left->type, - Type::eqref, + eqref, curr->left, "ref.eq's left argument should be a subtype of eqref"); shouldBeSubType(curr->right->type, - Type::eqref, + eqref, curr->right, "ref.eq's right argument should be a subtype of eqref"); } @@ -2330,7 +2326,7 @@ void FunctionValidator::visitI31Get(I31Get* curr) { curr, "i31.get_s/u requires gc to be enabled"); shouldBeSubType(curr->i31->type, - Type::i31ref, + Type(HeapType::i31, Nullable), curr->i31, "i31.get_s/u's argument should be i31ref"); } @@ -2853,11 +2849,6 @@ void FunctionValidator::validateAlignment( case Type::v128: case Type::unreachable: break; - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: case Type::none: WASM_UNREACHABLE("invalid type"); } @@ -3130,7 +3121,7 @@ static void validateTables(Module& module, ValidationInfo& info) { "--enable-reference-types)"); if (!module.tables.empty()) { auto& table = module.tables.front(); - info.shouldBeTrue(table->type == Type::funcref, + info.shouldBeTrue(table->type == Type(HeapType::func, Nullable), "table", "Only funcref is valid for table type (when reference " "types are disabled)"); @@ -3150,6 +3141,8 @@ static void validateTables(Module& module, ValidationInfo& info) { } } + Type anyref = Type(HeapType::any, Nullable); + Type funcref = Type(HeapType::func, Nullable); for (auto& table : module.tables) { info.shouldBeTrue(table->initial <= table->max, "table", @@ -3159,14 +3152,13 @@ static void validateTables(Module& module, ValidationInfo& info) { "table", "Non-nullable reference types are not yet supported for tables"); if (!module.features.hasGC()) { - info.shouldBeTrue(table->type.isFunction() || table->type == Type::anyref, + info.shouldBeTrue(table->type.isFunction() || table->type == anyref, "table", - "Only function reference types or anyref are valid " + "Only function reference types or externref are valid " "for table type (when GC is disabled)"); } if (!module.features.hasTypedFunctionReferences()) { - info.shouldBeTrue(table->type == Type::funcref || - table->type == Type::anyref, + info.shouldBeTrue(table->type == funcref || table->type == anyref, "table", "Only funcref and anyref are valid for table type " "(when typed-function references are disabled)"); diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index eceb4585b..bd83d62ed 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -903,7 +903,7 @@ void I31New::finalize() { if (value->type == Type::unreachable) { type = Type::unreachable; } else { - type = Type::i31ref; + type = Type(HeapType::i31, NonNullable); } } @@ -1024,11 +1024,11 @@ Type BrOn::getSentType() { } return Type(getIntendedType(), NonNullable); case BrOnFunc: - return Type::funcref; + return Type(HeapType::func, NonNullable); case BrOnData: - return Type::dataref; + return Type(HeapType::data, NonNullable); case BrOnI31: - return Type::i31ref; + return Type(HeapType::i31, NonNullable); case BrOnCastFail: case BrOnNonFunc: case BrOnNonData: @@ -1164,10 +1164,10 @@ void RefAs::finalize() { type = Type(HeapType::func, NonNullable); break; case RefAsData: - type = Type::dataref; + type = Type(HeapType::data, NonNullable); break; case RefAsI31: - type = Type::i31ref; + type = Type(HeapType::i31, NonNullable); break; default: WASM_UNREACHABLE("invalid ref.as_*"); diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index e3a2ab588..8b86017ff 100644 --- a/src/wasm/wat-parser.cpp +++ b/src/wasm/wat-parser.cpp @@ -1488,11 +1488,6 @@ Result<typename Ctx::InstrT> makeConst(Ctx& ctx, ParseInput& in, Type type) { return in.err("unimplemented instruction"); case Type::none: case Type::unreachable: - case Type::funcref: - case Type::anyref: - case Type::eqref: - case Type::i31ref: - case Type::dataref: break; } WASM_UNREACHABLE("unexpected type"); |