GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

Commit bcb40c0c authored by Kunshan Wang's avatar Kunshan Wang

Implement comparison of general reference types.

Including ref, iref, func and stack. There is currently no way to get
Thread values.
parent c932ca84
......@@ -201,11 +201,63 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
writeBooleanResult(result, br)
}
def doRef(b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
val op1v = b1.asInstanceOf[BoxRef].objRef
val op2v = b2.asInstanceOf[BoxRef].objRef
val result = op match {
case CmpOptr.EQ => op1v == op2v
case CmpOptr.NE => op1v != op2v
case _ => throw new UvmRuntimeException(ctx + "Comparison %s not suitable for reference type %s".format(op, opndTy))
}
writeBooleanResult(result, br)
}
def doIRef(b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
val op1v = b1.asInstanceOf[BoxIRef].oo
val op2v = b2.asInstanceOf[BoxIRef].oo
val result = op match {
case CmpOptr.EQ => op1v == op2v
case CmpOptr.NE => op1v != op2v
case _ => throw new UvmRuntimeException(ctx + "Comparison %s not suitable for internal reference type %s".format(op, opndTy))
}
writeBooleanResult(result, br)
}
def doFunc(b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
val op1v = b1.asInstanceOf[BoxFunc].func
val op2v = b2.asInstanceOf[BoxFunc].func
val result = op match {
case CmpOptr.EQ => op1v == op2v
case CmpOptr.NE => op1v != op2v
case _ => throw new UvmRuntimeException(ctx + "Comparison %s not suitable for function type %s".format(op, opndTy))
}
writeBooleanResult(result, br)
}
def doStack(b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
val op1v = b1.asInstanceOf[BoxStack].stack
val op2v = b2.asInstanceOf[BoxStack].stack
val result = op match {
case CmpOptr.EQ => op1v == op2v
case CmpOptr.NE => op1v != op2v
case _ => throw new UvmRuntimeException(ctx + "Comparison %s not suitable for stack type %s".format(op, opndTy))
}
writeBooleanResult(result, br)
}
def doScalar(scalarTy: Type, b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
scalarTy match {
case TypeInt(l) => doInt(l, b1, b2, br)
case TypeFloat() => doFloat(b1, b2, br)
case TypeDouble() => doDouble(b1, b2, br)
case TypeRef(_) => doRef(b1, b2, br)
case TypeIRef(_) => doIRef(b1, b2, br)
case TypeFunc(_) => doFunc(b1, b2, br)
case TypeStack() => doStack(b1, b2, br)
case _ => throw new UvmRuntimeException(ctx + "Comparison not suitable for type %s".format(opndTy))
}
}
......
......@@ -557,7 +557,89 @@ class UvmInterpreterSpec extends UvmBundleTesterBase {
}
ca.close()
}
"Comparing operations" should "work on general reference types" in {
val ca = microVM.newClientAgent()
val func = ca.putFunction("@cmp_ref")
val a0 = ca.newFixed("@i64")
val a1 = ca.newFixed("@i64")
val a2 = ca.putGlobal("@dummy_global1")
val a3 = ca.putGlobal("@dummy_global2")
val a4 = ca.putFunction("@dummy_func1")
val a5 = ca.putFunction("@dummy_func2")
val a6 = ca.newStack(a5, Seq())
val a7 = ca.newStack(a5, Seq())
testFunc(ca, func, Seq(a0, a0, a2, a2, a4, a4, a6, a6)) { (ca, th, st, wp) =>
val Seq(req, rne,ieq, ine, feq, fne, seq, sne) = ca.dumpKeepalives(st, 0)
req.vb.asUInt(1) shouldEqual 1
rne.vb.asUInt(1) shouldEqual 0
ieq.vb.asUInt(1) shouldEqual 1
ine.vb.asUInt(1) shouldEqual 0
feq.vb.asUInt(1) shouldEqual 1
fne.vb.asUInt(1) shouldEqual 0
seq.vb.asUInt(1) shouldEqual 1
sne.vb.asUInt(1) shouldEqual 0
TrapRebindPassVoid(st)
}
testFunc(ca, func, Seq(a0, a1, a2, a3, a4, a5, a6, a7)) { (ca, th, st, wp) =>
val Seq(req, rne,ieq, ine, feq, fne, seq, sne) = ca.dumpKeepalives(st, 0)
req.vb.asUInt(1) shouldEqual 0
rne.vb.asUInt(1) shouldEqual 1
ieq.vb.asUInt(1) shouldEqual 0
ine.vb.asUInt(1) shouldEqual 1
feq.vb.asUInt(1) shouldEqual 0
fne.vb.asUInt(1) shouldEqual 1
seq.vb.asUInt(1) shouldEqual 0
sne.vb.asUInt(1) shouldEqual 1
TrapRebindPassVoid(st)
}
val nr = ca.putConstant("@NULLREF_I64")
val ni = ca.putConstant("@NULLIREF_I64")
val nf = ca.putConstant("@NULLFUNC")
val ns = ca.putConstant("@NULLSTACK")
testFunc(ca, func, Seq(nr, nr, ni, ni, nf, nf, ns, ns)) { (ca, th, st, wp) =>
val Seq(req, rne,ieq, ine, feq, fne, seq, sne) = ca.dumpKeepalives(st, 0)
req.vb.asUInt(1) shouldEqual 1
rne.vb.asUInt(1) shouldEqual 0
ieq.vb.asUInt(1) shouldEqual 1
ine.vb.asUInt(1) shouldEqual 0
feq.vb.asUInt(1) shouldEqual 1
fne.vb.asUInt(1) shouldEqual 0
seq.vb.asUInt(1) shouldEqual 1
sne.vb.asUInt(1) shouldEqual 0
TrapRebindPassVoid(st)
}
testFunc(ca, func, Seq(a0, nr, a2, ni, a4, nf, a6, ns)) { (ca, th, st, wp) =>
val Seq(req, rne,ieq, ine, feq, fne, seq, sne) = ca.dumpKeepalives(st, 0)
req.vb.asUInt(1) shouldEqual 0
rne.vb.asUInt(1) shouldEqual 1
ieq.vb.asUInt(1) shouldEqual 0
ine.vb.asUInt(1) shouldEqual 1
feq.vb.asUInt(1) shouldEqual 0
fne.vb.asUInt(1) shouldEqual 1
seq.vb.asUInt(1) shouldEqual 0
sne.vb.asUInt(1) shouldEqual 1
TrapRebindPassVoid(st)
}
ca.close()
}
"Conversions" should "work on scalar types" in {
val ca = microVM.newClientAgent()
......
......@@ -76,7 +76,13 @@
.typedef @refvoid = ref<@void>
.typedef @irefvoid = iref<@void>
.typedef @weakrefvoid = weakref<@void>
.const @NULLREF <@refvoid> = NULL
.const @NULLREF <@refvoid> = NULL
.const @NULLIREF <@irefvoid> = NULL
.const @NULLFUNC <@funcdumb> = NULL
.const @NULLSTACK <@stack> = NULL
.const @NULLREF_I64 <@refi64> = NULL
.const @NULLIREF_I64 <@irefi64> = NULL
.funcsig @binops32_sig = @void (@i32 @i32)
.funcdef @binops32 VERSION @binops32_v1 <@binops32_sig> (%p0 %p1) {
......@@ -285,6 +291,33 @@
COMMINST @uvm.thread_exit
}
.global @dummy_global1 <@i64>
.global @dummy_global2 <@i64>
.funcdecl @dummy_func1 <@noparamsnoret>
.funcdef @dummy_func2 VERSION @dummy_func2.v1 <@noparamsnoret> () {
%entry:
RETVOID
}
.funcsig @cmp_ref_sig = @void (@refi64 @refi64 @irefi64 @irefi64 @funcdumb @funcdumb @stack @stack)
.funcdef @cmp_ref VERSION @cmp_ref_v1 <@cmp_ref_sig> (%p0 %p1 %p2 %p3 %p4 %p5 %p6 %p7) {
%entry:
%req = EQ <@refi64> %p0 %p1
%rne = NE <@refi64> %p0 %p1
%ieq = EQ <@irefi64> %p2 %p3
%ine = NE <@irefi64> %p2 %p3
%feq = EQ <@funcdumb> %p4 %p5
%fne = NE <@funcdumb> %p4 %p5
%seq = EQ <@stack> %p6 %p7
%sne = NE <@stack> %p6 %p7
%trap = TRAP <@void> KEEPALIVE (
%req %rne %ieq %ine %feq %fne %seq %sne
)
COMMINST @uvm.thread_exit
}
.funcsig @conv_sig = @void (@i32 @i64 @float @double)
.funcdef @conv VERSION @conv_v1 <@conv_sig> (%p0 %p1 %p2 %p3) {
%entry:
......@@ -662,8 +695,6 @@
COMMINST @uvm.thread_exit
}
.const @NULLIREF_I64 <@irefi64> = NULL
.funcdef @memAccessingNull VERSION @memAccessingNull_v1 <@noparamsnoret> () {
%entry:
%l = LOAD <@i64> @NULLIREF_I64 EXC(%unreachable %bb2)
......
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