Fix game-of-life example inconsistencies; Fix ternary expression issues in void contexts and variable statements; Simplify HEAP_BASE handling

This commit is contained in:
dcodeIO 2018-04-18 15:12:33 +02:00
parent 4026c087fd
commit 5a2f834c0d
19 changed files with 654 additions and 559 deletions

2
dist/asc.js vendored

File diff suppressed because one or more lines are too long

2
dist/asc.js.map vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1 +1 @@
node_modules/ node_modules/

View File

@ -1,21 +1,21 @@
Conway's Game of Life Conway's Game of Life
===================== =====================
An [AssemblyScript](http://assemblyscript.org) example. Continuously updates the cellular automaton and visualizes its state on a canvas. An [AssemblyScript](http://assemblyscript.org) example. Continuously updates the cellular automaton and visualizes its state on a canvas. Compiles to ~450 bytes of optimized WASM, no strings attached.
Instructions Instructions
------------ ------------
You have to install the 'opn' package to be able to run the `npm browser` command First, install the development dependencies:
``` ```
$> npm install $> npm install
``` ```
To build [assembly/game-of-life.ts](./assembly/game-of-life.ts) to an untouched and an optimized `.wasm` including their respective `.wat` representations, run: Now, to build [assembly/game-of-life.ts](./assembly/game-of-life.ts) to an untouched and an optimized `.wasm` including their respective `.wat` representations, run:
``` ```
$> npm run build $> npm run build
``` ```
Afterwards, open [game-of-life.html](./game-of-life.html) in a browser (ideally one that allows `fetch`ing the `.wasm` from the local filesystem). Afterwards, run `node server` to start a <a href="http://localhost:9080">local server</a>. Should also automatically launch a browser.

View File

@ -1,37 +1,54 @@
// A simplified version of the game of life as seen on http://dcode.io // The Game of Life, also known simply as Life, is a cellular automaton devised by the British
// mathematician John Horton Conway in 1970.
// see: https://en.wikipedia.org/wiki/Conway's_Game_of_Life
var w: u32, // width var w: i32, h: i32, s: i32;
h: u32, // height
s: u32; // total size
/** Initializes width and height. */ /** Initializes width and height. Called once from JS. */
export function init(w_: u32, h_: u32): void { export function init(width: i32, height: i32): void {
w = w_; w = width;
h = h_; h = height;
s = w * h; s = width * height;
} }
/** Performs one step. */ /** Performs one step. Called about 30 times a second from JS. */
export function step(): void { export function step(): void {
var hm1 = h - 1, var hm1 = h - 1, // h - 1
wm1 = w - 1; wm1 = w - 1; // w - 1
for (var y: u32 = 0; y < h; ++y) {
var ym1 = select<u32>(hm1, y - 1, y == 0), // The universe of the Game of Life is an infinite two-dimensional orthogonal grid of square
yp1 = select<u32>(0, y + 1, y == hm1); // "cells", each of which is in one of two possible states, alive or dead.
for (var x: u32 = 0; x < w; ++x) { for (let y = 0; y < h; ++y) {
var xm1 = select<u32>(wm1, x - 1, x == 0),
xp1 = select<u32>(0, x + 1, x == wm1); let ym1 = y == 0 ? hm1 : y - 1, // y - 1
var n = ( yp1 = y == hm1 ? 0 : y + 1; // y + 1
for (let x = 0; x < w; ++x) {
let xm1 = x == 0 ? wm1 : x - 1, // x - 1
xp1 = x == wm1 ? 0 : x + 1; // x + 1
// Every cell interacts with its eight neighbours, which are the cells that are horizontally,
// vertically, or diagonally adjacent:
let aliveNeighbors = (
load<u8>(ym1 * w + xm1) + load<u8>(ym1 * w + x) + load<u8>(ym1 * w + xp1) + 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>(y * w + xm1) + load<u8>(y * w + xp1) +
load<u8>(yp1 * w + xm1) + load<u8>(yp1 * w + x) + load<u8>(yp1 * w + xp1) load<u8>(yp1 * w + xm1) + load<u8>(yp1 * w + x) + load<u8>(yp1 * w + xp1)
); );
if (load<u8>(y * w + x)) {
if (n < 2 || n > 3) { let alive = load<u8>(y * w + x);
store<u8>(s + y * w + x, 0); if (alive) {
switch (aliveNeighbors) {
// A live cell with fewer than 2 live neighbors dies, as if caused by underpopulation.
// A live cell with more than 3 live neighbors dies, as if by overpopulation.
default: { store<u8>(s + y * w + x, 0); break; }
// A live cell with 2 or 3 live neighbors lives on to the next generation.
case 2: case 3:
}
} else {
switch (aliveNeighbors) {
// A dead cell with exactly 3 live neighbors becomes a live cell, as if by reproduction.
case 3: { store<u8>(s + y * w + x, 1); break; }
default:
} }
} else if (n == 3) {
store<u8>(s + y * w + x, 1);
} }
} }
} }

View File

@ -1,27 +1,47 @@
<canvas id="canvas" width="640" height="480"></canvas><script> <html>
<head>
<style>
html, body { height: 100%; margin: 0; overflow: hidden; color: #111; background: #fff; font-family: sans-serif; }
h1 { padding: 20px; font-size: 12pt; }
a { color: #111; text-decoration: none; }
a:hover { color: #0074C1; text-decoration: underline; }
canvas { position: absolute; top: 60px; left: 20px; width: calc(100% - 40px); height: calc(100% - 80px); }
</style>
</head>
<body>
<h1>
<a href="https://en.wikipedia.org/wiki/Conway's_Game_of_Life">Conway's Game Of Life</a> in
<a href="http://assemblyscript.org">AssemblyScript</a>
</h1>
<canvas id="canvas"></canvas>
<script>
// Fetch the .wasm // Set up the canvas with a 2D rendering context
fetch("game-of-life.optimized.wasm").then(response => response.arrayBuffer()).then(binary => { var cnv = document.getElementById("canvas");
var ctx = cnv.getContext("2d");
var bcr = cnv.getBoundingClientRect();
cnv.width = bcr.width | 0;
cnv.height = bcr.height | 0;
// Instantiate the module // Compute the size of the universe (here: 2px per cell)
var module = new WebAssembly.Module(binary); var w = bcr.width >>> 1;
var instance = new WebAssembly.Instance(module, { env: { abort: function() {} } }); var h = bcr.height >>> 1;
var s = w * h; // memory required to store either input or output
var S = s + s; // total memory required to store input and output
// Set up the canvas with a 2D rendering context // Compute the size of and instantiate the module's memory
var cnv = document.getElementById("canvas"); var nPages = ((S + 0xffff) & ~0xffff) >>> 16; // aligned up in 64k units
var ctx = cnv.getContext("2d"); var memory = new WebAssembly.Memory({ initial: nPages });
var w = cnv.width,
h = cnv.height,
s = w * h, // memory required to store either input or output
S = s + s; // total memory required to store input and output
// Grow the (exported) memory if its size isn't sufficient // Fetch and instantiate the module
var memory = instance.exports.memory; WebAssembly.instantiateStreaming(fetch("game-of-life.optimized.wasm"), {
if (memory.buffer.byteLength < S) env: { memory: memory }
memory.grow(Math.ceil((S - memory.buffer.byteLength) / 65536)); })
.then(module => {
var exports = module.instance.exports;
// Initialize with width and height // Tell the module about the universe's width and height
instance.exports.init(w, h); exports.init(w, h);
// Fill input at [0, s-1] with random live cells // Fill input at [0, s-1] with random live cells
var mem = new Uint8Array(memory.buffer); var mem = new Uint8Array(memory.buffer);
@ -31,23 +51,26 @@ fetch("game-of-life.optimized.wasm").then(response => response.arrayBuffer()).th
// Update about 30 times a second // Update about 30 times a second
(function update() { (function update() {
setTimeout(update, 33); setTimeout(update, 30);
instance.exports.step(); exports.step();
mem.set(mem.subarray(s, S), 0); // copy output -> input mem.copyWithin(0, s, S); // copy output at [s, S] to input at [0, s]
})(); })();
// Keep rendering the output at [s, 2*s-1] // Keep rendering the output at [s, S]
(function render() { (function render() {
requestAnimationFrame(render); requestAnimationFrame(render);
ctx.clearRect(0, 0, w, h); ctx.fillStyle = "rgba(238,238,238,0.67)";
ctx.fillRect(0, 0, w << 1, h << 1);
ctx.fillStyle = "#333"; ctx.fillStyle = "#333";
for (var y = 0; y < h; ++y) for (var y = 0; y < h; ++y)
for (var x = 0; x < w; ++x) for (var x = 0; x < w; ++x)
if (mem[s + y * w + x]) if (mem[s + y * w + x])
ctx.fillRect(x, y, 1, 1); ctx.fillRect(x << 1, y << 1, 2, 2);
})(); })();
}).catch(err => { }).catch(err => {
throw err; throw err;
}); });
</script> </script>
</body>
</html>

Binary file not shown.

View File

@ -1,10 +1,10 @@
(module (module
(type $iiv (func (param i32 i32))) (type $iiv (func (param i32 i32)))
(type $v (func)) (type $v (func))
(import "env" "memory" (memory $0 1))
(global $assembly/game-of-life/w (mut i32) (i32.const 0)) (global $assembly/game-of-life/w (mut i32) (i32.const 0))
(global $assembly/game-of-life/h (mut i32) (i32.const 0)) (global $assembly/game-of-life/h (mut i32) (i32.const 0))
(global $assembly/game-of-life/s (mut i32) (i32.const 0)) (global $assembly/game-of-life/s (mut i32) (i32.const 0))
(memory $0 1)
(export "init" (func $assembly/game-of-life/init)) (export "init" (func $assembly/game-of-life/init))
(export "step" (func $assembly/game-of-life/step)) (export "step" (func $assembly/game-of-life/step))
(export "memory" (memory $0)) (export "memory" (memory $0))
@ -23,9 +23,9 @@
(set_global $assembly/game-of-life/s (set_global $assembly/game-of-life/s
;;@ assembly/game-of-life.ts:11:6 ;;@ assembly/game-of-life.ts:11:6
(i32.mul (i32.mul
(get_global $assembly/game-of-life/w) (get_local $0)
;;@ assembly/game-of-life.ts:11:10 ;;@ assembly/game-of-life.ts:11:14
(get_global $assembly/game-of-life/h) (get_local $1)
) )
) )
) )
@ -38,7 +38,7 @@
(local $5 i32) (local $5 i32)
(local $6 i32) (local $6 i32)
(local $7 i32) (local $7 i32)
(set_local $6 (set_local $5
;;@ assembly/game-of-life.ts:16:12 ;;@ assembly/game-of-life.ts:16:12
(i32.sub (i32.sub
(get_global $assembly/game-of-life/h) (get_global $assembly/game-of-life/h)
@ -46,7 +46,7 @@
(i32.const 1) (i32.const 1)
) )
) )
(set_local $7 (set_local $6
;;@ assembly/game-of-life.ts:17:12 ;;@ assembly/game-of-life.ts:17:12
(i32.sub (i32.sub
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
@ -56,66 +56,64 @@
) )
(loop $continue|0 (loop $continue|0
(if (if
;;@ assembly/game-of-life.ts:18:23 ;;@ assembly/game-of-life.ts:21:18
(i32.lt_u (i32.lt_s
(get_local $0) (get_local $0)
;;@ assembly/game-of-life.ts:18:27 ;;@ assembly/game-of-life.ts:21:22
(get_global $assembly/game-of-life/h) (get_global $assembly/game-of-life/h)
) )
(block (block
(set_local $4 (set_local $3
;;@ assembly/game-of-life.ts:19:14 ;;@ assembly/game-of-life.ts:23:14
(select (if (result i32)
;;@ assembly/game-of-life.ts:19:31 (get_local $0)
;;@ assembly/game-of-life.ts:23:29
(i32.sub (i32.sub
(get_local $0) (get_local $0)
;;@ assembly/game-of-life.ts:19:35 ;;@ assembly/game-of-life.ts:23:33
(i32.const 1) (i32.const 1)
) )
;;@ assembly/game-of-life.ts:19:26 ;;@ assembly/game-of-life.ts:23:23
(get_local $6) (get_local $5)
;;@ assembly/game-of-life.ts:19:38
(get_local $0)
) )
) )
(set_local $5 (set_local $4
;;@ assembly/game-of-life.ts:20:14 ;;@ assembly/game-of-life.ts:24:14
(select (if (result i32)
;;@ assembly/game-of-life.ts:20:26
(i32.const 0)
;;@ assembly/game-of-life.ts:20:29
(i32.add
(get_local $0)
;;@ assembly/game-of-life.ts:20:33
(i32.const 1)
)
;;@ assembly/game-of-life.ts:20:36
(i32.eq (i32.eq
(get_local $0) (get_local $0)
;;@ assembly/game-of-life.ts:20:41 ;;@ assembly/game-of-life.ts:24:19
(get_local $6) (get_local $5)
)
;;@ assembly/game-of-life.ts:24:25
(i32.const 0)
;;@ assembly/game-of-life.ts:24:29
(i32.add
(get_local $0)
;;@ assembly/game-of-life.ts:24:33
(i32.const 1)
) )
) )
) )
;;@ assembly/game-of-life.ts:21:9 ;;@ assembly/game-of-life.ts:25:9
(set_local $1 (set_local $1
;;@ assembly/game-of-life.ts:21:22 ;;@ assembly/game-of-life.ts:25:17
(i32.const 0) (i32.const 0)
) )
(loop $continue|1 (loop $continue|1
(if (if
;;@ assembly/game-of-life.ts:21:25 ;;@ assembly/game-of-life.ts:25:20
(i32.lt_u (i32.lt_s
(get_local $1) (get_local $1)
;;@ assembly/game-of-life.ts:21:29 ;;@ assembly/game-of-life.ts:25:24
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
(block (block
;;@ assembly/game-of-life.ts:24:6 ;;@ assembly/game-of-life.ts:31:6
(set_local $2 (set_local $2
;;@ assembly/game-of-life.ts:24:14 ;;@ assembly/game-of-life.ts:31:27
(i32.add (i32.add
;;@ assembly/game-of-life.ts:25:8 ;;@ assembly/game-of-life.ts:32:8
(i32.add (i32.add
(i32.add (i32.add
(i32.add (i32.add
@ -123,236 +121,228 @@
(i32.add (i32.add
(i32.add (i32.add
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:25:17 ;;@ assembly/game-of-life.ts:32:17
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $4) (get_local $3)
;;@ assembly/game-of-life.ts:25:23 ;;@ assembly/game-of-life.ts:32:23
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
(tee_local $2 (tee_local $2
;;@ assembly/game-of-life.ts:22:16 ;;@ assembly/game-of-life.ts:26:16
(select (if (result i32)
;;@ assembly/game-of-life.ts:22:33 (get_local $1)
;;@ assembly/game-of-life.ts:26:31
(i32.sub (i32.sub
(get_local $1) (get_local $1)
;;@ assembly/game-of-life.ts:22:37 ;;@ assembly/game-of-life.ts:26:35
(i32.const 1) (i32.const 1)
) )
;;@ assembly/game-of-life.ts:22:28 ;;@ assembly/game-of-life.ts:26:25
(get_local $7) (get_local $6)
;;@ assembly/game-of-life.ts:22:40
(get_local $1)
) )
) )
) )
) )
;;@ assembly/game-of-life.ts:25:34 ;;@ assembly/game-of-life.ts:32:34
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:25:43 ;;@ assembly/game-of-life.ts:32:43
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $4) (get_local $3)
;;@ assembly/game-of-life.ts:25:49 ;;@ assembly/game-of-life.ts:32:49
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:25:53 ;;@ assembly/game-of-life.ts:32:53
(get_local $1) (get_local $1)
) )
) )
) )
;;@ assembly/game-of-life.ts:25:58 ;;@ assembly/game-of-life.ts:32:58
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:25:67 ;;@ assembly/game-of-life.ts:32:67
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $4) (get_local $3)
;;@ assembly/game-of-life.ts:25:73 ;;@ assembly/game-of-life.ts:32:73
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
(tee_local $3 (tee_local $7
;;@ assembly/game-of-life.ts:23:16 ;;@ assembly/game-of-life.ts:27:16
(select (if (result i32)
;;@ assembly/game-of-life.ts:23:28
(i32.const 0)
;;@ assembly/game-of-life.ts:23:31
(i32.add
(get_local $1)
;;@ assembly/game-of-life.ts:23:35
(i32.const 1)
)
;;@ assembly/game-of-life.ts:23:38
(i32.eq (i32.eq
(get_local $1) (get_local $1)
;;@ assembly/game-of-life.ts:23:43 ;;@ assembly/game-of-life.ts:27:21
(get_local $7) (get_local $6)
)
;;@ assembly/game-of-life.ts:27:27
(i32.const 0)
;;@ assembly/game-of-life.ts:27:31
(i32.add
(get_local $1)
;;@ assembly/game-of-life.ts:27:35
(i32.const 1)
) )
) )
) )
) )
) )
) )
;;@ assembly/game-of-life.ts:26:8 ;;@ assembly/game-of-life.ts:33:8
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:26:17 ;;@ assembly/game-of-life.ts:33:17
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $0) (get_local $0)
;;@ assembly/game-of-life.ts:26:23 ;;@ assembly/game-of-life.ts:33:23
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:26:27 ;;@ assembly/game-of-life.ts:33:27
(get_local $2) (get_local $2)
) )
) )
) )
;;@ assembly/game-of-life.ts:26:58 ;;@ assembly/game-of-life.ts:33:58
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:26:67 ;;@ assembly/game-of-life.ts:33:67
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $0) (get_local $0)
;;@ assembly/game-of-life.ts:26:73 ;;@ assembly/game-of-life.ts:33:73
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:26:77 ;;@ assembly/game-of-life.ts:33:77
(get_local $3) (get_local $7)
) )
) )
) )
;;@ assembly/game-of-life.ts:27:8 ;;@ assembly/game-of-life.ts:34:8
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:27:17 ;;@ assembly/game-of-life.ts:34:17
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $5) (get_local $4)
;;@ assembly/game-of-life.ts:27:23 ;;@ assembly/game-of-life.ts:34:23
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:27:27 ;;@ assembly/game-of-life.ts:34:27
(get_local $2) (get_local $2)
) )
) )
) )
;;@ assembly/game-of-life.ts:27:34 ;;@ assembly/game-of-life.ts:34:34
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:27:43 ;;@ assembly/game-of-life.ts:34:43
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $5) (get_local $4)
;;@ assembly/game-of-life.ts:27:49 ;;@ assembly/game-of-life.ts:34:49
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:27:53 ;;@ assembly/game-of-life.ts:34:53
(get_local $1) (get_local $1)
) )
) )
) )
;;@ assembly/game-of-life.ts:27:58 ;;@ assembly/game-of-life.ts:34:58
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:27:67 ;;@ assembly/game-of-life.ts:34:67
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $5) (get_local $4)
;;@ assembly/game-of-life.ts:27:73 ;;@ assembly/game-of-life.ts:34:73
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:27:77 ;;@ assembly/game-of-life.ts:34:77
(get_local $3) (get_local $7)
) )
) )
) )
) )
;;@ assembly/game-of-life.ts:29:6 ;;@ assembly/game-of-life.ts:38:6
(if (if
;;@ assembly/game-of-life.ts:29:10 ;;@ assembly/game-of-life.ts:37:18
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:29:19 ;;@ assembly/game-of-life.ts:37:27
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $0) (get_local $0)
;;@ assembly/game-of-life.ts:29:23 ;;@ assembly/game-of-life.ts:37:31
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:29:27 ;;@ assembly/game-of-life.ts:37:35
(get_local $1) (get_local $1)
) )
) )
;;@ assembly/game-of-life.ts:30:8 ;;@ assembly/game-of-life.ts:39:8
(if (block $break|2
;;@ assembly/game-of-life.ts:30:12 (br_if $break|2
(i32.and (i32.eq
(if (result i32) ;;@ assembly/game-of-life.ts:39:16
(tee_local $3 (get_local $2)
(i32.lt_s ;;@ assembly/game-of-life.ts:44:15
(get_local $2) (i32.const 2)
;;@ assembly/game-of-life.ts:30:16
(i32.const 2)
)
)
(get_local $3)
;;@ assembly/game-of-life.ts:30:21
(i32.gt_s
(get_local $2)
;;@ assembly/game-of-life.ts:30:25
(i32.const 3)
)
) )
(i32.const 1)
) )
;;@ assembly/game-of-life.ts:31:10 (br_if $break|2
(i32.eq
(get_local $2)
;;@ assembly/game-of-life.ts:44:23
(i32.const 3)
)
)
;;@ assembly/game-of-life.ts:42:21
(i32.store8 (i32.store8
;;@ assembly/game-of-life.ts:31:20 ;;@ assembly/game-of-life.ts:42:31
(i32.add (i32.add
(i32.add (i32.add
(get_global $assembly/game-of-life/s) (get_global $assembly/game-of-life/s)
;;@ assembly/game-of-life.ts:31:24 ;;@ assembly/game-of-life.ts:42:35
(i32.mul (i32.mul
(get_local $0) (get_local $0)
;;@ assembly/game-of-life.ts:31:28 ;;@ assembly/game-of-life.ts:42:39
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
) )
;;@ assembly/game-of-life.ts:31:32 ;;@ assembly/game-of-life.ts:42:43
(get_local $1) (get_local $1)
) )
;;@ assembly/game-of-life.ts:31:35 ;;@ assembly/game-of-life.ts:42:46
(i32.const 0) (i32.const 0)
) )
) )
;;@ assembly/game-of-life.ts:33:13
(if (if
;;@ assembly/game-of-life.ts:33:17
(i32.eq (i32.eq
;;@ assembly/game-of-life.ts:47:16
(get_local $2) (get_local $2)
;;@ assembly/game-of-life.ts:33:22 ;;@ assembly/game-of-life.ts:49:15
(i32.const 3) (i32.const 3)
) )
;;@ assembly/game-of-life.ts:34:8 ;;@ assembly/game-of-life.ts:49:20
(i32.store8 (i32.store8
;;@ assembly/game-of-life.ts:34:18 ;;@ assembly/game-of-life.ts:49:30
(i32.add (i32.add
(i32.add (i32.add
(get_global $assembly/game-of-life/s) (get_global $assembly/game-of-life/s)
;;@ assembly/game-of-life.ts:34:22 ;;@ assembly/game-of-life.ts:49:34
(i32.mul (i32.mul
(get_local $0) (get_local $0)
;;@ assembly/game-of-life.ts:34:26 ;;@ assembly/game-of-life.ts:49:38
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
) )
;;@ assembly/game-of-life.ts:34:30 ;;@ assembly/game-of-life.ts:49:42
(get_local $1) (get_local $1)
) )
;;@ assembly/game-of-life.ts:34:33 ;;@ assembly/game-of-life.ts:49:45
(i32.const 1) (i32.const 1)
) )
) )
) )
;;@ assembly/game-of-life.ts:21:32 ;;@ assembly/game-of-life.ts:25:27
(set_local $1 (set_local $1
(i32.add (i32.add
;;@ assembly/game-of-life.ts:21:34 ;;@ assembly/game-of-life.ts:25:29
(get_local $1) (get_local $1)
(i32.const 1) (i32.const 1)
) )
@ -361,10 +351,10 @@
) )
) )
) )
;;@ assembly/game-of-life.ts:18:30 ;;@ assembly/game-of-life.ts:21:25
(set_local $0 (set_local $0
(i32.add (i32.add
;;@ assembly/game-of-life.ts:18:32 ;;@ assembly/game-of-life.ts:21:27
(get_local $0) (get_local $0)
(i32.const 1) (i32.const 1)
) )

View File

@ -1,11 +1,11 @@
(module (module
(type $iiv (func (param i32 i32))) (type $iiv (func (param i32 i32)))
(type $v (func)) (type $v (func))
(import "env" "memory" (memory $0 1))
(global $assembly/game-of-life/w (mut i32) (i32.const 0)) (global $assembly/game-of-life/w (mut i32) (i32.const 0))
(global $assembly/game-of-life/h (mut i32) (i32.const 0)) (global $assembly/game-of-life/h (mut i32) (i32.const 0))
(global $assembly/game-of-life/s (mut i32) (i32.const 0)) (global $assembly/game-of-life/s (mut i32) (i32.const 0))
(global $HEAP_BASE i32 (i32.const 4)) (global $HEAP_BASE i32 (i32.const 4))
(memory $0 1)
(export "init" (func $assembly/game-of-life/init)) (export "init" (func $assembly/game-of-life/init))
(export "step" (func $assembly/game-of-life/step)) (export "step" (func $assembly/game-of-life/step))
(export "memory" (memory $0)) (export "memory" (memory $0))
@ -24,9 +24,9 @@
(set_global $assembly/game-of-life/s (set_global $assembly/game-of-life/s
;;@ assembly/game-of-life.ts:11:6 ;;@ assembly/game-of-life.ts:11:6
(i32.mul (i32.mul
(get_global $assembly/game-of-life/w) (get_local $0)
;;@ assembly/game-of-life.ts:11:10 ;;@ assembly/game-of-life.ts:11:14
(get_global $assembly/game-of-life/h) (get_local $1)
) )
) )
) )
@ -41,6 +41,7 @@
(local $7 i32) (local $7 i32)
(local $8 i32) (local $8 i32)
(local $9 i32) (local $9 i32)
(local $10 i32)
;;@ assembly/game-of-life.ts:16:2 ;;@ assembly/game-of-life.ts:16:2
(block (block
(set_local $0 (set_local $0
@ -60,125 +61,121 @@
) )
) )
) )
;;@ assembly/game-of-life.ts:18:2 ;;@ assembly/game-of-life.ts:21:2
(block $break|0 (block $break|0
;;@ assembly/game-of-life.ts:18:7 ;;@ assembly/game-of-life.ts:21:7
(set_local $2 (set_local $2
;;@ assembly/game-of-life.ts:18:20 ;;@ assembly/game-of-life.ts:21:15
(i32.const 0) (i32.const 0)
) )
(loop $continue|0 (loop $continue|0
(if (if
;;@ assembly/game-of-life.ts:18:23 ;;@ assembly/game-of-life.ts:21:18
(i32.lt_u (i32.lt_s
(get_local $2) (get_local $2)
;;@ assembly/game-of-life.ts:18:27 ;;@ assembly/game-of-life.ts:21:22
(get_global $assembly/game-of-life/h) (get_global $assembly/game-of-life/h)
) )
(block (block
(block (block
(block (block
(set_local $3 (set_local $3
;;@ assembly/game-of-life.ts:19:14 ;;@ assembly/game-of-life.ts:23:14
(select (if (result i32)
;;@ assembly/game-of-life.ts:19:26
(get_local $0)
;;@ assembly/game-of-life.ts:19:31
(i32.sub
(get_local $2)
;;@ assembly/game-of-life.ts:19:35
(i32.const 1)
)
;;@ assembly/game-of-life.ts:19:38
(i32.eq (i32.eq
(get_local $2) (get_local $2)
;;@ assembly/game-of-life.ts:19:43 ;;@ assembly/game-of-life.ts:23:19
(i32.const 0) (i32.const 0)
) )
;;@ assembly/game-of-life.ts:23:23
(get_local $0)
;;@ assembly/game-of-life.ts:23:29
(i32.sub
(get_local $2)
;;@ assembly/game-of-life.ts:23:33
(i32.const 1)
)
) )
) )
(set_local $4 (set_local $4
;;@ assembly/game-of-life.ts:20:14 ;;@ assembly/game-of-life.ts:24:14
(select (if (result i32)
;;@ assembly/game-of-life.ts:20:26
(i32.const 0)
;;@ assembly/game-of-life.ts:20:29
(i32.add
(get_local $2)
;;@ assembly/game-of-life.ts:20:33
(i32.const 1)
)
;;@ assembly/game-of-life.ts:20:36
(i32.eq (i32.eq
(get_local $2) (get_local $2)
;;@ assembly/game-of-life.ts:20:41 ;;@ assembly/game-of-life.ts:24:19
(get_local $0) (get_local $0)
) )
;;@ assembly/game-of-life.ts:24:25
(i32.const 0)
;;@ assembly/game-of-life.ts:24:29
(i32.add
(get_local $2)
;;@ assembly/game-of-life.ts:24:33
(i32.const 1)
)
) )
) )
) )
;;@ assembly/game-of-life.ts:21:4 ;;@ assembly/game-of-life.ts:25:4
(block $break|1 (block $break|1
;;@ assembly/game-of-life.ts:21:9 ;;@ assembly/game-of-life.ts:25:9
(set_local $5 (set_local $5
;;@ assembly/game-of-life.ts:21:22 ;;@ assembly/game-of-life.ts:25:17
(i32.const 0) (i32.const 0)
) )
(loop $continue|1 (loop $continue|1
(if (if
;;@ assembly/game-of-life.ts:21:25 ;;@ assembly/game-of-life.ts:25:20
(i32.lt_u (i32.lt_s
(get_local $5) (get_local $5)
;;@ assembly/game-of-life.ts:21:29 ;;@ assembly/game-of-life.ts:25:24
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
(block (block
(block (block
(block (block
(set_local $6 (set_local $6
;;@ assembly/game-of-life.ts:22:16 ;;@ assembly/game-of-life.ts:26:16
(select (if (result i32)
;;@ assembly/game-of-life.ts:22:28
(get_local $1)
;;@ assembly/game-of-life.ts:22:33
(i32.sub
(get_local $5)
;;@ assembly/game-of-life.ts:22:37
(i32.const 1)
)
;;@ assembly/game-of-life.ts:22:40
(i32.eq (i32.eq
(get_local $5) (get_local $5)
;;@ assembly/game-of-life.ts:22:45 ;;@ assembly/game-of-life.ts:26:21
(i32.const 0) (i32.const 0)
) )
;;@ assembly/game-of-life.ts:26:25
(get_local $1)
;;@ assembly/game-of-life.ts:26:31
(i32.sub
(get_local $5)
;;@ assembly/game-of-life.ts:26:35
(i32.const 1)
)
) )
) )
(set_local $7 (set_local $7
;;@ assembly/game-of-life.ts:23:16 ;;@ assembly/game-of-life.ts:27:16
(select (if (result i32)
;;@ assembly/game-of-life.ts:23:28
(i32.const 0)
;;@ assembly/game-of-life.ts:23:31
(i32.add
(get_local $5)
;;@ assembly/game-of-life.ts:23:35
(i32.const 1)
)
;;@ assembly/game-of-life.ts:23:38
(i32.eq (i32.eq
(get_local $5) (get_local $5)
;;@ assembly/game-of-life.ts:23:43 ;;@ assembly/game-of-life.ts:27:21
(get_local $1) (get_local $1)
) )
;;@ assembly/game-of-life.ts:27:27
(i32.const 0)
;;@ assembly/game-of-life.ts:27:31
(i32.add
(get_local $5)
;;@ assembly/game-of-life.ts:27:35
(i32.const 1)
)
) )
) )
) )
;;@ assembly/game-of-life.ts:24:6 ;;@ assembly/game-of-life.ts:31:6
(set_local $8 (set_local $8
;;@ assembly/game-of-life.ts:24:14 ;;@ assembly/game-of-life.ts:31:27
(i32.add (i32.add
;;@ assembly/game-of-life.ts:25:8 ;;@ assembly/game-of-life.ts:32:8
(i32.add (i32.add
(i32.add (i32.add
(i32.add (i32.add
@ -186,207 +183,237 @@
(i32.add (i32.add
(i32.add (i32.add
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:25:17 ;;@ assembly/game-of-life.ts:32:17
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $3) (get_local $3)
;;@ assembly/game-of-life.ts:25:23 ;;@ assembly/game-of-life.ts:32:23
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:25:27 ;;@ assembly/game-of-life.ts:32:27
(get_local $6) (get_local $6)
) )
) )
;;@ assembly/game-of-life.ts:25:34 ;;@ assembly/game-of-life.ts:32:34
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:25:43 ;;@ assembly/game-of-life.ts:32:43
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $3) (get_local $3)
;;@ assembly/game-of-life.ts:25:49 ;;@ assembly/game-of-life.ts:32:49
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:25:53 ;;@ assembly/game-of-life.ts:32:53
(get_local $5) (get_local $5)
) )
) )
) )
;;@ assembly/game-of-life.ts:25:58 ;;@ assembly/game-of-life.ts:32:58
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:25:67 ;;@ assembly/game-of-life.ts:32:67
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $3) (get_local $3)
;;@ assembly/game-of-life.ts:25:73 ;;@ assembly/game-of-life.ts:32:73
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:25:77 ;;@ assembly/game-of-life.ts:32:77
(get_local $7) (get_local $7)
) )
) )
) )
;;@ assembly/game-of-life.ts:26:8 ;;@ assembly/game-of-life.ts:33:8
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:26:17 ;;@ assembly/game-of-life.ts:33:17
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $2) (get_local $2)
;;@ assembly/game-of-life.ts:26:23 ;;@ assembly/game-of-life.ts:33:23
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:26:27 ;;@ assembly/game-of-life.ts:33:27
(get_local $6) (get_local $6)
) )
) )
) )
;;@ assembly/game-of-life.ts:26:58 ;;@ assembly/game-of-life.ts:33:58
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:26:67 ;;@ assembly/game-of-life.ts:33:67
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $2) (get_local $2)
;;@ assembly/game-of-life.ts:26:73 ;;@ assembly/game-of-life.ts:33:73
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:26:77 ;;@ assembly/game-of-life.ts:33:77
(get_local $7) (get_local $7)
) )
) )
) )
;;@ assembly/game-of-life.ts:27:8 ;;@ assembly/game-of-life.ts:34:8
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:27:17 ;;@ assembly/game-of-life.ts:34:17
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $4) (get_local $4)
;;@ assembly/game-of-life.ts:27:23 ;;@ assembly/game-of-life.ts:34:23
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:27:27 ;;@ assembly/game-of-life.ts:34:27
(get_local $6) (get_local $6)
) )
) )
) )
;;@ assembly/game-of-life.ts:27:34 ;;@ assembly/game-of-life.ts:34:34
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:27:43 ;;@ assembly/game-of-life.ts:34:43
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $4) (get_local $4)
;;@ assembly/game-of-life.ts:27:49 ;;@ assembly/game-of-life.ts:34:49
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:27:53 ;;@ assembly/game-of-life.ts:34:53
(get_local $5) (get_local $5)
) )
) )
) )
;;@ assembly/game-of-life.ts:27:58 ;;@ assembly/game-of-life.ts:34:58
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:27:67 ;;@ assembly/game-of-life.ts:34:67
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $4) (get_local $4)
;;@ assembly/game-of-life.ts:27:73 ;;@ assembly/game-of-life.ts:34:73
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:27:77 ;;@ assembly/game-of-life.ts:34:77
(get_local $7) (get_local $7)
) )
) )
) )
) )
;;@ assembly/game-of-life.ts:29:6 ;;@ assembly/game-of-life.ts:37:6
(if (set_local $9
;;@ assembly/game-of-life.ts:29:10 ;;@ assembly/game-of-life.ts:37:18
(i32.load8_u (i32.load8_u
;;@ assembly/game-of-life.ts:29:19 ;;@ assembly/game-of-life.ts:37:27
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $2) (get_local $2)
;;@ assembly/game-of-life.ts:29:23 ;;@ assembly/game-of-life.ts:37:31
(get_global $assembly/game-of-life/w) (get_global $assembly/game-of-life/w)
) )
;;@ assembly/game-of-life.ts:29:27 ;;@ assembly/game-of-life.ts:37:35
(get_local $5) (get_local $5)
) )
) )
;;@ assembly/game-of-life.ts:30:8 )
(if ;;@ assembly/game-of-life.ts:38:6
;;@ assembly/game-of-life.ts:30:12 (if
(i32.and ;;@ assembly/game-of-life.ts:38:10
(if (result i32) (get_local $9)
(tee_local $9 ;;@ assembly/game-of-life.ts:39:8
(i32.lt_s (block $break|2
(block $case2|2
(block $case1|2
(block $case0|2
(set_local $10
;;@ assembly/game-of-life.ts:39:16
(get_local $8) (get_local $8)
;;@ assembly/game-of-life.ts:30:16
(i32.const 2)
) )
(br_if $case1|2
(i32.eq
(get_local $10)
;;@ assembly/game-of-life.ts:44:15
(i32.const 2)
)
)
(br_if $case2|2
(i32.eq
(get_local $10)
;;@ assembly/game-of-life.ts:44:23
(i32.const 3)
)
)
(br $case0|2)
) )
(get_local $9) ;;@ assembly/game-of-life.ts:42:19
;;@ assembly/game-of-life.ts:30:21 (block
(i32.gt_s ;;@ assembly/game-of-life.ts:42:21
(get_local $8) (i32.store8
;;@ assembly/game-of-life.ts:30:25 ;;@ assembly/game-of-life.ts:42:31
(i32.const 3) (i32.add
(i32.add
(get_global $assembly/game-of-life/s)
;;@ assembly/game-of-life.ts:42:35
(i32.mul
(get_local $2)
;;@ assembly/game-of-life.ts:42:39
(get_global $assembly/game-of-life/w)
)
)
;;@ assembly/game-of-life.ts:42:43
(get_local $5)
)
;;@ assembly/game-of-life.ts:42:46
(i32.const 0)
)
;;@ assembly/game-of-life.ts:42:50
(br $break|2)
) )
) )
(i32.const 1)
)
;;@ assembly/game-of-life.ts:31:10
(i32.store8
;;@ assembly/game-of-life.ts:31:20
(i32.add
(i32.add
(get_global $assembly/game-of-life/s)
;;@ assembly/game-of-life.ts:31:24
(i32.mul
(get_local $2)
;;@ assembly/game-of-life.ts:31:28
(get_global $assembly/game-of-life/w)
)
)
;;@ assembly/game-of-life.ts:31:32
(get_local $5)
)
;;@ assembly/game-of-life.ts:31:35
(i32.const 0)
) )
) )
;;@ assembly/game-of-life.ts:33:13 ;;@ assembly/game-of-life.ts:47:8
(if (block $break|3
;;@ assembly/game-of-life.ts:33:17 (block $case1|3
(i32.eq (block $case0|3
(get_local $8) (set_local $10
;;@ assembly/game-of-life.ts:33:22 ;;@ assembly/game-of-life.ts:47:16
(i32.const 3) (get_local $8)
) )
;;@ assembly/game-of-life.ts:34:8 (br_if $case0|3
(i32.store8 (i32.eq
;;@ assembly/game-of-life.ts:34:18 (get_local $10)
(i32.add ;;@ assembly/game-of-life.ts:49:15
(i32.add (i32.const 3)
(get_global $assembly/game-of-life/s)
;;@ assembly/game-of-life.ts:34:22
(i32.mul
(get_local $2)
;;@ assembly/game-of-life.ts:34:26
(get_global $assembly/game-of-life/w)
) )
) )
;;@ assembly/game-of-life.ts:34:30 (br $case1|3)
(get_local $5) )
;;@ assembly/game-of-life.ts:49:18
(block
;;@ assembly/game-of-life.ts:49:20
(i32.store8
;;@ assembly/game-of-life.ts:49:30
(i32.add
(i32.add
(get_global $assembly/game-of-life/s)
;;@ assembly/game-of-life.ts:49:34
(i32.mul
(get_local $2)
;;@ assembly/game-of-life.ts:49:38
(get_global $assembly/game-of-life/w)
)
)
;;@ assembly/game-of-life.ts:49:42
(get_local $5)
)
;;@ assembly/game-of-life.ts:49:45
(i32.const 1)
)
;;@ assembly/game-of-life.ts:49:49
(br $break|3)
) )
;;@ assembly/game-of-life.ts:34:33
(i32.const 1)
) )
) )
) )
) )
;;@ assembly/game-of-life.ts:21:32 ;;@ assembly/game-of-life.ts:25:27
(set_local $5 (set_local $5
(i32.add (i32.add
;;@ assembly/game-of-life.ts:21:34 ;;@ assembly/game-of-life.ts:25:29
(get_local $5) (get_local $5)
(i32.const 1) (i32.const 1)
) )
@ -397,10 +424,10 @@
) )
) )
) )
;;@ assembly/game-of-life.ts:18:30 ;;@ assembly/game-of-life.ts:21:25
(set_local $2 (set_local $2
(i32.add (i32.add
;;@ assembly/game-of-life.ts:18:32 ;;@ assembly/game-of-life.ts:21:27
(get_local $2) (get_local $2)
(i32.const 1) (i32.const 1)
) )

View File

@ -4,11 +4,10 @@
"private": true, "private": true,
"scripts": { "scripts": {
"build": "npm run build:untouched && npm run build:optimized", "build": "npm run build:untouched && npm run build:optimized",
"build:untouched": "asc assembly/game-of-life.ts -b game-of-life.untouched.wasm -t game-of-life.untouched.wat --validate --sourceMap --measure", "build:untouched": "asc assembly/game-of-life.ts -b game-of-life.untouched.wasm -t game-of-life.untouched.wat --importMemory --validate --sourceMap --measure",
"build:optimized": "asc -O assembly/game-of-life.ts -b game-of-life.optimized.wasm -t game-of-life.optimized.wat --validate --sourceMap --measure", "build:optimized": "asc -O3 assembly/game-of-life.ts -b game-of-life.optimized.wasm -t game-of-life.optimized.wat --importMemory --validate --sourceMap --noDebug --measure"
"browser": "node server.js"
}, },
"dependencies": { "devDependencies": {
"opn": "^5.3.0" "opn": "^5.3.0"
} }
} }

