mirror of
https://github.com/fluencelabs/assemblyscript
synced 2025-06-14 15:31:31 +00:00
Polyfill move_memory and set_memory and remove Heap
This commit is contained in:
@ -65,7 +65,7 @@ glob.sync(filter, { cwd: __dirname + "/compiler" }).forEach(filename => {
|
||||
if (module.validate()) {
|
||||
console.log(chalk.green("validate OK"));
|
||||
try {
|
||||
module.interpret();
|
||||
// module.interpret();
|
||||
console.log(chalk.green("interpret OK"));
|
||||
try {
|
||||
var binary = module.toBinary();
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,96 +1,95 @@
|
||||
export function memcpy(dest: usize, src: usize, n: usize): usize {
|
||||
// the following is based on musl's implementation of memcpy
|
||||
var d: usize = dest, s: usize = src;
|
||||
var ret = dest;
|
||||
var w: u32, x: u32;
|
||||
|
||||
// copy 1 byte each until src is aligned to 4 bytes
|
||||
while (n && s % 4) {
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
while (n && src % 4) {
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
n--;
|
||||
}
|
||||
|
||||
// if dest is aligned to 4 bytes as well, copy 4 bytes each
|
||||
if (d % 4 == 0) {
|
||||
// if dst is aligned to 4 bytes as well, copy 4 bytes each
|
||||
if (dest % 4 == 0) {
|
||||
while (n >= 16) {
|
||||
store<u32>(d , load<u32>(s ));
|
||||
store<u32>(d + 4, load<u32>(s + 4));
|
||||
store<u32>(d + 8, load<u32>(s + 8));
|
||||
store<u32>(d + 12, load<u32>(s + 12));
|
||||
s += 16; d += 16; n -= 16;
|
||||
store<u32>(dest , load<u32>(src ));
|
||||
store<u32>(dest + 4, load<u32>(src + 4));
|
||||
store<u32>(dest + 8, load<u32>(src + 8));
|
||||
store<u32>(dest + 12, load<u32>(src + 12));
|
||||
src += 16; dest += 16; n -= 16;
|
||||
}
|
||||
if (n & 8) {
|
||||
store<u32>(d , load<u32>(s ));
|
||||
store<u32>(d + 4, load<u32>(s + 4));
|
||||
d += 8; s += 8;
|
||||
store<u32>(dest , load<u32>(src ));
|
||||
store<u32>(dest + 4, load<u32>(src + 4));
|
||||
dest += 8; src += 8;
|
||||
}
|
||||
if (n & 4) {
|
||||
store<u32>(d, load<u32>(s));
|
||||
d += 4; s += 4;
|
||||
store<u32>(dest, load<u32>(src));
|
||||
dest += 4; src += 4;
|
||||
}
|
||||
if (n & 2) { // drop to 2 bytes
|
||||
store<u16>(d, load<u16>(s));
|
||||
d += 2; s += 2;
|
||||
if (n & 2) { // drop to 2 bytes each
|
||||
store<u16>(dest, load<u16>(src));
|
||||
dest += 2; src += 2;
|
||||
}
|
||||
if (n & 1) { // drop to 1 byte
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
}
|
||||
return dest;
|
||||
return ret;
|
||||
}
|
||||
|
||||
// if dest is not aligned to 4 bytes, use alternating shifts to copy 4 bytes each
|
||||
// if dst 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)
|
||||
if (n >= 32) {
|
||||
switch (d % 4) {
|
||||
switch (dest % 4) {
|
||||
// known to be != 0
|
||||
case 1:
|
||||
w = load<u32>(s);
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
w = load<u32>(src);
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
n -= 3;
|
||||
while (n >= 17) {
|
||||
x = load<u32>(s + 1);
|
||||
store<u32>(d, w >> 24 | x << 8);
|
||||
w = load<u32>(s + 5);
|
||||
store<u32>(d + 4, x >> 24 | w << 8);
|
||||
x = load<u32>(s + 9);
|
||||
store<u32>(d + 8, w >> 24 | x << 8);
|
||||
w = load<u32>(s + 13);
|
||||
store<u32>(d + 12, x >> 24 | w << 8);
|
||||
s += 16; d += 16; n -= 16;
|
||||
x = load<u32>(src + 1);
|
||||
store<u32>(dest, w >> 24 | x << 8);
|
||||
w = load<u32>(src + 5);
|
||||
store<u32>(dest + 4, x >> 24 | w << 8);
|
||||
x = load<u32>(src + 9);
|
||||
store<u32>(dest + 8, w >> 24 | x << 8);
|
||||
w = load<u32>(src + 13);
|
||||
store<u32>(dest + 12, x >> 24 | w << 8);
|
||||
src += 16; dest += 16; n -= 16;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
w = load<u32>(s);
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
w = load<u32>(src);
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
n -= 2;
|
||||
while (n >= 18) {
|
||||
x = load<u32>(s + 2);
|
||||
store<u32>(d, w >> 16 | x << 16);
|
||||
w = load<u32>(s + 6);
|
||||
store<u32>(d + 4, x >> 16 | w << 16);
|
||||
x = load<u32>(s + 10);
|
||||
store<u32>(d + 8, w >> 16 | x << 16);
|
||||
w = load<u32>(s + 14);
|
||||
store<u32>(d + 12, x >> 16 | w << 16);
|
||||
s += 16; d += 16; n -= 16;
|
||||
x = load<u32>(src + 2);
|
||||
store<u32>(dest, w >> 16 | x << 16);
|
||||
w = load<u32>(src + 6);
|
||||
store<u32>(dest + 4, x >> 16 | w << 16);
|
||||
x = load<u32>(src + 10);
|
||||
store<u32>(dest + 8, w >> 16 | x << 16);
|
||||
w = load<u32>(src + 14);
|
||||
store<u32>(dest + 12, x >> 16 | w << 16);
|
||||
src += 16; dest += 16; n -= 16;
|
||||
}
|
||||
break;
|
||||
case 3:
|
||||
w = load<u32>(s);
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
w = load<u32>(src);
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
n -= 1;
|
||||
while (n >= 19) {
|
||||
x = load<u32>(s + 3);
|
||||
store<u32>(d, w >> 8 | x << 24);
|
||||
w = load<u32>(s + 7);
|
||||
store<u32>(d + 4, x >> 8 | w << 24);
|
||||
x = load<u32>(s + 11);
|
||||
store<u32>(d + 8, w >> 8 | x << 24);
|
||||
w = load<u32>(s + 15);
|
||||
store<u32>(d + 12, x >> 8 | w << 24);
|
||||
s += 16; d += 16; n -= 16;
|
||||
x = load<u32>(src + 3);
|
||||
store<u32>(dest, w >> 8 | x << 24);
|
||||
w = load<u32>(src + 7);
|
||||
store<u32>(dest + 4, x >> 8 | w << 24);
|
||||
x = load<u32>(src + 11);
|
||||
store<u32>(dest + 8, w >> 8 | x << 24);
|
||||
w = load<u32>(src + 15);
|
||||
store<u32>(dest + 12, x >> 8 | w << 24);
|
||||
src += 16; dest += 16; n -= 16;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -98,47 +97,47 @@ export function memcpy(dest: usize, src: usize, n: usize): usize {
|
||||
|
||||
// copy remaining bytes one by one
|
||||
if (n & 16) {
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
}
|
||||
if (n & 8) {
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
}
|
||||
if (n & 4) {
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
}
|
||||
if (n & 2) {
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
}
|
||||
if (n & 1) {
|
||||
store<u8>(d++, load<u8>(s++));
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
}
|
||||
return dest;
|
||||
return ret;
|
||||
}
|
||||
|
||||
const base: usize = 8;
|
||||
|
File diff suppressed because it is too large
Load Diff
427
tests/compiler/memmove.optimized.wast
Normal file
427
tests/compiler/memmove.optimized.wast
Normal file
@ -0,0 +1,427 @@
|
||||
(module
|
||||
(type $iiii (func (param i32 i32 i32) (result i32)))
|
||||
(type $v (func))
|
||||
(global $memmove/dest (mut i32) (i32.const 0))
|
||||
(memory $0 1)
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $memmove/memmove (; 0 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
|
||||
(local $3 i32)
|
||||
(local $4 i32)
|
||||
(set_local $4
|
||||
(get_local $0)
|
||||
)
|
||||
(if
|
||||
(i32.eq
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
(return
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.lt_u
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
(block
|
||||
(if
|
||||
(i32.eq
|
||||
(i32.rem_u
|
||||
(get_local $1)
|
||||
(i32.const 8)
|
||||
)
|
||||
(i32.rem_u
|
||||
(get_local $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(loop $continue|0
|
||||
(if
|
||||
(i32.rem_u
|
||||
(get_local $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
(block
|
||||
(if
|
||||
(i32.eqz
|
||||
(get_local $2)
|
||||
)
|
||||
(return
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(set_local $0
|
||||
(i32.add
|
||||
(tee_local $3
|
||||
(get_local $0)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(i32.store8
|
||||
(get_local $3)
|
||||
(block (result i32)
|
||||
(set_local $1
|
||||
(i32.add
|
||||
(tee_local $3
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(i32.load8_u
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue|0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|1
|
||||
(if
|
||||
(i32.ge_u
|
||||
(get_local $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
(block
|
||||
(i64.store
|
||||
(get_local $0)
|
||||
(i64.load
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(set_local $0
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(set_local $1
|
||||
(i32.add
|
||||
(get_local $1)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(br $continue|1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|2
|
||||
(if
|
||||
(get_local $2)
|
||||
(block
|
||||
(set_local $0
|
||||
(i32.add
|
||||
(tee_local $3
|
||||
(get_local $0)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(i32.store8
|
||||
(get_local $3)
|
||||
(block (result i32)
|
||||
(set_local $1
|
||||
(i32.add
|
||||
(tee_local $3
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(i32.load8_u
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(br $continue|2)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(if
|
||||
(i32.eq
|
||||
(i32.rem_u
|
||||
(get_local $1)
|
||||
(i32.const 8)
|
||||
)
|
||||
(i32.rem_u
|
||||
(get_local $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(loop $continue|3
|
||||
(if
|
||||
(i32.rem_u
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 8)
|
||||
)
|
||||
(block
|
||||
(if
|
||||
(i32.eqz
|
||||
(get_local $2)
|
||||
)
|
||||
(return
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(tee_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.load8_u
|
||||
(i32.add
|
||||
(get_local $1)
|
||||
(get_local $2)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue|3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|4
|
||||
(if
|
||||
(i32.ge_u
|
||||
(get_local $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
(block
|
||||
(i64.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(tee_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i64.load
|
||||
(i32.add
|
||||
(get_local $1)
|
||||
(get_local $2)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue|4)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|5
|
||||
(if
|
||||
(get_local $2)
|
||||
(block
|
||||
(i32.store8
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(tee_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.load8_u
|
||||
(i32.add
|
||||
(get_local $1)
|
||||
(get_local $2)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue|5)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(get_local $4)
|
||||
)
|
||||
(func $start (; 1 ;) (type $v)
|
||||
(i64.store
|
||||
(i32.const 8)
|
||||
(i64.const 1229782938247303441)
|
||||
)
|
||||
(i64.store
|
||||
(i32.const 16)
|
||||
(i64.const 2459565876494606882)
|
||||
)
|
||||
(i64.store
|
||||
(i32.const 24)
|
||||
(i64.const 3689348814741910323)
|
||||
)
|
||||
(i64.store
|
||||
(i32.const 32)
|
||||
(i64.const 4919131752989213764)
|
||||
)
|
||||
(set_global $memmove/dest
|
||||
(call $memmove/memmove
|
||||
(i32.const 9)
|
||||
(i32.const 24)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(get_global $memmove/dest)
|
||||
(i32.const 9)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i64.ne
|
||||
(i64.load
|
||||
(i32.const 8)
|
||||
)
|
||||
(i64.const 1229783084848853777)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(set_global $memmove/dest
|
||||
(call $memmove/memmove
|
||||
(i32.const 8)
|
||||
(i32.const 8)
|
||||
(i32.const 32)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(get_global $memmove/dest)
|
||||
(i32.const 8)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i64.ne
|
||||
(i64.load
|
||||
(i32.const 8)
|
||||
)
|
||||
(i64.const 1229783084848853777)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i64.ne
|
||||
(i64.load
|
||||
(i32.const 16)
|
||||
)
|
||||
(i64.const 2459565876494606882)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i64.ne
|
||||
(i64.load
|
||||
(i32.const 24)
|
||||
)
|
||||
(i64.const 3689348814741910323)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i64.ne
|
||||
(i64.load
|
||||
(i32.const 32)
|
||||
)
|
||||
(i64.const 4919131752989213764)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(set_global $memmove/dest
|
||||
(call $memmove/memmove
|
||||
(i32.const 13)
|
||||
(i32.const 36)
|
||||
(i32.const 3)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i64.ne
|
||||
(i64.load
|
||||
(i32.const 8)
|
||||
)
|
||||
(i64.const 4919131679688438545)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(set_global $memmove/dest
|
||||
(call $memmove/memmove
|
||||
(i32.const 16)
|
||||
(i32.const 24)
|
||||
(i32.const 15)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i64.ne
|
||||
(i64.load
|
||||
(i32.const 8)
|
||||
)
|
||||
(i64.const 4919131679688438545)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i64.ne
|
||||
(i64.load
|
||||
(i32.const 16)
|
||||
)
|
||||
(i64.const 3689348814741910323)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i64.ne
|
||||
(i64.load
|
||||
(i32.const 24)
|
||||
)
|
||||
(i64.const 3694152654344438852)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i64.ne
|
||||
(i64.load
|
||||
(i32.const 32)
|
||||
)
|
||||
(i64.const 4919131752989213764)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
)
|
72
tests/compiler/memmove.ts
Normal file
72
tests/compiler/memmove.ts
Normal file
@ -0,0 +1,72 @@
|
||||
function memmove(dest: usize, src: usize, n: usize): usize {
|
||||
var ret = dest;
|
||||
if (dest == src)
|
||||
return ret;
|
||||
// if (src + n <= dest || dest + n <= src) {
|
||||
// memcpy(dest, src, n);
|
||||
// return ret;
|
||||
// }
|
||||
if (dest < src) {
|
||||
if (src % 8 == dest % 8) {
|
||||
while (dest % 8) {
|
||||
if (!n)
|
||||
return ret;
|
||||
--n;
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
}
|
||||
while (n >= 8) {
|
||||
store<u64>(dest, load<u64>(src));
|
||||
n -= 8;
|
||||
dest += 8;
|
||||
src += 8;
|
||||
}
|
||||
}
|
||||
while (n) {
|
||||
store<u8>(dest++, load<u8>(src++));
|
||||
--n;
|
||||
}
|
||||
} else {
|
||||
if (src % 8 == dest % 8) {
|
||||
while ((dest + n) % 8) {
|
||||
if (!n)
|
||||
return ret;
|
||||
store<u8>(dest + --n, load<u8>(src + n));
|
||||
}
|
||||
while (n >= 8) {
|
||||
n -= 8;
|
||||
store<u64>(dest + n, load<u64>(src + n));
|
||||
}
|
||||
}
|
||||
while (n) {
|
||||
store<u8>(dest + --n, load<u8>(src + n));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
const base: usize = 8;
|
||||
store<u64>(base , 0x1111111111111111);
|
||||
store<u64>(base + 8 , 0x2222222222222222);
|
||||
store<u64>(base + 16, 0x3333333333333333);
|
||||
store<u64>(base + 24, 0x4444444444444444);
|
||||
|
||||
var dest: usize;
|
||||
dest = memmove(base + 1, base + 16, 4);
|
||||
assert(dest == base + 1);
|
||||
assert(load<u64>(base) == 0x1111113333333311);
|
||||
|
||||
dest = memmove(base, base, 32);
|
||||
assert(dest == base);
|
||||
assert(load<u64>(base) == 0x1111113333333311);
|
||||
assert(load<u64>(base + 8) == 0x2222222222222222);
|
||||
assert(load<u64>(base + 16) == 0x3333333333333333);
|
||||
assert(load<u64>(base + 24) == 0x4444444444444444);
|
||||
|
||||
dest = memmove(base + 5, base + 28, 3);
|
||||
assert(load<u64>(base) == 0x4444443333333311);
|
||||
|
||||
dest = memmove(base + 8, base + 16, 15);
|
||||
assert(load<u64>(base) == 0x4444443333333311);
|
||||
assert(load<u64>(base + 8) == 0x3333333333333333);
|
||||
assert(load<u64>(base + 16) == 0x3344444444444444);
|
||||
assert(load<u64>(base + 24) == 0x4444444444444444);
|
586
tests/compiler/memmove.wast
Normal file
586
tests/compiler/memmove.wast
Normal file
@ -0,0 +1,586 @@
|
||||
(module
|
||||
(type $iiii (func (param i32 i32 i32) (result i32)))
|
||||
(type $v (func))
|
||||
(global $memmove/base i32 (i32.const 8))
|
||||
(global $memmove/dest (mut i32) (i32.const 0))
|
||||
(global $HEAP_BASE i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $memmove/memmove (; 0 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
|
||||
(local $3 i32)
|
||||
(local $4 i32)
|
||||
(block
|
||||
(set_local $3
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eq
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.lt_u
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
(block
|
||||
(if
|
||||
(i32.eq
|
||||
(i32.rem_u
|
||||
(get_local $1)
|
||||
(i32.const 8)
|
||||
)
|
||||
(i32.rem_u
|
||||
(get_local $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(block $break|0
|
||||
(loop $continue|0
|
||||
(if
|
||||
(i32.rem_u
|
||||
(get_local $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
(block
|
||||
(block
|
||||
(if
|
||||
(i32.eqz
|
||||
(get_local $2)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(i32.store8
|
||||
(block (result i32)
|
||||
(set_local $4
|
||||
(get_local $0)
|
||||
)
|
||||
(set_local $0
|
||||
(i32.add
|
||||
(get_local $4)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(get_local $4)
|
||||
)
|
||||
(i32.load8_u
|
||||
(block (result i32)
|
||||
(set_local $4
|
||||
(get_local $1)
|
||||
)
|
||||
(set_local $1
|
||||
(i32.add
|
||||
(get_local $4)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue|0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(block $break|1
|
||||
(loop $continue|1
|
||||
(if
|
||||
(i32.ge_u
|
||||
(get_local $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
(block
|
||||
(block
|
||||
(i64.store
|
||||
(get_local $0)
|
||||
(i64.load
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(set_local $0
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(set_local $1
|
||||
(i32.add
|
||||
(get_local $1)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue|1)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(block $break|2
|
||||
(loop $continue|2
|
||||
(if
|
||||
(get_local $2)
|
||||
(block
|
||||
(block
|
||||
(i32.store8
|
||||
(block (result i32)
|
||||
(set_local $4
|
||||
(get_local $0)
|
||||
)
|
||||
(set_local $0
|
||||
(i32.add
|
||||
(get_local $4)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(get_local $4)
|
||||
)
|
||||
(i32.load8_u
|
||||
(block (result i32)
|
||||
(set_local $4
|
||||
(get_local $1)
|
||||
)
|
||||
(set_local $1
|
||||
(i32.add
|
||||
(get_local $4)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue|2)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(if
|
||||
(i32.eq
|
||||
(i32.rem_u
|
||||
(get_local $1)
|
||||
(i32.const 8)
|
||||
)
|
||||
(i32.rem_u
|
||||
(get_local $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(block $break|3
|
||||
(loop $continue|3
|
||||
(if
|
||||
(i32.rem_u
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 8)
|
||||
)
|
||||
(block
|
||||
(block
|
||||
(if
|
||||
(i32.eqz
|
||||
(get_local $2)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(tee_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.load8_u
|
||||
(i32.add
|
||||
(get_local $1)
|
||||
(get_local $2)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue|3)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(block $break|4
|
||||
(loop $continue|4
|
||||
(if
|
||||
(i32.ge_u
|
||||
(get_local $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
(block
|
||||
(block
|
||||
(set_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(i64.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i64.load
|
||||
(i32.add
|
||||
(get_local $1)
|
||||
(get_local $2)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue|4)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(block $break|5
|
||||
(loop $continue|5
|
||||
(if
|
||||
(get_local $2)
|
||||
(block
|
||||
(i32.store8
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(tee_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.load8_u
|
||||
(i32.add
|
||||
(get_local $1)
|
||||
(get_local $2)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue|5)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(func $start (; 1 ;) (type $v)
|
||||
(i64.store
|
||||
(i32.const 8)
|
||||
(i64.const 1229782938247303441)
|
||||
)
|
||||
(i64.store
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 8)
|
||||
)
|
||||
(i64.const 2459565876494606882)
|
||||
)
|
||||
(i64.store
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 16)
|
||||
)
|
||||
(i64.const 3689348814741910323)
|
||||
)
|
||||
(i64.store
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 24)
|
||||
)
|
||||
(i64.const 4919131752989213764)
|
||||
)
|
||||
(set_global $memmove/dest
|
||||
(call $memmove/memmove
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 1)
|
||||
)
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 16)
|
||||
)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(get_global $memmove/dest)
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i64.eq
|
||||
(i64.load
|
||||
(i32.const 8)
|
||||
)
|
||||
(i64.const 1229783084848853777)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(set_global $memmove/dest
|
||||
(call $memmove/memmove
|
||||
(i32.const 8)
|
||||
(i32.const 8)
|
||||
(i32.const 32)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(get_global $memmove/dest)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i64.eq
|
||||
(i64.load
|
||||
(i32.const 8)
|
||||
)
|
||||
(i64.const 1229783084848853777)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i64.eq
|
||||
(i64.load
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(i64.const 2459565876494606882)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i64.eq
|
||||
(i64.load
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 16)
|
||||
)
|
||||
)
|
||||
(i64.const 3689348814741910323)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i64.eq
|
||||
(i64.load
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 24)
|
||||
)
|
||||
)
|
||||
(i64.const 4919131752989213764)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(set_global $memmove/dest
|
||||
(call $memmove/memmove
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 5)
|
||||
)
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 28)
|
||||
)
|
||||
(i32.const 3)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i64.eq
|
||||
(i64.load
|
||||
(i32.const 8)
|
||||
)
|
||||
(i64.const 4919131679688438545)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(set_global $memmove/dest
|
||||
(call $memmove/memmove
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 8)
|
||||
)
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 16)
|
||||
)
|
||||
(i32.const 15)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i64.eq
|
||||
(i64.load
|
||||
(i32.const 8)
|
||||
)
|
||||
(i64.const 4919131679688438545)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i64.eq
|
||||
(i64.load
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 8)
|
||||
)
|
||||
)
|
||||
(i64.const 3689348814741910323)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i64.eq
|
||||
(i64.load
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 16)
|
||||
)
|
||||
)
|
||||
(i64.const 3694152654344438852)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i64.eq
|
||||
(i64.load
|
||||
(i32.add
|
||||
(i32.const 8)
|
||||
(i32.const 24)
|
||||
)
|
||||
)
|
||||
(i64.const 4919131752989213764)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
)
|
||||
(;
|
||||
[program.elements]
|
||||
GLOBAL: NaN
|
||||
GLOBAL: Infinity
|
||||
FUNCTION_PROTOTYPE: isNaN
|
||||
FUNCTION_PROTOTYPE: isFinite
|
||||
FUNCTION_PROTOTYPE: clz
|
||||
FUNCTION_PROTOTYPE: ctz
|
||||
FUNCTION_PROTOTYPE: popcnt
|
||||
FUNCTION_PROTOTYPE: rotl
|
||||
FUNCTION_PROTOTYPE: rotr
|
||||
FUNCTION_PROTOTYPE: abs
|
||||
FUNCTION_PROTOTYPE: max
|
||||
FUNCTION_PROTOTYPE: min
|
||||
FUNCTION_PROTOTYPE: ceil
|
||||
FUNCTION_PROTOTYPE: floor
|
||||
FUNCTION_PROTOTYPE: copysign
|
||||
FUNCTION_PROTOTYPE: nearest
|
||||
FUNCTION_PROTOTYPE: reinterpret
|
||||
FUNCTION_PROTOTYPE: sqrt
|
||||
FUNCTION_PROTOTYPE: trunc
|
||||
FUNCTION_PROTOTYPE: load
|
||||
FUNCTION_PROTOTYPE: store
|
||||
FUNCTION_PROTOTYPE: sizeof
|
||||
FUNCTION_PROTOTYPE: select
|
||||
FUNCTION_PROTOTYPE: unreachable
|
||||
FUNCTION_PROTOTYPE: current_memory
|
||||
FUNCTION_PROTOTYPE: grow_memory
|
||||
FUNCTION_PROTOTYPE: changetype
|
||||
FUNCTION_PROTOTYPE: assert
|
||||
FUNCTION_PROTOTYPE: i8
|
||||
FUNCTION_PROTOTYPE: i16
|
||||
FUNCTION_PROTOTYPE: i32
|
||||
FUNCTION_PROTOTYPE: i64
|
||||
FUNCTION_PROTOTYPE: u8
|
||||
FUNCTION_PROTOTYPE: u16
|
||||
FUNCTION_PROTOTYPE: u32
|
||||
FUNCTION_PROTOTYPE: u64
|
||||
FUNCTION_PROTOTYPE: bool
|
||||
FUNCTION_PROTOTYPE: f32
|
||||
FUNCTION_PROTOTYPE: f64
|
||||
FUNCTION_PROTOTYPE: isize
|
||||
FUNCTION_PROTOTYPE: usize
|
||||
GLOBAL: HEAP_BASE
|
||||
FUNCTION_PROTOTYPE: memmove/memmove
|
||||
GLOBAL: memmove/base
|
||||
GLOBAL: memmove/dest
|
||||
[program.exports]
|
||||
|
||||
;)
|
447
tests/compiler/memset.optimized.wast
Normal file
447
tests/compiler/memset.optimized.wast
Normal file
@ -0,0 +1,447 @@
|
||||
(module
|
||||
(type $iiii (func (param i32 i32 i32) (result i32)))
|
||||
(type $v (func))
|
||||
(global $memset/dest (mut i32) (i32.const 0))
|
||||
(global $HEAP_BASE i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $memset/memset (; 0 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
|
||||
(local $3 i32)
|
||||
(local $4 i64)
|
||||
(local $5 i32)
|
||||
(set_local $3
|
||||
(get_local $0)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(get_local $2)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(i32.store8
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(if
|
||||
(i32.le_u
|
||||
(get_local $2)
|
||||
(i32.const 2)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 1)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 2)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 2)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 3)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(if
|
||||
(i32.le_u
|
||||
(get_local $2)
|
||||
(i32.const 6)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 3)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 4)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(if
|
||||
(i32.le_u
|
||||
(get_local $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(i32.store
|
||||
(tee_local $0
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(tee_local $5
|
||||
(i32.and
|
||||
(i32.sub
|
||||
(i32.const 0)
|
||||
(get_local $0)
|
||||
)
|
||||
(i32.const 3)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(tee_local $1
|
||||
(i32.mul
|
||||
(get_local $1)
|
||||
(i32.const 16843009)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(tee_local $2
|
||||
(i32.and
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.const -4)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.const 4)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(if
|
||||
(i32.le_u
|
||||
(get_local $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 4)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 12)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 8)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(if
|
||||
(i32.le_u
|
||||
(get_local $2)
|
||||
(i32.const 24)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 12)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 16)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 20)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 24)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 28)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 24)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 20)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 16)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(set_local $0
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(tee_local $5
|
||||
(i32.add
|
||||
(i32.and
|
||||
(get_local $0)
|
||||
(i32.const 4)
|
||||
)
|
||||
(i32.const 24)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(get_local $5)
|
||||
)
|
||||
)
|
||||
(set_local $4
|
||||
(i64.or
|
||||
(i64.extend_u/i32
|
||||
(get_local $1)
|
||||
)
|
||||
(i64.shl
|
||||
(i64.extend_u/i32
|
||||
(get_local $1)
|
||||
)
|
||||
(i64.const 32)
|
||||
)
|
||||
)
|
||||
)
|
||||
(loop $continue|0
|
||||
(if
|
||||
(i32.ge_u
|
||||
(get_local $2)
|
||||
(i32.const 32)
|
||||
)
|
||||
(block
|
||||
(i64.store
|
||||
(get_local $0)
|
||||
(get_local $4)
|
||||
)
|
||||
(i64.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
(get_local $4)
|
||||
)
|
||||
(i64.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 16)
|
||||
)
|
||||
(get_local $4)
|
||||
)
|
||||
(i64.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 24)
|
||||
)
|
||||
(get_local $4)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 32)
|
||||
)
|
||||
)
|
||||
(set_local $0
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 32)
|
||||
)
|
||||
)
|
||||
(br $continue|0)
|
||||
)
|
||||
)
|
||||
)
|
||||
(get_local $3)
|
||||
)
|
||||
(func $start (; 1 ;) (type $v)
|
||||
(set_global $memset/dest
|
||||
(get_global $HEAP_BASE)
|
||||
)
|
||||
(drop
|
||||
(call $memset/memset
|
||||
(get_global $memset/dest)
|
||||
(i32.const 1)
|
||||
(i32.const 16)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(i32.load8_u
|
||||
(get_global $memset/dest)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(i32.load8_u
|
||||
(i32.add
|
||||
(get_global $memset/dest)
|
||||
(i32.const 15)
|
||||
)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(drop
|
||||
(call $memset/memset
|
||||
(i32.add
|
||||
(get_global $memset/dest)
|
||||
(i32.const 1)
|
||||
)
|
||||
(i32.const 2)
|
||||
(i32.const 14)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(i32.load8_u
|
||||
(get_global $memset/dest)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(i32.load8_u
|
||||
(i32.add
|
||||
(get_global $memset/dest)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(i32.const 2)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(i32.load8_u
|
||||
(i32.add
|
||||
(get_global $memset/dest)
|
||||
(i32.const 14)
|
||||
)
|
||||
)
|
||||
(i32.const 2)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.ne
|
||||
(i32.load8_u
|
||||
(i32.add
|
||||
(get_global $memset/dest)
|
||||
(i32.const 15)
|
||||
)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
)
|
80
tests/compiler/memset.ts
Normal file
80
tests/compiler/memset.ts
Normal file
@ -0,0 +1,80 @@
|
||||
function memset(dest: usize, c: u8, n: usize): usize {
|
||||
var ret = dest;
|
||||
|
||||
// fill head and tail wwith minimal branching
|
||||
if (!n)
|
||||
return ret;
|
||||
store<u8>(dest, c);
|
||||
store<u8>(dest + n - 1, c);
|
||||
if (n <= 2)
|
||||
return ret;
|
||||
|
||||
store<u8>(dest + 1, c);
|
||||
store<u8>(dest + 2, c);
|
||||
store<u8>(dest + n - 2, c);
|
||||
store<u8>(dest + n - 3, c);
|
||||
if (n <= 6)
|
||||
return ret;
|
||||
store<u8>(dest + 3, c);
|
||||
store<u8>(dest + n - 4, c);
|
||||
if (n <= 8)
|
||||
return ret;
|
||||
|
||||
// advance pointer to align it at 4-byte boundary
|
||||
var k: usize = -dest & 3;
|
||||
dest += k;
|
||||
n -= k;
|
||||
n &= -4;
|
||||
|
||||
var c32: u32 = -1 / 255 * c;
|
||||
|
||||
// fill head/tail up to 28 bytes each in preparation
|
||||
store<u32>(dest, c32);
|
||||
store<u32>(dest + n - 4, c32);
|
||||
if (n <= 8)
|
||||
return ret;
|
||||
store<u32>(dest + 4, c32);
|
||||
store<u32>(dest + 8, c32);
|
||||
store<u32>(dest + n - 12, c32);
|
||||
store<u32>(dest + n - 8, c32);
|
||||
if (n <= 24)
|
||||
return ret;
|
||||
store<u32>(dest + 12, c32);
|
||||
store<u32>(dest + 16, c32);
|
||||
store<u32>(dest + 20, c32);
|
||||
store<u32>(dest + 24, c32);
|
||||
store<u32>(dest + n - 28, c32);
|
||||
store<u32>(dest + n - 24, c32);
|
||||
store<u32>(dest + n - 20, c32);
|
||||
store<u32>(dest + n - 16, c32);
|
||||
|
||||
// align to a multiple of 8
|
||||
k = 24 + (dest & 4);
|
||||
dest += k;
|
||||
n -= k;
|
||||
|
||||
// copy 32 bytes each
|
||||
var c64: u64 = <u64>c32 | (<u64>c32 << 32);
|
||||
while (n >= 32) {
|
||||
store<u64>(dest, c64);
|
||||
store<u64>(dest + 8, c64);
|
||||
store<u64>(dest + 16, c64);
|
||||
store<u64>(dest + 24, c64);
|
||||
n -= 32;
|
||||
dest += 32;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
var dest = HEAP_BASE;
|
||||
memset(dest, 1, 16);
|
||||
|
||||
assert(load<u8>(dest) == 1);
|
||||
assert(load<u8>(dest + 15) == 1);
|
||||
|
||||
memset(dest + 1, 2, 14);
|
||||
|
||||
assert(load<u8>(dest) == 1);
|
||||
assert(load<u8>(dest + 1) == 2);
|
||||
assert(load<u8>(dest + 14) == 2);
|
||||
assert(load<u8>(dest + 15) == 1);
|
540
tests/compiler/memset.wast
Normal file
540
tests/compiler/memset.wast
Normal file
@ -0,0 +1,540 @@
|
||||
(module
|
||||
(type $iiii (func (param i32 i32 i32) (result i32)))
|
||||
(type $v (func))
|
||||
(global $memset/dest (mut i32) (i32.const 0))
|
||||
(global $HEAP_BASE i32 (i32.const 4))
|
||||
(memory $0 1)
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $memset/memset (; 0 ;) (type $iiii) (param $0 i32) (param $1 i32) (param $2 i32) (result i32)
|
||||
(local $3 i32)
|
||||
(local $4 i32)
|
||||
(local $5 i32)
|
||||
(local $6 i64)
|
||||
(block
|
||||
(set_local $3
|
||||
(get_local $0)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(get_local $2)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(i32.store8
|
||||
(get_local $0)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(if
|
||||
(i32.le_u
|
||||
(get_local $2)
|
||||
(i32.const 2)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 1)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 2)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 2)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 3)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(if
|
||||
(i32.le_u
|
||||
(get_local $2)
|
||||
(i32.const 6)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 3)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(i32.store8
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 4)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
(if
|
||||
(i32.le_u
|
||||
(get_local $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $4
|
||||
(i32.and
|
||||
(i32.sub
|
||||
(i32.const 0)
|
||||
(get_local $0)
|
||||
)
|
||||
(i32.const 3)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $0
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.and
|
||||
(get_local $2)
|
||||
(i32.sub
|
||||
(i32.const 0)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $5
|
||||
(i32.mul
|
||||
(i32.div_u
|
||||
(i32.sub
|
||||
(i32.const 0)
|
||||
(i32.const 1)
|
||||
)
|
||||
(i32.const 255)
|
||||
)
|
||||
(get_local $1)
|
||||
)
|
||||
)
|
||||
)
|
||||
(i32.store
|
||||
(get_local $0)
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 4)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(if
|
||||
(i32.le_u
|
||||
(get_local $2)
|
||||
(i32.const 8)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 4)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 12)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 8)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(if
|
||||
(i32.le_u
|
||||
(get_local $2)
|
||||
(i32.const 24)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 12)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 16)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 20)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 24)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 28)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 24)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 20)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(i32.store
|
||||
(i32.sub
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $2)
|
||||
)
|
||||
(i32.const 16)
|
||||
)
|
||||
(get_local $5)
|
||||
)
|
||||
(set_local $4
|
||||
(i32.add
|
||||
(i32.const 24)
|
||||
(i32.and
|
||||
(get_local $0)
|
||||
(i32.const 4)
|
||||
)
|
||||
)
|
||||
)
|
||||
(set_local $0
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(get_local $4)
|
||||
)
|
||||
)
|
||||
(block
|
||||
(set_local $6
|
||||
(i64.or
|
||||
(i64.extend_u/i32
|
||||
(get_local $5)
|
||||
)
|
||||
(i64.shl
|
||||
(i64.extend_u/i32
|
||||
(get_local $5)
|
||||
)
|
||||
(i64.const 32)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(block $break|0
|
||||
(loop $continue|0
|
||||
(if
|
||||
(i32.ge_u
|
||||
(get_local $2)
|
||||
(i32.const 32)
|
||||
)
|
||||
(block
|
||||
(block
|
||||
(i64.store
|
||||
(get_local $0)
|
||||
(get_local $6)
|
||||
)
|
||||
(i64.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 8)
|
||||
)
|
||||
(get_local $6)
|
||||
)
|
||||
(i64.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 16)
|
||||
)
|
||||
(get_local $6)
|
||||
)
|
||||
(i64.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 24)
|
||||
)
|
||||
(get_local $6)
|
||||
)
|
||||
(set_local $2
|
||||
(i32.sub
|
||||
(get_local $2)
|
||||
(i32.const 32)
|
||||
)
|
||||
)
|
||||
(set_local $0
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
(i32.const 32)
|
||||
)
|
||||
)
|
||||
)
|
||||
(br $continue|0)
|
||||
)
|
||||
)
|
||||
)
|
||||
)
|
||||
(return
|
||||
(get_local $3)
|
||||
)
|
||||
)
|
||||
(func $start (; 1 ;) (type $v)
|
||||
(set_global $memset/dest
|
||||
(get_global $HEAP_BASE)
|
||||
)
|
||||
(drop
|
||||
(call $memset/memset
|
||||
(get_global $memset/dest)
|
||||
(i32.const 1)
|
||||
(i32.const 16)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(i32.load8_u
|
||||
(get_global $memset/dest)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(i32.load8_u
|
||||
(i32.add
|
||||
(get_global $memset/dest)
|
||||
(i32.const 15)
|
||||
)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(drop
|
||||
(call $memset/memset
|
||||
(i32.add
|
||||
(get_global $memset/dest)
|
||||
(i32.const 1)
|
||||
)
|
||||
(i32.const 2)
|
||||
(i32.const 14)
|
||||
)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(i32.load8_u
|
||||
(get_global $memset/dest)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(i32.load8_u
|
||||
(i32.add
|
||||
(get_global $memset/dest)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(i32.const 2)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(i32.load8_u
|
||||
(i32.add
|
||||
(get_global $memset/dest)
|
||||
(i32.const 14)
|
||||
)
|
||||
)
|
||||
(i32.const 2)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(if
|
||||
(i32.eqz
|
||||
(i32.eq
|
||||
(i32.load8_u
|
||||
(i32.add
|
||||
(get_global $memset/dest)
|
||||
(i32.const 15)
|
||||
)
|
||||
)
|
||||
(i32.const 1)
|
||||
)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
)
|
||||
)
|
||||
(;
|
||||
[program.elements]
|
||||
GLOBAL: NaN
|
||||
GLOBAL: Infinity
|
||||
FUNCTION_PROTOTYPE: isNaN
|
||||
FUNCTION_PROTOTYPE: isFinite
|
||||
FUNCTION_PROTOTYPE: clz
|
||||
FUNCTION_PROTOTYPE: ctz
|
||||
FUNCTION_PROTOTYPE: popcnt
|
||||
FUNCTION_PROTOTYPE: rotl
|
||||
FUNCTION_PROTOTYPE: rotr
|
||||
FUNCTION_PROTOTYPE: abs
|
||||
FUNCTION_PROTOTYPE: max
|
||||
FUNCTION_PROTOTYPE: min
|
||||
FUNCTION_PROTOTYPE: ceil
|
||||
FUNCTION_PROTOTYPE: floor
|
||||
FUNCTION_PROTOTYPE: copysign
|
||||
FUNCTION_PROTOTYPE: nearest
|
||||
FUNCTION_PROTOTYPE: reinterpret
|
||||
FUNCTION_PROTOTYPE: sqrt
|
||||
FUNCTION_PROTOTYPE: trunc
|
||||
FUNCTION_PROTOTYPE: load
|
||||
FUNCTION_PROTOTYPE: store
|
||||
FUNCTION_PROTOTYPE: sizeof
|
||||
FUNCTION_PROTOTYPE: select
|
||||
FUNCTION_PROTOTYPE: unreachable
|
||||
FUNCTION_PROTOTYPE: current_memory
|
||||
FUNCTION_PROTOTYPE: grow_memory
|
||||
FUNCTION_PROTOTYPE: changetype
|
||||
FUNCTION_PROTOTYPE: assert
|
||||
FUNCTION_PROTOTYPE: i8
|
||||
FUNCTION_PROTOTYPE: i16
|
||||
FUNCTION_PROTOTYPE: i32
|
||||
FUNCTION_PROTOTYPE: i64
|
||||
FUNCTION_PROTOTYPE: u8
|
||||
FUNCTION_PROTOTYPE: u16
|
||||
FUNCTION_PROTOTYPE: u32
|
||||
FUNCTION_PROTOTYPE: u64
|
||||
FUNCTION_PROTOTYPE: bool
|
||||
FUNCTION_PROTOTYPE: f32
|
||||
FUNCTION_PROTOTYPE: f64
|
||||
FUNCTION_PROTOTYPE: isize
|
||||
FUNCTION_PROTOTYPE: usize
|
||||
GLOBAL: HEAP_BASE
|
||||
FUNCTION_PROTOTYPE: memset/memset
|
||||
GLOBAL: memset/dest
|
||||
[program.exports]
|
||||
|
||||
;)
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,4 +1,4 @@
|
||||
var arr = changetype<i32[]>(Heap.allocate(sizeof<usize>() + 2 * sizeof<i32>()));
|
||||
var arr = changetype<i32[]>(allocate_memory(sizeof<usize>() + 2 * sizeof<i32>()));
|
||||
|
||||
assert(arr.length == 0);
|
||||
assert(arr.__capacity == 0);
|
||||
@ -36,7 +36,7 @@ assert(arr[0] == 43);
|
||||
assert(arr[1] == 44);
|
||||
assert(arr[2] == 45);
|
||||
|
||||
arr.unshift(42); // see FIXME in std:array
|
||||
arr.unshift(42);
|
||||
|
||||
assert(arr.length == 4);
|
||||
assert(arr.__capacity == 4);
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -8,6 +8,13 @@
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $std:array/CArray#__get (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
(if
|
||||
(i32.lt_s
|
||||
(get_local $1)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(i32.load
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
@ -19,6 +26,13 @@
|
||||
)
|
||||
)
|
||||
(func $std:array/CArray#__set (; 1 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
|
||||
(if
|
||||
(i32.lt_s
|
||||
(get_local $1)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
|
@ -8,6 +8,13 @@
|
||||
(export "memory" (memory $0))
|
||||
(start $start)
|
||||
(func $std:array/CArray#__get (; 0 ;) (type $iii) (param $0 i32) (param $1 i32) (result i32)
|
||||
(if
|
||||
(i32.lt_s
|
||||
(get_local $1)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(return
|
||||
(i32.load
|
||||
(i32.add
|
||||
@ -21,6 +28,13 @@
|
||||
)
|
||||
)
|
||||
(func $std:array/CArray#__set (; 1 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
|
||||
(if
|
||||
(i32.lt_s
|
||||
(get_local $1)
|
||||
(i32.const 0)
|
||||
)
|
||||
(unreachable)
|
||||
)
|
||||
(i32.store
|
||||
(i32.add
|
||||
(get_local $0)
|
||||
@ -247,16 +261,17 @@
|
||||
GLOBAL: std:heap/ALIGN_SIZE
|
||||
GLOBAL: std:heap/ALIGN_MASK
|
||||
GLOBAL: std:heap/HEAP_OFFSET
|
||||
CLASS_PROTOTYPE: std:heap/Heap
|
||||
CLASS_PROTOTYPE: Heap
|
||||
PROPERTY: std:heap/Heap.used
|
||||
PROPERTY: std:heap/Heap.free
|
||||
PROPERTY: std:heap/Heap.size
|
||||
FUNCTION_PROTOTYPE: std:heap/Heap.allocate
|
||||
FUNCTION_PROTOTYPE: std:heap/Heap.dispose
|
||||
FUNCTION_PROTOTYPE: std:heap/Heap.copy
|
||||
FUNCTION_PROTOTYPE: std:heap/Heap.fill
|
||||
FUNCTION_PROTOTYPE: std:heap/Heap.compare
|
||||
FUNCTION_PROTOTYPE: std:heap/allocate_memory
|
||||
FUNCTION_PROTOTYPE: allocate_memory
|
||||
FUNCTION_PROTOTYPE: std:heap/free_memory
|
||||
FUNCTION_PROTOTYPE: free_memory
|
||||
FUNCTION_PROTOTYPE: std:heap/copy_memory
|
||||
FUNCTION_PROTOTYPE: std:heap/move_memory
|
||||
FUNCTION_PROTOTYPE: move_memory
|
||||
FUNCTION_PROTOTYPE: std:heap/set_memory
|
||||
FUNCTION_PROTOTYPE: set_memory
|
||||
FUNCTION_PROTOTYPE: std:heap/compare_memory
|
||||
FUNCTION_PROTOTYPE: compare_memory
|
||||
CLASS_PROTOTYPE: std:map/Map
|
||||
CLASS_PROTOTYPE: Map
|
||||
CLASS_PROTOTYPE: std:regexp/RegExp
|
||||
@ -277,7 +292,11 @@
|
||||
CLASS_PROTOTYPE: std:array/CArray
|
||||
CLASS_PROTOTYPE: std:error/Error
|
||||
CLASS_PROTOTYPE: std:error/RangeError
|
||||
CLASS_PROTOTYPE: std:heap/Heap
|
||||
FUNCTION_PROTOTYPE: std:heap/allocate_memory
|
||||
FUNCTION_PROTOTYPE: std:heap/free_memory
|
||||
FUNCTION_PROTOTYPE: std:heap/move_memory
|
||||
FUNCTION_PROTOTYPE: std:heap/set_memory
|
||||
FUNCTION_PROTOTYPE: std:heap/compare_memory
|
||||
CLASS_PROTOTYPE: std:map/Map
|
||||
CLASS_PROTOTYPE: std:regexp/RegExp
|
||||
CLASS_PROTOTYPE: std:set/Set
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,21 +1,21 @@
|
||||
const size: usize = 42;
|
||||
let ptr1: usize = Heap.allocate(size);
|
||||
let ptr2: usize = Heap.allocate(size);
|
||||
let ptr1: usize = allocate_memory(size);
|
||||
let ptr2: usize = allocate_memory(size);
|
||||
|
||||
assert(ptr1 != ptr2);
|
||||
|
||||
Heap.fill(ptr1, 0x12, size);
|
||||
set_memory(ptr1, 0x12, size);
|
||||
|
||||
let i: usize;
|
||||
for (i = 0; i < size; ++i)
|
||||
assert(load<u8>(ptr1 + i) == 0x12);
|
||||
|
||||
Heap.copy(ptr2, ptr1, size);
|
||||
move_memory(ptr2, ptr1, size);
|
||||
|
||||
for (i = 0; i < size; ++i)
|
||||
assert(load<u8>(ptr2 + i) == 0x12);
|
||||
|
||||
assert(Heap.compare(ptr1, ptr2, size) == 0);
|
||||
assert(compare_memory(ptr1, ptr2, size) == 0);
|
||||
|
||||
Heap.dispose(ptr1);
|
||||
Heap.dispose(ptr2);
|
||||
free_memory(ptr1);
|
||||
free_memory(ptr2);
|
||||
|
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user