diff --git a/src/compiler.ts b/src/compiler.ts index ce115da0..b1e293ed 100644 --- a/src/compiler.ts +++ b/src/compiler.ts @@ -1745,10 +1745,8 @@ export class Compiler extends DiagnosticEmitter { return this.module.createF32((intValue.lo) + (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()); } diff --git a/src/parser.ts b/src/parser.ts index 96c8194b..b7522a86 100644 --- a/src/parser.ts +++ b/src/parser.ts @@ -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; } diff --git a/src/tokenizer.ts b/src/tokenizer.ts index 9d8ac10e..d9d8a435 100644 --- a/src/tokenizer.ts +++ b/src/tokenizer.ts @@ -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); } diff --git a/tests/compiler/game-of-life.html b/tests/compiler/game-of-life.html new file mode 100644 index 00000000..31f791bc --- /dev/null +++ b/tests/compiler/game-of-life.html @@ -0,0 +1,37 @@ + + + diff --git a/tests/compiler/game-of-life.optimized.wast b/tests/compiler/game-of-life.optimized.wast new file mode 100644 index 00000000..d6d2cf72 --- /dev/null +++ b/tests/compiler/game-of-life.optimized.wast @@ -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) + ) + ) + ) + ) +) diff --git a/tests/compiler/game-of-life.ts b/tests/compiler/game-of-life.ts new file mode 100644 index 00000000..517155c4 --- /dev/null +++ b/tests/compiler/game-of-life.ts @@ -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(hm1, y - 1, y == 0); + yp1 = select(0, y + 1, y == hm1); + for (x = 0; x < w; ++x) { + xm1 = select(wm1, x - 1, x == 0); + xp1 = select(0, x + 1, x == wm1); + n = load(ym1 * w + xm1) + load(ym1 * w + x) + load(ym1 * w + xp1) + + load(y * w + xm1) + load(y * w + xp1) + + load(yp1 * w + xm1) + load(yp1 * w + x) + load(yp1 * w + xp1); + v = load(y * w + x); + if (v) { + if (n < 2 || n > 3) + store(s + y * w + x, 0); + } else if (n == 3) + store(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. diff --git a/tests/compiler/game-of-life.wast b/tests/compiler/game-of-life.wast new file mode 100644 index 00000000..d847c977 --- /dev/null +++ b/tests/compiler/game-of-life.wast @@ -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 +;) diff --git a/tests/compiler/tlsf.optimized-inlined.wast b/tests/compiler/tlsf.optimized-inlined.wast index 1d710ce5..bd557fb2 100644 --- a/tests/compiler/tlsf.optimized-inlined.wast +++ b/tests/compiler/tlsf.optimized-inlined.wast @@ -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) ) diff --git a/tests/compiler/tlsf.optimized.wast b/tests/compiler/tlsf.optimized.wast index 64d309f2..ebc990a3 100644 --- a/tests/compiler/tlsf.optimized.wast +++ b/tests/compiler/tlsf.optimized.wast @@ -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) ) diff --git a/tests/compiler/tlsf.ts b/tests/compiler/tlsf.ts index 2ad4c057..56e9a8d7 100644 --- a/tests/compiler/tlsf.ts +++ b/tests/compiler/tlsf.ts @@ -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(); -const BLOCK_NEXT_FREE_OFFSET: usize = BLOCK_SIZE_OFFSET + sizeof(); -const BLOCK_PREV_FREE_OFFSET: usize = BLOCK_NEXT_FREE_OFFSET + sizeof(); +const BLOCK$PREV_PHYS_BLOCK_OFFSET: usize = 0; +const BLOCK$TAGGED_SIZE_OFFSET: usize = BLOCK$PREV_PHYS_BLOCK_OFFSET + sizeof(); +const BLOCK$NEXT_FREE_OFFSET: usize = BLOCK$TAGGED_SIZE_OFFSET + sizeof(); +const BLOCK$PREV_FREE_OFFSET: usize = BLOCK$NEXT_FREE_OFFSET + sizeof(); +const BLOCK$SIZE: usize = BLOCK$PREV_FREE_OFFSET + sizeof(); -function block_get_prev_phys_block(ptr: usize): usize { - return load(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(); +const BLOCK_START_OFFSET: usize = BLOCK$TAGGED_SIZE_OFFSET + sizeof(); +const BLOCK_SIZE_MIN: usize = BLOCK$SIZE - BLOCK_OVERHEAD; +const BLOCK_SIZE_MAX: usize = 1 << (FL_INDEX_MAX); + +function block$get_prev_phys_block(block: usize): usize { + return load(block + BLOCK$PREV_PHYS_BLOCK_OFFSET); } -function block_set_prev_phys_block(ptr: usize, value: usize): void { - store(ptr + BLOCK_PREV_PHYS_OFFSET, value); +function block$set_prev_phys_block(block: usize, value: usize): void { + store(block + BLOCK$PREV_PHYS_BLOCK_OFFSET, value); } -function block_get_size(ptr: usize): usize { - return load(ptr + BLOCK_SIZE_OFFSET); +function block$get_tagged_size(block: usize): usize { + return load(block + BLOCK$TAGGED_SIZE_OFFSET); } -function block_set_size(ptr: usize, value: usize): void { - store(ptr + BLOCK_SIZE_OFFSET, value); +function block$set_tagged_size(block: usize, value: usize): void { + store(block + BLOCK$TAGGED_SIZE_OFFSET, value); } -function block_get_next_free(ptr: usize): usize { - return load(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(ptr + BLOCK_NEXT_FREE_OFFSET, value); +function block_set_size(block: usize, value: usize): void { + store(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(ptr + BLOCK_PREV_FREE_OFFSET); +function block$get_next_free(block: usize): usize { + return load(block + BLOCK$NEXT_FREE_OFFSET); } -function block_set_prev_free(ptr: usize, value: usize): void { - store(ptr + BLOCK_PREV_FREE_OFFSET, value); +function block$set_next_free(block: usize, value: usize): void { + store(block + BLOCK$NEXT_FREE_OFFSET, value); +} + +function block$get_prev_free(block: usize): usize { + return load(block + BLOCK$PREV_FREE_OFFSET); +} + +function block$set_prev_free(block: usize, value: usize): void { + store(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(block + BLOCK$TAGGED_SIZE_OFFSET, block$get_tagged_size(block) | BLOCK_HEADER_FREE_BIT); +} + +function block_set_used(block: usize): void { + store(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(block + BLOCK$TAGGED_SIZE_OFFSET, block$get_tagged_size(block) | BLOCK_HEADER_PREV_FREE_BIT); +} + +function block_set_prev_used(block: usize): void { + store(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(); -const CONTROL_SL_BITMAP_OFFSET: usize = CONTROL_FL_BITMAP_OFFSET + sizeof(); -const CONTROL_BLOCKS_OFFSET: usize = CONTROL_SL_BITMAP_OFFSET + FL_INDEX_COUNT * sizeof(); +const CONTROL$FL_BITMAP_OFFSET: usize = BLOCK$SIZE; +const CONTROL$SL_BITMAP_OFFSET: usize = CONTROL$FL_BITMAP_OFFSET + sizeof(); +const CONTROL$BLOCKS_OFFSET: usize = CONTROL$SL_BITMAP_OFFSET + FL_INDEX_COUNT * sizeof(); +const CONTROL$SIZE: usize = CONTROL$BLOCKS_OFFSET + FL_INDEX_COUNT * SL_INDEX_COUNT * sizeof(); -function control_get_fl(ptr: usize): u32 { - return load(ptr + CONTROL_FL_BITMAP_OFFSET); +function control$get_fl_bitmap(ptr: usize): u32 { + return load(ptr + CONTROL$FL_BITMAP_OFFSET); } -function control_set_fl(ptr: usize, value: u32): void { - store(ptr + CONTROL_FL_BITMAP_OFFSET, value); +function control$set_fl_bitmap(ptr: usize, value: u32): void { + store(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(ptr + CONTROL_SL_BITMAP_OFFSET + flIndex * sizeof()); + return load(ptr + CONTROL$SL_BITMAP_OFFSET + flIndex * sizeof()); } -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(ptr + CONTROL_SL_BITMAP_OFFSET + flIndex * sizeof(), value); + store(ptr + CONTROL$SL_BITMAP_OFFSET + flIndex * sizeof(), 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(ptr + CONTROL_BLOCKS_OFFSET + (flIndex * SL_INDEX_COUNT + slIndex) * sizeof()); + return load(ptr + CONTROL$BLOCKS_OFFSET + (flIndex * SL_INDEX_COUNT + slIndex) * sizeof()); } -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(ptr + CONTROL_BLOCKS_OFFSET + (flIndex * SL_INDEX_COUNT + slIndex) * sizeof(), value); + store(ptr + CONTROL$BLOCKS_OFFSET + (flIndex * SL_INDEX_COUNT + slIndex) * sizeof(), 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(sizeof())); // get HEAP_OFFSET and initialize there +control$construct(load(sizeof())); // get HEAP_OFFSET and initialize there diff --git a/tests/compiler/tlsf.wast b/tests/compiler/tlsf.wast index a141f1b0..d6cd4eab 100644 --- a/tests/compiler/tlsf.wast +++ b/tests/compiler/tlsf.wast @@ -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 ;)