From 4381499ae206324744f44080efb868cf32820556 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Fri, 7 Mar 2025 17:26:51 -0800 Subject: [PATCH 1/2] Update finalization for exact references Update the finalization of all instructions whose types (or sent types) depend on their operand reference types to handle exact references correctly. Specifically, update `ref.as_non_null`, `br_on_null`, `br_on_non_null`, `br_on_cast`, and `br_on_cast_fail`. Also add TODOs on all instructions that allocate new heap objects to remind us to make their types exact in the future. --- src/wasm/wasm.cpp | 44 +++- test/lit/basic/exact-references.wast | 296 ++++++++++++++++++++++++--- 2 files changed, 305 insertions(+), 35 deletions(-) diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index d023109ce7c..c530aca984a 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -800,6 +800,7 @@ void MemoryGrow::finalize() { void RefNull::finalize(HeapType heapType) { assert(heapType.isBottom()); + // TODO: Make this exact. type = Type(heapType, Nullable); } @@ -922,6 +923,7 @@ static void populateTryTableSentTypes(TryTable* curr, Module* wasm) { // wasm spec defines when GC is enabled (=== non-nullable types are allowed). // If GC is not enabled then we emit a nullable type in the binary format in // WasmBinaryWriter::writeType. + // TODO: Make this exact. Type exnref = Type(HeapType::exn, NonNullable); for (Index i = 0; i < curr->catchTags.size(); i++) { auto tagName = curr->catchTags[i]; @@ -976,6 +978,7 @@ void RefI31::finalize() { if (value->type == Type::unreachable) { type = Type::unreachable; } else { + // TODO: Make this exact. assert(type.isRef() && type.getHeapType().isMaybeShared(HeapType::i31)); } } @@ -1011,10 +1014,12 @@ void CallRef::finalize() { // unreachable instead (and similar in other GC accessors), although this // would currently cause the parser to admit more invalid modules. if (type.isRef()) { + // TODO: Make this exact. type = Type(type.getHeapType().getBottom(), NonNullable); } else if (type.isTuple()) { Tuple elems; for (auto t : type) { + // TODO: Make this exact. elems.push_back( t.isRef() ? Type(t.getHeapType().getBottom(), NonNullable) : t); } @@ -1071,7 +1076,8 @@ void BrOn::finalize() { switch (op) { case BrOnNull: // If we do not branch, we flow out the existing value as non-null. - type = Type(ref->type.getHeapType(), NonNullable); + type = + Type(ref->type.getHeapType(), NonNullable, ref->type.getExactness()); break; case BrOnNonNull: // If we do not branch, we flow out nothing (the spec could also have had @@ -1081,7 +1087,8 @@ void BrOn::finalize() { case BrOnCast: if (castType.isNullable()) { // Nulls take the branch, so the result is non-nullable. - type = Type(ref->type.getHeapType(), NonNullable); + type = + Type(ref->type.getHeapType(), NonNullable, ref->type.getExactness()); } else { // Nulls do not take the branch, so the result is non-nullable only if // the input is. @@ -1092,7 +1099,9 @@ void BrOn::finalize() { if (castType.isNullable()) { // Nulls do not take the branch, so the result is non-nullable only if // the input is. - type = Type(castType.getHeapType(), ref->type.getNullability()); + type = Type(castType.getHeapType(), + ref->type.getNullability(), + castType.getExactness()); } else { // Nulls take the branch, so the result is non-nullable. type = castType; @@ -1115,11 +1124,14 @@ Type BrOn::getSentType() { return Type::unreachable; } // BrOnNonNull sends the non-nullable type on the branch. - return Type(ref->type.getHeapType(), NonNullable); + return Type( + ref->type.getHeapType(), NonNullable, ref->type.getExactness()); case BrOnCast: // The same as the result type of br_on_cast_fail. if (castType.isNullable()) { - return Type(castType.getHeapType(), ref->type.getNullability()); + return Type(castType.getHeapType(), + ref->type.getNullability(), + castType.getExactness()); } else { return castType; } @@ -1129,7 +1141,8 @@ Type BrOn::getSentType() { return Type::unreachable; } if (castType.isNullable()) { - return Type(ref->type.getHeapType(), NonNullable); + return Type( + ref->type.getHeapType(), NonNullable, ref->type.getExactness()); } else { return ref->type; } @@ -1150,6 +1163,7 @@ void StructGet::finalize() { } else if (ref->type.isNull()) { // See comment on CallRef for explanation. if (type.isRef()) { + // TODO: Make this exact. type = Type(type.getHeapType().getBottom(), NonNullable); } } else { @@ -1225,6 +1239,7 @@ void ArrayGet::finalize() { } else if (ref->type.isNull()) { // See comment on CallRef for explanation. if (type.isRef()) { + // TODO: Make this exact. type = Type(type.getHeapType().getBottom(), NonNullable); } } else { @@ -1300,17 +1315,20 @@ void RefAs::finalize() { return; } auto valHeapType = value->type.getHeapType(); + auto exactness = value->type.getExactness(); switch (op) { case RefAsNonNull: - type = Type(valHeapType, NonNullable); + type = Type(valHeapType, NonNullable, exactness); break; case AnyConvertExtern: type = Type(HeapTypes::any.getBasic(valHeapType.getShared()), - value->type.getNullability()); + value->type.getNullability(), + Inexact); break; case ExternConvertAny: type = Type(HeapTypes::ext.getBasic(valHeapType.getShared()), - value->type.getNullability()); + value->type.getNullability(), + Inexact); break; default: WASM_UNREACHABLE("invalid ref.as_*"); @@ -1323,11 +1341,15 @@ void StringNew::finalize() { (end && end->type == Type::unreachable)) { type = Type::unreachable; } else { + // TODO: Make this exact. type = Type(HeapType::string, NonNullable); } } -void StringConst::finalize() { type = Type(HeapType::string, NonNullable); } +void StringConst::finalize() { + // TODO: Make this exact. + type = Type(HeapType::string, NonNullable); +} void StringMeasure::finalize() { if (ref->type == Type::unreachable) { @@ -1350,6 +1372,7 @@ void StringConcat::finalize() { if (left->type == Type::unreachable || right->type == Type::unreachable) { type = Type::unreachable; } else { + // TODO: Make this exact. type = Type(HeapType::string, NonNullable); } } @@ -1375,6 +1398,7 @@ void StringSliceWTF::finalize() { end->type == Type::unreachable) { type = Type::unreachable; } else { + // TODO: Make this exact. type = Type(HeapType::string, NonNullable); } } diff --git a/test/lit/basic/exact-references.wast b/test/lit/basic/exact-references.wast index 6aec1ca4d89..e6c1599ea48 100644 --- a/test/lit/basic/exact-references.wast +++ b/test/lit/basic/exact-references.wast @@ -22,25 +22,41 @@ (type $foo (struct (field (exact anyref) (ref exact any) (ref null exact $foo) (ref exact $foo)))) - ;; CHECK-TEXT: (type $1 (func (param anyref) (result anyref))) + ;; CHECK-TEXT: (type $1 (func (param (exact anyref)) (result (ref exact any)))) - ;; CHECK-TEXT: (type $2 (func (param (exact i31ref)))) + ;; CHECK-TEXT: (type $2 (func (param anyref) (result anyref))) - ;; CHECK-TEXT: (type $3 (func (param (exact eqref)))) + ;; CHECK-TEXT: (type $3 (func (param (exact i31ref)))) + + ;; CHECK-TEXT: (type $4 (func (param (exact eqref)))) + + ;; CHECK-TEXT: (type $5 (func (param (exact anyref)))) + + ;; CHECK-TEXT: (type $6 (func (param (exact anyref)) (result (exact anyref)))) ;; CHECK-TEXT: (import "" "g1" (global $g1 (exact anyref))) - ;; CHECK-BIN: (type $1 (func (param anyref) (result anyref))) + ;; CHECK-BIN: (type $1 (func (param (exact anyref)) (result (ref exact any)))) + + ;; CHECK-BIN: (type $2 (func (param anyref) (result anyref))) + + ;; CHECK-BIN: (type $3 (func (param (exact i31ref)))) - ;; CHECK-BIN: (type $2 (func (param (exact i31ref)))) + ;; CHECK-BIN: (type $4 (func (param (exact eqref)))) - ;; CHECK-BIN: (type $3 (func (param (exact eqref)))) + ;; CHECK-BIN: (type $5 (func (param (exact anyref)))) + + ;; CHECK-BIN: (type $6 (func (param (exact anyref)) (result (exact anyref)))) ;; CHECK-BIN: (import "" "g1" (global $g1 (exact anyref))) ;; NO-EXACT: (type $1 (func (param anyref) (result anyref))) - ;; NO-EXACT: (type $2 (func (param i31ref))) + ;; NO-EXACT: (type $2 (func (param anyref) (result (ref any)))) + + ;; NO-EXACT: (type $3 (func (param i31ref))) - ;; NO-EXACT: (type $3 (func (param eqref))) + ;; NO-EXACT: (type $4 (func (param eqref))) + + ;; NO-EXACT: (type $5 (func (param anyref))) ;; NO-EXACT: (import "" "g1" (global $g1 anyref)) (import "" "g1" (global $g1 (exact anyref))) @@ -60,7 +76,7 @@ ;; NO-EXACT: (import "" "g4" (global $g4 (ref $foo))) (import "" "g4" (global $g4 (ref exact $foo))) - ;; CHECK-TEXT: (func $ref-test (type $2) (param $0 (exact i31ref)) + ;; CHECK-TEXT: (func $ref-test (type $3) (param $0 (exact i31ref)) ;; CHECK-TEXT-NEXT: (drop ;; CHECK-TEXT-NEXT: (ref.test (ref exact i31) ;; CHECK-TEXT-NEXT: (local.get $0) @@ -72,7 +88,7 @@ ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) - ;; CHECK-BIN: (func $ref-test (type $2) (param $0 (exact i31ref)) + ;; CHECK-BIN: (func $ref-test (type $3) (param $0 (exact i31ref)) ;; CHECK-BIN-NEXT: (drop ;; CHECK-BIN-NEXT: (ref.test (ref exact i31) ;; CHECK-BIN-NEXT: (local.get $0) @@ -84,7 +100,7 @@ ;; CHECK-BIN-NEXT: ) ;; CHECK-BIN-NEXT: ) ;; CHECK-BIN-NEXT: ) - ;; NO-EXACT: (func $ref-test (type $2) (param $0 i31ref) + ;; NO-EXACT: (func $ref-test (type $3) (param $0 i31ref) ;; NO-EXACT-NEXT: (drop ;; NO-EXACT-NEXT: (ref.test (ref i31) ;; NO-EXACT-NEXT: (local.get $0) @@ -109,7 +125,7 @@ ) ) - ;; CHECK-TEXT: (func $ref-cast (type $3) (param $0 (exact eqref)) + ;; CHECK-TEXT: (func $ref-cast (type $4) (param $0 (exact eqref)) ;; CHECK-TEXT-NEXT: (drop ;; CHECK-TEXT-NEXT: (ref.cast (ref exact eq) ;; CHECK-TEXT-NEXT: (local.get $0) @@ -126,7 +142,7 @@ ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) - ;; CHECK-BIN: (func $ref-cast (type $3) (param $0 (exact eqref)) + ;; CHECK-BIN: (func $ref-cast (type $4) (param $0 (exact eqref)) ;; CHECK-BIN-NEXT: (drop ;; CHECK-BIN-NEXT: (ref.cast (ref exact eq) ;; CHECK-BIN-NEXT: (local.get $0) @@ -143,7 +159,7 @@ ;; CHECK-BIN-NEXT: ) ;; CHECK-BIN-NEXT: ) ;; CHECK-BIN-NEXT: ) - ;; NO-EXACT: (func $ref-cast (type $3) (param $0 eqref) + ;; NO-EXACT: (func $ref-cast (type $4) (param $0 eqref) ;; NO-EXACT-NEXT: (drop ;; NO-EXACT-NEXT: (ref.cast (ref eq) ;; NO-EXACT-NEXT: (local.get $0) @@ -178,7 +194,7 @@ ) ) - ;; CHECK-TEXT: (func $br-on-cast (type $1) (param $0 anyref) (result anyref) + ;; CHECK-TEXT: (func $br-on-cast (type $2) (param $0 anyref) (result anyref) ;; CHECK-TEXT-NEXT: (block $label (result anyref) ;; CHECK-TEXT-NEXT: (drop ;; CHECK-TEXT-NEXT: (br_on_cast $label anyref (exact eqref) @@ -198,7 +214,7 @@ ;; CHECK-TEXT-NEXT: (local.get $0) ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) - ;; CHECK-BIN: (func $br-on-cast (type $1) (param $0 anyref) (result anyref) + ;; CHECK-BIN: (func $br-on-cast (type $2) (param $0 anyref) (result anyref) ;; CHECK-BIN-NEXT: (block $block (result anyref) ;; CHECK-BIN-NEXT: (drop ;; CHECK-BIN-NEXT: (br_on_cast $block anyref (exact eqref) @@ -257,7 +273,7 @@ (local.get 0) ) - ;; CHECK-TEXT: (func $br-on-cast-fail (type $1) (param $0 anyref) (result anyref) + ;; CHECK-TEXT: (func $br-on-cast-fail (type $2) (param $0 anyref) (result anyref) ;; CHECK-TEXT-NEXT: (block $label (result anyref) ;; CHECK-TEXT-NEXT: (drop ;; CHECK-TEXT-NEXT: (br_on_cast_fail $label anyref (exact eqref) @@ -277,7 +293,7 @@ ;; CHECK-TEXT-NEXT: (local.get $0) ;; CHECK-TEXT-NEXT: ) ;; CHECK-TEXT-NEXT: ) - ;; CHECK-BIN: (func $br-on-cast-fail (type $1) (param $0 anyref) (result anyref) + ;; CHECK-BIN: (func $br-on-cast-fail (type $2) (param $0 anyref) (result anyref) ;; CHECK-BIN-NEXT: (block $block (result anyref) ;; CHECK-BIN-NEXT: (drop ;; CHECK-BIN-NEXT: (br_on_cast_fail $block anyref (exact eqref) @@ -335,14 +351,197 @@ ) (local.get 0) ) + + ;; CHECK-TEXT: (func $valid-ref-as-non-null (type $1) (param $0 (exact anyref)) (result (ref exact any)) + ;; CHECK-TEXT-NEXT: (ref.as_non_null + ;; CHECK-TEXT-NEXT: (local.get $0) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $valid-ref-as-non-null (type $1) (param $0 (exact anyref)) (result (ref exact any)) + ;; CHECK-BIN-NEXT: (ref.as_non_null + ;; CHECK-BIN-NEXT: (local.get $0) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + ;; NO-EXACT: (func $valid-ref-as-non-null (type $2) (param $0 anyref) (result (ref any)) + ;; NO-EXACT-NEXT: (ref.as_non_null + ;; NO-EXACT-NEXT: (local.get $0) + ;; NO-EXACT-NEXT: ) + ;; NO-EXACT-NEXT: ) + (func $valid-ref-as-non-null (param (ref null exact any)) (result (ref exact any)) + (ref.as_non_null + (local.get 0) + ) + ) + + ;; CHECK-TEXT: (func $valid-br-on-null (type $5) (param $0 (exact anyref)) + ;; CHECK-TEXT-NEXT: (block $label + ;; CHECK-TEXT-NEXT: (drop + ;; CHECK-TEXT-NEXT: (block (result (ref exact any)) + ;; CHECK-TEXT-NEXT: (br_on_null $label + ;; CHECK-TEXT-NEXT: (local.get $0) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $valid-br-on-null (type $5) (param $0 (exact anyref)) + ;; CHECK-BIN-NEXT: (block $block + ;; CHECK-BIN-NEXT: (drop + ;; CHECK-BIN-NEXT: (br_on_null $block + ;; CHECK-BIN-NEXT: (local.get $0) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + ;; NO-EXACT: (func $valid-br-on-null (type $5) (param $0 anyref) + ;; NO-EXACT-NEXT: (block $block + ;; NO-EXACT-NEXT: (drop + ;; NO-EXACT-NEXT: (br_on_null $block + ;; NO-EXACT-NEXT: (local.get $0) + ;; NO-EXACT-NEXT: ) + ;; NO-EXACT-NEXT: ) + ;; NO-EXACT-NEXT: ) + ;; NO-EXACT-NEXT: ) + (func $valid-br-on-null (param (ref null exact any)) + (drop + (block (result (ref exact any)) + (br_on_null 1 + (local.get 0) + ) + ) + ) + ) + + ;; CHECK-TEXT: (func $valid-br-on-non-null (type $1) (param $0 (exact anyref)) (result (ref exact any)) + ;; CHECK-TEXT-NEXT: (block $label (result (ref exact any)) + ;; CHECK-TEXT-NEXT: (br_on_non_null $label + ;; CHECK-TEXT-NEXT: (local.get $0) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: (unreachable) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $valid-br-on-non-null (type $1) (param $0 (exact anyref)) (result (ref exact any)) + ;; CHECK-BIN-NEXT: (block $block (result (ref exact any)) + ;; CHECK-BIN-NEXT: (br_on_non_null $block + ;; CHECK-BIN-NEXT: (local.get $0) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: (unreachable) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + ;; NO-EXACT: (func $valid-br-on-non-null (type $2) (param $0 anyref) (result (ref any)) + ;; NO-EXACT-NEXT: (block $block (result (ref any)) + ;; NO-EXACT-NEXT: (br_on_non_null $block + ;; NO-EXACT-NEXT: (local.get $0) + ;; NO-EXACT-NEXT: ) + ;; NO-EXACT-NEXT: (unreachable) + ;; NO-EXACT-NEXT: ) + ;; NO-EXACT-NEXT: ) + (func $valid-br-on-non-null (param (ref null exact any)) (result (ref exact any)) + (br_on_non_null 0 + (local.get 0) + ) + (unreachable) + ) + + ;; CHECK-TEXT: (func $valid-br-on-cast (type $6) (param $0 (exact anyref)) (result (exact anyref)) + ;; CHECK-TEXT-NEXT: (block $label (result (exact anyref)) + ;; CHECK-TEXT-NEXT: (drop + ;; CHECK-TEXT-NEXT: (block (result (ref exact any)) + ;; CHECK-TEXT-NEXT: (br_on_cast $label (exact anyref) (exact anyref) + ;; CHECK-TEXT-NEXT: (local.get $0) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: (unreachable) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $valid-br-on-cast (type $6) (param $0 (exact anyref)) (result (exact anyref)) + ;; CHECK-BIN-NEXT: (block $block (result (exact anyref)) + ;; CHECK-BIN-NEXT: (drop + ;; CHECK-BIN-NEXT: (br_on_cast $block (exact anyref) (exact anyref) + ;; CHECK-BIN-NEXT: (local.get $0) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: (unreachable) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + ;; NO-EXACT: (func $valid-br-on-cast (type $1) (param $0 anyref) (result anyref) + ;; NO-EXACT-NEXT: (block $block (result anyref) + ;; NO-EXACT-NEXT: (drop + ;; NO-EXACT-NEXT: (br_on_cast $block anyref anyref + ;; NO-EXACT-NEXT: (local.get $0) + ;; NO-EXACT-NEXT: ) + ;; NO-EXACT-NEXT: ) + ;; NO-EXACT-NEXT: (unreachable) + ;; NO-EXACT-NEXT: ) + ;; NO-EXACT-NEXT: ) + (func $valid-br-on-cast (param (ref null exact any)) (result (ref null exact any)) + (drop + (block (result (ref exact any)) + (br_on_cast 1 (ref null exact any) (ref null exact any) + (local.get 0) + ) + ) + ) + (unreachable) + ) + + ;; CHECK-TEXT: (func $valid-br-on-cast-fail (type $1) (param $0 (exact anyref)) (result (ref exact any)) + ;; CHECK-TEXT-NEXT: (block $label (result (ref exact any)) + ;; CHECK-TEXT-NEXT: (drop + ;; CHECK-TEXT-NEXT: (block (result (exact anyref)) + ;; CHECK-TEXT-NEXT: (br_on_cast_fail $label (exact anyref) (exact anyref) + ;; CHECK-TEXT-NEXT: (local.get $0) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: (unreachable) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-TEXT-NEXT: ) + ;; CHECK-BIN: (func $valid-br-on-cast-fail (type $1) (param $0 (exact anyref)) (result (ref exact any)) + ;; CHECK-BIN-NEXT: (block $block (result (ref exact any)) + ;; CHECK-BIN-NEXT: (drop + ;; CHECK-BIN-NEXT: (br_on_cast_fail $block (exact anyref) (exact anyref) + ;; CHECK-BIN-NEXT: (local.get $0) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: (unreachable) + ;; CHECK-BIN-NEXT: ) + ;; CHECK-BIN-NEXT: ) + ;; NO-EXACT: (func $valid-br-on-cast-fail (type $2) (param $0 anyref) (result (ref any)) + ;; NO-EXACT-NEXT: (block $block (result (ref any)) + ;; NO-EXACT-NEXT: (drop + ;; NO-EXACT-NEXT: (br_on_cast_fail $block anyref anyref + ;; NO-EXACT-NEXT: (local.get $0) + ;; NO-EXACT-NEXT: ) + ;; NO-EXACT-NEXT: ) + ;; NO-EXACT-NEXT: (unreachable) + ;; NO-EXACT-NEXT: ) + ;; NO-EXACT-NEXT: ) + (func $valid-br-on-cast-fail (param (ref null exact any)) (result (ref exact any)) + (drop + (block (result (ref null exact any)) + (br_on_cast_fail 1 (ref null exact any) (ref null exact any) + (local.get 0) + ) + ) + ) + (unreachable) + ) ) ;; CHECK-BIN-NODEBUG: (type $0 (struct (field (exact anyref)) (field (ref exact any)) (field (ref null exact $0)) (field (ref exact $0)))) -;; CHECK-BIN-NODEBUG: (type $1 (func (param anyref) (result anyref))) +;; CHECK-BIN-NODEBUG: (type $1 (func (param (exact anyref)) (result (ref exact any)))) -;; CHECK-BIN-NODEBUG: (type $2 (func (param (exact i31ref)))) +;; CHECK-BIN-NODEBUG: (type $2 (func (param anyref) (result anyref))) -;; CHECK-BIN-NODEBUG: (type $3 (func (param (exact eqref)))) +;; CHECK-BIN-NODEBUG: (type $3 (func (param (exact i31ref)))) + +;; CHECK-BIN-NODEBUG: (type $4 (func (param (exact eqref)))) + +;; CHECK-BIN-NODEBUG: (type $5 (func (param (exact anyref)))) + +;; CHECK-BIN-NODEBUG: (type $6 (func (param (exact anyref)) (result (exact anyref)))) ;; CHECK-BIN-NODEBUG: (import "" "g1" (global $gimport$0 (exact anyref))) @@ -352,7 +551,7 @@ ;; CHECK-BIN-NODEBUG: (import "" "g4" (global $gimport$3 (ref exact $0))) -;; CHECK-BIN-NODEBUG: (func $0 (type $2) (param $0 (exact i31ref)) +;; CHECK-BIN-NODEBUG: (func $0 (type $3) (param $0 (exact i31ref)) ;; CHECK-BIN-NODEBUG-NEXT: (drop ;; CHECK-BIN-NODEBUG-NEXT: (ref.test (ref exact i31) ;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) @@ -365,7 +564,7 @@ ;; CHECK-BIN-NODEBUG-NEXT: ) ;; CHECK-BIN-NODEBUG-NEXT: ) -;; CHECK-BIN-NODEBUG: (func $1 (type $3) (param $0 (exact eqref)) +;; CHECK-BIN-NODEBUG: (func $1 (type $4) (param $0 (exact eqref)) ;; CHECK-BIN-NODEBUG-NEXT: (drop ;; CHECK-BIN-NODEBUG-NEXT: (ref.cast (ref exact eq) ;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) @@ -383,7 +582,7 @@ ;; CHECK-BIN-NODEBUG-NEXT: ) ;; CHECK-BIN-NODEBUG-NEXT: ) -;; CHECK-BIN-NODEBUG: (func $2 (type $1) (param $0 anyref) (result anyref) +;; CHECK-BIN-NODEBUG: (func $2 (type $2) (param $0 anyref) (result anyref) ;; CHECK-BIN-NODEBUG-NEXT: (block $block (result anyref) ;; CHECK-BIN-NODEBUG-NEXT: (drop ;; CHECK-BIN-NODEBUG-NEXT: (br_on_cast $block anyref (exact eqref) @@ -404,7 +603,7 @@ ;; CHECK-BIN-NODEBUG-NEXT: ) ;; CHECK-BIN-NODEBUG-NEXT: ) -;; CHECK-BIN-NODEBUG: (func $3 (type $1) (param $0 anyref) (result anyref) +;; CHECK-BIN-NODEBUG: (func $3 (type $2) (param $0 anyref) (result anyref) ;; CHECK-BIN-NODEBUG-NEXT: (block $block (result anyref) ;; CHECK-BIN-NODEBUG-NEXT: (drop ;; CHECK-BIN-NODEBUG-NEXT: (br_on_cast_fail $block anyref (exact eqref) @@ -424,3 +623,50 @@ ;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) ;; CHECK-BIN-NODEBUG-NEXT: ) ;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $4 (type $1) (param $0 (exact anyref)) (result (ref exact any)) +;; CHECK-BIN-NODEBUG-NEXT: (ref.as_non_null +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $5 (type $5) (param $0 (exact anyref)) +;; CHECK-BIN-NODEBUG-NEXT: (block $block +;; CHECK-BIN-NODEBUG-NEXT: (drop +;; CHECK-BIN-NODEBUG-NEXT: (br_on_null $block +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $6 (type $1) (param $0 (exact anyref)) (result (ref exact any)) +;; CHECK-BIN-NODEBUG-NEXT: (block $block (result (ref exact any)) +;; CHECK-BIN-NODEBUG-NEXT: (br_on_non_null $block +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: (unreachable) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $7 (type $6) (param $0 (exact anyref)) (result (exact anyref)) +;; CHECK-BIN-NODEBUG-NEXT: (block $block (result (exact anyref)) +;; CHECK-BIN-NODEBUG-NEXT: (drop +;; CHECK-BIN-NODEBUG-NEXT: (br_on_cast $block (exact anyref) (exact anyref) +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: (unreachable) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) + +;; CHECK-BIN-NODEBUG: (func $8 (type $1) (param $0 (exact anyref)) (result (ref exact any)) +;; CHECK-BIN-NODEBUG-NEXT: (block $block (result (ref exact any)) +;; CHECK-BIN-NODEBUG-NEXT: (drop +;; CHECK-BIN-NODEBUG-NEXT: (br_on_cast_fail $block (exact anyref) (exact anyref) +;; CHECK-BIN-NODEBUG-NEXT: (local.get $0) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: (unreachable) +;; CHECK-BIN-NODEBUG-NEXT: ) +;; CHECK-BIN-NODEBUG-NEXT: ) From 304bdb74fce3fa9cb950f477b4e78d398730dc63 Mon Sep 17 00:00:00 2001 From: Thomas Lively Date: Mon, 10 Mar 2025 16:16:27 -0700 Subject: [PATCH 2/2] inline variable as suggested --- src/wasm/wasm.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/wasm/wasm.cpp b/src/wasm/wasm.cpp index c530aca984a..fa12dd49cf5 100644 --- a/src/wasm/wasm.cpp +++ b/src/wasm/wasm.cpp @@ -1315,10 +1315,9 @@ void RefAs::finalize() { return; } auto valHeapType = value->type.getHeapType(); - auto exactness = value->type.getExactness(); switch (op) { case RefAsNonNull: - type = Type(valHeapType, NonNullable, exactness); + type = Type(valHeapType, NonNullable, value->type.getExactness()); break; case AnyConvertExtern: type = Type(HeapTypes::any.getBasic(valHeapType.getShared()),