From 4e89456dcbbef9257da90032423607cdc7dc6c60 Mon Sep 17 00:00:00 2001 From: Max Graey Date: Mon, 12 Nov 2018 08:42:28 +0200 Subject: [PATCH] Add more numeric builtins (#330) --- std/assembly/builtins.ts | 32 + std/assembly/index.d.ts | 56 ++ std/portable/index.d.ts | 56 ++ tests/compiler/builtins.ts | 41 + tests/compiler/builtins.untouched.wat | 1332 ++++++++++++++++++++++++- 5 files changed, 1510 insertions(+), 7 deletions(-) diff --git a/std/assembly/builtins.ts b/std/assembly/builtins.ts index f38b5e7d..08e1ca37 100644 --- a/std/assembly/builtins.ts +++ b/std/assembly/builtins.ts @@ -46,12 +46,16 @@ export namespace i8 { export const MIN_VALUE: i8 = -128; export const MAX_VALUE: i8 = 127; + @inline export function parseInt(value: string, radix: i32 = 0): i8 { return parseI32(value, radix) } + @inline export function parseFloat(value: string): i8 { return parseFloat(value) } } @builtin export declare function i16(value: void): i16; export namespace i16 { export const MIN_VALUE: i16 = -32768; export const MAX_VALUE: i16 = 32767; + @inline export function parseInt(value: string, radix: i32 = 0): i16 { return parseI32(value, radix) } + @inline export function parseFloat(value: string): i16 { return parseFloat(value) } } @builtin export declare function i32(value: void): i32; @@ -72,6 +76,8 @@ export namespace i32 { @builtin export declare function store8(offset: usize, value: i32, constantOffset?: usize): void; @builtin export declare function store16(offset: usize, value: i32, constantOffset?: usize): void; @builtin export declare function store(offset: usize, value: i32, constantOffset?: usize): void; + @inline export function parseInt(value: string, radix: i32 = 0): i32 { return parseI32(value, radix) } + @inline export function parseFloat(value: string): i32 { return parseFloat(value) } } @builtin export declare function i64(value: void): i64; @@ -95,6 +101,8 @@ export namespace i64 { @builtin export declare function store16(offset: usize, value: i64, constantOffset?: usize): void; @builtin export declare function store32(offset: usize, value: i64, constantOffset?: usize): void; @builtin export declare function store(offset: usize, value: i64, constantOffset?: usize): void; + @inline export function parseInt(value: string, radix: i32 = 0): i64 { return parseI64(value, radix) } + @inline export function parseFloat(value: string): i64 { return parseFloat(value) } } @builtin export declare function isize(value: void): isize; @@ -105,30 +113,40 @@ export namespace isize { export const MAX_VALUE: isize = sizeof() == sizeof() ? 2147483647 : 9223372036854775807; + @inline export function parseInt(value: string, radix: i32 = 0): isize { return parseI64(value, radix) } + @inline export function parseFloat(value: string): isize { return parseFloat(value) } } @builtin export declare function u8(value: void): u8; export namespace u8 { export const MIN_VALUE: u8 = 0; export const MAX_VALUE: u8 = 255; + @inline export function parseInt(value: string, radix: i32 = 0): u8 { return parseI32(value, radix) } + @inline export function parseFloat(value: string): u8 { return parseFloat(value) } } @builtin export declare function u16(value: void): u16; export namespace u16 { export const MIN_VALUE: u16 = 0; export const MAX_VALUE: u16 = 65535; + @inline export function parseInt(value: string, radix: i32 = 0): u16 { return parseI32(value, radix) } + @inline export function parseFloat(value: string): u16 { return parseFloat(value) } } @builtin export declare function u32(value: void): u32; export namespace u32 { export const MIN_VALUE: u32 = 0; export const MAX_VALUE: u32 = 4294967295; + @inline export function parseInt(value: string, radix: i32 = 0): u32 { return parseI32(value, radix) } + @inline export function parseFloat(value: string): u32 { return parseFloat(value) } } @builtin export declare function u64(value: void): u64; export namespace u64 { export const MIN_VALUE: u64 = 0; export const MAX_VALUE: u64 = 18446744073709551615; + @inline export function parseInt(value: string, radix: i32 = 0): u64 { return parseI64(value, radix) } + @inline export function parseFloat(value: string): u64 { return parseFloat(value) } } @builtin export declare function usize(value: void): usize; @@ -137,6 +155,8 @@ export namespace usize { export const MAX_VALUE: usize = sizeof() == sizeof() ? 4294967295 : 18446744073709551615; + @inline export function parseInt(value: string, radix: i32 = 0): usize { return parseI64(value, radix) } + @inline export function parseFloat(value: string): usize { return parseFloat(value) } } @builtin export declare function bool(value: void): bool; @@ -168,6 +188,12 @@ export namespace f32 { @builtin export declare function sqrt(value: f32): f32; @builtin export declare function store(offset: usize, value: f32, constantOffset?: usize): void; @builtin export declare function trunc(value: f32): f32; + @inline export function isNaN(value: f32): bool { return isNaN(value) } + @inline export function isFinite(value: f32): bool { return isFinite(value) } + @inline export function isSafeInteger(value: f32): bool { return abs(value) <= f32.MAX_SAFE_INTEGER && trunc(value) == value } + @inline export function isInteger(value: f32): bool { return isFinite(value) && trunc(value) == value } + @inline export function parseInt(value: string, radix: i32 = 0): f32 { return parseI64(value, radix) } + @inline export function parseFloat(value: string): f32 { return parseFloat(value) } } @builtin export declare function f64(value: void): f64; @@ -193,6 +219,12 @@ export namespace f64 { @builtin export declare function sqrt(value: f64): f64; @builtin export declare function store(offset: usize, value: f64, constantOffset?: usize): void; @builtin export declare function trunc(value: f64): f64; + @inline export function isNaN(value: f64): bool { return isNaN(value) } + @inline export function isFinite(value: f64): bool { return isFinite(value) } + @inline export function isSafeInteger(value: f64): bool { return abs(value) <= f64.MAX_SAFE_INTEGER && trunc(value) == value } + @inline export function isInteger(value: f64): bool { return isFinite(value) && trunc(value) == value } + @inline export function parseInt(value: string, radix: i32 = 0): f64 { return parseI64(value, radix) } + @inline export function parseFloat(value: string): f64 { return parseFloat(value) } } @builtin export declare function start(): void; diff --git a/std/assembly/index.d.ts b/std/assembly/index.d.ts index de65ca0a..f8843128 100644 --- a/std/assembly/index.d.ts +++ b/std/assembly/index.d.ts @@ -156,6 +156,10 @@ declare namespace i8 { export const MIN_VALUE: i8; /** Largest representable value. */ export const MAX_VALUE: i8; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): i8; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): i8; } /** Converts any other numeric value to a 16-bit signed integer. */ declare function i16(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): i8; @@ -164,6 +168,10 @@ declare namespace i16 { export const MIN_VALUE: i16; /** Largest representable value. */ export const MAX_VALUE: i16; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): i16; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): i16; } /** Converts any other numeric value to a 32-bit signed integer. */ declare function i32(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): i32; @@ -188,6 +196,10 @@ declare namespace i32 { export function store16(offset: usize, value: i32, constantOffset?: usize): void; /** Stores a 32-bit integer to memory. */ export function store(offset: usize, value: i32, constantOffset?: usize): void; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): i32; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): i32; } /** Converts any other numeric value to a 64-bit signed integer. */ declare function i64(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): i64; @@ -218,6 +230,10 @@ declare namespace i64 { export function store32(offset: usize, value: i64, constantOffset?: usize): void; /** Stores a 64-bit integer to memory. */ export function store(offset: usize, value: i64, constantOffset?: usize): void; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): i64; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): i64; } /** Converts any other numeric value to a 32-bit (in WASM32) respectivel 64-bit (in WASM64) signed integer. */ declare var isize: i32 | i64; @@ -228,6 +244,10 @@ declare namespace u8 { export const MIN_VALUE: u8; /** Largest representable value. */ export const MAX_VALUE: u8; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): u8; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): u8; } /** Converts any other numeric value to a 16-bit unsigned integer. */ declare function u16(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): i8; @@ -236,6 +256,10 @@ declare namespace u16 { export const MIN_VALUE: u16; /** Largest representable value. */ export const MAX_VALUE: u16; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): u16; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): u16; } /** Converts any other numeric value to a 32-bit unsigned integer. */ declare function u32(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): i32; @@ -244,6 +268,10 @@ declare namespace u32 { export const MIN_VALUE: u32; /** Largest representable value. */ export const MAX_VALUE: u32; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): u64; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): u64; } /** Converts any other numeric value to a 64-bit unsigned integer. */ declare function u64(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): i64; @@ -252,6 +280,10 @@ declare namespace u64 { export const MIN_VALUE: u64; /** Largest representable value. */ export const MAX_VALUE: u64; + /** Converts a string to a floating-point number. */ + export function parseFloat(string: string): u64; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): u64; } /** Converts any other numeric value to a 32-bit (in WASM32) respectivel 64-bit (in WASM64) unsigned integer. */ declare var usize: u32 | u64; @@ -286,6 +318,18 @@ declare namespace f32 { export function load(offset: usize, constantOffset?: usize): f32; /** Stores a 32-bit float to memory. */ export function store(offset: usize, value: f32, constantOffset?: usize): void; + /** Returns a boolean value that indicates whether a value is the reserved value NaN (not a number). */ + export function isNaN(value: f32): bool; + /** Returns true if passed value is finite. */ + export function isFinite(value: f32): bool; + /** Returns true if the value passed is a safe integer. */ + export function isSafeInteger(value: f32): bool; + /** Returns true if the value passed is an integer, false otherwise. */ + export function isInteger(value: f32): bool; + /** Converts a string to a floating-point number. */ + export function parseFloat(string: string): f32; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): f32; } /** Converts any other numeric value to a 64-bit float. */ declare function f64(value: i8 | i16 | i32 | i64 | isize | u8 | u16 | u32 | u64 | usize | bool | f32 | f64): f64; @@ -306,6 +350,18 @@ declare namespace f64 { export function load(offset: usize, constantOffset?: usize): f64; /** Stores a 64-bit float to memory. */ export function store(offset: usize, value: f64, constantOffset?: usize): void; + /** Returns a boolean value that indicates whether a value is the reserved value NaN (not a number). */ + export function isNaN(value: f32): bool; + /** Returns true if passed value is finite. */ + export function isFinite(value: f32): bool; + /** Returns true if the value passed is a safe integer. */ + export function isSafeInteger(value: f64): bool; + /** Returns true if the value passed is an integer, false otherwise. */ + export function isInteger(value: f64): bool; + /** Converts a string to a floating-point number. */ + export function parseFloat(string: string): f64; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): f64; } // User-defined diagnostic macros diff --git a/std/portable/index.d.ts b/std/portable/index.d.ts index 94b5ddd6..095585b3 100644 --- a/std/portable/index.d.ts +++ b/std/portable/index.d.ts @@ -114,6 +114,10 @@ declare namespace i8 { export const MIN_VALUE: i8; /** Largest representable value. */ export const MAX_VALUE: i8; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): i8; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): i8; } /** Converts any other numeric value to a 16-bit signed integer. */ declare function i16(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): i8; @@ -122,6 +126,10 @@ declare namespace i16 { export const MIN_VALUE: i16; /** Largest representable value. */ export const MAX_VALUE: i16; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): i16; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): i16; } /** Converts any other numeric value to a 32-bit signed integer. */ declare function i32(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): i32; @@ -130,6 +138,10 @@ declare namespace i32 { export const MIN_VALUE: i32; /** Largest representable value. */ export const MAX_VALUE: i32; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): i32; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): i32; } /** Converts any other numeric value to a 32-bit (in WASM32) respectivel 64-bit (in WASM64) signed integer. */ declare function isize(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): isize; @@ -138,6 +150,10 @@ declare namespace isize { export const MIN_VALUE: isize; /** Largest representable value. */ export const MAX_VALUE: isize; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): isize; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): isize; } /** Converts any other numeric value to an 8-bit unsigned integer. */ declare function u8(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): i8; @@ -146,6 +162,10 @@ declare namespace u8 { export const MIN_VALUE: u8; /** Largest representable value. */ export const MAX_VALUE: u8; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): u8; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): u8; } /** Converts any other numeric value to a 16-bit unsigned integer. */ declare function u16(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): i8; @@ -154,6 +174,10 @@ declare namespace u16 { export const MIN_VALUE: u16; /** Largest representable value. */ export const MAX_VALUE: u16; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): u16; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): u16; } /** Converts any other numeric value to a 32-bit unsigned integer. */ declare function u32(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): i32; @@ -162,6 +186,10 @@ declare namespace u32 { export const MIN_VALUE: u32; /** Largest representable value. */ export const MAX_VALUE: u32; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): u32; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): u32; } /** Converts any other numeric value to a 32-bit (in WASM32) respectivel 64-bit (in WASM64) unsigned integer. */ declare function usize(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): isize; @@ -170,6 +198,10 @@ declare namespace usize { export const MIN_VALUE: usize; /** Largest representable value. */ export const MAX_VALUE: usize; + /** Converts a string to a floating-point number and cast to target integer after. */ + export function parseFloat(string: string): usize; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): usize; } /** Converts any other numeric value to a 1-bit unsigned integer. */ declare function bool(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): bool; @@ -194,6 +226,18 @@ declare namespace f32 { export const MAX_SAFE_INTEGER: f32; /** Difference between 1 and the smallest representable value greater than 1. */ export const EPSILON: f32; + /** Returns a boolean value that indicates whether a value is the reserved value NaN (not a number). */ + export function isNaN(value: f32): bool; + /** Returns true if passed value is finite. */ + export function isFinite(value: f32): bool; + /** Returns true if the value passed is a safe integer. */ + export function isSafeInteger(value: f32): bool; + /** Returns true if the value passed is an integer, false otherwise. */ + export function isInteger(value: f32): bool; + /** Converts a string to a floating-point number. */ + export function parseFloat(string: string): f32; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): f32; } /** Converts any other numeric value to a 64-bit float. */ declare function f64(value: i8 | i16 | i32 | isize | u8 | u16 | u32 | usize | bool | f32 | f64): f64; @@ -210,6 +254,18 @@ declare namespace f64 { export const MAX_SAFE_INTEGER: f64; /** Difference between 1 and the smallest representable value greater than 1. */ export const EPSILON: f64; + /** Returns a boolean value that indicates whether a value is the reserved value NaN (not a number). */ + export function isNaN(value: f32): bool; + /** Returns true if passed value is finite. */ + export function isFinite(value: f32): bool; + /** Returns true if the value passed is a safe integer. */ + export function isSafeInteger(value: f64): bool; + /** Returns true if the value passed is an integer, false otherwise. */ + export function isInteger(value: f64): bool; + /** Converts a string to a floating-point number. */ + export function parseFloat(string: string): f64; + /** Converts A string to an integer. */ + export function parseInt(string: string, radix?: i32): f64; } // Polyfills diff --git a/tests/compiler/builtins.ts b/tests/compiler/builtins.ts index 486df391..a9bfa2e3 100644 --- a/tests/compiler/builtins.ts +++ b/tests/compiler/builtins.ts @@ -315,6 +315,27 @@ assert(f32.MIN_SAFE_INTEGER == -16777215); assert(f32.MAX_SAFE_INTEGER == 16777215); assert(f32.EPSILON == 1.19209290e-07); assert(isNaN(f32.NaN)); +assert(f32.isSafeInteger(f32.MIN_SAFE_INTEGER - 1) == false); +assert(f32.isSafeInteger(f32.MIN_SAFE_INTEGER) == true); +assert(f32.isSafeInteger(+0.0) == true); +assert(f32.isSafeInteger(-0.0) == true); +assert(f32.isSafeInteger(NaN) == false); +assert(f32.isSafeInteger(Infinity) == false); +assert(f32.isSafeInteger(f32.MAX_SAFE_INTEGER) == true); +assert(f32.isSafeInteger(f32.MAX_SAFE_INTEGER + 1) == false); +assert(f32.isSafeInteger(0.5) == false); +assert(f32.isInteger(+0.0) == true); +assert(f32.isInteger(-0.0) == true); +assert(f32.isInteger(NaN) == false); +assert(f32.isInteger(Infinity) == false); +assert(f32.isInteger(f32.EPSILON) == false); +assert(f32.isInteger(+1.0) == true); +assert(f32.isInteger(-1.0) == true); +assert(f32.isInteger(f32.MIN_SAFE_INTEGER) == true); +assert(f32.isInteger(f32.MAX_SAFE_INTEGER) == true); +assert(f32.isInteger(+0.5) == false); +assert(f32.isInteger(-1.5) == false); + assert(f64.MIN_NORMAL_VALUE == 2.2250738585072014e-308); assert(f64.MIN_VALUE == 5e-324); assert(f64.MAX_VALUE == 1.7976931348623157e+308); @@ -322,6 +343,26 @@ assert(f64.MIN_SAFE_INTEGER == -9007199254740991); assert(f64.MAX_SAFE_INTEGER == 9007199254740991); assert(f64.EPSILON == 2.2204460492503131e-16); assert(isNaN(f64.NaN)); +assert(f64.isSafeInteger(f64.MIN_SAFE_INTEGER - 1) == false); +assert(f64.isSafeInteger(f64.MIN_SAFE_INTEGER) == true); +assert(f64.isSafeInteger(+0.0) == true); +assert(f64.isSafeInteger(-0.0) == true); +assert(f64.isSafeInteger(NaN) == false); +assert(f64.isSafeInteger(Infinity) == false); +assert(f64.isSafeInteger(f64.MAX_SAFE_INTEGER) == true); +assert(f64.isSafeInteger(f64.MAX_SAFE_INTEGER + 1) == false); +assert(f64.isSafeInteger(0.5) == false); +assert(f64.isInteger(+0.0) == true); +assert(f64.isInteger(-0.0) == true); +assert(f64.isInteger(NaN) == false); +assert(f64.isInteger(Infinity) == false); +assert(f64.isInteger(f64.EPSILON) == false); +assert(f64.isInteger(+1.0) == true); +assert(f64.isInteger(-1.0) == true); +assert(f64.isInteger(f64.MIN_SAFE_INTEGER) == true); +assert(f64.isInteger(f64.MAX_SAFE_INTEGER) == true); +assert(f64.isInteger(+0.5) == false); +assert(f64.isInteger(-1.5) == false); // inline-assembler diff --git a/tests/compiler/builtins.untouched.wat b/tests/compiler/builtins.untouched.wat index 5a92c8d2..99659b2f 100644 --- a/tests/compiler/builtins.untouched.wat +++ b/tests/compiler/builtins.untouched.wat @@ -1943,6 +1943,665 @@ call $~lib/env/abort unreachable end + block $~lib/builtins/f32.isSafeInteger|inlined.0 (result i32) + get_global $~lib/builtins/f32.MIN_SAFE_INTEGER + f32.const 1 + f32.sub + set_local $4 + get_local $4 + f32.abs + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + f32.le + tee_local $0 + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 318 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isSafeInteger|inlined.1 (result i32) + get_global $~lib/builtins/f32.MIN_SAFE_INTEGER + set_local $4 + get_local $4 + f32.abs + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + f32.le + tee_local $0 + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 319 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isSafeInteger|inlined.2 (result i32) + f32.const 0 + set_local $4 + get_local $4 + f32.abs + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + f32.le + tee_local $0 + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 320 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isSafeInteger|inlined.3 (result i32) + f32.const -0 + set_local $4 + get_local $4 + f32.abs + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + f32.le + tee_local $0 + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 321 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isSafeInteger|inlined.4 (result i32) + f32.const nan:0x400000 + set_local $4 + get_local $4 + f32.abs + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + f32.le + tee_local $0 + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 322 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isSafeInteger|inlined.5 (result i32) + f32.const inf + set_local $4 + get_local $4 + f32.abs + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + f32.le + tee_local $0 + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 323 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isSafeInteger|inlined.6 (result i32) + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + set_local $4 + get_local $4 + f32.abs + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + f32.le + tee_local $0 + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 324 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isSafeInteger|inlined.7 (result i32) + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + f32.const 1 + f32.add + set_local $4 + get_local $4 + f32.abs + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + f32.le + tee_local $0 + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 325 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isSafeInteger|inlined.8 (result i32) + f32.const 0.5 + set_local $4 + get_local $4 + f32.abs + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + f32.le + tee_local $0 + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 326 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isInteger|inlined.0 (result i32) + f32.const 0 + set_local $4 + block $~lib/builtins/isFinite|inlined.8 (result i32) + get_local $4 + get_local $4 + f32.sub + f32.const 0 + f32.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 327 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isInteger|inlined.1 (result i32) + f32.const -0 + set_local $4 + block $~lib/builtins/isFinite|inlined.9 (result i32) + get_local $4 + get_local $4 + f32.sub + f32.const 0 + f32.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 328 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isInteger|inlined.2 (result i32) + f32.const nan:0x400000 + set_local $4 + block $~lib/builtins/isFinite|inlined.10 (result i32) + get_local $4 + get_local $4 + f32.sub + f32.const 0 + f32.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 329 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isInteger|inlined.3 (result i32) + f32.const inf + set_local $4 + block $~lib/builtins/isFinite|inlined.11 (result i32) + get_local $4 + get_local $4 + f32.sub + f32.const 0 + f32.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 330 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isInteger|inlined.4 (result i32) + get_global $~lib/builtins/f32.EPSILON + set_local $4 + block $~lib/builtins/isFinite|inlined.12 (result i32) + get_local $4 + get_local $4 + f32.sub + f32.const 0 + f32.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 331 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isInteger|inlined.5 (result i32) + f32.const 1 + set_local $4 + block $~lib/builtins/isFinite|inlined.13 (result i32) + get_local $4 + get_local $4 + f32.sub + f32.const 0 + f32.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 332 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isInteger|inlined.6 (result i32) + f32.const -1 + set_local $4 + block $~lib/builtins/isFinite|inlined.14 (result i32) + get_local $4 + get_local $4 + f32.sub + f32.const 0 + f32.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 333 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isInteger|inlined.7 (result i32) + get_global $~lib/builtins/f32.MIN_SAFE_INTEGER + set_local $4 + block $~lib/builtins/isFinite|inlined.15 (result i32) + get_local $4 + get_local $4 + f32.sub + f32.const 0 + f32.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 334 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isInteger|inlined.8 (result i32) + get_global $~lib/builtins/f32.MAX_SAFE_INTEGER + set_local $4 + block $~lib/builtins/isFinite|inlined.16 (result i32) + get_local $4 + get_local $4 + f32.sub + f32.const 0 + f32.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 335 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isInteger|inlined.9 (result i32) + f32.const 0.5 + set_local $4 + block $~lib/builtins/isFinite|inlined.17 (result i32) + get_local $4 + get_local $4 + f32.sub + f32.const 0 + f32.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 336 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f32.isInteger|inlined.10 (result i32) + f32.const -1.5 + set_local $4 + block $~lib/builtins/isFinite|inlined.18 (result i32) + get_local $4 + get_local $4 + f32.sub + f32.const 0 + f32.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $4 + f32.trunc + get_local $4 + f32.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 337 + i32.const 0 + call $~lib/env/abort + unreachable + end get_global $~lib/builtins/f64.MIN_NORMAL_VALUE f64.const 2.2250738585072014e-308 f64.eq @@ -1950,7 +2609,7 @@ if i32.const 0 i32.const 8 - i32.const 318 + i32.const 339 i32.const 0 call $~lib/env/abort unreachable @@ -1962,7 +2621,7 @@ if i32.const 0 i32.const 8 - i32.const 319 + i32.const 340 i32.const 0 call $~lib/env/abort unreachable @@ -1974,7 +2633,7 @@ if i32.const 0 i32.const 8 - i32.const 320 + i32.const 341 i32.const 0 call $~lib/env/abort unreachable @@ -1986,7 +2645,7 @@ if i32.const 0 i32.const 8 - i32.const 321 + i32.const 342 i32.const 0 call $~lib/env/abort unreachable @@ -1998,7 +2657,7 @@ if i32.const 0 i32.const 8 - i32.const 322 + i32.const 343 i32.const 0 call $~lib/env/abort unreachable @@ -2010,7 +2669,7 @@ if i32.const 0 i32.const 8 - i32.const 323 + i32.const 344 i32.const 0 call $~lib/env/abort unreachable @@ -2028,7 +2687,666 @@ if i32.const 0 i32.const 8 - i32.const 324 + i32.const 345 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isSafeInteger|inlined.0 (result i32) + get_global $~lib/builtins/f64.MIN_SAFE_INTEGER + f64.const 1 + f64.sub + set_local $5 + get_local $5 + f64.abs + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + f64.le + tee_local $0 + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 346 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isSafeInteger|inlined.1 (result i32) + get_global $~lib/builtins/f64.MIN_SAFE_INTEGER + set_local $5 + get_local $5 + f64.abs + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + f64.le + tee_local $0 + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 347 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isSafeInteger|inlined.2 (result i32) + f64.const 0 + set_local $5 + get_local $5 + f64.abs + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + f64.le + tee_local $0 + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 348 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isSafeInteger|inlined.3 (result i32) + f64.const -0 + set_local $5 + get_local $5 + f64.abs + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + f64.le + tee_local $0 + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 349 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isSafeInteger|inlined.4 (result i32) + f64.const nan:0x8000000000000 + set_local $5 + get_local $5 + f64.abs + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + f64.le + tee_local $0 + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 350 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isSafeInteger|inlined.5 (result i32) + f64.const inf + set_local $5 + get_local $5 + f64.abs + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + f64.le + tee_local $0 + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 351 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isSafeInteger|inlined.6 (result i32) + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + set_local $5 + get_local $5 + f64.abs + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + f64.le + tee_local $0 + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 352 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isSafeInteger|inlined.7 (result i32) + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + f64.const 1 + f64.add + set_local $5 + get_local $5 + f64.abs + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + f64.le + tee_local $0 + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 353 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isSafeInteger|inlined.8 (result i32) + f64.const 0.5 + set_local $5 + get_local $5 + f64.abs + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + f64.le + tee_local $0 + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 354 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isInteger|inlined.0 (result i32) + f64.const 0 + set_local $5 + block $~lib/builtins/isFinite|inlined.8 (result i32) + get_local $5 + get_local $5 + f64.sub + f64.const 0 + f64.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 355 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isInteger|inlined.1 (result i32) + f64.const -0 + set_local $5 + block $~lib/builtins/isFinite|inlined.9 (result i32) + get_local $5 + get_local $5 + f64.sub + f64.const 0 + f64.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 356 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isInteger|inlined.2 (result i32) + f64.const nan:0x8000000000000 + set_local $5 + block $~lib/builtins/isFinite|inlined.10 (result i32) + get_local $5 + get_local $5 + f64.sub + f64.const 0 + f64.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 357 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isInteger|inlined.3 (result i32) + f64.const inf + set_local $5 + block $~lib/builtins/isFinite|inlined.11 (result i32) + get_local $5 + get_local $5 + f64.sub + f64.const 0 + f64.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 358 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isInteger|inlined.4 (result i32) + get_global $~lib/builtins/f64.EPSILON + set_local $5 + block $~lib/builtins/isFinite|inlined.12 (result i32) + get_local $5 + get_local $5 + f64.sub + f64.const 0 + f64.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 359 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isInteger|inlined.5 (result i32) + f64.const 1 + set_local $5 + block $~lib/builtins/isFinite|inlined.13 (result i32) + get_local $5 + get_local $5 + f64.sub + f64.const 0 + f64.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 360 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isInteger|inlined.6 (result i32) + f64.const -1 + set_local $5 + block $~lib/builtins/isFinite|inlined.14 (result i32) + get_local $5 + get_local $5 + f64.sub + f64.const 0 + f64.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 361 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isInteger|inlined.7 (result i32) + get_global $~lib/builtins/f64.MIN_SAFE_INTEGER + set_local $5 + block $~lib/builtins/isFinite|inlined.15 (result i32) + get_local $5 + get_local $5 + f64.sub + f64.const 0 + f64.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 362 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isInteger|inlined.8 (result i32) + get_global $~lib/builtins/f64.MAX_SAFE_INTEGER + set_local $5 + block $~lib/builtins/isFinite|inlined.16 (result i32) + get_local $5 + get_local $5 + f64.sub + f64.const 0 + f64.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 1 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 363 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isInteger|inlined.9 (result i32) + f64.const 0.5 + set_local $5 + block $~lib/builtins/isFinite|inlined.17 (result i32) + get_local $5 + get_local $5 + f64.sub + f64.const 0 + f64.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 364 + i32.const 0 + call $~lib/env/abort + unreachable + end + block $~lib/builtins/f64.isInteger|inlined.10 (result i32) + f64.const -1.5 + set_local $5 + block $~lib/builtins/isFinite|inlined.18 (result i32) + get_local $5 + get_local $5 + f64.sub + f64.const 0 + f64.eq + end + tee_local $0 + i32.const 1 + i32.and + if (result i32) + get_local $5 + f64.trunc + get_local $5 + f64.eq + else + get_local $0 + end + end + i32.const 1 + i32.and + i32.const 0 + i32.eq + i32.eqz + if + i32.const 0 + i32.const 8 + i32.const 365 i32.const 0 call $~lib/env/abort unreachable