Commit 3dd5c9cd authored by Kunshan Wang's avatar Kunshan Wang

Some instructions.

parent 4fcad221
......@@ -482,7 +482,17 @@ class ClientAgent(microVM: MicroVM) {
}
def newStack(func: Handle, args: Seq[Handle]): Handle = {
throw new UvmRefImplException("Not Implemented")
val fv = func.vb.asInstanceOf[BoxFunc].func match {
case None => throw new UvmRuntimeException("Stack-bottom function must not be NULL")
case Some(v) => v
}
val argBoxes = args.map(_.vb)
val sta = microVM.threadStackManager.newStack(fv, argBoxes, mutator)
val nb = BoxStack(Some(sta))
newHandle(InternalTypes.STACK, nb)
}
def newThread(stack: Handle): Handle = {
......
......@@ -10,3 +10,13 @@ class UvmOutOfMemoryException(message: String = null, cause: Throwable = null) e
/** Thrown when an action not required by the specification and not implemented by this refimpl is performed. */
class UnimplementedOprationException(message: String = null, cause: Throwable = null) extends UvmRefImplException(message, cause)
/**
* Thrown when a dynamic error (errors that cannot be found at compile time) happens. This refimpl may sometimes throw
* exceptions on static errors rather than checking before running because the µVM has undefined behaviour on static
* errors. (It has undefined behaviour on dynamic errors, too.)
*/
class UvmRuntimeException(message: String = null, cause: Throwable = null) extends UvmRefImplException(message, cause)
/** Thrown when a division by zero is executed and the exception claues is not present. */
class UvmDivisionByZeroException(message: String = null, cause: Throwable = null) extends UvmRuntimeException(message, cause)
\ No newline at end of file
package uvm.refimpl.itpr
object OpHelper {
val ONE = BigInt(1)
def mask(n: Int): BigInt = {
(ONE << n) - ONE
}
def truncFromBigInt(n: BigInt, len: Int): BigInt = n & mask(len)
def zextToBigInt(n: BigInt, len: Int): BigInt = n & mask(len)
def sextToBigInt(n: BigInt, len: Int): BigInt = {
val bit = n.testBit(len - 1)
if (bit) {
n | (~mask(len - 1))
} else {
n & (mask(len - 1))
}
}
def prepareUnsigned(n: BigInt, len: Int): BigInt = truncFromBigInt(n, len)
def prepareSigned(n: BigInt, len: Int): BigInt = {
sextToBigInt(truncFromBigInt(n, len), len)
}
def unprepare(n: BigInt, len: Int): BigInt = truncFromBigInt(n, len)
def trunc(n: BigInt, toLen: Int): BigInt = truncFromBigInt(n, toLen)
def zext(n: BigInt, fromLen: Int, toLen: Int): BigInt = truncFromBigInt(n, fromLen)
def sext(n: BigInt, fromLen: Int, toLen: Int): BigInt = {
truncFromBigInt(sextToBigInt(n, fromLen), toLen)
}
def tr64IsInt(opnd: Long): Boolean = {
(opnd & 0x7ff0000000000001L) == 0x7ff0000000000001L
}
def tr64IsFp(opnd: Long): Boolean = {
(opnd & 0x7ff0000000000001L) != 0x7ff0000000000001L &&
(opnd & 0x7ff0000000000003L) != 0x7ff0000000000002L
}
def tr64IsRef(opnd: Long): Boolean = {
(opnd & 0x7ff0000000000003L) == 0x7ff0000000000002L
}
def intToTr64(opnd: Long): Long = {
(0x7ff0000000000001L | ((opnd & 0x7ffffffffffffL) << 1) |
((opnd & 0x8000000000000L) << 12))
}
def fpToTr64(opnd: Double): Long = {
var bits = java.lang.Double.doubleToRawLongBits(opnd)
if (java.lang.Double.isNaN(opnd)) {
bits = bits & 0xfff8000000000000L | 0x0000000000000008L
}
bits
}
def refToTr64(opnd: Long, tag: Long): Long = {
(0x7ff0000000000002L | (opnd & 0x7ffffffffff8L) | ((opnd & 0x800000000000L) << 16) |
((tag & 0x3eL) << 46) |
((tag & 0x1) << 2))
}
def tr64ToInt(opnd: Long): Long = {
(((opnd & 0xffffffffffffeL) >> 1) | ((opnd & 0x8000000000000000L) >> 12) & (1L << 51))
}
def tr64ToFp(opnd: Long): Double = java.lang.Double.longBitsToDouble(opnd)
def tr64ToRef(opnd: Long): Long = {
((opnd & 0x7ffffffffff8L) |
(((~(((opnd & 0x8000000000000000L) << 1) - 1)) >> 17) &
0xffff800000000000L))
}
def tr64ToTag(opnd: Long): Long = {
(((opnd & 0x000f800000000000L) >> 46) | ((opnd & 0x4) >> 2))
}
}
......@@ -48,7 +48,6 @@ class ThreadStackManager(microVM: MicroVM) {
val id = makeThreadID()
val thr = new InterpreterThread(id, microVM, stack, mutator)
threadRegistry.put(id, thr)
thr.start()
thr
}
......
......@@ -5,7 +5,9 @@ import uvm.types._
import uvm.refimpl._
import uvm.refimpl.mem.TypeSizes.Word
abstract class ValueBox
abstract class ValueBox {
def copyFrom(other: ValueBox): Unit
}
abstract class HasObjRef extends ValueBox {
def hasObjRef(): Boolean
......@@ -13,28 +15,60 @@ abstract class HasObjRef extends ValueBox {
def setObjRef(newObjRef: Word): Unit
}
abstract class ObjectBox[T](obj: Option[T]) extends ValueBox
abstract class ObjectBox[T] extends ValueBox {
def obj: Option[T]
def obj_=(o: Option[T]): Unit
def copyFrom(other: ValueBox): Unit = { this.obj = other.asInstanceOf[ObjectBox[T]].obj }
}
case class BoxInt(var value: BigInt) extends ValueBox
case class BoxFloat(var value: Float) extends ValueBox
case class BoxDouble(var value: Double) extends ValueBox
case class BoxVector(var values: Seq[ValueBox]) extends ValueBox
case class BoxInt(var value: BigInt) extends ValueBox {
def copyFrom(other: ValueBox): Unit = { this.value = other.asInstanceOf[BoxInt].value }
}
case class BoxFloat(var value: Float) extends ValueBox {
def copyFrom(other: ValueBox): Unit = { this.value = other.asInstanceOf[BoxFloat].value }
}
case class BoxDouble(var value: Double) extends ValueBox {
def copyFrom(other: ValueBox): Unit = { this.value = other.asInstanceOf[BoxDouble].value }
}
case class BoxVector(var values: Seq[ValueBox]) extends ValueBox {
def copyFrom(other: ValueBox): Unit = { for ((t, o) <- this.values.zip(other.asInstanceOf[BoxVector].values)) t.copyFrom(o) }
}
case class BoxRef(var objRef: Word) extends HasObjRef {
def copyFrom(other: ValueBox): Unit = { this.objRef = other.asInstanceOf[BoxRef].objRef }
def hasObjRef() = true
def getObjRef() = objRef
def setObjRef(newObjRef: Word): Unit = { objRef = newObjRef }
}
case class BoxIRef(var objRef: Word, var offset: Word) extends HasObjRef {
def copyFrom(other: ValueBox): Unit = {
val that = other.asInstanceOf[BoxIRef]
this.objRef = that.objRef; this.offset = that.offset
}
def hasObjRef() = objRef != 0
def getObjRef() = objRef
def setObjRef(newObjRef: Word): Unit = { objRef = newObjRef }
}
case class BoxStruct(var values: Seq[ValueBox]) extends ValueBox
case class BoxVoid() extends ValueBox
case class BoxFunc(var func: Option[Function]) extends ObjectBox[Function](func)
case class BoxThread(var thread: Option[InterpreterThread]) extends ObjectBox[InterpreterThread](thread)
case class BoxStack(var stack: Option[InterpreterStack]) extends ObjectBox[InterpreterStack](stack)
case class BoxStruct(var values: Seq[ValueBox]) extends ValueBox {
def copyFrom(other: ValueBox): Unit = { for ((t, o) <- this.values.zip(other.asInstanceOf[BoxStruct].values)) t.copyFrom(o) }
}
case class BoxVoid() extends ValueBox {
def copyFrom(other: ValueBox): Unit = {}
}
case class BoxFunc(var func: Option[Function]) extends ObjectBox[Function] {
def obj = func
def obj_=(other: Option[Function]): Unit = { func = other }
}
case class BoxThread(var thread: Option[InterpreterThread]) extends ObjectBox[InterpreterThread] {
def obj = thread
def obj_=(other: Option[InterpreterThread]): Unit = { thread = other }
}
case class BoxStack(var stack: Option[InterpreterStack]) extends ObjectBox[InterpreterStack] {
def obj = stack
def obj_=(other: Option[InterpreterStack]): Unit = { stack = other }
}
case class BoxTagRef64(var raw: Long) extends HasObjRef {
def copyFrom(other: ValueBox): Unit = { this.raw = other.asInstanceOf[BoxTagRef64].raw }
def hasObjRef() = OpHelper.tr64IsRef(raw)
def getObjRef() = OpHelper.tr64ToRef(raw)
def setObjRef(newObjRef: Word) = {
......
package uvm.refimpl.itpr
import uvm.ssavariables._
import uvm.refimpl._
object OpHelper {
val ONE = BigInt(1)
def mask(n: Int): BigInt = {
(ONE << n) - ONE
}
def truncFromBigInt(n: BigInt, len: Int): BigInt = n & mask(len)
def zextToBigInt(n: BigInt, len: Int): BigInt = n & mask(len)
def sextToBigInt(n: BigInt, len: Int): BigInt = {
val bit = n.testBit(len - 1)
if (bit) {
n | (~mask(len - 1))
} else {
n & (mask(len - 1))
}
}
def prepareUnsigned(n: BigInt, len: Int): BigInt = truncFromBigInt(n, len)
def prepareSigned(n: BigInt, len: Int): BigInt = {
sextToBigInt(truncFromBigInt(n, len), len)
}
def unprepare(n: BigInt, len: Int): BigInt = truncFromBigInt(n, len)
def trunc(n: BigInt, toLen: Int): BigInt = truncFromBigInt(n, toLen)
def zext(n: BigInt, fromLen: Int, toLen: Int): BigInt = truncFromBigInt(n, fromLen)
def sext(n: BigInt, fromLen: Int, toLen: Int): BigInt = {
truncFromBigInt(sextToBigInt(n, fromLen), toLen)
}
def maxSInt(l: Int): BigInt = (BigInt(1) << (l - 1)) - 1
def minSIntAbs(l: Int): BigInt = BigInt(1) << (l - 1)
def maxUInt(l: Int): BigInt = (BigInt(1) << l) - 1
/**
* Convert a float to an integer. The result only has the lowest iLen binary digits.
*/
def floatToI(n: Float, iLen: Int, signed: Boolean): BigInt = {
val lExp = Math.getExponent(n)
val rExp = lExp - 23
val frac = (java.lang.Float.floatToRawIntBits(n) & 0x7fffff) | 0x800000;
if (java.lang.Float.isNaN(n)) 0
else if (signed) {
if (java.lang.Float.isInfinite(n)) { if (n > 0.0F) maxSInt(iLen) else minSIntAbs(iLen) }
else {
if (lExp >= (iLen - 1)) if (n > 0.0F) maxSInt(iLen) else minSIntAbs(iLen)
else if (lExp < 0) 0
else {
val abs = BigInt(frac) << rExp
unprepare(if (n < 0.0F) -abs else abs, iLen)
}
}
} else {
if (n < 0.0F) 0
else if (java.lang.Float.isInfinite(n)) maxUInt(iLen)
else {
if (lExp >= iLen) maxUInt(iLen)
else if (lExp < 0) 0
else unprepare(BigInt(frac) << rExp, iLen)
}
}
}
/**
* Convert a float to an integer. The result only has the lowest iLen binary digits.
*/
def doubleToI(n: Double, iLen: Int, signed: Boolean): BigInt = {
val lExp = Math.getExponent(n)
val rExp = lExp - 52
val frac = (java.lang.Double.doubleToRawLongBits(n) & 0xfffffffffffffL) | 0x10000000000000L;
if (java.lang.Double.isNaN(n)) 0
else if (signed) {
if (java.lang.Double.isInfinite(n)) { if (n > 0.0D) maxSInt(iLen) else minSIntAbs(iLen) }
else {
if (lExp >= (iLen - 1)) if (n > 0.0D) maxSInt(iLen) else minSIntAbs(iLen)
else if (lExp < 0) 0
else {
val abs = BigInt(frac) << rExp
unprepare(if (n < 0.0D) -abs else abs, iLen)
}
}
} else {
if (n < 0.0D) 0
else if (java.lang.Double.isInfinite(n)) maxUInt(iLen)
else {
if (lExp >= iLen) maxUInt(iLen)
else if (lExp < 0) 0
else unprepare(BigInt(frac) << rExp, iLen)
}
}
}
def tr64IsInt(opnd: Long): Boolean = {
(opnd & 0x7ff0000000000001L) == 0x7ff0000000000001L
}
def tr64IsFp(opnd: Long): Boolean = {
(opnd & 0x7ff0000000000001L) != 0x7ff0000000000001L &&
(opnd & 0x7ff0000000000003L) != 0x7ff0000000000002L
}
def tr64IsRef(opnd: Long): Boolean = {
(opnd & 0x7ff0000000000003L) == 0x7ff0000000000002L
}
def intToTr64(opnd: Long): Long = {
(0x7ff0000000000001L | ((opnd & 0x7ffffffffffffL) << 1) |
((opnd & 0x8000000000000L) << 12))
}
def fpToTr64(opnd: Double): Long = {
var bits = java.lang.Double.doubleToRawLongBits(opnd)
if (java.lang.Double.isNaN(opnd)) {
bits = bits & 0xfff8000000000000L | 0x0000000000000008L
}
bits
}
def refToTr64(opnd: Long, tag: Long): Long = {
(0x7ff0000000000002L | (opnd & 0x7ffffffffff8L) | ((opnd & 0x800000000000L) << 16) |
((tag & 0x3eL) << 46) |
((tag & 0x1) << 2))
}
def tr64ToInt(opnd: Long): Long = {
(((opnd & 0xffffffffffffeL) >> 1) | ((opnd & 0x8000000000000000L) >> 12) & (1L << 51))
}
def tr64ToFp(opnd: Long): Double = java.lang.Double.longBitsToDouble(opnd)
def tr64ToRef(opnd: Long): Long = {
((opnd & 0x7ffffffffff8L) |
(((~(((opnd & 0x8000000000000000L) << 1) - 1)) >> 17) &
0xffff800000000000L))
}
def tr64ToTag(opnd: Long): Long = {
(((opnd & 0x000f800000000000L) >> 46) | ((opnd & 0x4) >> 2))
}
}
object PrimOpHelpers {
@throws(classOf[UvmDivisionByZeroException])
def intBinOp(op: BinOptr.BinOptr, l: Int, op1v: BigInt, op2v: BigInt, ctx: => String): BigInt = {
def pu(v: BigInt): BigInt = OpHelper.prepareUnsigned(v, l)
def ps(v: BigInt): BigInt = OpHelper.prepareSigned(v, l)
def up(v: BigInt): BigInt = OpHelper.unprepare(v, l)
def shiftMask = {
var i = 1
while (i < l) { i <<= 1 }
i - 1
}
def checkDivByZero(): Unit = {
if (op2v == 0) throw new UvmDivisionByZeroException(ctx + "Division by zero.")
}
up(op match {
case BinOptr.ADD => pu(op1v) + pu(op2v)
case BinOptr.SUB => pu(op1v) - pu(op2v)
case BinOptr.MUL => pu(op1v) * pu(op2v)
case BinOptr.UDIV => { checkDivByZero(); pu(op1v) / pu(op2v) }
case BinOptr.SDIV => { checkDivByZero(); ps(op1v) / ps(op2v) }
case BinOptr.UREM => { checkDivByZero(); pu(op1v) % pu(op2v) }
case BinOptr.SREM => { checkDivByZero(); ps(op1v) % ps(op2v) }
case BinOptr.SHL => pu(op1v) << (op2v.intValue & shiftMask)
case BinOptr.LSHR => pu(op1v) >> (op2v.intValue & shiftMask)
case BinOptr.ASHR => ps(op1v) >> (op2v.intValue & shiftMask)
case BinOptr.AND => pu(op1v) & pu(op2v)
case BinOptr.OR => pu(op1v) | pu(op2v)
case BinOptr.XOR => pu(op1v) ^ pu(op2v)
case _ => throw new UvmRuntimeException(ctx + "Binary operator %s is not suitable for integer.".format(op))
})
}
def floatBinOp(op: BinOptr.BinOptr, op1v: Float, op2v: Float, ctx: => String): Float = {
op match {
case BinOptr.FADD => op1v + op2v
case BinOptr.FSUB => op1v - op2v
case BinOptr.FMUL => op1v * op2v
case BinOptr.FDIV => op1v / op2v
case BinOptr.FREM => Math.IEEEremainder(op1v, op2v).toFloat
case _ => throw new UvmRuntimeException(ctx + "Binary operator %s is not suitable for float.".format(op))
}
}
def doubleBinOp(op: BinOptr.BinOptr, op1v: Double, op2v: Double, ctx: => String): Double = {
op match {
case BinOptr.FADD => op1v + op2v
case BinOptr.FSUB => op1v - op2v
case BinOptr.FMUL => op1v * op2v
case BinOptr.FDIV => op1v / op2v
case BinOptr.FREM => Math.IEEEremainder(op1v, op2v)
case _ => throw new UvmRuntimeException(ctx + "Binary operator %s is not suitable for double.".format(op))
}
}
def intCmp(op: CmpOptr.CmpOptr, l: Int, op1v: BigInt, op2v: BigInt, ctx: => String): Boolean = {
def pu(v: BigInt): BigInt = OpHelper.prepareUnsigned(v, l)
def ps(v: BigInt): BigInt = OpHelper.prepareSigned(v, l)
op match {
case CmpOptr.EQ => pu(op1v) == pu(op2v)
case CmpOptr.NE => pu(op1v) != pu(op2v)
case CmpOptr.UGT => pu(op1v) > pu(op2v)
case CmpOptr.UGE => pu(op1v) >= pu(op2v)
case CmpOptr.ULT => pu(op1v) < pu(op2v)
case CmpOptr.ULE => pu(op1v) <= pu(op2v)
case CmpOptr.SGT => ps(op1v) > ps(op2v)
case CmpOptr.SGE => ps(op1v) >= ps(op2v)
case CmpOptr.SLT => ps(op1v) < ps(op2v)
case CmpOptr.SLE => ps(op1v) <= ps(op2v)
case _ => throw new UvmRuntimeException(ctx + "Comparison operator %s not suitable for integers".format(op))
}
}
def floatCmp(op: CmpOptr.CmpOptr, op1v: Float, op2v: Float, ctx: => String): Boolean = {
import java.lang.Float.isNaN
def ord = !isNaN(op1v) && !isNaN(op2v)
def uno = isNaN(op1v) || isNaN(op2v)
op match {
case CmpOptr.FTRUE => true
case CmpOptr.FFALSE => false
case CmpOptr.FOEQ => ord && op1v == op2v
case CmpOptr.FONE => ord && op1v != op2v
case CmpOptr.FOGT => ord && op1v > op2v
case CmpOptr.FOGE => ord && op1v >= op2v
case CmpOptr.FOLT => ord && op1v < op2v
case CmpOptr.FOLE => ord && op1v <= op2v
case CmpOptr.FORD => ord
case CmpOptr.FUEQ => uno || op1v == op2v
case CmpOptr.FUNE => uno || op1v != op2v
case CmpOptr.FUGT => uno || op1v > op2v
case CmpOptr.FUGE => uno || op1v >= op2v
case CmpOptr.FULT => uno || op1v < op2v
case CmpOptr.FULE => uno || op1v <= op2v
case CmpOptr.FUNO => uno
case _ => throw new UvmRuntimeException(ctx + "Comparison operator %s is not suitable for float.".format(op))
}
}
def doubleCmp(op: CmpOptr.CmpOptr, op1v: Double, op2v: Double, ctx: => String): Boolean = {
import java.lang.Double.isNaN
def ord = !isNaN(op1v) && !isNaN(op2v)
def uno = isNaN(op1v) || isNaN(op2v)
op match {
case CmpOptr.FTRUE => true
case CmpOptr.FFALSE => false
case CmpOptr.FOEQ => ord && op1v == op2v
case CmpOptr.FONE => ord && op1v != op2v
case CmpOptr.FOGT => ord && op1v > op2v
case CmpOptr.FOGE => ord && op1v >= op2v
case CmpOptr.FOLT => ord && op1v < op2v
case CmpOptr.FOLE => ord && op1v <= op2v
case CmpOptr.FORD => ord
case CmpOptr.FUEQ => uno || op1v == op2v
case CmpOptr.FUNE => uno || op1v != op2v
case CmpOptr.FUGT => uno || op1v > op2v
case CmpOptr.FUGE => uno || op1v >= op2v
case CmpOptr.FULT => uno || op1v < op2v
case CmpOptr.FULE => uno || op1v <= op2v
case CmpOptr.FUNO => uno
case _ => throw new UvmRuntimeException(ctx + "Comparison operator %s is not suitable for double.".format(op))
}
}
}
......@@ -21,7 +21,7 @@ class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFun
var state: StackState = StackState.Ready(InternalTypes.VOID) // Initial state is READY<void>
var top: InterpreterFrame = new InterpreterFrame(stackBottomFunc, None) // Bottom frame
var top: InterpreterFrame = InterpreterFrame.frameForCall(stackBottomFunc, args, None)
def frames: Iterator[InterpreterFrame] = new AbstractIterator[InterpreterFrame] {
var curFrame: Option[InterpreterFrame] = Some(top)
......@@ -79,4 +79,16 @@ class InterpreterFrame(val funcVer: FuncVer, val prev: Option[InterpreterFrame])
case i => throw new UvmRefImplException("Instruction does not have keepalives: " + i.repr)
}
}
}
object InterpreterFrame {
def frameForCall(funcVer: FuncVer, args: Seq[ValueBox], prev: Option[InterpreterFrame]): InterpreterFrame = {
val frm = new InterpreterFrame(funcVer, prev) // Bottom frame
for ((p, a) <- (funcVer.params zip args)) {
frm.boxes(p).copyFrom(a)
}
frm
}
}
\ No newline at end of file
package uvm.refimpl.itpr
import uvm._
import uvm.types._
import uvm.ssavariables._
import uvm.refimpl._
import uvm.refimpl.mem._
import TypeSizes.Word
class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: InterpreterStack, val mutator: Mutator) {
var stack: Option[InterpreterStack] = Some(initialStack)
throw new UvmRefImplException("Not implemented")
def start(): Unit = {
throw new UvmRefImplException("Not implemented")
var isRunning: Boolean = true
def step(): Unit = {
interpretCurrentInstruction()
}
def isRunning: Boolean = {
throw new UvmRefImplException("Not implemented")
def sta = stack.get
def top = sta.top
def curBB = top.curBB
def inst = top.curInst
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 step(): Unit = {
throw new UvmRefImplException("Not implemented")
def continueNormally(excClause: Option[ExcClause]): Unit = {
excClause match {
case None => incPC()
case Some(ec) => {
branchAndMovePC(ec.nor)
}
}
}
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, inst)
private def interpretCurrentInstruction(): Unit = {
inst match {
case i @ InstBinOp(op, opndTy, op1, op2, excClause) => {
def doInt(l: Int, b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
val op1v = b1.asInstanceOf[BoxInt].value
val op2v = b2.asInstanceOf[BoxInt].value
val result = PrimOpHelpers.intBinOp(op, l, op1v, op2v, ctx)
val iBox = boxOf(i).asInstanceOf[BoxInt]
iBox.value = result
}
def doFloat(b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
val op1v = b1.asInstanceOf[BoxFloat].value
val op2v = b2.asInstanceOf[BoxFloat].value
val result = PrimOpHelpers.floatBinOp(op, op1v, op2v, ctx)
val iBox = boxOf(i).asInstanceOf[BoxFloat]
iBox.value = result
}
def doDouble(b1: ValueBox, b2: ValueBox, br: ValueBox): Unit = {
val op1v = b1.asInstanceOf[BoxDouble].value
val op2v = b2.asInstanceOf[BoxDouble].value
val result = PrimOpHelpers.doubleBinOp(op, op1v, op2v, ctx)
val iBox = boxOf(i).asInstanceOf[BoxDouble]
iBox.value = result
}
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 _ => throw new UvmRuntimeException(ctx + "BinOp not suitable for type %s".format(opndTy))
}
}
try {
opndTy match {
case TypeVector(scalarTy, sz) => {
val op1Bs = boxOf(op1).asInstanceOf[BoxVector].values
val op2Bs = boxOf(op1).asInstanceOf[BoxVector].values
val rBs = boxOf(i).asInstanceOf[BoxVector].values
for (((b1, b2), br) <- ((op1Bs zip op2Bs) zip rBs)) {
doScalar(scalarTy, b1, b2, br)
}
}
case scalarTy => doScalar(scalarTy, boxOf(op1), boxOf(op2), boxOf(i))
}
continueNormally(excClause)
} catch {
case e: UvmDivisionByZeroException => excClause match {
case None => throw e