Conway's Game of life compiler test incl. html

This commit is contained in:
dcodeIO 2017-12-07 02:02:22 +01:00
parent d9ad42ed2e
commit 325ecf5165
11 changed files with 885 additions and 113 deletions

View File

@ -1745,10 +1745,8 @@ export class Compiler extends DiagnosticEmitter {
return this.module.createF32((<f32>intValue.lo) + (<f32>intValue.hi) * 0xffffffff);
if (contextualType.isLongInteger)
return this.module.createI64(intValue.lo, intValue.hi);
if (!intValue.fitsInI32) {
this.currentType = Type.i64;
return this.module.createI64(intValue.lo, intValue.hi);
}
if (contextualType.isSmallInteger)
return this.module.createI32(intValue.toI32());
this.currentType = Type.i32;
return this.module.createI32(intValue.toI32());
}

View File

@ -379,7 +379,7 @@ export class Parser extends DiagnosticEmitter {
if (tn.skip(Token.EQUALS)) {
if (isDeclare)
this.error(DiagnosticCode.Initializers_are_not_allowed_in_ambient_contexts, tn.range()); // recoverable
initializer = this.parseExpression(tn);
initializer = this.parseExpression(tn, Precedence.COMMA + 1);
if (!initializer)
return null;
}

View File

@ -1110,7 +1110,7 @@ function isOctalDigit(c: i32): bool {
function isIdentifierStart(c: i32): bool {
return c >= CharCode.A && c <= CharCode.Z
|| c >= CharCode.a && c <= CharCode.z
// || c == CharCode.DOLLAR // reserved for internal in case we have to change the naming scheme
|| c == CharCode.DOLLAR
|| c == CharCode._
|| c > 0x7f && isUnicodeIdentifierStart(c);
}
@ -1123,7 +1123,7 @@ function isIdentifierPart(c: i32): bool {
return c >= CharCode.A && c <= CharCode.Z
|| c >= CharCode.a && c <= CharCode.z
|| c >= CharCode._0 && c <= CharCode._9
// || c == CharCode.DOLLAR // reserved for internal use, see above
|| c == CharCode.DOLLAR
|| c == CharCode._
|| c > 0x7f && isUnicodeIdentifierPart(c);
}

View File

@ -0,0 +1,37 @@
<canvas id="canvas" width="640" height="480"></canvas>
<script src="../../node_modules/binaryen/index.js"></script>
<script>
fetch("game-of-life.optimized.wast").then(response =>
response.text()
).then(text => {
let buffer = Binaryen.parseText(text).emitBinary();
return WebAssembly.instantiate(buffer, {});
}).then(result => {
let cnv = document.getElementById("canvas");
let ctx = cnv.getContext("2d");
let w = cnv.width, h = cnv.height, s = w * h, S = s + s;
if (result.instance.exports.memory.buffer.byteLength < S)
result.instance.exports.memory.grow(Math.ceil(S / 65536) - 1);
let mem = new Uint8Array(result.instance.exports.memory.buffer);
for (let y = 0; y < h; ++y)
for (let x = 0; x < w; ++x)
mem[y * w + x] = Math.random() > 0.1 ? 0 : 1;
result.instance.exports.init(w, h);
setInterval(function() {
result.instance.exports.step();
mem.set(mem.subarray(s, S), 0);
}, 33);
function render() {
requestAnimationFrame(render);
ctx.clearRect(0, 0, w, h);
ctx.fillStyle = "#333";
for (let y = 0; y < h; ++y)
for (let x = 0; x < w; ++x)
if (mem[s + y * w + x])
ctx.fillRect(x, y, 1, 1);
}
render();
}).catch(err => {
throw err;
});
</script>

View File

@ -0,0 +1,278 @@
(module
(type $iiv (func (param i32 i32)))
(type $v (func))
(global $game-of-life/w (mut i32) (i32.const 0))
(global $game-of-life/h (mut i32) (i32.const 0))
(global $game-of-life/s (mut i32) (i32.const 0))
(memory $0 1)
(data (i32.const 4) "\08")
(export "init" (func $game-of-life/init))
(export "step" (func $game-of-life/step))
(export "memory" (memory $0))
(func $game-of-life/init (; 0 ;) (type $iiv) (param $0 i32) (param $1 i32)
(set_global $game-of-life/w
(get_local $0)
)
(set_global $game-of-life/h
(get_local $1)
)
(set_global $game-of-life/s
(i32.mul
(get_global $game-of-life/w)
(get_global $game-of-life/h)
)
)
)
(func $game-of-life/step (; 1 ;) (type $v)
(local $0 i32)
(local $1 i32)
(local $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
(local $6 i32)
(local $7 i32)
(set_local $6
(i32.sub
(get_global $game-of-life/h)
(i32.const 1)
)
)
(set_local $7
(i32.sub
(get_global $game-of-life/w)
(i32.const 1)
)
)
(set_local $0
(i32.const 0)
)
(loop $continue|1.1
(if
(i32.lt_s
(get_local $0)
(get_global $game-of-life/h)
)
(block
(set_local $4
(select
(i32.sub
(get_local $0)
(i32.const 1)
)
(get_local $6)
(get_local $0)
)
)
(set_local $5
(select
(i32.const 0)
(i32.add
(get_local $0)
(i32.const 1)
)
(i32.eq
(get_local $0)
(get_local $6)
)
)
)
(set_local $1
(i32.const 0)
)
(loop $continue|1.2
(if
(i32.lt_s
(get_local $1)
(get_global $game-of-life/w)
)
(block
(set_local $2
(i32.add
(i32.add
(i32.add
(i32.add
(i32.add
(i32.add
(i32.add
(i32.load8_u
(i32.add
(i32.mul
(get_local $4)
(get_global $game-of-life/w)
)
(tee_local $2
(select
(i32.sub
(get_local $1)
(i32.const 1)
)
(get_local $7)
(get_local $1)
)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $4)
(get_global $game-of-life/w)
)
(get_local $1)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $4)
(get_global $game-of-life/w)
)
(tee_local $3
(select
(i32.const 0)
(i32.add
(get_local $1)
(i32.const 1)
)
(i32.eq
(get_local $1)
(get_local $7)
)
)
)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $0)
(get_global $game-of-life/w)
)
(get_local $2)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $0)
(get_global $game-of-life/w)
)
(get_local $3)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $5)
(get_global $game-of-life/w)
)
(get_local $2)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $5)
(get_global $game-of-life/w)
)
(get_local $1)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $5)
(get_global $game-of-life/w)
)
(get_local $3)
)
)
)
)
(if
(i32.load8_u
(i32.add
(i32.mul
(get_local $0)
(get_global $game-of-life/w)
)
(get_local $1)
)
)
(if
(if (result i32)
(tee_local $3
(i32.lt_s
(get_local $2)
(i32.const 2)
)
)
(get_local $3)
(i32.gt_s
(get_local $2)
(i32.const 3)
)
)
(i32.store8
(i32.add
(i32.add
(get_global $game-of-life/s)
(i32.mul
(get_local $0)
(get_global $game-of-life/w)
)
)
(get_local $1)
)
(i32.const 0)
)
)
(if
(i32.eq
(get_local $2)
(i32.const 3)
)
(i32.store8
(i32.add
(i32.add
(get_global $game-of-life/s)
(i32.mul
(get_local $0)
(get_global $game-of-life/w)
)
)
(get_local $1)
)
(i32.const 1)
)
)
)
(set_local $1
(i32.add
(get_local $1)
(i32.const 1)
)
)
(br $continue|1.2)
)
)
)
(set_local $0
(i32.add
(get_local $0)
(i32.const 1)
)
)
(br $continue|1.1)
)
)
)
)
)

