Commit 1dc55f78 authored by Kunshan Wang's avatar Kunshan Wang

THROW AND LANDINGPAD

parent b80efcce
......@@ -387,6 +387,15 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
continueNormally()
}
case i @ InstThrow(excVal) => {
val exc = boxOf(excVal).asInstanceOf[BoxRef].objRef
curStack.popFrame()
catchException(exc)
}
case i @ InstLandingPad() => throw new UvmRefImplException(ctx + "LANDINGPAD instructions reached in normal execution, " +
"but LANDINGPAD must only appear in the beginning of basic blocks and not in the entry block.")
// Indentation guide: Insert more instructions here.
case i @ InstTrap(retTy, excClause, keepAlives) => {
......
......@@ -765,12 +765,51 @@ class UvmInterpreterSpec extends FlatSpec with Matchers {
val a0 = ca.putInt("@i64", 3)
val a1 = ca.putInt("@i64", 4)
testFunc(ca, func, Seq(a0, a1)) { (ca, th, st, wp) =>
val Seq(ss) = ca.dumpKeepalives(st, 0)
ss.vb.asInt shouldEqual 25
TrapRebindPassVoid(st)
}
ca.close()
}
"CALL, THROW and LANDINGPAD" should "handle exceptions" in {
val ca = microVM.newClientAgent()
val func = ca.putFunction("@call_throw")
val a0 = ca.putInt("@i64", 3)
testFunc(ca, func, Seq(a0)) { (ca, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match {
case "@call_throw_v1.trapnor" => {
val Seq(rv) = ca.dumpKeepalives(st, 0)
rv.vb.asInt shouldEqual 3
}
case "@call_throw_v1.trapexc" => {
fail("Should not receive exception")
}
}
TrapRebindPassVoid(st)
}
val a1 = ca.putInt("@i64", 0)
testFunc(ca, func, Seq(a1)) { (ca, th, st, wp) =>
nameOf(ca.currentInstruction(st, 0)) match {
case "@call_throw_v1.trapnor" => {
fail("Should not return normally")
}
case "@call_throw_v1.trapexc" => {
val Seq(lp) = ca.dumpKeepalives(st, 0)
lp.vb.asRef shouldEqual 0L
}
}
TrapRebindPassVoid(st)
}
ca.close()
......
......@@ -68,6 +68,7 @@
.const @2xD_V1 <@2xdouble> = VEC {@D_0 @D_1}
.const @2xD_V2 <@2xdouble> = VEC {@D_2 @D_3}
.funcsig @i_i = @i64 (@i64)
.funcsig @i_ii = @i64 (@i64 @i64)
.typedef @refvoid = ref<@void>
......@@ -420,25 +421,28 @@
COMMINST @uvm.thread_exit
}
// .funcsig @thrower_sig = @noparamsnoret
// .funcdef @thrower VERSION @thrower_v1 <@thrower_sig> () {
// %entry:
// THROW @NULLREF
// }
//
// .funcsig @invoke_landingpad_sig = @noparamsnoret
// .funcdef @invoke_landingpad VERSION @invoke_landingpad_v1 <@invoke_landingpad_sig> () {
// %entry:
// %ss = INVOKE <@noparamsnoret> @thrower () %nor %exc
// %nor:
// %trapnor = TRAP <@void> %exit %exit KEEPALIVE ()
// %exc:
// %lp = LANDINGPAD
// %trapexc = TRAP <@void> %exit %exit KEEPALIVE (%lp)
// %exit:
// COMMINST @uvm.thread_exit
// }
//
.funcdef @thrower VERSION @thrower_v1 <@i_i> (%p0) {
%entry:
%n0 = NE <@i64> %p0 @I64_0
BRANCH2 %n0 %nz %z
%nz:
RET <@i64> %p0
%z:
THROW @NULLREF
}
.funcdef @call_throw VERSION @call_throw_v1 <@i_i> (%p0) {
%entry:
%rv = CALL <@i_i> @thrower (%p0) EXC(%nor %exc)
%nor:
%trapnor = TRAP <@void> EXC(%exit %exit) KEEPALIVE (%rv)
%exc:
%lp = LANDINGPAD
%trapexc = TRAP <@void> EXC(%exit %exit) KEEPALIVE (%lp)
%exit:
COMMINST @uvm.thread_exit
}
// // Some simple struct constants
//
// .typedef @StructFoo = struct <@i32 @i64 @float @double>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment