Commit 5c2d1c03 authored by Kunshan Wang's avatar Kunshan Wang

Adding uvm.meta.* comminsts...

parent 6b3ecf77
......@@ -39,4 +39,23 @@ object CommInsts extends SimpleNamespace[CommInst] {
commInst(0x242, "@uvm.native.expose")
commInst(0x243, "@uvm.native.unexpose")
commInst(0x244, "@uvm.native.get_cookie")
commInst(0x250, "@uvm.meta.id_of")
commInst(0x251, "@uvm.meta.name_of")
commInst(0x252, "@uvm.meta.load_bundle")
commInst(0x253, "@uvm.meta.load_hail")
commInst(0x254, "@uvm.meta.cur_func")
commInst(0x255, "@uvm.meta.cur_func_ver")
commInst(0x256, "@uvm.meta.cur_inst")
commInst(0x257, "@uvm.meta.dump_keepalives")
commInst(0x258, "@uvm.meta.pop_frame")
commInst(0x259, "@uvm.meta.push_frame")
commInst(0x25a, "@uvm.meta.enable_watchpoint")
commInst(0x25b, "@uvm.meta.disable_watchpoint")
commInst(0x25c, "@uvm.meta.set_trap_handler")
}
\ No newline at end of file
package uvm.refimpl
import java.io.Reader
import uvm.refimpl.mem.Mutator
/** Common implementations of operations on the MicroVM. Used by both the MuCtx and many comminsts. */
object MetaOperations {
/** Load a Mu IR bundle */
def loadBundle(r: Reader)(implicit microVM: MicroVM): Unit = {
val bundle = microVM.irReader.read(r, microVM.globalBundle)
microVM.addBundle(bundle)
}
/** Load a Mu IR bundle */
def loadBundle(s: String)(implicit microVM: MicroVM): Unit = {
val bundle = microVM.irReader.read(s, microVM.globalBundle)
microVM.addBundle(bundle)
}
/** Load a HAIL script */
def loadHail(r: Reader)(implicit microVM: MicroVM, mutator: Mutator): Unit = ???
/** Load a HAIL script */
def loadHail(s: String)(implicit microVM: MicroVM, mutator: Mutator): Unit = ???
}
\ No newline at end of file
......@@ -42,6 +42,12 @@ class MicroVM(heapSize: Word = MicroVM.DEFAULT_HEAP_SIZE,
globalBundle.typeNs.add(InternalTypes.VOID)
globalBundle.typeNs.add(InternalTypes.BYTE)
globalBundle.typeNs.add(InternalTypes.BYTE_ARRAY)
// Types for the @uvm.meta.* common instructions.
globalBundle.typeNs.add(InternalTypes.BYTES)
globalBundle.typeNs.add(InternalTypes.BYTES_R)
globalBundle.typeNs.add(InternalTypes.REFS)
globalBundle.typeNs.add(InternalTypes.REFS_R)
}
/**
......
......@@ -18,12 +18,21 @@ object InternalTypes {
i.name = Some(name)
i
}
def :=(idName: (Int, String)): T = {
val (id, name) = idName
i.id = id
i.name = Some(name)
i
}
}
def internal(name: String) = "@uvm.internal.types." + name
val I1 = TypeInt(1) := internal("i1")
val I6 = TypeInt(6) := internal("i6")
val I8 = TypeInt(6) := internal("i8")
val I16 = TypeInt(6) := internal("i16")
val I32 = TypeInt(32) := internal("i32")
val I52 = TypeInt(52) := internal("i52")
val I64 = TypeInt(52) := internal("i64")
......@@ -39,6 +48,11 @@ object InternalTypes {
val STACK = TypeStackRef() := internal("stack")
val THREAD = TypeThreadRef() := internal("thread")
val TAGREF64 = TypeTagRef64() := internal("tagref64")
val BYTES = TypeHybrid(Seq(I64), I8) := (0x260, "@uvm.meta.bytes")
val BYTES_R = TypeRef(BYTES) := (0x261, "@uvm.meta.bytes_r")
val REFS = TypeHybrid(Seq(I64), REF_VOID) := (0x262, "@uvm.meta.refs")
val REFS_R = TypeRef(BYTES) := (0x263, "@uvm.meta.refs_r")
}
object InternalTypePool {
......@@ -146,10 +160,28 @@ object TypeInferer {
case TypeRef(t) => Seq(ptrOf(t))
case TypeIRef(t) => Seq(ptrOf(t))
}
case "@uvm.native.unpin" => Seq()
case "@uvm.native.expose" => Seq(funcPtrOf(i.funcSigList(0)))
case "@uvm.native.unexpose" => Seq()
case "@uvm.native.get_cookie" => Seq(I64)
case "@uvm.native.unpin" => Seq()
case "@uvm.native.expose" => Seq(funcPtrOf(i.funcSigList(0)))
case "@uvm.native.unexpose" => Seq()
case "@uvm.native.get_cookie" => Seq(I64)
case "@uvm.meta.id_of" => Seq(I32)
case "@uvm.meta.name_of" => Seq(BYTES_R)
case "@uvm.meta.load_bundle" => Seq(BYTES_R)
case "@uvm.meta.load_hail" => Seq(BYTES_R)
case "@uvm.meta.cur_func" => Seq(I32)
case "@uvm.meta.cur_func_ver" => Seq(I32)
case "@uvm.meta.cur_inst" => Seq(I32)
case "@uvm.meta.dump_keepalives" => Seq(REFS_R)
case "@uvm.meta.pop_frame" => Seq()
case "@uvm.meta.push_frame" => Seq()
case "@uvm.meta.enable_watchpoint" => Seq()
case "@uvm.meta.disable_watchpoint" => Seq()
case "@uvm.meta.set_trap_handler" => Seq()
}
}
}
\ No newline at end of file
......@@ -17,7 +17,7 @@ import uvm.refimpl.nat.NativeCallResult
trait CommInstExecutor extends InterpreterActions with ObjectPinner {
import InterpreterThread.logger
protected def mutator: Mutator
implicit protected def mutator: Mutator
implicit protected def memorySupport: MemorySupport
override def interpretCurrentCommonInstruction(): Unit = {
......@@ -314,6 +314,45 @@ trait CommInstExecutor extends InterpreterActions with ObjectPinner {
continueNormally()
}
case "@uvm.meta.id_of" => {
val Seq(name) = argList
val nameStr = MemoryOperations.bytesToStr(boxOf(name).asInstanceOf[BoxRef].objRef)
val theID = microVM.idOf(nameStr)
resultBox(0).asInstanceOf[BoxInt].value = OpHelper.unprepare(theID, 32)
continueNormally()
}
case "@uvm.meta.name_of" => {
val Seq(theID) = argList
val idInt = boxOf(theID).asInstanceOf[BoxInt].value.toInt
val name = microVM.nameOf(idInt)
val bytesRef = MemoryOperations.strToBytes(name)
resultBox(0).asInstanceOf[BoxRef].objRef = bytesRef
continueNormally()
}
case "@uvm.meta.load_bundle" => {
val Seq(bundle) = argList
val bundleStr = MemoryOperations.bytesToStr(boxOf(bundle).asInstanceOf[BoxRef].objRef)
MetaOperations.loadBundle(bundleStr)
continueNormally()
}
case "@uvm.meta.load_hail" => {
val Seq(hailScript) = argList
val hailStr = MemoryOperations.bytesToStr(boxOf(hailScript).asInstanceOf[BoxRef].objRef)
MetaOperations.loadHail(hailStr)
continueNormally()
}
// Insert more CommInsts here.
case ciName => {
......
package uvm.refimpl.itpr
import uvm.types._
import uvm.ssavariables._
import java.nio.charset.Charset
import uvm.refimpl._
import uvm.refimpl.mem.TypeSizes._
import uvm.refimpl.mem.MemorySupport
import AtomicRMWOptr._
import uvm.refimpl.mem.Mutator
import uvm.refimpl.mem.TypeSizes._
import uvm.refimpl.mem.TypeSizes
import uvm.ssavariables._
import uvm.ssavariables.AtomicRMWOptr._
import uvm.types._
object OpHelper {
......@@ -564,5 +568,39 @@ object MemoryOperations {
}
case _ => throw new UnimplementedOprationException("Futex of %d bit int is not supported".format(len))
}
val US_ASCII = Charset.forName("US-ASCII")
/**
* Read an ASCII string from the memory.
*
* @param loc A ref to a @uvm.meta.bytes object.
*/
def bytesToStr(loc: Word)(implicit memorySupport: MemorySupport): String = {
// It is a hybrid<@i64 @i8> object. The length is determined by the fixed part.
val len = memorySupport.loadLong(loc)
val bytes = new Array[Byte](len.toInt)
val begin = loc + TypeSizes.WORD_SIZE_BYTES
memorySupport.loadBytes(begin, bytes, 0, len, true)
val result = new String(bytes, US_ASCII)
result
}
/**
* Create a Mu @uvm.meta.bytes object to hold an ASCII string.
*
* @return The address of the allocated object.
*/
def strToBytes(str: String)(implicit memorySupport: MemorySupport, mutator: Mutator): Word = {
val bytes = str.getBytes(US_ASCII)
val len = bytes.length
val loc = mutator.newHybrid(InternalTypes.BYTES, len)
memorySupport.storeLong(loc, bytes.length.toLong)
val begin = loc + TypeSizes.WORD_SIZE_BYTES
memorySupport.storeBytes(begin, bytes, 0, len, true)
loc
}
}
......@@ -258,6 +258,18 @@ class InterpreterStack(val id: Int, val stackMemory: StackMemory, stackBottomFun
}
}
/**
* Return the n-th frame of the current stack.
*/
def nthFrame(n: Int): InterpreterFrame = {
val dropped = frames.drop(n)
if (dropped.hasNext) {
dropped.next
} else {
throw new UvmRuntimeException("The stack %d only has %d frames, but the %d-th frame is requested.".format(id, n))
}
}
/** Pop a frame. Part of the API. Also used by THROW */
def popFrame(): Unit = {
top match {
......@@ -281,6 +293,16 @@ abstract class InterpreterFrame(val prev: Option[InterpreterFrame]) {
* The state of the frame. Must be set when creating the frame.
*/
var state: FrameState = _
/** ID of the current function. Return 0 for native frames. */
def curFuncID: Int
/** ID of the current function version Return 0 for native frames or undefined Mu frames. */
def curFuncVerID: Int
/** ID of the current instruction. Return 0 for native frames, undefined Mu frames, or a just-created frame. */
def curInstID: Int
}
object InterpreterFrame {
......@@ -305,7 +327,11 @@ object InterpreterFrame {
}
}
class NativeFrame(val func: Word, prev: Option[InterpreterFrame]) extends InterpreterFrame(prev)
class NativeFrame(val func: Word, prev: Option[InterpreterFrame]) extends InterpreterFrame(prev) {
override def curFuncID: Int = 0
override def curFuncVerID: Int = 0
override def curInstID: Int = 0
}
abstract class MuFrame(val func: Function, prev: Option[InterpreterFrame]) extends InterpreterFrame(prev) {
/**
......@@ -354,6 +380,10 @@ class UndefinedMuFrame(func: Function, prev: Option[InterpreterFrame]) extends M
var virtInst = VIRT_INST_NOT_STARTED
override def scannableBoxes = boxes
override def curFuncID: Int = func.id
override def curFuncVerID: Int = 0
override def curInstID: Int = 0
def resumeNormally(args: Seq[ValueBox]): Boolean = {
if (justCreated) {
......@@ -447,6 +477,10 @@ class DefinedMuFrame(val savedStackPointer: Word, val funcVer: FuncVer, val cook
edgeAssignedBoxes.put(lv.asInstanceOf[Parameter], ValueBox.makeBoxForType(ty))
}
}
override def curFuncID: Int = func.id
override def curFuncVerID: Int = funcVer.id
override def curInstID: Int = if (justCreated) 0 else curInst.id
def curInst: Instruction = try {
curBB.insts(curInstIndex)
......
......@@ -129,8 +129,24 @@ class MemorySupport(val muMemorySize: Word) {
storeI128(addr, desired, inMu)
return oldVal
}
def memset(addr: Word, size: Word, value: Byte): Unit = {
theMemory.setMemory(addr, size, value)
}
def loadBytes(addr: Word, dest: Array[Byte], index: Int, len: Word, inMu: Boolean = true): Unit = {
assertInMuMemory(inMu, addr)
assertInMuMemory(inMu, addr + len - 1)
assert(index >= 0, "Index is negative")
assert(index + len <= dest.length, "array too small. dest.size=%d, len=%d".format(dest.size, len))
theMemory.get(addr, dest, 0, len.toInt)
}
def storeBytes(addr: Word, dest: Array[Byte], index: Int, len: Word, inMu: Boolean = true): Unit = {
assertInMuMemory(inMu, addr)
assertInMuMemory(inMu, addr + len - 1)
assert(index >= 0, "Index is negative")
assert(index + len <= dest.length, "array too small. dest.size=%d, len=%d".format(dest.size, len))
theMemory.put(addr, dest, 0, len.toInt)
}
}
package uvm.refimpl.itpr
import org.scalatest._
import java.io.FileReader
import uvm._
import uvm.types._
import uvm.ssavariables._
import uvm.refimpl._
import uvm.refimpl.itpr._
import MemoryOrder._
import AtomicRMWOptr._
import uvm.refimpl.mem.TypeSizes.Word
import ch.qos.logback.classic.Level._
import uvm.refimpl.UvmBundleTesterBase
import uvm.refimpl.TrapHandlerResult.{ ThreadExit, Rebind }
import uvm.refimpl.HowToResume.{ PassValues, ThrowExc }
class UvmInterpreterMetaTests extends UvmBundleTesterBase {
setLogLevels(
ROOT_LOGGER_NAME -> INFO,
"uvm.refimpl.itpr" -> DEBUG)
preloadBundles("tests/uvm-refimpl-test/primitives.uir",
"tests/uvm-refimpl-test/meta-tests.uir")
"id_of and name_of" should "work" in {
val ctx = microVM.newContext()
val func = ctx.handleFromFunc("@id_name")
testFunc(ctx, func, Seq()) { (ctx, th, st, wp) =>
ctx.nameOf(ctx.curInst(st, 0)) match {
case "@id_name.v1.entry.trap" => {
val Seq(id: MuIntValue, name: MuRefValue) = ctx.dumpKeepalives(st, 0)
ctx.handleToSInt(id) shouldBe idOf("@foo")
returnFromTrap(st)
}
}
}
ctx.closeContext()
}
}
\ No newline at end of file
// require "primitives.uir"
.typedef @foo = int<64>
.const @I8_AT <@i8> = 64
.const @I8_f <@i8> = 102
.const @I8_o <@i8> = 111
.funcdef @id_name VERSION %v1 <@v_v> {
%entry():
%name_o = NEWHYBRID <@uvm.meta.bytes @i64> @I64_4
%name_i = GETIREF <@uvm.meta.bytes> %name_o
%name_f = GETFIELDIREF <@uvm.meta.bytes 0> %name_i
[%store_len] STORE <@i64> %name_f @I64_4
%name_v = GETVARPARTIREF <@uvm.meta.bytes> %name_i
%name_v0 = SHIFTIREF <@i8 @i64> %name_v @I64_0
[%store_0] STORE <@i8> %name_v0 @I8_AT
%name_v1 = SHIFTIREF <@i8 @i64> %name_v @I64_1
[%store_1] STORE <@i8> %name_v1 @I8_f
%name_v2 = SHIFTIREF <@i8 @i64> %name_v @I64_2
[%store_2] STORE <@i8> %name_v2 @I8_o
%name_v3 = SHIFTIREF <@i8 @i64> %name_v @I64_3
[%store_3] STORE <@i8> %name_v3 @I8_o
%id = COMMINST @uvm.meta.id_of (%name_o)
%name = COMMINST @uvm.meta.name_of (%id)
[%trap] TRAP <> KEEPALIVE(%id %name)
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