Commit 795c2c7e authored by Kunshan Wang's avatar Kunshan Wang

WIP: ir building API

parent ceb1729b
This diff is collapsed.
package uvm
import scala.collection.mutable.ArrayBuffer
import uvm.types._
import uvm.ssavariables._
......@@ -23,8 +25,8 @@ class Function extends GlobalVariable {
*/
class FuncVer extends IdentifiedSettable {
var func: Function = null
var bbs: IndexedSeq[BasicBlock] = null
var entry: BasicBlock = null
var bbs: ArrayBuffer[BasicBlock] = null
def entry: BasicBlock = bbs.head
def sig: FuncSig = func.sig
......@@ -32,9 +34,9 @@ class FuncVer extends IdentifiedSettable {
}
class BasicBlock extends IdentifiedSettable {
var norParams: IndexedSeq[NorParam] = null
var norParams: ArrayBuffer[NorParam] = null
var excParam: Option[ExcParam] = null
var insts: IndexedSeq[Instruction] = null
var insts: ArrayBuffer[Instruction] = null
var localVarNs: NestedNamespace[LocalVariable] = null // sub-namespace of allNs
var localInstNs: NestedNamespace[Instruction] = null // sub-namespace of allNs
......
......@@ -369,7 +369,7 @@ private[textinput] class InstanceUIRTextReader(idFactory: IDFactory, source: Str
val sourceInfo = toSourceInfo(p)
addLocalVar(param, sourceInfo)
param
}.toIndexedSeq
}.to[ArrayBuffer]
bb.excParam = Option(label.excParam).map { p =>
val param = mkExcParam(p.name())
val sourceInfo = toSourceInfo(p)
......@@ -610,9 +610,9 @@ private[textinput] class InstanceUIRTextReader(idFactory: IDFactory, source: Str
addInst(inst, toSourceInfo(instDef))
val instRess: Seq[InstResult] = Option(instDef.instResults) match {
case None => Seq()
case Some(r) => for ((instResDef, index) <- r.results.zipWithIndex) yield {
val instRess: ArrayBuffer[InstResult] = Option(instDef.instResults) match {
case None => ArrayBuffer()
case Some(r) => (for ((instResDef, index) <- r.results.zipWithIndex) yield {
val resName = globalize(instResDef.getText, bbName)
val instRes = InstResult(inst, index)
......@@ -621,23 +621,23 @@ private[textinput] class InstanceUIRTextReader(idFactory: IDFactory, source: Str
addLocalVar(instRes, toSourceInfo(instResDef))
instRes
}
}).to[ArrayBuffer]
}
inst.bb = bb
inst.results = instRess
return inst
}
bb.insts = bbCtx.inst.map(i => mkInst(bb, i)).toIndexedSeq
bb.insts = bbCtx.inst.map(i => mkInst(bb, i)).to[ArrayBuffer]
return bb
}
val bbs = fDefCtx.funcBody.basicBlock().map(makeBB).toIndexedSeq
val bbs = fDefCtx.funcBody.basicBlock().map(makeBB).to[ArrayBuffer]
ver.bbs = bbs
ver.entry = bbs.head
phase4.doAll()
}
......
package uvm.refimpl
import scala.collection.mutable.ArrayBuffer
import uvm.utils.IDFactory
import uvm._
import uvm.types._
import uvm.ssavariables._
object IRBuilder {
type BN = BundleNode
type CN[+T <: Identified] = ChildNode[T]
implicit def BundleNodeAutoUnbox(node: BN): TrantientBundle = {
node.bundle
}
implicit def childNodeAutoUnbox[T <: Identified](node: CN[T]): T = {
node.obj
}
implicit def childNodeAutoUnboxMany[T <: Identified](nodes: Seq[CN[T]]): Seq[T] = {
nodes.map(_.obj)
}
}
class IRBuilder(idFactory: IDFactory)(implicit microVM: MicroVM) {
import IRBuilder._
import uvm.RichIdentifiedSettable._
private def globalBundle = microVM.globalBundle
private def nextID(): Int = idFactory.getID()
private def newObj[T <: IdentifiedSettable, U >: T <: Identified](ns: Namespace[U], obj: T): CN[T] = {
obj := nextID()
ns.add(obj)
new CN(obj)
}
def newBundle(): BN = {
val b = new TrantientBundle()
val node = new BN(b)
node
}
def loadBundleFromNode(b: BN): Unit = {
val bundle = b.bundle
microVM.addBundle(bundle)
}
def abortBundleNode(b: BN): Unit = {
// no-op for this implementation
}
def getNode(b: BN, id: Int): CN[_] = {
val ent = globalBundle.allNs.get(id).getOrElse {
throw new UvmRuntimeException("No entity has id %d".format(id))
}
new ChildNode(ent)
}
def getID(b: BN, node: CN[Identified]): Int = {
node.id
}
def setName(b: BN, node: CN[IdentifiedSettable], name: String): Unit = {
node.name = Some(name)
}
// format: OFF
def newTypeInt (b: BN, len: Int): CN[TypeInt] = newObj(b.typeNs, TypeInt(len))
def newTypeFloat (b: BN): CN[TypeFloat] = newObj(b.typeNs, TypeFloat())
def newTypeDouble (b: BN): CN[TypeDouble] = newObj(b.typeNs, TypeDouble())
def newTypeUPtr (b: BN): CN[TypeUPtr] = newObj(b.typeNs, TypeUPtr(null))
def newTypeUFuncPtr (b: BN): CN[TypeUFuncPtr] = newObj(b.typeNs, TypeUFuncPtr(null))
def newTypeVoid (b: BN): CN[TypeVoid] = newObj(b.typeNs, TypeVoid())
def newTypeRef (b: BN): CN[TypeRef] = newObj(b.typeNs, TypeRef(null))
def newTypeIRef (b: BN): CN[TypeIRef] = newObj(b.typeNs, TypeIRef(null))
def newTypeWeakRef (b: BN): CN[TypeWeakRef] = newObj(b.typeNs, TypeWeakRef(null))
def newTypeFuncRef (b: BN): CN[TypeFuncRef] = newObj(b.typeNs, TypeFuncRef(null))
def newTypeTagRef64 (b: BN): CN[TypeTagRef64] = newObj(b.typeNs, TypeTagRef64())
def newTypeThreadRef (b: BN): CN[TypeThreadRef] = newObj(b.typeNs, TypeThreadRef())
def newTypeStackRef (b: BN): CN[TypeStackRef] = newObj(b.typeNs, TypeStackRef())
def newTypeFrameCursorRef(b: BN): CN[TypeFrameCursorRef] = newObj(b.typeNs, TypeFrameCursorRef())
def newTypeIRNodeRef (b: BN): CN[TypeIRNodeRef] = newObj(b.typeNs, TypeIRNodeRef())
def newTypeStruct(b: BN, fieldTys: Seq[CN[Type]]): CN[TypeStruct] = newObj(b.typeNs, TypeStruct(fieldTys))
def newTypeHybrid(b: BN, fixedTys: Seq[CN[Type]], varTy: CN[Type]): CN[TypeHybrid] = newObj(b.typeNs, TypeHybrid(fixedTys, varTy))
def newTypeArray (b: BN, elemTy: CN[Type], len: Long): CN[TypeArray] = newObj(b.typeNs, TypeArray(elemTy, len))
def newTypeVector(b: BN, elemTy: CN[Type], len: Long): CN[TypeVector] = newObj(b.typeNs, TypeVector(elemTy, len))
def setTypeUPtr (uptr: CN[TypeUPtr], ty: CN[Type]): Unit = uptr.ty = ty
def setTypeRef (ref: CN[TypeRef], ty: ChildNode[Type]): Unit = ref.ty = ty
def setTypeIRef (iref: CN[TypeIRef], ty: ChildNode[Type]): Unit = iref.ty = ty
def setTypeWeakRef (weakref: CN[TypeWeakRef], ty: ChildNode[Type]): Unit = weakref.ty = ty
def setTypeUFuncPtr(ufuncptr: CN[TypeUFuncPtr], sig: ChildNode[FuncSig]): Unit = ufuncptr.sig = sig
def setTypeFuncRef (funcref: CN[TypeFuncRef], sig: ChildNode[FuncSig]): Unit = funcref.sig = sig
// format: ON
def newFuncSig(b: BN, paramTys: Seq[CN[Type]], retTys: Seq[CN[Type]]): CN[FuncSig] = {
newObj(b.funcSigNs, new FuncSig(paramTys, retTys))
}
// format: OFF
def newConstInt (b: BN, ty: CN[Type], value: BigInt): CN[ConstInt] = newObj(b.constantNs, ConstInt(ty, value))
def newConstFloat (b: BN, ty: CN[Type], value: Float): CN[ConstFloat] = newObj(b.constantNs, ConstFloat(ty, value))
def newConstDouble(b: BN, ty: CN[Type], value: Double): CN[ConstDouble] = newObj(b.constantNs, ConstDouble(ty, value))
def newConstNull (b: BN, ty: CN[Type]): CN[ConstNull] = newObj(b.constantNs, ConstNull(ty))
def newConstSeq (b: BN, ty: CN[Type], elems: Seq[CN[Constant]]): CN[ConstSeq] = newObj(b.constantNs, ConstSeq(ty, elems))
// format: ON
def newGlobalCell(b: BN, ty: CN[Type]): CN[GlobalCell] = newObj(b.globalCellNs, new GlobalCell(ty))
def newFunc(b: BN, sig: CN[FuncSig]): CN[Function] = {
val func = new Function()
func.sig = sig
newObj(b.funcNs, func)
}
def newFuncVer(b: BN, func: CN[Function]): CN[FuncVer] = {
val funcVer = new FuncVer()
funcVer.func = func
funcVer.bbs = new ArrayBuffer()
funcVer.bbNs = b.allNs.makeSubSpace[BasicBlock]("basic block")
newObj(b.funcVerNs, funcVer)
}
def newExpFunc(b: BN, func: CN[Function], callconv: Flag, cookie: CN[ConstInt]): CN[ExposedFunc] = {
val expFunc = new ExposedFunc(func, callconv, cookie)
newObj(b.expFuncNs, expFunc)
}
def newBB(fv: CN[FuncVer]): CN[BasicBlock] = {
val bb = new BasicBlock()
bb.norParams = new ArrayBuffer()
bb.excParam = None
bb.insts = new ArrayBuffer()
val allNs = fv.bbNs.maybeParent.get.asInstanceOf[NestedNamespace[Identified]]
bb.localVarNs = allNs.makeSubSpace[LocalVariable]("local variable")
bb.localInstNs = allNs.makeSubSpace[Instruction]("instruction")
newObj(fv.bbNs, bb)
}
def newNorParam(bb: CN[BasicBlock], ty: CN[Type]): CN[NorParam] = {
val np = NorParam(ty)
bb.norParams += np
newObj(bb.localVarNs, np)
}
def newExcParam(bb: CN[BasicBlock]): CN[ExcParam] = {
val ep = ExcParam()
bb.excParam = Some(ep)
newObj(bb.localVarNs, ep)
}
def newInstRes(inst: CN[Instruction]): CN[InstResult] = {
val nResults = inst.results.size
val ir = InstResult(inst, nResults)
inst.results += ir
newObj(inst.bb.localVarNs, ir)
}
private def newInst[T <: Instruction](bb: BasicBlock, inst: T): CN[T] = {
inst.bb = bb
inst.results = new ArrayBuffer(2)
newObj(bb.localInstNs, inst)
}
}
\ No newline at end of file
This diff is collapsed.
package uvm.refimpl
import uvm._
import uvm.refimpl.itpr._
/**
* Mix-in to MuCtx to support the IR building API.
*/
trait MuCtxIRBuilderPart {
protected def microVM: MicroVM
protected def addHandle[T <: MuValue](h: T): T
@inline
def IRNODEREF = InternalTypes.IRNODEREF
def newBundle(): MuBundleNode = {
val b = new TrantientBundle()
val node = new BundleNode(b)
addHandle(MuBundleNode(IRNODEREF, BoxIRNode(Some(node))))
}
def loadBundleFromNode(b: MuBundleNode): Unit = {
require(!b.isNull, "bundle must not be NULL")
val bundle = b.bundle
microVM.addBundle(bundle)
}
def abortBundleNode(b: MuBundleNode): Unit = {
// no op
}
def getNode(b: MuBundleNode, id: Int): MuIRNode = {
???
}
def getID(node: MuChildNode): Int = {
require(!node.isNull)
node.obj.id
}
}
\ No newline at end of file
package uvm.refimpl
import scala.collection.mutable.ArrayBuffer
import scala.collection.mutable.Buffer
import uvm.ssavariables.MemoryOrder._
object RichMuCtx {
/**
* Allow you to use the `val h = x << ctx.makeSomeHandle()` or `val h = x(ctx.makeSomeHandle())`
* syntax to dispose it later
*/
class DelayedDisposer(garbageList: Buffer[MuValue]) {
def apply[T <: MuValue](v: T): T = {
garbageList += v
v
}
def <<[T <: MuValue](v: T): T = {
garbageList += v
v
}
}
/** Extensions to the MuCtx interface. Not officially part of the client API. */
implicit class RichMuCtx(val ctx: MuCtx) extends AnyVal {
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)
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]
def bytesToStr(bytes: MuRefValue): String = ctx.autoDispose { x =>
val hIR = x << ctx.getIRef(bytes)
val hFix = x << ctx.getFieldIRef(hIR, 0)
val hLen = x << ctx.loadInt(NOT_ATOMIC, hFix)
val len = ctx.handleToSInt(hLen).toLong
val hVar = x << ctx.getVarPartIRef(hIR)
val byteValues = for (i <- 0L until len) yield ctx.autoDispose { x =>
val hI = x << ctx.handleFromInt64(i)
val hVarI = x << ctx.shiftIRef(hVar, hI)
val hByte = x << ctx.loadInt(NOT_ATOMIC, hVarI)
val byte = ctx.handleToSInt(hByte).toByte
byte
}
val bytesArray = byteValues.toArray
val str = new String(bytesArray, MuCtx.US_ASCII)
str
}
// legacy support
/** Get the ID of the current function of a frame. Return 0 for native frames. */
def curFunc(stack: MuStackRefValue, frame: Int): Int = {
val cursor = ctx.newCursor(stack)
for (i <- 0 until frame) {
ctx.nextFrame(cursor)
}
val id = ctx.curFunc(cursor)
ctx.closeCursor(cursor)
ctx.deleteValue(cursor)
id
}
/**
* 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 = {
val cursor = ctx.newCursor(stack)
for (i <- 0 until frame) {
ctx.nextFrame(cursor)
}
val id = ctx.curFuncVer(cursor)
ctx.closeCursor(cursor)
ctx.deleteValue(cursor)
id
}
/**
* 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 = {
val cursor = ctx.newCursor(stack)
for (i <- 0 until frame) {
ctx.nextFrame(cursor)
}
val id = ctx.curInst(cursor)
ctx.closeCursor(cursor)
ctx.deleteValue(cursor)
id
}
/** Dump keep-alive variables of the current instruction. */
def dumpKeepalives(stack: MuStackRefValue, frame: Int): Seq[MuValue] = {
val cursor = ctx.newCursor(stack)
for (i <- 0 until frame) {
ctx.nextFrame(cursor)
}
val kas = ctx.dumpKeepalives(cursor)
ctx.closeCursor(cursor)
ctx.deleteValue(cursor)
kas
}
}
}
\ No newline at end of file
......@@ -43,6 +43,7 @@ object InternalTypes {
val STACKREF = TypeStackRef() := internal("stackref")
val THREADREF = TypeThreadRef() := internal("threadref")
val FRAMECURSORREF = TypeFrameCursorRef() := internal("framecursorref")
val IRNODEREF = TypeIRNodeRef() := internal("irnoderef")
val TAGREF64 = TypeTagRef64() := internal("tagref64")
val BYTES = TypeHybrid(Seq(I64), I8) := (0x260, "@uvm.meta.bytes")
......
package uvm.refimpl
import uvm._
import uvm.types._
import uvm.ssavariables._
import scala.collection.mutable.ArrayBuffer
/**
* Abstract class for all nodes.
* @param obj The contained object.
*/
abstract class IRNode
/**
* Node for the newly-built bundle.
* @param bundle The bundle
*/
class BundleNode(val bundle: TrantientBundle) extends IRNode {
/**
* Nodes not in this bundle, but is referred to, such as types defined in previously loaded bundles.
* In a non-garbage-collected implementation, these nodes need to be explicitly freed when the bundle node is loaded
* or aborted.
*/
val externalNodes = new ArrayBuffer[IRNode]()
}
/**
* Any children of BundleNode.
* @param obj the underlying object
*/
class ChildNode[+T <: Identified](val obj: T) extends IRNode
......@@ -69,6 +69,10 @@ case class BoxFrameCursor(var cursor: Option[FrameCursor]) extends ObjectBox[Fra
def obj = cursor
def obj_=(other: Option[FrameCursor]): Unit = { cursor = other }
}
case class BoxIRNode(var node: Option[IRNode]) extends ObjectBox[IRNode] {
def obj = node
def obj_=(other: Option[IRNode]): Unit = { node = other }
}
case class BoxTagRef64(var raw: Long) extends HasObjRef {
def copyFrom(other: ValueBox): Unit = { this.raw = other.asInstanceOf[BoxTagRef64].raw }
def hasObjRef() = OpHelper.tr64IsRef(raw)
......
package uvm.ssavariables
import scala.collection.mutable.ArrayBuffer
import uvm._
import uvm.comminsts._
import uvm.types._
......@@ -44,7 +46,8 @@ case class InstResult(inst: Instruction, index: Int) extends LocalVariable
// Instructions
abstract class Instruction extends IdentifiedSettable {
var results: Seq[InstResult] = Seq()
var bb: BasicBlock = null
var results: ArrayBuffer[InstResult] = null
override def toString = "[(%s) = %s %s]".format(this.results.map(_.repr).mkString(" "), this.repr, this.getClass.getSimpleName)
}
......
......@@ -47,6 +47,7 @@ case class TypeVector(var elemTy: Type, var len: Long) extends AbstractSeqType
case class TypeUPtr(var ty: Type) extends AbstractPointerType
case class TypeUFuncPtr(var sig: FuncSig) extends AbstractPointerType
case class TypeFrameCursorRef() extends AbstractGenRefType
case class TypeIRNodeRef() extends AbstractGenRefType
object Type {
def prettyPrint(ty: Type): String = ty match {
......@@ -68,6 +69,7 @@ object Type {
case TypeUPtr(ty) => "uptr<%s>".format(ty.repr)
case TypeUFuncPtr(sig) => "ufuncptr<%s>".format(sig.repr)
case TypeFrameCursorRef() => "framecursorref"
case TypeIRNodeRef() => "irnoderef"
case _ => "unknown type " + ty.getClass.getName
}
}
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