From 2b39bedd4eb393855a327e01b6cda2ce5c93b0ec Mon Sep 17 00:00:00 2001 From: Kunshan Wang Date: Mon, 22 Dec 2014 16:01:36 +1100 Subject: [PATCH] Aggregate operations. --- .../uvm/refimpl/itpr/InterpreterThread.scala | 93 ++++++++++++++++++- .../uvm/refimpl/itpr/operationHelpers.scala | 7 ++ .../uvm/refimpl/itpr/UvmInterpreterSpec.scala | 38 +++++++- tests/uvm-parsing-test/instructions.uir | 6 +- tests/uvm-refimpl-test/basic-tests.uir | 47 ++++++---- 5 files changed, 165 insertions(+), 26 deletions(-) diff --git a/src/main/scala/uvm/refimpl/itpr/InterpreterThread.scala b/src/main/scala/uvm/refimpl/itpr/InterpreterThread.scala index d8748a3..5229371 100644 --- a/src/main/scala/uvm/refimpl/itpr/InterpreterThread.scala +++ b/src/main/scala/uvm/refimpl/itpr/InterpreterThread.scala @@ -361,7 +361,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter curStack.pushFrame(funcVer, argBoxes) } - + case i @ InstTailCall(sig, callee, argList) => { val calleeFunc = boxOf(callee).asInstanceOf[BoxFunc].func.getOrElse { throw new UvmRuntimeException(ctx + "Callee must not be NULL") @@ -373,7 +373,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter curStack.replaceTop(funcVer, argBoxes) } - + case i @ InstRet(retTy, retVal) => { val rvb = boxOf(retVal) curStack.popFrame() @@ -381,20 +381,103 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter boxOf(newCurInst).copyFrom(rvb) continueNormally() } - + case i @ InstRetVoid() => { curStack.popFrame() 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.") + + case i @ InstExtractValue(strTy, index, opnd) => { + val ob = boxOf(opnd).asInstanceOf[BoxStruct] + val fb = ob.values(index) + val ib = boxOf(i) + ib.copyFrom(fb) + continueNormally() + } + + case i @ InstInsertValue(strTy, index, opnd, newVal) => { + val ob = boxOf(opnd).asInstanceOf[BoxStruct] + val nvb = boxOf(newVal) + val ib = boxOf(i).asInstanceOf[BoxStruct] + for (((ofb, ifb), ind) <- (ob.values zip ib.values).zipWithIndex) { + if (ind == index) { + ifb.copyFrom(nvb) + } else { + ifb.copyFrom(ofb) + } + } + continueNormally() + } + + case i @ InstExtractElement(vecTy, indTy, opnd, index) => { + val ob = boxOf(opnd).asInstanceOf[BoxVector] + val indb = boxOf(index).asInstanceOf[BoxInt] + val ind = OpHelper.prepareSigned(indb.value, indTy.length) + + if (ind < 0 || ind > vecTy.len) { + throw new UvmRuntimeException(ctx + "Index %d out of range. Vector type: %s".format(ind, vecTy)) + } + + val eb = ob.values(ind.intValue()) + val ib = boxOf(i) + ib.copyFrom(eb) + continueNormally() + } + + case i @ InstInsertElement(vecTy, indTy, opnd, index, newVal) => { + val ob = boxOf(opnd).asInstanceOf[BoxVector] + + val indb = boxOf(index).asInstanceOf[BoxInt] + val ind = OpHelper.prepareSigned(indb.value, indTy.length) + + if (ind < 0 || ind > vecTy.len) { + throw new UvmRuntimeException(ctx + "Index %d out of range. Vector type: %s".format(ind, vecTy)) + } + + val indInt = ind.intValue + + val nvb = boxOf(newVal) + val ib = boxOf(i).asInstanceOf[BoxVector] + + for (((oeb, ieb), ind2) <- (ob.values zip ib.values).zipWithIndex) { + if (ind2 == indInt) { + ieb.copyFrom(nvb) + } else { + ieb.copyFrom(oeb) + } + } + continueNormally() + } + + case i @ InstShuffleVector(vecTy, maskTy, vec1, vec2, mask) => { + val vecLen = vecTy.len.toInt + val maskIntLen = maskTy.elemTy.asInstanceOf[TypeInt].length + val vb1 = boxOf(vec1).asInstanceOf[BoxVector] + val vb2 = boxOf(vec2).asInstanceOf[BoxVector] + val mb = boxOf(mask).asInstanceOf[BoxVector] + val ib = boxOf(i).asInstanceOf[BoxVector] + + for (((meb, ieb), ind) <- (mb.values zip ib.values).zipWithIndex) { + val me = OpHelper.prepareSigned(meb.asInstanceOf[BoxInt].value, maskIntLen) + if (0 <= me && me < vecLen) { + ieb.copyFrom(vb1.values(me.intValue)) + } else if (vecLen <= me && me < vecLen * 2) { + ieb.copyFrom(vb2.values(me.intValue - vecLen)) + } else { + throw new UvmRuntimeException(ctx + "Index %d as the %d-th element of mask is out of range. Vector type: %s".format(me, ind, vecTy)) + } + } + continueNormally() + } // Indentation guide: Insert more instructions here. diff --git a/src/main/scala/uvm/refimpl/itpr/operationHelpers.scala b/src/main/scala/uvm/refimpl/itpr/operationHelpers.scala index 1acc59f..955913e 100644 --- a/src/main/scala/uvm/refimpl/itpr/operationHelpers.scala +++ b/src/main/scala/uvm/refimpl/itpr/operationHelpers.scala @@ -277,3 +277,10 @@ object PrimOpHelpers { } } } + +object AggregateOperations { + def extractValue(boxStr: BoxStruct, index: Int, boxResult: ValueBox): Unit = { + + } +} + diff --git a/src/test/scala/uvm/refimpl/itpr/UvmInterpreterSpec.scala b/src/test/scala/uvm/refimpl/itpr/UvmInterpreterSpec.scala index 6773a9a..c3b8851 100644 --- a/src/test/scala/uvm/refimpl/itpr/UvmInterpreterSpec.scala +++ b/src/test/scala/uvm/refimpl/itpr/UvmInterpreterSpec.scala @@ -18,7 +18,7 @@ class UvmInterpreterSpec extends UvmBundleTesterBase { setLogLevels( ROOT_LOGGER_NAME -> INFO, "uvm.refimpl.itpr" -> DEBUG) - + preloadBundles("tests/uvm-refimpl-test/basic-tests.uir") "The constant pool" should "contain appropriate constant values" in { @@ -760,4 +760,40 @@ class UvmInterpreterSpec extends UvmBundleTesterBase { } ca.close() } + + "EXTRACTVALUE and INSERTVALUE" should "work" in { + val ca = microVM.newClientAgent() + + val func = ca.putFunction("@aggregate_struct") + + testFunc(ca, func, Seq()) { (ca, th, st, wp) => + val Seq(f1, f12) = ca.dumpKeepalives(st, 0) + + f1.vb.asSInt(64) shouldEqual 2 + f12.vb.asSInt(64) shouldEqual 7 + + TrapRebindPassVoid(st) + } + + ca.close() + } + + "EXTRACTELEMENT and INSERTELEMENT" should "work on vectors" in { + val ca = microVM.newClientAgent() + + val func = ca.putFunction("@aggregate_vector") + + testFunc(ca, func, Seq()) { (ca, th, st, wp) => + val Seq(ee0, ie0, sv0) = ca.dumpKeepalives(st, 0) + + ee0.vb.asFloat shouldEqual 0.0f + ie0.vb.asVec.map(_.asFloat) shouldEqual Seq(0.0f, 6.0f, 2.0f, 3.0f) + sv0.vb.asVec.map(_.asFloat) shouldEqual Seq(0.0f, 2.0f, 4.0f, 6.0f) + + TrapRebindPassVoid(st) + } + + ca.close() + } + } \ No newline at end of file diff --git a/tests/uvm-parsing-test/instructions.uir b/tests/uvm-parsing-test/instructions.uir index d4ebfd2..8241da9 100644 --- a/tests/uvm-parsing-test/instructions.uir +++ b/tests/uvm-parsing-test/instructions.uir @@ -239,12 +239,12 @@ .typedef @sid = struct <@i64 @double> .const @sid1 <@sid> = {@I64_1 @D_1} -.const @v1 <@4xfloat> = {@F_0 @F_0 @F_0 @F_0} -.const @v2 <@4xfloat> = {@F_1 @F_1 @F_1 @F_1} +.const @v1 <@4xfloat> = VEC {@F_0 @F_0 @F_0 @F_0} +.const @v2 <@4xfloat> = VEC {@F_1 @F_1 @F_1 @F_1} .const @I32_4 <@i32> = 4 .const @I32_6 <@i32> = 6 -.const @vshf <@4xi32> = {@I32_0 @I32_2 @I32_4 @I32_6} +.const @vshf <@4xi32> = VEC {@I32_0 @I32_2 @I32_4 @I32_6} .funcdef @aggregate VERSION @aggregate_v1 <@npnr_sig> () { %entry: diff --git a/tests/uvm-refimpl-test/basic-tests.uir b/tests/uvm-refimpl-test/basic-tests.uir index 31ed70c..adc02b4 100644 --- a/tests/uvm-refimpl-test/basic-tests.uir +++ b/tests/uvm-refimpl-test/basic-tests.uir @@ -443,23 +443,36 @@ COMMINST @uvm.thread_exit } -// // Some simple struct constants -// -// .typedef @StructFoo = struct <@i32 @i64 @float @double> -// -// .const @STRUCT_FOO <@StructFoo> = {1 2 3.0f 4.0d} -// -// .funcsig @aggregate_sig = @noparamsnoret -// .funcdef @aggregate VERSION @aggregate_v1 <@aggregate_sig> () { -// %entry: -// %f1 = EXTRACTVALUE <@StructFoo 1> @STRUCT_FOO -// %s2 = INSERTVALUE <@StructFoo 1> @STRUCT_FOO 222 -// %f12 = EXTRACTVALUE <@StructFoo 1> %s2 -// %trapnor = TRAP <@void> KEEPALIVE (%f1 %f12) -// %exit: -// COMMINST @uvm.thread_exit -// } -// +// Some simple struct constants + +.typedef @StructFoo = struct <@i32 @i64 @float @double> + +.const @STRUCT_FOO <@StructFoo> = {@I32_1 @I64_2 @F_3 @D_4} + +.funcdef @aggregate_struct VERSION @aggregate_struct_v1 <@noparamsnoret> () { + %entry: + %f1 = EXTRACTVALUE <@StructFoo 1> @STRUCT_FOO + %s2 = INSERTVALUE <@StructFoo 1> @STRUCT_FOO @I64_7 + %f12 = EXTRACTVALUE <@StructFoo 1> %s2 + + %trapnor = TRAP <@void> KEEPALIVE (%f1 %f12) + COMMINST @uvm.thread_exit +} + +.const @v1 <@4xfloat> = VEC {@F_0 @F_1 @F_2 @F_3} +.const @v2 <@4xfloat> = VEC {@F_4 @F_5 @F_6 @F_7} +.const @vshf <@4xi32> = VEC {@I32_0 @I32_2 @I32_4 @I32_6} + +.funcdef @aggregate_vector VERSION @aggregate_vector_v1 <@noparamsnoret> () { + %entry: + %ee0 = EXTRACTELEMENT <@4xfloat @i32> @4xF_V1 @I32_0 + %ie0 = INSERTELEMENT <@4xfloat @i32> @4xF_V1 @I32_1 @F_6 + %sv0 = SHUFFLEVECTOR <@4xfloat @4xi32> @4xF_V1 @4xF_V2 @vshf + + %trapnor = TRAP <@void> KEEPALIVE (%ee0 %ie0 %sv0) + COMMINST @uvm.thread_exit +} + // .typedef @refi64 = ref<@i64> // .typedef @irefi64 = iref<@i64> // .typedef @weakrefi64 = weakref<@i64> -- 2.26.2