View File

@ -0,0 +1,40 @@
// A simplified version of the game of life as seen on http://dcode.io
let w: u32; // width
let h: u32; // height
let s: u32; // total size
/** Initializes width and height. */
export function init(w_: u32, h_: u32): void {
w = w_;
h = h_;
s = w * h;
}
/** Performs one step. */
export function step(): void {
let y: u32, ym1: u32, yp1: u32; // y, y-1 and y+1
let x: u32, xm1: u32, xp1: u32; // x, x-1 and x+1
let hm1: u32 = h - 1, wm1: u32 = w - 1;
let n: u32, v: u8, c: u32 = 0;
for (y = 0; y < h; ++y) {
ym1 = select<u32>(hm1, y - 1, y == 0);
yp1 = select<u32>(0, y + 1, y == hm1);
for (x = 0; x < w; ++x) {
xm1 = select<u32>(wm1, x - 1, x == 0);
xp1 = select<u32>(0, x + 1, x == wm1);
n = load<u8>(ym1 * w + xm1) + load<u8>(ym1 * w + x) + load<u8>(ym1 * w + xp1)
+ load<u8>(y * w + xm1) + load<u8>(y * w + xp1)
+ load<u8>(yp1 * w + xm1) + load<u8>(yp1 * w + x) + load<u8>(yp1 * w + xp1);
v = load<u8>(y * w + x);
if (v) {
if (n < 2 || n > 3)
store<u8>(s + y * w + x, 0);
} else if (n == 3)
store<u8>(s + y * w + x, 1);
}
}
}
// Performing a step uses bytes [0, s-1] as the input and writes the output to [s, 2*s-1].
// Note that the code above wastes a lot of space by using one byte per cell.

View File

