Skip to content

Commit 6b495f7

Browse files
MaxGraeydcodeIO
authored andcommitted
Ensure Math.clz32/imul compatibility with JS (AssemblyScript#474)
1 parent 0041572 commit 6b495f7

File tree

8 files changed

+762
-233
lines changed

8 files changed

+762
-233
lines changed

std/assembly/math.ts

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -349,9 +349,17 @@ export namespace NativeMath {
349349
return builtin_ceil<f64>(x);
350350
}
351351

352-
@inline
353352
export function clz32(x: f64): f64 {
354-
return <f64>builtin_clz<i32>(<i32>x);
353+
if (!isFinite(x)) return 32;
354+
/*
355+
* Wasm (MVP) and JS have different approaches for double->int conversions.
356+
*
357+
* For emulate JS conversion behavior and avoid trapping from wasm we should modulate by MAX_INT
358+
* our float-point arguments before actual convertion to integers.
359+
*/
360+
return builtin_clz(
361+
<i32><i64>(x - 4294967296 * builtin_floor(x * (1.0 / 4294967296)))
362+
);
355363
}
356364

357365
export function cos(x: f64): f64 { // TODO
@@ -543,7 +551,7 @@ export namespace NativeMath {
543551

544552
export function imul(x: f64, y: f64): f64 {
545553
/*
546-
* Wasm (MVP) and JS have different approachas for double->int conversions.
554+
* Wasm (MVP) and JS have different approaches for double->int conversions.
547555
*
548556
* For emulate JS conversion behavior and avoid trapping from wasm we should modulate by MAX_INT
549557
* our float-point arguments before actual convertion to integers.
@@ -1493,9 +1501,11 @@ export namespace NativeMathf {
14931501
return builtin_ceil<f32>(x);
14941502
}
14951503

1496-
@inline
14971504
export function clz32(x: f32): f32 {
1498-
return <f32>builtin_clz<i32>(<i32>x);
1505+
if (!isFinite(x)) return 32;
1506+
return builtin_clz(
1507+
<i32><i64>(x - 4294967296 * builtin_floor(x * (1.0 / 4294967296)))
1508+
);
14991509
}
15001510

15011511
export function cos(x: f32): f32 { // TODO
@@ -1669,7 +1679,18 @@ export namespace NativeMathf {
16691679

16701680
@inline
16711681
export function imul(x: f32, y: f32): f32 {
1672-
return <f32>(<i32>x * <i32>y);
1682+
/*
1683+
* Wasm (MVP) and JS have different approaches for double->int conversions.
1684+
*
1685+
* For emulate JS conversion behavior and avoid trapping from wasm we should modulate by MAX_INT
1686+
* our float-point arguments before actual convertion to integers.
1687+
*/
1688+
if (!isFinite(x + y)) return 0;
1689+
const inv32 = 1.0 / 4294967296;
1690+
return (
1691+
<i32><i64>(x - 4294967296 * builtin_floor(x * inv32)) *
1692+
<i32><i64>(y - 4294967296 * builtin_floor(y * inv32))
1693+
);
16731694
}
16741695

16751696
export function log(x: f32): f32 { // see: musl/src/math/logf.c and SUN COPYRIGHT NOTICE above

tests/compiler/std/array.optimized.wat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3876,7 +3876,7 @@
38763876
if
38773877
i32.const 0
38783878
i32.const 2896
3879-
i32.const 968
3879+
i32.const 976
38803880
i32.const 4
38813881
call $~lib/env/abort
38823882
unreachable
@@ -5552,7 +5552,7 @@
55525552
if
55535553
i32.const 0
55545554
i32.const 2896
5555-
i32.const 977
5555+
i32.const 985
55565556
i32.const 24
55575557
call $~lib/env/abort
55585558
unreachable

tests/compiler/std/array.untouched.wat

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5505,7 +5505,7 @@
55055505
if
55065506
i32.const 0
55075507
i32.const 2896
5508-
i32.const 968
5508+
i32.const 976
55095509
i32.const 4
55105510
call $~lib/env/abort
55115511
unreachable
@@ -9230,7 +9230,7 @@
92309230
if
92319231
i32.const 0
92329232
i32.const 2896
9233-
i32.const 977
9233+
i32.const 985
92349234
i32.const 24
92359235
call $~lib/env/abort
92369236
unreachable

tests/compiler/std/libm.optimized.wat

Lines changed: 56 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1563,16 +1563,37 @@
15631563
local.get $0
15641564
f64.ceil
15651565
)
1566-
(func $std/libm/clz32 (; 21 ;) (type $FF) (param $0 f64) (result f64)
1566+
(func $~lib/math/NativeMath.clz32 (; 21 ;) (type $FF) (param $0 f64) (result f64)
15671567
local.get $0
1568-
i32.trunc_f64_s
1568+
local.get $0
1569+
f64.sub
1570+
f64.const 0
1571+
f64.ne
1572+
if
1573+
f64.const 32
1574+
return
1575+
end
1576+
local.get $0
1577+
f64.const 4294967296
1578+
local.get $0
1579+
f64.const 2.3283064365386963e-10
1580+
f64.mul
1581+
f64.floor
1582+
f64.mul
1583+
f64.sub
1584+
i64.trunc_f64_s
1585+
i32.wrap_i64
15691586
i32.clz
15701587
f64.convert_i32_s
15711588
)
1572-
(func $std/libm/cos (; 22 ;) (type $FF) (param $0 f64) (result f64)
1589+
(func $std/libm/clz32 (; 22 ;) (type $FF) (param $0 f64) (result f64)
1590+
local.get $0
1591+
call $~lib/math/NativeMath.clz32
1592+
)
1593+
(func $std/libm/cos (; 23 ;) (type $FF) (param $0 f64) (result f64)
15731594
unreachable
15741595
)
1575-
(func $~lib/math/NativeMath.expm1 (; 23 ;) (type $FF) (param $0 f64) (result f64)
1596+
(func $~lib/math/NativeMath.expm1 (; 24 ;) (type $FF) (param $0 f64) (result f64)
15761597
(local $1 f64)
15771598
(local $2 f64)
15781599
(local $3 i32)
@@ -1851,7 +1872,7 @@
18511872
local.get $5
18521873
f64.mul
18531874
)
1854-
(func $~lib/math/NativeMath.scalbn (; 24 ;) (type $FiF) (param $0 f64) (param $1 i32) (result f64)
1875+
(func $~lib/math/NativeMath.scalbn (; 25 ;) (type $FiF) (param $0 f64) (param $1 i32) (result f64)
18551876
local.get $1
18561877
i32.const 1023
18571878
i32.gt_s
@@ -1928,7 +1949,7 @@
19281949
f64.reinterpret_i64
19291950
f64.mul
19301951
)
1931-
(func $~lib/math/NativeMath.exp (; 25 ;) (type $FF) (param $0 f64) (result f64)
1952+
(func $~lib/math/NativeMath.exp (; 26 ;) (type $FF) (param $0 f64) (result f64)
19321953
(local $1 i32)
19331954
(local $2 f64)
19341955
(local $3 i32)
@@ -2078,7 +2099,7 @@
20782099
local.get $3
20792100
call $~lib/math/NativeMath.scalbn
20802101
)
2081-
(func $~lib/math/NativeMath.cosh (; 26 ;) (type $FF) (param $0 f64) (result f64)
2102+
(func $~lib/math/NativeMath.cosh (; 27 ;) (type $FF) (param $0 f64) (result f64)
20822103
(local $1 i32)
20832104
(local $2 i64)
20842105
local.get $0
@@ -2142,27 +2163,27 @@
21422163
f64.const 2247116418577894884661631e283
21432164
f64.mul
21442165
)
2145-
(func $std/libm/cosh (; 27 ;) (type $FF) (param $0 f64) (result f64)
2166+
(func $std/libm/cosh (; 28 ;) (type $FF) (param $0 f64) (result f64)
21462167
local.get $0
21472168
call $~lib/math/NativeMath.cosh
21482169
)
2149-
(func $std/libm/exp (; 28 ;) (type $FF) (param $0 f64) (result f64)
2170+
(func $std/libm/exp (; 29 ;) (type $FF) (param $0 f64) (result f64)
21502171
local.get $0
21512172
call $~lib/math/NativeMath.exp
21522173
)
2153-
(func $std/libm/expm1 (; 29 ;) (type $FF) (param $0 f64) (result f64)
2174+
(func $std/libm/expm1 (; 30 ;) (type $FF) (param $0 f64) (result f64)
21542175
local.get $0
21552176
call $~lib/math/NativeMath.expm1
21562177
)
2157-
(func $std/libm/floor (; 30 ;) (type $FF) (param $0 f64) (result f64)
2178+
(func $std/libm/floor (; 31 ;) (type $FF) (param $0 f64) (result f64)
21582179
local.get $0
21592180
f64.floor
21602181
)
2161-
(func $std/libm/fround (; 31 ;) (type $Ff) (param $0 f64) (result f32)
2182+
(func $std/libm/fround (; 32 ;) (type $Ff) (param $0 f64) (result f32)
21622183
local.get $0
21632184
f32.demote_f64
21642185
)
2165-
(func $~lib/math/NativeMath.hypot (; 32 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
2186+
(func $~lib/math/NativeMath.hypot (; 33 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
21662187
(local $2 f64)
21672188
(local $3 i64)
21682189
(local $4 f64)
@@ -2341,12 +2362,12 @@
23412362
f64.sqrt
23422363
f64.mul
23432364
)
2344-
(func $std/libm/hypot (; 33 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
2365+
(func $std/libm/hypot (; 34 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
23452366
local.get $0
23462367
local.get $1
23472368
call $~lib/math/NativeMath.hypot
23482369
)
2349-
(func $~lib/math/NativeMath.imul (; 34 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
2370+
(func $~lib/math/NativeMath.imul (; 35 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
23502371
(local $2 f64)
23512372
local.get $0
23522373
local.get $1
@@ -2383,16 +2404,16 @@
23832404
i32.mul
23842405
f64.convert_i32_s
23852406
)
2386-
(func $std/libm/imul (; 35 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
2407+
(func $std/libm/imul (; 36 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
23872408
local.get $0
23882409
local.get $1
23892410
call $~lib/math/NativeMath.imul
23902411
)
2391-
(func $std/libm/log (; 36 ;) (type $FF) (param $0 f64) (result f64)
2412+
(func $std/libm/log (; 37 ;) (type $FF) (param $0 f64) (result f64)
23922413
local.get $0
23932414
call $~lib/math/NativeMath.log
23942415
)
2395-
(func $~lib/math/NativeMath.log10 (; 37 ;) (type $FF) (param $0 f64) (result f64)
2416+
(func $~lib/math/NativeMath.log10 (; 38 ;) (type $FF) (param $0 f64) (result f64)
23962417
(local $1 f64)
23972418
(local $2 i32)
23982419
(local $3 i32)
@@ -2604,15 +2625,15 @@
26042625
local.get $0
26052626
f64.add
26062627
)
2607-
(func $std/libm/log10 (; 38 ;) (type $FF) (param $0 f64) (result f64)
2628+
(func $std/libm/log10 (; 39 ;) (type $FF) (param $0 f64) (result f64)
26082629
local.get $0
26092630
call $~lib/math/NativeMath.log10
26102631
)
2611-
(func $std/libm/log1p (; 39 ;) (type $FF) (param $0 f64) (result f64)
2632+
(func $std/libm/log1p (; 40 ;) (type $FF) (param $0 f64) (result f64)
26122633
local.get $0
26132634
call $~lib/math/NativeMath.log1p
26142635
)
2615-
(func $~lib/math/NativeMath.log2 (; 40 ;) (type $FF) (param $0 f64) (result f64)
2636+
(func $~lib/math/NativeMath.log2 (; 41 ;) (type $FF) (param $0 f64) (result f64)
26162637
(local $1 f64)
26172638
(local $2 i32)
26182639
(local $3 i32)
@@ -2818,21 +2839,21 @@
28182839
local.get $0
28192840
f64.add
28202841
)
2821-
(func $std/libm/log2 (; 41 ;) (type $FF) (param $0 f64) (result f64)
2842+
(func $std/libm/log2 (; 42 ;) (type $FF) (param $0 f64) (result f64)
28222843
local.get $0
28232844
call $~lib/math/NativeMath.log2
28242845
)
2825-
(func $std/libm/max (; 42 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
2846+
(func $std/libm/max (; 43 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
28262847
local.get $0
28272848
local.get $1
28282849
f64.max
28292850
)
2830-
(func $std/libm/min (; 43 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
2851+
(func $std/libm/min (; 44 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
28312852
local.get $0
28322853
local.get $1
28332854
f64.min
28342855
)
2835-
(func $~lib/math/NativeMath.pow (; 44 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
2856+
(func $~lib/math/NativeMath.pow (; 45 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
28362857
(local $2 f64)
28372858
(local $3 f64)
28382859
(local $4 i32)
@@ -3782,20 +3803,20 @@
37823803
f64.const 1e-300
37833804
f64.mul
37843805
)
3785-
(func $std/libm/pow (; 45 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
3806+
(func $std/libm/pow (; 46 ;) (type $FFF) (param $0 f64) (param $1 f64) (result f64)
37863807
local.get $0
37873808
local.get $1
37883809
call $~lib/math/NativeMath.pow
37893810
)
3790-
(func $std/libm/round (; 46 ;) (type $FF) (param $0 f64) (result f64)
3811+
(func $std/libm/round (; 47 ;) (type $FF) (param $0 f64) (result f64)
37913812
local.get $0
37923813
f64.const 0.5
37933814
f64.add
37943815
f64.floor
37953816
local.get $0
37963817
f64.copysign
37973818
)
3798-
(func $std/libm/sign (; 47 ;) (type $FF) (param $0 f64) (result f64)
3819+
(func $std/libm/sign (; 48 ;) (type $FF) (param $0 f64) (result f64)
37993820
local.get $0
38003821
f64.const 0
38013822
f64.gt
@@ -3813,7 +3834,7 @@
38133834
end
38143835
local.get $0
38153836
)
3816-
(func $~lib/math/NativeMath.sinh (; 48 ;) (type $FF) (param $0 f64) (result f64)
3837+
(func $~lib/math/NativeMath.sinh (; 49 ;) (type $FF) (param $0 f64) (result f64)
38173838
(local $1 f64)
38183839
(local $2 f64)
38193840
(local $3 i32)
@@ -3890,15 +3911,15 @@
38903911
f64.mul
38913912
f64.mul
38923913
)
3893-
(func $std/libm/sinh (; 49 ;) (type $FF) (param $0 f64) (result f64)
3914+
(func $std/libm/sinh (; 50 ;) (type $FF) (param $0 f64) (result f64)
38943915
local.get $0
38953916
call $~lib/math/NativeMath.sinh
38963917
)
3897-
(func $std/libm/sqrt (; 50 ;) (type $FF) (param $0 f64) (result f64)
3918+
(func $std/libm/sqrt (; 51 ;) (type $FF) (param $0 f64) (result f64)
38983919
local.get $0
38993920
f64.sqrt
39003921
)
3901-
(func $~lib/math/NativeMath.tanh (; 51 ;) (type $FF) (param $0 f64) (result f64)
3922+
(func $~lib/math/NativeMath.tanh (; 52 ;) (type $FF) (param $0 f64) (result f64)
39023923
(local $1 f64)
39033924
(local $2 i32)
39043925
(local $3 i64)
@@ -3977,15 +3998,15 @@
39773998
local.get $0
39783999
f64.copysign
39794000
)
3980-
(func $std/libm/tanh (; 52 ;) (type $FF) (param $0 f64) (result f64)
4001+
(func $std/libm/tanh (; 53 ;) (type $FF) (param $0 f64) (result f64)
39814002
local.get $0
39824003
call $~lib/math/NativeMath.tanh
39834004
)
3984-
(func $std/libm/trunc (; 53 ;) (type $FF) (param $0 f64) (result f64)
4005+
(func $std/libm/trunc (; 54 ;) (type $FF) (param $0 f64) (result f64)
39854006
local.get $0
39864007
f64.trunc
39874008
)
3988-
(func $null (; 54 ;) (type $_)
4009+
(func $null (; 55 ;) (type $_)
39894010
nop
39904011
)
39914012
)

0 commit comments

Comments
 (0)