Skip to content

Commit

Permalink
fix ret (#55)
Browse files Browse the repository at this point in the history
* a failed test case

* update tribonacci.wat

* fix and test return behavior

* validation of return.wat

* `trail` is local jump table (#56)

* use rust compiled tribonacci.wat(a data section involved)

* keep both versions of tribonacci

---------

Co-authored-by: butterunderflow <[email protected]>
Co-authored-by: butterunderflow <[email protected]>
  • Loading branch information
3 people authored Oct 13, 2024
1 parent ea20ef7 commit 87db8a2
Show file tree
Hide file tree
Showing 6 changed files with 146 additions and 10 deletions.
13 changes: 8 additions & 5 deletions benchmarks/wasm/return.wat
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
(module
(type (;0;) (func))
(func (;0;) (type 0)
block ;; label = @1
(type (;1;) (func (result i32)))
(func (type 1)
block
i32.const 42
return
end
unreachable
i32.const 100
)
(func (;1;) (type 0)
(func (type 0)
call 0
unreachable
)
(start 1)
)
)
43 changes: 43 additions & 0 deletions benchmarks/wasm/tribonacci.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
(module
(type (;0;) (func (param i32) (result i32)))
(type (;1;) (func (result i32)))
(func (;0;) (type 0) (param i32) (result i32)
local.get 0
if (result i32) ;; label = @1
local.get 0
i32.const 1
i32.eq
if (result i32) ;; label = @2
i32.const 1
else
local.get 0
i32.const 2
i32.eq
if (result i32) ;; label = @3
i32.const 1
else
local.get 0
i32.const 1
i32.sub
call 0
local.get 0
i32.const 2
i32.sub
call 0
i32.add
local.get 0
i32.const 3
i32.sub
call 0
i32.add
end
end
else
i32.const 0
end)
(func (;1;) (type 1) (result i32)
i32.const 12
call 0)
(start 1)
(memory (;0;) 0)
(export "memory" (memory 0)))
13 changes: 13 additions & 0 deletions benchmarks/wasm/tribonacci_ret.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#[no_mangle]
#[inline(never)]
fn tribonacci(n: i32) -> i32 {
if n == 0 { 0 }
else if n == 1 { 1 }
else if n == 2 { 1 }
else { tribonacci(n - 1) + tribonacci(n - 2) + tribonacci(n - 3) }
}

#[no_mangle]
fn real_main() -> i32 {
tribonacci(12)
}
68 changes: 68 additions & 0 deletions benchmarks/wasm/tribonacci_ret.wat
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
(module $tribonacci.wat.temp
(type (;0;) (func (param i32) (result i32)))
(type (;1;) (func (result i32)))
(func $tribonacci (type 0) (param i32) (result i32)
(local i32 i32)
local.get 0
i32.const 2
i32.shl
i32.const 1048576
i32.add
local.set 1
i32.const 0
local.set 2
local.get 0
local.set 0
loop (result i32) ;; label = @1
local.get 2
local.set 2
local.get 1
local.set 1
block ;; label = @2
local.get 0
local.tee 0
i32.const 2
i32.gt_u
br_if 0 (;@2;)
local.get 1
i32.load
local.get 2
i32.add
return
end
local.get 1
i32.const -12
i32.add
local.set 1
local.get 0
i32.const -1
i32.add
call $tribonacci
local.get 0
i32.const -2
i32.add
call $tribonacci
i32.add
local.get 2
i32.add
local.set 2
local.get 0
i32.const -3
i32.add
local.set 0
br 0 (;@1;)
end)
(func $real_main (type 1) (result i32)
i32.const 12
call $tribonacci)
(table (;0;) 1 1 funcref)
(memory (;0;) 17)
(global $__stack_pointer (mut i32) (i32.const 1048576))
(global (;1;) i32 (i32.const 1048588))
(global (;2;) i32 (i32.const 1048592))
(export "memory" (memory 0))
(export "tribonacci" (func $tribonacci))
(export "real_main" (func $real_main))
(export "__data_end" (global 1))
(export "__heap_base" (global 2))
(data $.rodata (i32.const 1048576) "\00\00\00\00\01\00\00\00\01\00\00\00"))
6 changes: 4 additions & 2 deletions src/main/scala/wasm/MiniWasm.scala
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ import gensym.wasm.memory._
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.HashMap

case class Trap() extends Exception

case class ModuleInstance(
types: List[FuncType],
funcs: HashMap[Int, WIR],
Expand Down Expand Up @@ -259,7 +261,7 @@ object Evaluator {
eval(rest, I32V(value) :: newStack, frame, kont, trail, ret)
case Nop =>
eval(rest, stack, frame, kont, trail, ret)
case Unreachable => throw new RuntimeException("Unreachable")
case Unreachable => throw Trap()
case Block(ty, inner) =>
val k: Cont[Ans] = (retStack) =>
eval(rest, retStack.take(ty.toList.size) ++ stack, frame, kont, trail, ret)
Expand Down Expand Up @@ -302,7 +304,7 @@ object Evaluator {
eval(rest, retStack.take(ty.out.size) ++ newStack, frame, kont, trail, ret)
// We push newK on the trail since function creates a new block to escape
// (more or less like `return`)
eval(body, List(), newFrame, newK, newK :: trail, ret+1)
eval(body, List(), newFrame, newK, List(newK), 0)
case Call(f) if frame.module.funcs(f).isInstanceOf[Import] =>
frame.module.funcs(f) match {
case Import("console", "log", _) =>
Expand Down
13 changes: 10 additions & 3 deletions src/test/scala/genwasym/TestEval.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,6 @@ import collection.mutable.ArrayBuffer
import org.scalatest.FunSuite

class TestEval extends FunSuite {

// Mostly testing the files generated form `benchmarks/wasm/test.rs`
def testFile(filename: String,
main: Option[String] = None,
expected: Option[Int] = None) = {
Expand All @@ -40,10 +38,19 @@ class TestEval extends FunSuite {
test("fact") { testFile("./benchmarks/wasm/fact.wat", None, Some(120)) }
test("loop") { testFile("./benchmarks/wasm/loop.wat", None, Some(10)) }
test("even-odd") { testFile("./benchmarks/wasm/even_odd.wat", None, Some(1)) }
test("return") { testFile("./benchmarks/wasm/return.wat", None, None) }
test("load") { testFile("./benchmarks/wasm/load.wat", None, Some(1)) }
test("btree") { testFile("./benchmarks/wasm/btree/2o1u-unlabeled.wat") }
test("fib") { testFile("./benchmarks/wasm/fib.wat", None, Some(144)) }
test("tribonacci") { testFile("./benchmarks/wasm/tribonacci.wat", None, Some(504)) }

test("return") {
intercept[gensym.wasm.miniwasm.Trap] {
testFile("./benchmarks/wasm/return.wat", None, None)
}
}

// FIXME:
//test("tribonacci-ret") { testFile("./benchmarks/wasm/tribonacci_ret.wat", None, Some(504)) }

// TODO: add wasm spec tests? How to utilize wast files?
}

0 comments on commit 87db8a2

Please sign in to comment.