Commit e65b732f authored by Kunshan Wang's avatar Kunshan Wang

Implemented binop with flags.

parent 18eb5b94
This diff is collapsed.
......@@ -127,6 +127,7 @@ _top_level_structs = ["MuVM", "MuCtx", "MuIRBuilder"]
_enums = [(typename, re.compile(regex)) for typename, regex in [
("MuTrapHandlerResult", r'^MU_(THREAD|REBIND)'),
("MuDestKind", r'^MU_DEST_'),
("MuBinOpStatus", r'^MU_BOS_'),
("MuBinOptr", r'^MU_BINOP_'),
("MuCmpOptr", r'^MU_CMP_'),
("MuConvOptr", r'^MU_CONV_'),
......
......@@ -197,6 +197,7 @@ _special_converters = {
"MuCString" : "readCString",
"MuMemOrd" : "toMemoryOrder",
"MuAtomicRMWOptr" : "toAtomicRMWOptr",
"MuBinOpStatus" : "toBinOpStatus",
"MuBinOptr" : "toBinOptr",
"MuCmpOptr" : "toCmpOptr",
"MuConvOptr" : "toConvOptr",
......
......@@ -35,6 +35,7 @@ _type_map = {
"MuBool" : "int<32>",
"MuWPID" : "int<32>",
"MuArraySize" : "int<64>",
"MuBinOpStatus" : "int<32>",
"MuBinOptr" : "int<32>",
"MuCmpOptr" : "int<32>",
"MuConvOptr" : "int<32>",
......
......@@ -222,6 +222,7 @@ CMuArraySize = ctypes.c_uint64
CMuWPID = ctypes.c_uint32
CMuFlag = ctypes.c_uint32
CMuTrapHandlerResult = CMuFlag
CMuBinOpStatus = CMuFlag
CMuBinOptr = CMuFlag
CMuCmpOptr = CMuFlag
CMuConvOptr = CMuFlag
......@@ -428,42 +429,43 @@ common_instruction_opcodes = {
'@uvm.irbuilder.new_nsc_pass_values': 0x328,
'@uvm.irbuilder.new_nsc_throw_exc': 0x329,
'@uvm.irbuilder.new_binop': 0x32a,
'@uvm.irbuilder.new_cmp': 0x32b,
'@uvm.irbuilder.new_conv': 0x32c,
'@uvm.irbuilder.new_select': 0x32d,
'@uvm.irbuilder.new_branch': 0x32e,
'@uvm.irbuilder.new_branch2': 0x32f,
'@uvm.irbuilder.new_switch': 0x330,
'@uvm.irbuilder.new_call': 0x331,
'@uvm.irbuilder.new_tailcall': 0x332,
'@uvm.irbuilder.new_ret': 0x333,
'@uvm.irbuilder.new_throw': 0x334,
'@uvm.irbuilder.new_extractvalue': 0x335,
'@uvm.irbuilder.new_insertvalue': 0x336,
'@uvm.irbuilder.new_extractelement': 0x337,
'@uvm.irbuilder.new_insertelement': 0x338,
'@uvm.irbuilder.new_shufflevector': 0x339,
'@uvm.irbuilder.new_new': 0x33a,
'@uvm.irbuilder.new_newhybrid': 0x33b,
'@uvm.irbuilder.new_alloca': 0x33c,
'@uvm.irbuilder.new_allocahybrid': 0x33d,
'@uvm.irbuilder.new_getiref': 0x33e,
'@uvm.irbuilder.new_getfieldiref': 0x33f,
'@uvm.irbuilder.new_getelemiref': 0x340,
'@uvm.irbuilder.new_shiftiref': 0x341,
'@uvm.irbuilder.new_getvarpartiref': 0x342,
'@uvm.irbuilder.new_load': 0x343,
'@uvm.irbuilder.new_store': 0x344,
'@uvm.irbuilder.new_cmpxchg': 0x345,
'@uvm.irbuilder.new_atomicrmw': 0x346,
'@uvm.irbuilder.new_fence': 0x347,
'@uvm.irbuilder.new_trap': 0x348,
'@uvm.irbuilder.new_watchpoint': 0x349,
'@uvm.irbuilder.new_wpbranch': 0x34a,
'@uvm.irbuilder.new_ccall': 0x34b,
'@uvm.irbuilder.new_newthread': 0x34c,
'@uvm.irbuilder.new_swapstack': 0x34d,
'@uvm.irbuilder.new_comminst': 0x34e,
'@uvm.irbuilder.new_binop_with_status': 0x32b,
'@uvm.irbuilder.new_cmp': 0x32c,
'@uvm.irbuilder.new_conv': 0x32d,
'@uvm.irbuilder.new_select': 0x32e,
'@uvm.irbuilder.new_branch': 0x32f,
'@uvm.irbuilder.new_branch2': 0x330,
'@uvm.irbuilder.new_switch': 0x331,
'@uvm.irbuilder.new_call': 0x332,
'@uvm.irbuilder.new_tailcall': 0x333,
'@uvm.irbuilder.new_ret': 0x334,
'@uvm.irbuilder.new_throw': 0x335,
'@uvm.irbuilder.new_extractvalue': 0x336,
'@uvm.irbuilder.new_insertvalue': 0x337,
'@uvm.irbuilder.new_extractelement': 0x338,
'@uvm.irbuilder.new_insertelement': 0x339,
'@uvm.irbuilder.new_shufflevector': 0x33a,
'@uvm.irbuilder.new_new': 0x33b,
'@uvm.irbuilder.new_newhybrid': 0x33c,
'@uvm.irbuilder.new_alloca': 0x33d,
'@uvm.irbuilder.new_allocahybrid': 0x33e,
'@uvm.irbuilder.new_getiref': 0x33f,
'@uvm.irbuilder.new_getfieldiref': 0x340,
'@uvm.irbuilder.new_getelemiref': 0x341,
'@uvm.irbuilder.new_shiftiref': 0x342,
'@uvm.irbuilder.new_getvarpartiref': 0x343,
'@uvm.irbuilder.new_load': 0x344,
'@uvm.irbuilder.new_store': 0x345,
'@uvm.irbuilder.new_cmpxchg': 0x346,
'@uvm.irbuilder.new_atomicrmw': 0x347,
'@uvm.irbuilder.new_fence': 0x348,
'@uvm.irbuilder.new_trap': 0x349,
'@uvm.irbuilder.new_watchpoint': 0x34a,
'@uvm.irbuilder.new_wpbranch': 0x34b,
'@uvm.irbuilder.new_ccall': 0x34c,
'@uvm.irbuilder.new_newthread': 0x34d,
'@uvm.irbuilder.new_swapstack': 0x34e,
'@uvm.irbuilder.new_comminst': 0x34f,
}
## GEN:END:CENUMS
......@@ -1224,6 +1226,22 @@ class MuIRBuilder(_StructOfMethodsWrapper):
_actual_ntysvars = len(vars)
return self.new_nsc_pass_values_(_actual_id, _actual_tys, _actual_vars, _actual_ntysvars)
def new_binop_with_status(self, id, result_id, status_result_ids, optr, status_flags, ty, opnd1, opnd2, exc_clause):
_actual_id = id
_actual_result_id = result_id
_actual_status_result_ids_ty = CMuID * len(status_result_ids)
_actual_status_result_ids = _actual_status_result_ids_ty()
for _i,_v in enumerate(status_result_ids):
_actual_status_result_ids[_i] = _v
_actual_n_status_result_ids = len(status_result_ids)
_actual_optr = optr
_actual_status_flags = status_flags
_actual_ty = ty
_actual_opnd1 = opnd1
_actual_opnd2 = opnd2
_actual_exc_clause = 0 if exc_clause is None else exc_clause
return self.new_binop_with_status_(_actual_id, _actual_result_id, _actual_status_result_ids, _actual_n_status_result_ids, _actual_optr, _actual_status_flags, _actual_ty, _actual_opnd1, _actual_opnd2, _actual_exc_clause)
def new_switch(self, id, opnd_ty, opnd, default_dest, cases, dests):
_actual_id = id
_actual_opnd_ty = opnd_ty
......@@ -1644,6 +1662,7 @@ _initialize_methods(MuIRBuilder, [
('new_nsc_pass_values_', None, [CMuID, ctypes.c_void_p, ctypes.c_void_p, CMuArraySize]),
('new_nsc_throw_exc', None, [CMuID, CMuVarNode]),
('new_binop', None, [CMuID, CMuID, CMuBinOptr, CMuTypeNode, CMuVarNode, CMuVarNode, CMuExcClause]),
('new_binop_with_status_', None, [CMuID, CMuID, ctypes.c_void_p, CMuArraySize, CMuBinOptr, CMuBinOpStatus, CMuTypeNode, CMuVarNode, CMuVarNode, CMuExcClause]),
('new_cmp', None, [CMuID, CMuID, CMuCmpOptr, CMuTypeNode, CMuVarNode, CMuVarNode]),
('new_conv', None, [CMuID, CMuID, CMuConvOptr, CMuTypeNode, CMuTypeNode, CMuVarNode]),
('new_select', None, [CMuID, CMuID, CMuTypeNode, CMuTypeNode, CMuVarNode, CMuVarNode, CMuVarNode]),
......
......@@ -140,7 +140,7 @@ inst
instBody
// Integer/FP Arithmetic
: binop '<' ty=type '>' op1=value op2=value excClause # InstBinOp
: binop (flagList)? '<' ty=type '>' op1=value op2=value excClause # InstBinOp
// Integer/FP Comparison
| cmpop '<' ty=type '>' op1=value op2=value # InstCmp
......
......@@ -110,41 +110,42 @@ object CommInsts extends SimpleNamespace[CommInst] {
commInst(0x328, "@uvm.irbuilder.new_nsc_pass_values")
commInst(0x329, "@uvm.irbuilder.new_nsc_throw_exc")
commInst(0x32a, "@uvm.irbuilder.new_binop")
commInst(0x32b, "@uvm.irbuilder.new_cmp")
commInst(0x32c, "@uvm.irbuilder.new_conv")
commInst(0x32d, "@uvm.irbuilder.new_select")
commInst(0x32e, "@uvm.irbuilder.new_branch")
commInst(0x32f, "@uvm.irbuilder.new_branch2")
commInst(0x330, "@uvm.irbuilder.new_switch")
commInst(0x331, "@uvm.irbuilder.new_call")
commInst(0x332, "@uvm.irbuilder.new_tailcall")
commInst(0x333, "@uvm.irbuilder.new_ret")
commInst(0x334, "@uvm.irbuilder.new_throw")
commInst(0x335, "@uvm.irbuilder.new_extractvalue")
commInst(0x336, "@uvm.irbuilder.new_insertvalue")
commInst(0x337, "@uvm.irbuilder.new_extractelement")
commInst(0x338, "@uvm.irbuilder.new_insertelement")
commInst(0x339, "@uvm.irbuilder.new_shufflevector")
commInst(0x33a, "@uvm.irbuilder.new_new")
commInst(0x33b, "@uvm.irbuilder.new_newhybrid")
commInst(0x33c, "@uvm.irbuilder.new_alloca")
commInst(0x33d, "@uvm.irbuilder.new_allocahybrid")
commInst(0x33e, "@uvm.irbuilder.new_getiref")
commInst(0x33f, "@uvm.irbuilder.new_getfieldiref")
commInst(0x340, "@uvm.irbuilder.new_getelemiref")
commInst(0x341, "@uvm.irbuilder.new_shiftiref")
commInst(0x342, "@uvm.irbuilder.new_getvarpartiref")
commInst(0x343, "@uvm.irbuilder.new_load")
commInst(0x344, "@uvm.irbuilder.new_store")
commInst(0x345, "@uvm.irbuilder.new_cmpxchg")
commInst(0x346, "@uvm.irbuilder.new_atomicrmw")
commInst(0x347, "@uvm.irbuilder.new_fence")
commInst(0x348, "@uvm.irbuilder.new_trap")
commInst(0x349, "@uvm.irbuilder.new_watchpoint")
commInst(0x34a, "@uvm.irbuilder.new_wpbranch")
commInst(0x34b, "@uvm.irbuilder.new_ccall")
commInst(0x34c, "@uvm.irbuilder.new_newthread")
commInst(0x34d, "@uvm.irbuilder.new_swapstack")
commInst(0x34e, "@uvm.irbuilder.new_comminst")
commInst(0x32b, "@uvm.irbuilder.new_binop_with_status")
commInst(0x32c, "@uvm.irbuilder.new_cmp")
commInst(0x32d, "@uvm.irbuilder.new_conv")
commInst(0x32e, "@uvm.irbuilder.new_select")
commInst(0x32f, "@uvm.irbuilder.new_branch")
commInst(0x330, "@uvm.irbuilder.new_branch2")
commInst(0x331, "@uvm.irbuilder.new_switch")
commInst(0x332, "@uvm.irbuilder.new_call")
commInst(0x333, "@uvm.irbuilder.new_tailcall")
commInst(0x334, "@uvm.irbuilder.new_ret")
commInst(0x335, "@uvm.irbuilder.new_throw")
commInst(0x336, "@uvm.irbuilder.new_extractvalue")
commInst(0x337, "@uvm.irbuilder.new_insertvalue")
commInst(0x338, "@uvm.irbuilder.new_extractelement")
commInst(0x339, "@uvm.irbuilder.new_insertelement")
commInst(0x33a, "@uvm.irbuilder.new_shufflevector")
commInst(0x33b, "@uvm.irbuilder.new_new")
commInst(0x33c, "@uvm.irbuilder.new_newhybrid")
commInst(0x33d, "@uvm.irbuilder.new_alloca")
commInst(0x33e, "@uvm.irbuilder.new_allocahybrid")
commInst(0x33f, "@uvm.irbuilder.new_getiref")
commInst(0x340, "@uvm.irbuilder.new_getfieldiref")
commInst(0x341, "@uvm.irbuilder.new_getelemiref")
commInst(0x342, "@uvm.irbuilder.new_shiftiref")
commInst(0x343, "@uvm.irbuilder.new_getvarpartiref")
commInst(0x344, "@uvm.irbuilder.new_load")
commInst(0x345, "@uvm.irbuilder.new_store")
commInst(0x346, "@uvm.irbuilder.new_cmpxchg")
commInst(0x347, "@uvm.irbuilder.new_atomicrmw")
commInst(0x348, "@uvm.irbuilder.new_fence")
commInst(0x349, "@uvm.irbuilder.new_trap")
commInst(0x34a, "@uvm.irbuilder.new_watchpoint")
commInst(0x34b, "@uvm.irbuilder.new_wpbranch")
commInst(0x34c, "@uvm.irbuilder.new_ccall")
commInst(0x34d, "@uvm.irbuilder.new_newthread")
commInst(0x34e, "@uvm.irbuilder.new_swapstack")
commInst(0x34f, "@uvm.irbuilder.new_comminst")
/// GEN:END:IRBUILDER_COMMINSTS
}
......@@ -321,8 +321,8 @@ class BundleConstructor(idNameMap: Map[MuID, MuName], nodeList: Seq[IRBuilderNod
}
val muInst: Instruction = irInst match {
case NodeBinOp(id, resultID, optr, ty, opnd1, opnd2, excClause) =>
InstBinOp(optr, ty, opnd1, opnd2, null) --> resultID EXC excClause
case NodeBinOp(id, resultID, statusResultIDs, optr, flags, ty, opnd1, opnd2, excClause) =>
InstBinOp(optr, flags, ty, opnd1, opnd2, null) --> (Seq(resultID)++statusResultIDs) EXC excClause
case NodeCmp(id, resultID, optr, ty, opnd1, opnd2) =>
InstCmp(optr, ty, opnd1, opnd2) --> resultID
case NodeConv(id, resultID, optr, fromTy, toTy, opnd) =>
......
......@@ -100,6 +100,17 @@ class IRBuilder(val id: MuInternalID,
def genSym(): MuID = genSym(None)
def genSym(name: String): MuID = genSym(Some(name))
// Special cases
def newBinOp(id: MuID, resultID: MuID, optr: BinOptr.Value, ty: MuTypeNode, opnd1: MuVarNode, opnd2: MuVarNode, excClause: Option[MuExcClause]): Unit = {
newBinOp(id, resultID, Seq(), optr, 0, ty, opnd1, opnd2, excClause)
}
def newBinOpWithStatus(id: MuID, resultID: MuID, statusResultIDs: Seq[MuID], optr: BinOptr.Value, flags: BinOpStatus, ty: MuTypeNode, opnd1: MuVarNode, opnd2: MuVarNode, excClause: Option[MuExcClause]): Unit = {
newBinOp(id, resultID, statusResultIDs, optr, flags, ty, opnd1, opnd2, excClause)
}
// The following functions are generated from irBuilderNodes.scala by /migrate_scripts/irbuildernodestoirbuildermethods.py
// GEN:BEGIN:IRBUILDERNODE_CONSTRUCTORS
......@@ -255,8 +266,8 @@ class IRBuilder(val id: MuInternalID,
val _node = new NodeNscThrowExc(id, exc)
onNewNodeCreated(_node)
}
def newBinOp(id: MuID, resultID: MuID, optr: BinOptr.Value, ty: MuTypeNode, opnd1: MuVarNode, opnd2: MuVarNode, excClause: Option[MuExcClause]): Unit = {
val _node = new NodeBinOp(id, resultID, optr, ty, opnd1, opnd2, excClause)
def newBinOp(id: MuID, resultID: MuID, statusResultIDs: Seq[MuID], optr: BinOptr.Value, flags: BinOpStatus, ty: MuTypeNode, opnd1: MuVarNode, opnd2: MuVarNode, excClause: Option[MuExcClause]): Unit = {
val _node = new NodeBinOp(id, resultID, statusResultIDs, optr, flags, ty, opnd1, opnd2, excClause)
onNewNodeCreated(_node)
}
def newCmp(id: MuID, resultID: MuID, optr: CmpOptr.Value, ty: MuTypeNode, opnd1: MuVarNode, opnd2: MuVarNode): Unit = {
......
......@@ -111,7 +111,7 @@ case class NodeCscKillOld(id: MuID) extends IRCurStackClauseNode
case class NodeNscPassValues(id: MuID, tys: Seq[MuTypeNode], vars: Seq[MuVarNode]) extends IRNewStackClauseNode
case class NodeNscThrowExc(id: MuID, exc: MuVarNode) extends IRNewStackClauseNode
case class NodeBinOp(id: MuID, resultID: MuID, optr: BinOptr.Value, ty: MuTypeNode, opnd1: MuVarNode, opnd2: MuVarNode, excClause: Option[MuExcClause]) extends IRInstNode
case class NodeBinOp(id: MuID, resultID: MuID, statusResultIDs: Seq[MuID], optr: BinOptr.Value, flags: BinOpStatus, ty: MuTypeNode, opnd1: MuVarNode, opnd2: MuVarNode, excClause: Option[MuExcClause]) extends IRInstNode
case class NodeCmp(id: MuID, resultID: MuID, optr: CmpOptr.Value, ty: MuTypeNode, opnd1: MuVarNode, opnd2: MuVarNode) extends IRInstNode
case class NodeConv(id: MuID, resultID: MuID, optr: ConvOptr.Value, fromTy: MuTypeNode, toTy: MuTypeNode, opnd: MuVarNode) extends IRInstNode
case class NodeSelect(id: MuID, resultID: MuID, condTy: MuTypeNode, opndTy: MuTypeNode, cond: MuVarNode, ifTrue: MuVarNode, ifFalse: MuVarNode) extends IRInstNode
......
......@@ -458,13 +458,38 @@ private[textinput] class InstanceUIRTextReader(idFactory: IDFactory, source: Str
}
}
def resBinOpStatus(flagList: FlagListContext): BinOpStatus = {
if (flagList == null) {
return 0
}
var status = 0
val texts = flagList.flag().map(_.getText)
val ordered = Seq("#N", "#Z", "#C", "#V").filter(t => texts.contains(t))
if(ordered != texts ) {
throw new TextIRParsingException(inCtx(flagList, "Flags must appear in the order of #N #Z #C #V"))
}
for (text <- texts) {
val nextStatus = text match {
case "#N" => BOS_N
case "#Z" => BOS_Z
case "#C" => BOS_C
case "#V" => BOS_V
case _ => throw new TextIRParsingException(inCtx(flagList, "Unexpected flag %s".format()))
}
status = status | nextStatus
}
status
}
// Make instruction
def mkInst(bb: BasicBlock, instDef: InstContext): Instruction = {
val inst: Instruction = instDef.instBody match {
case ii: InstBinOpContext =>
InstBinOp(BinOptr.withName(ii.binop.getText), ii.`type`, null, null, null).later(phase4) { i =>
InstBinOp(BinOptr.withName(ii.binop.getText), resBinOpStatus(ii.flagList()), ii.`type`, null, null, null).later(phase4) { i =>
i.op1 = ii.op1; i.op2 = ii.op2; i.excClause = ii.excClause
}
case ii: InstCmpContext =>
......
......@@ -128,7 +128,7 @@ abstract class AbstractBundleSerializer(bundle: Bundle) {
implicit val bs = this
val body = inst match {
case InstBinOp(op, opndTy, op1, op2, excClause) => s"${op.s} <${opndTy.n}> ${op1.n} ${op2.n} ${excClause.e}"
case InstBinOp(op, flags, opndTy, op1, op2, excClause) => s"${op.s} ${flags.flags} <${opndTy.n}> ${op1.n} ${op2.n} ${excClause.e}"
case InstCmp(op, opndTy, op1, op2) => s"${op.s} <${opndTy.n}> ${op1.n} ${op2.n}"
case InstConv(op, fromTy, toTy, opnd) => s"${op.s} <${fromTy.n} ${toTy.n}> ${opnd.n}"
case InstSelect(condTy, opndTy, cond, ifTrue, ifFalse) => s"SELECT <${condTy.n} ${opndTy.n}> ${cond.n} ${ifTrue.n} ${ifFalse.n}"
......@@ -246,6 +246,14 @@ object AbstractBundleSerializer {
def p: String = if (value) "PTR" else ""
def w: String = if (value) "WEAK" else ""
}
implicit class MagicalBinOpStatus(val thing: BinOpStatus) extends AnyVal {
def flags: String = if (thing==0) "" else {
val nzcv = Seq((BOS_N, "N"), (BOS_Z, "Z"), (BOS_C, "C"), (BOS_V, "V")).flatMap { case (bit, txt) =>
if ((thing & bit) == 0) None else Some("#"+txt)
}
"[" + nzcv.mkString(" ") + "]"
}
}
}
/**
......
......@@ -258,7 +258,7 @@ class TransitiveClosureBuilder(initialSet: Seq[TopLevel], val primordial: Primor
}
private def visitInstruction(inst: Instruction): Unit = inst match {
case InstBinOp(op, opndTy, op1, op2, excClause) => tls += opndTy ?= op1 ?= op2 ??= excClause
case InstBinOp(op, flags, opndTy, op1, op2, excClause) => tls += opndTy ?= op1 ?= op2 ??= excClause
case InstCmp(op, opndTy, op1, op2) => tls += opndTy ?= op1 ?= op2
case InstConv(op, fromTy, toTy, opnd) => tls += fromTy += toTy ?= opnd
case InstSelect(condTy, opndTy, cond, ifTrue, ifFalse) => tls += condTy += opndTy ?= cond ?= ifTrue ?= ifFalse
......
......@@ -102,7 +102,7 @@ object TypeInferer {
}
def inferInstResultTypes(inst: Instruction): Seq[Type] = inst match {
case i: InstBinOp => Seq(i.opndTy)
case i: InstBinOp => Seq(i.opndTy) ++ Seq.fill(BinOpStatus.numOfFlags(i.flags))(I1)
case i: InstCmp => i.opndTy match {
case TypeVector(_, l) => Seq(vecOf(I1, l))
case _ => Seq(I1)
......@@ -241,6 +241,7 @@ object TypeInferer {
case "@uvm.irbuilder.new_nsc_pass_values" => Seq()
case "@uvm.irbuilder.new_nsc_throw_exc" => Seq()
case "@uvm.irbuilder.new_binop" => Seq()
case "@uvm.irbuilder.new_binop_with_status" => Seq()
case "@uvm.irbuilder.new_cmp" => Seq()
case "@uvm.irbuilder.new_conv" => Seq()
case "@uvm.irbuilder.new_select" => Seq()
......
......@@ -421,6 +421,22 @@ trait IRBuilderCommInstExecutor extends InterpreterActions with ObjectPinner {
val _rv = b.newBinOp(id, result_id, optr, ty, opnd1, opnd2, exc_clause)
continueNormally()
}
case "@uvm.irbuilder.new_binop_with_status" => {
val b = argList(0).asIRBuilder.getOrElse(throw new UvmNullGenRefException("CommInst arg %b must not be null"))
val id = argList(1).asInt32.toInt
val result_id = argList(2).asInt32.toInt
val status_result_ids = argList(3).asIRef
val n_status_result_ids = argList(4).asInt64.toLong
val optr = argList(5).asInt32.toInt
val status_flags = argList(6).asInt32.toInt
val ty = argList(7).asInt32.toInt
val opnd1 = argList(8).asInt32.toInt
val opnd2 = argList(9).asInt32.toInt
val exc_clause = argList(10).asInt32.toInt.asOptionalID
val _ary_status_result_ids = loadInt32Array(status_result_ids, n_status_result_ids)
val _rv = b.newBinOpWithStatus(id, result_id, _ary_status_result_ids, optr, status_flags, ty, opnd1, opnd2, exc_clause)
continueNormally()
}
case "@uvm.irbuilder.new_cmp" => {
val b = argList(0).asIRBuilder.getOrElse(throw new UvmNullGenRefException("CommInst arg %b must not be null"))
val id = argList(1).asInt32.toInt
......
......@@ -26,7 +26,7 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor {
microVM.stats.onInstExec(statInstName)
curInst match {
case i @ InstBinOp(op, opndTy, op1, op2, excClause) => {
case i @ InstBinOp(op, flags, opndTy, op1, op2, excClause) => {
val statOpName = op.toString()
microVM.stats.onInstExec(statInstName + "/" + statOpName)
......@@ -39,6 +39,22 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor {
}
}
def doFlags(): Unit = {
val (n, z, c, v) = opndTy match {
case TypeInt(l) => PrimOpHelpers.intBinOpFlags(op, l, op1.asIntRaw, op2.asIntRaw, results(0).asIntRaw, ctx)
case _ => throw new UvmRuntimeException(ctx + "BinOp flags are only applicable to scalar integer types. Actual type: %s".format(opndTy))
}
var nextResultIndex = 1
for ((bit, res) <- BinOpStatus.ALL_FLAGS zip Seq(n,z,c,v)) {
if ((flags & bit) != 0) {
val resultIndex = nextResultIndex
nextResultIndex += 1
results(resultIndex).asBoolean = res
}
}
}
try {
opndTy match {
case TypeVector(scalarTy, sz) => {
......@@ -46,7 +62,12 @@ trait InstructionExecutor extends InterpreterActions with CommInstExecutor {
doScalar(scalarTy, b1, b2, br)
}
}
case scalarTy => doScalar(scalarTy, op1, op2, results(0))
case scalarTy => {
doScalar(scalarTy, op1, op2, results(0))
if (flags != 0) {
doFlags()
}
}
}
continueNormally()
} catch {
......
......@@ -508,62 +508,6 @@ trait InterpreterActions extends InterpreterThreadState {
}
}
import MagicalBox.MagicalBox
implicit protected def ssaVariableToValueBox(v: SSAVariable): ValueBox = boxOf(v)
implicit protected def ssaVariableToMagicalBox(v: SSAVariable): MagicalBox = new MagicalBox(boxOf(v))
implicit protected def boxToMagicalBox(b: ValueBox): MagicalBox = new MagicalBox(b)
}
object MagicalBox {
implicit class MagicalBox(val box: ValueBox) extends AnyVal {
def asIntRaw: BigInt = box.asInstanceOf[BoxInt].value
def asInt32: BigInt = OpHelper.prepareUnsigned(box.asIntRaw, 32)
def asInt64: BigInt = OpHelper.prepareUnsigned(box.asIntRaw, 64)
def asUInt32: BigInt = OpHelper.prepareUnsigned(box.asIntRaw, 32)
def asUInt64: BigInt = OpHelper.prepareUnsigned(box.asIntRaw, 64)
def asSInt32: BigInt = OpHelper.prepareSigned(box.asIntRaw, 32)
def asSInt64: BigInt = OpHelper.prepareSigned(box.asIntRaw, 64)
def asInt1: BigInt = OpHelper.prepareUnsigned(box.asIntRaw, 1)
def asBoolean: Boolean = OpHelper.prepareUnsigned(box.asIntRaw, 1) == 1
def asFloat: Float = box.asInstanceOf[BoxFloat].value
def asDouble: Double = box.asInstanceOf[BoxDouble].value
def asPtr: Word = box.asInstanceOf[BoxPointer].addr
def asSeq: Seq[ValueBox] = box.asInstanceOf[BoxSeq].values
def asRef: Word = box.asInstanceOf[BoxRef].objRef
def asIRef: (Word, Word) = box.asInstanceOf[BoxIRef].oo
def asIRefLoc: Word = box.asInstanceOf[BoxIRef].addr
def asTR64Raw: Long = box.asInstanceOf[BoxTagRef64].raw
def asFunc: Option[Function] = box.asInstanceOf[BoxFunc].obj
def asThread: Option[InterpreterThread] = box.asInstanceOf[BoxThread].obj
def asStack: Option[InterpreterStack] = box.asInstanceOf[BoxStack].obj
def asFrameCursor: Option[FrameCursor] = box.asInstanceOf[BoxFrameCursor].obj
def asIRBuilder: Option[IRBuilder] = box.asInstanceOf[BoxIRBuilder].obj
def asIntRaw_=(v: BigInt): Unit = box.asInstanceOf[BoxInt].value = v
def asInt1_=(v: BigInt): Unit = box.setInt(v, 1)
def asInt32_=(v: BigInt): Unit = box.setInt(v, 32)
def asInt64_=(v: BigInt): Unit = box.setInt(v, 64)
def asUInt32_=(v: BigInt): Unit = box.setInt(v, 32)
def asUInt64_=(v: BigInt): Unit = box.setInt(v, 64)
def asSInt32_=(v: BigInt): Unit = box.setInt(v, 32)
def asSInt64_=(v: BigInt): Unit = box.setInt(v, 64)
def asBoolean_=(v: Boolean): Unit = box.setInt(if (v) 1 else 0, 1)
def asFloat_=(v: Float): Unit = box.asInstanceOf[BoxFloat].value = v
def asDouble_=(v: Double): Unit = box.asInstanceOf[BoxDouble].value = v
def asPtr_=(v: Word): Unit = box.asInstanceOf[BoxPointer].addr = v
def asSeq_=(vs: Seq[ValueBox]): Unit = { for ((dst, src) <- box.asSeq zip vs) { dst copyFrom src } }
def asRef_=(v: Word): Unit = box.asInstanceOf[BoxRef].objRef = v
def asIRef_=(oo: (Word, Word)): Unit = box.asInstanceOf[BoxIRef].oo = oo
def asTR64Raw_=(v: Long): Unit = box.asInstanceOf[BoxTagRef64].raw = v
def asFunc_=(v: Option[Function]): Unit = box.asInstanceOf[BoxFunc].obj = v
def asThread_=(v: Option[InterpreterThread]): Unit = box.asInstanceOf[BoxThread].obj = v
def asStack_=(v: Option[InterpreterStack]): Unit = box.asInstanceOf[BoxStack].obj = v
def asFrameCursor_=(v: Option[FrameCursor]): Unit = box.asInstanceOf[BoxFrameCursor].obj = v
def asIRBuilder_=(v: Option[IRBuilder]): Unit = box.asInstanceOf[BoxIRBuilder].obj = v
def getSInt(len: Int): BigInt = OpHelper.prepareSigned(box.asIntRaw, len)
def getUInt(len: Int): BigInt = OpHelper.prepareUnsigned(box.asIntRaw, len)
def setInt(v: BigInt, len: Int): Unit = box.asIntRaw = OpHelper.unprepare(v, len)
}
}
\ No newline at end of file
......@@ -201,6 +201,28 @@ object PrimOpHelpers {
})
}
def intBinOpFlags(op: BinOptr.BinOptr, l: Int, op1v: BigInt, op2v: BigInt, resv: BigInt, ctx: => String): (Boolean, Boolean, Boolean, Boolean) = {
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)
val (op1u, op1s) = (pu(op1v), ps(op1v))
val (op2u, op2s) = (pu(op2v), ps(op2v))
val (resu, ress) = (pu(resv), ps(resv))
val n = ress < 0
val z = resu == 0
val (c, v) = op match {
case BinOptr.ADD => (resu != op1u + op2u, ress != op1s + op2s)
case BinOptr.SUB => (resu != op1u - op2u, ress != op1s - op2s)
case BinOptr.MUL => (resu != op1u * op2u, ress != op1s * op2s)
case _ => (false, false)
}
(n, z, c, v)
}
def floatBinOp(op: BinOptr.BinOptr, op1v: Float, op2v: Float, ctx: => String): Float = {
op match {
case BinOptr.FADD => op1v + op2v
......
......@@ -16,4 +16,57 @@ package object itpr {
def BoxStack = BoxOpaque.apply[InterpreterStack] _
def BoxFrameCursor = BoxOpaque.apply[FrameCursor] _
def BoxIRBuilder = BoxOpaque.apply[IRBuilder] _
implicit class MagicalBox(val box: ValueBox) extends AnyVal {
def asIntRaw: BigInt = box.asInstanceOf[BoxInt].value
def asUInt(l: Int): BigInt = OpHelper.prepareUnsigned(box.asIntRaw, l)
def asSInt(l: Int): BigInt = OpHelper.prepareSigned(box.asIntRaw, l)
def asInt32: BigInt = asUInt(32)
def asInt64: BigInt = asUInt(64)
def asUInt32: BigInt = asUInt(32)
def asUInt64: BigInt = asUInt(64)
def asSInt32: BigInt = asSInt(32)
def asSInt64: BigInt = asSInt(64)
def asInt1: BigInt = OpHelper.prepareUnsigned(box.asIntRaw, 1)
def asBoolean: Boolean = OpHelper.prepareUnsigned(box.asIntRaw, 1) == 1
def asFloat: Float = box.asInstanceOf[BoxFloat].value
def asDouble: Double = box.asInstanceOf[BoxDouble].value
def asPtr: Word = box.asInstanceOf[BoxPointer].addr
def asSeq: Seq[ValueBox] = box.asInstanceOf[BoxSeq].values
def asRef: Word = box.asInstanceOf[BoxRef].objRef
def asIRef: (Word, Word) = box.asInstanceOf[BoxIRef].oo
def asIRefLoc: Word = box.asInstanceOf[BoxIRef].addr
def asTR64Raw: Long = box.asInstanceOf[BoxTagRef64].raw
def asFunc: Option[Function] = box.asInstanceOf[BoxFunc].obj
def asThread: Option[InterpreterThread] = box.asInstanceOf[BoxThread].obj
def asStack: Option[InterpreterStack] = box.asInstanceOf[BoxStack].obj
def asFrameCursor: Option[FrameCursor] = box.asInstanceOf[BoxFrameCursor].obj
def asIRBuilder: Option[IRBuilder] = box.asInstanceOf[BoxIRBuilder].obj
def asIntRaw_=(v: BigInt): Unit = box.asInstanceOf[BoxInt].value = v
def asInt1_=(v: BigInt): Unit = box.setInt(v, 1)
def asInt32_=(v: BigInt): Unit = box.setInt(v, 32)
def asInt64_=(v: BigInt): Unit = box.setInt(v, 64)
def asUInt32_=(v: BigInt): Unit = box.setInt(v, 32)
def asUInt64_=(v: BigInt): Unit = box.setInt(v, 64)
def asSInt32_=(v: BigInt): Unit = box.setInt(v, 32)
def asSInt64_=(v: BigInt): Unit = box.setInt(v, 64)
def asBoolean_=(v: Boolean): Unit = box.setInt(if (v) 1 else 0, 1)
def asFloat_=(v: Float): Unit = box.asInstanceOf[BoxFloat].value = v
def asDouble_=(v: Double): Unit = box.asInstanceOf[BoxDouble].value = v
def asPtr_=(v: Word): Unit = box.asInstanceOf[BoxPointer].addr = v
def asSeq_=(vs: Seq[ValueBox]): Unit = { for ((dst, src) <- box.asSeq zip vs) { dst copyFrom src } }
def asRef_=(v: Word): Unit = box.asInstanceOf[BoxRef].objRef = v
def asIRef_=(oo: (Word, Word)): Unit = box.asInstanceOf[BoxIRef].oo = oo
def asTR64Raw_=(v: Long): Unit = box.asInstanceOf[BoxTagRef64].raw = v
def asFunc_=(v: Option[Function]): Unit = box.asInstanceOf[BoxFunc].obj = v
def asThread_=(v: Option[InterpreterThread]): Unit = box.asInstanceOf[BoxThread].obj = v
def asStack_=(v: Option[InterpreterStack]): Unit = box.asInstanceOf[BoxStack].obj = v
def asFrameCursor_=(v: Option[FrameCursor]): Unit = box.asInstanceOf[BoxFrameCursor].obj = v
def asIRBuilder_=(v: Option[IRBuilder]): Unit = box.asInstanceOf[BoxIRBuilder].obj = v
def getSInt(len: Int): BigInt = OpHelper.prepareSigned(box.asIntRaw, len)
def getUInt(len: Int): BigInt = OpHelper.prepareUnsigned(box.asIntRaw, len)
def setInt(v: BigInt, len: Int): Unit = box.asIntRaw = OpHelper.unprepare(v, len)
}
}
\ No newline at end of file
This diff is collapsed.
......@@ -16,6 +16,7 @@ import uvm.refimpl._
import uvm.refimpl.MicroVM
import uvm.ssavariables.{ MemoryOrder, AtomicRMWOptr }
import uvm.ssavariables.Flag
import uvm.ssavariables.BinOpStatus
class ExposedMethod(name: String, jRetTy: JType, jParamTys: Array[JType], invokeFunc: Buffer => Unit) {
val closure = new SimpleClosure(name, invokeFunc)
......@@ -118,6 +119,8 @@ private object CDefsHelperFunctions {
bigNum
}
def toBinOpStatus(s: MuBinOpStatus): BinOpStatus = s
implicit class RichMuVM(val mvm: MicroVM) extends AnyVal {
def setTrapHandler(trap_handler: MuTrapHandlerFP, userdata: MuCPtr): Unit = {
mvm.setTrapHandler(new NativeTrapHandler(trap_handler, userdata))
......
......@@ -236,6 +236,7 @@ object NativeClientSupport {
type MuHowToResume = Int
type MuHowToResumePtr = IntPtr
type MuCallConv = Int
type MuBinOpStatus = Int
type MuBinOptr = Int
type MuCmpOptr = Int
type MuConvOptr = Int
......
package uvm
package object ssavariables {
type BinOpStatus = Int
val BOS_N: BinOpStatus = 1
val BOS_Z: BinOpStatus = 2
val BOS_C: BinOpStatus = 4
val BOS_V: BinOpStatus = 8