diff options
author | Thomas Lively <tlively@google.com> | 2022-12-08 11:50:45 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-12-08 09:50:45 -0800 |
commit | 48959ab5a74d849e9782f54b3535c6fca69d51d7 (patch) | |
tree | b6da926b399636eb2cfc34ce6adbdc24b8488bcc /src | |
parent | 2cb5cefb6392619d908ce2ab683815d7e22ac9a5 (diff) | |
download | binaryen-48959ab5a74d849e9782f54b3535c6fca69d51d7.tar.gz binaryen-48959ab5a74d849e9782f54b3535c6fca69d51d7.tar.bz2 binaryen-48959ab5a74d849e9782f54b3535c6fca69d51d7.zip |
Allow casting to basic heap types (#5332)
The standard casting instructions now allow casting to basic heap types, not
just user-defined types, but they also require that the intended type and
argument type have a common supertype. Update the validator to use the standard
rules, update the binary parser and printer to allow basic types, and update the
tests to remove or modify newly invalid test cases.
Diffstat (limited to 'src')
-rw-r--r-- | src/wasm/wasm-binary.cpp | 11 | ||||
-rw-r--r-- | src/wasm/wasm-stack.cpp | 6 | ||||
-rw-r--r-- | src/wasm/wasm-validator.cpp | 61 |
3 files changed, 44 insertions, 34 deletions
diff --git a/src/wasm/wasm-binary.cpp b/src/wasm/wasm-binary.cpp index 7b2922d3c..996ee8cf6 100644 --- a/src/wasm/wasm-binary.cpp +++ b/src/wasm/wasm-binary.cpp @@ -6894,7 +6894,8 @@ bool WasmBinaryBuilder::maybeVisitI31Get(Expression*& out, uint32_t code) { bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) { if (code == BinaryConsts::RefTestStatic || code == BinaryConsts::RefTest) { - auto intendedType = getIndexedHeapType(); + bool legacy = code == BinaryConsts::RefTestStatic; + auto intendedType = legacy ? getIndexedHeapType() : getHeapType(); auto* ref = popNonVoidExpression(); out = Builder(wasm).makeRefTest(ref, intendedType); return true; @@ -6905,7 +6906,9 @@ bool WasmBinaryBuilder::maybeVisitRefTest(Expression*& out, uint32_t code) { bool WasmBinaryBuilder::maybeVisitRefCast(Expression*& out, uint32_t code) { if (code == BinaryConsts::RefCastStatic || code == BinaryConsts::RefCastNull || code == BinaryConsts::RefCastNop) { - auto intendedType = getIndexedHeapType(); + bool legacy = + code == BinaryConsts::RefCastStatic || code == BinaryConsts::RefCastNop; + auto intendedType = legacy ? getIndexedHeapType() : getHeapType(); auto* ref = popNonVoidExpression(); auto safety = code == BinaryConsts::RefCastNop ? RefCast::Unsafe : RefCast::Safe; @@ -6956,7 +6959,9 @@ bool WasmBinaryBuilder::maybeVisitBrOn(Expression*& out, uint32_t code) { auto name = getBreakTarget(getU32LEB()).name; HeapType intendedType; if (op == BrOnCast || op == BrOnCastFail) { - intendedType = getIndexedHeapType(); + bool legacy = code == BinaryConsts::BrOnCastStatic || + code == BinaryConsts::BrOnCastStaticFail; + intendedType = legacy ? getIndexedHeapType() : getHeapType(); } auto* ref = popNonVoidExpression(); out = Builder(wasm).makeBrOn(op, name, ref, intendedType); diff --git a/src/wasm/wasm-stack.cpp b/src/wasm/wasm-stack.cpp index 1f477a10c..c4b9598c7 100644 --- a/src/wasm/wasm-stack.cpp +++ b/src/wasm/wasm-stack.cpp @@ -2026,7 +2026,7 @@ void BinaryInstWriter::visitCallRef(CallRef* curr) { void BinaryInstWriter::visitRefTest(RefTest* curr) { o << int8_t(BinaryConsts::GCPrefix); o << U32LEB(BinaryConsts::RefTest); - parent.writeIndexedHeapType(curr->intendedType); + parent.writeHeapType(curr->intendedType); } void BinaryInstWriter::visitRefCast(RefCast* curr) { @@ -2036,7 +2036,7 @@ void BinaryInstWriter::visitRefCast(RefCast* curr) { } else { o << U32LEB(BinaryConsts::RefCastNull); } - parent.writeIndexedHeapType(curr->intendedType); + parent.writeHeapType(curr->intendedType); } void BinaryInstWriter::visitBrOn(BrOn* curr) { @@ -2078,7 +2078,7 @@ void BinaryInstWriter::visitBrOn(BrOn* curr) { } o << U32LEB(getBreakIndex(curr->name)); if (curr->op == BrOnCast || curr->op == BrOnCastFail) { - parent.writeIndexedHeapType(curr->intendedType); + parent.writeHeapType(curr->intendedType); } } diff --git a/src/wasm/wasm-validator.cpp b/src/wasm/wasm-validator.cpp index ba8712d35..16b6f5314 100644 --- a/src/wasm/wasm-validator.cpp +++ b/src/wasm/wasm-validator.cpp @@ -2504,49 +2504,54 @@ void FunctionValidator::visitI31Get(I31Get* curr) { void FunctionValidator::visitRefTest(RefTest* curr) { shouldBeTrue( getModule()->features.hasGC(), curr, "ref.test requires gc [--enable-gc]"); - if (curr->ref->type != Type::unreachable) { - shouldBeTrue( - curr->ref->type.isRef(), curr, "ref.test ref must have ref type"); + if (curr->ref->type == Type::unreachable) { + return; } - shouldBeUnequal(curr->intendedType, - HeapType(), - curr, - "static ref.test must set intendedType field"); - shouldBeTrue( - !curr->intendedType.isBasic(), curr, "ref.test must test a non-basic"); + if (!shouldBeTrue( + curr->ref->type.isRef(), curr, "ref.test ref must have ref type")) { + return; + } + shouldBeEqual( + curr->intendedType.getBottom(), + curr->ref->type.getHeapType().getBottom(), + curr, + "ref.test target type and ref type must have a common supertype"); } void FunctionValidator::visitRefCast(RefCast* curr) { shouldBeTrue( getModule()->features.hasGC(), curr, "ref.cast requires gc [--enable-gc]"); - if (curr->ref->type != Type::unreachable) { - shouldBeTrue( - curr->ref->type.isRef(), curr, "ref.cast ref must have ref type"); + if (curr->ref->type == Type::unreachable) { + return; } - 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"); + if (!shouldBeTrue( + curr->ref->type.isRef(), curr, "ref.cast ref must have ref type")) { + return; + } + shouldBeEqual( + curr->intendedType.getBottom(), + curr->ref->type.getHeapType().getBottom(), + curr, + "ref.cast target type and ref type must have a common supertype"); } void FunctionValidator::visitBrOn(BrOn* curr) { shouldBeTrue(getModule()->features.hasGC(), curr, "br_on_cast requires gc [--enable-gc]"); - if (curr->ref->type != Type::unreachable) { - shouldBeTrue( - curr->ref->type.isRef(), curr, "br_on_cast ref must have ref type"); + if (curr->ref->type == Type::unreachable) { + return; + } + if (!shouldBeTrue( + curr->ref->type.isRef(), curr, "br_on_cast ref must have ref type")) { + return; } if (curr->op == BrOnCast || curr->op == BrOnCastFail) { - 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"); + shouldBeEqual( + curr->intendedType.getBottom(), + curr->ref->type.getHeapType().getBottom(), + curr, + "br_on_cast* target type and ref type must have a common supertype"); } else { shouldBeEqual(curr->intendedType, HeapType(), |