Commit 235fdab5 authored by Kunshan Wang's avatar Kunshan Wang

Testing binary operations.

parent 86fe9958
......@@ -8,6 +8,7 @@ import uvm.refimpl.mem.TypeSizes._
import uvm.ssavariables.MemoryOrder._
import uvm.ssavariables.AtomicRMWOptr._
import uvm.refimpl.mem._
import uvm.ssavariables.HasKeepAliveClause
case class Handle(ty: Type, vb: ValueBox)
......@@ -495,31 +496,85 @@ class ClientAgent(microVM: MicroVM) {
newHandle(InternalTypes.STACK, nb)
}
private def getStackNotNull(stack: Handle): InterpreterStack = {
stack.vb.asInstanceOf[BoxStack].stack match {
case None => throw new UvmRuntimeException("Stack argument cannot be a NULL MicroVM stack value.")
case Some(v) => v
}
}
def newThread(stack: Handle): Handle = {
throw new UvmRefImplException("Not Implemented")
val sv = getStackNotNull(stack)
val thr = microVM.threadStackManager.newThread(sv)
val nb = BoxThread(Some(thr))
newHandle(InternalTypes.THREAD, nb)
}
def killStack(stack: Handle): Unit = {
throw new UvmRefImplException("Not Implemented")
val sv = getStackNotNull(stack)
sv.state = StackState.Dead
}
private def nthFrame(stack: InterpreterStack, n: Int): InterpreterFrame = {
val it = stack.frames
for (i <- (0 until n)) {
if (it.hasNext) {
it.next()
} else {
throw new UvmRuntimeException("The stack only has %d frames, but the %d-th frame is requested.".format(i, n))
}
}
if (it.hasNext) {
it.next()
} else {
throw new UvmRuntimeException("The stack only has %d frames, but the %d-th frame is requested.".format(n, n))
}
}
def currentFuncVer(stack: Handle, frame: Int): Int = {
throw new UvmRefImplException("Not Implemented")
val sv = getStackNotNull(stack)
val fr = nthFrame(sv, frame)
fr.funcVer.id
}
def currentInstruction(stack: Handle, frame: Int): Int = {
throw new UvmRefImplException("Not Implemented")
val sv = getStackNotNull(stack)
val fr = nthFrame(sv, frame)
fr.curInst.id
}
def dumpKeepalives(stack: Handle, frame: Int): Seq[Handle] = {
throw new UvmRefImplException("Not Implemented")
val sv = getStackNotNull(stack)
val fr = nthFrame(sv, frame)
val i = fr.curInst
i match {
case hkac: HasKeepAliveClause => {
val kas = hkac.keepAlives
for (ka <- kas) yield {
val box = fr.boxes(ka)
val ty = TypeInferer.inferType(ka)
newHandle(ty, box)
}
}
case _ => {
throw new UvmRuntimeException("The current instruction %s does not have keep-alive clause.".format(i.repr))
}
}
}
def popFrame(stack: Handle): Unit = {
throw new UvmRefImplException("Not Implemented")
val st = getStackNotNull(stack)
val top = st.top
top.prev match {
case None => throw new UvmRuntimeException("Attempting to pop the last frame of a stack.")
case Some(prev) => st.top = prev
}
}
def pushFrame = throw new UvmRefImplException("Not Implemented")
def pushFrame = throw new UvmRefImplException("Not defined in spec")
def tr64IsFp(handle: Handle): Boolean = {
OpHelper.tr64IsFp(handle.vb.asInstanceOf[BoxTagRef64].raw)
......@@ -583,7 +638,7 @@ class ClientAgent(microVM: MicroVM) {
val box = BoxThread(thr)
newHandle(t, box)
}
def putStack(sta: Option[InterpreterStack]): Handle = {
val t = InternalTypes.STACK
val box = BoxStack(sta)
......
......@@ -3,11 +3,21 @@ package uvm.refimpl.itpr
import uvm._
import uvm.types._
import uvm.ssavariables._
import uvm.comminsts._
import uvm.refimpl._
import uvm.refimpl.mem._
import TypeSizes.Word
import scala.annotation.tailrec
import org.slf4j.LoggerFactory
import com.typesafe.scalalogging.Logger
object InterpreterThread {
val logger = Logger(LoggerFactory.getLogger(getClass.getName))
}
class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: InterpreterStack, val mutator: Mutator) {
import InterpreterThread._
var stack: Option[InterpreterStack] = Some(initialStack)
var isRunning: Boolean = true
......@@ -16,6 +26,11 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
interpretCurrentInstruction()
}
def threadExit(): Unit = {
curStack.state = StackState.Dead
isRunning = false
}
def curStack = stack.get
def top = curStack.top
def curBB = top.curBB
......@@ -24,52 +39,18 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
def incPC(): Unit = top.incPC()
def jump(bb: BasicBlock, ix: Int): Unit = top.jump(bb, ix)
def branchAndMovePC(dest: BasicBlock, excAddr: Word = 0L): Unit = {
val curBB = this.curBB
var cont = true
var i = 0
while (cont) {
dest.insts(i) match {
case phi @ InstPhi(opndTy, cases) => {
val caseVal = cases.find({ case (bb, _) => bb == dest }).map(_._2).getOrElse {
throw new UvmRuntimeException(s"Phi node ${phi.repr} does not include the case for source basic block ${curBB.repr}")
}
val vb = boxOf(caseVal)
val db = boxOf(phi)
db.copyFrom(vb)
i += 1
}
case lp: InstLandingPad => {
val db = boxOf(lp).asInstanceOf[BoxRef]
db.objRef = excAddr
i += 1
}
case _ => cont = false
}
}
jump(dest, i)
}
def continueNormally(): Unit = {
curInst match {
case h: HasExcClause => h.excClause match {
case None => incPC()
case Some(ec) => {
branchAndMovePC(ec.nor)
}
}
case _ => incPC()
}
}
def boxOf(v: SSAVariable): ValueBox = v match {
case g: GlobalVariable => microVM.constantPool.getGlobalVarBox(g)
case l: LocalVariable => top.boxes(l)
}
def ctx = "FuncVer %s, BasicBlock %s, Instruction %s (%s): ".format(top.funcVer, curBB, curInst)
def ctx = "FuncVer %s, BasicBlock %s, Instruction %s (%s): ".format(top.funcVer.repr, curBB.repr, curInst.repr, curInst.getClass.getName)
private def interpretCurrentInstruction(): Unit = {
val curInst = this.curInst
logger.debug(ctx + "Executing instruction...")
curInst match {
case i @ InstBinOp(op, opndTy, op1, op2, excClause) => {
def doInt(l: Int, b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
......@@ -335,6 +316,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
continueNormally()
}
// Indentation guide: Insert more instructions here.
case i @ InstTrap(retTy, excClause, keepAlives) => {
......@@ -362,12 +344,65 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
}
}
ca.close()
}
// Indentation guide: Insert more instructions here.
// Indentation guide: Insert more instructions (after TRAP) here.
case i @ InstCommInst(ci, typeList, argList, excClause, keepAlives) => {
def theCI(name: String): CommInst = CommInsts(name)
ci.name.get match {
case "@uvm.thread_exit" => {
threadExit()
}
case ciName => {
throw new UvmRefImplException("Unimplemented common instruction %s".format(ciName))
}
}
}
case i => {
throw new UvmRefImplException("Unimplemented instruction %s".format(i.getClass.getName))
}
}
}
def branchAndMovePC(dest: BasicBlock, excAddr: Word = 0L): Unit = {
val curBB = this.curBB
var cont = true
var i = 0
while (cont) {
dest.insts(i) match {
case phi @ InstPhi(opndTy, cases) => {
val caseVal = cases.find({ case (bb, _) => bb == dest }).map(_._2).getOrElse {
throw new UvmRuntimeException(s"Phi node ${phi.repr} does not include the case for source basic block ${curBB.repr}")
}
val vb = boxOf(caseVal)
val db = boxOf(phi)
db.copyFrom(vb)
i += 1
}
case lp: InstLandingPad => {
val db = boxOf(lp).asInstanceOf[BoxRef]
db.objRef = excAddr
i += 1
}
case _ => cont = false
}
}
jump(dest, i)
}
def continueNormally(): Unit = {
curInst match {
case h: HasExcClause => h.excClause match {
case None => incPC()
case Some(ec) => {
branchAndMovePC(ec.nor)
}
}
case _ => incPC()
}
}
......@@ -376,10 +411,13 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
stack = None
}
def rebindPassValue(newStack: Option[InterpreterStack], value: ValueBox): Unit = {
def rebind(newStack: Option[InterpreterStack]): Unit = {
if (newStack == None) throw new UvmRuntimeException(ctx + "Rebinding to NULL stack. This does not make sense.")
stack = newStack
}
def rebindPassValue(newStack: Option[InterpreterStack], value: ValueBox): Unit = {
rebind(newStack)
try {
boxOf(curInst).copyFrom(value)
} catch {
......@@ -394,28 +432,61 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
}
def rebindPassVoid(newStack: Option[InterpreterStack]): Unit = {
if (newStack == None) throw new UvmRuntimeException(ctx + "Rebinding to NULL stack. This does not make sense.")
stack = newStack
rebind(newStack)
continueNormally()
}
def rebindThrowExc(newStack: Option[InterpreterStack], exc: ValueBox): Unit = {
if (newStack == None) throw new UvmRuntimeException(ctx + "Rebinding to NULL stack. This does not make sense.")
rebind(newStack)
val excObjRef = exc.asInstanceOf[BoxRef].objRef
stack = newStack
catchException(excObjRef)
}
/**
* Attempt to catch exception in the current frame. Will repeatedly unwind the stack until the exception can be
* handled. Stack underflow is an undefined behaviour.
* handled. Stack underflow is an undefined behaviour.
*/
def catchException(exc: Word): Unit = {
throw new UvmRefImplException("Not implemented.")
@tailrec
def unwindUntilCatchable(f: InterpreterFrame): (InterpreterFrame, BasicBlock) = {
maybeFindExceptionHandler(f.curInst) match {
case Some(bb) => (f, bb)
case None => f.prev match {
case None => throw new UvmRuntimeException(ctx + "Exception is thrown out of the bottom frame.")
case Some(prev) => unwindUntilCatchable(prev)
}
}
}
val s = curStack
val f = s.top
val (newFrame, newBB) = unwindUntilCatchable(f)
s.top = newFrame
branchAndMovePC(newBB, exc)
}
/**
* Test if the current frame with i as the current instruction can catch an exception that unwinds the stack.
*
* @return Return Some(h) if i can catch the exception and h is the basic block for the exception. Return None if i
* cannot catch exceptions.
*
* @throw Throw UvmRefimplException if a frame stops at an unexpected instruction. Normally the top frame can be
* executing TRAP, WATCHPOINT, SWAPSTACK or CALL and all other frames must be executing CALL.
*/
def maybeFindExceptionHandler(inst: Instruction): Option[BasicBlock] = {
inst match {
case i: InstCall => i.excClause.map(_.exc)
case i: InstTrap => i.excClause.map(_.exc)
case i: InstWatchPoint => i.exc
case i: InstSwapStack => i.excClause.map(_.exc)
case _ => {
throw new UvmRefImplException("Instruction %s (%s) is in a stack frame when an exception is thrown.".format(inst.repr, inst.getClass.getName))
}
}
}
}
......@@ -17,8 +17,6 @@ object StackState {
}
class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFunc: FuncVer, args: Seq[ValueBox]) {
throw new UvmRefImplException("Not implemented")
var state: StackState = StackState.Ready(InternalTypes.VOID) // Initial state is READY<void>
var top: InterpreterFrame = InterpreterFrame.frameForCall(stackBottomFunc, args, None)
......
......@@ -19,10 +19,54 @@
.const @TRUE <@i64> = 1
.const @FALSE <@i64> = 0
.const @I32_0 <@i32> = 0
.const @I32_1 <@i32> = 1
.const @I32_2 <@i32> = 2
.const @I32_3 <@i32> = 3
.const @I32_4 <@i32> = 4
.const @I32_5 <@i32> = 5
.const @I32_6 <@i32> = 6
.const @I32_7 <@i32> = 7
.const @I64_0 <@i64> = 0
.const @I64_1 <@i64> = 1
.const @I64_2 <@i64> = 2
.const @I64_3 <@i64> = 3
.const @I64_4 <@i64> = 4
.const @I64_5 <@i64> = 5
.const @I64_6 <@i64> = 6
.const @I64_7 <@i64> = 7
.const @F_0 <@float> = 0.0f
.const @F_1 <@float> = 1.0f
.const @F_2 <@float> = 2.0f
.const @F_3 <@float> = 3.0f
.const @F_4 <@float> = 4.0f
.const @F_5 <@float> = 5.0f
.const @F_6 <@float> = 6.0f
.const @F_7 <@float> = 7.0f
.const @D_0 <@double> = 0.0d
.const @D_1 <@double> = 1.0d
.const @D_2 <@double> = 2.0d
.const @D_3 <@double> = 3.0d
.const @D_4 <@double> = 4.0d
.const @D_5 <@double> = 5.0d
.const @D_6 <@double> = 6.0d
.const @D_7 <@double> = 7.0d
.typedef @4xfloat = vector <@float 4>
.typedef @4xi32 = vector <@i32 4>
.typedef @2xdouble = vector <@double 2>
.const @4xI32_V1 <@4xi32> = {@I32_0 @I32_1 @I32_2 @I32_3}
.const @4xI32_V2 <@4xi32> = {@I32_4 @I32_5 @I32_6 @I32_7}
.const @4xF_V1 <@4xfloat> = {@F_0 @F_1 @F_2 @F_3}
.const @4xF_V2 <@4xfloat> = {@F_4 @F_5 @F_6 @F_7}
.const @2xD_V1 <@2xdouble> = {@D_0 @D_1}
.const @2xD_V2 <@2xdouble> = {@D_2 @D_3}
.funcsig @i_ii = @i64 (@i64 @i64)
......@@ -81,25 +125,23 @@
COMMINST @uvm.thread_exit
}
.const @I64_MAX_S <@I64> = 0x7fffffffffffffff
.const @I64_MAX_U <@I64> = 0xffffffffffffffff
.const @I64_BIG <@I64> = 1000000000000
.const @I64_MIN_S <@I64> = -0x8000000000000000
.const @I64_N1 < <@I64> = -1
.funcsig @binops_ovf_sig = @noparamsnoret
.funcdef @binops_ovf VERSION @binops_ovf_v1 <@binops_ovf_sig> () {
.funcsig @binops64_div0_sig = @void (@i64 @i64 @i64 @i64 @i64)
.funcdef @binops64_div0 VERSION @binops64_div0_v1 <@binops64_div0_sig> (%p0 %p1 %p2 %p3 %p4) {
%entry:
%add = ADD <@i64> @I64_MAX_S @I64_1
%add2 = ADD <@i64> @I64_MAX_U @I64_2
%mul = MUL <@i64> @I64_BIG @I64_BIG
%udiv = UDIV <@i64> @I64_MIN_S @I64_N2 // MIN_S is treated as positive
%sdiv = SDIV <@i64> @I64_MIN_S @I64_N1 // This raises an exception in x86 assembly, but not microvm
%trap = TRAP <@void> KEEPALIVE (
%add %add2 %mul %udiv %sdiv
)
%udiv = UDIV <@i64> %p0 %p1 EXC(%bb2 %exc)
%bb2:
%sdiv = SDIV <@i64> %p0 %p2 EXC(%bb3 %exc)
%bb3:
%urem = UREM <@i64> %p0 %p3 EXC(%bb4 %exc)
%bb4:
%srem = SREM <@i64> %p0 %p4 EXC(%nor %exc)
%nor:
%trapnor = TRAP <@void>
COMMINST @uvm.thread_exit
%exc:
%trapexc = TRAP <@void>
COMMINST @uvm.thread_exit
}
......@@ -115,8 +157,6 @@
%trap = TRAP <@void> KEEPALIVE (
%fadd %fsub %fmul %fdiv %frem
)
%exit:
COMMINST @uvm.thread_exit
}
......@@ -132,8 +172,6 @@
%trap = TRAP <@void> KEEPALIVE (
%fadd %fsub %fmul %fdiv %frem
)
%exit:
COMMINST @uvm.thread_exit
}
......@@ -242,14 +280,22 @@
COMMINST @uvm.thread_exit
}
.funcsig @select_sig = @noparamsnoret
.funcdef @select VERSION @select_v1 <@select_sig> () {
.typedef @4xi1 = vector <@i1 4>
.const @4xI1_COND <@4xi1> = {@TRUE @FALSE @FALSE @TRUE}
.funcdef @select VERSION @select_v1 <@noparamsnoret> () {
%entry:
%sel1 = SELECT <@i64> @TRUE 2 3
%sel2 = SELECT <@i64> @FALSE 2 3
%sel1 = SELECT <@i1 @i64> @TRUE @I64_2 @I64_3
%sel2 = SELECT <@i1 @i64> @FALSE @I64_2 @I64_3
%sel3 = SELECT <@4xi1 @4xi32> @4xI1_COND @4xI32_V1 @4xI32_V2
%sel4 = SELECT <@i1 @4xi32> @TRUE @4xI32_V1 @4xI32_V2
%sel5 = SELECT <@i1 @4xi32> @FALSE @4xI32_V1 @4xI32_V2
%trap = TRAP <@void> KEEPALIVE (
%sel1 %sel2
%sel1 %sel2 %sel3 %sel4 %sel5
)
%exit:
......@@ -740,4 +786,4 @@
// %exit:
// %exittrap = TRAP <@void> KEEPALIVE (%sum) // should stop thread
// COMMINST @uvm.thread_exit
// }
\ No newline at end of file
// }
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