Commit cf9b01d9 authored by Kunshan Wang's avatar Kunshan Wang

Tested binop, cmp, conversion and select.

parent 6dbde1d3
......@@ -33,7 +33,7 @@ class Bundle {
val constantNs = new SimpleNamespace[Constant]()
val globalCellNs = new SimpleNamespace[GlobalCell]()
val funcNs = new SimpleNamespace[Function]()
private def simpleMerge[T <: Identified](oldNs: Namespace[T], newNs: Namespace[T]) {
for (cand <- newNs.all) {
if (!cand.isInstanceOf[Function] || oldNs.get(cand.id) == None) {
......
......@@ -26,6 +26,17 @@ class MicroVM(heapSize: Word = MicroVM.DEFAULT_HEAP_SIZE,
val clientAgents = new HashSet[ClientAgent]()
val irReader = new UIRTextReader(new IDFactory())
{
// The µVM allocates stacks on the heap in the large object space. It is represented as a bug chunk of byte array.
// So the GC must know about this type because the GC looks up the globalBundle for types.
globalBundle.allNs.add(InternalTypes.VOID)
globalBundle.typeNs.add(InternalTypes.VOID)
globalBundle.allNs.add(InternalTypes.BYTE)
globalBundle.typeNs.add(InternalTypes.BYTE)
globalBundle.allNs.add(InternalTypes.BYTE_ARRAY)
globalBundle.typeNs.add(InternalTypes.BYTE_ARRAY)
}
/**
* Add things from a bundle to the Micro VM.
......
......@@ -66,7 +66,10 @@ object TypeInferer {
case f: Function => funcOf(f.sig)
case p: Parameter => p.funcVer.sig.paramTy(p.index)
case i: InstBinOp => i.opndTy
case i: InstCmp => I1
case i: InstCmp => i.opndTy match {
case TypeVector(_, l) => vecOf(I1, l)
case _ => I1
}
case i: InstConv => i.toTy
case i: InstSelect => i.opndTy
case i: InstBranch => VOID
......
......@@ -20,7 +20,7 @@ class ConstantPool(microVM: MicroVM) {
}
def makeBox(g: GlobalVariable): ValueBox = g match {
case ConstInt(ty, num) => BoxInt(num & (1 << ty.asInstanceOf[TypeInt].length))
case ConstInt(ty, num) => BoxInt(OpHelper.unprepare(num, ty.asInstanceOf[TypeInt].length))
case ConstFloat(ty, num) => BoxFloat(num)
case ConstDouble(ty, num) => BoxDouble(num)
case ConstStruct(ty, flds) => BoxStruct(flds.map(maybeMakeBox))
......@@ -31,6 +31,7 @@ class ConstantPool(microVM: MicroVM) {
case _:TypeThread => BoxThread(None)
case _:TypeStack => BoxStack(None)
}
case ConstVector(ty, elems) => BoxVector(elems.map(maybeMakeBox))
case gc:GlobalCell => BoxIRef(0L, microVM.memoryManager.globalMemory.addrForGlobalCell(gc))
case f:Function => BoxFunc(Some(f))
}
......
......@@ -255,14 +255,14 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
case ConvOptr.ZEXT => iToI()
case ConvOptr.SEXT => iToI()
case ConvOptr.FPTRUNC => {
val od = opnd.asInstanceOf[BoxDouble].value
val od = bOpnd.asInstanceOf[BoxDouble].value
val result = od.toFloat
boxOf(i).asInstanceOf[BoxFloat].value = result
br.asInstanceOf[BoxFloat].value = result
}
case ConvOptr.FPEXT => {
val od = opnd.asInstanceOf[BoxFloat].value
val od = bOpnd.asInstanceOf[BoxFloat].value
val result = od.toDouble
boxOf(i).asInstanceOf[BoxDouble].value = result
br.asInstanceOf[BoxDouble].value = result
}
case ConvOptr.FPTOUI => fpToI(signed = false)
case ConvOptr.FPTOSI => fpToI(signed = true)
......@@ -290,9 +290,10 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
incPC()
}
case i @ InstSelect(opndTy, condTy, cond, ifTrue, ifFalse) => {
case i @ InstSelect(condTy, opndTy, cond, ifTrue, ifFalse) => {
def doScalar(bCond: ValueBox, bTrue: ValueBox, bFalse: ValueBox, br: ValueBox): Unit = {
val c = bCond.asInstanceOf[BoxInt].value
if (c == 1) {
br.copyFrom(bTrue)
} else {
......@@ -314,7 +315,7 @@ class InterpreterThread(val id: Int, microVM: MicroVM, initialStack: Interpreter
case TypeInt(1) => {
doScalar(boxOf(cond), boxOf(ifTrue), boxOf(ifFalse), boxOf(i))
}
case _ => throw new UvmRefImplException(ctx + "Condition must be either int<1> or a vector of int<1>")
case _ => throw new UvmRefImplException(ctx + "Condition must be either int<1> or a vector of int<1>. Found %s".format(condTy))
}
continueNormally()
......
......@@ -56,7 +56,7 @@ class ThreadStackManager(microVM: MicroVM) {
do {
someRunning = false
val curThreads = threadRegistry.values.toList
for (thr2 <- curThreads) {
for (thr2 <- curThreads if thr2.isRunning) {
thr2.step()
someRunning = thr2.isRunning || someRunning
}
......
......@@ -57,7 +57,13 @@ class InterpreterFrame(val funcVer: FuncVer, val prev: Option[InterpreterFrame])
boxes.put(lv, ValueBox.makeBoxForType(ty))
}
def curInst: Instruction = curBB.insts(curInstIndex)
def curInst: Instruction = try {
curBB.insts(curInstIndex)
} catch {
case e: IndexOutOfBoundsException =>
throw new UvmRefImplException(("Current instruction beyond the last instruction of a basic block. " +
"FuncVer: %s, BasicBlock: %s").format(funcVer.repr, curBB.repr))
}
def incPC() {
curInstIndex += 1
......
......@@ -150,7 +150,7 @@ case class InstCmp(var op: CmpOptr, var opndTy: Type, var op1: SSAVariable, var
case class InstConv(var op: ConvOptr, var fromTy: Type, var toTy: Type, var opnd: SSAVariable) extends Instruction
case class InstSelect(var opndTy: Type, var condTy: Type,
case class InstSelect(var condTy: Type, var opndTy: Type,
var cond: SSAVariable, var ifTrue: SSAVariable, var ifFalse: SSAVariable) extends Instruction
case class InstBranch(var dest: BasicBlock) extends Instruction
......
......@@ -164,6 +164,14 @@
RETVOID
}
.funcsig @select_sig = @void ()
.funcdef @select VERSION @select_v1 <@select_sig> () {
%entry:
%select = SELECT <@i1 @i32> @TRUE @I32_0 @I32_1
RETVOID
}
.funcsig @ctrlFlow_sig = @void (@i32)
.funcdef @ctrlFlow VERSION @ctrlFlow_v1 <@ctrlFlow_sig> (%p0) {
%entry:
......
......@@ -59,14 +59,14 @@
.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 @4xI32_V1 <@4xi32> = VEC {@I32_0 @I32_1 @I32_2 @I32_3}
.const @4xI32_V2 <@4xi32> = VEC {@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 @4xF_V1 <@4xfloat> = VEC {@F_0 @F_1 @F_2 @F_3}
.const @4xF_V2 <@4xfloat> = VEC {@F_4 @F_5 @F_6 @F_7}
.const @2xD_V1 <@2xdouble> = {@D_0 @D_1}
.const @2xD_V2 <@2xdouble> = {@D_2 @D_3}
.const @2xD_V1 <@2xdouble> = VEC {@D_0 @D_1}
.const @2xD_V2 <@2xdouble> = VEC {@D_2 @D_3}
.funcsig @i_ii = @i64 (@i64 @i64)
......@@ -209,8 +209,6 @@
%trap = TRAP <@void> KEEPALIVE (
%eq %ne %ult %ule %ugt %uge %slt %sle %sgt %sge
)
%exit:
COMMINST @uvm.thread_exit
}
......@@ -238,8 +236,6 @@
%ftrue %ffalse %ford %foeq %fone %folt %fole %fogt %foge
%funo %fueq %fune %fult %fule %fugt %fuge
)
%exit:
COMMINST @uvm.thread_exit
}
......@@ -267,8 +263,22 @@
%ftrue %ffalse %ford %foeq %fone %folt %fole %fogt %foge
%funo %fueq %fune %fult %fule %fugt %fuge
)
%exit:
COMMINST @uvm.thread_exit
}
.funcsig @cmp_vec_sig = @void (@4xi32 @4xi32 @4xfloat @4xfloat @2xdouble @2xdouble)
.funcdef @cmp_vec VERSION @cmp_vec_v1 <@cmp_vec_sig> (%p0 %p1 %p2 %p3 %p4 %p5) {
%entry:
%eq = EQ <@4xi32> %p0 %p1
%slt = SLT <@4xi32> %p0 %p1
%foeqf = FOEQ <@4xfloat> %p2 %p3
%fultf = FULT <@4xfloat> %p2 %p3
%foeqd = FOEQ <@2xdouble> %p4 %p5
%fultd = FULT <@2xdouble> %p4 %p5
%trap = TRAP <@void> KEEPALIVE (
%eq %slt %foeqf %fultf %foeqd %fultd
)
COMMINST @uvm.thread_exit
}
......@@ -282,24 +292,51 @@
%fptrunc = FPTRUNC <@double @float> %p3
%fpext = FPEXT <@float @double> %p2
%fptoui = FPTOUI <@double @i64> %p3
%fptosi = FPTOSI <@double @i64> %p3
%fptoui1 = FPTOUI <@double @i64> %p3
%fptosi1 = FPTOSI <@double @i64> %p3
%fptoui2 = FPTOUI <@float @i32> %p2
%fptosi2 = FPTOSI <@float @i32> %p2
%uitofp = UITOFP <@i64 @double> %p1
%sitofp = SITOFP <@i64 @double> %p1
%bitcast = BITCAST <@double @i64> %p3
%bitcast1 = BITCAST <@float @i32> %p2
%bitcast2 = BITCAST <@double @i64> %p3
%bitcast3 = BITCAST <@i32 @float > %bitcast1
%bitcast4 = BITCAST <@i64 @double> %bitcast2
%trap = TRAP <@void> KEEPALIVE (
%trunc %zext %sext %fptrunc %fpext %fptoui %fptosi %uitofp %sitofp
%bitcast
%trunc %zext %sext %fptrunc %fpext
%fptoui1 %fptosi1 %fptoui2 %fptosi2 %uitofp %sitofp
%bitcast1 %bitcast2 %bitcast3 %bitcast4
)
%exit:
COMMINST @uvm.thread_exit
}
.typedef @4xi16 = vector <@i16 4>
.typedef @4xi64 = vector <@i64 4>
.typedef @4xdouble = vector <@double 4>
.typedef @2xfloat = vector <@float 2>
.funcsig @conv_vec_sig = @void (@4xi32 @4xfloat @2xdouble)
.funcdef @conv_vec VERSION @conv_vec_v1 <@conv_vec_sig> (%p0 %p1 %p2) {
%entry:
%trunc = TRUNC <@4xi32 @4xi16> %p0
%zext = ZEXT <@4xi32 @4xi64> %p0
%sext = SEXT <@4xi32 @4xi64> %p0
%fptrunc = FPTRUNC <@2xdouble @2xfloat> %p2
%fpext = FPEXT <@4xfloat @4xdouble> %p1
%trap = TRAP <@void> KEEPALIVE (
%trunc %zext %sext %fptrunc %fpext
)
COMMINST @uvm.thread_exit
}
.typedef @4xi1 = vector <@i1 4>
.const @4xI1_COND <@4xi1> = {@TRUE @FALSE @FALSE @TRUE}
.const @4xI1_COND <@4xi1> = VEC {@TRUE @FALSE @FALSE @TRUE}
.funcdef @select VERSION @select_v1 <@noparamsnoret> () {
%entry:
......@@ -314,8 +351,6 @@
%trap = TRAP <@void> KEEPALIVE (
%sel1 %sel2 %sel3 %sel4 %sel5
)
%exit:
COMMINST @uvm.thread_exit
}
......
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