diff --git a/Makefile b/Makefile index d6e2d54..6832ada 100644 --- a/Makefile +++ b/Makefile @@ -1,6 +1,6 @@ WASM2WAT=wasm2wat WAT2WASM=wat2wasm -WAT2WASM_FLAGS= +WAT2WASM_FLAGS=--enable-mutable-globals ifeq ($(DEBUG),1) WAT2WASM_FLAGS=--debug-names endif diff --git a/src/shell/WAForth.js b/src/shell/WAForth.js index f24a72c..9cbfdb0 100644 --- a/src/shell/WAForth.js +++ b/src/shell/WAForth.js @@ -25,6 +25,7 @@ class WAForth { const { skipPrelude } = options; let table; let memory; + let tos; const buffer = (this.buffer = []); return WebAssembly.instantiate(this.wasmModule, { @@ -89,7 +90,7 @@ class WAForth { // console.log("Load", index, this.arrayToBase64(data)); var module = new WebAssembly.Module(data); new WebAssembly.Instance(module, { - env: { table, memory, tos: -1 } + env: { table, memory, tos } }); } } @@ -97,6 +98,7 @@ class WAForth { this.core = instance.instance; table = this.core.exports.table; memory = this.core.exports.memory; + tos = this.core.exports.tos; if (!skipPrelude) { this.core.exports.loadPrelude(); } diff --git a/src/tools/quadruple.wat b/src/tools/quadruple.wat index eff6fb9..3c0e236 100644 --- a/src/tools/quadruple.wat +++ b/src/tools/quadruple.wat @@ -3,7 +3,7 @@ (module $quadruple (import "env" "table" (table 4 anyfunc)) (import "env" "memory" (memory 1)) - (import "env" "tos" (global $tos i32)) + (import "env" "tos" (global $tos (mut i32))) (type $void (func)) (type $push (func (param i32))) @@ -16,13 +16,16 @@ (local $incr1 i32) ;; Push - (call_indirect (type $push) (i32.const 43) (i32.const 1)) + (i32.store (get_global $tos) (i32.const 43)) + (set_global $tos (i32.add (get_global $tos) (i32.const 4))) ;; Word call (call_indirect (type $push) (i32.const 10) (i32.const 9)) ;; Conditional - (if (i32.ne (call_indirect (type $pop) (i32.const 2)) (i32.const 0)) + (i32.load (get_global $tos)) + (set_global $tos (i32.sub (get_global $tos) (i32.const 4))) + (if (i32.ne (i32.const 0)) (then (nop) (nop)) diff --git a/src/waforth.wat b/src/waforth.wat index 9d537d8..0879b69 100644 --- a/src/waforth.wat +++ b/src/waforth.wat @@ -56,7 +56,7 @@ "\u0003\u0065\u006E\u0076" "\u0006\u006d\u0065\u006d\u006f\u0072\u0079" ;; 'env' . 'memory' "\u0002" "\u0000" "\u0001" ;; memory "\u0003\u0065\u006E\u0076" "\u0003\u0074\u006f\u0073" ;; 'env' . 'tos' - "\u0003" "\u007F" "\u0000" ;; global, i32, immutable + "\u0003" "\u007F" "\u0001" ;; global, i32, mutable "\u0003" "\u0002" ;; Function section @@ -109,6 +109,9 @@ (define !compileCallIndex 7) (define !tableStartIndex 8) +;; Predefined imported globals +(define !tosIndex 0) + (define !dictionaryLatest 0) (define !dictionaryTop !dictionaryBase) @@ -179,7 +182,7 @@ (type $word (func)) (type $dataWord (func (param i32))) - (global $tos (mut i32) (i32.const !stackBase)) + (global $tos (export "tos") (mut i32) (i32.const !stackBase)) (global $tors (mut i32) (i32.const !returnStackBase)) (global $inputBufferSize (mut i32) (i32.const 0)) (global $inputBufferBase (mut i32) (i32.const !inputBufferBase)) @@ -1873,10 +1876,40 @@ EOF (set_global $cp (i32.add (get_global $cp) (i32.const 1))) (set_global $cp (call $leb128 (get_global $cp) (get_local $n)))) + (func $emitSetGlobal (param $n i32) + (i32.store8 (get_global $cp) (i32.const 0x24)) + (set_global $cp (i32.add (get_global $cp) (i32.const 1))) + (set_global $cp (call $leb128 (get_global $cp) (get_local $n)))) + + (func $emitGetGlobal (param $n i32) + (i32.store8 (get_global $cp) (i32.const 0x23)) + (set_global $cp (i32.add (get_global $cp) (i32.const 1))) + (set_global $cp (call $leb128 (get_global $cp) (get_local $n)))) + + (func $emitStore + (i32.store8 (get_global $cp) (i32.const 0x36)) + (set_global $cp (i32.add (get_global $cp) (i32.const 1))) + (i32.store8 (get_global $cp) (i32.const 0x02)) + (set_global $cp (i32.add (get_global $cp) (i32.const 1))) + (i32.store8 (get_global $cp) (i32.const 0x00)) + (set_global $cp (i32.add (get_global $cp) (i32.const 1)))) + + (func $emitLoad + (i32.store8 (get_global $cp) (i32.const 0x28)) + (set_global $cp (i32.add (get_global $cp) (i32.const 1))) + (i32.store8 (get_global $cp) (i32.const 0x02)) + (set_global $cp (i32.add (get_global $cp) (i32.const 1))) + (i32.store8 (get_global $cp) (i32.const 0x00)) + (set_global $cp (i32.add (get_global $cp) (i32.const 1)))) + (func $emitAdd (i32.store8 (get_global $cp) (i32.const 0x6a)) (set_global $cp (i32.add (get_global $cp) (i32.const 1)))) + (func $emitSub + (i32.store8 (get_global $cp) (i32.const 0x6b)) + (set_global $cp (i32.add (get_global $cp) (i32.const 1)))) + (func $emitEqualsZero (i32.store8 (get_global $cp) (i32.const 0x45)) (set_global $cp (i32.add (get_global $cp) (i32.const 1)))) @@ -2074,47 +2107,62 @@ EOF (call $here) (call $over) (call $erase) - (call $push (i32.const 2)) + (i32.store (get_global $tos) (i32.const 2)) + (set_global $tos (i32.add (get_global $tos) (i32.const 4))) (block $endLoop1 (loop $loop1 (call $two-dupe) (call $dupe) (call $star) (call $greater-than) - (br_if $endLoop1 (i32.eqz (call $pop))) + (set_global $tos (i32.sub (get_global $tos) (i32.const 4))) + (br_if $endLoop1 (i32.eqz (i32.load (get_global $tos)))) (call $dupe) (call $sieve_prime) - (if (i32.ne (call $pop) (i32.const 0)) + (set_global $tos (i32.sub (get_global $tos) (i32.const 4))) + (if (i32.ne (i32.load (get_global $tos)) (i32.const 0)) (block (call $two-dupe) (call $dupe) (call $star) - (set_local $i (call $pop)) - (set_local $end (call $pop)) + (set_global $tos (i32.sub (get_global $tos) (i32.const 4))) + (set_local $i (i32.load (get_global $tos))) + (set_global $tos (i32.sub (get_global $tos) (i32.const 4))) + (set_local $end (i32.load (get_global $tos))) (block $endLoop2 (loop $loop2 - (call $push (get_local $i)) + (i32.store (get_global $tos) (get_local $i)) + (set_global $tos (i32.add (get_global $tos) (i32.const 4))) (call $sieve_composite) (call $dupe) - (set_local $i (i32.add (call $pop) (get_local $i))) + (set_global $tos (i32.sub (get_global $tos) (i32.const 4))) + (set_local $i (i32.add (i32.load (get_global $tos)) (get_local $i))) (br_if $endLoop2 (i32.ge_s (get_local $i) (get_local $end))) (br $loop2))))) (call $one-plus) (br $loop1))) (call $drop) - (call $push (i32.const 1)) + (i32.store (get_global $tos) (i32.const 1)) + (set_global $tos (i32.add (get_global $tos) (i32.const 4))) (call $swap) - (call $push (i32.const 2)) - (set_local $i (call $pop)) - (set_local $end (call $pop)) + (i32.store (get_global $tos) (i32.const 2)) + (set_global $tos (i32.add (get_global $tos) (i32.const 4))) + + (set_global $tos (i32.sub (get_global $tos) (i32.const 4))) + (set_local $i (i32.load (get_global $tos))) + (set_global $tos (i32.sub (get_global $tos) (i32.const 4))) + (set_local $end (i32.load (get_global $tos))) (block $endLoop3 (loop $loop3 - (call $push (get_local $i)) + (i32.store (get_global $tos) (get_local $i)) + (set_global $tos (i32.add (get_global $tos) (i32.const 4))) (call $sieve_prime) - (if (i32.ne (call $pop) (i32.const 0)) + (set_global $tos (i32.sub (get_global $tos) (i32.const 4))) + (if (i32.ne (i32.load (get_global $tos)) (i32.const 0)) (block (call $drop) - (call $push (get_local $i)))) + (i32.store (get_global $tos) (get_local $i)) + (set_global $tos (i32.add (get_global $tos) (i32.const 4))))) (set_local $i (i32.add (i32.const 1) (get_local $i))) (br_if $endLoop3 (i32.ge_s (get_local $i) (get_local $end))) (br $loop3)))) @@ -2141,9 +2189,6 @@ EOF (data (i32.const !moduleHeaderBase) !moduleHeader) (data (i32.const !preludeDataBase) !preludeData) - (func (export "tos") (result i32) - (get_global $tos)) - (func (export "interpret") (result i32) (local $result i32) (call $refill) diff --git a/tests/tests.js b/tests/tests.js index e5b12c9..7cdfc26 100644 --- a/tests/tests.js +++ b/tests/tests.js @@ -100,14 +100,14 @@ function loadTests(wasmModule, arrayToBase64) { function here() { run("HERE"); - const result = memory[core.tos() / 4 - 1]; + const result = memory[core.tos.value / 4 - 1]; run("DROP"); return result; } function latest() { run("LATEST"); - const result = memory[core.tos() / 4 - 1]; + const result = memory[core.tos.value / 4 - 1]; run("DROP"); return result; }