Commit ffdc3604 authored by Kunshan Wang's avatar Kunshan Wang

Fixed memory layout and memory op tests

parent ebe76f0d
FN=$1 FN=$1
sed -i 's/newClientAgent/newContext/g' $FN if [ x$SED == x ]; then
sed -i 's/\bca\b/ctx/g' $FN SED=sed
sed -i 's/ctx\.close()/ctx.closeContext()/g' $FN fi
sed -i 's/putInt("@i32",/i32(/g' $FN $SED -i 's/newClientAgent/newContext/g' $FN
sed -i 's/putInt("@i64",/i64(/g' $FN $SED -i 's/deleteHandle/deleteValue/g' $FN
sed -i 's/putConstant/handleFromConst/g' $FN $SED -i 's/\bca\b/ctx/g' $FN
sed -i 's/putGlobal/handleFromGlobal/g' $FN $SED -i 's/ctx\.close()/ctx.closeContext()/g' $FN
sed -i 's/putFunction/handleFromFunc/g' $FN $SED -i 's/putInt("@i32",/handleFromInt32(/g' $FN
sed -i 's/toInt(\(\w\+\),\s*signExt\s*=\s*true)/handleToSInt(\1.asInstanceOf[MuIntValue])/g' $FN $SED -i 's/putInt("@i64",/handleFromInt64(/g' $FN
sed -i 's/currentInstruction/curInst/g' $FN $SED -i 's/putInt("@i\(\d\+\)"\s*,\s*\([^)]*\))/handleFromInt(\2, \1)/g' $FN
sed -i 's/TrapRebindPassVoid/returnFromTrap/g' $FN $SED -i 's/putFloat("@float",/handleFromFloat(/g' $FN
sed -i 's/TrapRebindPassValue(\(\w\+\),\s*\(\w\+\)\s*)/Rebind(\1, PassValues(Seq(\2)))/g' $FN $SED -i 's/putDouble("@double",/handleFromDouble(/g' $FN
$SED -i 's/putConstant/handleFromConst/g' $FN
$SED -i 's/putGlobal/handleFromGlobal/g' $FN
$SED -i 's/putFunction/handleFromFunc/g' $FN
$SED -i 's/toInt(\(\w\+\),\s*\(signExt\s*=\s*\)\?true)/handleToSInt(\1.asInstanceOf[MuIntValue])/g' $FN
$SED -i 's/toFloat/handleToFloat/g' $FN
$SED -i 's/toDouble/handleToDouble/g' $FN
$SED -i 's/refCast/refcast/g' $FN
$SED -i 's/currentInstruction/curInst/g' $FN
$SED -i 's/TrapRebindPassVoid/returnFromTrap/g' $FN
$SED -i 's/TrapRebindPassValue(\(\w\+\),\s*\(\w\+\)\s*)/Rebind(\1, PassValues(Seq(\2)))/g' $FN
...@@ -12,6 +12,7 @@ import uvm.ssavariables.HasKeepAliveClause ...@@ -12,6 +12,7 @@ import uvm.ssavariables.HasKeepAliveClause
import scala.collection.mutable.ArrayBuffer import scala.collection.mutable.ArrayBuffer
import uvm.ssavariables.Flag import uvm.ssavariables.Flag
import uvm.refimpl.itpr.{ HowToResume => ItprHowToResume } import uvm.refimpl.itpr.{ HowToResume => ItprHowToResume }
import scala.collection.mutable.Buffer
object MuValue { object MuValue {
def apply(ty: Type, vb: ValueBox): MuValue = (ty, vb) match { def apply(ty: Type, vb: ValueBox): MuValue = (ty, vb) match {
...@@ -90,6 +91,10 @@ trait UndefinedFunctionHandler { ...@@ -90,6 +91,10 @@ trait UndefinedFunctionHandler {
def handleUndefinedFunction(functionID: Int): Unit def handleUndefinedFunction(functionID: Int): Unit
} }
/**
* A client context. The main part of the API. It keeps thread-local states, including a set of handles. It provides
* operations on the Mu VM.
*/
class MuCtx(mutator: Mutator)( class MuCtx(mutator: Mutator)(
implicit microVM: MicroVM, memorySupport: MemorySupport) extends ObjectPinner { implicit microVM: MicroVM, memorySupport: MemorySupport) extends ObjectPinner {
val handles = new HashSet[MuValue]() val handles = new HashSet[MuValue]()
...@@ -317,7 +322,7 @@ class MuCtx(mutator: Mutator)( ...@@ -317,7 +322,7 @@ class MuCtx(mutator: Mutator)(
} }
/** Cast between two refs, two irefs or two funcrefs */ /** Cast between two refs, two irefs or two funcrefs */
def refcast(opnd: MuValue, newType: Int): MuValue = { def refcast[T <: MuGenRefValue](opnd: T, newType: Int): T = {
val nt = microVM.globalBundle.typeNs(newType) val nt = microVM.globalBundle.typeNs(newType)
val nh = (opnd, nt) match { val nh = (opnd, nt) match {
...@@ -330,7 +335,7 @@ class MuCtx(mutator: Mutator)( ...@@ -330,7 +335,7 @@ class MuCtx(mutator: Mutator)(
} }
} }
addHandle(nh) addHandle(nh.asInstanceOf[T])
} }
/** Convert ref to iref */ /** Convert ref to iref */
...@@ -424,7 +429,7 @@ class MuCtx(mutator: Mutator)( ...@@ -424,7 +429,7 @@ class MuCtx(mutator: Mutator)(
MemoryOperations.store(ptr, uty, addr, nvb) MemoryOperations.store(ptr, uty, addr, nvb)
} }
/** Perform compare exchange on a location. */ /** Perform compare exchange on a location. */
def cmpXchg(ordSucc: MemoryOrder, ordFail: MemoryOrder, weak: Boolean, def cmpXchg(ordSucc: MemoryOrder, ordFail: MemoryOrder, weak: Boolean,
loc: MuIRefValue, expected: MuValue, desired: MuValue): (MuValue, Boolean) = { loc: MuIRefValue, expected: MuValue, desired: MuValue): (MuValue, Boolean) = {
val (ptr, ty) = loc.ty match { val (ptr, ty) = loc.ty match {
...@@ -522,8 +527,10 @@ class MuCtx(mutator: Mutator)( ...@@ -522,8 +527,10 @@ class MuCtx(mutator: Mutator)(
} }
} }
/** Get the ID of the current function version of a frame. Return 0 for native frames /**
* or Mu frames of undefined functions*/ * Get the ID of the current function version of a frame. Return 0 for native frames
* or Mu frames of undefined functions
*/
def curFuncVer(stack: MuStackRefValue, frame: Int): Int = { def curFuncVer(stack: MuStackRefValue, frame: Int): Int = {
val sv = getStackNotNull(stack) val sv = getStackNotNull(stack)
val fr = nthFrame(sv, frame) val fr = nthFrame(sv, frame)
...@@ -534,8 +541,10 @@ class MuCtx(mutator: Mutator)( ...@@ -534,8 +541,10 @@ class MuCtx(mutator: Mutator)(
} }
} }
/** Get the ID of the current instruction of a frame. Return 0 for native frames, Mu frames for undefined /**
* functions, or if the frame is just created by newStack or pushFrame. */ * Get the ID of the current instruction of a frame. Return 0 for native frames, Mu frames for undefined
* functions, or if the frame is just created by newStack or pushFrame.
*/
def curInst(stack: MuStackRefValue, frame: Int): Int = { def curInst(stack: MuStackRefValue, frame: Int): Int = {
val sv = getStackNotNull(stack) val sv = getStackNotNull(stack)
val fr = nthFrame(sv, frame) val fr = nthFrame(sv, frame)
...@@ -655,7 +664,7 @@ class MuCtx(mutator: Mutator)( ...@@ -655,7 +664,7 @@ class MuCtx(mutator: Mutator)(
/** Convert an object ref and a tag to a tagref64. */ /** Convert an object ref and a tag to a tagref64. */
def tr64FromRef(ref: MuRefValue, tag: MuIntValue): MuTagRef64Value = { def tr64FromRef(ref: MuRefValue, tag: MuIntValue): MuTagRef64Value = {
if (tag.ty.length != 52) throw new IllegalArgumentException("Expect int<6> tag, found %s".format(tag.ty.repr)) if (tag.ty.length != 6) throw new IllegalArgumentException("Expect int<6> tag, found %s".format(tag.ty.repr))
val refv = ref.vb.objRef val refv = ref.vb.objRef
val tagv = tag.vb.value val tagv = tag.vb.value
val box = new BoxTagRef64(OpHelper.refToTr64(refv, tagv.longValue)) val box = new BoxTagRef64(OpHelper.refToTr64(refv, tagv.longValue))
...@@ -725,5 +734,56 @@ class MuCtx(mutator: Mutator)( ...@@ -725,5 +734,56 @@ class MuCtx(mutator: Mutator)(
val box = BoxStack(sta) val box = BoxStack(sta)
addHandle(MuStackRefValue(s, box)) addHandle(MuStackRefValue(s, box))
} }
}
object RichMuCtx {
/** Extensions to the MuCtx interface. Not officially part of the client API. */
implicit class RichMuCtx(ctx: MuCtx) {
def handleFromBoolean(b: Boolean) = ctx.handleFromInt(if (b) 1 else 0, 1)
def handleFromInt1(num: BigInt) = ctx.handleFromInt(num, 1)
def handleFromInt6(num: BigInt) = ctx.handleFromInt(num, 6)
def handleFromInt8(num: BigInt) = ctx.handleFromInt(num, 8)
def handleFromInt16(num: BigInt) = ctx.handleFromInt(num, 16)
def handleFromInt32(num: BigInt) = ctx.handleFromInt(num, 32)
def handleFromInt52(num: BigInt) = ctx.handleFromInt(num, 52)
def handleFromInt64(num: BigInt) = ctx.handleFromInt(num, 64)
def deleteValue(vs: MuValue*) = vs.foreach(ctx.deleteValue)
class DelayedDisposer(garbageList: Buffer[MuValue]) {
def apply[T<:MuValue](v: T): T = {
garbageList += v
v
}
}
def autoDispose[T](f: DelayedDisposer => T) = {
val garbages = ArrayBuffer[MuValue]()
val dd = new DelayedDisposer(garbages)
val rv = f(dd)
garbages.foreach(ctx.deleteValue)
rv
}
def loadInt(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuIntValue]
def loadFloat(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuFloatValue]
def loadDouble(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuDoubleValue]
def loadRef(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuRefValue]
def loadIRef(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuIRefValue]
def loadFuncRef(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuFuncRefValue]
def loadThreadRef(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuThreadRefValue]
def loadStackRef(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuStackRefValue]
def loadTagRef64(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuTagRef64Value]
def loadVector(ord: MemoryOrder, loc: MuIRefValue) = ctx.load(ord, loc).asInstanceOf[MuVectorValue]
def storeInt(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuIntValue]
def storeFloat(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuFloatValue]
def storeDouble(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuDoubleValue]
def storeRef(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuRefValue]
def storeIRef(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuIRefValue]
def storeFuncRef(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuFuncRefValue]
def storeThreadRef(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuThreadRefValue]
def storeStackRef(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuStackRefValue]
def storeTagRef64(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuTagRef64Value]
def storeVector(ord: MemoryOrder, loc: MuIRefValue, newval: MuValue) = ctx.store(ord, loc, newval).asInstanceOf[MuVectorValue]
}
} }
\ No newline at end of file
...@@ -95,11 +95,7 @@ abstract class UvmBundleTesterBase extends FlatSpec with Matchers { ...@@ -95,11 +95,7 @@ abstract class UvmBundleTesterBase extends FlatSpec with Matchers {
def asPointer: Word = vb.asInstanceOf[BoxPointer].addr def asPointer: Word = vb.asInstanceOf[BoxPointer].addr
} }
implicit class RichMuCtx(ctx: MuCtx) { implicit def richMuCtx(ctx: MuCtx) = RichMuCtx.RichMuCtx(ctx)
def i32(num: BigInt) = ctx.handleFromInt(num, 32)
def i64(num: BigInt) = ctx.handleFromInt(num, 64)
def func(id: Int) = ctx.handleFromFunc(id)
}
def returnFromTrap(st: MuStackRefValue) = Rebind(st, PassValues(Seq())) def returnFromTrap(st: MuStackRefValue) = Rebind(st, PassValues(Seq()))
} }
\ No newline at end of file
...@@ -146,10 +146,10 @@ class UvmInterpreterFutexTests extends UvmBundleTesterBase { ...@@ -146,10 +146,10 @@ class UvmInterpreterFutexTests extends UvmBundleTesterBase {
val nthr2 = nt2.vb.asThread.get val nthr2 = nt2.vb.asThread.get
if (nthr.isFutexWaiting && nthr2.isFutexWaiting) { if (nthr.isFutexWaiting && nthr2.isFutexWaiting) {
val one = ctx.i32(1) val one = ctx.handleFromInt32(1)
Rebind(st, PassValues(Seq(one))) Rebind(st, PassValues(Seq(one)))
} else { } else {
val zero = ctx.i32(0) val zero = ctx.handleFromInt32(0)
Rebind(st, PassValues(Seq(zero))) Rebind(st, PassValues(Seq(zero)))
} }
} }
...@@ -215,10 +215,10 @@ class UvmInterpreterFutexTests extends UvmBundleTesterBase { ...@@ -215,10 +215,10 @@ class UvmInterpreterFutexTests extends UvmBundleTesterBase {
val nthr = nt.vb.asThread.get val nthr = nt.vb.asThread.get
if (nthr.isFutexWaiting) { if (nthr.isFutexWaiting) {
val one = ctx.i32(1) val one = ctx.handleFromInt32(1)
Rebind(st, PassValues(Seq(one))) Rebind(st, PassValues(Seq(one)))
} else { } else {
val zero = ctx.i32(0) val zero = ctx.handleFromInt32(0)
Rebind(st, PassValues(Seq(zero))) Rebind(st, PassValues(Seq(zero)))
} }
} }
......
...@@ -19,7 +19,7 @@ class UvmMemLayoutSpec extends FlatSpec with Matchers with BeforeAndAfter { ...@@ -19,7 +19,7 @@ class UvmMemLayoutSpec extends FlatSpec with Matchers with BeforeAndAfter {
sizeOf(TypeIRef(TypeVoid())) shouldBe 16 sizeOf(TypeIRef(TypeVoid())) shouldBe 16
sizeOf(TypeWeakRef(TypeVoid())) shouldBe 8 sizeOf(TypeWeakRef(TypeVoid())) shouldBe 8
sizeOf(TypeVoid()) shouldBe 0 sizeOf(TypeVoid()) shouldBe 0
sizeOf(TypeFuncRef(FuncSig(TypeVoid(), Seq()))) shouldBe 8 sizeOf(TypeFuncRef(FuncSig(Seq(), Seq()))) shouldBe 8
sizeOf(TypeThreadRef()) shouldBe 8 sizeOf(TypeThreadRef()) shouldBe 8
sizeOf(TypeStackRef()) shouldBe 8 sizeOf(TypeStackRef()) shouldBe 8
sizeOf(TypeTagRef64()) shouldBe 8 sizeOf(TypeTagRef64()) shouldBe 8
...@@ -36,7 +36,7 @@ class UvmMemLayoutSpec extends FlatSpec with Matchers with BeforeAndAfter { ...@@ -36,7 +36,7 @@ class UvmMemLayoutSpec extends FlatSpec with Matchers with BeforeAndAfter {
alignOf(TypeIRef(TypeVoid())) shouldBe 16 alignOf(TypeIRef(TypeVoid())) shouldBe 16
alignOf(TypeWeakRef(TypeVoid())) shouldBe 8 alignOf(TypeWeakRef(TypeVoid())) shouldBe 8
alignOf(TypeVoid()) shouldBe 1 alignOf(TypeVoid()) shouldBe 1
alignOf(TypeFuncRef(FuncSig(TypeVoid(), Seq()))) shouldBe 8 alignOf(TypeFuncRef(FuncSig(Seq(), Seq()))) shouldBe 8
alignOf(TypeThreadRef()) shouldBe 8 alignOf(TypeThreadRef()) shouldBe 8
alignOf(TypeStackRef()) shouldBe 8 alignOf(TypeStackRef()) shouldBe 8
alignOf(TypeTagRef64()) shouldBe 8 alignOf(TypeTagRef64()) shouldBe 8
...@@ -75,10 +75,20 @@ class UvmMemLayoutSpec extends FlatSpec with Matchers with BeforeAndAfter { ...@@ -75,10 +75,20 @@ class UvmMemLayoutSpec extends FlatSpec with Matchers with BeforeAndAfter {
} }
"In a hybrid, fields" should "be laid out in the fixed-then-var fasion" in { "In a hybrid, fields" should "be laid out in the fixed-then-var fasion" in {
val ty = TypeHybrid(TypeInt(16), TypeDouble()) val ty = TypeHybrid(Seq(TypeInt(8), TypeInt(16), TypeInt(32), TypeInt(64)), TypeDouble())
hybridSizeOf(ty, 10) shouldBe 88 hybridSizeOf(ty, 10) shouldBe 96
hybridAlignOf(ty, 10) shouldBe 8 hybridAlignOf(ty, 10) shouldBe 8
fixedPartOffsetOf(ty) shouldBe 0 fieldOffsetOf(ty, 0) shouldBe 0
varPartOffsetOf(ty) shouldBe 8 fieldOffsetOf(ty, 1) shouldBe 2
fieldOffsetOf(ty, 2) shouldBe 4
fieldOffsetOf(ty, 3) shouldBe 8
varPartOffsetOf(ty) shouldBe 16
}
"In a hybrid with no fixed parts, the variable part" should "have offset 0" in {
val ty = TypeHybrid(Seq(), TypeFloat())
hybridSizeOf(ty, 10) shouldBe 40
hybridAlignOf(ty, 10) shouldBe 4
varPartOffsetOf(ty) shouldBe 0
} }
} }
\ No newline at end of file
.typedef @i1 = int<1> // require 'primitives.uir'
.typedef @i8 = int<8>
.typedef @i16 = int<16>
.typedef @i32 = int<32>
.typedef @i64 = int<64>
.typedef @float = float
.typedef @double = double
.typedef @rv = ref<@void>
.typedef @irv = iref<@void>
.typedef @wrv = weakref<@void>
.const @NULLRV <@rv> = NULL
.const @NULLIRV <@irv> = NULL
.typedef @ri16 = ref<@i16> .typedef @ri16 = ref<@i16>
.typedef @s1 = struct<@i8 @i16 @i32 @i64 @float @double @rv @irv @wrv @ri16> .typedef @s1 = struct<@i8 @i16 @i32 @i64 @float @double @refvoid @irefvoid @weakrefvoid @ri16>
.typedef @Cons = struct<@i64 @RefCons> .typedef @Cons = struct<@i64 @RefCons>
.typedef @RefCons = ref<@Cons> .typedef @RefCons = ref<@Cons>
...@@ -27,33 +13,20 @@ ...@@ -27,33 +13,20 @@
.typedef @a1 = array<@foo 10> .typedef @a1 = array<@foo 10>
.typedef @a2 = array<@a1 10> .typedef @a2 = array<@a1 10>
.typedef @h0 = hybrid <@void @i8> .typedef @h0 = hybrid <@i8>
.typedef @h1 = hybrid <@foo @i64> .typedef @h1 = hybrid <@foo @i64>
.typedef @void = void .funcsig @sig0 = () -> ()
.funcsig @sig0 = @void ()
.typedef @ii8 = iref<@i8> .typedef @ii8 = iref<@i8>
.typedef @iii8 = iref<@ii8> .typedef @iii8 = iref<@ii8>
.funcsig @sig1 = @i32 (@i32 @iii8) .funcsig @sig1 = (@i32 @iii8) -> (@i32)
.typedef @f0 = funcref<@sig0> .typedef @f0 = funcref<@sig0>
.typedef @f1 = funcref<@sig1> .typedef @f1 = funcref<@sig1>
.typedef @th = threadref .typedef @s2 = struct<@f0 @thread @stack @tagref64>
.typedef @st = stackref
.typedef @tr64 = tagref64
.typedef @i6 = int<6>
.typedef @i52 = int<52>
.typedef @s2 = struct<@f0 @th @st @tr64>
.typedef @4xfloat = vector <@float 4>
.typedef @4xi32 = vector <@i32 4>
.typedef @2xdouble = vector <@double 2>
.funcdecl @fun <@sig0> .funcdecl @fun <@sig0>
.funcdecl @fun2 <@sig0> .funcdecl @fun2 <@sig0>
.const @NULLF0 <@f0> = NULL .const @NULLF0 <@f0> = NULL
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