diff --git a/src/builtins.ts b/src/builtins.ts index 6e8cd28d4e..5ab67dc454 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -127,10 +127,11 @@ export namespace BuiltinNames { export const trace = "~lib/builtins/trace"; export const seed = "~lib/builtins/seed"; - export const isInteger = "~lib/builtins/isInteger"; - export const isFloat = "~lib/builtins/isFloat"; export const isBoolean = "~lib/builtins/isBoolean"; + export const isInteger = "~lib/builtins/isInteger"; export const isSigned = "~lib/builtins/isSigned"; + export const isFloat = "~lib/builtins/isFloat"; + export const isVector = "~lib/builtins/isVector"; export const isReference = "~lib/builtins/isReference"; export const isString = "~lib/builtins/isString"; export const isArray = "~lib/builtins/isArray"; @@ -758,6 +759,17 @@ export const function_builtins = new Map Express // === Static type evaluation ================================================================= +// isBoolean() / isBoolean(value: T) -> bool +function builtin_isBoolean(ctx: BuiltinContext): ExpressionRef { + var compiler = ctx.compiler; + var module = compiler.module; + var type = checkConstantType(ctx); + compiler.currentType = Type.bool; + if (!type) return module.unreachable(); + return reifyConstantType(ctx, module.i32(type.isBooleanValue ? 1 : 0)); +} +builtins.set(BuiltinNames.isBoolean, builtin_isBoolean); + // isInteger() / isInteger(value: T) -> bool function builtin_isInteger(ctx: BuiltinContext): ExpressionRef { var compiler = ctx.compiler; @@ -769,38 +781,38 @@ function builtin_isInteger(ctx: BuiltinContext): ExpressionRef { } builtins.set(BuiltinNames.isInteger, builtin_isInteger); -// isFloat() / isFloat(value: T) -> bool -function builtin_isFloat(ctx: BuiltinContext): ExpressionRef { +// isSigned() / isSigned(value: T) -> bool +function builtin_isSigned(ctx: BuiltinContext): ExpressionRef { var compiler = ctx.compiler; var module = compiler.module; var type = checkConstantType(ctx); compiler.currentType = Type.bool; if (!type) return module.unreachable(); - return reifyConstantType(ctx, module.i32(type.isFloatValue ? 1 : 0)); + return reifyConstantType(ctx, module.i32(type.isSignedIntegerValue ? 1 : 0)); } -builtins.set(BuiltinNames.isFloat, builtin_isFloat); +builtins.set(BuiltinNames.isSigned, builtin_isSigned); -// isBoolean() / isBoolean(value: T) -> bool -function builtin_isBoolean(ctx: BuiltinContext): ExpressionRef { +// isFloat() / isFloat(value: T) -> bool +function builtin_isFloat(ctx: BuiltinContext): ExpressionRef { var compiler = ctx.compiler; var module = compiler.module; var type = checkConstantType(ctx); compiler.currentType = Type.bool; if (!type) return module.unreachable(); - return reifyConstantType(ctx, module.i32(type.isBooleanValue ? 1 : 0)); + return reifyConstantType(ctx, module.i32(type.isFloatValue ? 1 : 0)); } -builtins.set(BuiltinNames.isBoolean, builtin_isBoolean); +builtins.set(BuiltinNames.isFloat, builtin_isFloat); -// isSigned() / isSigned(value: T) -> bool -function builtin_isSigned(ctx: BuiltinContext): ExpressionRef { +// isVector() / isVector(value: T) -> bool +function builtin_isVector(ctx: BuiltinContext): ExpressionRef { var compiler = ctx.compiler; var module = compiler.module; var type = checkConstantType(ctx); compiler.currentType = Type.bool; if (!type) return module.unreachable(); - return reifyConstantType(ctx, module.i32(type.isSignedIntegerValue ? 1 : 0)); + return reifyConstantType(ctx, module.i32(type.isVectorValue ? 1 : 0)); } -builtins.set(BuiltinNames.isSigned, builtin_isSigned); +builtins.set(BuiltinNames.isVector, builtin_isVector); // isReference() / isReference(value: T) -> bool function builtin_isReference(ctx: BuiltinContext): ExpressionRef { diff --git a/std/assembly/builtins.ts b/std/assembly/builtins.ts index 20a7bd9fc3..3cbe42a94c 100644 --- a/std/assembly/builtins.ts +++ b/std/assembly/builtins.ts @@ -1,20 +1,24 @@ type auto = i32; +// @ts-ignore: decorator +@builtin +export declare function isBoolean(value?: T): bool; + // @ts-ignore: decorator @builtin export declare function isInteger(value?: T): bool; // @ts-ignore: decorator @builtin -export declare function isFloat(value?: T): bool; +export declare function isSigned(value?: T): bool; // @ts-ignore: decorator @builtin -export declare function isBoolean(value?: T): bool; +export declare function isFloat(value?: T): bool; // @ts-ignore: decorator @builtin -export declare function isSigned(value?: T): bool; +export declare function isVector(value?: T): bool; // @ts-ignore: decorator @builtin diff --git a/std/assembly/index.d.ts b/std/assembly/index.d.ts index 7c741f027d..32d70052d0 100644 --- a/std/assembly/index.d.ts +++ b/std/assembly/index.d.ts @@ -196,14 +196,16 @@ declare function instantiate(...args: any[]): T; declare function isNaN(value: T): bool; /** Tests if a 32-bit or 64-bit float is finite, that is not `NaN` or +/-`Infinity`. */ declare function isFinite(value: T): bool; -/** Tests if the specified type *or* expression is of an integer type and not a reference. Compiles to a constant. */ -declare function isInteger(value?: any): value is number; -/** Tests if the specified type *or* expression is of a float type. Compiles to a constant. */ -declare function isFloat(value?: any): value is number; /** Tests if the specified type *or* expression is of a boolean type. */ declare function isBoolean(value?: any): value is number; +/** Tests if the specified type *or* expression is of an integer type and not a reference. Compiles to a constant. */ +declare function isInteger(value?: any): value is number; /** Tests if the specified type *or* expression can represent negative numbers. Compiles to a constant. */ declare function isSigned(value?: any): value is number; +/** Tests if the specified type *or* expression is of a float type. Compiles to a constant. */ +declare function isFloat(value?: any): value is number; +/** Tests if the specified type *or* expression is of a v128 type. Compiles to a constant. */ +declare function isVector(value?: any): value is v128; /** Tests if the specified type *or* expression is of a reference type. Compiles to a constant. */ declare function isReference(value?: any): value is object | string; /** Tests if the specified type *or* expression can be used as a string. Compiles to a constant. */ diff --git a/tests/compiler/simd.debug.wat b/tests/compiler/simd.debug.wat index 2c62812e5d..1ee5517225 100644 --- a/tests/compiler/simd.debug.wat +++ b/tests/compiler/simd.debug.wat @@ -4657,6 +4657,16 @@ (func $start:simd i32.const 1 drop + i32.const 1 + drop + i32.const 0 + i32.eqz + drop + i32.const 1 + drop + i32.const 0 + i32.eqz + drop call $simd/test_v128 call $simd/test_i8x16 call $simd/test_i16x8 diff --git a/tests/compiler/simd.ts b/tests/compiler/simd.ts index 857aa280a7..0efcb864d6 100644 --- a/tests/compiler/simd.ts +++ b/tests/compiler/simd.ts @@ -760,6 +760,13 @@ export function test_vars_f64x2_full(a: f64, b: f64): v128 { } if (ASC_FEATURE_SIMD) { + // test builtins + assert(isVector()); + assert(!isVector()); + + assert(isVector(i32x4.splat(0))); + assert(!isVector(0)); + test_v128(); test_i8x16(); test_i16x8();