Commit 08b6e8f0 authored by Kunshan Wang's avatar Kunshan Wang

Scala 2.12.2, deprecated, clientsupport

Switched Scala version to 2.12.2, the most recent stable version.  It
will now require Java 1.8.

Fixed existing uses of deprecated features.

Removed the `uvm.clientsupport` package.  This package was intended to
help Mu clients build text-based Mu IR bundles.  However, we started
using the IR Builder API instead, and the `uvm.clientsupport` package
remained unused.  The same capability can be provided by the
`mu-tool-compiler` project
(https://gitlab.anu.edu.au/mu/mu-tool-compiler).  `uvm.clientsupport`
provided a non-SSA-to-ssa converter, which can be useful for clients.
If there are needs of resurrecting that feature, please checkout the
previous commit.
parent 9fcd3c14
......@@ -17,12 +17,12 @@ Specification](https://gitlab.anu.edu.au/mu/mu-spec).
* Install JDK 8. If you use Mac, download from
[Oracle](http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html).
* If you use Mac, install [Homebrew](http://brew.sh/).
* Install [Scala](http://scala-lang.org/) 2.11. If you use Mac and Homebrew,
* Install [Scala](http://scala-lang.org/) 2.12. If you use Mac and Homebrew,
`brew install scala`.
* Install [sbt](http://www.scala-sbt.org/) 0.13. If you use Mac and Homebrew,
`brew install sbt`.
* Install [Scala IDE](http://scala-ide.org/) 4.x (Eclipse with pre-installed
plugins for Scala).
* Install [Scala IDE](http://scala-ide.org/) 4.6 or later (Eclipse with
pre-installed plugins for Scala).
* Clone this repository:
```bash
......@@ -49,7 +49,7 @@ sbt update genSrc eclipse
The reference implementation is developed and tested with Java VM 8. You need a
JRE to build the Scala/Java part, and a JDK to build the C binding.
You also need [Scala](http://scala-lang.org/) 2.11 and
You also need [Scala](http://scala-lang.org/) 2.12 and
[sbt](http://www.scala-sbt.org/) 0.13. It is recommended to install them using
the package manager of your operating system or distribution (such as apt-get,
yum, pacman, etc. for GNU/Linux distributions and Homebrew for Mac OS X) if such
......@@ -69,7 +69,7 @@ compile this project. Or you can do it step by step:
update`.
* To generate the Mu IR parser from the Antlr grammar, invoke `sbt genSrc`. The
generated sources will be in the `target/scala-2.11/src_managed` directory.
generated sources will be in the `target/scala-2.12/src_managed` directory.
* To compile, invoke `sbt compile`. This will also generate the Mu IR parser
using Antlr.
......
......@@ -17,19 +17,21 @@ lazy val root = (project in file(".")).
licenses := Seq("CC BY-SA 4.0" -> url("https://creativecommons.org/licenses/by-sa/4.0/legalcode")),
scalaVersion := "2.11.11",
scalaVersion := "2.12.2",
libraryDependencies ++= Seq(
"org.antlr" % "antlr4" % "4.7",
"com.typesafe.scala-logging" %% "scala-logging" % "3.5.0",
"com.typesafe.scala-logging" %% "scala-logging" % "3.7.1",
"ch.qos.logback" % "logback-classic" % "1.2.3",
"com.github.jnr" % "jnr-ffi" % "2.1.5",
"com.github.jnr" % "jffi" % "1.2.15" classifier "native",
"com.github.jnr" % "jnr-ffi" % "2.1.6",
"com.github.jnr" % "jffi" % "1.2.16" classifier "native",
"com.github.jnr" % "jnr-posix" % "3.0.41",
"org.scalatest" %% "scalatest" % "3.0.3" % "test",
"junit" % "junit" % "4.12" % "test"
),
scalacOptions += "-language:implicitConversions",
testOptions in Test += Tests.Argument("-oF"), // print full stack trace when testing
parallelExecution in Test := false, // disable parallel tests because the refimpl2 is not thread-safe
......
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 scala.annotation.tailrec
import scala.collection.mutable
import scala.collection.JavaConversions._
import java.util
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
private var nextSigNumber = 0
private var nextConstNumber = 0
private var nextGlobalCellNumber = 0
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
// ------------------------------------------------------------
private def generateName(prefix: String, n: String): String = {
var n_ = prefix + "." + n
while (usedNames contains n_) n_ += "_"
usedNames += n_
n_
}
def newVarName(): GlobalVarName = {
var nextName: String = null
do {
nextName = "global" + nextGlobalCellNumber
nextGlobalCellNumber += 1
} while (usedNames contains nextName)
newVarName(nextName)
}
def newVarName(name: String): GlobalVarName = newVarName(name, baseName)
def newVarName(name: String, prefix: String): GlobalVarName =
GlobalVarName(generateName(prefix, name))
def newTypeName(): TypeName = {
var nextName: String = null
do {
nextName = "type" + nextTypeNumber
nextTypeNumber += 1
} while (usedNames contains nextName)
newTypeName(nextName)
}
def newTypeName(name: String) = TypeName(generateName(typePrefix, name))
def newFuncSigName(): FuncSigName = {
var nextName: String = null
do {
nextName = "sig" + nextSigNumber
nextSigNumber += 1
} while (usedNames contains nextName)
newFuncSigName(nextName)
}
def newFuncSigName(name: String) = FuncSigName(generateName(baseName, name))
def newFuncVerName(function: GlobalVarName): FuncVerName = {
val nameStr = function.name + "_" + java.util.UUID.randomUUID()
usedNames += nameStr
FuncVerName(nameStr)
}
def newFuncVerName(name: String): FuncVerName = FuncVerName(generateName(baseName, name))
def setTypePrefix(newPrefix: String): Unit = typePrefix = newPrefix
def setConstPrefix(newPrefix: String): Unit = constPrefix = newPrefix
// Code generation
// ------------------------------------------------------------
private def descriptiveTypeName(ctor: TypeCtor): TypeName = ctor match {
case TypeCtor.Int(n) => newTypeName("i" + n)
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.UPtr(TypeCtor.Int(n)) => newTypeName("i" + n + "ptr")
case _ => newTypeName()
}
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
}
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(), args, ret)
def funcSig(name: FuncSigName, args: IList[TypeName], ret: IList[TypeName]): FuncSigName = {
funcSigDefs.put(name, new FuncSig(args, ret))
name
}
override def constDef(c: Const): GlobalVarName =
constDefs collectFirst { case (name, existing) if c == existing => name } getOrElse {
var nextName: String = null
do {
nextName = "const" + nextConstNumber
nextConstNumber += 1
} while (usedNames contains nextName)
constDef(newVarName(nextName, constPrefix), c)
}
def constDef(name: GlobalVarName, c: Const): GlobalVarName = {
constDefs.put(name, c)
name
}
def globalCell(`type`: TypeName): GlobalVarName = globalCell(newVarName(), `type`)
def globalCell(name: GlobalVarName, `type`: TypeName): GlobalVarName = {
globalCellDefs.put(name, `type`)
name
}
def funcDecl(name: GlobalVarName, sig: FuncSigName): GlobalVarName = {
funcDecls.put(name, sig)
name
}
def exposeFunc(
exposeName: GlobalVarName,
funcName: GlobalVarName,
callConv: Flag,
cookie: GlobalVarName
): GlobalVarName = {
funcExpDefs.put(exposeName, new Expose(funcName, callConv, cookie))
exposeName
}
def newFuncVersion(
funcName: GlobalVarName,
paramTy: IList[TypeName],
retTy: IList[TypeName]
): FunctionBuilder = newFuncVersion(funcName, newFuncVerName(funcName), paramTy, retTy)
def newFuncVersion(
funcName: GlobalVarName,
versionName: FuncVerName,
paramTy: IList[TypeName],
retTy: IList[TypeName]
): FunctionBuilder = {
val sig = funcSig(paramTy, retTy)
val builder = new FunctionBuilderImpl(
this, funcName, sig, versionName, new IList(paramTy.toSeq.indices.map("param"+_)))
funcVers.put(versionName, builder)
builder
}
def newFuncVersion(
funcName: GlobalVarName,
sigName: FuncSigName,
paramNames: IList[String]
): FunctionBuilder = newFuncVersion(funcName, sigName, newFuncVerName(funcName), paramNames)
def newFuncVersion(
funcName: GlobalVarName,
sigName: FuncSigName,
versionName: FuncVerName,
paramNames: IList[String]
): FunctionBuilder = {
val builder = new FunctionBuilderImpl(this, funcName, sigName, versionName, paramNames)
funcVers.put(versionName, builder)
builder
}
def comment(name: GlobalName, comment: String): Unit = comments.put(name, comment)
def build(): Bundle = new Bundle(
cTypeDefs = typeDefs,
cFuncSigDefs = funcSigDefs,
cConstDefs = constDefs,
cGlobalCellDefs = globalCellDefs,
cFuncDecls = funcDecls,
cFuncVers = funcVers map { case (k, v) => k -> v.build() },
cFuncExpDefs = funcExpDefs,
cComments = comments
)
}
trait FunctionBuilder extends Context {
def functionName: GlobalVarName
def functionSignature: FuncSigName
def versionName: FuncVerName
def paramNames: IList[LocalVarName]
def newVarName(): LocalVarName
def newVarName(name: String): LocalVarName
def newLabelName(): LabelName
def newLabelName(name: String): LabelName
def currentBlockLabel: LabelName
def startNewBlock(): LabelName
def startNewBlock(label: LabelName): LabelName
def inst(inst: PreInst): LocalVarName
def inst(names: IList[LocalVarName], inst: PreInst): Unit
def preBuild(): PreFuncVer
def build(): PostFuncVer
}
private[text] class FunctionBuilderImpl(
context: Context,
override val functionName: GlobalVarName,
override val functionSignature: FuncSigName,
override val versionName: FuncVerName,
val paramNameBases: IList[String]
) extends FunctionBuilder {
type Block = (LabelName, mutable.ArrayBuffer[(IList[LocalVarName], PreInst)])
protected val blocks = mutable.ArrayBuffer.empty[Block]
protected val usedNames = mutable.Set.empty[String]
private var nextVarNumber = 0
private var nextLabelNumber = 0
private var currentBlock: Block = createBlock(newLabelName("entry"))
override lazy val paramNames = new IList(paramNameBases map newVarName)
private def generateName(n: String): String = {
var n_ = n
while (usedNames contains n_) n_ += "_"
usedNames += n_
n_
}
override def newVarName(): LocalVarName = {
var nextName: String = null
do {
nextName = "var" + nextVarNumber
nextVarNumber += 1
} while (usedNames contains nextName)
newVarName(nextName)
}
override def newVarName(name: String): LocalVarName = LocalVarName(generateName(name))
override def newLabelName(): LabelName = {
var nextName: String = null
do {
nextName = "label" + nextLabelNumber
nextLabelNumber += 1
} while (usedNames contains nextName)
newLabelName(nextName)
}
override def newLabelName(name: String): LabelName = LabelName(generateName(name))
private def createBlock(name: LabelName): Block = {
val newBlock = (name, mutable.ArrayBuffer.empty[(IList[LocalVarName], PreInst)])
blocks += newBlock
newBlock
}
override def currentBlockLabel: LabelName = currentBlock._1
override def startNewBlock(): LabelName = startNewBlock(newLabelName())
override def startNewBlock(label: LabelName): LabelName = {
currentBlock = createBlock(label)
label
}
override def inst(inst: PreInst): LocalVarName = {
val name = newVarName()
currentBlock._2 += (IList(name) -> inst)
name
}
override def inst(names: IList[LocalVarName], inst: PreInst): Unit = {
currentBlock._2 += (names -> inst)
}
override def preBuild() = new PreFuncVer(
functionName, functionSignature, paramNames,
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
case class DestClause(dest: LabelName, args: IList[VarName]) {
override def toString = s"$dest($args)"
}
sealed trait Inst {
@throws(classOf[TypeResolveException])
def returnTypes(implicit context: Context): IList[TypeName]
def referencedVars: IList[VarName]
}
sealed trait PreInst extends Inst {
def possibleJumps: IList[LabelName]