Add i64 polyfill example

This commit is contained in:
dcodeIO 2017-12-11 22:04:30 +01:00
parent 7e93618384
commit 09cbad6ede
8 changed files with 1912 additions and 93 deletions

View File

@ -20,6 +20,8 @@ A few early examples to get an idea:
[source](./tests/compiler/memcpy.ts) - [wast](./tests/compiler/memcpy.optimized.wast) [source](./tests/compiler/memcpy.ts) - [wast](./tests/compiler/memcpy.optimized.wast)
* **Conway's Game of Life** as seen on [dcode.io](http://dcode.io)<br /> * **Conway's Game of Life** as seen on [dcode.io](http://dcode.io)<br />
[source](./tests/compiler/game-of-life.ts) - [wast](./tests/compiler/game-of-life.optimized.wast) - [html](./tests/compiler/game-of-life.html) [source](./tests/compiler/game-of-life.ts) - [wast](./tests/compiler/game-of-life.optimized.wast) - [html](./tests/compiler/game-of-life.html)
* **i64 polyfill** using 32-bit integers<br />
[source](./tests/compiler/i64.ts) - [wast](./tests/compiler/i64.optimized.wast)
Getting started Getting started
--------------- ---------------
@ -32,7 +34,7 @@ $> cd next
$> npm install $> npm install
``` ```
Author your module in AssemblyScript ([definitions](./assembly.d.ts), [base config](./assembly.json)) or portable AssemblyScript ([definitions](./portable.d.ts), [base config](./portable.json) and run: Author your module in AssemblyScript ([definitions](./assembly.d.ts), [base config](./assembly.json)) or portable AssemblyScript ([definitions](./portable.d.ts), [base config](./portable.json)) and run:
``` ```
$> node bin\asc yourModule.ts $> node bin\asc yourModule.ts

View File

@ -1206,7 +1206,7 @@ export class Compiler extends DiagnosticEmitter {
// i64 to i32 // i64 to i32
if (!toType.isLongInteger) { if (!toType.isLongInteger) {
losesInformation = true; losesInformation = true;
expr = mod.createUnary(UnaryOp.WrapI64, expr); expr = mod.createUnary(UnaryOp.WrapI64, expr); // discards upper bits
if (toType.isSmallInteger) { if (toType.isSmallInteger) {
if (toType.isSignedInteger) { if (toType.isSignedInteger) {
expr = mod.createBinary(BinaryOp.ShlI32, expr, mod.createI32(toType.smallIntegerShift)); expr = mod.createBinary(BinaryOp.ShlI32, expr, mod.createI32(toType.smallIntegerShift));

View File

@ -1,8 +1,16 @@
(module (module
(type $i (func (result i32)))
(type $iiv (func (param i32 i32)))
(type $iiiiv (func (param i32 i32 i32 i32))) (type $iiiiv (func (param i32 i32 i32 i32)))
(global $i64/lo (mut i32) (i32.const 0)) (global $i64/lo (mut i32) (i32.const 0))
(global $i64/hi (mut i32) (i32.const 0)) (global $i64/hi (mut i32) (i32.const 0))
(memory $0 1) (memory $0 1)
(export "getLo" (func $i64/getLo))
(export "getHi" (func $i64/getHi))
(export "clz" (func $i64/clz_))
(export "ctz" (func $i64/ctz_))
(export "popcnt" (func $i64/popcnt_))
(export "eqz" (func $i64/eqz))
(export "add" (func $i64/add)) (export "add" (func $i64/add))
(export "sub" (func $i64/sub)) (export "sub" (func $i64/sub))
(export "mul" (func $i64/mul)) (export "mul" (func $i64/mul))
@ -10,30 +18,140 @@
(export "div_u" (func $i64/div_u)) (export "div_u" (func $i64/div_u))
(export "rem_s" (func $i64/rem_s)) (export "rem_s" (func $i64/rem_s))
(export "rem_u" (func $i64/rem_u)) (export "rem_u" (func $i64/rem_u))
(export "and" (func $i64/and))
(export "or" (func $i64/or))
(export "xor" (func $i64/xor))
(export "shl" (func $i64/shl))
(export "shr_u" (func $i64/shr_u))
(export "shr_s" (func $i64/shr_s))
(export "rotl" (func $i64/rotl_))
(export "rotr" (func $i64/rotr_))
(export "eq" (func $i64/eq))
(export "ne" (func $i64/ne))
(export "lt_s" (func $i64/lt_s))
(export "lt_u" (func $i64/lt_u))
(export "le_s" (func $i64/le_s))
(export "le_u" (func $i64/le_u))
(export "gt_s" (func $i64/gt_s))
(export "gt_u" (func $i64/gt_u))
(export "ge_s" (func $i64/ge_s))
(export "ge_u" (func $i64/ge_u))
(export "memory" (memory $0)) (export "memory" (memory $0))
(func $i64/add (; 0 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (func $i64/getLo (; 0 ;) (type $i) (result i32)
(get_global $i64/lo)
)
(func $i64/getHi (; 1 ;) (type $i) (result i32)
(get_global $i64/hi)
)
(func $i64/clz_ (; 2 ;) (type $iiv) (param $0 i32) (param $1 i32)
(set_global $i64/lo
(i32.wrap/i64
(i64.clz
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/ctz_ (; 3 ;) (type $iiv) (param $0 i32) (param $1 i32)
(set_global $i64/lo
(i32.wrap/i64
(i64.ctz
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/popcnt_ (; 4 ;) (type $iiv) (param $0 i32) (param $1 i32)
(set_global $i64/lo
(i32.wrap/i64
(i64.popcnt
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/eqz (; 5 ;) (type $iiv) (param $0 i32) (param $1 i32)
(set_global $i64/lo
(i64.eqz
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/add (; 6 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64) (local $4 i64)
(set_global $i64/lo (set_global $i64/lo
(i32.wrap/i64 (i32.wrap/i64
(tee_local $4 (tee_local $4
(i64.add (i64.add
(i64.or (i64.or
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $0) (get_local $0)
) )
(i64.shl (i64.shl
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $1) (get_local $1)
) )
(i64.const 32) (i64.const 32)
) )
) )
(i64.or (i64.or
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $2) (get_local $2)
) )
(i64.shl (i64.shl
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $3) (get_local $3)
) )
(i64.const 32) (i64.const 32)
@ -52,29 +170,29 @@
) )
) )
) )
(func $i64/sub (; 1 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (func $i64/sub (; 7 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64) (local $4 i64)
(set_global $i64/lo (set_global $i64/lo
(i32.wrap/i64 (i32.wrap/i64
(tee_local $4 (tee_local $4
(i64.sub (i64.sub
(i64.or (i64.or
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $0) (get_local $0)
) )
(i64.shl (i64.shl
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $1) (get_local $1)
) )
(i64.const 32) (i64.const 32)
) )
) )
(i64.or (i64.or
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $2) (get_local $2)
) )
(i64.shl (i64.shl
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $3) (get_local $3)
) )
(i64.const 32) (i64.const 32)
@ -93,29 +211,29 @@
) )
) )
) )
(func $i64/mul (; 2 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (func $i64/mul (; 8 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64) (local $4 i64)
(set_global $i64/lo (set_global $i64/lo
(i32.wrap/i64 (i32.wrap/i64
(tee_local $4 (tee_local $4
(i64.mul (i64.mul
(i64.or (i64.or
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $0) (get_local $0)
) )
(i64.shl (i64.shl
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $1) (get_local $1)
) )
(i64.const 32) (i64.const 32)
) )
) )
(i64.or (i64.or
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $2) (get_local $2)
) )
(i64.shl (i64.shl
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $3) (get_local $3)
) )
(i64.const 32) (i64.const 32)
@ -134,29 +252,29 @@
) )
) )
) )
(func $i64/div_s (; 3 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (func $i64/div_s (; 9 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64) (local $4 i64)
(set_global $i64/lo (set_global $i64/lo
(i32.wrap/i64 (i32.wrap/i64
(tee_local $4 (tee_local $4
(i64.div_s (i64.div_s
(i64.or (i64.or
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $0) (get_local $0)
) )
(i64.shl (i64.shl
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $1) (get_local $1)
) )
(i64.const 32) (i64.const 32)
) )
) )
(i64.or (i64.or
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $2) (get_local $2)
) )
(i64.shl (i64.shl
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $3) (get_local $3)
) )
(i64.const 32) (i64.const 32)
@ -175,7 +293,7 @@
) )
) )
) )
(func $i64/div_u (; 4 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (func $i64/div_u (; 10 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64) (local $4 i64)
(set_global $i64/lo (set_global $i64/lo
(i32.wrap/i64 (i32.wrap/i64
@ -216,29 +334,29 @@
) )
) )
) )
(func $i64/rem_s (; 5 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (func $i64/rem_s (; 11 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64) (local $4 i64)
(set_global $i64/lo (set_global $i64/lo
(i32.wrap/i64 (i32.wrap/i64
(tee_local $4 (tee_local $4
(i64.rem_s (i64.rem_s
(i64.or (i64.or
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $0) (get_local $0)
) )
(i64.shl (i64.shl
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $1) (get_local $1)
) )
(i64.const 32) (i64.const 32)
) )
) )
(i64.or (i64.or
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $2) (get_local $2)
) )
(i64.shl (i64.shl
(i64.extend_s/i32 (i64.extend_u/i32
(get_local $3) (get_local $3)
) )
(i64.const 32) (i64.const 32)
@ -257,7 +375,7 @@
) )
) )
) )
(func $i64/rem_u (; 6 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32) (func $i64/rem_u (; 12 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64) (local $4 i64)
(set_global $i64/lo (set_global $i64/lo
(i32.wrap/i64 (i32.wrap/i64
@ -298,4 +416,642 @@
) )
) )
) )
(func $i64/and (; 13 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64)
(set_global $i64/lo
(i32.wrap/i64
(tee_local $4
(i64.and
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
)
)
(set_global $i64/hi
(i32.wrap/i64
(i64.shr_u
(get_local $4)
(i64.const 32)
)
)
)
)
(func $i64/or (; 14 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64)
(set_global $i64/lo
(i32.wrap/i64
(tee_local $4
(i64.or
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
)
)
(set_global $i64/hi
(i32.wrap/i64
(i64.shr_u
(get_local $4)
(i64.const 32)
)
)
)
)
(func $i64/xor (; 15 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64)
(set_global $i64/lo
(i32.wrap/i64
(tee_local $4
(i64.xor
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
)
)
(set_global $i64/hi
(i32.wrap/i64
(i64.shr_u
(get_local $4)
(i64.const 32)
)
)
)
)
(func $i64/shl (; 16 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64)
(set_global $i64/lo
(i32.wrap/i64
(tee_local $4
(i64.shl
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
)
)
(set_global $i64/hi
(i32.wrap/i64
(i64.shr_u
(get_local $4)
(i64.const 32)
)
)
)
)
(func $i64/shr_u (; 17 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64)
(set_global $i64/lo
(i32.wrap/i64
(tee_local $4
(i64.shr_u
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
)
)
(set_global $i64/hi
(i32.wrap/i64
(i64.shr_u
(get_local $4)
(i64.const 32)
)
)
)
)
(func $i64/shr_s (; 18 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64)
(set_global $i64/lo
(i32.wrap/i64
(tee_local $4
(i64.shr_s
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
)
)
(set_global $i64/hi
(i32.wrap/i64
(i64.shr_u
(get_local $4)
(i64.const 32)
)
)
)
)
(func $i64/rotl_ (; 19 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64)
(set_global $i64/lo
(i32.wrap/i64
(tee_local $4
(i64.rotl
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
)
)
(set_global $i64/hi
(i32.wrap/i64
(i64.shr_u
(get_local $4)
(i64.const 32)
)
)
)
)
(func $i64/rotr_ (; 20 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(local $4 i64)
(set_global $i64/lo
(i32.wrap/i64
(tee_local $4
(i64.rotr
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
)
)
(set_global $i64/hi
(i32.wrap/i64
(i64.shr_u
(get_local $4)
(i64.const 32)
)
)
)
)
(func $i64/eq (; 21 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(set_global $i64/lo
(i64.eq
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/ne (; 22 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(set_global $i64/lo
(i64.ne
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/lt_s (; 23 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(set_global $i64/lo
(i64.lt_s
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/lt_u (; 24 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(set_global $i64/lo
(i64.lt_u
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/le_s (; 25 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(set_global $i64/lo
(i64.le_s
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/le_u (; 26 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(set_global $i64/lo
(i64.le_u
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/gt_s (; 27 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(set_global $i64/lo
(i64.gt_s
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/gt_u (; 28 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(set_global $i64/lo
(i64.gt_u
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/ge_s (; 29 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(set_global $i64/lo
(i64.ge_s
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
(func $i64/ge_u (; 30 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(set_global $i64/lo
(i64.ge_u
(i64.or
(i64.extend_u/i32
(get_local $0)
)
(i64.shl
(i64.extend_u/i32
(get_local $1)
)
(i64.const 32)
)
)
(i64.or
(i64.extend_u/i32
(get_local $2)
)
(i64.shl
(i64.extend_u/i32
(get_local $3)
)
(i64.const 32)
)
)
)
)
(set_global $i64/hi
(i32.const 0)
)
)
) )

View File

@ -1,40 +1,75 @@
let lo: u32; let lo: u32;
let hi: u32; let hi: u32;
export function add(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void { export function getLo(): u32 {
const ret: i64 = (<i64>loLeft | <i64>hiLeft << 32) + (<i64>loRight | <i64>hiRight << 32); return lo;
}
export function getHi(): u32 {
return hi;
}
function clz_(loLeft: u32, hiLeft: u32): void {
const ret: u64 = clz<u64>(<u64>loLeft | <u64>hiLeft << 32);
lo = <u32>ret; lo = <u32>ret;
hi = <u32>(ret >>> 32); hi = 0;
}
export { clz_ as clz };
function ctz_(loLeft: u32, hiLeft: u32): void {
const ret: u64 = ctz<u64>(<u64>loLeft | <u64>hiLeft << 32);
lo = <u32>ret;
hi = 0;
}
export { ctz_ as ctz };
function popcnt_(loLeft: u32, hiLeft: u32): void {
const ret: u64 = popcnt<u64>(<u64>loLeft | <u64>hiLeft << 32);
lo = <u32>ret;
hi = 0;
}
export { popcnt_ as popcnt };
export function eqz(loLeft: u32, hiLeft: u32): void {
const ret: bool = !(<u64>loLeft | <u64>hiLeft << 32);
lo = <u32>ret;
hi = 0;
}
export function add(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: u64 = (<u64>loLeft | <u64>hiLeft << 32) + (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = <u32>(ret >> 32);
} }
export function sub(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void { export function sub(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: i64 = (<i64>loLeft | <i64>hiLeft << 32) - (<i64>loRight | <i64>hiRight << 32); const ret: u64 = (<u64>loLeft | <u64>hiLeft << 32) - (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret; lo = <u32>ret;
hi = <u32>(ret >>> 32); hi = <u32>(ret >> 32);
} }
export function mul(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void { export function mul(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: i64 = (<i64>loLeft | <i64>hiLeft << 32) * (<i64>loRight | <i64>hiRight << 32); const ret: u64 = (<u64>loLeft | <u64>hiLeft << 32) * (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret; lo = <u32>ret;
hi = <u32>(ret >>> 32); hi = <u32>(ret >> 32);
} }
export function div_s(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void { export function div_s(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: i64 = (<i64>loLeft | <i64>hiLeft << 32) / (<i64>loRight | <i64>hiRight << 32); const ret: u64 = <u64>(<i64>(<u64>loLeft | <u64>hiLeft << 32) / <i64>(<u64>loRight | <u64>hiRight << 32));
lo = <u32>ret; lo = <u32>ret;
hi = <u32>(ret >>> 32); hi = <u32>(ret >> 32);
} }
export function div_u(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void { export function div_u(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: u64 = (<u64>loLeft | <u64>hiLeft << 32) / (<u64>loRight | <u64>hiRight << 32); const ret: u64 = (<u64>loLeft | <u64>hiLeft << 32) / (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret; lo = <u32>ret;
hi = <u32>(ret >>> 32); hi = <u32>(ret >> 32);
} }
export function rem_s(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void { export function rem_s(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: i64 = (<i64>loLeft | <i64>hiLeft << 32) % (<i64>loRight | <i64>hiRight << 32); const ret: u64 = <u64>(<i64>(<u64>loLeft | <u64>hiLeft << 32) % <i64>(<u64>loRight | <u64>hiRight << 32));
lo = <u32>ret; lo = <u32>ret;
hi = <u32>(ret >>> 32); hi = <u32>(ret >> 32);
} }
export function rem_u(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void { export function rem_u(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
@ -42,3 +77,113 @@ export function rem_u(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): voi
lo = <u32>ret; lo = <u32>ret;
hi = <u32>(ret >>> 32); hi = <u32>(ret >>> 32);
} }
export function and(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: u64 = (<u64>loLeft | <u64>hiLeft << 32) & (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = <u32>(ret >>> 32);
}
export function or(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: u64 = (<u64>loLeft | <u64>hiLeft << 32) | (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = <u32>(ret >>> 32);
}
export function xor(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: u64 = (<u64>loLeft | <u64>hiLeft << 32) ^ (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = <u32>(ret >>> 32);
}
export function shl(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: u64 = (<u64>loLeft | <u64>hiLeft << 32) << (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = <u32>(ret >>> 32);
}
export function shr_u(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: u64 = (<u64>loLeft | <u64>hiLeft << 32) >> (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = <u32>(ret >>> 32);
}
export function shr_s(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: u64 = <u64>(<i64>(<u64>loLeft | <u64>hiLeft << 32) >> <i64>(<u64>loRight | <u64>hiRight << 32));
lo = <u32>ret;
hi = <u32>(ret >>> 32);
}
function rotl_(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: u64 = rotl<u64>(<u64>loLeft | <u64>hiLeft << 32, <u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = <u32>(ret >>> 32);
}
export { rotl_ as rotl };
function rotr_(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: u64 = rotr<u64>(<u64>loLeft | <u64>hiLeft << 32, <u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = <u32>(ret >>> 32);
}
export { rotr_ as rotr };
export function eq(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: bool = (<u64>loLeft | <u64>hiLeft << 32) == (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = 0;
}
export function ne(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: bool = (<u64>loLeft | <u64>hiLeft << 32) != (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = 0;
}
export function lt_s(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: bool = <i64>(<u64>loLeft | <u64>hiLeft << 32) < <i64>(<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = 0;
}
export function lt_u(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: bool = (<u64>loLeft | <u64>hiLeft << 32) < (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = 0;
}
export function le_s(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: bool = <i64>(<u64>loLeft | <u64>hiLeft << 32) <= <i64>(<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = 0;
}
export function le_u(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: bool = (<u64>loLeft | <u64>hiLeft << 32) <= (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = 0;
}
export function gt_s(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: bool = <i64>(<u64>loLeft | <u64>hiLeft << 32) > <i64>(<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = 0;
}
export function gt_u(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: bool = (<u64>loLeft | <u64>hiLeft << 32) > (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = 0;
}
export function ge_s(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: bool = <i64>(<u64>loLeft | <u64>hiLeft << 32) >= <i64>(<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = 0;
}
export function ge_u(loLeft: u32, hiLeft: u32, loRight: u32, hiRight: u32): void {
const ret: bool = (<u64>loLeft | <u64>hiLeft << 32) >= (<u64>loRight | <u64>hiRight << 32);
lo = <u32>ret;
hi = 0;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
(module (module
(type $iiii (func (param i32 i32 i32) (result i32))) (type $iiii (func (param i32 i32 i32) (result i32)))
(type $v (func)) (type $v (func))
(global $memcpy/dst (mut i32) (i32.const 0)) (global $memcpy/dest (mut i32) (i32.const 0))
(memory $0 1) (memory $0 1)
(export "memcpy" (func $memcpy/memcpy)) (export "memcpy" (func $memcpy/memcpy))
(export "memory" (memory $0)) (export "memory" (memory $0))
@ -1588,7 +1588,7 @@
(i32.const 32) (i32.const 32)
(i64.const 4919131752989213764) (i64.const 4919131752989213764)
) )
(set_global $memcpy/dst (set_global $memcpy/dest
(call $memcpy/memcpy (call $memcpy/memcpy
(i32.const 9) (i32.const 9)
(i32.const 24) (i32.const 24)
@ -1597,7 +1597,7 @@
) )
(if (if
(i32.ne (i32.ne
(get_global $memcpy/dst) (get_global $memcpy/dest)
(i32.const 9) (i32.const 9)
) )
(unreachable) (unreachable)
@ -1611,7 +1611,7 @@
) )
(unreachable) (unreachable)
) )
(set_global $memcpy/dst (set_global $memcpy/dest
(call $memcpy/memcpy (call $memcpy/memcpy
(i32.const 8) (i32.const 8)
(i32.const 8) (i32.const 8)
@ -1620,7 +1620,7 @@
) )
(if (if
(i32.ne (i32.ne
(get_global $memcpy/dst) (get_global $memcpy/dest)
(i32.const 8) (i32.const 8)
) )
(unreachable) (unreachable)
@ -1661,7 +1661,7 @@
) )
(unreachable) (unreachable)
) )
(set_global $memcpy/dst (set_global $memcpy/dest
(call $memcpy/memcpy (call $memcpy/memcpy
(i32.const 13) (i32.const 13)
(i32.const 36) (i32.const 36)
@ -1677,7 +1677,7 @@
) )
(unreachable) (unreachable)
) )
(set_global $memcpy/dst (set_global $memcpy/dest
(call $memcpy/memcpy (call $memcpy/memcpy
(i32.const 16) (i32.const 16)
(i32.const 24) (i32.const 24)

View File

@ -9,7 +9,7 @@ export function memcpy(dest: usize, src: usize, n: usize): usize {
n--; n--;
} }
// if dst is aligned to 4 bytes as well, copy 4 bytes each // if dest is aligned to 4 bytes as well, copy 4 bytes each
if (d % 4 == 0) { if (d % 4 == 0) {
while (n >= 16) { while (n >= 16) {
store<u32>(d , load<u32>(s )); store<u32>(d , load<u32>(s ));
@ -27,7 +27,7 @@ export function memcpy(dest: usize, src: usize, n: usize): usize {
store<u32>(d, load<u32>(s)); store<u32>(d, load<u32>(s));
d += 4; s += 4; d += 4; s += 4;
} }
if (n & 2) { // drop to 2 bytes each if (n & 2) { // drop to 2 bytes
store<u16>(d, load<u16>(s)); store<u16>(d, load<u16>(s));
d += 2; s += 2; d += 2; s += 2;
} }
@ -37,7 +37,7 @@ export function memcpy(dest: usize, src: usize, n: usize): usize {
return dest; return dest;
} }
// if dst is not aligned to 4 bytes, use alternating shifts to copy 4 bytes each // if dest is not aligned to 4 bytes, use alternating shifts to copy 4 bytes each
// doing shifts if faster when copying enough bytes (here: 32 or more) // doing shifts if faster when copying enough bytes (here: 32 or more)
if (n >= 32) { if (n >= 32) {
switch (d % 4) { switch (d % 4) {
@ -147,22 +147,22 @@ store<u64>(base + 8 , 0x2222222222222222);
store<u64>(base + 16, 0x3333333333333333); store<u64>(base + 16, 0x3333333333333333);
store<u64>(base + 24, 0x4444444444444444); store<u64>(base + 24, 0x4444444444444444);
let dst: usize; let dest: usize;
dst = memcpy(base + 1, base + 16, 4); dest = memcpy(base + 1, base + 16, 4);
assert(dst == base + 1); assert(dest == base + 1);
assert(load<u64>(base) == 0x1111113333333311); assert(load<u64>(base) == 0x1111113333333311);
dst = memcpy(base, base, 32); dest = memcpy(base, base, 32);
assert(dst == base); assert(dest == base);
assert(load<u64>(base) == 0x1111113333333311); assert(load<u64>(base) == 0x1111113333333311);
assert(load<u64>(base + 8) == 0x2222222222222222); assert(load<u64>(base + 8) == 0x2222222222222222);
assert(load<u64>(base + 16) == 0x3333333333333333); assert(load<u64>(base + 16) == 0x3333333333333333);
assert(load<u64>(base + 24) == 0x4444444444444444); assert(load<u64>(base + 24) == 0x4444444444444444);
dst = memcpy(base + 5, base + 28, 3); dest = memcpy(base + 5, base + 28, 3);
assert(load<u64>(base) == 0x4444443333333311); assert(load<u64>(base) == 0x4444443333333311);
dst = memcpy(base + 8, base + 16, 15); dest = memcpy(base + 8, base + 16, 15);
assert(load<u64>(base) == 0x4444443333333311); assert(load<u64>(base) == 0x4444443333333311);
assert(load<u64>(base + 8) == 0x3333333333333333); assert(load<u64>(base + 8) == 0x3333333333333333);
assert(load<u64>(base + 16) == 0x3344444444444444); assert(load<u64>(base + 16) == 0x3344444444444444);

View File

@ -2,7 +2,7 @@
(type $iiii (func (param i32 i32 i32) (result i32))) (type $iiii (func (param i32 i32 i32) (result i32)))
(type $v (func)) (type $v (func))
(global $memcpy/base i32 (i32.const 8)) (global $memcpy/base i32 (i32.const 8))
(global $memcpy/dst (mut i32) (i32.const 0)) (global $memcpy/dest (mut i32) (i32.const 0))
(global $HEAP_START i32 (i32.const 4)) (global $HEAP_START i32 (i32.const 4))
(memory $0 1) (memory $0 1)
(export "memcpy" (func $memcpy/memcpy)) (export "memcpy" (func $memcpy/memcpy))
@ -1936,7 +1936,7 @@
) )
(i64.const 4919131752989213764) (i64.const 4919131752989213764)
) )
(set_global $memcpy/dst (set_global $memcpy/dest
(call $memcpy/memcpy (call $memcpy/memcpy
(i32.add (i32.add
(i32.const 8) (i32.const 8)
@ -1952,7 +1952,7 @@
(if (if
(i32.eqz (i32.eqz
(i32.eq (i32.eq
(get_global $memcpy/dst) (get_global $memcpy/dest)
(i32.add (i32.add
(i32.const 8) (i32.const 8)
(i32.const 1) (i32.const 1)
@ -1972,7 +1972,7 @@
) )
(unreachable) (unreachable)
) )
(set_global $memcpy/dst (set_global $memcpy/dest
(call $memcpy/memcpy (call $memcpy/memcpy
(i32.const 8) (i32.const 8)
(i32.const 8) (i32.const 8)
@ -1982,7 +1982,7 @@
(if (if
(i32.eqz (i32.eqz
(i32.eq (i32.eq
(get_global $memcpy/dst) (get_global $memcpy/dest)
(i32.const 8) (i32.const 8)
) )
) )
@ -2041,7 +2041,7 @@
) )
(unreachable) (unreachable)
) )
(set_global $memcpy/dst (set_global $memcpy/dest
(call $memcpy/memcpy (call $memcpy/memcpy
(i32.add (i32.add
(i32.const 8) (i32.const 8)
@ -2065,7 +2065,7 @@
) )
(unreachable) (unreachable)
) )
(set_global $memcpy/dst (set_global $memcpy/dest
(call $memcpy/memcpy (call $memcpy/memcpy
(i32.add (i32.add
(i32.const 8) (i32.const 8)
@ -2163,7 +2163,7 @@
assert assert
memcpy/memcpy memcpy/memcpy
memcpy/base memcpy/base
memcpy/dst memcpy/dest
[program.exports] [program.exports]
memcpy/memcpy memcpy/memcpy
;) ;)