Commit 07457d9e authored by Kunshan Wang's avatar Kunshan Wang

command line mu starter

parent 54354982
......@@ -22,6 +22,7 @@ libraryDependencies ++= Seq(
"com.github.jnr" % "jnr-ffi" % "2.0.9",
"com.github.jnr" % "jffi" % "1.2.11",
"com.github.jnr" % "jnr-posix" % "3.0.29",
"org.rogach" %% "scallop" % "1.0.2",
"org.scalatest" %% "scalatest" % "2.2.6" % "test",
"junit" % "junit" % "4.12" % "test"
)
......
......@@ -6,43 +6,158 @@
package uvm.refimpl
import uvm.refimpl.mem.TypeSizes._
import scala.collection.mutable.ArrayBuffer
class VMOption[+T](
val name: String,
val desc: String,
val parser: String => T,
val default: T
) {
def maybeParse(maybeStr: Option[String]): T = {
maybeStr.map(parser).getOrElse(default)
}
def apply(kvMap: Map[String, String]): T = {
maybeParse(kvMap.get(name))
}
}
object VMConfParser {
def sizeWithSuffix(str: String): Long = {
val multiplier = str.last match {
case 'K' => Some(1024L)
case 'M' => Some(1024L * 1024L)
case 'G' => Some(1024L * 1024L * 1024L)
case 'T' => Some(1024L * 1024L * 1024L * 1024L)
case _ => None
}
multiplier match {
case Some(m) => str.init.toLong * m
case None => str.toLong
}
}
def parseBoolean(str: String): Boolean = {
str.toLowerCase().toBoolean
}
def parseColonSeparatedList(str: String): Seq[String] = {
str.split(":")
}
def parseMaybeString(str: String): Option[String] = {
Some(str)
}
val options = new ArrayBuffer[VMOption[Any]]
def opt[T](
name: String,
desc: String,
parser: String => T,
default: T
): VMOption[T] = {
val option = new VMOption[T](name, desc, parser, default)
options += option
option
}
val sosSize = opt[Long](
name = "sosSize",
desc = """The size of the small object space in bytes. May have suffix K, M, G or T. 1K = 1024B""",
parser = sizeWithSuffix,
default = VMConf.DEFAULT_CONF.sosSize)
val losSize = opt[Long](
name = "losSize",
desc = """The size of the large object space in bytes. May have suffix K, M, G or T. 1K = 1024B""",
parser = sizeWithSuffix,
default = VMConf.DEFAULT_CONF.losSize)
val globalSize = opt[Long](
name = "globalSize",
desc = """The size of the large object space in bytes. May have suffix K, M, G or T. 1K = 1024B""",
parser = sizeWithSuffix,
default = VMConf.DEFAULT_CONF.globalSize)
val stackSize = opt[Long](
name = "stackSize",
desc = """The size of each stack in bytes. May have suffix K, M, G or T. 1K = 1024B""",
parser = sizeWithSuffix,
default = VMConf.DEFAULT_CONF.stackSize)
val staticCheck = opt[Boolean](
name = "staticCheck",
desc = """Run static checker after each bundle is loaded.""",
parser = parseBoolean,
default = VMConf.DEFAULT_CONF.staticCheck)
val sourceInfo = opt[Boolean](
name = "sourceInfo",
desc = """Provide line/column info in Mu IR when errors occur. May significantly slow down parsing!!!""",
parser = parseBoolean,
default = VMConf.DEFAULT_CONF.sourceInfo)
val extraLibs = opt[Seq[String]](
name = "extraLibs",
desc = """Extra libraries to load when starting the micro VM. This is a colon-separated list of libraries.
Each is passed to the dlsym function.""",
parser = parseColonSeparatedList,
default = VMConf.DEFAULT_CONF.extraLibs)
val bootImg = opt[Option[String]](
name = "bootImg",
desc = """The path to the boot image.""",
parser = parseMaybeString,
default = VMConf.DEFAULT_CONF.bootImg)
val vmLog = opt[String](
name = "vmLog",
desc = """The log level of the micro VM. Can be ALL, TRACE, DEBUG, INFO, WARN, ERROR, OFF""",
parser = identity,
default = "WARN")
val gcLog = opt[String](
name = "gcLog",
desc = """The log level of the garbage collector. Can be ALL, TRACE, DEBUG, INFO, WARN, ERROR, OFF""",
parser = identity,
default = "ERROR")
}
object VMConf {
val DEFAULT_CONF = new VMConf()
val ReComment = """^\s*#.*$""".r
val ReBlank = """^\s*$""".r
val ReConf = """^\s*(\w+)=(\w+)\s*$""".r
val ReConf = """^\s*(\w+)=(\S+)\s*$""".r
def apply(confStr: String): VMConf = {
var sosSize = DEFAULT_CONF.sosSize
var losSize = DEFAULT_CONF.losSize
var globalSize = DEFAULT_CONF.globalSize
var stackSize = DEFAULT_CONF.stackSize
var staticCheck = DEFAULT_CONF.staticCheck
var sourceInfo = DEFAULT_CONF.sourceInfo
var extraLibs = DEFAULT_CONF.extraLibs
var bootImg: Option[String] = None
confStr.lines foreach {
case ReComment() =>
case ReBlank() =>
case ReConf(key, value) => {
key match {
case "sosSize" => sosSize = value.toLong
case "losSize" => losSize = value.toLong
case "globalSize" => globalSize = value.toLong
case "stackSize" => stackSize = value.toLong
case "staticCheck" => staticCheck = value.toLowerCase().toBoolean
case "sourceInfo" => sourceInfo = value.toLowerCase().toBoolean
case "vmLog" => setLog("uvm", value)
case "gcLog" => setLog("uvm.refimpl.mem", value)
case "extraLibs" => extraLibs = value.split(":")
case "bootImg" => bootImg = Some(value)
case _ => throw new UvmRefImplException("Unrecognized option %s".format(key))
}
}
}
new VMConf(sosSize, losSize, globalSize, stackSize, staticCheck, sourceInfo, extraLibs, bootImg)
val kvs = confStr.lines map {
case ReComment() => None
case ReBlank() => None
case ReConf(key, value) => Some((key, value))
} flatten
val map = kvs.toMap
apply(map)
}
def apply(kvMap: Map[String, String]): VMConf = {
kvMap.get("vmLog") foreach { value => setLog("uvm", value) }
kvMap.get("gcLog") foreach { value => setLog("uvm.refimpl.mem", value) }
new VMConf(
sosSize = VMConfParser.sosSize(kvMap),
losSize = VMConfParser.losSize(kvMap),
globalSize = VMConfParser.globalSize(kvMap),
stackSize = VMConfParser.stackSize(kvMap),
staticCheck = VMConfParser.staticCheck(kvMap),
sourceInfo = VMConfParser.sourceInfo(kvMap),
extraLibs = VMConfParser.extraLibs(kvMap),
bootImg = VMConfParser.bootImg(kvMap)
)
}
def setLog(name: String, levelStr: String): Unit = {
......@@ -63,7 +178,7 @@ class VMConf(
val globalSize: Word = MicroVM.DEFAULT_GLOBAL_SIZE,
val stackSize: Word = MicroVM.DEFAULT_STACK_SIZE,
val staticCheck: Boolean = true,
val sourceInfo: Boolean = true,
val sourceInfo: Boolean = false,
val extraLibs: Seq[String] = Seq(),
val bootImg: Option[String] = None)
......@@ -22,6 +22,7 @@ import uvm.utils.MappedIDFactory
import uvm.utils.WithUtils.tryWithResource
import uvm.refimpl.itpr.OpHelper
import uvm.Function
import java.io.FileNotFoundException
object BootImageLoader {
val MUTATOR_NAME = "bootimgldr"
......@@ -39,7 +40,12 @@ class BootImageLoader(file: String)(implicit microVM: MicroVM) {
private implicit val memorySupport = memoryManager.memorySupport
val bootImagePath = Paths.get(file)
val zip = new ZipFile(bootImagePath.toFile())
val zip = try {
new ZipFile(bootImagePath.toFile())
} catch {
case e: FileNotFoundException => throw new BootImageLoaderException(
"Boot image not found: " + file, e)
}
val objNumToAddr = new HashMap[Long, Word]()
def globalNumToAddr(num: Long): Word = {
......
......@@ -2,18 +2,67 @@ package uvm.refimpl.cmdline
import uvm.refimpl.MicroVM
import uvm.refimpl.nat.ScalaCInitiater
import scala.collection.mutable.HashMap
import uvm.refimpl.VMConf
/** Run Mu from the command line. */
object RunMu {
def main(args: Array[String]): Unit = {
println("Welcome!")
ScalaCInitiater.configureLog()
val configText = args.mkString("\n")
private val KVOPT = """--(\w+)=(.+)""".r
private val SEP = "--"
private val HELP = "-h|--help".r
val microVM = MicroVM(configText)
def main(args: Array[String]): Unit = {
val props = new HashMap[String, String]()
var curArgs = args.toList
var parsing = true
while(parsing) {
curArgs match {
case Nil => parsing = false
case arg :: rest => {
arg match {
case HELP() => {
System.err.println(DOCSTRING)
return
}
case SEP => {
curArgs = rest
parsing = false
}
case KVOPT(k,v) => {
props(k) = v
curArgs = rest
}
case _ => {
parsing = false
}
}
}
}
}
println("Hello! this is micro VM!")
args foreach println
val (bootImg, appArgs) = curArgs match {
case h::t => (h, t)
case Nil => {
System.err.println(DOCSTRING)
return
}
}
props("bootImg") = bootImg
val microVM = new MicroVM(VMConf(props.toMap))
}
private val DOCSTRING = """USAGE: runmu.sh --prop1=value1 --prop2=value2 ... [--] bootimg [args...]
Properties and values are the same as the argument of mu_refimpl_new_ex. See
README.md for more information.
bootimg is the path to the boot image (overrides the bootImg property if set).
It will start execution at the entry point specified in the boot image.
Extra args will be passed to the entry point function.
"""
}
\ No newline at end of file
......@@ -10,4 +10,4 @@ if [[ ! -f ${CLASSPATH_TXT} ]]; then
popd
fi
JAVA_OPTS="-Xmx4096M" scala -cp $(< ${CLASSPATH_TXT}) uvm.refimpl.cmdline.RunMu $*
exec java -Xmx4096M -cp $(< ${CLASSPATH_TXT}) uvm.refimpl.cmdline.RunMu "$@"
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