@ -0,0 +1,346 @@
(module
(type $iiv (func (param i32 i32)))
(type $v (func))
(global $game-of-life/w (mut i32) (i32.const 0))
(global $game-of-life/h (mut i32) (i32.const 0))
(global $game-of-life/s (mut i32) (i32.const 0))
(memory $0 1)
(data (i32.const 4) "\08\00\00\00")
(export "init" (func $game-of-life/init))
(export "step" (func $game-of-life/step))
(export "memory" (memory $0))
(func $game-of-life/init (; 0 ;) (type $iiv) (param $0 i32) (param $1 i32)
(set_global $game-of-life/w
(get_local $0)
)
(set_global $game-of-life/h
(get_local $1)
)
(set_global $game-of-life/s
(i32.mul
(get_global $game-of-life/w)
(get_global $game-of-life/h)
)
)
)
(func $game-of-life/step (; 1 ;) (type $v)
(local $0 i32)
(local $1 i32)
(local $2 i32)
(local $3 i32)
(local $4 i32)
(local $5 i32)
(local $6 i32)
(local $7 i32)
(local $8 i32)
(local $9 i32)
(local $10 i32)
(local $11 i32)
(nop)
(nop)
(block
(set_local $6
(i32.sub
(get_global $game-of-life/h)
(i32.const 1)
)
)
(set_local $7
(i32.sub
(get_global $game-of-life/w)
(i32.const 1)
)
)
)
(block
(set_local $10
(i32.const 0)
)
)
(block $break|1.1
(set_local $0
(i32.const 0)
)
(loop $continue|1.1
(if
(i32.lt_s
(get_local $0)
(get_global $game-of-life/h)
)
(block
(block
(set_local $1
(select
(get_local $6)
(i32.sub
(get_local $0)
(i32.const 1)
)
(i32.eq
(get_local $0)
(i32.const 0)
)
)
)
(set_local $2
(select
(i32.const 0)
(i32.add
(get_local $0)
(i32.const 1)
)
(i32.eq
(get_local $0)
(get_local $6)
)
)
)
(block $break|1.2
(set_local $3
(i32.const 0)
)
(loop $continue|1.2
(if
(i32.lt_s
(get_local $3)
(get_global $game-of-life/w)
)
(block
(block
(set_local $4
(select
(get_local $7)
(i32.sub
(get_local $3)
(i32.const 1)
)
(i32.eq
(get_local $3)
(i32.const 0)
)
)
)
(set_local $5
(select
(i32.const 0)
(i32.add
(get_local $3)
(i32.const 1)
)
(i32.eq
(get_local $3)
(get_local $7)
)
)
)
(set_local $8
(i32.add
(i32.add
(i32.add
(i32.add
(i32.add
(i32.add
(i32.add
(i32.load8_u
(i32.add
(i32.mul
(get_local $1)
(get_global $game-of-life/w)
)
(get_local $4)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $1)
(get_global $game-of-life/w)
)
(get_local $3)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $1)
(get_global $game-of-life/w)
)
(get_local $5)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $0)
(get_global $game-of-life/w)
)
(get_local $4)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $0)
(get_global $game-of-life/w)
)
(get_local $5)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $2)
(get_global $game-of-life/w)
)
(get_local $4)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $2)
(get_global $game-of-life/w)
)
(get_local $3)
)
)
)
(i32.load8_u
(i32.add
(i32.mul
(get_local $2)
(get_global $game-of-life/w)
)
(get_local $5)
)
)
)
)
(set_local $9
(i32.load8_u
(i32.add
(i32.mul
(get_local $0)
(get_global $game-of-life/w)
)
(get_local $3)
)
)
)
(if
(get_local $9)
(if
(if (result i32)
(tee_local $11
(i32.lt_s
(get_local $8)
(i32.const 2)
)
)
(get_local $11)
(i32.gt_s
(get_local $8)
(i32.const 3)
)
)
(i32.store8
(i32.add
(i32.add
(get_global $game-of-life/s)
(i32.mul
(get_local $0)
(get_global $game-of-life/w)
)
)
(get_local $3)
)
(i32.const 0)
)
)
(if
(i32.eq
(get_local $8)
(i32.const 3)
)
(i32.store8
(i32.add
(i32.add
(get_global $game-of-life/s)
(i32.mul
(get_local $0)
(get_global $game-of-life/w)
)
)
(get_local $3)
)
(i32.const 1)
)
)
)
)
(set_local $3
(i32.add
(get_local $3)
(i32.const 1)
)
)
(br $continue|1.2)
)
)
)
)
)
(set_local $0
(i32.add
(get_local $0)
(i32.const 1)
)
)
(br $continue|1.1)
)
)
)
)
)
)
(;
[program.elements]
clz
ctz
popcnt
rotl
rotr
abs
ceil
copysign
floor
max
min
nearest
sqrt
trunc
current_memory
grow_memory
unreachable
load
store
reinterpret
select
sizeof
isNaN
isFinite
assert
game-of-life/w
game-of-life/h
game-of-life/s
game-of-life/init
game-of-life/step
[program.exports]
game-of-life/init
game-of-life/step
;)

View File

