Commit fd391284 authored by Kunshan Wang's avatar Kunshan Wang

Tested coroutines, multithreading and tagref64.

parent f22f5539
......@@ -34,7 +34,7 @@ object InternalTypes {
val REF_VOID = TypeRef(VOID) := internal("ref_void")
val STACK = TypeStack() := internal("stack")
val THREAD = TypeStack() := internal("thread")
val THREAD = TypeThread() := internal("thread")
val TAGREF64 = TypeTagRef64() := internal("tagref64")
}
......
......@@ -733,7 +733,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
continueNormally()
}
case "@uvm.kill_thread" => {
case "@uvm.kill_stack" => {
val Seq(s) = argList
val sta = boxOf(s).asInstanceOf[BoxStack].stack.getOrElse {
throw new UvmRuntimeException(ctx + "Attempt to kill NULL stack.")
......
......@@ -72,4 +72,60 @@ class UvmInterpreterSimpleTests extends UvmBundleTesterBase {
ca.close()
}
"Coroutine test" should "work" in {
val ca = microVM.newClientAgent()
val func = ca.putFunction("@test_coroutine")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
val trapName = nameOf(ca.currentInstruction(st, 0))
trapName match {
case "@test_coroutine_v1.trap_body" => {
val Seq(v) = ca.dumpKeepalives(st, 0)
println(v.vb.asSInt(64))
TrapRebindPassVoid(st)
}
case "@test_coroutine_v1.trap_exit" => {
val Seq(exc) = ca.dumpKeepalives(st, 0)
val hsi = ca.putGlobal("@StopIteration")
val hrsi = ca.load(MemoryOrder.NOT_ATOMIC, hsi)
exc.vb.asRef shouldEqual hrsi.vb.asRef
TrapRebindPassVoid(st)
}
case _ => fail("Should not hit " + trapName)
}
}
ca.close()
}
"Multi-threading test" should "work" in {
val ca = microVM.newClientAgent()
val func = ca.putFunction("@test_multithreading")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
val trapName = nameOf(ca.currentInstruction(st, 0))
trapName match {
case "@test_multithreading_v1.trap_result" => {
val Seq(v) = ca.dumpKeepalives(st, 0)
v.vb.asSInt(64) shouldEqual 4950
TrapRebindPassVoid(st)
}
case _ => fail("Should not hit " + trapName)
}
}
ca.close()
}
}
\ No newline at end of file
......@@ -1060,7 +1060,7 @@ class UvmInterpreterSpec extends UvmBundleTesterBase {
val ca = microVM.newClientAgent()
val func = ca.putFunction("@testswapstack")
var coro1Reached = false
var coro2Reached = false
var main1Reached = false
......@@ -1089,7 +1089,7 @@ class UvmInterpreterSpec extends UvmBundleTesterBase {
val Seq(mss1) = ca.dumpKeepalives(st, 0)
mss1.vb.asSInt(64) shouldBe 3L
main1Reached = true
TrapRebindPassVoid(st)
}
......@@ -1097,21 +1097,46 @@ class UvmInterpreterSpec extends UvmBundleTesterBase {
val Seq(excVal) = ca.dumpKeepalives(st, 0)
excVal.vb.asSInt(64) shouldBe 7L
main2Reached = true
TrapRebindPassVoid(st)
}
}
}
coro1Reached shouldBe true
coro2Reached shouldBe true
main1Reached shouldBe true
main2Reached shouldBe true
fail()
ca.close()
}
"COMMINST @uvm.tr64.*" should "work" in {
val ca = microVM.newClientAgent()
val func = ca.putFunction("@testtr64")
testFunc(ca, func, Seq()) { (ca, th, st, wp) =>
val Seq(rv, f, i, r,
f_is_f, f_is_i, f_is_r, i_is_f, i_is_i, i_is_r, r_is_f, r_is_i, r_is_r,
fb, ib, rb, tb) = ca.dumpKeepalives(st, 0)
f.vb.asTR64Raw shouldBe OpHelper.fpToTr64(42.0d)
i.vb.asTR64Raw shouldBe OpHelper.intToTr64(0xfedcba9876543L)
r.vb.asTR64Raw shouldBe OpHelper.refToTr64(rv.vb.asRef, 31L)
(Seq(f_is_f, f_is_i, f_is_r, i_is_f, i_is_i, i_is_r, r_is_f, r_is_i, r_is_r).map(_.vb.asUInt(1)) shouldBe
Seq(1, 0, 0, 0, 1, 0, 0, 0, 1))
fb.vb.asDouble shouldBe 42.0d
ib.vb.asUInt(52) shouldBe 0xfedcba9876543L
rb.vb.asRef shouldBe rv.vb.asRef
tb.vb.asUInt(6) shouldBe 31L
TrapRebindPassVoid(st)
}
ca.close()
}
}
\ No newline at end of file
.typedef @i1 = int<1>
.typedef @i6 = int<6>
.typedef @i8 = int<8>
.typedef @i16 = int<16>
.typedef @i32 = int<32>
.typedef @i52 = int<52>
.typedef @i64 = int<64>
.typedef @float = float
.typedef @double = double
......@@ -794,153 +796,39 @@
COMMINST @uvm.thread_exit
}
// .typedef @irefi64 = iref<@i64>
//
// .typedef @irefstack = iref<@stack>
//
// .funcsig @itersig = @void (@i64 @stack @irefi64 @irefi64)
//
// .funcsig @rangeiter_sig = @itersig
// .funcdef @rangeiter VERSION @rangeiter_v1 <@rangeiter_sig> (%n %src %valueret %shouldstop) {
// %entry:
// BRANCH %head
//
// %head:
// %i = PHI <@i64> {
// %entry: 0;
// %body: %i2;
// }
// %lt = SLT <@i64> %i %n
// BRANCH2 %lt %body %exit
//
// %body:
// STORE <@i64> %valueret %i
// COMMINST @uvm.swap_stack (%src)
// %i2 = ADD <@i64> %i 1
// BRANCH %head
//
// %exit:
// STORE <@i64> %shouldstop 1
// COMMINST @uvm.swap_and_kill (%src)
// }
//
// .const @I64_100 <@i64> = 100
// .const @I64_50 <@i64> = 50
// .const @I64_0 <@i64> = 0
// .typedef @LongAry = hybrid <@void @i64>
//
// .funcsig @testmultithreading_sig = @noparamsnoret
// .funcdef @testmultithreading VERSION @testmultithreading_v1 <@testmultithreading_sig> () {
// %entry:
// %ary_r = NEWHYBRID <@LongAry> @I64_100
// %ary_ir = GETIREF <@LongAry> %ary_r
// %ary0_ir = GETVARPARTIREF <@LongAry> %ary_ir
// BRANCH %head
//
// %head:
// %i = PHI <@i64> { %entry: 0; %body: %i2; }
// %cmp = SLT <@i64> %i @I64_100
// BRANCH2 %cmp %body %next
//
// %body:
// %aryi_ir = SHIFTIREF <@i64> %ary0_ir %i
// STORE <@i64> %aryi_ir %i
// %i2 = ADD <@i64> %i 1
// BRANCH %head
//
// %next:
// %result0 = ALLOCA <@i64>
// %sta0 = NEWSTACK <@summingslavesig> @summingslave (%ary0_ir @I64_50 %result0)
// %result1 = ALLOCA <@i64>
// %ary50_ir = SHIFTIREF <@i64> %ary0_ir @I64_50
// %sta1 = NEWSTACK <@summingslavesig> @summingslave (%ary50_ir @I64_50 %result1)
//
// %thr0 = COMMINST @uvm.new_thread (%sta0)
// %thr1 = COMMINST @uvm.new_thread (%sta1)
//
// BRANCH %wait0
//
// %wait0:
// %res0val = LOAD SEQ_CST <@i64> %result0
// %cz0 = EQ <@i64> %res0val @I64_0
// BRANCH2 %cz0 %wait0 %wait1
//
// %wait1:
// %res1val = LOAD SEQ_CST <@i64> %result1
// %cz1 = EQ <@i64> %res1val @I64_0
// BRANCH2 %cz1 %wait1 %getresult
//
// %getresult:
// %sum = ADD <@i64> %res0val %res1val
// TRAP <@void> KEEPALIVE (%sum)
//
// %exit:
// COMMINST @uvm.thread_exit
// }
//
// .funcsig @summingslavesig = @void (@irefi64 @i64 @irefi64)
//
// .funcsig @summingslave_sig = @summingslavesig
// .funcdef @summingslave VERSION @summingslave_v1 <@summingslave_sig> (%ary %sz %result) {
// %entry:
// BRANCH %head
//
// %head:
// %sum = PHI <@i64> { %entry: 0; %body: %sum2; }
// %i = PHI <@i64> { %entry: 0; %body: %i2; }
// %cmp = SLT <@i64> %i %sz
// BRANCH2 %cmp %body %exit
//
// %body:
// %curptr = SHIFTIREF <@i64> %ary %i
// %curnum = LOAD <@i64> %curptr
// %sum2 = ADD <@i64> %sum %curnum
// %i2 = ADD <@i64> %i 1
// BRANCH %head
//
// %exit:
// STORE SEQ_CST <@i64> %result %sum
// COMMINST @uvm.thread_exit
// }
//
// .typedef @i6 = int<6>
// .typedef @i52 = int<52>
//
// .const @I6_31 <@i6> = 31
// .const @I52_SAMPLE <@i52> = 0xfedcba9876543
// .const @D_42 <@double> = 42.0d
//
// .funcsig @testtr64_sig = @noparamsnoret
// .funcdef @testtr64 VERSION @testtr64_v1 <@testtr64_sig> () {
// %someobj = NEW <@i64>
// %rv = REFCAST <@refi64 @refvoid> %someobj
//
// %f = COMMINST @uvm.tr64.from_fp (@D_42)
// %i = COMMINST @uvm.tr64.from_int (@I52_SAMPLE)
// %r = COMMINST @uvm.tr64.from_ref (%rv @I6_31)
//
// %f_is_f = COMMINST @uvm.tr64.is_fp (%f)
// %f_is_i = COMMINST @uvm.tr64.is_int (%f)
// %f_is_r = COMMINST @uvm.tr64.is_ref (%f)
// %i_is_f = COMMINST @uvm.tr64.is_fp (%i)
// %i_is_i = COMMINST @uvm.tr64.is_int (%i)
// %i_is_r = COMMINST @uvm.tr64.is_ref (%i)
// %r_is_f = COMMINST @uvm.tr64.is_fp (%r)
// %r_is_i = COMMINST @uvm.tr64.is_int (%r)
// %r_is_r = COMMINST @uvm.tr64.is_ref (%r)
//
// %fb = COMMINST @uvm.tr64.to_fp (%f)
// %ib = COMMINST @uvm.tr64.to_int (%i)
// %rb = COMMINST @uvm.tr64.to_ref (%r)
// %rt = COMMINST @uvm.tr64.to_tag (%r)
//
// TRAP <@void> KEEPALIVE (%rv %f %i %r %f_is_f %f_is_i %f_is_r
// %i_is_f %i_is_i %i_is_r %r_is_f %r_is_i %r_is_r %fb %ib %rb %rt)
//
// %exit:
// COMMINST @uvm.thread_exit
// }
//
.const @I6_31 <@i6> = 31
.const @I52_SAMPLE <@i52> = 0xfedcba9876543
.const @D_42 <@double> = 42.0d
.funcdef @testtr64 VERSION @testtr64_v1 <@noparamsnoret> () {
%entry:
%someobj = NEW <@i64>
%rv = REFCAST <@refi64 @refvoid> %someobj
%f = COMMINST @uvm.tr64.from_fp (@D_42)
%i = COMMINST @uvm.tr64.from_int (@I52_SAMPLE)
%r = COMMINST @uvm.tr64.from_ref (%rv @I6_31)
%f_is_f = COMMINST @uvm.tr64.is_fp (%f)
%f_is_i = COMMINST @uvm.tr64.is_int (%f)
%f_is_r = COMMINST @uvm.tr64.is_ref (%f)
%i_is_f = COMMINST @uvm.tr64.is_fp (%i)
%i_is_i = COMMINST @uvm.tr64.is_int (%i)
%i_is_r = COMMINST @uvm.tr64.is_ref (%i)
%r_is_f = COMMINST @uvm.tr64.is_fp (%r)
%r_is_i = COMMINST @uvm.tr64.is_int (%r)
%r_is_r = COMMINST @uvm.tr64.is_ref (%r)
%fb = COMMINST @uvm.tr64.to_fp (%f)
%ib = COMMINST @uvm.tr64.to_int (%i)
%rb = COMMINST @uvm.tr64.to_ref (%r)
%rt = COMMINST @uvm.tr64.to_tag (%r)
TRAP <@void> KEEPALIVE (%rv %f %i %r %f_is_f %f_is_i %f_is_r
%i_is_f %i_is_i %i_is_r %r_is_f %r_is_i %r_is_r %fb %ib %rb %rt)
COMMINST @uvm.thread_exit
}
// ///////////////////////// Simple sum
//
// .funcsig @simplesum_sig = @void (@i64 @i64)
......
......@@ -9,6 +9,10 @@
.funcsig @noparamsnoret = @void ()
.typedef @thread = thread
.typedef @stack = stack
.typedef @tagref64 = tagref64
.const @TRUE <@i64> = 1
.const @FALSE <@i64> = 0
......@@ -26,3 +30,5 @@
.const @I64_1 <@i64> = 1
.const @I64_2 <@i64> = 2
.const @I64_10 <@i64> = 10
.const @I64_50 <@i64> = 50
.const @I64_100 <@i64> = 100
// require primitives.uir
// Factorial
.funcdef @factorial_rec VERSION @factorial_rec_v1 <@i_i> (%n) {
%entry:
%zero = EQ <@i64> %n @I64_0
......@@ -60,6 +62,8 @@
COMMINST @uvm.thread_exit
}
// Fibonacci
.funcdef @fibonacci_rec VERSION @fibonacci_rec_v1 <@i_i> (%n) {
%entry:
%zero = EQ <@i64> %n @I64_0
......@@ -167,3 +171,129 @@
)
COMMINST @uvm.thread_exit
}
// Coroutine iterator
.global @StopIteration <@refvoid>
.funcsig @itersig = @void (@i64 @stack)
.funcdef @rangeiter VERSION @rangeiter_v1 <@itersig> (%n %src) {
%entry:
BRANCH %head
%head:
%i = PHI <@i64> {
%entry: @I64_0;
%body: %i2;
}
%lt = SLT <@i64> %i %n
BRANCH2 %lt %body %exit
%body:
SWAPSTACK %src RET_WITH <@void> PASS_VALUE <@i64> %i
%i2 = ADD <@i64> %i @I64_1
BRANCH %head
%exit:
%stop_iteration = LOAD <@refvoid> @StopIteration
SWAPSTACK %src KILL_OLD THROW_EXC %stop_iteration
}
.funcdef @test_coroutine VERSION @test_coroutine_v1 <@noparamsnoret> () {
%entry:
%stop_iteration = NEW <@void>
STORE <@refvoid> @StopIteration %stop_iteration
%curstack = COMMINST @uvm.current_stack
%coro = NEWSTACK <@itersig> @rangeiter (@I64_10 %curstack)
BRANCH %head
%head:
%val = SWAPSTACK %coro RET_WITH <@i64> PASS_VOID EXC(%body %exit)
%body:
%trap_body = TRAP <@void> KEEPALIVE(%val)
BRANCH %head
%exit:
%exc = LANDINGPAD
%trap_exit = TRAP <@void> KEEPALIVE(%exc)
COMMINST @uvm.thread_exit
}
// Multi-threading
.typedef @LongAry = hybrid <@void @i64>
.funcsig @summingslave_sig = @void (@irefi64 @i64 @irefi64)
.funcdef @summingslave VERSION @summingslave_v1 <@summingslave_sig> (%ary %sz %result) {
%entry:
BRANCH %head
%head:
%sum = PHI <@i64> { %entry: @I64_0; %body: %sum2; }
%i = PHI <@i64> { %entry: @I64_0; %body: %i2; }
%cmp = SLT <@i64> %i %sz
BRANCH2 %cmp %body %exit
%body:
%curptr = SHIFTIREF <@i64 @i64> %ary %i
%curnum = LOAD <@i64> %curptr
%sum2 = ADD <@i64> %sum %curnum
%i2 = ADD <@i64> %i @I64_1
BRANCH %head
%exit:
STORE SEQ_CST <@i64> %result %sum
COMMINST @uvm.thread_exit
}
.funcdef @test_multithreading VERSION @test_multithreading_v1 <@noparamsnoret> () {
%entry:
%ary_r = NEWHYBRID <@LongAry @i64> @I64_100
%ary_ir = GETIREF <@LongAry> %ary_r
%ary0_ir = GETVARPARTIREF <@LongAry> %ary_ir
BRANCH %head
%head:
%i = PHI <@i64> { %entry: @I64_0; %body: %i2; }
%cmp = SLT <@i64> %i @I64_100
BRANCH2 %cmp %body %next
%body:
%aryi_ir = SHIFTIREF <@i64 @i64> %ary0_ir %i
STORE <@i64> %aryi_ir %i
%i2 = ADD <@i64> %i @I64_1
BRANCH %head
%next:
%result0 = ALLOCA <@i64>
%sta0 = NEWSTACK <@summingslave_sig> @summingslave (%ary0_ir @I64_50 %result0)
%result1 = ALLOCA <@i64>
%ary50_ir = SHIFTIREF <@i64 @i64> %ary0_ir @I64_50
%sta1 = NEWSTACK <@summingslave_sig> @summingslave (%ary50_ir @I64_50 %result1)
%thr0 = COMMINST @uvm.new_thread (%sta0)
%thr1 = COMMINST @uvm.new_thread (%sta1)
BRANCH %wait0
%wait0:
%res0val = LOAD SEQ_CST <@i64> %result0
%cz0 = EQ <@i64> %res0val @I64_0
BRANCH2 %cz0 %wait0 %wait1
%wait1:
%res1val = LOAD SEQ_CST <@i64> %result1
%cz1 = EQ <@i64> %res1val @I64_0
BRANCH2 %cz1 %wait1 %getresult
%getresult:
%sum = ADD <@i64> %res0val %res1val
%trap_result = TRAP <@void> KEEPALIVE (%sum)
COMMINST @uvm.thread_exit
}
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