Commit c161413e authored by Adam R. Nelson's avatar Adam R. Nelson

Added pre-SSA to SSA conversion

parent 4c11b17c
......@@ -3,39 +3,36 @@ lazy val genSrc = taskKey[List[File]]("generate sources")
genSrc <<= (sourceGenerators in Compile) { _.join.map(_.flatten.toList) }
lazy val root = (project in file(".")).settings(
organization := "org.microvm",
organization := "org.microvm"
name := "microvm-refimpl2",
version := "2.1.0",
name := "microvm-refimpl2"
description := "The second reference implementation of Mu, the micro virtual machine",
version := "2.1.0"
licenses := Seq("CC BY-SA 4.0" -> url("https://creativecommons.org/licenses/by-sa/4.0/legalcode")),
description := "The second reference implementation of Mu, the micro virtual machine"
scalaVersion := "2.11.7",
licenses := Seq("CC BY-SA 4.0" -> url("https://creativecommons.org/licenses/by-sa/4.0/legalcode"))
libraryDependencies ++= Seq(
"org.antlr" % "antlr4" % "4.5.1-1",
"com.typesafe.scala-logging" %% "scala-logging" % "3.1.0",
"ch.qos.logback" % "logback-classic" % "1.1.3",
"com.github.jnr" % "jnr-ffi" % "2.0.7",
"com.github.jnr" % "jffi" % "1.2.10",
"com.github.jnr" % "jnr-posix" % "3.0.23",
"org.scalatest" %% "scalatest" % "2.2.4" % "test",
"junit" % "junit" % "4.12" % "test"
),
scalaVersion := "2.11.7"
testOptions in Test += Tests.Argument("-oF"), // print full stack trace when testing
antlr4Settings,
libraryDependencies ++= Seq(
"org.antlr" % "antlr4" % "4.5.1",
"com.typesafe.scala-logging" %% "scala-logging" % "3.1.0",
"ch.qos.logback" % "logback-classic" % "1.1.3",
"com.github.jnr" % "jnr-ffi" % "2.0.7",
"com.github.jnr" % "jffi" % "1.2.10",
"com.github.jnr" % "jnr-posix" % "3.0.23",
"org.scalatest" %% "scalatest" % "2.2.4" % "test",
"junit" % "junit" % "4.12" % "test"
)
antlr4PackageName in Antlr4 := Some("uvm.ir.textinput.gen"),
testOptions in Test += Tests.Argument("-oF") // print full stack trace when testing
antlr4GenListener in Antlr4 := false,
antlr4Settings
antlr4GenVisitor in Antlr4 := false
)
antlr4PackageName in Antlr4 := Some("uvm.ir.textinput.gen")
antlr4GenListener in Antlr4 := false
antlr4GenVisitor in Antlr4 := false
package uvm.clientsupport.text
import java.util
import scala.collection.JavaConversions._
/**
* A Mu IR bundle. This class is more representation-oriented rather than semantic oriented. For example, there are
* "type definitions" rather than "types". Similarly "function definitions" and "function declarations" are separated
* rather than contained in each other.
*/
class Bundle(
cTypeDefs: TraversableOnce[(TypeName, TypeCtor)],
cFuncSigDefs: TraversableOnce[(FuncSigName, FuncSig)],
cConstDefs: TraversableOnce[(GlobalVarName, Const)],
cGlobalCellDefs: TraversableOnce[(GlobalVarName, TypeName)],
cFuncDecls: TraversableOnce[(GlobalVarName, FuncSigName)],
cFuncVers: TraversableOnce[(FuncVerName, PostFuncVer)],
cFuncExpDefs: TraversableOnce[(GlobalVarName, Expose)],
cComments: TraversableOnce[(GlobalName, String)]
) {
private def buildMap[K, V](seq: TraversableOnce[(K, V)]): util.Map[K, V] = {
val map = new util.LinkedHashMap[K, V]
seq foreach { case (k, v) => map.put(k, v) }
map
}
lazy val typeDefs = buildMap(cTypeDefs)
lazy val funcSigDefs = buildMap(cFuncSigDefs)
lazy val constDefs = buildMap(cConstDefs)
lazy val globalCellDefs = buildMap(cGlobalCellDefs)
lazy val funcDecls = buildMap(cFuncDecls)
lazy val funcVers = buildMap(cFuncVers)
lazy val funcExpDefs = buildMap(cFuncExpDefs)
lazy val comments = buildMap(cComments)
override lazy val toString = {
val sb = new StringBuilder
def printBlock[N <: GlobalName, V](block: util.Map[N, V])(fn: (N, V) => Unit): Unit =
if (!block.isEmpty) {
sb append "\n"
block foreach { case (name, value) =>
Option(comments get name) foreach (_ split '\n' map ("// " + _ + "\n") foreach sb.append)
fn(name, value)
}
}
printBlock(typeDefs)((name, ctor) => sb append s".typedef $name = $ctor\n")
printBlock(funcSigDefs)((name, sig) => sb append s".funcsig $name = $sig\n")
printBlock(constDefs)((name, const) => sb append s".const $name <${const.ty}> = $const\n")
printBlock(globalCellDefs)((name, ty) => sb append s".global $name <$ty>\n")
printBlock(funcDecls)((name, sig) => sb append s".funcdecl $name <$sig>\n")
printBlock(funcExpDefs)((name, exp) => sb append s".expose $name = $exp\n")
printBlock(funcVers)((name, ver) =>
sb append s".funcdef ${ver.func} VERSION $name <${ver.sig}> $ver\n\n")
sb.toString
}
}
package uvm.clientsupport.text
import java.util
import scala.collection.JavaConversions
class IList[T](members: TraversableOnce[T]) extends util.AbstractList[T] with Traversable[T] {
def this(membersIterable: java.lang.Iterable[T]) =
this(JavaConversions iterableAsScalaIterable membersIterable)
private val vector = members.toVector
override def get(index: Int): T = vector(index)
override def size: Int = vector.length
override def isEmpty: Boolean = vector.isEmpty
override def toString = vector mkString " "
override def foreach[U](f: (T) => U): Unit = vector foreach f
def apply(idx: Int): T = vector(idx)
}
object IList {
def apply[T](members: T*): IList[T] = new IList(members)
def empty[T]: IList[T] = new IList[T](Nil)
}
package uvm.clientsupport.text
import java.util
import scala.collection.{JavaConversions, mutable}
import scala.annotation.tailrec
import scala.collection.mutable
import scala.collection.JavaConversions._
import java.util
class BundleBuilder(baseName: String) {
protected val typeDefs = mutable.AnyRefMap.empty[TypeName, TypeCtor]
protected val funcSigDefs = mutable.AnyRefMap.empty[FuncSigName, FuncSig]
protected val constDefs = mutable.AnyRefMap.empty[GlobalVarName, Const]
protected val globalCellDefs = mutable.AnyRefMap.empty[GlobalVarName, TypeName]
protected val funcDecls = mutable.AnyRefMap.empty[GlobalVarName, FuncSigName]
protected val funcVers = mutable.AnyRefMap.empty[FuncVerName, FunctionBuilder]
protected val funcExpDefs = mutable.AnyRefMap.empty[GlobalVarName, Expose]
protected val comments = mutable.AnyRefMap.empty[GlobalName, String]
class BundleBuilder(baseName: String) extends Context {
protected val typeDefs = new util.LinkedHashMap[TypeName, TypeCtor]
protected val funcSigDefs = new util.LinkedHashMap[FuncSigName, FuncSig]
protected val constDefs = new util.LinkedHashMap[GlobalVarName, Const]
protected val globalCellDefs = new util.LinkedHashMap[GlobalVarName, TypeName]
protected val funcDecls = new util.LinkedHashMap[GlobalVarName, FuncSigName]
protected val funcVers = new util.LinkedHashMap[FuncVerName, FunctionBuilder]
protected val funcExpDefs = new util.LinkedHashMap[GlobalVarName, Expose]
protected val comments = new util.LinkedHashMap[GlobalName, String]
protected val usedNames = mutable.Set.empty[String]
private var nextTypeNumber = 0
......@@ -23,6 +23,15 @@ class BundleBuilder(baseName: String) {
private var typePrefix = baseName
private var constPrefix = baseName
override def resolve(typeName: TypeName) = {
typeDefs.get(typeName) match {
case next: TypeName => resolve(next)
case res => Option(res)
}
}
override def resolve(funcSigName: FuncSigName) =
Option(funcSigDefs.get(funcSigName))
// Name generation
// ------------------------------------------------------------
......@@ -86,46 +95,45 @@ class BundleBuilder(baseName: String) {
private def descriptiveTypeName(ctor: TypeCtor): TypeName = ctor match {
case TypeCtor.Int(n) => newTypeName("i" + n)
case TypeCtor.Float() => newTypeName("float")
case TypeCtor.Double() => newTypeName("double")
case TypeCtor.Stack() => newTypeName("stack")
case TypeCtor.Thread() => newTypeName("thread")
case TypeCtor.Void() => newTypeName("void")
case TypeCtor.Ref(TypeCtor.Void()) => newTypeName("voidref")
case TypeCtor.IRef(TypeCtor.Void()) => newTypeName("voidiref")
case TypeCtor.Ptr(TypeCtor.Void()) => newTypeName("voidptr")
case TypeCtor.Singletons.Float => newTypeName("float")
case TypeCtor.Singletons.Double => newTypeName("double")
case TypeCtor.Singletons.StackRef => newTypeName("stack")
case TypeCtor.Singletons.ThreadRef => newTypeName("thread")
case TypeCtor.Singletons.Void => newTypeName("void")
case TypeCtor.Ref(TypeCtor.Singletons.Void) => newTypeName("voidref")
case TypeCtor.IRef(TypeCtor.Singletons.Void) => newTypeName("voidiref")
case TypeCtor.UPtr(TypeCtor.Singletons.Void) => newTypeName("voidptr")
case TypeCtor.Ref(TypeCtor.Int(n)) => newTypeName("i" + n + "ref")
case TypeCtor.IRef(TypeCtor.Int(n)) => newTypeName("i" + n + "iref")
case TypeCtor.Ptr(TypeCtor.Int(n)) => newTypeName("i" + n + "ptr")
case TypeCtor.UPtr(TypeCtor.Int(n)) => newTypeName("i" + n + "ptr")
case _ => newTypeName()
}
def typeDef(ctor: TypeCtor): TypeName =
typeDefs collectFirst { case (name, existing) if ctor == existing => name } getOrElse
typeDef(descriptiveTypeName(ctor), ctor)
override def typeDef(ctor: TypeCtor): TypeName = ctor match {
case name: TypeName if resolve(name).isDefined => typeDef(resolve(name).get)
case _ =>
typeDefs collectFirst {
case (name, existing) if ctor == existing => name
} getOrElse
typeDef (descriptiveTypeName (ctor), ctor)
}
def typeDef(name: TypeName, ctor: TypeCtor): TypeName = {
typeDefs.put(name, ctor)
name
}
def funcSig(ret: TypeName, args: Traversable[TypeName]): FuncSigName =
override def funcSig(args: IList[TypeName], ret: IList[TypeName]): FuncSigName =
funcSigDefs collectFirst {
case (name, sig) if sig.retTy == ret && sig.paramTy.toSeq == args.toSeq => name
} getOrElse funcSig(newFuncSigName(), ret, args)
def funcSig(ret: TypeName, args: util.List[TypeName]): FuncSigName =
funcSig(ret, JavaConversions.asScalaBuffer(args))
} getOrElse funcSig(newFuncSigName(), args, ret)
def funcSig(name: FuncSigName, ret: TypeName, args: Traversable[TypeName]): FuncSigName = {
funcSigDefs.put(name, new FuncSig(ret, args))
def funcSig(name: FuncSigName, args: IList[TypeName], ret: IList[TypeName]): FuncSigName = {
funcSigDefs.put(name, new FuncSig(args, ret))
name
}
def funcSig(name: FuncSigName, ret: TypeName, args: util.List[TypeName]): FuncSigName =
funcSig(name, ret, JavaConversions.asScalaBuffer(args))
def constDef(c: Const): GlobalVarName =
override def constDef(c: Const): GlobalVarName =
constDefs collectFirst { case (name, existing) if c == existing => name } getOrElse {
var nextName: String = null
do {
......@@ -164,67 +172,40 @@ class BundleBuilder(baseName: String) {
def newFuncVersion(
funcName: GlobalVarName,
retTy: TypeName,
paramTy: Traversable[TypeName]
): FunctionBuilder = newFuncVersion(funcName, newFuncVerName(funcName), retTy, paramTy)
def newFuncVersion(
funcName: GlobalVarName,
retTy: TypeName,
paramTy: util.List[TypeName]
): FunctionBuilder = newFuncVersion(funcName, retTy, JavaConversions asScalaBuffer paramTy)
paramTy: IList[TypeName],
retTy: IList[TypeName]
): FunctionBuilder = newFuncVersion(funcName, newFuncVerName(funcName), paramTy, retTy)
def newFuncVersion(
funcName: GlobalVarName,
versionName: FuncVerName,
retTy: TypeName,
paramTy: Traversable[TypeName]
paramTy: IList[TypeName],
retTy: IList[TypeName]
): FunctionBuilder = {
val sig = funcSig(retTy, paramTy)
val sig = funcSig(paramTy, retTy)
val builder = new FunctionBuilderImpl(
this, funcName, sig, versionName, paramTy.toSeq.indices.map("param"+_))
this, funcName, sig, versionName, new IList(paramTy.toSeq.indices.map("param"+_)))
funcVers.put(versionName, builder)
builder
}
def newFuncVersion(
funcName: GlobalVarName,
versionName: FuncVerName,
retTy: TypeName,
paramTy: util.List[TypeName]
): FunctionBuilder = newFuncVersion(funcName, versionName, retTy, JavaConversions asScalaBuffer paramTy)
def newFuncVersion(
funcName: GlobalVarName,
sigName: FuncSigName,
paramNames: Traversable[String]
paramNames: IList[String]
): FunctionBuilder = newFuncVersion(funcName, sigName, newFuncVerName(funcName), paramNames)
def newFuncVersion(
funcName: GlobalVarName,
sigName: FuncSigName,
paramNames: util.List[String]
): FunctionBuilder = newFuncVersion(funcName, sigName, JavaConversions asScalaBuffer paramNames)
def newFuncVersion(
funcName: GlobalVarName,
sigName: FuncSigName,
versionName: FuncVerName,
paramNames: Traversable[String]
paramNames: IList[String]
): FunctionBuilder = {
val builder = new FunctionBuilderImpl(this, funcName, sigName, versionName, paramNames)
funcVers.put(versionName, builder)
builder
}
def newFuncVersion(
funcName: GlobalVarName,
sigName: FuncSigName,
versionName: FuncVerName,
paramNames: util.List[String]
): FunctionBuilder =
newFuncVersion(funcName, sigName, versionName, JavaConversions asScalaBuffer paramNames)
def comment(name: GlobalName, comment: String): Unit = comments.put(name, comment)
def build(): Bundle = new Bundle(
......@@ -233,41 +214,39 @@ class BundleBuilder(baseName: String) {
cConstDefs = constDefs,
cGlobalCellDefs = globalCellDefs,
cFuncDecls = funcDecls,
cFuncVers = funcVers.mapValues(_.build()),
cFuncVers = funcVers map { case (k, v) => k -> v.build() },
cFuncExpDefs = funcExpDefs,
cComments = comments
)
}
trait FunctionBuilder {
trait FunctionBuilder extends Context {
def functionName: GlobalVarName
def functionSignature: FuncSigName
def versionName: FuncVerName
def paramNames: util.List[LocalVarName]
def paramName(index: Int): LocalVarName
def paramNames: IList[LocalVarName]
def newVarName(): LocalVarName
def newVarName(name: String): LocalVarName
def newLabelName(): LabelName
def newLabelName(name: String): LabelName
def typeDef(ctor: TypeCtor): TypeName
def constDef(c: Const): VarName
def currentBlockLabel: LabelName
def startNewBlock(): LabelName
def startNewBlock(label: LabelName): LabelName
def inst(inst: NameableInst): LocalVarName
def inst(name: LocalVarName, inst: Inst): LocalVarName
def build(): FuncVer
def inst(inst: PreInst): LocalVarName
def inst(names: IList[LocalVarName], inst: PreInst): Unit
def preBuild(): PreFuncVer
def build(): PostFuncVer
}
private[text] class FunctionBuilderImpl(
bundleBuilder: BundleBuilder,
context: Context,
override val functionName: GlobalVarName,
override val functionSignature: FuncSigName,
override val versionName: FuncVerName,
cParamNames: TraversableOnce[String]
val paramNameBases: IList[String]
) extends FunctionBuilder {
type Block = (LabelName, mutable.ArrayBuffer[NameableInst])
type Block = (LabelName, mutable.ArrayBuffer[(IList[LocalVarName], PreInst)])
protected val blocks = mutable.ArrayBuffer.empty[Block]
protected val usedNames = mutable.Set.empty[String]
......@@ -275,9 +254,7 @@ private[text] class FunctionBuilderImpl(
private var nextLabelNumber = 0
private var currentBlock: Block = createBlock(newLabelName("entry"))
override lazy val paramNames = Helpers.buildList(cParamNames map newVarName)
override def paramName(index: Int): LocalVarName = paramNames get index
override lazy val paramNames = new IList(paramNameBases map newVarName)
private def generateName(n: String): String = {
var n_ = n
......@@ -308,13 +285,9 @@ private[text] class FunctionBuilderImpl(
override def newLabelName(name: String): LabelName = LabelName(generateName(name))
override def typeDef(ctor: TypeCtor): TypeName = bundleBuilder.typeDef(ctor)
override def constDef(c: Const): VarName = bundleBuilder.constDef(c)
private def createBlock(name: LabelName): Block = {
val newBlock = (name, mutable.ArrayBuffer.empty[NameableInst])
blocks add newBlock
val newBlock = (name, mutable.ArrayBuffer.empty[(IList[LocalVarName], PreInst)])
blocks += newBlock
newBlock
}
......@@ -327,24 +300,211 @@ private[text] class FunctionBuilderImpl(
label
}
override def inst(inst: NameableInst): LocalVarName = inst match {
case NamedInst(name, _) =>
currentBlock._2 add inst
name
case i: Inst =>
override def inst(inst: PreInst): LocalVarName = {
val name = newVarName()
currentBlock._2 add NamedInst(name, i)
currentBlock._2 += (IList(name) -> inst)
name
}
override def inst(name: LocalVarName, inst: Inst): LocalVarName = {
currentBlock._2 add NamedInst(name, inst)
name
override def inst(names: IList[LocalVarName], inst: PreInst): Unit = {
currentBlock._2 += (names -> inst)
}
override def build(): FuncVer = new FuncVer(
override def preBuild() = new PreFuncVer(
functionName, functionSignature, paramNames,
blocks map { case (name, insts) => new BasicBlock(name, insts) }
new IList(blocks map { case (name, insts) => new PreBasicBlock(name, new IList(insts)) })
)
def convertFunction(preFunc: PreFuncVer)(implicit context: Context): PostFuncVer = {
// Step 1: Cache some data about each block (incoming jumps, local variable names, etc.)
case class BlockData(
incoming: Set[LabelName],
locals: Map[LocalVarName, () => TypeCtor],
args: mutable.Map[LocalVarName, Option[TypeCtor]])
val blockData = blocks.map {
case (label, insts) =>
val locals = (for ((labels, inst) <- insts; (l, i) <- labels.toSeq.zipWithIndex) yield {
lazy val x = context.resolve(inst.returnTypes get i).get
l -> (() => x)
}).toMap
label -> BlockData(
incoming = blocks.filter(_._2 flatMap (_._2.possibleJumps) contains label).map(_._1).toSet,
locals = locals,
args = mutable.Map((for ((_, inst) <- insts; label <- inst.referencedVars) yield label) collect {
case v: LocalVarName if !locals.contains(v) => v -> None
}: _*)
)
}.toMap
for ((name, ty) <- paramNames.toSeq zip resolve(functionSignature).get.paramTy.toSeq) {
blockData(blocks(0)._1).args.put(name, Some(ty))
}
// Step 2: Determine block arities and argument types
// Iteratively propagate passthrough args and arg types until a fixpoint is reached.
var continue = true
while (continue) {
continue = false
for (
(to, BlockData(froms, _, args)) <- blockData;
from <- froms;
BlockData(_, fromLocals, fromArgs) = blockData(from);
arg <- args.keys
) {
(fromLocals ++ fromArgs.collect{case (k, Some(v)) => (k, () => v)}).get(arg) match {
case Some(fn) =>
val ctor = fn()
args(arg) match {
case Some(current) if ctor == current => // Do nothing.
case Some(current) =>
// FIXME: This may throw unnecessary exceptions in the case of TypeNames inside TypeCtors
// For example: iref<@a> and iref<@b> would be a type mismatch even if @a and @b
// are the same type. Context.resolve doesn't check nested names yet.
throw new IllegalStateException(
s"Pre-SSA variable type mismatch for $arg in ($from, $to): $ctor != $current")
case None =>
continue = true
args.put(arg, Some(ctor))
}
case None =>
if (!(fromArgs contains arg)) {
continue = true
fromArgs.put(arg, None)
}
}
}
}
// Step 3: Process preinsts into postinsts, renaming reused labels along the way.
val newBlocks = blocks map { case (label, insts) =>
import Inst._
val BlockData(_, locals, args) = blockData(label)
val used = mutable.Set(args.keys.toSeq: _*)
val replacements = mutable.Map.empty[LocalVarName, VarName]
@tailrec def gensym(n: Int = 0): LocalVarName = {
val sym = LocalVarName(s"v$n")
if ((used contains sym) || (locals contains sym)) gensym(n+1) else {
used += sym
sym
}
}
@tailrec def r(v: VarName): VarName = v match {
case lv: LocalVarName => replacements get lv match {
case Some(lv2) => r(lv2)
case None => v
}
case _ => v
}
def l(n: LocalVarName): LocalVarName =
if (used contains n) {
val n2 = gensym()
replacements.put(n, n2)
n2
} else { used += n; n }
def mapKeepAlive(ka: Option[KeepAliveClause]) =
ka map (c => KeepAliveClause(new IList(c.vars map r collect {case lv: LocalVarName => lv})))
def mapNewStackClause(c: NewStackClause): NewStackClause = c match {
case NewStackClause.PassValue(argTy, arg) => NewStackClause.PassValue(argTy, r(arg))
case i: NewStackClause.PassVoid => i
case NewStackClause.ThrowExc(exc) => NewStackClause.ThrowExc(r(exc))
}
def mapDest(lbl: LabelName): DestClause =
DestClause(lbl, new IList(blockData(lbl).args.keys.toSeq.sortBy(_.name).map(r)))
def mapInst(names: Traversable[LocalVarName], inst: PreInst):
Option[(IList[LocalVarName], PostInst)] = inst match {
case ppinst: PrePostInst =>
val postInst: PostInst = ppinst match {
case BinOp(op, opndTy, op1, op2) => BinOp(op, opndTy, r(op1), r(op2))
case Cmp(op, opndTy, op1, op2) => Cmp(op, opndTy, r(op1), r(op2))
case Conv(op, fromTy, toTy, opnd) => Conv(op, fromTy, toTy, r(opnd))
case Select(condTy, opndTy, cond, ifTrue, ifFalse) =>
Select(condTy, opndTy, r(cond), r(ifTrue), r(ifFalse))
case Call(sig, callee, argList, ka) =>
Call(sig, r(callee), new IList(argList map r), mapKeepAlive(ka))
case TailCall(sig, callee, argList) =>
TailCall(sig, r(callee), new IList(argList map r))
case Ret(rv) => Ret(new IList(rv map r))
case i: RetVoid => i
case Throw(exc) => Throw(r(exc))
case i: LandingPad => i
case ExtractValue(strTy, index, opnd) => ExtractValue(strTy, index, r(opnd))
case InsertValue(strTy, index, opnd, newVal) =>
InsertValue(strTy, index, r(opnd), r(newVal))
case ExtractElement(vecTy, indTy, opnd, index) =>
ExtractElement(vecTy, indTy, r(opnd), r(index))
case InsertElement(vecTy, indTy, opnd, index, newVal) =>
InsertElement(vecTy, indTy, r(opnd), r(index), r(newVal))
case ShuffleVector(vecTy, maskTy, vec1, vec2, mask) =>
ShuffleVector(vecTy, maskTy, r(vec1), r(vec2), r(mask))
case i: New => i
case NewHybrid(allocTy, len, length) => NewHybrid(allocTy, len, r(length))
case i: Alloca => i
case AllocaHybrid(allocTy, len, length) => AllocaHybrid(allocTy, len, r(length))
case GetIRef(refTy, opnd) => GetIRef(refTy, r(opnd))
case GetFieldIRef(ptr, refTy, index, opnd) => GetFieldIRef(ptr, refTy, index, r(opnd))
case GetElemIRef(ptr, refTy, indexTy, opnd, index) =>
GetElemIRef(ptr, refTy, indexTy, r(opnd), r(index))
case ShiftIRef(ptr, refTy, offTy, opnd, offset) =>
ShiftIRef(ptr, refTy, offTy, r(opnd), r(offset))
case GetFixedPartIRef(ptr, refTy, opnd) => GetFixedPartIRef(ptr, refTy, r(opnd))
case GetVarPartIRef(ptr, refTy, opnd) => GetVarPartIRef(ptr, refTy, r(opnd))
case Load(ptr, ord, locTy, loc) => Load(ptr, ord, locTy, r(loc))
case Store(ptr, ord, locTy, loc, newVal) => Store(ptr, ord, locTy, r(loc), r(newVal))
case i: CmpXchg => i.copy(loc = r(i.loc), expected = r(i.expected), desired = r(i.desired))
case i: AtomicRMW => i.copy(loc = r(i.loc), opnd = r(i.opnd))
case i: Fence => i
case Trap(retTy, ka) => Trap(retTy, mapKeepAlive(ka))
case i: CCall => i.copy(callee = r(i.callee), argList = new IList(i.argList map r),
keepAliveClause = mapKeepAlive(i.keepAliveClause))
case NewThread(stack, nsClause) => NewThread(r(stack), mapNewStackClause(nsClause))
case SwapStack(swappee, csClause, nsClause, ka) =>
SwapStack(r(swappee), csClause, mapNewStackClause(nsClause), mapKeepAlive(ka))
case i: CommInst => i.copy(argList = i.argList map (l => new IList(l map r)),
keepAliveClause = mapKeepAlive(i.keepAliveClause))
}
Some(new IList(names map l) -> postInst)
case Id(_, v) =>
used += names.head
replacements.put(names.head, v)
None
case PreExcClause(subInst, nor, exc) =>
mapInst(Nil, subInst.asInstanceOf[PreInst]) map {
case (_, postSub) =>
val post = PostExcClause(postSub.asInstanceOf[SupportsExcClause],
mapDest(nor), mapDest(exc))
(new IList(names map l), post)
}
case PreBranch(dest) =>
Some((IList[LocalVarName](), PostBranch(mapDest(dest))))
case PreBranch2(cond, ifTrue, ifFalse) =>
Some((IList[LocalVarName](), PostBranch2(r(cond), mapDest(ifTrue), mapDest(ifFalse))))
case PreSwitch(opndTy, opnd, defDest, cases) =>
Some((IList[LocalVarName](), PostSwitch(opndTy, r(opnd), mapDest(defDest),
new IList(cases map (c => SwitchCase(r(c.value), mapDest(c.dest)))))))
case PreWatchPoint(wpid, retTy, dis, ena, exc, ka) =>
val post = PostWatchPoint(wpid, retTy, mapDest(dis), mapDest(ena), exc map mapDest,
mapKeepAlive(ka))
Some((new IList(names map l), post))
}
PostBasicBlock(
label = label,
args = new IList(blockData(label).args.toSeq sortBy (_._1.name) map {
case (name, ty) => (name, context typeDef (ty getOrElse {
throw new IllegalStateException(s"Cannot infer type of argument $name for block $label")
}))
}),
insts = new IList(insts flatMap { case (names, inst) => mapInst(names, inst) })
)
}
PostFuncVer(preFunc.func, preFunc.sig, new IList(newBlocks))
}
override def build() = convertFunction(preBuild())(this)
override def typeDef(ctor: TypeCtor) = context.typeDef(ctor)
override def funcSig(args: IList[TypeName], ret: IList[TypeName]) = context.funcSig(args, ret)
override def constDef(c: Const) = context.constDef(c)
override def resolve(typeName: TypeName) = context.resolve(typeName)
override def resolve(funcSigName: FuncSigName) = context.resolve(funcSigName)
}
package uvm.clientsupport.text
import java.util
import scala.collection.JavaConversions
private[text] object Helpers {
def buildMap[K, V](iter: TraversableOnce[(K, V)]): util.Map[K, V] = {
val map = new util.LinkedHashMap[K, V]
iter foreach { case (k, v) => map.put(k, v) }
util.Collections unmodifiableMap map
}
def buildList[T](iter: TraversableOnce[T]): util.List[T] = {
val list = new util.ArrayList[T]
iter foreach list.add
util.Collections unmodifiableList list
}