@ -7,7 +7,7 @@
(type $v (func))
(memory $0 1)
(data (i32.const 4) "\08")
(export "control_construct" (func $tlsf/control_construct))
(export "control$construct" (func $tlsf/control$construct))
(export "memory" (memory $0))
(start $start)
(func $tlsf/fls (; 0 ;) (type $ii) (param $0 i32) (result i32)
@ -31,7 +31,7 @@
(i32.const -1)
)
)
(func $tlsf/control_set_block (; 2 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(func $tlsf/control$set_block (; 2 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(if
(i32.ge_s
(get_local $1)
@ -66,7 +66,7 @@
(get_local $3)
)
)
(func $tlsf/control_construct (; 3 ;) (type $iv) (param $0 i32)
(func $tlsf/control$construct (; 3 ;) (type $iv) (param $0 i32)
(local $1 i32)
(local $2 i32)
(local $3 i32)
@ -79,7 +79,7 @@
(local $10 i32)
(local $11 i32)
(block
(block $__inlined_func$tlsf/block_set_next_free
(block $__inlined_func$tlsf/block$set_next_free
(set_local $3
(get_local $0)
)
@ -96,7 +96,7 @@
)
)
(block
(block $__inlined_func$tlsf/block_set_prev_free
(block $__inlined_func$tlsf/block$set_prev_free
(set_local $5
(get_local $0)
)
@ -113,7 +113,7 @@
)
)
(block
(block $__inlined_func$tlsf/control_set_fl
(block $__inlined_func$tlsf/control$set_fl_bitmap
(set_local $7
(get_local $0)
)
@ -140,7 +140,7 @@
)
(block
(block
(block $__inlined_func$tlsf/control_set_sl
(block $__inlined_func$tlsf/control$set_sl_bitmap
(set_local $9
(get_local $0)
)
@ -184,7 +184,7 @@
(i32.const 32)
)
(block
(call $tlsf/control_set_block
(call $tlsf/control$set_block
(get_local $0)
(get_local $1)
(get_local $2)
@ -269,7 +269,7 @@
)
(unreachable)
)
(call $tlsf/control_construct
(call $tlsf/control$construct
(i32.load
(i32.const 4)
)

View File

@ -7,7 +7,7 @@
(type $v (func))
(memory $0 1)
(data (i32.const 4) "\08")
(export "control_construct" (func $tlsf/control_construct))
(export "control$construct" (func $tlsf/control$construct))
(export "memory" (memory $0))
(start $start)
(func $tlsf/fls (; 0 ;) (type $ii) (param $0 i32) (result i32)
@ -31,7 +31,7 @@
(i32.const -1)
)
)
(func $tlsf/block_set_next_free (; 2 ;) (type $iiv) (param $0 i32) (param $1 i32)
(func $tlsf/block$set_next_free (; 2 ;) (type $iiv) (param $0 i32) (param $1 i32)
(i32.store
(i32.add
(get_local $0)
@ -40,7 +40,7 @@
(get_local $1)
)
)
(func $tlsf/block_set_prev_free (; 3 ;) (type $iiv) (param $0 i32) (param $1 i32)
(func $tlsf/block$set_prev_free (; 3 ;) (type $iiv) (param $0 i32) (param $1 i32)
(i32.store
(i32.add
(get_local $0)
@ -49,7 +49,7 @@
(get_local $1)
)
)
(func $tlsf/control_set_fl (; 4 ;) (type $iiv) (param $0 i32) (param $1 i32)
(func $tlsf/control$set_fl_bitmap (; 4 ;) (type $iiv) (param $0 i32) (param $1 i32)
(i32.store
(i32.add
(get_local $0)
@ -58,7 +58,7 @@
(get_local $1)
)
)
(func $tlsf/control_set_sl (; 5 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(func $tlsf/control$set_sl_bitmap (; 5 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(if
(i32.ge_s
(get_local $1)
@ -80,7 +80,7 @@
(get_local $2)
)
)
(func $tlsf/control_set_block (; 6 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(func $tlsf/control$set_block (; 6 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(if
(i32.ge_s
(get_local $1)
@ -115,18 +115,18 @@
(get_local $3)
)
)
(func $tlsf/control_construct (; 7 ;) (type $iv) (param $0 i32)
(func $tlsf/control$construct (; 7 ;) (type $iv) (param $0 i32)
(local $1 i32)
(local $2 i32)
(call $tlsf/block_set_next_free
(call $tlsf/block$set_next_free
(get_local $0)
(get_local $0)
)
(call $tlsf/block_set_prev_free
(call $tlsf/block$set_prev_free
(get_local $0)
(get_local $0)
)
(call $tlsf/control_set_fl
(call $tlsf/control$set_fl_bitmap
(get_local $0)
(i32.const 0)
)
@ -140,7 +140,7 @@
(i32.const 23)
)
(block
(call $tlsf/control_set_sl
(call $tlsf/control$set_sl_bitmap
(get_local $0)
(get_local $1)
(i32.const 0)
@ -155,7 +155,7 @@
(i32.const 32)
)
(block
(call $tlsf/control_set_block
(call $tlsf/control$set_block
(get_local $0)
(get_local $1)
(get_local $2)
@ -240,7 +240,7 @@
)
(unreachable)
)
(call $tlsf/control_construct
(call $tlsf/control$construct
(i32.load
(i32.const 4)
)

View File

@ -41,46 +41,98 @@ const SMALL_BLOCK_SIZE: i32 = 1 << FL_INDEX_SHIFT;
// struct block_header_t {
// struct block_header_t* prev_phys_block;
// size_t size;
// size_t tagged_size;
// struct block_header_t* next_free;
// struct block_header_t* prev_free;
// }
const BLOCK_PREV_PHYS_OFFSET: usize = 0;
const BLOCK_SIZE_OFFSET: usize = BLOCK_PREV_PHYS_OFFSET + sizeof<usize>();
const BLOCK_NEXT_FREE_OFFSET: usize = BLOCK_SIZE_OFFSET + sizeof<usize>();
const BLOCK_PREV_FREE_OFFSET: usize = BLOCK_NEXT_FREE_OFFSET + sizeof<usize>();
const BLOCK$PREV_PHYS_BLOCK_OFFSET: usize = 0;
const BLOCK$TAGGED_SIZE_OFFSET: usize = BLOCK$PREV_PHYS_BLOCK_OFFSET + sizeof<usize>();
const BLOCK$NEXT_FREE_OFFSET: usize = BLOCK$TAGGED_SIZE_OFFSET + sizeof<usize>();
const BLOCK$PREV_FREE_OFFSET: usize = BLOCK$NEXT_FREE_OFFSET + sizeof<usize>();
const BLOCK$SIZE: usize = BLOCK$PREV_FREE_OFFSET + sizeof<usize>();
function block_get_prev_phys_block(ptr: usize): usize {
return load<usize>(ptr + BLOCK_PREV_PHYS_OFFSET);
const BLOCK_HEADER_FREE_BIT: u32 = 1 << 0;
const BLOCK_HEADER_PREV_FREE_BIT: u32 = 1 << 1;
const BLOCK_OVERHEAD: usize = sizeof<usize>();
const BLOCK_START_OFFSET: usize = BLOCK$TAGGED_SIZE_OFFSET + sizeof<usize>();
const BLOCK_SIZE_MIN: usize = BLOCK$SIZE - BLOCK_OVERHEAD;
const BLOCK_SIZE_MAX: usize = 1 << (<usize>FL_INDEX_MAX);
function block$get_prev_phys_block(block: usize): usize {
return load<usize>(block + BLOCK$PREV_PHYS_BLOCK_OFFSET);
}
function block_set_prev_phys_block(ptr: usize, value: usize): void {
store<usize>(ptr + BLOCK_PREV_PHYS_OFFSET, value);
function block$set_prev_phys_block(block: usize, value: usize): void {
store<usize>(block + BLOCK$PREV_PHYS_BLOCK_OFFSET, value);
}
function block_get_size(ptr: usize): usize {
return load<usize>(ptr + BLOCK_SIZE_OFFSET);
function block$get_tagged_size(block: usize): usize {
return load<usize>(block + BLOCK$TAGGED_SIZE_OFFSET);
}
function block_set_size(ptr: usize, value: usize): void {
store<usize>(ptr + BLOCK_SIZE_OFFSET, value);
function block$set_tagged_size(block: usize, value: usize): void {
store<usize>(block + BLOCK$TAGGED_SIZE_OFFSET, value);
}
function block_get_next_free(ptr: usize): usize {
return load<usize>(ptr + BLOCK_NEXT_FREE_OFFSET);
function block_size(block: usize): usize {
return block$get_tagged_size(block) & ~(BLOCK_HEADER_FREE_BIT | BLOCK_HEADER_PREV_FREE_BIT);
}
function block_set_next_free(ptr: usize, value: usize): void {
store<usize>(ptr + BLOCK_NEXT_FREE_OFFSET, value);
function block_set_size(block: usize, value: usize): void {
store<usize>(block + BLOCK$TAGGED_SIZE_OFFSET, value | (block$get_tagged_size(block) & (BLOCK_HEADER_FREE_BIT | BLOCK_HEADER_PREV_FREE_BIT)));
}
function block_get_prev_free(ptr: usize): usize {
return load<usize>(ptr + BLOCK_PREV_FREE_OFFSET);
function block$get_next_free(block: usize): usize {
return load<usize>(block + BLOCK$NEXT_FREE_OFFSET);
}
function block_set_prev_free(ptr: usize, value: usize): void {
store<usize>(ptr + BLOCK_PREV_FREE_OFFSET, value);
function block$set_next_free(block: usize, value: usize): void {
store<usize>(block + BLOCK$NEXT_FREE_OFFSET, value);
}
function block$get_prev_free(block: usize): usize {
return load<usize>(block + BLOCK$PREV_FREE_OFFSET);
}
function block$set_prev_free(block: usize, value: usize): void {
store<usize>(block + BLOCK$PREV_FREE_OFFSET, value);
}
function block_is_last(block: usize): bool {
return block_size(block) == 0;
}
function block_is_free(block: usize): bool {
return (block$get_tagged_size(block) & BLOCK_HEADER_FREE_BIT) != 0;
}
function block_set_free(block: usize): void {
store<usize>(block + BLOCK$TAGGED_SIZE_OFFSET, block$get_tagged_size(block) | BLOCK_HEADER_FREE_BIT);
}
function block_set_used(block: usize): void {
store<usize>(block + BLOCK$TAGGED_SIZE_OFFSET, block$get_tagged_size(block) & ~BLOCK_HEADER_FREE_BIT);
}
function block_is_prev_free(block: usize): bool {
return (block$get_tagged_size(block) & BLOCK_HEADER_PREV_FREE_BIT) != 0;
}
function block_set_prev_free(block: usize): void {
store<usize>(block + BLOCK$TAGGED_SIZE_OFFSET, block$get_tagged_size(block) | BLOCK_HEADER_PREV_FREE_BIT);
}
function block_set_prev_used(block: usize): void {
store<usize>(block + BLOCK$TAGGED_SIZE_OFFSET, block$get_tagged_size(block) & ~BLOCK_HEADER_PREV_FREE_BIT);
}
function block_from_ptr(ptr: usize): usize {
return ptr - BLOCK_START_OFFSET;
}
function block_to_ptr(block: usize): usize {
return block + BLOCK_START_OFFSET;
}
// struct control_t {
@ -90,50 +142,51 @@ function block_set_prev_free(ptr: usize, value: usize): void {
// block_header_t* blocks[FL_INDEX_COUNT][SL_INDEX_COUNT];
// }
const CONTROL_FL_BITMAP_OFFSET: usize = BLOCK_PREV_FREE_OFFSET + sizeof<usize>();
const CONTROL_SL_BITMAP_OFFSET: usize = CONTROL_FL_BITMAP_OFFSET + sizeof<u32>();
const CONTROL_BLOCKS_OFFSET: usize = CONTROL_SL_BITMAP_OFFSET + FL_INDEX_COUNT * sizeof<u32>();
const CONTROL$FL_BITMAP_OFFSET: usize = BLOCK$SIZE;
const CONTROL$SL_BITMAP_OFFSET: usize = CONTROL$FL_BITMAP_OFFSET + sizeof<u32>();
const CONTROL$BLOCKS_OFFSET: usize = CONTROL$SL_BITMAP_OFFSET + FL_INDEX_COUNT * sizeof<u32>();
const CONTROL$SIZE: usize = CONTROL$BLOCKS_OFFSET + FL_INDEX_COUNT * SL_INDEX_COUNT * sizeof<u32>();
function control_get_fl(ptr: usize): u32 {
return load<u32>(ptr + CONTROL_FL_BITMAP_OFFSET);
function control$get_fl_bitmap(ptr: usize): u32 {
return load<u32>(ptr + CONTROL$FL_BITMAP_OFFSET);
}
function control_set_fl(ptr: usize, value: u32): void {
store<u32>(ptr + CONTROL_FL_BITMAP_OFFSET, value);
function control$set_fl_bitmap(ptr: usize, value: u32): void {
store<u32>(ptr + CONTROL$FL_BITMAP_OFFSET, value);
}
function control_get_sl(ptr: usize, flIndex: usize): u32 {
function control$get_sl_bitmap(ptr: usize, flIndex: usize): u32 {
assert(flIndex < FL_INDEX_COUNT);
return load<u32>(ptr + CONTROL_SL_BITMAP_OFFSET + flIndex * sizeof<u32>());
return load<u32>(ptr + CONTROL$SL_BITMAP_OFFSET + flIndex * sizeof<u32>());
}
function control_set_sl(ptr: usize, flIndex: usize, value: u32): void {
function control$set_sl_bitmap(ptr: usize, flIndex: usize, value: u32): void {
assert(flIndex < FL_INDEX_COUNT);
store<u32>(ptr + CONTROL_SL_BITMAP_OFFSET + flIndex * sizeof<u32>(), value);
store<u32>(ptr + CONTROL$SL_BITMAP_OFFSET + flIndex * sizeof<u32>(), value);
}
function control_get_block(ptr: usize, flIndex: usize, slIndex: usize): usize {
function control$get_block(ptr: usize, flIndex: usize, slIndex: usize): usize {
assert(flIndex < FL_INDEX_COUNT);
assert(slIndex < SL_INDEX_COUNT);
return load<usize>(ptr + CONTROL_BLOCKS_OFFSET + (flIndex * SL_INDEX_COUNT + slIndex) * sizeof<usize>());
return load<usize>(ptr + CONTROL$BLOCKS_OFFSET + (flIndex * SL_INDEX_COUNT + slIndex) * sizeof<usize>());
}
function control_set_block(ptr: usize, flIndex: usize, slIndex: usize, value: usize): void {
function control$set_block(ptr: usize, flIndex: usize, slIndex: usize, value: usize): void {
assert(flIndex < FL_INDEX_COUNT);
assert(slIndex < SL_INDEX_COUNT);
store<usize>(ptr + CONTROL_BLOCKS_OFFSET + (flIndex * SL_INDEX_COUNT + slIndex) * sizeof<usize>(), value);
store<usize>(ptr + CONTROL$BLOCKS_OFFSET + (flIndex * SL_INDEX_COUNT + slIndex) * sizeof<usize>(), value);
}
/* Clear structure and point all empty lists at the null block. */
export function control_construct(ptr: usize): void {
block_set_next_free(ptr, ptr);
block_set_prev_free(ptr, ptr);
control_set_fl(ptr, 0);
export function control$construct(ptr: usize): void {
block$set_next_free(ptr, ptr);
block$set_prev_free(ptr, ptr);
control$set_fl_bitmap(ptr, 0);
for (let flIndex: usize = 0; flIndex < FL_INDEX_COUNT; ++flIndex) {
control_set_sl(ptr, flIndex, 0);
control$set_sl_bitmap(ptr, flIndex, 0);
for (let slIndex: usize = 0; slIndex < SL_INDEX_COUNT; ++slIndex)
control_set_block(ptr, flIndex, slIndex, ptr);
control$set_block(ptr, flIndex, slIndex, ptr);
}
}
control_construct(load<usize>(sizeof<usize>())); // get HEAP_OFFSET and initialize there
control$construct(load<usize>(sizeof<usize>())); // get HEAP_OFFSET and initialize there

View File

@ -8,21 +8,22 @@
(type $v (func))
(global $tlsf/ALIGN_SIZE_LOG2 i32 (i32.const 3))
(global $tlsf/ALIGN_SIZE i32 (i32.const 8))
(global $tlsf/BLOCK_PREV_PHYS_OFFSET i32 (i32.const 0))
(global $tlsf/BLOCK_SIZE_OFFSET i32 (i32.const 4))
(global $tlsf/BLOCK_NEXT_FREE_OFFSET i32 (i32.const 8))
(global $tlsf/BLOCK_PREV_FREE_OFFSET i32 (i32.const 12))
(global $tlsf/CONTROL_FL_BITMAP_OFFSET i32 (i32.const 16))
(global $tlsf/BLOCK$PREV_PHYS_BLOCK_OFFSET i32 (i32.const 0))
(global $tlsf/BLOCK$TAGGED_SIZE_OFFSET i32 (i32.const 4))
(global $tlsf/BLOCK$NEXT_FREE_OFFSET i32 (i32.const 8))
(global $tlsf/BLOCK$PREV_FREE_OFFSET i32 (i32.const 12))
(global $tlsf/BLOCK$SIZE i32 (i32.const 16))
(global $tlsf/CONTROL$FL_BITMAP_OFFSET i32 (i32.const 16))
(global $tlsf/FL_INDEX_MAX i32 (i32.const 30))
(global $tlsf/SL_INDEX_COUNT_LOG2 i32 (i32.const 5))
(global $tlsf/FL_INDEX_SHIFT i32 (i32.const 8))
(global $tlsf/FL_INDEX_COUNT i32 (i32.const 23))
(global $tlsf/CONTROL_SL_BITMAP_OFFSET i32 (i32.const 20))
(global $tlsf/CONTROL$SL_BITMAP_OFFSET i32 (i32.const 20))
(global $tlsf/SL_INDEX_COUNT i32 (i32.const 32))
(global $tlsf/CONTROL_BLOCKS_OFFSET i32 (i32.const 112))
(global $tlsf/CONTROL$BLOCKS_OFFSET i32 (i32.const 112))
(memory $0 1)
(data (i32.const 4) "\08\00\00\00")
(export "control_construct" (func $tlsf/control_construct))
(export "control$construct" (func $tlsf/control$construct))
(export "memory" (memory $0))
(start $start)
(func $tlsf/fls (; 0 ;) (type $ii) (param $0 i32) (result i32)
@ -60,7 +61,7 @@
)
)
)
(func $tlsf/block_set_next_free (; 2 ;) (type $iiv) (param $0 i32) (param $1 i32)
(func $tlsf/block$set_next_free (; 2 ;) (type $iiv) (param $0 i32) (param $1 i32)
(i32.store
(i32.add
(get_local $0)
@ -69,7 +70,7 @@
(get_local $1)
)
)
(func $tlsf/block_set_prev_free (; 3 ;) (type $iiv) (param $0 i32) (param $1 i32)
(func $tlsf/block$set_prev_free (; 3 ;) (type $iiv) (param $0 i32) (param $1 i32)
(i32.store
(i32.add
(get_local $0)
@ -78,7 +79,7 @@
(get_local $1)
)
)
(func $tlsf/control_set_fl (; 4 ;) (type $iiv) (param $0 i32) (param $1 i32)
(func $tlsf/control$set_fl_bitmap (; 4 ;) (type $iiv) (param $0 i32) (param $1 i32)
(i32.store
(i32.add
(get_local $0)
@ -87,7 +88,7 @@
(get_local $1)
)
)
(func $tlsf/control_set_sl (; 5 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(func $tlsf/control$set_sl_bitmap (; 5 ;) (type $iiiv) (param $0 i32) (param $1 i32) (param $2 i32)
(if
(i32.eqz
(i32.lt_s
@ -111,7 +112,7 @@
(get_local $2)
)
)
(func $tlsf/control_set_block (; 6 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(func $tlsf/control$set_block (; 6 ;) (type $iiiiv) (param $0 i32) (param $1 i32) (param $2 i32) (param $3 i32)
(if
(i32.eqz
(i32.lt_s
@ -150,18 +151,18 @@
(get_local $3)
)
)
(func $tlsf/control_construct (; 7 ;) (type $iv) (param $0 i32)
(func $tlsf/control$construct (; 7 ;) (type $iv) (param $0 i32)
(local $1 i32)
(local $2 i32)
(call $tlsf/block_set_next_free
(call $tlsf/block$set_next_free
(get_local $0)
(get_local $0)
)
(call $tlsf/block_set_prev_free
(call $tlsf/block$set_prev_free
(get_local $0)
(get_local $0)
)
(call $tlsf/control_set_fl
(call $tlsf/control$set_fl_bitmap
(get_local $0)
(i32.const 0)
)
@ -179,7 +180,7 @@
)
(block
(block
(call $tlsf/control_set_sl
(call $tlsf/control$set_sl_bitmap
(get_local $0)
(get_local $1)
(i32.const 0)
@ -197,7 +198,7 @@
(i32.const 32)
)
(block
(call $tlsf/control_set_block
(call $tlsf/control$set_block
(get_local $0)
(get_local $1)
(get_local $2)
@ -320,7 +321,7 @@
)
(unreachable)
)
(call $tlsf/control_construct
(call $tlsf/control$construct
(i32.load
(i32.const 4)
)
@ -364,28 +365,47 @@
tlsf/FL_INDEX_SHIFT
tlsf/FL_INDEX_COUNT
tlsf/SMALL_BLOCK_SIZE
tlsf/BLOCK_PREV_PHYS_OFFSET
tlsf/BLOCK_SIZE_OFFSET
tlsf/BLOCK_NEXT_FREE_OFFSET
tlsf/BLOCK_PREV_FREE_OFFSET
tlsf/block_get_prev_phys_block
tlsf/block_set_prev_phys_block
tlsf/block_get_size
tlsf/BLOCK$PREV_PHYS_BLOCK_OFFSET
tlsf/BLOCK$TAGGED_SIZE_OFFSET
tlsf/BLOCK$NEXT_FREE_OFFSET
tlsf/BLOCK$PREV_FREE_OFFSET
tlsf/BLOCK$SIZE
tlsf/BLOCK_HEADER_FREE_BIT
tlsf/BLOCK_HEADER_PREV_FREE_BIT
tlsf/BLOCK_OVERHEAD
tlsf/BLOCK_START_OFFSET
tlsf/BLOCK_SIZE_MIN
tlsf/BLOCK_SIZE_MAX
tlsf/block$get_prev_phys_block
tlsf/block$set_prev_phys_block
tlsf/block$get_tagged_size
tlsf/block$set_tagged_size
tlsf/block_size
tlsf/block_set_size
tlsf/block_get_next_free
tlsf/block_set_next_free
tlsf/block_get_prev_free
tlsf/block$get_next_free
tlsf/block$set_next_free
tlsf/block$get_prev_free
tlsf/block$set_prev_free
tlsf/block_is_last
tlsf/block_is_free
tlsf/block_set_free
tlsf/block_set_used
tlsf/block_is_prev_free
tlsf/block_set_prev_free
tlsf/CONTROL_FL_BITMAP_OFFSET
tlsf/CONTROL_SL_BITMAP_OFFSET
tlsf/CONTROL_BLOCKS_OFFSET
tlsf/control_get_fl
tlsf/control_set_fl
tlsf/control_get_sl
tlsf/control_set_sl
tlsf/control_get_block
tlsf/control_set_block
tlsf/control_construct
tlsf/block_set_prev_used
tlsf/block_from_ptr
tlsf/block_to_ptr
tlsf/CONTROL$FL_BITMAP_OFFSET
tlsf/CONTROL$SL_BITMAP_OFFSET
tlsf/CONTROL$BLOCKS_OFFSET
tlsf/CONTROL$SIZE
tlsf/control$get_fl_bitmap
tlsf/control$set_fl_bitmap
tlsf/control$get_sl_bitmap
tlsf/control$set_sl_bitmap
tlsf/control$get_block
tlsf/control$set_block
tlsf/control$construct
[program.exports]
tlsf/control_construct
tlsf/control$construct
;)