Commit 3a639c3b authored by Matthias Liedtke's avatar Matthias Liedtke Committed by V8 LUCI CQ

[wasm-gc] Introduce extern null type noextern

noextern is the abstract null type for the extern type.

Bug: v8:7748
Change-Id: I03ac0daf3051f479e096f3d05f4fa7cbf03968f1
Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3810191Reviewed-by: 's avatarJakob Kummerow <jkummerow@chromium.org>
Commit-Queue: Matthias Liedtke <mliedtke@chromium.org>
Cr-Commit-Position: refs/heads/main@{#82276}
parent c1874ac3
...@@ -239,6 +239,7 @@ HeapType read_heap_type(Decoder* decoder, const byte* pc, ...@@ -239,6 +239,7 @@ HeapType read_heap_type(Decoder* decoder, const byte* pc,
case kArrayRefCode: case kArrayRefCode:
case kAnyRefCode: case kAnyRefCode:
case kNoneCode: case kNoneCode:
case kNoExternCode:
case kNoFuncCode: case kNoFuncCode:
if (!VALIDATE(enabled.has_gc())) { if (!VALIDATE(enabled.has_gc())) {
DecodeError<validate>( DecodeError<validate>(
...@@ -317,6 +318,7 @@ ValueType read_value_type(Decoder* decoder, const byte* pc, ...@@ -317,6 +318,7 @@ ValueType read_value_type(Decoder* decoder, const byte* pc,
case kArrayRefCode: case kArrayRefCode:
case kAnyRefCode: case kAnyRefCode:
case kNoneCode: case kNoneCode:
case kNoExternCode:
case kNoFuncCode: case kNoFuncCode:
if (!VALIDATE(enabled.has_gc())) { if (!VALIDATE(enabled.has_gc())) {
DecodeError<validate>( DecodeError<validate>(
......
...@@ -72,6 +72,7 @@ class HeapType { ...@@ -72,6 +72,7 @@ class HeapType {
kStringViewIter, // shorthand: z. kStringViewIter, // shorthand: z.
kNone, // kNone, //
kNoFunc, // kNoFunc, //
kNoExtern, //
// This value is used to represent failures in the parsing of heap types and // This value is used to represent failures in the parsing of heap types and
// does not correspond to a wasm heap type. It has to be last in this list. // does not correspond to a wasm heap type. It has to be last in this list.
kBottom kBottom
...@@ -103,6 +104,8 @@ class HeapType { ...@@ -103,6 +104,8 @@ class HeapType {
return HeapType(kStringViewIter); return HeapType(kStringViewIter);
case ValueTypeCode::kNoneCode: case ValueTypeCode::kNoneCode:
return HeapType(kNone); return HeapType(kNone);
case ValueTypeCode::kNoExternCode:
return HeapType(kNoExtern);
case ValueTypeCode::kNoFuncCode: case ValueTypeCode::kNoFuncCode:
return HeapType(kNoFunc); return HeapType(kNoFunc);
default: default:
...@@ -171,6 +174,8 @@ class HeapType { ...@@ -171,6 +174,8 @@ class HeapType {
return std::string("stringview_iter"); return std::string("stringview_iter");
case kNone: case kNone:
return std::string("none"); return std::string("none");
case kNoExtern:
return std::string("noextern");
case kNoFunc: case kNoFunc:
return std::string("nofunc"); return std::string("nofunc");
default: default:
...@@ -208,6 +213,8 @@ class HeapType { ...@@ -208,6 +213,8 @@ class HeapType {
return mask | kStringViewIterCode; return mask | kStringViewIterCode;
case kNone: case kNone:
return mask | kNoneCode; return mask | kNoneCode;
case kNoExtern:
return mask | kNoExternCode;
case kNoFunc: case kNoFunc:
return mask | kNoFuncCode; return mask | kNoFuncCode;
default: default:
...@@ -430,6 +437,7 @@ class ValueType { ...@@ -430,6 +437,7 @@ class ValueType {
// If {this} is (ref null $t), returns (ref $t). Otherwise, returns {this}. // If {this} is (ref null $t), returns (ref $t). Otherwise, returns {this}.
constexpr ValueType AsNonNull() const { constexpr ValueType AsNonNull() const {
if (is_reference_to(HeapType::kNone) || if (is_reference_to(HeapType::kNone) ||
is_reference_to(HeapType::kNoExtern) ||
is_reference_to(HeapType::kNoFunc)) { is_reference_to(HeapType::kNoFunc)) {
// Non-null none type is not a valid type. // Non-null none type is not a valid type.
return ValueType::Primitive(kBottom); return ValueType::Primitive(kBottom);
...@@ -556,6 +564,8 @@ class ValueType { ...@@ -556,6 +564,8 @@ class ValueType {
return kStringViewIterCode; return kStringViewIterCode;
case HeapType::kNone: case HeapType::kNone:
return kNoneCode; return kNoneCode;
case HeapType::kNoExtern:
return kNoExternCode;
case HeapType::kNoFunc: case HeapType::kNoFunc:
return kNoFuncCode; return kNoFuncCode;
default: default:
...@@ -701,6 +711,8 @@ constexpr ValueType kWasmStringViewWtf16 = ...@@ -701,6 +711,8 @@ constexpr ValueType kWasmStringViewWtf16 =
constexpr ValueType kWasmStringViewIter = constexpr ValueType kWasmStringViewIter =
ValueType::RefNull(HeapType::kStringViewIter); ValueType::RefNull(HeapType::kStringViewIter);
constexpr ValueType kWasmNullRef = ValueType::RefNull(HeapType::kNone); constexpr ValueType kWasmNullRef = ValueType::RefNull(HeapType::kNone);
constexpr ValueType kWasmNullExternRef =
ValueType::RefNull(HeapType::kNoExtern);
constexpr ValueType kWasmNullFuncRef = ValueType::RefNull(HeapType::kNoFunc); constexpr ValueType kWasmNullFuncRef = ValueType::RefNull(HeapType::kNoFunc);
// Constants used by the generic js-to-wasm wrapper. // Constants used by the generic js-to-wasm wrapper.
......
...@@ -39,6 +39,7 @@ enum ValueTypeCode : uint8_t { ...@@ -39,6 +39,7 @@ enum ValueTypeCode : uint8_t {
kFuncRefCode = 0x70, kFuncRefCode = 0x70,
// TODO(7784): Switch to official opcodes once they are aligned with the // TODO(7784): Switch to official opcodes once they are aligned with the
// stringref proposal for nofunc and noextern. // stringref proposal for nofunc and noextern.
kNoExternCode = 0x69,
kNoFuncCode = 0x68, kNoFuncCode = 0x68,
kExternRefCode = 0x6f, kExternRefCode = 0x6f,
// typed-funcref and GC proposal types // typed-funcref and GC proposal types
......
...@@ -107,17 +107,18 @@ HeapType::Representation NullSentinel(HeapType type, const WasmModule* module) { ...@@ -107,17 +107,18 @@ HeapType::Representation NullSentinel(HeapType type, const WasmModule* module) {
case HeapType::kData: case HeapType::kData:
case HeapType::kArray: case HeapType::kArray:
case HeapType::kAny: case HeapType::kAny:
case HeapType::kExtern: // TODO(mliedtke): Add noextern.
case HeapType::kString: case HeapType::kString:
case HeapType::kStringViewWtf8: case HeapType::kStringViewWtf8:
case HeapType::kStringViewWtf16: case HeapType::kStringViewWtf16:
case HeapType::kStringViewIter: case HeapType::kStringViewIter:
return HeapType::kNone; return HeapType::kNone;
case HeapType::kExtern:
case HeapType::kNoExtern:
return HeapType::kNoExtern;
case HeapType::kFunc: case HeapType::kFunc:
case HeapType::kNoFunc: case HeapType::kNoFunc:
return HeapType::kNoFunc; return HeapType::kNoFunc;
default: default:
// TODO(mliedtke): Add noextern.
return module->has_signature(type.ref_index()) ? HeapType::kNoFunc return module->has_signature(type.ref_index()) ? HeapType::kNoFunc
: HeapType::kNone; : HeapType::kNone;
} }
...@@ -126,8 +127,8 @@ HeapType::Representation NullSentinel(HeapType type, const WasmModule* module) { ...@@ -126,8 +127,8 @@ HeapType::Representation NullSentinel(HeapType type, const WasmModule* module) {
bool IsNullSentinel(HeapType type) { bool IsNullSentinel(HeapType type) {
switch (type.representation()) { switch (type.representation()) {
case HeapType::kNone: case HeapType::kNone:
case HeapType::kNoExtern:
case HeapType::kNoFunc: case HeapType::kNoFunc:
// TODO(mliedtke): Add noextern.
return true; return true;
default: default:
return false; return false;
...@@ -228,11 +229,15 @@ V8_NOINLINE V8_EXPORT_PRIVATE bool IsHeapSubtypeOfImpl( ...@@ -228,11 +229,15 @@ V8_NOINLINE V8_EXPORT_PRIVATE bool IsHeapSubtypeOfImpl(
case HeapType::kNone: case HeapType::kNone:
// none is a subtype of every non-func, non-extern reference type under // none is a subtype of every non-func, non-extern reference type under
// wasm-gc. // wasm-gc.
// TODO(mliedtke): Break-up extern and nullref subtyping.
if (super_heap.is_index()) { if (super_heap.is_index()) {
return !super_module->has_signature(super_heap.ref_index()); return !super_module->has_signature(super_heap.ref_index());
} }
return super_heap != HeapType::kFunc && super_heap != HeapType::kNoFunc; return super_heap != HeapType::kFunc && super_heap != HeapType::kNoFunc &&
super_heap != HeapType::kExtern &&
super_heap != HeapType::kNoExtern;
case HeapType::kNoExtern:
return super_heap == HeapType::kNoExtern ||
super_heap == HeapType::kExtern;
case HeapType::kNoFunc: case HeapType::kNoFunc:
// nofunc is a subtype of every funcref type under wasm-gc. // nofunc is a subtype of every funcref type under wasm-gc.
if (super_heap.is_index()) { if (super_heap.is_index()) {
...@@ -268,6 +273,7 @@ V8_NOINLINE V8_EXPORT_PRIVATE bool IsHeapSubtypeOfImpl( ...@@ -268,6 +273,7 @@ V8_NOINLINE V8_EXPORT_PRIVATE bool IsHeapSubtypeOfImpl(
case HeapType::kBottom: case HeapType::kBottom:
UNREACHABLE(); UNREACHABLE();
case HeapType::kNone: case HeapType::kNone:
case HeapType::kNoExtern:
case HeapType::kNoFunc: case HeapType::kNoFunc:
// Abstract null types are not supertypes for any index type. // Abstract null types are not supertypes for any index type.
return false; return false;
...@@ -391,6 +397,7 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1, ...@@ -391,6 +397,7 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1,
return HeapType::kAny; return HeapType::kAny;
case HeapType::kFunc: case HeapType::kFunc:
case HeapType::kExtern: case HeapType::kExtern:
case HeapType::kNoExtern:
case HeapType::kNoFunc: case HeapType::kNoFunc:
UNREACHABLE(); UNREACHABLE();
default: default:
...@@ -410,6 +417,7 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1, ...@@ -410,6 +417,7 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1,
return HeapType::kAny; return HeapType::kAny;
case HeapType::kFunc: case HeapType::kFunc:
case HeapType::kExtern: case HeapType::kExtern:
case HeapType::kNoExtern:
case HeapType::kNoFunc: case HeapType::kNoFunc:
UNREACHABLE(); UNREACHABLE();
default: default:
...@@ -430,6 +438,7 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1, ...@@ -430,6 +438,7 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1,
return HeapType::kAny; return HeapType::kAny;
case HeapType::kFunc: case HeapType::kFunc:
case HeapType::kExtern: case HeapType::kExtern:
case HeapType::kNoExtern:
case HeapType::kNoFunc: case HeapType::kNoFunc:
UNREACHABLE(); UNREACHABLE();
default: default:
...@@ -452,6 +461,7 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1, ...@@ -452,6 +461,7 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1,
case HeapType::kEq: case HeapType::kEq:
case HeapType::kAny: case HeapType::kAny:
case HeapType::kExtern: case HeapType::kExtern:
case HeapType::kNoExtern:
UNREACHABLE(); UNREACHABLE();
case HeapType::kNoFunc: case HeapType::kNoFunc:
return HeapType::kNoFunc; return HeapType::kNoFunc;
...@@ -462,6 +472,11 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1, ...@@ -462,6 +472,11 @@ HeapType::Representation CommonAncestorWithGeneric(HeapType heap1,
? heap2.representation() ? heap2.representation()
: HeapType::kBottom; : HeapType::kBottom;
} }
case HeapType::kNoExtern:
return heap2.representation() == HeapType::kExtern ? HeapType::kExtern
: HeapType::kNoExtern;
case HeapType::kExtern:
return HeapType::kExtern;
default: default:
UNREACHABLE(); UNREACHABLE();
} }
......
...@@ -1546,7 +1546,7 @@ WASM_COMPILED_EXEC_TEST(CallAbstractNullTypeImplicitConversion) { ...@@ -1546,7 +1546,7 @@ WASM_COMPILED_EXEC_TEST(CallAbstractNullTypeImplicitConversion) {
{kWasmDataRef.AsNullable(), kNoneCode}, {kWasmDataRef.AsNullable(), kNoneCode},
{kWasmArrayRef.AsNullable(), kNoneCode}, {kWasmArrayRef.AsNullable(), kNoneCode},
{kWasmAnyRef, kNoneCode}, {kWasmAnyRef, kNoneCode},
{kWasmExternRef, kNoneCode}, {kWasmExternRef, kNoExternCode},
{refNull(0), kNoneCode}, // struct {refNull(0), kNoneCode}, // struct
{refNull(1), kNoneCode}, // array {refNull(1), kNoneCode}, // array
{refNull(2), kNoFuncCode}, // signature {refNull(2), kNoFuncCode}, // signature
......
...@@ -2142,6 +2142,19 @@ TEST_F(FunctionBodyDecoderTest, NullRefGlobals) { ...@@ -2142,6 +2142,19 @@ TEST_F(FunctionBodyDecoderTest, NullRefGlobals) {
&sig, {WASM_GLOBAL_SET(0, WASM_REF_NULL(kNoneCode)), WASM_LOCAL_GET(0)}); &sig, {WASM_GLOBAL_SET(0, WASM_REF_NULL(kNoneCode)), WASM_LOCAL_GET(0)});
} }
TEST_F(FunctionBodyDecoderTest, NullExternRefGlobals) {
WASM_FEATURE_SCOPE(gc);
ValueType nullExternRefs[] = {kWasmNullExternRef, kWasmNullExternRef,
kWasmNullExternRef};
FunctionSig sig(1, 2, nullExternRefs);
builder.AddGlobal(kWasmNullExternRef);
ExpectValidates(&sig, {WASM_GLOBAL_GET(0)});
ExpectValidates(&sig,
{WASM_GLOBAL_SET(0, WASM_LOCAL_GET(0)), WASM_LOCAL_GET(0)});
ExpectValidates(&sig, {WASM_GLOBAL_SET(0, WASM_REF_NULL(kNoExternCode)),
WASM_LOCAL_GET(0)});
}
TEST_F(FunctionBodyDecoderTest, NullFuncRefGlobals) { TEST_F(FunctionBodyDecoderTest, NullFuncRefGlobals) {
WASM_FEATURE_SCOPE(gc); WASM_FEATURE_SCOPE(gc);
ValueType nullFuncRefs[] = {kWasmNullFuncRef, kWasmNullFuncRef, ValueType nullFuncRefs[] = {kWasmNullFuncRef, kWasmNullFuncRef,
......
...@@ -189,6 +189,7 @@ struct ValueTypePair { ...@@ -189,6 +189,7 @@ struct ValueTypePair {
{kFuncRefCode, kWasmFuncRef}, // -- {kFuncRefCode, kWasmFuncRef}, // --
{kNoFuncCode, kWasmNullFuncRef}, // -- {kNoFuncCode, kWasmNullFuncRef}, // --
{kExternRefCode, kWasmExternRef}, // -- {kExternRefCode, kWasmExternRef}, // --
{kNoExternCode, kWasmNullExternRef}, // --
{kAnyRefCode, kWasmAnyRef}, // -- {kAnyRefCode, kWasmAnyRef}, // --
{kEqRefCode, kWasmEqRef}, // -- {kEqRefCode, kWasmEqRef}, // --
{kI31RefCode, kWasmI31Ref}, // -- {kI31RefCode, kWasmI31Ref}, // --
......
...@@ -129,13 +129,14 @@ TEST_F(WasmSubtypingTest, Subtyping) { ...@@ -129,13 +129,14 @@ TEST_F(WasmSubtypingTest, Subtyping) {
constexpr ValueType numeric_types[] = {kWasmI32, kWasmI64, kWasmF32, kWasmF64, constexpr ValueType numeric_types[] = {kWasmI32, kWasmI64, kWasmF32, kWasmF64,
kWasmS128}; kWasmS128};
constexpr ValueType ref_types[] = { constexpr ValueType ref_types[] = {
// TODO(mliedtke): Add externref kWasmFuncRef, kWasmEqRef, // --
kWasmFuncRef, kWasmEqRef, kWasmI31Ref, // -- kWasmDataRef, kWasmArrayRef, // --
kWasmDataRef, kWasmArrayRef, kWasmAnyRef, // -- kWasmI31Ref, kWasmAnyRef, // --
kWasmNullRef, kWasmNullFuncRef, // -- kWasmExternRef, kWasmNullExternRef, // --
refNull(0), ref(0), // struct kWasmNullRef, kWasmNullFuncRef, // --
refNull(2), ref(2), // array refNull(0), ref(0), // struct
refNull(11), ref(11) // signature refNull(2), ref(2), // array
refNull(11), ref(11) // signature
}; };
// Some macros to help managing types and modules. // Some macros to help managing types and modules.
...@@ -192,6 +193,8 @@ TEST_F(WasmSubtypingTest, Subtyping) { ...@@ -192,6 +193,8 @@ TEST_F(WasmSubtypingTest, Subtyping) {
} }
for (ValueType ref_type : ref_types) { for (ValueType ref_type : ref_types) {
const bool is_extern =
ref_type == kWasmExternRef || ref_type == kWasmNullExternRef;
const bool is_any_func = ref_type == kWasmFuncRef || const bool is_any_func = ref_type == kWasmFuncRef ||
ref_type == kWasmNullFuncRef || ref_type == kWasmNullFuncRef ||
ref_type == refNull(11) || ref_type == ref(11); ref_type == refNull(11) || ref_type == ref(11);
...@@ -199,7 +202,7 @@ TEST_F(WasmSubtypingTest, Subtyping) { ...@@ -199,7 +202,7 @@ TEST_F(WasmSubtypingTest, Subtyping) {
// Concrete reference types, i31ref and dataref are subtypes of eqref, // Concrete reference types, i31ref and dataref are subtypes of eqref,
// externref/funcref/anyref/functions are not. // externref/funcref/anyref/functions are not.
SUBTYPE_IFF(ref_type, kWasmEqRef, SUBTYPE_IFF(ref_type, kWasmEqRef,
ref_type != kWasmAnyRef && !is_any_func); ref_type != kWasmAnyRef && !is_any_func && !is_extern);
// Struct/array types are subtypes of dataref. // Struct/array types are subtypes of dataref.
SUBTYPE_IFF(ref_type, kWasmDataRef, SUBTYPE_IFF(ref_type, kWasmDataRef,
ref_type == kWasmDataRef || ref_type == kWasmArrayRef || ref_type == kWasmDataRef || ref_type == kWasmArrayRef ||
...@@ -215,16 +218,17 @@ TEST_F(WasmSubtypingTest, Subtyping) { ...@@ -215,16 +218,17 @@ TEST_F(WasmSubtypingTest, Subtyping) {
// Each reference type is a subtype of itself. // Each reference type is a subtype of itself.
SUBTYPE(ref_type, ref_type); SUBTYPE(ref_type, ref_type);
// Each non-func, non-extern reference type is a subtype of anyref. // Each non-func, non-extern reference type is a subtype of anyref.
SUBTYPE_IFF(ref_type, kWasmAnyRef, !is_any_func); SUBTYPE_IFF(ref_type, kWasmAnyRef, !is_any_func && !is_extern);
// Only anyref is a subtype of anyref. // Only anyref is a subtype of anyref.
SUBTYPE_IFF(kWasmAnyRef, ref_type, ref_type == kWasmAnyRef); SUBTYPE_IFF(kWasmAnyRef, ref_type, ref_type == kWasmAnyRef);
// TODO(mliedtke): Improve test coverage for externref. // Only externref and nullexternref are subtypes of externref.
// Only externref is a subtype of externref. SUBTYPE_IFF(ref_type, kWasmExternRef, is_extern);
NOT_SUBTYPE(kWasmExternRef, ref_type); // Only nullexternref is a subtype of nullexternref.
SUBTYPE_IFF(ref_type, kWasmNullExternRef, ref_type == kWasmNullExternRef);
// Each nullable non-func, non-extern reference type is a supertype of // Each nullable non-func, non-extern reference type is a supertype of
// nullref. // nullref.
SUBTYPE_IFF(kWasmNullRef, ref_type, SUBTYPE_IFF(kWasmNullRef, ref_type,
ref_type.is_nullable() && !is_any_func); ref_type.is_nullable() && !is_any_func && !is_extern);
// Only nullref is a subtype of nullref. // Only nullref is a subtype of nullref.
SUBTYPE_IFF(ref_type, kWasmNullRef, ref_type == kWasmNullRef); SUBTYPE_IFF(ref_type, kWasmNullRef, ref_type == kWasmNullRef);
// Only nullable funcs are supertypes of nofunc. // Only nullable funcs are supertypes of nofunc.
...@@ -348,8 +352,9 @@ TEST_F(WasmSubtypingTest, Subtyping) { ...@@ -348,8 +352,9 @@ TEST_F(WasmSubtypingTest, Subtyping) {
UNION(type, type, type); UNION(type, type, type);
INTERSECTION(type, type, type); INTERSECTION(type, type, type);
if (type == kWasmFuncRef || type == kWasmNullFuncRef || type == ref(11) || if (type == kWasmFuncRef || type == kWasmNullFuncRef || type == ref(11) ||
type == refNull(11)) { type == refNull(11) || type == kWasmExternRef ||
// functypes don't share the same type hierarchy as anyref. type == kWasmNullExternRef) {
// func and extern types don't share the same type hierarchy as anyref.
INTERSECTION(type, kWasmAnyRef, kWasmBottom); INTERSECTION(type, kWasmAnyRef, kWasmBottom);
continue; continue;
} }
...@@ -377,12 +382,30 @@ TEST_F(WasmSubtypingTest, Subtyping) { ...@@ -377,12 +382,30 @@ TEST_F(WasmSubtypingTest, Subtyping) {
kWasmEqRef.AsNonNull()); kWasmEqRef.AsNonNull());
UNION(kWasmDataRef, kWasmArrayRef, kWasmDataRef); UNION(kWasmDataRef, kWasmArrayRef, kWasmDataRef);
UNION(kWasmI31Ref.AsNonNull(), kWasmArrayRef, kWasmEqRef); UNION(kWasmI31Ref.AsNonNull(), kWasmArrayRef, kWasmEqRef);
UNION(kWasmAnyRef, kWasmNullRef, kWasmAnyRef);
UNION(kWasmExternRef, kWasmNullExternRef, kWasmExternRef);
UNION(kWasmFuncRef, kWasmNullFuncRef, kWasmFuncRef);
INTERSECTION(kWasmExternRef, kWasmEqRef, kWasmBottom);
INTERSECTION(kWasmExternRef, kWasmDataRef, kWasmBottom);
INTERSECTION(kWasmExternRef, kWasmI31Ref.AsNonNull(), kWasmBottom);
INTERSECTION(kWasmExternRef, kWasmArrayRef, kWasmBottom);
INTERSECTION(kWasmExternRef, kWasmNullRef, kWasmBottom);
INTERSECTION(kWasmExternRef, kWasmFuncRef, kWasmBottom);
INTERSECTION(kWasmNullExternRef, kWasmEqRef, kWasmBottom);
INTERSECTION(kWasmNullExternRef, kWasmDataRef, kWasmBottom);
INTERSECTION(kWasmNullExternRef, kWasmI31Ref, kWasmBottom);
INTERSECTION(kWasmNullExternRef, kWasmArrayRef, kWasmBottom);
INTERSECTION(kWasmNullExternRef, kWasmNullRef, kWasmBottom);
INTERSECTION(kWasmNullExternRef, kWasmExternRef, kWasmNullExternRef);
INTERSECTION(kWasmNullExternRef, kWasmExternRef.AsNonNull(), kWasmBottom);
INTERSECTION(kWasmFuncRef, kWasmEqRef, kWasmBottom); INTERSECTION(kWasmFuncRef, kWasmEqRef, kWasmBottom);
INTERSECTION(kWasmFuncRef, kWasmDataRef, kWasmBottom); INTERSECTION(kWasmFuncRef, kWasmDataRef, kWasmBottom);
INTERSECTION(kWasmFuncRef, kWasmI31Ref.AsNonNull(), kWasmBottom); INTERSECTION(kWasmFuncRef, kWasmI31Ref.AsNonNull(), kWasmBottom);
INTERSECTION(kWasmFuncRef, kWasmArrayRef, kWasmBottom); INTERSECTION(kWasmFuncRef, kWasmArrayRef, kWasmBottom);
INTERSECTION(kWasmFuncRef, kWasmNullRef, kWasmBottom); INTERSECTION(kWasmFuncRef, kWasmNullRef, kWasmBottom);
INTERSECTION(kWasmFuncRef, kWasmNullExternRef, kWasmBottom);
INTERSECTION(kWasmNullFuncRef, kWasmEqRef, kWasmBottom); INTERSECTION(kWasmNullFuncRef, kWasmEqRef, kWasmBottom);
INTERSECTION(kWasmNullFuncRef, kWasmDataRef, kWasmBottom); INTERSECTION(kWasmNullFuncRef, kWasmDataRef, kWasmBottom);
INTERSECTION(kWasmNullFuncRef, kWasmI31Ref, kWasmBottom); INTERSECTION(kWasmNullFuncRef, kWasmI31Ref, kWasmBottom);
...@@ -390,6 +413,8 @@ TEST_F(WasmSubtypingTest, Subtyping) { ...@@ -390,6 +413,8 @@ TEST_F(WasmSubtypingTest, Subtyping) {
INTERSECTION(kWasmNullFuncRef, kWasmNullRef, kWasmBottom); INTERSECTION(kWasmNullFuncRef, kWasmNullRef, kWasmBottom);
INTERSECTION(kWasmNullFuncRef, kWasmFuncRef, kWasmNullFuncRef); INTERSECTION(kWasmNullFuncRef, kWasmFuncRef, kWasmNullFuncRef);
INTERSECTION(kWasmNullFuncRef, kWasmFuncRef.AsNonNull(), kWasmBottom); INTERSECTION(kWasmNullFuncRef, kWasmFuncRef.AsNonNull(), kWasmBottom);
INTERSECTION(kWasmNullFuncRef, kWasmNullExternRef, kWasmBottom);
INTERSECTION(kWasmEqRef, kWasmDataRef, kWasmDataRef); INTERSECTION(kWasmEqRef, kWasmDataRef, kWasmDataRef);
INTERSECTION(kWasmEqRef, kWasmI31Ref, kWasmI31Ref); INTERSECTION(kWasmEqRef, kWasmI31Ref, kWasmI31Ref);
INTERSECTION(kWasmEqRef, kWasmArrayRef, kWasmArrayRef); INTERSECTION(kWasmEqRef, kWasmArrayRef, kWasmArrayRef);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment