diff options
Diffstat (limited to 'src/wasm')
-rw-r--r-- | src/wasm/literal.cpp | 74 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 122 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 127 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 79 | ||||
-rw-r--r-- | src/wasm/wasm-type.cpp | 149 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 143 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 66 | ||||
-rw-r--r-- | src/wasm/wat-parser.cpp | 44 |
8 files changed, 50 insertions, 754 deletions
diff --git a/src/wasm/literal.cpp b/src/wasm/literal.cpp index b8a6c7e7a..05f9d93d5 100644 --- a/src/wasm/literal.cpp +++ b/src/wasm/literal.cpp @@ -53,8 +53,6 @@ Literal::Literal(Type type) : type(type) { if (isData()) { assert(!type.isNonNullable()); new (&gcData) std::shared_ptr<GCData>(); - } else if (type.isRtt()) { - new (this) Literal(Literal::makeCanonicalRtt(type.getHeapType())); } else { // For anything else, zero out all the union data. memset(&v128, 0, 16); @@ -71,11 +69,6 @@ Literal::Literal(std::shared_ptr<GCData> gcData, HeapType type) assert(isData()); } -Literal::Literal(std::unique_ptr<RttSupers>&& rttSupers, Type type) - : rttSupers(std::move(rttSupers)), type(type) { - assert(type.isRtt()); -} - Literal::Literal(const Literal& other) : type(other.type) { if (type.isBasic()) { switch (type.getBasic()) { @@ -104,11 +97,6 @@ Literal::Literal(const Literal& other) : type(other.type) { func = other.func; return; } - if (type.isRtt()) { - // Allocate a new RttSupers with a copy of the other's data. - new (&rttSupers) auto(std::make_unique<RttSupers>(*other.rttSupers)); - return; - } if (type.isRef()) { auto heapType = type.getHeapType(); if (heapType.isBasic()) { @@ -136,11 +124,8 @@ Literal::~Literal() { if (type.isBasic()) { return; } - if (isData()) { gcData.~shared_ptr(); - } else if (type.isRtt()) { - rttSupers.~unique_ptr(); } } @@ -152,18 +137,6 @@ Literal& Literal::operator=(const Literal& other) { return *this; } -Literal Literal::makeCanonicalRtt(HeapType type) { - auto supers = std::make_unique<RttSupers>(); - std::optional<HeapType> supertype; - for (auto curr = type; (supertype = curr.getSuperType()); curr = *supertype) { - supers->emplace_back(*supertype); - } - // We want the highest types to be first. - std::reverse(supers->begin(), supers->end()); - size_t depth = supers->size(); - return Literal(std::move(supers), Type(Rtt(depth, type))); -} - template<typename LaneT, int Lanes> static void extractBytes(uint8_t (&dest)[16], const LaneArray<Lanes>& lanes) { std::array<uint8_t, 16> bytes; @@ -228,8 +201,6 @@ Literal Literal::makeZero(Type type) { assert(type.isSingle()); if (type.isRef()) { return makeNull(type.getHeapType()); - } else if (type.isRtt()) { - return Literal(type); } else { return makeFromInt32(0, type); } @@ -257,11 +228,6 @@ std::shared_ptr<GCData> Literal::getGCData() const { return gcData; } -const RttSupers& Literal::getRttSupers() const { - assert(type.isRtt()); - return *rttSupers; -} - Literal Literal::castToF32() { assert(type == Type::i32); Literal ret(Type::f32); @@ -383,8 +349,6 @@ bool Literal::operator==(const Literal& other) const { // 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; } WASM_UNREACHABLE("unexpected type"); } @@ -494,7 +458,7 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { if (literal.isData()) { auto data = literal.getGCData(); if (data) { - o << "[ref " << data->rtt << ' ' << data->values << ']'; + o << "[ref " << data->type << ' ' << data->values << ']'; } else { o << "[ref null " << literal.type << ']'; } @@ -524,15 +488,6 @@ std::ostream& operator<<(std::ostream& o, Literal literal) { WASM_UNREACHABLE("type should have been handled above"); } } - } else if (literal.type.isRtt()) { - o << "[rtt "; - for (auto& super : literal.getRttSupers()) { - o << super.type << " :> "; - if (super.freshPtr) { - o << " (fresh)"; - } - } - o << literal.type << ']'; } else { TODO_SINGLE_COMPOUND(literal.type); switch (literal.type.getBasic()) { @@ -2564,31 +2519,4 @@ Literal Literal::relaxedFmsF64x2(const Literal& left, return ternary<2, &Literal::getLanesF64x2, &Literal::fms>(*this, left, right); } -bool Literal::isSubRtt(const Literal& other) const { - assert(type.isRtt() && other.type.isRtt()); - // For this literal to be a sub-rtt of the other rtt, the supers must be a - // superset. That is, if other is a->b->c then we should be a->b->c as well - // with possibly ->d->.. added. The rttSupers array represents those chains, - // but only the supers, which means the last item in the chain is simply the - // type of the literal. - const auto& supers = getRttSupers(); - const auto& otherSupers = other.getRttSupers(); - if (otherSupers.size() > supers.size()) { - return false; - } - for (Index i = 0; i < otherSupers.size(); i++) { - if (supers[i] != otherSupers[i]) { - return false; - } - } - // If we have more supers than other, compare that extra super. Otherwise, - // we have the same amount of supers, and must be completely identical to - // other. - if (otherSupers.size() < supers.size()) { - return other.type.getHeapType() == supers[otherSupers.size()].type; - } else { - return other.type == type; - } -} - } // namespace wasm diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 4e8e3f0d7..b74ef017b 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -1383,17 +1383,6 @@ void WasmBinaryWriter::writeType(Type type) { writeHeapType(type.getHeapType()); return; } - if (type.isRtt()) { - auto rtt = type.getRtt(); - if (rtt.hasDepth()) { - o << S32LEB(BinaryConsts::EncodedType::rtt_n); - o << U32LEB(rtt.depth); - } else { - o << S32LEB(BinaryConsts::EncodedType::rtt); - } - writeIndexedHeapType(rtt.heapType); - return; - } int ret = 0; TODO_SINGLE_COMPOUND(type); switch (type.getBasic()) { @@ -1877,14 +1866,6 @@ Type WasmBinaryBuilder::getType(int initial) { return Type(getHeapType(), Nullable); case BinaryConsts::EncodedType::nonnullable: return Type(getHeapType(), NonNullable); - case BinaryConsts::EncodedType::rtt_n: { - auto depth = getU32LEB(); - auto heapType = getIndexedHeapType(); - return Type(Rtt(depth, heapType)); - } - case BinaryConsts::EncodedType::rtt: { - return Type(Rtt(getIndexedHeapType())); - } default: throwError("invalid wasm type: " + std::to_string(initial)); } @@ -2029,16 +2010,6 @@ void WasmBinaryBuilder::readTypes() { } return builder.getTempRefType(builder[size_t(htCode)], nullability); } - case BinaryConsts::EncodedType::rtt_n: - case BinaryConsts::EncodedType::rtt: { - auto depth = typeCode == BinaryConsts::EncodedType::rtt ? Rtt::NoDepth - : getU32LEB(); - auto htCode = getU32LEB(); - if (size_t(htCode) >= builder.size()) { - throwError("invalid type index: " + std::to_string(htCode)); - } - return builder.getTempRttType(Rtt(depth, builder[htCode])); - } default: throwError("unexpected type index: " + std::to_string(typeCode)); } @@ -3875,12 +3846,6 @@ BinaryConsts::ASTNodes WasmBinaryBuilder::readExpression(Expression*& curr) { if (maybeVisitBrOn(curr, opcode)) { break; } - if (maybeVisitRttCanon(curr, opcode)) { - break; - } - if (maybeVisitRttSub(curr, opcode)) { - break; - } if (maybeVisitStructNew(curr, opcode)) { break; } @@ -6793,12 +6758,7 @@ bool WasmBinaryBuilder::maybeVisitI31Get(Expression*& out, uint32_t code) { } bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) { - if (code == BinaryConsts::RefTest) { - auto* rtt = popNonVoidExpression(); - auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeRefTest(ref, rtt); - return true; - } else if (code == BinaryConsts::RefTestStatic) { + if (code == BinaryConsts::RefTestStatic) { auto intendedType = getIndexedHeapType(); auto* ref = popNonVoidExpression(); out = Builder(wasm).makeRefTest(ref, intendedType); @@ -6808,13 +6768,8 @@ bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) { } bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) { - if (code == BinaryConsts::RefCast) { - auto* rtt = popNonVoidExpression(); - auto* ref = popNonVoidExpression(); - out = Builder(wasm).makeRefCast(ref, rtt); - return true; - } else if (code == BinaryConsts::RefCastStatic || - code == BinaryConsts::RefCastNopStatic) { + if (code == BinaryConsts::RefCastStatic || + code == BinaryConsts::RefCastNopStatic) { auto intendedType = getIndexedHeapType(); auto* ref = popNonVoidExpression(); auto safety = @@ -6834,11 +6789,9 @@ bool WasmBinaryBuilder::maybeVisitBrOn(Expression*& out, uint32_t code) { case BinaryConsts::BrOnNonNull: op = BrOnNonNull; break; - case BinaryConsts::BrOnCast: case BinaryConsts::BrOnCastStatic: op = BrOnCast; break; - case BinaryConsts::BrOnCastFail: case BinaryConsts::BrOnCastStaticFail: op = BrOnCastFail; break; @@ -6871,35 +6824,8 @@ bool WasmBinaryBuilder::maybeVisitBrOn(Expression*& out, uint32_t code) { out = Builder(wasm).makeBrOn(op, name, ref, intendedType); return true; } - Expression* rtt = nullptr; - if (op == BrOnCast || op == BrOnCastFail) { - rtt = popNonVoidExpression(); - } auto* ref = popNonVoidExpression(); - out = ValidatingBuilder(wasm, pos).validateAndMakeBrOn(op, name, ref, rtt); - return true; -} - -bool WasmBinaryBuilder::maybeVisitRttCanon(Expression*& out, uint32_t code) { - if (code != BinaryConsts::RttCanon) { - return false; - } - auto heapType = getIndexedHeapType(); - out = Builder(wasm).makeRttCanon(heapType); - return true; -} - -bool WasmBinaryBuilder::maybeVisitRttSub(Expression*& out, uint32_t code) { - if (code != BinaryConsts::RttSub && code != BinaryConsts::RttFreshSub) { - return false; - } - auto targetHeapType = getIndexedHeapType(); - auto* parent = popNonVoidExpression(); - if (code == BinaryConsts::RttSub) { - out = Builder(wasm).makeRttSub(targetHeapType, parent); - } else { - out = Builder(wasm).makeRttFreshSub(targetHeapType, parent); - } + out = ValidatingBuilder(wasm, pos).validateAndMakeBrOn(op, name, ref); return true; } @@ -6917,21 +6843,6 @@ bool WasmBinaryBuilder::maybeVisitStructNew(Expression*& out, uint32_t code) { } out = Builder(wasm).makeStructNew(heapType, operands); return true; - } else if (code == BinaryConsts::StructNewWithRtt || - code == BinaryConsts::StructNewDefaultWithRtt) { - auto heapType = getIndexedHeapType(); - auto* rtt = popNonVoidExpression(); - validateHeapTypeUsingChild(rtt, heapType); - std::vector<Expression*> operands; - if (code == BinaryConsts::StructNewWithRtt) { - auto numOperands = heapType.getStruct().fields.size(); - operands.resize(numOperands); - for (Index i = 0; i < numOperands; i++) { - operands[numOperands - i - 1] = popNonVoidExpression(); - } - } - out = Builder(wasm).makeStructNew(rtt, operands); - return true; } return false; } @@ -6987,18 +6898,6 @@ bool WasmBinaryBuilder::maybeVisitArrayNew(Expression*& out, uint32_t code) { } out = Builder(wasm).makeArrayNew(heapType, size, init); return true; - } else if (code == BinaryConsts::ArrayNewWithRtt || - code == BinaryConsts::ArrayNewDefaultWithRtt) { - auto heapType = getIndexedHeapType(); - auto* rtt = popNonVoidExpression(); - validateHeapTypeUsingChild(rtt, heapType); - auto* size = popNonVoidExpression(); - Expression* init = nullptr; - if (code == BinaryConsts::ArrayNewWithRtt) { - init = popNonVoidExpression(); - } - out = Builder(wasm).makeArrayNew(rtt, size, init); - return true; } return false; } @@ -7013,17 +6912,6 @@ bool WasmBinaryBuilder::maybeVisitArrayInit(Expression*& out, uint32_t code) { } out = Builder(wasm).makeArrayInit(heapType, values); return true; - } else if (code == BinaryConsts::ArrayInit) { - auto heapType = getIndexedHeapType(); - auto size = getU32LEB(); - auto* rtt = popNonVoidExpression(); - validateHeapTypeUsingChild(rtt, heapType); - std::vector<Expression*> values(size); - for (size_t i = 0; i < size; i++) { - values[size - i - 1] = popNonVoidExpression(); - } - out = Builder(wasm).makeArrayInit(rtt, values); - return true; } return false; } @@ -7370,7 +7258,7 @@ void WasmBinaryBuilder::validateHeapTypeUsingChild(Expression* child, if (child->type == Type::unreachable) { return; } - if ((!child->type.isRef() && !child->type.isRtt()) || + if (!child->type.isRef() || !HeapType::isSubType(child->type.getHeapType(), heapType)) { throwError("bad heap type: expected " + heapType.toString() + " but found " + child->type.toString()); diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index 38ec788ba..f13091c91 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -54,7 +54,7 @@ namespace wasm { static Name STRUCT("struct"), FIELD("field"), ARRAY("array"), FUNC_SUBTYPE("func_subtype"), STRUCT_SUBTYPE("struct_subtype"), ARRAY_SUBTYPE("array_subtype"), EXTENDS("extends"), REC("rec"), I8("i8"), - I16("i16"), RTT("rtt"), DECLARE("declare"), ITEM("item"), OFFSET("offset"); + I16("i16"), DECLARE("declare"), ITEM("item"), OFFSET("offset"); static Address getAddress(const Element* s) { return atoll(s->c_str()); } @@ -752,46 +752,11 @@ void SExpressionWasmBuilder::preParseHeapTypes(Element& module) { } }; - auto parseRttType = [&](Element& elem) -> Type { - // '(' 'rtt' depth? typeidx ')' - uint32_t depth; - Element* idx; - switch (elem.size()) { - default: - throw ParseException( - "unexpected number of rtt parameters", elem.line, elem.col); - case 2: - depth = Rtt::NoDepth; - idx = elem[1]; - break; - case 3: - if (!String::isNumber(elem[1]->c_str())) { - throw ParseException( - "invalid rtt depth", elem[1]->line, elem[1]->col); - } - depth = atoi(elem[1]->c_str()); - idx = elem[2]; - break; - } - if (idx->dollared()) { - HeapType type = builder[typeIndices[idx->c_str()]]; - return builder.getTempRttType(Rtt(depth, type)); - } else if (String::isNumber(idx->c_str())) { - size_t index = atoi(idx->c_str()); - if (index < numTypes) { - return builder.getTempRttType(Rtt(depth, builder[index])); - } - } - throw ParseException("invalid type index", idx->line, idx->col); - }; - auto parseValType = [&](Element& elem) { if (elem.isStr()) { return stringToType(elem.c_str()); } else if (*elem[0] == REF) { return parseRefType(elem); - } else if (*elem[0] == RTT) { - return parseRttType(elem); } else { throw ParseException("unknown valtype kind", elem[0]->line, elem[0]->col); } @@ -1281,18 +1246,6 @@ Type SExpressionWasmBuilder::elementToType(Element& s) { } return Type(parseHeapType(*s[i]), nullable); } - if (elementStartsWith(s, RTT)) { - // It's an RTT, something like (rtt N $typename) or just (rtt $typename) - // if there is no depth. - if (s[1]->dollared()) { - auto heapType = parseHeapType(*s[1]); - return Type(Rtt(heapType)); - } else { - auto depth = atoi(s[1]->str().c_str()); - auto heapType = parseHeapType(*s[2]); - return Type(Rtt(depth, heapType)); - } - } // It's a tuple. std::vector<Type> types; for (size_t i = 0; i < s.size(); ++i) { @@ -2702,24 +2655,12 @@ Expression* SExpressionWasmBuilder::makeI31Get(Element& s, bool signed_) { return ret; } -Expression* SExpressionWasmBuilder::makeRefTest(Element& s) { - auto* ref = parseExpression(*s[1]); - auto* rtt = parseExpression(*s[2]); - return Builder(wasm).makeRefTest(ref, rtt); -} - Expression* SExpressionWasmBuilder::makeRefTestStatic(Element& s) { auto heapType = parseHeapType(*s[1]); auto* ref = parseExpression(*s[2]); return Builder(wasm).makeRefTest(ref, heapType); } -Expression* SExpressionWasmBuilder::makeRefCast(Element& s) { - auto* ref = parseExpression(*s[1]); - auto* rtt = parseExpression(*s[2]); - return Builder(wasm).makeRefCast(ref, rtt); -} - Expression* SExpressionWasmBuilder::makeRefCastStatic(Element& s) { auto heapType = parseHeapType(*s[1]); auto* ref = parseExpression(*s[2]); @@ -2735,12 +2676,8 @@ Expression* SExpressionWasmBuilder::makeRefCastNopStatic(Element& s) { Expression* SExpressionWasmBuilder::makeBrOn(Element& s, BrOnOp op) { auto name = getLabel(*s[1]); auto* ref = parseExpression(*s[2]); - Expression* rtt = nullptr; - if (op == BrOnCast || op == BrOnCastFail) { - rtt = parseExpression(*s[3]); - } return ValidatingBuilder(wasm, s.line, s.col) - .validateAndMakeBrOn(op, name, ref, rtt); + .validateAndMakeBrOn(op, name, ref); } Expression* SExpressionWasmBuilder::makeBrOnStatic(Element& s, BrOnOp op) { @@ -2750,39 +2687,6 @@ Expression* SExpressionWasmBuilder::makeBrOnStatic(Element& s, BrOnOp op) { return Builder(wasm).makeBrOn(op, name, ref, heapType); } -Expression* SExpressionWasmBuilder::makeRttCanon(Element& s) { - return Builder(wasm).makeRttCanon(parseHeapType(*s[1])); -} - -Expression* SExpressionWasmBuilder::makeRttSub(Element& s) { - auto heapType = parseHeapType(*s[1]); - auto parent = parseExpression(*s[2]); - return Builder(wasm).makeRttSub(heapType, parent); -} - -Expression* SExpressionWasmBuilder::makeRttFreshSub(Element& s) { - auto heapType = parseHeapType(*s[1]); - auto parent = parseExpression(*s[2]); - return Builder(wasm).makeRttFreshSub(heapType, parent); -} - -Expression* SExpressionWasmBuilder::makeStructNew(Element& s, bool default_) { - auto heapType = parseHeapType(*s[1]); - auto numOperands = s.size() - 3; - if (default_ && numOperands > 0) { - throw ParseException( - "arguments provided for struct.new_with_default", s.line, s.col); - } - std::vector<Expression*> operands; - operands.resize(numOperands); - for (Index i = 0; i < numOperands; i++) { - operands[i] = parseExpression(*s[i + 2]); - } - auto* rtt = parseExpression(*s[s.size() - 1]); - validateHeapTypeUsingChild(rtt, heapType, s); - return Builder(wasm).makeStructNew(rtt, operands); -} - Expression* SExpressionWasmBuilder::makeStructNewStatic(Element& s, bool default_) { auto heapType = parseHeapType(*s[1]); @@ -2841,19 +2745,6 @@ Expression* SExpressionWasmBuilder::makeStructSet(Element& s) { return Builder(wasm).makeStructSet(index, ref, value); } -Expression* SExpressionWasmBuilder::makeArrayNew(Element& s, bool default_) { - auto heapType = parseHeapType(*s[1]); - Expression* init = nullptr; - size_t i = 2; - if (!default_) { - init = parseExpression(*s[i++]); - } - auto* size = parseExpression(*s[i++]); - auto* rtt = parseExpression(*s[i++]); - validateHeapTypeUsingChild(rtt, heapType, s); - return Builder(wasm).makeArrayNew(rtt, size, init); -} - Expression* SExpressionWasmBuilder::makeArrayNewStatic(Element& s, bool default_) { auto heapType = parseHeapType(*s[1]); @@ -2866,18 +2757,6 @@ Expression* SExpressionWasmBuilder::makeArrayNewStatic(Element& s, return Builder(wasm).makeArrayNew(heapType, size, init); } -Expression* SExpressionWasmBuilder::makeArrayInit(Element& s) { - auto heapType = parseHeapType(*s[1]); - size_t i = 2; - std::vector<Expression*> values; - while (i < s.size() - 1) { - values.push_back(parseExpression(*s[i++])); - } - auto* rtt = parseExpression(*s[i++]); - validateHeapTypeUsingChild(rtt, heapType, s); - return Builder(wasm).makeArrayInit(rtt, values); -} - Expression* SExpressionWasmBuilder::makeArrayInitStatic(Element& s) { auto heapType = parseHeapType(*s[1]); size_t i = 2; @@ -3853,7 +3732,7 @@ void SExpressionWasmBuilder::validateHeapTypeUsingChild(Expression* child, if (child->type == Type::unreachable) { return; } - if ((!child->type.isRef() && !child->type.isRtt()) || + if (!child->type.isRef() || !HeapType::isSubType(child->type.getHeapType(), heapType)) { throw ParseException("bad heap type: expected " + heapType.toString() + " but found " + child->type.toString(), diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 2fc06b176..c29384dad 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2016,26 +2016,18 @@ void BinaryInstWriter::visitCallRef(CallRef* curr) { void BinaryInstWriter::visitRefTest(RefTest* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::RefTest); - } else { - o << U32LEB(BinaryConsts::RefTestStatic); - parent.writeIndexedHeapType(curr->intendedType); - } + o << U32LEB(BinaryConsts::RefTestStatic); + parent.writeIndexedHeapType(curr->intendedType); } void BinaryInstWriter::visitRefCast(RefCast* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::RefCast); + if (curr->safety == RefCast::Unsafe) { + o << U32LEB(BinaryConsts::RefCastNopStatic); } else { - if (curr->safety == RefCast::Unsafe) { - o << U32LEB(BinaryConsts::RefCastNopStatic); - } else { - o << U32LEB(BinaryConsts::RefCastStatic); - } - parent.writeIndexedHeapType(curr->intendedType); + o << U32LEB(BinaryConsts::RefCastStatic); } + parent.writeIndexedHeapType(curr->intendedType); } void BinaryInstWriter::visitBrOn(BrOn* curr) { @@ -2048,19 +2040,11 @@ void BinaryInstWriter::visitBrOn(BrOn* curr) { break; case BrOnCast: o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::BrOnCast); - } else { - o << U32LEB(BinaryConsts::BrOnCastStatic); - } + o << U32LEB(BinaryConsts::BrOnCastStatic); break; case BrOnCastFail: o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::BrOnCastFail); - } else { - o << U32LEB(BinaryConsts::BrOnCastStaticFail); - } + o << U32LEB(BinaryConsts::BrOnCastStaticFail); break; case BrOnFunc: o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::BrOnFunc); @@ -2084,36 +2068,17 @@ void BinaryInstWriter::visitBrOn(BrOn* curr) { WASM_UNREACHABLE("invalid br_on_*"); } o << U32LEB(getBreakIndex(curr->name)); - if ((curr->op == BrOnCast || curr->op == BrOnCastFail) && !curr->rtt) { + if (curr->op == BrOnCast || curr->op == BrOnCastFail) { parent.writeIndexedHeapType(curr->intendedType); } } -void BinaryInstWriter::visitRttCanon(RttCanon* curr) { - o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RttCanon); - parent.writeIndexedHeapType(curr->type.getRtt().heapType); -} - -void BinaryInstWriter::visitRttSub(RttSub* curr) { - o << int8_t(BinaryConsts::GCPrefix); - o << U32LEB(curr->fresh ? BinaryConsts::RttFreshSub : BinaryConsts::RttSub); - parent.writeIndexedHeapType(curr->type.getRtt().heapType); -} - void BinaryInstWriter::visitStructNew(StructNew* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - if (curr->isWithDefault()) { - o << U32LEB(BinaryConsts::StructNewDefaultWithRtt); - } else { - o << U32LEB(BinaryConsts::StructNewWithRtt); - } + if (curr->isWithDefault()) { + o << U32LEB(BinaryConsts::StructNewDefault); } else { - if (curr->isWithDefault()) { - o << U32LEB(BinaryConsts::StructNewDefault); - } else { - o << U32LEB(BinaryConsts::StructNew); - } + o << U32LEB(BinaryConsts::StructNew); } parent.writeIndexedHeapType(curr->type.getHeapType()); } @@ -2142,29 +2107,17 @@ void BinaryInstWriter::visitStructSet(StructSet* curr) { void BinaryInstWriter::visitArrayNew(ArrayNew* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - if (curr->isWithDefault()) { - o << U32LEB(BinaryConsts::ArrayNewDefaultWithRtt); - } else { - o << U32LEB(BinaryConsts::ArrayNewWithRtt); - } + if (curr->isWithDefault()) { + o << U32LEB(BinaryConsts::ArrayNewDefault); } else { - if (curr->isWithDefault()) { - o << U32LEB(BinaryConsts::ArrayNewDefault); - } else { - o << U32LEB(BinaryConsts::ArrayNew); - } + o << U32LEB(BinaryConsts::ArrayNew); } parent.writeIndexedHeapType(curr->type.getHeapType()); } void BinaryInstWriter::visitArrayInit(ArrayInit* curr) { o << int8_t(BinaryConsts::GCPrefix); - if (curr->rtt) { - o << U32LEB(BinaryConsts::ArrayInit); - } else { - o << U32LEB(BinaryConsts::ArrayInitStatic); - } + o << U32LEB(BinaryConsts::ArrayInitStatic); parent.writeIndexedHeapType(curr->type.getHeapType()); o << U32LEB(curr->values.size()); } diff --git a/src/wasm/wasm-type.cpp b/src/wasm/wasm-type.cpp index 84b11000f..23d2877f7 100644 --- a/src/wasm/wasm-type.cpp +++ b/src/wasm/wasm-type.cpp @@ -60,7 +60,6 @@ struct TypeInfo { enum Kind { TupleKind, RefKind, - RttKind, } kind; struct Ref { HeapType heapType; @@ -69,20 +68,17 @@ struct TypeInfo { union { Tuple tuple; Ref ref; - Rtt rtt; }; TypeInfo(const Tuple& tuple) : kind(TupleKind), tuple(tuple) {} TypeInfo(Tuple&& tuple) : kind(TupleKind), tuple(std::move(tuple)) {} TypeInfo(HeapType heapType, Nullability nullable) : kind(RefKind), ref{heapType, nullable} {} - TypeInfo(Rtt rtt) : kind(RttKind), rtt(rtt) {} TypeInfo(const TypeInfo& other); ~TypeInfo(); constexpr bool isTuple() const { return kind == TupleKind; } constexpr bool isRef() const { return kind == RefKind; } - constexpr bool isRtt() const { return kind == RttKind; } bool isNullable() const { return kind == RefKind && ref.nullable; } @@ -165,7 +161,6 @@ struct SubTyper { bool isSubType(const Signature& a, const Signature& b); bool isSubType(const Struct& a, const Struct& b); bool isSubType(const Array& a, const Array& b); - bool isSubType(const Rtt& a, const Rtt& b); }; // Helper for finding the equirecursive least upper bound of two types. @@ -192,7 +187,6 @@ private: std::optional<Signature> lub(const Signature& a, const Signature& b); Struct lub(const Struct& a, const Struct& b); std::optional<Array> lub(const Array& a, const Array& b); - std::optional<Rtt> lub(const Rtt& a, const Rtt& b); }; // Helper for printing types. @@ -231,7 +225,6 @@ struct TypePrinter { std::optional<HeapType> super = std::nullopt); std::ostream& print(const Array& array, std::optional<HeapType> super = std::nullopt); - std::ostream& print(const Rtt& rtt); }; // Helper for hashing the shapes of TypeInfos and HeapTypeInfos. Keeps track of @@ -255,7 +248,6 @@ struct FiniteShapeHasher { size_t hash(const Signature& sig); size_t hash(const Struct& struct_); size_t hash(const Array& array); - size_t hash(const Rtt& rtt); }; // Helper for comparing the shapes of TypeInfos and HeapTypeInfos for equality. @@ -281,7 +273,6 @@ struct FiniteShapeEquator { bool eq(const Signature& a, const Signature& b); bool eq(const Struct& a, const Struct& b); bool eq(const Array& a, const Array& b); - bool eq(const Rtt& a, const Rtt& b); }; struct RecGroupHasher { @@ -307,7 +298,6 @@ struct RecGroupHasher { size_t hash(const Signature& sig) const; size_t hash(const Struct& struct_) const; size_t hash(const Array& array) const; - size_t hash(const Rtt& rtt) const; }; struct RecGroupEquator { @@ -334,7 +324,6 @@ struct RecGroupEquator { bool eq(const Signature& a, const Signature& b) const; bool eq(const Struct& a, const Struct& b) const; bool eq(const Array& a, const Array& b) const; - bool eq(const Rtt& a, const Rtt& b) const; }; // A wrapper around a RecGroup that provides equality and hashing based on the @@ -626,9 +615,6 @@ TypeInfo::TypeInfo(const TypeInfo& other) { case RefKind: new (&ref) auto(other.ref); return; - case RttKind: - new (&rtt) auto(other.rtt); - return; } WASM_UNREACHABLE("unexpected kind"); } @@ -641,9 +627,6 @@ TypeInfo::~TypeInfo() { case RefKind: ref.~Ref(); return; - case RttKind: - rtt.~Rtt(); - return; } WASM_UNREACHABLE("unexpected kind"); } @@ -670,8 +653,6 @@ bool TypeInfo::operator==(const TypeInfo& other) const { case RefKind: return ref.nullable == other.ref.nullable && ref.heapType == other.ref.heapType; - case RttKind: - return rtt == other.rtt; } WASM_UNREACHABLE("unexpected kind"); } @@ -947,11 +928,6 @@ Type::Type(HeapType heapType, Nullability nullable) { new (this) Type(globalTypeStore.insert(TypeInfo(heapType, nullable))); } -Type::Type(Rtt rtt) { - assert(!isTemp(rtt.heapType) && "Leaking temporary type!"); - new (this) Type(globalTypeStore.insert(rtt)); -} - bool Type::isTuple() const { if (isBasic()) { return false; @@ -1002,14 +978,6 @@ bool Type::isNonNullable() const { } } -bool Type::isRtt() const { - if (isBasic()) { - return false; - } else { - return getTypeInfo(*this)->isRtt(); - } -} - bool Type::isStruct() const { return isRef() && getHeapType().isStruct(); } bool Type::isArray() const { return isRef() && getHeapType().isArray(); } @@ -1026,19 +994,7 @@ bool Type::isDefaultable() const { } return true; } - return isConcrete() && !isNonNullable() && !isRtt(); -} - -bool Type::isDefaultableOrNonNullable() const { - if (isTuple()) { - for (auto t : *this) { - if (!t.isDefaultableOrNonNullable()) { - return false; - } - } - return true; - } - return isConcrete() && !isRtt(); + return isConcrete() && !isNonNullable(); } Nullability Type::getNullability() const { @@ -1132,8 +1088,6 @@ FeatureSet Type::getFeatures() const { // load of the wasm we don't know the features yet, so we apply the more // refined types), so we don't add that in any case here. return FeatureSet::ReferenceTypes; - } else if (t.isRtt()) { - return FeatureSet::ReferenceTypes | FeatureSet::GC; } TODO_SINGLE_COMPOUND(t); switch (t.getBasic()) { @@ -1179,18 +1133,11 @@ HeapType Type::getHeapType() const { break; case TypeInfo::RefKind: return info->ref.heapType; - case TypeInfo::RttKind: - return info->rtt.heapType; } WASM_UNREACHABLE("Unexpected type"); } } -Rtt Type::getRtt() const { - assert(isRtt()); - return getTypeInfo(*this)->rtt; -} - Type Type::get(unsigned byteSize, bool float_) { if (byteSize < 4) { return Type::i32; @@ -1264,15 +1211,6 @@ Type Type::getLeastUpperBound(Type a, Type b) { HeapType::getLeastUpperBound(a.getHeapType(), b.getHeapType()); return Type(heapType, nullability); } - if (a.isRtt() && b.isRtt()) { - auto heapType = a.getHeapType(); - if (heapType != b.getHeapType()) { - return Type::none; - } - auto rttA = a.getRtt(), rttB = b.getRtt(); - auto depth = rttA.depth == rttB.depth ? rttA.depth : Rtt::NoDepth; - return Rtt(depth, heapType); - } return Type::none; WASM_UNREACHABLE("unexpected type"); } @@ -1593,7 +1531,6 @@ std::string Tuple::toString() const { return genericToString(*this); } std::string Signature::toString() const { return genericToString(*this); } std::string Struct::toString() const { return genericToString(*this); } std::string Array::toString() const { return genericToString(*this); } -std::string Rtt::toString() const { return genericToString(*this); } std::ostream& operator<<(std::ostream& os, Type type) { return TypePrinter(os).print(type); @@ -1622,9 +1559,6 @@ std::ostream& operator<<(std::ostream& os, Struct struct_) { std::ostream& operator<<(std::ostream& os, Array array) { return TypePrinter(os).print(array); } -std::ostream& operator<<(std::ostream& os, Rtt rtt) { - return TypePrinter(os).print(rtt); -} std::ostream& operator<<(std::ostream& os, TypeBuilder::ErrorReason reason) { switch (reason) { case TypeBuilder::ErrorReason::SelfSupertype: @@ -1670,9 +1604,6 @@ bool SubTyper::isSubType(Type a, Type b) { if (a.isTuple() && b.isTuple()) { return isSubType(a.getTuple(), b.getTuple()); } - if (a.isRtt() && b.isRtt()) { - return isSubType(a.getRtt(), b.getRtt()); - } return false; } @@ -1783,13 +1714,6 @@ bool SubTyper::isSubType(const Array& a, const Array& b) { return isSubType(a.element, b.element); } -bool SubTyper::isSubType(const Rtt& a, const Rtt& b) { - // (rtt n $x) is a subtype of (rtt $x), that is, if the only difference in - // information is that the left side specifies a depth while the right side - // allows any depth. - return a.heapType == b.heapType && a.hasDepth() && !b.hasDepth(); -} - bool TypeBounder::hasLeastUpperBound(Type a, Type b) { return bool(lub(a, b)); } Type TypeBounder::getLeastUpperBound(Type a, Type b) { @@ -1847,12 +1771,6 @@ std::optional<Type> TypeBounder::lub(Type a, Type b) { (a.isNullable() || b.isNullable()) ? Nullable : NonNullable; HeapType heapType = lub(a.getHeapType(), b.getHeapType()); return builder.getTempRefType(heapType, nullability); - } else if (a.isRtt() && b.isRtt()) { - auto rtt = lub(a.getRtt(), b.getRtt()); - if (!rtt) { - return {}; - } - return builder.getTempRttType(*rtt); } return {}; } @@ -1987,14 +1905,6 @@ std::optional<Array> TypeBounder::lub(const Array& a, const Array& b) { } } -std::optional<Rtt> TypeBounder::lub(const Rtt& a, const Rtt& b) { - if (a.heapType != b.heapType) { - return {}; - } - uint32_t depth = (a.depth == b.depth) ? a.depth : Rtt::NoDepth; - return Rtt(depth, a.heapType); -} - void TypePrinter::printHeapTypeName(HeapType type) { if (type.isBasic()) { print(type); @@ -2080,8 +1990,6 @@ std::ostream& TypePrinter::print(Type type) { } printHeapTypeName(heapType); os << ')'; - } else if (type.isRtt()) { - print(type.getRtt()); } else { WASM_UNREACHABLE("unexpected type"); } @@ -2234,15 +2142,6 @@ std::ostream& TypePrinter::print(const Array& array, return os << ')'; } -std::ostream& TypePrinter::print(const Rtt& rtt) { - os << "(rtt "; - if (rtt.hasDepth()) { - os << rtt.depth << ' '; - } - printHeapTypeName(rtt.heapType); - return os << ')'; -} - size_t FiniteShapeHasher::hash(Type type) { size_t digest = wasm::hash(type.isBasic()); if (type.isBasic()) { @@ -2285,9 +2184,6 @@ size_t FiniteShapeHasher::hash(const TypeInfo& info) { rehash(digest, info.ref.nullable); hash_combine(digest, hash(info.ref.heapType)); return digest; - case TypeInfo::RttKind: - hash_combine(digest, hash(info.rtt)); - return digest; } WASM_UNREACHABLE("unexpected kind"); } @@ -2355,12 +2251,6 @@ size_t FiniteShapeHasher::hash(const Array& array) { return hash(array.element); } -size_t FiniteShapeHasher::hash(const Rtt& rtt) { - size_t digest = wasm::hash(rtt.depth); - hash_combine(digest, hash(rtt.heapType)); - return digest; -} - bool FiniteShapeEquator::eq(Type a, Type b) { if (a.isBasic() != b.isBasic()) { return false; @@ -2404,8 +2294,6 @@ bool FiniteShapeEquator::eq(const TypeInfo& a, const TypeInfo& b) { case TypeInfo::RefKind: return a.ref.nullable == b.ref.nullable && eq(a.ref.heapType, b.ref.heapType); - case TypeInfo::RttKind: - return eq(a.rtt, b.rtt); } WASM_UNREACHABLE("unexpected kind"); } @@ -2466,10 +2354,6 @@ bool FiniteShapeEquator::eq(const Array& a, const Array& b) { return eq(a.element, b.element); } -bool FiniteShapeEquator::eq(const Rtt& a, const Rtt& b) { - return a.depth == b.depth && eq(a.heapType, b.heapType); -} - size_t RecGroupHasher::operator()() const { size_t digest = wasm::hash(group.size()); for (auto type : group) { @@ -2526,9 +2410,6 @@ size_t RecGroupHasher::hash(const TypeInfo& info) const { rehash(digest, info.ref.nullable); hash_combine(digest, hash(info.ref.heapType)); return digest; - case TypeInfo::RttKind: - hash_combine(digest, hash(info.rtt)); - return digest; } WASM_UNREACHABLE("unexpected kind"); } @@ -2589,12 +2470,6 @@ size_t RecGroupHasher::hash(const Array& array) const { return hash(array.element); } -size_t RecGroupHasher::hash(const Rtt& rtt) const { - size_t digest = wasm::hash(rtt.depth); - hash_combine(digest, hash(rtt.heapType)); - return digest; -} - bool RecGroupEquator::operator()() const { if (newGroup == otherGroup) { return true; @@ -2655,8 +2530,6 @@ bool RecGroupEquator::eq(const TypeInfo& a, const TypeInfo& b) const { case TypeInfo::RefKind: return a.ref.nullable == b.ref.nullable && eq(a.ref.heapType, b.ref.heapType); - case TypeInfo::RttKind: - return eq(a.rtt, b.rtt); } WASM_UNREACHABLE("unexpected kind"); } @@ -2717,10 +2590,6 @@ bool RecGroupEquator::eq(const Array& a, const Array& b) const { return eq(a.element, b.element); } -bool RecGroupEquator::eq(const Rtt& a, const Rtt& b) const { - return a.depth == b.depth && eq(a.heapType, b.heapType); -} - template<typename Self> void TypeGraphWalkerBase<Self>::walkRoot(Type* type) { assert(taskList.empty()); taskList.push_back(Task::scan(type)); @@ -2781,9 +2650,6 @@ template<typename Self> void TypeGraphWalkerBase<Self>::scanType(Type* type) { taskList.push_back(Task::scan(&info->ref.heapType)); break; } - case TypeInfo::RttKind: - taskList.push_back(Task::scan(&info->rtt.heapType)); - break; } } @@ -2921,10 +2787,6 @@ Type TypeBuilder::getTempRefType(HeapType type, Nullability nullable) { return markTemp(impl->typeStore.insert(TypeInfo(type, nullable))); } -Type TypeBuilder::getTempRttType(Rtt rtt) { - return markTemp(impl->typeStore.insert(rtt)); -} - void TypeBuilder::setSubType(size_t i, size_t j) { assert(i < size() && j < size() && "index out of bounds"); HeapTypeInfo* sub = impl->entries[i].info.get(); @@ -4031,12 +3893,6 @@ size_t hash<wasm::RecGroup>::operator()(const wasm::RecGroup& group) const { return wasm::hash(group.getID()); } -size_t hash<wasm::Rtt>::operator()(const wasm::Rtt& rtt) const { - auto digest = wasm::hash(rtt.depth); - wasm::rehash(digest, rtt.heapType); - return digest; -} - size_t hash<wasm::TypeInfo>::operator()(const wasm::TypeInfo& info) const { auto digest = wasm::hash(info.kind); switch (info.kind) { @@ -4047,9 +3903,6 @@ size_t hash<wasm::TypeInfo>::operator()(const wasm::TypeInfo& info) const { wasm::rehash(digest, info.ref.nullable); wasm::rehash(digest, info.ref.heapType); return digest; - case wasm::TypeInfo::RttKind: - wasm::rehash(digest, info.rtt); - return digest; } WASM_UNREACHABLE("unexpected kind"); } diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index 65a910747..bc51d8b63 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -383,8 +383,6 @@ public: void visitRefTest(RefTest* curr); void visitRefCast(RefCast* curr); void visitBrOn(BrOn* curr); - void visitRttCanon(RttCanon* curr); - void visitRttSub(RttSub* curr); void visitStructNew(StructNew* curr); void visitStructGet(StructGet* curr); void visitStructSet(StructSet* curr); @@ -2338,23 +2336,12 @@ void FunctionValidator::visitRefTest(RefTest* curr) { shouldBeTrue( curr->ref->type.isRef(), curr, "ref.test ref must have ref type"); } - if (curr->rtt) { - if (curr->rtt->type != Type::unreachable) { - shouldBeTrue( - curr->rtt->type.isRtt(), curr, "ref.test rtt must have rtt type"); - } - shouldBeEqual(curr->intendedType, + shouldBeUnequal(curr->intendedType, HeapType(), curr, - "dynamic ref.test must not use intendedType field"); - } else { - shouldBeUnequal(curr->intendedType, - HeapType(), - curr, - "static ref.test must set intendedType field"); - shouldBeTrue( - !curr->intendedType.isBasic(), curr, "ref.test must test a non-basic"); - } + "static ref.test must set intendedType field"); + shouldBeTrue( + !curr->intendedType.isBasic(), curr, "ref.test must test a non-basic"); } void FunctionValidator::visitRefCast(RefCast* curr) { @@ -2364,23 +2351,12 @@ void FunctionValidator::visitRefCast(RefCast* curr) { shouldBeTrue( curr->ref->type.isRef(), curr, "ref.cast ref must have ref type"); } - if (curr->rtt) { - if (curr->rtt->type != Type::unreachable) { - shouldBeTrue( - curr->rtt->type.isRtt(), curr, "ref.cast rtt must have rtt type"); - } - shouldBeEqual(curr->intendedType, + shouldBeUnequal(curr->intendedType, HeapType(), curr, - "dynamic ref.cast must not use intendedType field"); - } else { - shouldBeUnequal(curr->intendedType, - HeapType(), - curr, - "static ref.cast must set intendedType field"); - shouldBeTrue( - !curr->intendedType.isBasic(), curr, "ref.cast must cast to a non-basic"); - } + "static ref.cast must set intendedType field"); + shouldBeTrue( + !curr->intendedType.isBasic(), curr, "ref.cast must cast to a non-basic"); } void FunctionValidator::visitBrOn(BrOn* curr) { @@ -2392,28 +2368,14 @@ void FunctionValidator::visitBrOn(BrOn* curr) { curr->ref->type.isRef(), curr, "br_on_cast ref must have ref type"); } if (curr->op == BrOnCast || curr->op == BrOnCastFail) { - if (curr->rtt) { - // Note that an unreachable rtt is not supported: the text and binary - // formats do not provide the type, so if it's unreachable we should not - // even create a br_on_cast in such a case, as we'd have no idea what it - // casts to. - shouldBeTrue( - curr->rtt->type.isRtt(), curr, "br_on_cast rtt must have rtt type"); - shouldBeEqual(curr->intendedType, + shouldBeUnequal(curr->intendedType, HeapType(), curr, - "dynamic br_on_cast* must not use intendedType field"); - } else { - shouldBeUnequal(curr->intendedType, - HeapType(), - curr, - "static br_on_cast* must set intendedType field"); - shouldBeTrue(!curr->intendedType.isBasic(), - curr, - "br_on_cast* must cast to a non-basic"); - } + "static br_on_cast* must set intendedType field"); + shouldBeTrue(!curr->intendedType.isBasic(), + curr, + "br_on_cast* must cast to a non-basic"); } else { - shouldBeTrue(curr->rtt == nullptr, curr, "non-cast BrOn must not have rtt"); shouldBeEqual(curr->intendedType, HeapType(), curr, @@ -2422,38 +2384,6 @@ void FunctionValidator::visitBrOn(BrOn* curr) { noteBreak(curr->name, curr->getSentType(), curr); } -void FunctionValidator::visitRttCanon(RttCanon* curr) { - shouldBeTrue( - getModule()->features.hasGC(), curr, "rtt.canon requires gc to be enabled"); - shouldBeTrue(curr->type.isRtt(), curr, "rtt.canon must have RTT type"); - auto rtt = curr->type.getRtt(); - shouldBeEqual(rtt.depth, - Index(curr->type.getHeapType().getDepth()), - curr, - "rtt.canon must have the depth of its heap type"); -} - -void FunctionValidator::visitRttSub(RttSub* curr) { - shouldBeTrue( - getModule()->features.hasGC(), curr, "rtt.sub requires gc to be enabled"); - shouldBeTrue(curr->type.isRtt(), curr, "rtt.sub must have RTT type"); - if (curr->parent->type != Type::unreachable) { - shouldBeTrue( - curr->parent->type.isRtt(), curr, "rtt.sub parent must have RTT type"); - auto parentRtt = curr->parent->type.getRtt(); - auto rtt = curr->type.getRtt(); - if (rtt.hasDepth() && parentRtt.hasDepth()) { - shouldBeEqual(rtt.depth, - parentRtt.depth + 1, - curr, - "rtt.canon has a depth of 1 over the parent"); - } - shouldBeTrue(HeapType::isSubType(rtt.heapType, parentRtt.heapType), - curr, - "rtt.sub parent must be a supertype"); - } -} - void FunctionValidator::visitStructNew(StructNew* curr) { shouldBeTrue(getModule()->features.hasGC(), curr, @@ -2461,19 +2391,7 @@ void FunctionValidator::visitStructNew(StructNew* curr) { if (curr->type == Type::unreachable) { return; } - if (curr->rtt) { - if (!shouldBeTrue( - curr->rtt->type.isRtt(), curr, "struct.new rtt must be rtt")) { - return; - } - } auto heapType = curr->type.getHeapType(); - if (curr->rtt) { - shouldBeEqual(curr->rtt->type.getHeapType(), - heapType, - curr, - "struct.new heap type must match rtt"); - } if (!shouldBeTrue( heapType.isStruct(), curr, "struct.new heap type must be struct")) { return; @@ -2565,19 +2483,7 @@ void FunctionValidator::visitArrayNew(ArrayNew* curr) { if (curr->type == Type::unreachable) { return; } - if (curr->rtt) { - if (!shouldBeTrue( - curr->rtt->type.isRtt(), curr, "array.new rtt must be rtt")) { - return; - } - } auto heapType = curr->type.getHeapType(); - if (curr->rtt) { - shouldBeEqual(curr->rtt->type.getHeapType(), - heapType, - curr, - "array.new heap type must match rtt"); - } if (!shouldBeTrue( heapType.isArray(), curr, "array.new heap type must be array")) { return; @@ -2607,19 +2513,7 @@ void FunctionValidator::visitArrayInit(ArrayInit* curr) { if (curr->type == Type::unreachable) { return; } - if (curr->rtt) { - if (!shouldBeTrue( - curr->rtt->type.isRtt(), curr, "array.init rtt must be rtt")) { - return; - } - } auto heapType = curr->type.getHeapType(); - if (curr->rtt) { - shouldBeEqual(curr->rtt->type.getHeapType(), - heapType, - curr, - "array.init heap type must match rtt"); - } if (!shouldBeTrue( heapType.isArray(), curr, "array.init heap type must be array")) { return; @@ -2716,9 +2610,7 @@ void FunctionValidator::visitFunction(Function* curr) { } for (const auto& var : curr->vars) { features |= var.getFeatures(); - bool valid = getModule()->features.hasGCNNLocals() - ? var.isDefaultableOrNonNullable() - : var.isDefaultable(); + bool valid = getModule()->features.hasGCNNLocals() || var.isDefaultable(); shouldBeTrue(valid, var, "vars must be defaultable"); } shouldBeTrue(features <= getModule()->features, @@ -3167,10 +3059,9 @@ static void validateTables(Module& module, ValidationInfo& info) { for (auto& segment : module.elementSegments) { // Since element segment items need to be constant expressions, that leaves - // us with ref.null, ref.func and global.get. The GC proposal adds rtt.canon - // and rtt.sub to the list, but Binaryen doesn't consider RTTs as reference- - // types yet. As a result, the only possible type for element segments will - // be function references. + // us with ref.null, ref.func and global.get. As a result, the only possible + // type for element segments will be function references. + // TODO: This is not true! Allow GC data here (#4846). info.shouldBeTrue(segment->type.isFunction(), "elem", "element segment type must be of function type."); diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 1a6acf5bd..34b1e82b7 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -931,36 +931,25 @@ void CallRef::finalize(Type type_) { } void RefTest::finalize() { - if (ref->type == Type::unreachable || - (rtt && rtt->type == Type::unreachable)) { + if (ref->type == Type::unreachable) { type = Type::unreachable; } else { type = Type::i32; } } -HeapType RefTest::getIntendedType() { - return rtt ? rtt->type.getHeapType() : intendedType; -} - void RefCast::finalize() { - if (ref->type == Type::unreachable || - (rtt && rtt->type == Type::unreachable)) { + if (ref->type == Type::unreachable) { type = Type::unreachable; } else { // The output of ref.cast may be null if the input is null (in that case the // null is passed through). - type = Type(getIntendedType(), ref->type.getNullability()); + type = Type(intendedType, ref->type.getNullability()); } } -HeapType RefCast::getIntendedType() { - return rtt ? rtt->type.getHeapType() : intendedType; -} - void BrOn::finalize() { - if (ref->type == Type::unreachable || - (rtt && rtt->type == Type::unreachable)) { + if (ref->type == Type::unreachable) { type = Type::unreachable; return; } @@ -984,7 +973,7 @@ void BrOn::finalize() { case BrOnCastFail: // If we do not branch, the cast worked, and we have something of the cast // type. - type = Type(getIntendedType(), NonNullable); + type = Type(intendedType, NonNullable); break; case BrOnNonFunc: type = Type(HeapType::func, NonNullable); @@ -1000,11 +989,6 @@ void BrOn::finalize() { } } -HeapType BrOn::getIntendedType() { - assert(op == BrOnCast || op == BrOnCastFail); - return rtt ? rtt->type.getHeapType() : intendedType; -} - Type BrOn::getSentType() { switch (op) { case BrOnNull: @@ -1022,7 +1006,7 @@ Type BrOn::getSentType() { if (ref->type == Type::unreachable) { return Type::unreachable; } - return Type(getIntendedType(), NonNullable); + return Type(intendedType, NonNullable); case BrOnFunc: return Type(HeapType::func, NonNullable); case BrOnData: @@ -1039,31 +1023,10 @@ Type BrOn::getSentType() { } } -void RttCanon::finalize() { - // Nothing to do - the type must have been set already during construction. -} - -void RttSub::finalize() { - if (parent->type == Type::unreachable) { - type = Type::unreachable; - } - // Else nothing to do - the type must have been set already during - // construction. -} - void StructNew::finalize() { - if (rtt && rtt->type == Type::unreachable) { - type = Type::unreachable; - return; - } if (handleUnreachableOperands(this)) { return; } - // A dynamic StructNew infers the type from the rtt. A static one has the type - // already in the type field. - if (rtt) { - type = Type(rtt->type.getHeapType(), NonNullable); - } } void StructGet::finalize() { @@ -1083,35 +1046,20 @@ void StructSet::finalize() { } void ArrayNew::finalize() { - if ((rtt && rtt->type == Type::unreachable) || - size->type == Type::unreachable || + if (size->type == Type::unreachable || (init && init->type == Type::unreachable)) { type = Type::unreachable; return; } - // A dynamic ArrayNew infers the type from the rtt. A static one has the type - // already in the type field. - if (rtt) { - type = Type(rtt->type.getHeapType(), NonNullable); - } } void ArrayInit::finalize() { - if (rtt && rtt->type == Type::unreachable) { - type = Type::unreachable; - return; - } for (auto* value : values) { if (value->type == Type::unreachable) { type = Type::unreachable; return; } } - // A dynamic ArrayInit infers the type from the rtt. A static one has the type - // already in the type field. - if (rtt) { - type = Type(rtt->type.getHeapType(), NonNullable); - } } void ArrayGet::finalize() { diff --git a/src/wasm/wat-parser.cpp b/src/wasm/wat-parser.cpp index 8b86017ff..89eab3297 100644 --- a/src/wasm/wat-parser.cpp +++ b/src/wasm/wat-parser.cpp @@ -967,14 +967,6 @@ Result<typename Ctx::InstrT> makeBrOn(Ctx&, ParseInput&, BrOnOp op); template<typename Ctx> Result<typename Ctx::InstrT> makeBrOnStatic(Ctx&, ParseInput&, BrOnOp op); template<typename Ctx> -Result<typename Ctx::InstrT> makeRttCanon(Ctx&, ParseInput&); -template<typename Ctx> -Result<typename Ctx::InstrT> makeRttSub(Ctx&, ParseInput&); -template<typename Ctx> -Result<typename Ctx::InstrT> makeRttFreshSub(Ctx&, ParseInput&); -template<typename Ctx> -Result<typename Ctx::InstrT> makeStructNew(Ctx&, ParseInput&, bool default_); -template<typename Ctx> Result<typename Ctx::InstrT> makeStructNewStatic(Ctx&, ParseInput&, bool default_); template<typename Ctx> @@ -983,13 +975,9 @@ makeStructGet(Ctx&, ParseInput&, bool signed_ = false); template<typename Ctx> Result<typename Ctx::InstrT> makeStructSet(Ctx&, ParseInput&); template<typename Ctx> -Result<typename Ctx::InstrT> makeArrayNew(Ctx&, ParseInput&, bool default_); -template<typename Ctx> Result<typename Ctx::InstrT> makeArrayNewStatic(Ctx&, ParseInput&, bool default_); template<typename Ctx> -Result<typename Ctx::InstrT> makeArrayInit(Ctx&, ParseInput&); -template<typename Ctx> Result<typename Ctx::InstrT> makeArrayInitStatic(Ctx&, ParseInput&); template<typename Ctx> Result<typename Ctx::InstrT> @@ -1779,27 +1767,6 @@ makeBrOnStatic(Ctx& ctx, ParseInput& in, BrOnOp op) { } template<typename Ctx> -Result<typename Ctx::InstrT> makeRttCanon(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template<typename Ctx> -Result<typename Ctx::InstrT> makeRttSub(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template<typename Ctx> -Result<typename Ctx::InstrT> makeRttFreshSub(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template<typename Ctx> -Result<typename Ctx::InstrT> -makeStructNew(Ctx& ctx, ParseInput& in, bool default_) { - return in.err("unimplemented instruction"); -} - -template<typename Ctx> Result<typename Ctx::InstrT> makeStructNewStatic(Ctx& ctx, ParseInput& in, bool default_) { return in.err("unimplemented instruction"); @@ -1818,22 +1785,11 @@ Result<typename Ctx::InstrT> makeStructSet(Ctx& ctx, ParseInput& in) { template<typename Ctx> Result<typename Ctx::InstrT> -makeArrayNew(Ctx& ctx, ParseInput& in, bool default_) { - return in.err("unimplemented instruction"); -} - -template<typename Ctx> -Result<typename Ctx::InstrT> makeArrayNewStatic(Ctx& ctx, ParseInput& in, bool default_) { return in.err("unimplemented instruction"); } template<typename Ctx> -Result<typename Ctx::InstrT> makeArrayInit(Ctx& ctx, ParseInput& in) { - return in.err("unimplemented instruction"); -} - -template<typename Ctx> Result<typename Ctx::InstrT> makeArrayInitStatic(Ctx& ctx, ParseInput& in) { return in.err("unimplemented instruction"); } |