View File

@ -1,18 +1,32 @@
var open = require('opn'); var http = require("http");
var http = require('http'); var fs = require("fs");
var fs = require('fs'); var open = require("opn");
const PORT = 9080; const PORT = 9080;
fs.readFile('./game-of-life.html', function (err, html) { http.createServer((req, res) => {
var url = req.url;
if (err) throw err; console.log(req.method + " " + url);
if (/^\/([\w\-_]+(\.\w+)+)?$/i.test(url)) {
http.createServer(function(request, response) { if (url === "/") url = "/game-of-life.html";
response.writeHeader(200, {"Content-Type": "text/html"}); fs.readFile(__dirname + url, function(err, data) {
response.write(html); if (err) {
response.end(); res.writeHeader(404);
}).listen(PORT); } else {
res.writeHeader(200, {
"Content-Type":
/\.wasm$/.test(url) ? "application/wasm" :
/\.(json|map)$/.test(url) ? "application/json"
: "text/html"
});
res.write(data);
}
res.end();
});
} else {
res.writeHeader(404);
res.end();
}
}).listen(PORT, () => {
open("http://localhost:9080/");
}); });
open('http://localhost:9080/game-of-life.html');

View File

@ -47,25 +47,6 @@ import {
OperatorKind OperatorKind
} from "./program"; } from "./program";
/** Compiles a get of a built-in global. */
export function compileGetConstant(
compiler: Compiler,
global: Global,
reportNode: Node
): ExpressionRef {
switch (global.internalName) {
case "HEAP_BASE": { // never inlined for linking purposes
compiler.currentType = compiler.options.usizeType;
return compiler.module.createGetGlobal("HEAP_BASE", compiler.currentType.toNativeType());
}
}
compiler.error(
DiagnosticCode.Operation_not_supported,
reportNode.range
);
return compiler.module.createUnreachable();
}
/** Compiles a call to a built-in function. */ /** Compiles a call to a built-in function. */
export function compileCall( export function compileCall(
compiler: Compiler, compiler: Compiler,

View File

@ -5,7 +5,6 @@
import { import {
compileCall as compileBuiltinCall, compileCall as compileBuiltinCall,
compileGetConstant as compileBuiltinGetConstant,
compileAllocate as compileBuiltinAllocate, compileAllocate as compileBuiltinAllocate,
compileAbort as compileBuiltinAbort compileAbort as compileBuiltinAbort
} from "./builtins"; } from "./builtins";
@ -458,8 +457,8 @@ export class Compiler extends DiagnosticEmitter {
} }
compileGlobal(global: Global): bool { compileGlobal(global: Global): bool {
if (global.is(CommonFlags.COMPILED) || global.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN)) return true; if (global.is(CommonFlags.COMPILED)) return true;
global.set(CommonFlags.COMPILED); // ^ built-ins are compiled on use global.set(CommonFlags.COMPILED);
var module = this.module; var module = this.module;
var declaration = global.declaration; var declaration = global.declaration;
@ -510,6 +509,9 @@ export class Compiler extends DiagnosticEmitter {
} }
} }
// ambient builtins like 'HEAP_BASE' need to be resolved but are added explicitly
if (global.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN)) return true;
var nativeType = global.type.toNativeType(); var nativeType = global.type.toNativeType();
var isConstant = global.isAny(CommonFlags.CONST) || global.is(CommonFlags.STATIC | CommonFlags.READONLY); var isConstant = global.isAny(CommonFlags.CONST) || global.is(CommonFlags.STATIC | CommonFlags.READONLY);
@ -928,18 +930,7 @@ export class Compiler extends DiagnosticEmitter {
if (signature.requiredParameters < signature.parameterTypes.length) { if (signature.requiredParameters < signature.parameterTypes.length) {
// export the trampoline if the function takes optional parameters // export the trampoline if the function takes optional parameters
instance = this.ensureTrampoline(instance); instance = this.ensureTrampoline(instance);
if (!this.argcSet) { this.ensureArgcSet();
this.ensureArgumentCount(0);
this.argcSet = module.addFunction("~setargc",
this.ensureFunctionType([ Type.u32 ], Type.void),
null,
module.createSetGlobal("~argc",
module.createGetLocal(0, NativeType.I32)
)
);
// export a helper to set argc prior to calling it
module.addFunctionExport("~setargc", "_setargc");
}
} }
module.addFunctionExport(instance.internalName, mangleExportName(instance)); module.addFunctionExport(instance.internalName, mangleExportName(instance));
} }
@ -5098,6 +5089,38 @@ export class Compiler extends DiagnosticEmitter {
return trampoline; return trampoline;
} }
/** Makes sure that the argument count helper global is present and returns its name. */
private ensureArgcVar(): string {
var internalName = "~argc";
if (!this.argcVar) {
let module = this.module;
this.argcVar = module.addGlobal(
internalName,
NativeType.I32,
true,
module.createI32(0)
);
}
return internalName;
}
/** Makes sure that the argument count helper setter is present and returns its name. */
private ensureArgcSet(): string {
var internalName = "~setargc";
if (!this.argcSet) {
let module = this.module;
this.argcSet = module.addFunction(internalName,
this.ensureFunctionType([ Type.u32 ], Type.void),
null,
module.createSetGlobal(this.ensureArgcVar(),
module.createGetLocal(0, NativeType.I32)
)
);
module.addFunctionExport(internalName, "_setargc");
}
return internalName;
}
/** Creates a direct call to the specified function. */ /** Creates a direct call to the specified function. */
makeCallDirect( makeCallDirect(
instance: Function, instance: Function,
@ -5137,7 +5160,7 @@ export class Compiler extends DiagnosticEmitter {
let nativeReturnType = returnType.toNativeType(); let nativeReturnType = returnType.toNativeType();
this.currentType = returnType; this.currentType = returnType;
return module.createBlock(null, [ return module.createBlock(null, [
this.ensureArgumentCount(numArguments), module.createSetGlobal(this.ensureArgcVar(), module.createI32(numArguments)),
module.createCall(instance.internalName, operands, nativeReturnType) module.createCall(instance.internalName, operands, nativeReturnType)
], nativeReturnType); ], nativeReturnType);
} }
@ -5224,25 +5247,13 @@ export class Compiler extends DiagnosticEmitter {
var returnType = signature.returnType; var returnType = signature.returnType;
this.currentType = returnType; this.currentType = returnType;
return module.createBlock(null, [ return module.createBlock(null, [
this.ensureArgumentCount(numArguments), // might still be calling a trampoline module.createSetGlobal(this.ensureArgcVar(), // might still be calling a trampoline
module.createI32(numArguments)
),
module.createCallIndirect(indexArg, operands, signature.toSignatureString()) module.createCallIndirect(indexArg, operands, signature.toSignatureString())
], returnType.toNativeType()); ], returnType.toNativeType());
} }
/** Makes sure that the argument count helper global is present and returns an expression that sets it. */
private ensureArgumentCount(argumentCount: i32): ExpressionRef {
var module = this.module;
if (!this.argcVar) {
this.argcVar = module.addGlobal(
"~argc",
NativeType.I32,
true,
module.createI32(0)
);
}
return module.createSetGlobal("~argc", module.createI32(argumentCount));
}
compileCommaExpression(expression: CommaExpression, contextualType: Type): ExpressionRef { compileCommaExpression(expression: CommaExpression, contextualType: Type): ExpressionRef {
var expressions = expression.expressions; var expressions = expression.expressions;
var numExpressions = expressions.length; var numExpressions = expressions.length;
@ -5430,9 +5441,6 @@ export class Compiler extends DiagnosticEmitter {
return this.module.createGetLocal(localIndex, localType.toNativeType()); return this.module.createGetLocal(localIndex, localType.toNativeType());
} }
case ElementKind.GLOBAL: { case ElementKind.GLOBAL: {
if (target.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN)) {
return compileBuiltinGetConstant(this, <Global>target, expression);
}
if (!this.compileGlobal(<Global>target)) { // reports; not yet compiled if a static field if (!this.compileGlobal(<Global>target)) { // reports; not yet compiled if a static field
return this.module.createUnreachable(); return this.module.createUnreachable();
} }
@ -5898,9 +5906,6 @@ export class Compiler extends DiagnosticEmitter {
switch (target.kind) { switch (target.kind) {
case ElementKind.GLOBAL: { // static property case ElementKind.GLOBAL: { // static property
if (target.is(CommonFlags.AMBIENT | CommonFlags.BUILTIN)) {
return compileBuiltinGetConstant(this, <Global>target, propertyAccess);
}
if (!this.compileGlobal(<Global>target)) { // reports; not yet compiled if a static field if (!this.compileGlobal(<Global>target)) { // reports; not yet compiled if a static field
return module.createUnreachable(); return module.createUnreachable();
} }
@ -6008,6 +6013,8 @@ export class Compiler extends DiagnosticEmitter {
var currentFunction = this.currentFunction; var currentFunction = this.currentFunction;
var ifThenExpr: ExpressionRef; var ifThenExpr: ExpressionRef;
var ifElseExpr: ExpressionRef; var ifElseExpr: ExpressionRef;
var ifThenType: Type;
var ifElseType: Type;
// if part of a constructor, keep track of memory allocations // if part of a constructor, keep track of memory allocations
if (currentFunction.is(CommonFlags.CONSTRUCTOR)) { if (currentFunction.is(CommonFlags.CONSTRUCTOR)) {
@ -6015,14 +6022,16 @@ export class Compiler extends DiagnosticEmitter {
flow = flow.enterBranchOrScope(); flow = flow.enterBranchOrScope();
currentFunction.flow = flow; currentFunction.flow = flow;
ifThenExpr = this.compileExpression(ifThen, contextualType); ifThenExpr = this.compileExpressionRetainType(ifThen, contextualType);
ifThenType = this.currentType;
let ifThenAllocates = flow.is(FlowFlags.ALLOCATES); let ifThenAllocates = flow.is(FlowFlags.ALLOCATES);
flow = flow.leaveBranchOrScope(); flow = flow.leaveBranchOrScope();
currentFunction.flow = flow; currentFunction.flow = flow;
flow = flow.enterBranchOrScope(); flow = flow.enterBranchOrScope();
currentFunction.flow = flow; currentFunction.flow = flow;
ifElseExpr = this.compileExpression(ifElse, contextualType); ifElseExpr = this.compileExpressionRetainType(ifElse, contextualType);
ifElseType = this.currentType;
let ifElseAllocates = flow.is(FlowFlags.ALLOCATES); let ifElseAllocates = flow.is(FlowFlags.ALLOCATES);
flow = flow.leaveBranchOrScope(); flow = flow.leaveBranchOrScope();
currentFunction.flow = flow; currentFunction.flow = flow;
@ -6031,10 +6040,23 @@ export class Compiler extends DiagnosticEmitter {
// otherwise simplify // otherwise simplify
} else { } else {
ifThenExpr = this.compileExpression(ifThen, contextualType); ifThenExpr = this.compileExpressionRetainType(ifThen, contextualType);
ifElseExpr = this.compileExpression(ifElse, contextualType); ifThenType = this.currentType;
ifElseExpr = this.compileExpressionRetainType(ifElse, contextualType);
ifElseType = this.currentType;
} }
var commonType = Type.commonCompatible(ifThenType, ifElseType, false);
if (!commonType) {
this.error(
DiagnosticCode.Type_0_is_not_assignable_to_type_1,
expression.range, ifThenType.toString(), ifElseType.toString()
);
this.currentType = contextualType;
return this.module.createUnreachable();
}
ifThenExpr = this.convertExpression(ifThenExpr, ifThenType, commonType, ConversionKind.IMPLICIT, ifThen);
ifElseExpr = this.convertExpression(ifElseExpr, ifElseType, commonType, ConversionKind.IMPLICIT, ifElse);
this.currentType = commonType;
return this.module.createIf(condExpr, ifThenExpr, ifElseExpr); return this.module.createIf(condExpr, ifThenExpr, ifElseExpr);
} }

View File

@ -3101,7 +3101,7 @@ export class Parser extends DiagnosticEmitter {
); );
return null; return null;
} }
let ifElse = this.parseExpression(tn); let ifElse = this.parseExpression(tn, precedence > Precedence.COMMA ? Precedence.COMMA + 1 : 0);
if (!ifElse) return null; if (!ifElse) return null;
expr = Node.createTernaryExpression( expr = Node.createTernaryExpression(
expr, expr,

View File

@ -17,8 +17,8 @@
) )
(set_global $../../examples/game-of-life/assembly/game-of-life/s (set_global $../../examples/game-of-life/assembly/game-of-life/s
(i32.mul (i32.mul
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_local $0)
(get_global $../../examples/game-of-life/assembly/game-of-life/h) (get_local $1)
) )
) )
) )
@ -31,13 +31,13 @@
(local $5 i32) (local $5 i32)
(local $6 i32) (local $6 i32)
(local $7 i32) (local $7 i32)
(set_local $6 (set_local $5
(i32.sub (i32.sub
(get_global $../../examples/game-of-life/assembly/game-of-life/h) (get_global $../../examples/game-of-life/assembly/game-of-life/h)
(i32.const 1) (i32.const 1)
) )
) )
(set_local $7 (set_local $6
(i32.sub (i32.sub
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
(i32.const 1) (i32.const 1)
@ -45,22 +45,22 @@
) )
(loop $continue|0 (loop $continue|0
(if (if
(i32.lt_u (i32.lt_s
(get_local $0) (get_local $0)
(get_global $../../examples/game-of-life/assembly/game-of-life/h) (get_global $../../examples/game-of-life/assembly/game-of-life/h)
) )
(block (block
(set_local $4 (set_local $3
(select (select
(i32.sub (i32.sub
(get_local $0) (get_local $0)
(i32.const 1) (i32.const 1)
) )
(get_local $6) (get_local $5)
(get_local $0) (get_local $0)
) )
) )
(set_local $5 (set_local $4
(select (select
(i32.const 0) (i32.const 0)
(i32.add (i32.add
@ -69,7 +69,7 @@
) )
(i32.eq (i32.eq
(get_local $0) (get_local $0)
(get_local $6) (get_local $5)
) )
) )
) )
@ -78,7 +78,7 @@
) )
(loop $continue|1 (loop $continue|1
(if (if
(i32.lt_u (i32.lt_s
(get_local $1) (get_local $1)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
@ -94,7 +94,7 @@
(i32.load8_u (i32.load8_u
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $4) (get_local $3)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(tee_local $2 (tee_local $2
@ -103,7 +103,7 @@
(get_local $1) (get_local $1)
(i32.const 1) (i32.const 1)
) )
(get_local $7) (get_local $6)
(get_local $1) (get_local $1)
) )
) )
@ -112,7 +112,7 @@
(i32.load8_u (i32.load8_u
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $4) (get_local $3)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $1) (get_local $1)
@ -122,10 +122,10 @@
(i32.load8_u (i32.load8_u
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $4) (get_local $3)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(tee_local $3 (tee_local $7
(select (select
(i32.const 0) (i32.const 0)
(i32.add (i32.add
@ -134,7 +134,7 @@
) )
(i32.eq (i32.eq
(get_local $1) (get_local $1)
(get_local $7) (get_local $6)
) )
) )
) )
@ -157,14 +157,14 @@
(get_local $0) (get_local $0)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $3) (get_local $7)
) )
) )
) )
(i32.load8_u (i32.load8_u
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $5) (get_local $4)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $2) (get_local $2)
@ -174,7 +174,7 @@
(i32.load8_u (i32.load8_u
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $5) (get_local $4)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $1) (get_local $1)
@ -184,10 +184,10 @@
(i32.load8_u (i32.load8_u
(i32.add (i32.add
(i32.mul (i32.mul
(get_local $5) (get_local $4)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
(get_local $3) (get_local $7)
) )
) )
) )
@ -203,21 +203,17 @@
) )
) )
(if (if
(i32.and (i32.eqz
(if (result i32) (i32.or
(tee_local $3 (i32.eq
(i32.lt_s (get_local $2)
(get_local $2) (i32.const 2)
(i32.const 2)
)
) )
(get_local $3) (i32.eq
(i32.gt_s
(get_local $2) (get_local $2)
(i32.const 3) (i32.const 3)
) )
) )
(i32.const 1)
) )
(i32.store8 (i32.store8
(i32.add (i32.add

View File

@ -18,8 +18,8 @@
) )
(set_global $../../examples/game-of-life/assembly/game-of-life/s (set_global $../../examples/game-of-life/assembly/game-of-life/s
(i32.mul (i32.mul
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_local $0)
(get_global $../../examples/game-of-life/assembly/game-of-life/h) (get_local $1)
) )
) )
) )
@ -34,6 +34,7 @@
(local $7 i32) (local $7 i32)
(local $8 i32) (local $8 i32)
(local $9 i32) (local $9 i32)
(local $10 i32)
(block (block
(set_local $0 (set_local $0
(i32.sub (i32.sub
@ -54,7 +55,7 @@
) )
(loop $continue|0 (loop $continue|0
(if (if
(i32.lt_u (i32.lt_s
(get_local $2) (get_local $2)
(get_global $../../examples/game-of-life/assembly/game-of-life/h) (get_global $../../examples/game-of-life/assembly/game-of-life/h)
) )
@ -62,29 +63,29 @@
(block (block
(block (block
(set_local $3 (set_local $3
(select (if (result i32)
(i32.eq
(get_local $2)
(i32.const 0)
)
(get_local $0) (get_local $0)
(i32.sub (i32.sub
(get_local $2) (get_local $2)
(i32.const 1) (i32.const 1)
) )
(i32.eq
(get_local $2)
(i32.const 0)
)
) )
) )
(set_local $4 (set_local $4
(select (if (result i32)
(i32.eq
(get_local $2)
(get_local $0)
)
(i32.const 0) (i32.const 0)
(i32.add (i32.add
(get_local $2) (get_local $2)
(i32.const 1) (i32.const 1)
) )
(i32.eq
(get_local $2)
(get_local $0)
)
) )
) )
) )
@ -94,7 +95,7 @@
) )
(loop $continue|1 (loop $continue|1
(if (if
(i32.lt_u (i32.lt_s
(get_local $5) (get_local $5)
(get_global $../../examples/game-of-life/assembly/game-of-life/w) (get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
@ -102,29 +103,29 @@
(block (block
(block (block
(set_local $6 (set_local $6
(select (if (result i32)
(i32.eq
(get_local $5)
(i32.const 0)
)
(get_local $1) (get_local $1)
(i32.sub (i32.sub
(get_local $5) (get_local $5)
(i32.const 1) (i32.const 1)
) )
(i32.eq
(get_local $5)
(i32.const 0)
)
) )
) )
(set_local $7 (set_local $7
(select (if (result i32)
(i32.eq
(get_local $5)
(get_local $1)
)
(i32.const 0) (i32.const 0)
(i32.add (i32.add
(get_local $5) (get_local $5)
(i32.const 1) (i32.const 1)
) )
(i32.eq
(get_local $5)
(get_local $1)
)
) )
) )
) )
@ -216,7 +217,7 @@
) )
) )
) )
(if (set_local $9
(i32.load8_u (i32.load8_u
(i32.add (i32.add
(i32.mul (i32.mul
@ -226,54 +227,79 @@
(get_local $5) (get_local $5)
) )
) )
(if )
(i32.and (if
(if (result i32) (get_local $9)
(tee_local $9 (block $break|2
(i32.lt_s (block $case2|2
(block $case1|2
(block $case0|2
(set_local $10
(get_local $8) (get_local $8)
(i32.const 2)
) )
(br_if $case1|2
(i32.eq
(get_local $10)
(i32.const 2)
)
)
(br_if $case2|2
(i32.eq
(get_local $10)
(i32.const 3)
)
)
(br $case0|2)
) )
(get_local $9) (block
(i32.gt_s (i32.store8
(get_local $8) (i32.add
(i32.const 3) (i32.add
(get_global $../../examples/game-of-life/assembly/game-of-life/s)
(i32.mul
(get_local $2)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
)
(get_local $5)
)
(i32.const 0)
)
(br $break|2)
) )
) )
(i32.const 1)
)
(i32.store8
(i32.add
(i32.add
(get_global $../../examples/game-of-life/assembly/game-of-life/s)
(i32.mul
(get_local $2)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
)
(get_local $5)
)
(i32.const 0)
) )
) )
(if (block $break|3
(i32.eq (block $case1|3
(get_local $8) (block $case0|3
(i32.const 3) (set_local $10
) (get_local $8)
(i32.store8 )
(i32.add (br_if $case0|3
(i32.add (i32.eq
(get_global $../../examples/game-of-life/assembly/game-of-life/s) (get_local $10)
(i32.mul (i32.const 3)
(get_local $2)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
) )
) )
(get_local $5) (br $case1|3)
)
(block
(i32.store8
(i32.add
(i32.add
(get_global $../../examples/game-of-life/assembly/game-of-life/s)
(i32.mul
(get_local $2)
(get_global $../../examples/game-of-life/assembly/game-of-life/w)
)
)
(get_local $5)
)
(i32.const 1)
)
(br $break|3)
) )
(i32.const 1)
) )
) )
) )

View File

@ -6,30 +6,30 @@
(export "memory" (memory $0)) (export "memory" (memory $0))
(start $start) (start $start)
(func $start (; 0 ;) (type $v) (func $start (; 0 ;) (type $v)
(if (drop
(i32.const 0)
(unreachable)
(drop
(i32.const 1)
)
)
(if
(i32.const 1)
(drop
(i32.const 1)
)
(unreachable)
)
(if
(if (result i32) (if (result i32)
(i32.const 0) (i32.const 0)
(unreachable) (unreachable)
(i32.const 1) (i32.const 1)
) )
(drop )
(drop
(if (result i32)
(i32.const 1) (i32.const 1)
(i32.const 1)
(unreachable)
)
)
(drop
(if (result i32)
(if (result i32)
(i32.const 0)
(unreachable)
(i32.const 1)
)
(i32.const 1)
(unreachable)
) )
(unreachable)
) )
(set_global $ternary/a (set_global $ternary/a
(if (result i32) (if (result i32)