GitLab will be upgraded to the 12.10.14-ce.0 on 28 Sept 2020 at 2.00pm (AEDT) to 2.30pm (AEDT). During the update, GitLab and Mattermost services will not be available. If you have any concerns with this, please talk to us at N110 (b) CSIT building.

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

Added pre-SSA to SSA conversion

parent 4c11b17c
......@@ -3,21 +3,20 @@ lazy val genSrc = taskKey[List[File]]("generate sources")
genSrc <<= (sourceGenerators in Compile) { }
lazy val root = (project in file(".")).settings(
organization := "org.microvm",
organization := "org.microvm"
name := "microvm-refimpl2",
name := "microvm-refimpl2"
version := "2.1.0",
version := "2.1.0"
description := "The second reference implementation of Mu, the micro virtual machine",
description := "The second reference implementation of Mu, the micro virtual machine"
licenses := Seq("CC BY-SA 4.0" -> url("")),
licenses := Seq("CC BY-SA 4.0" -> url(""))
scalaVersion := "2.11.7",
scalaVersion := "2.11.7"
libraryDependencies ++= Seq(
"org.antlr" % "antlr4" % "4.5.1-1",
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",
......@@ -25,17 +24,15 @@ lazy val root = (project in file(".")).settings(
"com.github.jnr" % "jnr-posix" % "3.0.23",
"org.scalatest" %% "scalatest" % "2.2.4" % "test",
"junit" % "junit" % "4.12" % "test"
testOptions in Test += Tests.Argument("-oF"), // print full stack trace when testing
testOptions in Test += Tests.Argument("-oF") // print full stack trace when testing
antlr4PackageName in Antlr4 := Some(""),
antlr4PackageName in Antlr4 := Some("")
antlr4GenListener in Antlr4 := false,
antlr4GenVisitor in Antlr4 := false
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) }
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")
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)
This diff is collapsed.
package uvm.clientsupport.text
sealed abstract class TypeCtor(str: => String) {
override lazy val toString: String = str
object TypeCtor {
def Void = Singletons.Void; type Void = Singletons.Void.type
case class Int(bits: scala.Int) extends TypeCtor(s"int<$bits>")
def Float = Singletons.Float; type Float = Singletons.Float.type
def Double = Singletons.Double; type Double = Singletons.Double.type
def ThreadRef = Singletons.ThreadRef; type ThreadRef = Singletons.ThreadRef.type
def StackRef = Singletons.StackRef; type StackRef = Singletons.StackRef.type
def FrameCursorRef = Singletons.FrameCursorRef; type FrameCursorRef = Singletons.FrameCursorRef.type
case class Ref(ty: TypeCtor) extends TypeCtor(s"ref<$ty>")
case class IRef(ty: TypeCtor) extends TypeCtor(s"iref<$ty>")
case class WeakRef(ty: TypeCtor) extends TypeCtor(s"weakref<$ty>")
case class FuncRef(sig: FuncSigName) extends TypeCtor(s"funcref<$sig>")
case class UPtr(ty: TypeCtor) extends TypeCtor(s"uptr<$ty>")
case class UFuncPtr(sig: FuncSigName) extends TypeCtor(s"ufuncptr<$sig>")
def TagRef64 = Singletons.TagRef64; type TagRef64 = Singletons.TagRef64.type
case class Array(ty: TypeCtor, len: scala.Long) extends TypeCtor(s"array<$ty $len>")
case class Vector(ty: TypeCtor, len: scala.Int) extends TypeCtor(s"vector<$ty $len>")
case class Hybrid(fixedTy: TypeCtor, varTy: TypeCtor) extends TypeCtor(s"hybrid<$fixedTy $varTy>")
case class Struct(types: IList[TypeCtor]) extends TypeCtor(s"struct<${types mkString " "}>")
object Singletons {
case object Void extends TypeCtor("void")
case object Float extends TypeCtor("float")
case object Double extends TypeCtor("double")
case object ThreadRef extends TypeCtor("threadref")
case object StackRef extends TypeCtor("stackref")
case object FrameCursorRef extends TypeCtor("framecursorref")
case object TagRef64 extends TypeCtor("tagref64")
sealed trait MuName {
def name: String
sealed trait GlobalName extends MuName {
override lazy val toString = "@" + name
sealed trait LocalName extends MuName {
override lazy val toString = "%" + name
sealed trait VarName extends MuName
case class TypeName(name: String) extends TypeCtor("@" + name) with GlobalName
case class FuncSigName(name: String) extends GlobalName
case class FuncVerName(name: String) extends GlobalName
case class GlobalVarName(name: String) extends GlobalName with VarName
case class LocalVarName(name: String) extends LocalName with VarName
case class LabelName(name: String) extends LocalName
final class Flag(cName: String) {
val name = cName.toUpperCase.replaceAll("[^A-Z_]", "")
override def toString = "#" + name
package uvm.clientsupport.text
sealed abstract class Const(str: => String) {
def ty: TypeName
override def toString = str
object Const {
case class Null(ty: TypeName) extends Const("NULL")
case class Int(ty: TypeName, value: scala.Long) extends Const(value.toString)
case class Float(ty: TypeName, value: scala.Float)
extends Const(s"bitsf(0x${Integer.toHexString(java.lang.Float.floatToRawIntBits(value))})")
case class Double(ty: TypeName, value: scala.Double)
extends Const(s"bitsd(0x${java.lang.Long.toHexString(java.lang.Double.doubleToRawLongBits(value))})")
case class Pointer(ty: TypeName, addr: scala.Long) extends Const(addr.toString)
case class List(ty: TypeName, fields: IList[GlobalVarName]) extends Const(s"{$fields}")
case class FuncSig(paramTy: IList[TypeName], retTy: IList[TypeName]) {
override def toString = s"($paramTy) -> ($retTy)"
case class PreFuncVer(
func: GlobalVarName,
sig: FuncSigName,
params: IList[LocalVarName],
bbs: IList[PreBasicBlock]
) {
override lazy val toString = "(" + params + ") {\n" + (bbs mkString "\n") + "\n}"
case class PostFuncVer(func: GlobalVarName, sig: FuncSigName, bbs: IList[PostBasicBlock]) {
override lazy val toString = "{\n" + (bbs mkString "\n") + "\n}"
case class Expose(func: GlobalVarName, callConv: Flag, cookie: GlobalVarName) {
override def toString = s"$func $callConv $cookie"
trait Context {
def resolve(typeName: TypeName): Option[TypeCtor]
def resolve(funcSigName: FuncSigName): Option[FuncSig]
def typeDef(ctor: TypeCtor): TypeName
def funcSig(args: IList[TypeName], ret: IList[TypeName]): FuncSigName
def constDef(c: Const): GlobalVarName
\ No newline at end of file
package uvm.clientsupport.text
import java.util.regex.Pattern
import org.scalatest.matchers.{MatchResult, Matcher}
trait TextOutputMatchers {
private val varPattern = Pattern compile "[@%]\\$(\\w+)"
private val specialPattern = Pattern compile "\\s+|[@%]\\$\\w+"
class IRTemplateMatcher(outputTemplate: String) extends Matcher[BundleBuilder] {
private val lines = outputTemplate split "\n" map (_.trim) filter (_.nonEmpty)
private lazy val varIndexes = lines map { line =>
val matcher = varPattern matcher line
var indexes = Seq.empty[String]
while (matcher.find) indexes :+= matcher group 1
private lazy val linePatterns = lines map (line => Pattern compile {
var pattern = "^"
var lastEnd = 0
val matcher = specialPattern matcher line
while (matcher.find) {
val slice = line.substring(lastEnd, matcher.start)
if (slice.nonEmpty) pattern += Pattern quote slice
if ( matches "\\s+") pattern += "\\s+"
else pattern += "([@%][\\w\\-.]+)"
lastEnd = matcher.end
if (lastEnd < line.length) pattern += (Pattern quote (line substring lastEnd))
pattern + "$"
override def apply(left: BundleBuilder): MatchResult = {
val ir =
val testLines = ir split "\n" map (_.trim) filter (_.nonEmpty)
var varMap = Map.empty[String, String]
for ((((line, n), pattern), vars) <- testLines.zipWithIndex zip linePatterns zip varIndexes) {
val matcher = pattern matcher line
if (matcher.matches) {
for ((varName, index) <- vars.zipWithIndex) {
varMap get varName match {
case Some(value) =>
val newValue = matcher group (index+1)
if (newValue != value) return MatchResult(matches = false,
s"Placeholder variable $varName had differing values ($value, $newValue)\nin IR:\n$ir",
s"Placeholder variable $varName had consistent value ($value)")
case None => varMap += varName -> (matcher group (index+1))
} else return MatchResult(matches = false,
s"""Line $n, "$line", did not match regex "$pattern"
in IR:
s"""Line $n, "$line", matched regex "$pattern"""")
MatchResult(lines.length == testLines.length,
s"IR with ${testLines.length} lines did not match template with ${lines.length} lines",
s"IR with ${testLines.length} lines matched template with ${lines.length} lines")
def matchIRTemplate(template: String) = new IRTemplateMatcher(template)
object TextOutputMatchers extends TextOutputMatchers
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