GitLab will be upgraded on June 2nd 2020 at 2.00 pm (AEDT) to 3.00 pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to local Gitlab admin team.

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