diff --git a/src/builtins.ts b/src/builtins.ts index fd7dfae38e..91558c0466 100644 --- a/src/builtins.ts +++ b/src/builtins.ts @@ -161,6 +161,8 @@ export namespace BuiltinNames { export const reinterpret = "~lib/builtins/reinterpret"; export const sqrt = "~lib/builtins/sqrt"; export const trunc = "~lib/builtins/trunc"; + export const eq = "~lib/builtins/eq"; + export const ne = "~lib/builtins/ne"; export const load = "~lib/builtins/load"; export const store = "~lib/builtins/store"; export const atomic_load = "~lib/builtins/atomic.load"; @@ -258,6 +260,15 @@ export namespace BuiltinNames { export const f32_div = "~lib/builtins/f32.div"; export const f64_div = "~lib/builtins/f64.div"; + export const i32_eq = "~lib/builtins/i32.eq"; + export const i64_eq = "~lib/builtins/i64.eq"; + export const f32_eq = "~lib/builtins/f32.eq"; + export const f64_eq = "~lib/builtins/f64.eq"; + export const i32_ne = "~lib/builtins/i32.ne"; + export const i64_ne = "~lib/builtins/i64.ne"; + export const f32_ne = "~lib/builtins/f32.ne"; + export const f64_ne = "~lib/builtins/f64.ne"; + export const i32_load8_s = "~lib/builtins/i32.load8_s"; export const i32_load8_u = "~lib/builtins/i32.load8_u"; export const i32_load16_s = "~lib/builtins/i32.load16_s"; @@ -2436,6 +2447,116 @@ function builtin_div(ctx: BuiltinContext): ExpressionRef { } builtins.set(BuiltinNames.div, builtin_div); +// eq(left: T, right: T) -> i32 +function builtin_eq(ctx: BuiltinContext): ExpressionRef { + var compiler = ctx.compiler; + var module = compiler.module; + if (checkTypeOptional(ctx, true) | checkArgsRequired(ctx, 2)) { + return module.unreachable(); + } + var operands = ctx.operands; + var typeArguments = ctx.typeArguments; + var left = operands[0]; + var arg0 = typeArguments + ? compiler.compileExpression( + left, + typeArguments[0], + Constraints.CONV_IMPLICIT + ) + : compiler.compileExpression(operands[0], Type.auto); + var type = compiler.currentType; + if (type.isValue) { + let arg1: ExpressionRef; + if (!typeArguments && left.isNumericLiteral) { + // prefer right type + arg1 = compiler.compileExpression( + operands[1], + type + ); + if (compiler.currentType != type) { + arg0 = compiler.compileExpression( + left, + (type = compiler.currentType), + Constraints.CONV_IMPLICIT + ); + } + } else { + arg1 = compiler.compileExpression( + operands[1], + type, + Constraints.CONV_IMPLICIT + ); + } + if (type.isNumericValue) { + compiler.currentType = Type.i32; + return compiler.makeEq(arg0, arg1, type, ctx.reportNode); + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + ctx.reportNode.typeArgumentsRange, + "eq", + type.toString() + ); + return module.unreachable(); +} +builtins.set(BuiltinNames.eq, builtin_eq); + +// ne(left: T, right: T) -> i32 +function builtin_ne(ctx: BuiltinContext): ExpressionRef { + var compiler = ctx.compiler; + var module = compiler.module; + if (checkTypeOptional(ctx, true) | checkArgsRequired(ctx, 2)) { + return module.unreachable(); + } + var operands = ctx.operands; + var typeArguments = ctx.typeArguments; + var left = operands[0]; + var arg0 = typeArguments + ? compiler.compileExpression( + left, + typeArguments[0], + Constraints.CONV_IMPLICIT + ) + : compiler.compileExpression(operands[0], Type.auto); + var type = compiler.currentType; + if (type.isValue) { + let arg1: ExpressionRef; + if (!typeArguments && left.isNumericLiteral) { + // prefer right type + arg1 = compiler.compileExpression( + operands[1], + type + ); + if (compiler.currentType != type) { + arg0 = compiler.compileExpression( + left, + (type = compiler.currentType), + Constraints.CONV_IMPLICIT + ); + } + } else { + arg1 = compiler.compileExpression( + operands[1], + type, + Constraints.CONV_IMPLICIT + ); + } + if (type.isNumericValue) { + compiler.currentType = Type.i32; + return compiler.makeNe(arg0, arg1, type, ctx.reportNode); + } + } + compiler.error( + DiagnosticCode.Operation_0_cannot_be_applied_to_type_1, + ctx.reportNode.typeArgumentsRange, + "ne", + type.toString() + ); + return module.unreachable(); +} +builtins.set(BuiltinNames.ne, builtin_ne); + // === Atomics ================================================================================ // atomic.load(offset: usize, immOffset?: usize) -> T* @@ -6679,6 +6800,78 @@ function builtin_f64_div(ctx: BuiltinContext): ExpressionRef { } builtins.set(BuiltinNames.f64_div, builtin_f64_div); +// i32.eq -> eq +function builtin_i32_eq(ctx: BuiltinContext): ExpressionRef { + checkTypeAbsent(ctx); + ctx.typeArguments = [ Type.i32 ]; + ctx.contextualType = Type.i32; + return builtin_eq(ctx); +} +builtins.set(BuiltinNames.i32_eq, builtin_i32_eq); + +// i64.eq -> eq +function builtin_i64_eq(ctx: BuiltinContext): ExpressionRef { + checkTypeAbsent(ctx); + ctx.typeArguments = [ Type.i64 ]; + ctx.contextualType = Type.i32; + return builtin_eq(ctx); +} +builtins.set(BuiltinNames.i64_eq, builtin_i64_eq); + +// f32.eq -> eq +function builtin_f32_eq(ctx: BuiltinContext): ExpressionRef { + checkTypeAbsent(ctx); + ctx.typeArguments = [ Type.f32 ]; + ctx.contextualType = Type.i32; + return builtin_eq(ctx); +} +builtins.set(BuiltinNames.f32_eq, builtin_f32_eq); + +// f64.eq -> eq +function builtin_f64_eq(ctx: BuiltinContext): ExpressionRef { + checkTypeAbsent(ctx); + ctx.typeArguments = [ Type.f64 ]; + ctx.contextualType = Type.i32; + return builtin_eq(ctx); +} +builtins.set(BuiltinNames.f64_eq, builtin_f64_eq); + +// i32.ne -> ne +function builtin_i32_ne(ctx: BuiltinContext): ExpressionRef { + checkTypeAbsent(ctx); + ctx.typeArguments = [ Type.i32 ]; + ctx.contextualType = Type.i32; + return builtin_ne(ctx); +} +builtins.set(BuiltinNames.i32_ne, builtin_i32_ne); + +// i64.ne -> ne +function builtin_i64_ne(ctx: BuiltinContext): ExpressionRef { + checkTypeAbsent(ctx); + ctx.typeArguments = [ Type.i64 ]; + ctx.contextualType = Type.i32; + return builtin_ne(ctx); +} +builtins.set(BuiltinNames.i64_ne, builtin_i64_ne); + +// f32.ne -> ne +function builtin_f32_ne(ctx: BuiltinContext): ExpressionRef { + checkTypeAbsent(ctx); + ctx.typeArguments = [ Type.f32 ]; + ctx.contextualType = Type.i32; + return builtin_ne(ctx); +} +builtins.set(BuiltinNames.f32_ne, builtin_f32_ne); + +// f64.ne-> ne +function builtin_f64_ne(ctx: BuiltinContext): ExpressionRef { + checkTypeAbsent(ctx); + ctx.typeArguments = [ Type.f64 ]; + ctx.contextualType = Type.i32; + return builtin_ne(ctx); +} +builtins.set(BuiltinNames.f64_ne, builtin_f64_ne); + // i32.load8_s -> load function builtin_i32_load8_s(ctx: BuiltinContext): ExpressionRef { checkTypeAbsent(ctx); diff --git a/std/assembly/builtins.ts b/std/assembly/builtins.ts index 18ec475c01..b476c4cd88 100644 --- a/std/assembly/builtins.ts +++ b/std/assembly/builtins.ts @@ -136,6 +136,14 @@ export declare function mul(left: T, right: T): T; @builtin export declare function div(left: T, right: T): T; +// @ts-ignore: decorator +@builtin +export declare function eq(left: T, right: T): i32; + +// @ts-ignore: decorator +@builtin +export declare function ne(left: T, right: T): i32; + // @ts-ignore: decorator @unsafe @builtin export declare function load(ptr: usize, immOffset?: usize, immAlign?: usize): T; @@ -334,6 +342,14 @@ export namespace i32 { @builtin export declare function rotr(value: i32, shift: i32): i32; + // @ts-ignore: decorator + @builtin + export declare function eq(left: i32, right:i32): i32; + + // @ts-ignore: decorator + @builtin + export declare function ne(left: i32, right:i32): i32; + // @ts-ignore: decorator @builtin export declare function reinterpret_f32(value: f32): i32; @@ -577,6 +593,14 @@ export namespace i64 { @builtin export declare function rotr(value: i64, shift: i64): i64; + // @ts-ignore: decorator + @builtin + export declare function eq(left: i64, right:i64): i32; + + // @ts-ignore: decorator + @builtin + export declare function ne(left: i64, right:i64): i32; + // @ts-ignore: decorator @builtin export declare function reinterpret_f64(value: f64): i64; @@ -977,6 +1001,14 @@ export namespace f32 { // @ts-ignore: decorator @builtin export declare function div(left: f32, right: f32): f32; + + // @ts-ignore: decorator + @builtin + export declare function eq(left: f32, right: f32): i32; + + // @ts-ignore: decorator + @builtin + export declare function ne(left: f32, right: f32): i32; } // @ts-ignore: decorator @@ -1084,6 +1116,14 @@ export namespace f64 { // @ts-ignore: decorator @builtin export declare function div(left: f64, right: f64): f64; + + // @ts-ignore: decorator + @builtin + export declare function eq(left: f64, right: f64): i32; + + // @ts-ignore: decorator + @builtin + export declare function ne(left: f64, right: f64): i32; } // @ts-ignore: decorator diff --git a/std/assembly/index.d.ts b/std/assembly/index.d.ts index 8f9fda79fb..85cd68cb59 100644 --- a/std/assembly/index.d.ts +++ b/std/assembly/index.d.ts @@ -147,6 +147,10 @@ declare function sub(left: T, right: T): T; declare function mul(left: T, right: T): T; /** Computes the quotient of two integers or floats. */ declare function div(left: T, right: T): T; +/** Return 1 if two numbers are equal to each other, 0 otherwise. */ +declare function eq(left: T, right: T): i32; +/** Return 0 if two numbers are equal to each other, 1 otherwise. */ +declare function ne(left: T, right: T): i32; /** Loads a value of the specified type from memory. Equivalent to dereferncing a pointer in other languages. */ declare function load(ptr: usize, immOffset?: usize, immAlign?: usize): T; /** Stores a value of the specified type to memory. Equivalent to dereferencing a pointer in other languages when assigning a value. */ @@ -338,6 +342,10 @@ declare namespace i32 { export function div_s(left: i32, right: i32): i32; /** Computes the unsigned quotient of two 32-bit integers. */ export function div_u(left: i32, right: i32): i32; + /** Return 1 two 32-bit inegers are equal to each other, 0 otherwise. */ + export function eq(left: i32, right: i32): i32; + /** Return 0 two 32-bit inegers are equal to each other, 1 otherwise. */ + export function ne(left: i32, right: i32): i32; /** Atomic 32-bit integer operations. */ export namespace atomic { /** Atomically loads an 8-bit unsigned integer value from memory and returns it as a 32-bit integer. */ @@ -458,6 +466,10 @@ declare namespace i64 { export function div_s(left: i64, right: i64): i64; /** Computes the unsigned quotient of two 64-bit integers. */ export function div_u(left: i64, right: i64): i64; + /** Return 1 two 64-bit inegers are equal to each other, 0 otherwise. */ + export function eq(left: i64, right: i64): i32; + /** Return 0 two 64-bit inegers are equal to each other, 1 otherwise. */ + export function ne(left: i64, right: i64): i32; /** Atomic 64-bit integer operations. */ export namespace atomic { /** Atomically loads an 8-bit unsigned integer value from memory and returns it as a 64-bit integer. */ @@ -625,6 +637,10 @@ declare namespace f32 { export function mul(left: f32, right: f32): f32; /** Computes the quotient of two 32-bit floats. */ export function div(left: f32, right: f32): f32; + /** Return 1 two 32-bit floats are equal to each other, 0 otherwise. */ + export function eq(left: f32, right: f32): i32; + /** Return 0 two 32-bit floats are equal to each other, 1 otherwise. */ + export function ne(left: f32, right: f32): i32; /** Computes the absolute value of a 32-bit float. */ export function abs(value: f32): f32; /** Determines the maximum of two 32-bit floats. If either operand is `NaN`, returns `NaN`. */ @@ -679,6 +695,10 @@ declare namespace f64 { export function mul(left: f64, right: f64): f64; /** Computes the quotient of two 64-bit floats. */ export function div(left: f64, right: f64): f64; + /** Return 1 two 64-bit floats are equal to each other, 0 otherwise. */ + export function eq(left: f64, right: f64): i32; + /** Return 0 two 32-bit floats are equal to each other, 1 otherwise. */ + export function ne(left: f64, right: f64): i32; /** Computes the absolute value of a 64-bit float. */ export function abs(value: f64): f64; /** Determines the maximum of two 64-bit floats. If either operand is `NaN`, returns `NaN`. */ diff --git a/tests/compiler/builtins.debug.wat b/tests/compiler/builtins.debug.wat index 69599f70f3..1a89fb333e 100644 --- a/tests/compiler/builtins.debug.wat +++ b/tests/compiler/builtins.debug.wat @@ -10,11 +10,13 @@ (import "env" "trace" (func $~lib/builtins/trace (param i32 i32 f64 f64 f64 f64 f64))) (global $builtins/b (mut i32) (i32.const 0)) (global $builtins/l (mut i32) (i32.const 0)) - (global $builtins/v (mut i32) (i32.const 0)) (global $builtins/i (mut i32) (i32.const 0)) + (global $builtins/v (mut i32) (i32.const 0)) (global $builtins/I (mut i64) (i64.const 0)) (global $builtins/f (mut f32) (f32.const 0)) + (global $~lib/builtins/f32.NaN f32 (f32.const nan:0x400000)) (global $builtins/F (mut f64) (f64.const 0)) + (global $~lib/builtins/f64.NaN f64 (f64.const nan:0x8000000000000)) (global $builtins/constantOffset i32 (i32.const 8)) (global $builtins/u (mut i32) (i32.const 0)) (global $builtins/U (mut i64) (i64.const 0)) @@ -603,6 +605,70 @@ call $~lib/builtins/abort unreachable end + i32.const 1 + i32.const 1 + i32.eq + global.set $builtins/i + global.get $builtins/i + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 55 + i32.const 19 + call $~lib/builtins/abort + unreachable + end + i32.const 1 + i32.const 0 + i32.eq + global.set $builtins/i + global.get $builtins/i + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 56 + i32.const 19 + call $~lib/builtins/abort + unreachable + end + i32.const 1 + i32.const 1 + i32.ne + global.set $builtins/i + global.get $builtins/i + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 57 + i32.const 19 + call $~lib/builtins/abort + unreachable + end + i32.const 1 + i32.const 0 + i32.ne + global.set $builtins/i + global.get $builtins/i + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 58 + i32.const 19 + call $~lib/builtins/abort + unreachable + end i32.const 143 local.tee $0 i32.const 3 @@ -628,7 +694,7 @@ if i32.const 0 i32.const 96 - i32.const 57 + i32.const 61 i32.const 34 call $~lib/builtins/abort unreachable @@ -658,7 +724,7 @@ if i32.const 0 i32.const 96 - i32.const 58 + i32.const 62 i32.const 34 call $~lib/builtins/abort unreachable @@ -725,6 +791,51 @@ i32.div_s drop i32.const 1 + i32.const 0 + i32.eq + drop + i32.const 1 + i32.const 0 + i32.ne + drop + i32.const 1 + i32.clz + drop + i32.const 1 + i32.ctz + drop + i32.const 1 + i32.popcnt + drop + i32.const 1 + i32.const 1 + i32.rotl + drop + i32.const 1 + i32.const 1 + i32.rotr + drop + i32.const 1 + i32.const 2 + i32.add + drop + i32.const 2 + i32.const 1 + i32.sub + drop + i32.const 1 + i32.const 2 + i32.mul + drop + i32.const 1 + i32.const 0 + i32.eq + drop + i32.const 1 + i32.const 0 + i32.ne + drop + i32.const 1 i32.clz global.set $builtins/i i32.const 1 @@ -758,7 +869,7 @@ if i32.const 0 i32.const 96 - i32.const 82 + i32.const 99 i32.const 20 call $~lib/builtins/abort unreachable @@ -779,7 +890,7 @@ if i32.const 0 i32.const 96 - i32.const 83 + i32.const 100 i32.const 21 call $~lib/builtins/abort unreachable @@ -800,7 +911,7 @@ if i32.const 0 i32.const 96 - i32.const 84 + i32.const 101 i32.const 21 call $~lib/builtins/abort unreachable @@ -816,7 +927,7 @@ if i32.const 0 i32.const 96 - i32.const 85 + i32.const 102 i32.const 21 call $~lib/builtins/abort unreachable @@ -832,7 +943,7 @@ if i32.const 0 i32.const 96 - i32.const 86 + i32.const 103 i32.const 21 call $~lib/builtins/abort unreachable @@ -848,7 +959,7 @@ if i32.const 0 i32.const 96 - i32.const 87 + i32.const 104 i32.const 21 call $~lib/builtins/abort unreachable @@ -864,11 +975,75 @@ if i32.const 0 i32.const 96 - i32.const 88 + i32.const 105 i32.const 21 call $~lib/builtins/abort unreachable end + i32.const 1 + i32.const 1 + i32.eq + global.set $builtins/i + global.get $builtins/i + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 106 + i32.const 20 + call $~lib/builtins/abort + unreachable + end + i32.const 1 + i32.const 0 + i32.eq + global.set $builtins/i + global.get $builtins/i + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 107 + i32.const 20 + call $~lib/builtins/abort + unreachable + end + i32.const 1 + i32.const 1 + i32.ne + global.set $builtins/i + global.get $builtins/i + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 108 + i32.const 20 + call $~lib/builtins/abort + unreachable + end + i32.const 1 + i32.const 0 + i32.ne + global.set $builtins/i + global.get $builtins/i + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 109 + i32.const 20 + call $~lib/builtins/abort + unreachable + end i64.const 1 i64.clz drop @@ -897,6 +1072,39 @@ i64.xor drop i64.const 1 + i64.const 0 + i64.eq + drop + i64.const 1 + i64.const 0 + i64.ne + drop + i64.const 1 + i64.clz + drop + i64.const 1 + i64.ctz + drop + i64.const 1 + i64.popcnt + drop + i64.const 1 + i64.const 1 + i64.rotl + drop + i64.const 1 + i64.const 1 + i64.rotr + drop + i64.const 1 + i64.const 0 + i64.eq + drop + i64.const 1 + i64.const 0 + i64.ne + drop + i64.const 1 i64.clz global.set $builtins/I i64.const 1 @@ -930,7 +1138,7 @@ if i32.const 0 i32.const 96 - i32.const 104 + i32.const 135 i32.const 20 call $~lib/builtins/abort unreachable @@ -951,7 +1159,7 @@ if i32.const 0 i32.const 96 - i32.const 105 + i32.const 136 i32.const 21 call $~lib/builtins/abort unreachable @@ -972,7 +1180,7 @@ if i32.const 0 i32.const 96 - i32.const 106 + i32.const 137 i32.const 21 call $~lib/builtins/abort unreachable @@ -988,7 +1196,7 @@ if i32.const 0 i32.const 96 - i32.const 107 + i32.const 138 i32.const 21 call $~lib/builtins/abort unreachable @@ -1004,7 +1212,7 @@ if i32.const 0 i32.const 96 - i32.const 108 + i32.const 139 i32.const 21 call $~lib/builtins/abort unreachable @@ -1020,7 +1228,7 @@ if i32.const 0 i32.const 96 - i32.const 109 + i32.const 140 i32.const 21 call $~lib/builtins/abort unreachable @@ -1036,8 +1244,72 @@ if i32.const 0 i32.const 96 - i32.const 110 - i32.const 21 + i32.const 141 + i32.const 21 + call $~lib/builtins/abort + unreachable + end + i64.const 1 + i64.const 1 + i64.eq + global.set $builtins/i + global.get $builtins/i + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 142 + i32.const 20 + call $~lib/builtins/abort + unreachable + end + i64.const 1 + i64.const 0 + i64.eq + global.set $builtins/i + global.get $builtins/i + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 143 + i32.const 20 + call $~lib/builtins/abort + unreachable + end + i64.const 1 + i64.const 1 + i64.ne + global.set $builtins/i + global.get $builtins/i + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 144 + i32.const 20 + call $~lib/builtins/abort + unreachable + end + i64.const 1 + i64.const 0 + i64.ne + global.set $builtins/i + global.get $builtins/i + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 145 + i32.const 20 call $~lib/builtins/abort unreachable end @@ -1091,6 +1363,14 @@ f32.const 1.25 f32.trunc drop + f32.const 1.5 + f32.const 2.5 + f32.eq + drop + f32.const 1.5 + f32.const 2.5 + f32.ne + drop f32.const 1.25 local.tee $4 local.get $4 @@ -1142,6 +1422,62 @@ i32.const 0 i32.eq drop + global.get $~lib/builtins/f32.NaN + drop + f32.const 1.25 + f32.abs + drop + f32.const 1.25 + f32.ceil + drop + f32.const 1.25 + f32.const 2.5 + f32.copysign + drop + f32.const 1.25 + f32.floor + drop + f32.const 1.5 + f32.const 2.5 + f32.add + drop + f32.const 2.5 + f32.const 1.5 + f32.sub + drop + f32.const 1.5 + f32.const 2 + f32.mul + drop + f32.const 1.5 + f32.const 0.5 + f32.div + drop + f32.const 1.25 + f32.const 2.5 + f32.max + drop + f32.const 1.25 + f32.const 2.5 + f32.min + drop + f32.const 1.25 + f32.nearest + drop + f32.const 1.25 + f32.sqrt + drop + f32.const 1.25 + f32.trunc + drop + f32.const 1.5 + f32.const 2.5 + f32.eq + drop + f32.const 1.5 + f32.const 2.5 + f32.ne + drop f32.const nan:0x400000 global.set $builtins/f f32.const inf @@ -1170,7 +1506,7 @@ if i32.const 0 i32.const 96 - i32.const 144 + i32.const 197 i32.const 25 call $~lib/builtins/abort unreachable @@ -1186,7 +1522,7 @@ if i32.const 0 i32.const 96 - i32.const 145 + i32.const 198 i32.const 25 call $~lib/builtins/abort unreachable @@ -1202,7 +1538,7 @@ if i32.const 0 i32.const 96 - i32.const 146 + i32.const 199 i32.const 25 call $~lib/builtins/abort unreachable @@ -1218,7 +1554,7 @@ if i32.const 0 i32.const 96 - i32.const 147 + i32.const 200 i32.const 25 call $~lib/builtins/abort unreachable @@ -1234,7 +1570,7 @@ if i32.const 0 i32.const 96 - i32.const 148 + i32.const 201 i32.const 26 call $~lib/builtins/abort unreachable @@ -1252,6 +1588,70 @@ f32.const 1.25 f32.trunc global.set $builtins/f + f32.const 1.5 + f32.const 1.5 + f32.eq + global.set $builtins/i + global.get $builtins/i + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 206 + i32.const 24 + call $~lib/builtins/abort + unreachable + end + f32.const 1.5 + f32.const 2.5 + f32.eq + global.set $builtins/i + global.get $builtins/i + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 207 + i32.const 24 + call $~lib/builtins/abort + unreachable + end + f32.const 1.5 + f32.const 1.5 + f32.ne + global.set $builtins/i + global.get $builtins/i + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 208 + i32.const 24 + call $~lib/builtins/abort + unreachable + end + f32.const 1.5 + f32.const 2.5 + f32.ne + global.set $builtins/i + global.get $builtins/i + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 209 + i32.const 24 + call $~lib/builtins/abort + unreachable + end f32.const 1.25 local.tee $4 local.get $4 @@ -1318,6 +1718,22 @@ f64.const 1.25 f64.trunc drop + f64.const 1.5 + f64.const 1.5 + f64.eq + drop + f64.const 1.5 + f64.const 2.5 + f64.eq + drop + f64.const 1.5 + f64.const 1.5 + f64.ne + drop + f64.const 1.5 + f64.const 2.5 + f64.ne + drop f64.const 1.25 local.tee $5 local.get $5 @@ -1369,6 +1785,62 @@ i32.const 0 i32.eq drop + global.get $~lib/builtins/f64.NaN + drop + f64.const 1.25 + f64.abs + drop + f64.const 1.25 + f64.ceil + drop + f64.const 1.25 + f64.const 2.5 + f64.copysign + drop + f64.const 1.25 + f64.floor + drop + f64.const 1.5 + f64.const 2.5 + f64.add + drop + f64.const 2.5 + f64.const 1.5 + f64.sub + drop + f64.const 1.5 + f64.const 2 + f64.mul + drop + f64.const 1.5 + f64.const 0.5 + f64.div + drop + f64.const 1.25 + f64.const 2.5 + f64.max + drop + f64.const 1.25 + f64.const 2.5 + f64.min + drop + f64.const 1.25 + f64.nearest + drop + f64.const 1.25 + f64.sqrt + drop + f64.const 1.25 + f64.trunc + drop + f64.const 1.5 + f64.const 2.5 + f64.eq + drop + f64.const 1.5 + f64.const 2.5 + f64.ne + drop f64.const nan:0x8000000000000 global.set $builtins/F f64.const inf @@ -1397,7 +1869,7 @@ if i32.const 0 i32.const 96 - i32.const 188 + i32.const 265 i32.const 25 call $~lib/builtins/abort unreachable @@ -1413,7 +1885,7 @@ if i32.const 0 i32.const 96 - i32.const 189 + i32.const 266 i32.const 25 call $~lib/builtins/abort unreachable @@ -1429,7 +1901,7 @@ if i32.const 0 i32.const 96 - i32.const 190 + i32.const 267 i32.const 25 call $~lib/builtins/abort unreachable @@ -1445,7 +1917,7 @@ if i32.const 0 i32.const 96 - i32.const 191 + i32.const 268 i32.const 25 call $~lib/builtins/abort unreachable @@ -1467,6 +1939,70 @@ f64.const 1.25 f64.trunc global.set $builtins/F + f64.const 1.5 + f64.const 1.5 + f64.eq + global.set $builtins/i + global.get $builtins/i + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 274 + i32.const 24 + call $~lib/builtins/abort + unreachable + end + f64.const 1.5 + f64.const 2.5 + f64.eq + global.set $builtins/i + global.get $builtins/i + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 275 + i32.const 24 + call $~lib/builtins/abort + unreachable + end + f64.const 1.5 + f64.const 1.5 + f64.ne + global.set $builtins/i + global.get $builtins/i + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 276 + i32.const 24 + call $~lib/builtins/abort + unreachable + end + f64.const 1.5 + f64.const 2.5 + f64.ne + global.set $builtins/i + global.get $builtins/i + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 96 + i32.const 277 + i32.const 24 + call $~lib/builtins/abort + unreachable + end f64.const 1.25 local.tee $5 local.get $5 @@ -1776,7 +2312,7 @@ if i32.const 0 i32.const 96 - i32.const 312 + i32.const 393 i32.const 1 call $~lib/builtins/abort unreachable @@ -1797,7 +2333,7 @@ if i32.const 0 i32.const 96 - i32.const 313 + i32.const 394 i32.const 1 call $~lib/builtins/abort unreachable @@ -1825,7 +2361,7 @@ if i32.const 0 i32.const 96 - i32.const 314 + i32.const 395 i32.const 1 call $~lib/builtins/abort unreachable @@ -1843,7 +2379,7 @@ if i32.const 0 i32.const 96 - i32.const 315 + i32.const 396 i32.const 1 call $~lib/builtins/abort unreachable @@ -1861,7 +2397,7 @@ if i32.const 0 i32.const 96 - i32.const 316 + i32.const 397 i32.const 1 call $~lib/builtins/abort unreachable @@ -1889,7 +2425,7 @@ if i32.const 0 i32.const 96 - i32.const 317 + i32.const 398 i32.const 1 call $~lib/builtins/abort unreachable @@ -2431,7 +2967,7 @@ if i32.const 0 i32.const 96 - i32.const 499 + i32.const 580 i32.const 1 call $~lib/builtins/abort unreachable @@ -2444,7 +2980,7 @@ if i32.const 0 i32.const 96 - i32.const 500 + i32.const 581 i32.const 1 call $~lib/builtins/abort unreachable @@ -2457,7 +2993,7 @@ if i32.const 0 i32.const 96 - i32.const 501 + i32.const 582 i32.const 1 call $~lib/builtins/abort unreachable @@ -2470,7 +3006,7 @@ if i32.const 0 i32.const 96 - i32.const 502 + i32.const 583 i32.const 1 call $~lib/builtins/abort unreachable @@ -2483,7 +3019,7 @@ if i32.const 0 i32.const 96 - i32.const 503 + i32.const 584 i32.const 1 call $~lib/builtins/abort unreachable @@ -2496,7 +3032,7 @@ if i32.const 0 i32.const 96 - i32.const 504 + i32.const 585 i32.const 1 call $~lib/builtins/abort unreachable @@ -2509,7 +3045,7 @@ if i32.const 0 i32.const 96 - i32.const 505 + i32.const 586 i32.const 1 call $~lib/builtins/abort unreachable @@ -2549,7 +3085,7 @@ if i32.const 304 i32.const 96 - i32.const 515 + i32.const 596 i32.const 3 call $~lib/builtins/abort unreachable @@ -2561,7 +3097,7 @@ if i32.const 0 i32.const 96 - i32.const 516 + i32.const 597 i32.const 3 call $~lib/builtins/abort unreachable @@ -2573,7 +3109,7 @@ if i32.const 0 i32.const 96 - i32.const 517 + i32.const 598 i32.const 3 call $~lib/builtins/abort unreachable @@ -2585,7 +3121,7 @@ if i32.const 0 i32.const 96 - i32.const 518 + i32.const 599 i32.const 3 call $~lib/builtins/abort unreachable @@ -2607,7 +3143,7 @@ if i32.const 0 i32.const 96 - i32.const 522 + i32.const 603 i32.const 3 call $~lib/builtins/abort unreachable @@ -2629,7 +3165,7 @@ if i32.const 0 i32.const 96 - i32.const 523 + i32.const 604 i32.const 3 call $~lib/builtins/abort unreachable @@ -2651,7 +3187,7 @@ if i32.const 0 i32.const 96 - i32.const 524 + i32.const 605 i32.const 3 call $~lib/builtins/abort unreachable @@ -2673,7 +3209,7 @@ if i32.const 0 i32.const 96 - i32.const 525 + i32.const 606 i32.const 3 call $~lib/builtins/abort unreachable @@ -2695,7 +3231,7 @@ if i32.const 0 i32.const 96 - i32.const 526 + i32.const 607 i32.const 3 call $~lib/builtins/abort unreachable @@ -2717,7 +3253,7 @@ if i32.const 0 i32.const 96 - i32.const 527 + i32.const 608 i32.const 3 call $~lib/builtins/abort unreachable @@ -2739,7 +3275,7 @@ if i32.const 0 i32.const 96 - i32.const 528 + i32.const 609 i32.const 3 call $~lib/builtins/abort unreachable @@ -2761,7 +3297,7 @@ if i32.const 0 i32.const 96 - i32.const 529 + i32.const 610 i32.const 3 call $~lib/builtins/abort unreachable @@ -2783,7 +3319,7 @@ if i32.const 0 i32.const 96 - i32.const 530 + i32.const 611 i32.const 3 call $~lib/builtins/abort unreachable @@ -2805,7 +3341,7 @@ if i32.const 0 i32.const 96 - i32.const 531 + i32.const 612 i32.const 3 call $~lib/builtins/abort unreachable @@ -2827,7 +3363,7 @@ if i32.const 0 i32.const 96 - i32.const 532 + i32.const 613 i32.const 3 call $~lib/builtins/abort unreachable @@ -2849,7 +3385,7 @@ if i32.const 0 i32.const 96 - i32.const 533 + i32.const 614 i32.const 3 call $~lib/builtins/abort unreachable @@ -2871,7 +3407,7 @@ if i32.const 0 i32.const 96 - i32.const 534 + i32.const 615 i32.const 3 call $~lib/builtins/abort unreachable @@ -2893,7 +3429,7 @@ if i32.const 0 i32.const 96 - i32.const 535 + i32.const 616 i32.const 3 call $~lib/builtins/abort unreachable @@ -2915,7 +3451,7 @@ if i32.const 0 i32.const 96 - i32.const 536 + i32.const 617 i32.const 3 call $~lib/builtins/abort unreachable @@ -2937,7 +3473,7 @@ if i32.const 0 i32.const 96 - i32.const 537 + i32.const 618 i32.const 3 call $~lib/builtins/abort unreachable @@ -2959,7 +3495,7 @@ if i32.const 0 i32.const 96 - i32.const 538 + i32.const 619 i32.const 3 call $~lib/builtins/abort unreachable @@ -2981,7 +3517,7 @@ if i32.const 0 i32.const 96 - i32.const 539 + i32.const 620 i32.const 3 call $~lib/builtins/abort unreachable @@ -3003,7 +3539,7 @@ if i32.const 0 i32.const 96 - i32.const 540 + i32.const 621 i32.const 3 call $~lib/builtins/abort unreachable @@ -3025,7 +3561,7 @@ if i32.const 0 i32.const 96 - i32.const 541 + i32.const 622 i32.const 3 call $~lib/builtins/abort unreachable @@ -3106,7 +3642,7 @@ if i32.const 0 i32.const 96 - i32.const 575 + i32.const 656 i32.const 1 call $~lib/builtins/abort unreachable @@ -3121,7 +3657,7 @@ if i32.const 0 i32.const 96 - i32.const 580 + i32.const 661 i32.const 1 call $~lib/builtins/abort unreachable @@ -3136,7 +3672,7 @@ if i32.const 0 i32.const 96 - i32.const 585 + i32.const 666 i32.const 1 call $~lib/builtins/abort unreachable @@ -3151,7 +3687,7 @@ if i32.const 0 i32.const 96 - i32.const 590 + i32.const 671 i32.const 1 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/builtins.release.wat b/tests/compiler/builtins.release.wat index 1513ba75c4..30ac6324d7 100644 --- a/tests/compiler/builtins.release.wat +++ b/tests/compiler/builtins.release.wat @@ -225,6 +225,14 @@ local.get $0 i32.const 0 i32.store offset=8 + i32.const 1 + global.set $builtins/i + i32.const 0 + global.set $builtins/i + i32.const 0 + global.set $builtins/i + i32.const 1 + global.set $builtins/i i32.const 31 global.set $builtins/i i32.const 0 @@ -249,6 +257,14 @@ global.set $builtins/i i32.const 3 global.set $builtins/i + i32.const 1 + global.set $builtins/i + i32.const 0 + global.set $builtins/i + i32.const 0 + global.set $builtins/i + i32.const 1 + global.set $builtins/i i64.const 63 global.set $builtins/I i64.const 0 @@ -273,6 +289,14 @@ global.set $builtins/I i64.const 3 global.set $builtins/I + i32.const 1 + global.set $builtins/i + i32.const 0 + global.set $builtins/i + i32.const 0 + global.set $builtins/i + i32.const 1 + global.set $builtins/i f32.const nan:0x400000 global.set $builtins/f f32.const inf @@ -303,6 +327,14 @@ global.set $builtins/f f32.const 1 global.set $builtins/f + i32.const 1 + global.set $builtins/i + i32.const 0 + global.set $builtins/i + i32.const 0 + global.set $builtins/i + i32.const 1 + global.set $builtins/i f64.const nan:0x8000000000000 global.set $builtins/F f64.const inf @@ -333,6 +365,14 @@ global.set $builtins/F f64.const 1 global.set $builtins/F + i32.const 1 + global.set $builtins/i + i32.const 0 + global.set $builtins/i + i32.const 0 + global.set $builtins/i + i32.const 1 + global.set $builtins/i f64.const 0 global.set $builtins/F f32.const 1 @@ -538,7 +578,7 @@ if i32.const 0 i32.const 1120 - i32.const 312 + i32.const 393 i32.const 1 call $~lib/builtins/abort unreachable @@ -556,7 +596,7 @@ if i32.const 0 i32.const 1120 - i32.const 313 + i32.const 394 i32.const 1 call $~lib/builtins/abort unreachable @@ -578,7 +618,7 @@ if i32.const 0 i32.const 1120 - i32.const 314 + i32.const 395 i32.const 1 call $~lib/builtins/abort unreachable @@ -606,7 +646,7 @@ if i32.const 0 i32.const 1120 - i32.const 317 + i32.const 398 i32.const 1 call $~lib/builtins/abort unreachable @@ -705,7 +745,7 @@ if i32.const 0 i32.const 1120 - i32.const 522 + i32.const 603 i32.const 3 call $~lib/builtins/abort unreachable @@ -724,7 +764,7 @@ if i32.const 0 i32.const 1120 - i32.const 523 + i32.const 604 i32.const 3 call $~lib/builtins/abort unreachable @@ -743,7 +783,7 @@ if i32.const 0 i32.const 1120 - i32.const 524 + i32.const 605 i32.const 3 call $~lib/builtins/abort unreachable @@ -762,7 +802,7 @@ if i32.const 0 i32.const 1120 - i32.const 525 + i32.const 606 i32.const 3 call $~lib/builtins/abort unreachable @@ -781,7 +821,7 @@ if i32.const 0 i32.const 1120 - i32.const 526 + i32.const 607 i32.const 3 call $~lib/builtins/abort unreachable @@ -800,7 +840,7 @@ if i32.const 0 i32.const 1120 - i32.const 527 + i32.const 608 i32.const 3 call $~lib/builtins/abort unreachable @@ -819,7 +859,7 @@ if i32.const 0 i32.const 1120 - i32.const 528 + i32.const 609 i32.const 3 call $~lib/builtins/abort unreachable @@ -838,7 +878,7 @@ if i32.const 0 i32.const 1120 - i32.const 529 + i32.const 610 i32.const 3 call $~lib/builtins/abort unreachable @@ -857,7 +897,7 @@ if i32.const 0 i32.const 1120 - i32.const 530 + i32.const 611 i32.const 3 call $~lib/builtins/abort unreachable @@ -876,7 +916,7 @@ if i32.const 0 i32.const 1120 - i32.const 531 + i32.const 612 i32.const 3 call $~lib/builtins/abort unreachable @@ -895,7 +935,7 @@ if i32.const 0 i32.const 1120 - i32.const 532 + i32.const 613 i32.const 3 call $~lib/builtins/abort unreachable @@ -914,7 +954,7 @@ if i32.const 0 i32.const 1120 - i32.const 533 + i32.const 614 i32.const 3 call $~lib/builtins/abort unreachable @@ -933,7 +973,7 @@ if i32.const 0 i32.const 1120 - i32.const 534 + i32.const 615 i32.const 3 call $~lib/builtins/abort unreachable @@ -952,7 +992,7 @@ if i32.const 0 i32.const 1120 - i32.const 535 + i32.const 616 i32.const 3 call $~lib/builtins/abort unreachable @@ -971,7 +1011,7 @@ if i32.const 0 i32.const 1120 - i32.const 536 + i32.const 617 i32.const 3 call $~lib/builtins/abort unreachable @@ -990,7 +1030,7 @@ if i32.const 0 i32.const 1120 - i32.const 537 + i32.const 618 i32.const 3 call $~lib/builtins/abort unreachable @@ -1009,7 +1049,7 @@ if i32.const 0 i32.const 1120 - i32.const 538 + i32.const 619 i32.const 3 call $~lib/builtins/abort unreachable @@ -1028,7 +1068,7 @@ if i32.const 0 i32.const 1120 - i32.const 539 + i32.const 620 i32.const 3 call $~lib/builtins/abort unreachable @@ -1047,7 +1087,7 @@ if i32.const 0 i32.const 1120 - i32.const 540 + i32.const 621 i32.const 3 call $~lib/builtins/abort unreachable @@ -1066,7 +1106,7 @@ if i32.const 0 i32.const 1120 - i32.const 541 + i32.const 622 i32.const 3 call $~lib/builtins/abort unreachable diff --git a/tests/compiler/builtins.ts b/tests/compiler/builtins.ts index bb776279ef..45789fe139 100644 --- a/tests/compiler/builtins.ts +++ b/tests/compiler/builtins.ts @@ -52,6 +52,10 @@ l = add(1, 2); assert(l == 3); l = sub(2, 1); assert(l == 1); l = mul(1, 2); assert(l == 2); l = div(6, 2); assert(l == 3); +i = eq(1, 1); assert(i == 1); +i = eq(1, 0); assert(i == 0); +i = ne(1, 1); assert(i == 0); +i = ne(1, 0); assert(i == 1); var v: u8; v = rotl(0b10001111, 3); assert(v == 0b01111100); @@ -73,6 +77,19 @@ add(1, 2); sub(2, 1); mul(1, 2); div(6, 2); +eq(1, 0); +ne(1, 0); + +i32.clz(1); +i32.ctz(1); +i32.popcnt(1); +i32.rotl(1, 1); +i32.rotr(1, 1); +i32.add(1, 2); +i32.sub(2, 1); +i32.mul(1, 2); +i32.eq(1, 0); +i32.ne(1, 0); i = clz(1); i = ctz(1); @@ -86,6 +103,10 @@ i = add(1, 2); assert(i == 3); i = sub(2, 1); assert(i == 1); i = mul(2, 3); assert(i == 6); i = div(6, 2); assert(i == 3); +i = eq(1, 1); assert(i == 1); +i = eq(1, 0); assert(i == 0); +i = ne(1, 1); assert(i == 0); +i = ne(1, 0); assert(i == 1); var I: i64; @@ -95,6 +116,16 @@ popcnt(1); rotl(1, 1); rotr(1, 1); abs(-42); +eq(1, 0); +ne(1, 0); + +i64.clz(1); +i64.ctz(1); +i64.popcnt(1); +i64.rotl(1, 1); +i64.rotr(1, 1); +i64.eq(1, 0); +i64.ne(1, 0); I = clz(1); I = ctz(1); @@ -108,6 +139,10 @@ I = add(1, 2); assert(I == 3); I = sub(2, 1); assert(I == 1); I = mul(2, 3); assert(I == 6); I = div(6, 2); assert(I == 3); +i = eq(1, 1); assert(i == 1); +i = eq(1, 0); assert(i == 0); +i = ne(1, 1); assert(i == 0); +i = ne(1, 0); assert(i == 1); // floats @@ -128,12 +163,30 @@ min(1.25, 2.5); nearest(1.25); sqrt(1.25); trunc(1.25); +eq(1.5, 2.5); +ne(1.5, 2.5); assert(isNaN(1.25) == false); assert(isNaN(NaN) == true); assert(isFinite(1.25) == true); assert(isFinite(Infinity) == false); assert(isFinite(-Infinity) == false); assert(isFinite(NaN) == false); +f32.NaN; +f32.abs(1.25); +f32.ceil(1.25); +f32.copysign(1.25, 2.5); +f32.floor(1.25); +f32.add(1.5, 2.5); +f32.sub(2.5, 1.5); +f32.mul(1.5, 2.0); +f32.div(1.5, 0.5); +f32.max(1.25, 2.5); +f32.min(1.25, 2.5); +f32.nearest(1.25); +f32.sqrt(1.25); +f32.trunc(1.25); +f32.eq(1.5, 2.5); +f32.ne(1.5, 2.5); f = NaN; f = Infinity; @@ -150,6 +203,10 @@ f = min(1.25, 2.5); f = nearest(1.25); f = sqrt(1.25); f = trunc(1.25); +i = eq(1.5, 1.5); assert(i == 1); +i = eq(1.5, 2.5); assert(i == 0); +i = ne(1.5, 1.5); assert(i == 0); +i = ne(1.5, 2.5); assert(i == 1); b = isNaN(1.25); b = isFinite(1.25); @@ -172,12 +229,32 @@ min(1.25, 2.5); nearest(1.25); sqrt(1.25); trunc(1.25); +eq(1.5, 1.5); +eq(1.5, 2.5); +ne(1.5, 1.5); +ne(1.5, 2.5); assert(isNaN(1.25) == false); assert(isNaN(NaN) == true); assert(isFinite(1.25) == true); assert(isFinite(Infinity) == false); assert(isFinite(-Infinity) == false); assert(isFinite(NaN) == false); +f64.NaN; +f64.abs(1.25); +f64.ceil(1.25); +f64.copysign(1.25, 2.5); +f64.floor(1.25); +f64.add(1.5, 2.5); +f64.sub(2.5, 1.5); +f64.mul(1.5, 2.0); +f64.div(1.5, 0.5); +f64.max(1.25, 2.5); +f64.min(1.25, 2.5); +f64.nearest(1.25); +f64.sqrt(1.25); +f64.trunc(1.25); +f64.eq(1.5, 2.5); +f64.ne(1.5, 2.5); F = NaN; F = Infinity; @@ -194,6 +271,10 @@ F = min(1.25, 2.5); F = nearest(1.25); F = sqrt(1.25); F = trunc(1.25); +i = eq(1.5, 1.5); assert(i == 1); +i = eq(1.5, 2.5); assert(i == 0); +i = ne(1.5, 1.5); assert(i == 0); +i = ne(1.5, 2.5); assert(i == 1); b = isNaN(1.25); b = isFinite(1.25);