diff --git a/src/compiler.ts b/src/compiler.ts index 4341992c34..891a0f57e7 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -9965,8 +9965,14 @@ export class Compiler extends DiagnosticEmitter { case TypeKind.STRINGREF: case TypeKind.STRINGVIEW_WTF8: case TypeKind.STRINGVIEW_WTF16: - case TypeKind.STRINGVIEW_ITER: return module.ref_null(type.toRef()); - case TypeKind.I31REF: return module.i31_new(module.i32(0)); + case TypeKind.STRINGVIEW_ITER: { + // TODO: what if not nullable? + return module.ref_null(type.toRef()); + } + case TypeKind.I31REF: { + if (type.is(TypeFlags.NULLABLE)) return module.ref_null(type.toRef()); + return module.i31_new(module.i32(0)); + } } } diff --git a/src/types.ts b/src/types.ts index 9a2f0361d6..65d131dcdd 100644 --- a/src/types.ts +++ b/src/types.ts @@ -11,9 +11,12 @@ import { import { TypeRef, - createType + createType, + HeapTypeRef } from "./module"; +import * as binaryen from "./glue/binaryen"; + /** Indicates the kind of a type. */ export const enum TypeKind { /** A 1-bit unsigned integer. */ @@ -583,7 +586,7 @@ export class Type { /** Converts this type to its respective type reference. */ toRef(): TypeRef { switch (this.kind) { - default: assert(false); + default: assert(false); // TODO: Concrete struct, array and signature types case TypeKind.BOOL: case TypeKind.I8: case TypeKind.I16: @@ -598,17 +601,36 @@ export class Type { case TypeKind.F32: return TypeRef.F32; case TypeKind.F64: return TypeRef.F64; case TypeKind.V128: return TypeRef.V128; - // TODO: nullable/non-nullable refs have different type refs - case TypeKind.FUNCREF: return TypeRef.Funcref; - case TypeKind.EXTERNREF: return TypeRef.Externref; - case TypeKind.ANYREF: return TypeRef.Anyref; - case TypeKind.EQREF: return TypeRef.Eqref; - case TypeKind.I31REF: return TypeRef.I31ref; - case TypeKind.DATAREF: return TypeRef.Dataref; - case TypeKind.STRINGREF: return TypeRef.Stringref; - case TypeKind.STRINGVIEW_WTF8: return TypeRef.StringviewWTF8; - case TypeKind.STRINGVIEW_WTF16: return TypeRef.StringviewWTF16; - case TypeKind.STRINGVIEW_ITER: return TypeRef.StringviewIter; + case TypeKind.FUNCREF: { + return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Func, this.is(TypeFlags.NULLABLE)); + } + case TypeKind.EXTERNREF: { + return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Ext, this.is(TypeFlags.NULLABLE)); + } + case TypeKind.ANYREF: { + return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Any, this.is(TypeFlags.NULLABLE)); + } + case TypeKind.EQREF: { + return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Eq, this.is(TypeFlags.NULLABLE)); + } + case TypeKind.I31REF: { + return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.I31, this.is(TypeFlags.NULLABLE)); + } + case TypeKind.DATAREF: { + return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.Data, this.is(TypeFlags.NULLABLE)); + } + case TypeKind.STRINGREF: { + return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.String, this.is(TypeFlags.NULLABLE)); + } + case TypeKind.STRINGVIEW_WTF8: { + return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.StringviewWTF8, this.is(TypeFlags.NULLABLE)); + } + case TypeKind.STRINGVIEW_WTF16: { + return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.StringviewWTF16, this.is(TypeFlags.NULLABLE)); + } + case TypeKind.STRINGVIEW_ITER: { + return binaryen._BinaryenTypeFromHeapType(HeapTypeRef.StringviewIter, this.is(TypeFlags.NULLABLE)); + } case TypeKind.VOID: return TypeRef.None; } } diff --git a/tests/compiler/features/gc.debug.wat b/tests/compiler/features/gc.debug.wat index 00ca2b1702..1cfa57402d 100644 --- a/tests/compiler/features/gc.debug.wat +++ b/tests/compiler/features/gc.debug.wat @@ -3,6 +3,8 @@ (type $i32_i32_i32_i32_=>_none (func (param i32 i32 i32 i32))) (import "env" "abort" (func $~lib/builtins/abort (param i32 i32 i32 i32))) (global $features/gc/a anyref (ref.null any)) + (global $features/gc/b i31ref (ref.null i31)) + (global $features/gc/c dataref (ref.null data)) (global $~lib/memory/__data_end i32 (i32.const 60)) (global $~lib/memory/__stack_pointer (mut i32) (i32.const 16444)) (global $~lib/memory/__heap_base i32 (i32.const 16444)) @@ -12,10 +14,12 @@ (table $0 1 1 funcref) (elem $0 (i32.const 1)) (export "a" (global $features/gc/a)) + (export "b" (global $features/gc/b)) + (export "c" (global $features/gc/c)) (export "memory" (memory $0)) (export "_start" (func $~start)) (func $features/gc/test_i31 - (local $ref (ref i31)) + (local $ref i31ref) (local $val i32) (local $uval i32) i32.const 123 diff --git a/tests/compiler/features/gc.release.wat b/tests/compiler/features/gc.release.wat index 1bc02d535f..3f54908d37 100644 --- a/tests/compiler/features/gc.release.wat +++ b/tests/compiler/features/gc.release.wat @@ -1,10 +1,14 @@ (module (type $none_=>_none (func)) (global $features/gc/a anyref (ref.null any)) + (global $features/gc/b i31ref (ref.null i31)) + (global $features/gc/c dataref (ref.null data)) (memory $0 1) (data (i32.const 1036) ",") (data (i32.const 1048) "\01\00\00\00\1c\00\00\00f\00e\00a\00t\00u\00r\00e\00s\00/\00g\00c\00.\00t\00s") (export "a" (global $features/gc/a)) + (export "b" (global $features/gc/b)) + (export "c" (global $features/gc/c)) (export "memory" (memory $0)) (export "_start" (func $~start)) (func $~start diff --git a/tests/compiler/features/gc.ts b/tests/compiler/features/gc.ts index 4346bd1ba0..838b06e051 100644 --- a/tests/compiler/features/gc.ts +++ b/tests/compiler/features/gc.ts @@ -10,5 +10,5 @@ test_i31(); // constant globals export const a: anyref = null; -// export const b: i31ref = null; // TODO: not yet nullable in Binaryen -// export const c: dataref = null; // TODO: not yet nullable in Binaryen +export const b: i31ref = null; +export const c: dataref = null;