GitLab will be upgraded on June 2nd 2020 at 2.00 pm (AEDT) to 3.00 pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to local Gitlab admin team.

Commit ac4beb8f authored by Kunshan Wang's avatar Kunshan Wang

Test recursive Mu-C calls

parent 77e72680
......@@ -35,7 +35,7 @@ class UvmInterpreterNativeCallbackTests extends UvmBundleTesterBase {
hCBAddr should not be 0L
val nativeFuncAddr = libCallbacktest.getSymbolAddress("one_level")
assert(nativeFuncAddr != 0L)
nativeFuncAddr should not be 0L
val hFP = ca.putPointer("@one_level.fp", nativeFuncAddr)
......@@ -90,7 +90,7 @@ class UvmInterpreterNativeCallbackTests extends UvmBundleTesterBase {
val ca = microVM.newClientAgent()
val nativeFuncAddr = libCallbacktest.getSymbolAddress("one_level")
assert(nativeFuncAddr != 0L)
nativeFuncAddr should not be 0L
val hFP = ca.putPointer("@one_level.fp", nativeFuncAddr)
......@@ -178,7 +178,7 @@ class UvmInterpreterNativeCallbackTests extends UvmBundleTesterBase {
hCBAddr should not be 0L
val nativeFuncAddr = libCallbacktest.getSymbolAddress("one_level")
assert(nativeFuncAddr != 0L)
nativeFuncAddr should not be 0L
val hFP = ca.putPointer("@one_level.fp", nativeFuncAddr)
......@@ -232,4 +232,85 @@ class UvmInterpreterNativeCallbackTests extends UvmBundleTesterBase {
ca.close()
}
"The exposing definition" should "allow multi-level nested/recursive Mu-native calls" in {
val ca = microVM.newClientAgent()
val hPongFP = ca.putExpFunc("@pong.exposed")
val pongAddr = ca.toPointer(hPongFP)
println("Exposed Mu func (pong) addr: 0x%x".format(pongAddr))
pongAddr should not be 0L
val pingAddr = libCallbacktest.getSymbolAddress("ping")
println("Native func (ping) addr: 0x%x".format(pingAddr))
pingAddr should not be 0L
val hPingFP = ca.putPointer("@PingPong.fp", pingAddr)
val hPongTest = ca.putFunction("@pong_test")
val initialV = ca.putInt("@i32", 10)
var pongCalled: Int = 0
testFunc(ca, hPongTest, Seq(initialV, hPingFP)) { (ca, th, st, wp) =>
ca.nameOf(ca.currentInstruction(st, 0)) match {
case "@pong.v1.entrytrap" => {
val Seq(v, peer) = ca.dumpKeepalives(st, 0)
val vInt = ca.toInt(v).toInt
val peerAddr = ca.toPointer(peer)
pongCalled += 1
printf("Pong called. v=%d, peer=0x%x\n", vInt, peerAddr)
vInt shouldBe (pongCalled match {
case 1 => 10
case 2 => 8
case 3 => 6
case 4 => 4
case 5 => 2
case 6 => 0
})
ca.toPointer(peer) shouldEqual pingAddr
TrapRebindPassVoid(st)
}
case "@pong.v1.resptrap" => {
val Seq(v, resp) = ca.dumpKeepalives(st, 0)
val vInt = ca.toInt(v).toInt
val respInt = ca.toInt(resp).toInt
respInt shouldBe (vInt match {
case 10 => 362880
case 8 => 5040
case 6 => 120
case 4 => 6
case 2 => 1
})
TrapRebindPassVoid(st)
}
case "@pong_test.v1.entrytrap" => {
val Seq(v, peer) = ca.dumpKeepalives(st, 0)
ca.toInt(v).toInt shouldEqual 10
ca.toPointer(peer) shouldEqual pingAddr
TrapRebindPassVoid(st)
}
case "@pong_test.v1.exittrap" => {
val Seq(rv) = ca.dumpKeepalives(st, 0)
ca.toInt(rv).toInt shouldEqual 3628800
TrapRebindPassVoid(st)
}
}
}
pongCalled shouldBe 6
ca.close()
}
}
\ No newline at end of file
......@@ -12,3 +12,19 @@ double one_level(double v1, DoubleToDouble cb) {
v3 = cb(v1+1.0);
return v2 + v3;
}
//typedef int (*PingPong)(int v, PingPong cb); // ERROR
typedef void (*AnyFunc)(); // workaround
typedef int (*PingPong)(int v, AnyFunc cb); // workaround
int ping(int v, PingPong cb) {
printf("[C:ping] v=%d, cb=%p\n", v, cb);
if (v == 0) {
return 1;
} else {
PingPong cbPingPong = (PingPong)cb;
AnyFunc selfAnyFunc = (AnyFunc)ping;
return v * cbPingPong(v-1, selfAnyFunc);
}
}
......@@ -193,3 +193,33 @@
%trap = TRAP <@void> KEEPALIVE (%fp %rv)
COMMINST @uvm.thread_exit
}
.funcsig @PingPong.sig = @i32 (@i32 @PingPong.fp)
.typedef @PingPong.fp = funcptr<@PingPong.sig>
.funcdef @pong VERSION @pong.v1 <@PingPong.sig> (%v %peer) {
%entry:
%entrytrap = TRAP<@void> KEEPALIVE (%v %peer)
%check_zero = EQ <@i32> %v @I32_0
BRANCH2 %check_zero %is_zero %not_zero
%is_zero:
RET <@i32> @I32_1
%not_zero:
%nextv = SUB <@i32> %v @I32_1
%resp = CCALL #DEFAULT <@PingPong.fp @PingPong.sig> %peer (%nextv @pong.exposed)
%resptrap = TRAP<@void> KEEPALIVE (%v %resp)
%rv = MUL <@i32> %resp %v
RET <@i32> %rv
}
.expose @pong.exposed = @pong #DEFAULT @I64_0
.funcdef @pong_test VERSION @pong_test.v1 <@PingPong.sig> (%v %peer) {
%entry:
%entrytrap = TRAP<@void> KEEPALIVE (%v %peer)
%rv = CALL <@PingPong.sig> @pong (%v %peer)
%exittrap = TRAP<@void> KEEPALIVE (%rv)
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