diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/cost.h | 8 | ||||
-rw-r--r-- | src/ir/effects.h | 7 | ||||
-rw-r--r-- | src/passes/Print.cpp | 22 | ||||
-rw-r--r-- | src/wasm-builder.h | 10 | ||||
-rw-r--r-- | src/wasm-delegations-fields.h | 6 | ||||
-rw-r--r-- | src/wasm-type.h | 2 | ||||
-rw-r--r-- | src/wasm.h | 10 | ||||
-rw-r--r-- | src/wasm/wasm-binary.cpp | 22 | ||||
-rw-r--r-- | src/wasm/wasm-s-parser.cpp | 18 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 18 | ||||
-rw-r--r-- | src/wasm/wasm.cpp | 19 |
12 files changed, 103 insertions, 45 deletions
diff --git a/src/ir/cost.h b/src/ir/cost.h index b71e1ea0e..66a316bf6 100644 --- a/src/ir/cost.h +++ b/src/ir/cost.h @@ -560,8 +560,12 @@ struct CostAnalyzer : public OverriddenVisitor<CostAnalyzer, Index> { Index visitDataDrop(DataDrop* curr) { return 5; } Index visitI31New(I31New* curr) { return 3 + visit(curr->value); } Index visitI31Get(I31Get* curr) { return 2 + visit(curr->i31); } - Index visitRefTest(RefTest* curr) { WASM_UNREACHABLE("TODO: GC"); } - Index visitRefCast(RefCast* curr) { WASM_UNREACHABLE("TODO: GC"); } + Index visitRefTest(RefTest* curr) { + return 2 + nullCheckCost(curr->ref) + visit(curr->ref) + visit(curr->rtt); + } + Index visitRefCast(RefCast* curr) { + return 2 + nullCheckCost(curr->ref) + visit(curr->ref) + visit(curr->rtt); + } Index visitBrOnCast(BrOnCast* curr) { WASM_UNREACHABLE("TODO: GC"); } Index visitRttCanon(RttCanon* curr) { // TODO: investigate actual RTT costs in VMs diff --git a/src/ir/effects.h b/src/ir/effects.h index 94387c2cf..3cbddc491 100644 --- a/src/ir/effects.h +++ b/src/ir/effects.h @@ -545,11 +545,10 @@ private: // traps when the arg is null parent.implicitTrap = true; } - void visitRefTest(RefTest* curr) { - WASM_UNREACHABLE("TODO (gc): ref.test"); - } + void visitRefTest(RefTest* curr) {} void visitRefCast(RefCast* curr) { - WASM_UNREACHABLE("TODO (gc): ref.cast"); + // Traps if the ref is not null and it has an invalid rtt. + parent.implicitTrap = true; } void visitBrOnCast(BrOnCast* curr) { WASM_UNREACHABLE("TODO (gc): br_on_cast"); diff --git a/src/passes/Print.cpp b/src/passes/Print.cpp index 694b1b118..4007b6daa 100644 --- a/src/passes/Print.cpp +++ b/src/passes/Print.cpp @@ -1692,12 +1692,12 @@ struct PrintExpressionContents } } void visitRefTest(RefTest* curr) { - printMedium(o, "ref.test"); - WASM_UNREACHABLE("TODO (gc): ref.test"); + printMedium(o, "ref.test "); + printHeapTypeName(o, curr->rtt->type.getHeapType()); } void visitRefCast(RefCast* curr) { - printMedium(o, "ref.cast"); - WASM_UNREACHABLE("TODO (gc): ref.cast"); + printMedium(o, "ref.cast "); + printHeapTypeName(o, curr->rtt->type.getHeapType()); } void visitBrOnCast(BrOnCast* curr) { printMedium(o, "br_on_cast"); @@ -1717,7 +1717,7 @@ struct PrintExpressionContents o << "default_"; } o << "with_rtt "; - printHeapTypeName(o, curr->rtt->type.getRtt().heapType); + printHeapTypeName(o, curr->rtt->type.getHeapType()); } void visitStructGet(StructGet* curr) { const auto& field = @@ -1747,7 +1747,7 @@ struct PrintExpressionContents o << "default_"; } o << "with_rtt "; - printHeapTypeName(o, curr->rtt->type.getRtt().heapType); + printHeapTypeName(o, curr->rtt->type.getHeapType()); } void visitArrayGet(ArrayGet* curr) { const auto& element = curr->ref->type.getHeapType().getArray().element; @@ -2394,12 +2394,18 @@ struct PrintSExpression : public OverriddenVisitor<PrintSExpression> { void visitRefTest(RefTest* curr) { o << '('; PrintExpressionContents(currFunction, o).visit(curr); - WASM_UNREACHABLE("TODO (gc): ref.test"); + incIndent(); + printFullLine(curr->ref); + printFullLine(curr->rtt); + decIndent(); } void visitRefCast(RefCast* curr) { o << '('; PrintExpressionContents(currFunction, o).visit(curr); - WASM_UNREACHABLE("TODO (gc): ref.cast"); + incIndent(); + printFullLine(curr->ref); + printFullLine(curr->rtt); + decIndent(); } void visitBrOnCast(BrOnCast* curr) { o << '('; diff --git a/src/wasm-builder.h b/src/wasm-builder.h index 73c8f9823..59c8d4c1b 100644 --- a/src/wasm-builder.h +++ b/src/wasm-builder.h @@ -691,15 +691,17 @@ public: ret->finalize(); return ret; } - RefTest* makeRefTest() { + RefTest* makeRefTest(Expression* ref, Expression* rtt) { auto* ret = wasm.allocator.alloc<RefTest>(); - WASM_UNREACHABLE("TODO (gc): ref.test"); + ret->ref = ref; + ret->rtt = rtt; ret->finalize(); return ret; } - RefCast* makeRefCast() { + RefCast* makeRefCast(Expression* ref, Expression* rtt) { auto* ret = wasm.allocator.alloc<RefCast>(); - WASM_UNREACHABLE("TODO (gc): ref.cast"); + ret->ref = ref; + ret->rtt = rtt; ret->finalize(); return ret; } diff --git a/src/wasm-delegations-fields.h b/src/wasm-delegations-fields.h index b90bf720b..d53af695f 100644 --- a/src/wasm-delegations-fields.h +++ b/src/wasm-delegations-fields.h @@ -559,13 +559,15 @@ switch (DELEGATE_ID) { } case Expression::Id::RefTestId: { DELEGATE_START(RefTest); - WASM_UNREACHABLE("TODO (gc): ref.test"); + DELEGATE_FIELD_CHILD(RefTest, ref); + DELEGATE_FIELD_CHILD(RefTest, rtt); DELEGATE_END(RefTest); break; } case Expression::Id::RefCastId: { DELEGATE_START(RefCast); - WASM_UNREACHABLE("TODO (gc): ref.cast"); + DELEGATE_FIELD_CHILD(RefCast, ref); + DELEGATE_FIELD_CHILD(RefCast, rtt); DELEGATE_END(RefCast); break; } diff --git a/src/wasm-type.h b/src/wasm-type.h index a76e30b42..0df515f79 100644 --- a/src/wasm-type.h +++ b/src/wasm-type.h @@ -352,7 +352,7 @@ struct Tuple { std::string toString() const; // Prevent accidental copies - Struct& operator=(const Struct&) = delete; + Tuple& operator=(const Tuple&) = delete; private: void validate() { diff --git a/src/wasm.h b/src/wasm.h index 0cc2f430c..0c6566407 100644 --- a/src/wasm.h +++ b/src/wasm.h @@ -1310,14 +1310,20 @@ class RefTest : public SpecificExpression<Expression::RefTestId> { public: RefTest(MixedArena& allocator) {} - void finalize() { WASM_UNREACHABLE("TODO (gc): ref.test"); } + Expression* ref; + Expression* rtt; + + void finalize(); }; class RefCast : public SpecificExpression<Expression::RefCastId> { public: RefCast(MixedArena& allocator) {} - void finalize() { WASM_UNREACHABLE("TODO (gc): ref.cast"); } + Expression* ref; + Expression* rtt; + + void finalize(); }; class BrOnCast : public SpecificExpression<Expression::BrOnCastId> { diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 0c68264a3..1b3d50a41 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -5599,10 +5599,13 @@ bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) { if (code != BinaryConsts::RefTest) { return false; } - auto* curr = allocator.alloc<RefTest>(); - WASM_UNREACHABLE("TODO (gc): ref.test"); - curr->finalize(); - out = curr; + auto heapType1 = getHeapType(); + auto heapType2 = getHeapType(); + auto* ref = popNonVoidExpression(); + validateHeapTypeUsingChild(ref, heapType1); + auto* rtt = popNonVoidExpression(); + validateHeapTypeUsingChild(rtt, heapType2); + out = Builder(wasm).makeRefTest(ref, rtt); return true; } @@ -5610,10 +5613,13 @@ bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) { if (code != BinaryConsts::RefCast) { return false; } - auto* curr = allocator.alloc<RefCast>(); - WASM_UNREACHABLE("TODO (gc): ref.cast"); - curr->finalize(); - out = curr; + auto heapType1 = getHeapType(); + auto heapType2 = getHeapType(); + auto* ref = popNonVoidExpression(); + validateHeapTypeUsingChild(ref, heapType1); + auto* rtt = popNonVoidExpression(); + validateHeapTypeUsingChild(rtt, heapType2); + out = Builder(wasm).makeRefCast(ref, rtt); return true; } diff --git a/src/wasm/wasm-s-parser.cpp b/src/wasm/wasm-s-parser.cpp index b9f321b14..85bc2aba9 100644 --- a/src/wasm/wasm-s-parser.cpp +++ b/src/wasm/wasm-s-parser.cpp @@ -2093,17 +2093,19 @@ Expression* SExpressionWasmBuilder::makeI31Get(Element& s, bool signed_) { } Expression* SExpressionWasmBuilder::makeRefTest(Element& s) { - auto ret = allocator.alloc<RefTest>(); - WASM_UNREACHABLE("TODO (gc): ref.test"); - ret->finalize(); - return ret; + auto heapType = parseHeapType(*s[1]); + auto* ref = parseExpression(*s[2]); + auto* rtt = parseExpression(*s[3]); + validateHeapTypeUsingChild(rtt, heapType, s); + return Builder(wasm).makeRefTest(ref, rtt); } Expression* SExpressionWasmBuilder::makeRefCast(Element& s) { - auto ret = allocator.alloc<RefCast>(); - WASM_UNREACHABLE("TODO (gc): ref.cast"); - ret->finalize(); - return ret; + auto heapType = parseHeapType(*s[1]); + auto* ref = parseExpression(*s[2]); + auto* rtt = parseExpression(*s[3]); + validateHeapTypeUsingChild(rtt, heapType, s); + return Builder(wasm).makeRefCast(ref, rtt); } Expression* SExpressionWasmBuilder::makeBrOnCast(Element& s) { diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 60c352c5d..741aef5ce 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -1882,12 +1882,14 @@ void BinaryInstWriter::visitCallRef(CallRef* curr) { void BinaryInstWriter::visitRefTest(RefTest* curr) { o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefTest); - WASM_UNREACHABLE("TODO (gc): ref.test"); + parent.writeHeapType(curr->ref->type.getHeapType()); + parent.writeHeapType(curr->rtt->type.getHeapType()); } void BinaryInstWriter::visitRefCast(RefCast* curr) { o << int8_t(BinaryConsts::GCPrefix) << U32LEB(BinaryConsts::RefCast); - WASM_UNREACHABLE("TODO (gc): ref.cast"); + parent.writeHeapType(curr->ref->type.getHeapType()); + parent.writeHeapType(curr->rtt->type.getHeapType()); } void BinaryInstWriter::visitBrOnCast(BrOnCast* curr) { diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index cf92cf4d3..56cf9c114 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -2192,13 +2192,27 @@ void FunctionValidator::visitI31Get(I31Get* curr) { void FunctionValidator::visitRefTest(RefTest* curr) { shouldBeTrue( getModule()->features.hasGC(), curr, "ref.test requires gc to be enabled"); - WASM_UNREACHABLE("TODO (gc): ref.test"); + if (curr->ref->type != Type::unreachable) { + shouldBeTrue( + curr->ref->type.isRef(), curr, "ref.test ref must have ref type"); + } + if (curr->rtt->type != Type::unreachable) { + shouldBeTrue( + curr->rtt->type.isRtt(), curr, "ref.test rtt must have rtt type"); + } } void FunctionValidator::visitRefCast(RefCast* curr) { shouldBeTrue( getModule()->features.hasGC(), curr, "ref.cast requires gc to be enabled"); - WASM_UNREACHABLE("TODO (gc): ref.cast"); + if (curr->ref->type != Type::unreachable) { + shouldBeTrue( + curr->ref->type.isRef(), curr, "ref.test ref must have ref type"); + } + if (curr->rtt->type != Type::unreachable) { + shouldBeTrue( + curr->rtt->type.isRtt(), curr, "ref.test rtt must have rtt type"); + } } void FunctionValidator::visitBrOnCast(BrOnCast* curr) { diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index 2eed06981..93a14aecc 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -1080,8 +1080,23 @@ void CallRef::finalize(Type type_) { finalize(); } -// TODO (gc): ref.test -// TODO (gc): ref.cast +void RefTest::finalize() { + if (ref->type == Type::unreachable || rtt->type == Type::unreachable) { + type = Type::unreachable; + } else { + type = Type::i32; + } +} + +void RefCast::finalize() { + if (ref->type == Type::unreachable || rtt->type == Type::unreachable) { + type = Type::unreachable; + } else { + // TODO: make non-nullable when we support that + type = Type(rtt->type.getHeapType(), /* nullable = */ true); + } +} + // TODO (gc): br_on_cast void RttCanon::finalize() { |