WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

Commit 4c11b17c authored by Adam R. Nelson's avatar Adam R. Nelson
Browse files

Merge branch 'master' of https://github.com/microvm/microvm-refimpl2 into client-uir-writer

parents 2608dee4 607995f8
......@@ -9,3 +9,4 @@ target
......@@ -2,11 +2,13 @@ Mu Reference Implementation version 2
This project is the current reference implementation of Mu, the micro virtual
machine designed by [The Micro Virtual Machine Project](http://microvm.org). It
implements the [Mu Specification version
machine designed by [The Micro Virtual Machine Project](http://microvm.org).
This project is based on the
Version 2.1.x implements the [master branch of the Mu
which uses the goto-with-values form.
This project is based on the previous works of
[microvm-refimpl](https://github.com/microvm-project/microvm-refimpl) is the
previous reference implementation.
......@@ -21,7 +23,7 @@ How to compile
`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.0 (Eclipse with pre-installed
* Install [Scala IDE](http://scala-ide.org/) 4.x (Eclipse with pre-installed
plugins for Scala).
* Clone this repository:
......@@ -32,9 +34,7 @@ git clone git@github.com:microvm/microvm-refimpl2.git
* In the directory `microvm-refimpl2`, do the following:
sbt update
sbt antlr4:antlr4Generate
sbt eclipse
sbt update genSrc eclipse
* Open Scala IDE and import the generated project as "existing project into
......@@ -50,15 +50,16 @@ yum, pacman, etc. for GNU/Linux distributions and Homebrew for Mac OS X).
To download all dependencies from the Maven central repository, invoke `sbt
To generate the Mu IR parser from its Antlr grammar, invoke `sbt
antlr4:antlr4Generate`. The generated sources will be in
`target/scala-2.11/src_managed`. Make sure your IDE can see those generated
To compile, invoke `sbt compile` or do this in your favourite IDE.
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.
To generate an Eclipse project, install the [sbt-eclipse
plugin](https://github.com/typesafehub/sbteclipse) and invoke `sbt eclipse`.
Make sure you generate the parser before creating the Eclipse project, so that
the generated sources will be on the Eclipse build path.
To compile, invoke `sbt compile`. This will also generate the Mu IR parser using
IntelliJ IDEA has plugins for Scala and SBT. Make sure you don't commit `.idea`
or generated project files into the repository.
organization := "org.microvm"
name := "microvm-refimpl2"
lazy val genSrc = taskKey[List[File]]("generate sources")
description := "The second reference implementation of Mu, the micro virtual machine"
genSrc <<= (sourceGenerators in Compile) { _.join.map(_.flatten.toList) }
licenses := Seq("CC BY-SA 4.0" -> url("https://creativecommons.org/licenses/by-sa/4.0/legalcode"))
lazy val root = (project in file(".")).settings(
organization := "org.microvm",
scalaVersion := "2.11.7"
name := "microvm-refimpl2",
version := "2.1.0",
libraryDependencies := Seq(
"org.antlr" % "antlr4" % "4.5.1",
"com.typesafe.scala-logging" %% "scala-logging" % "3.1.0",
"ch.qos.logback" % "logback-classic" % "1.1.2",
"com.github.jnr" % "jnr-ffi" % "2.0.3",
"com.github.jnr" % "jffi" % "1.2.9",
"com.github.jnr" % "jnr-posix" % "3.0.17",
"org.scalatest" %% "scalatest" % "2.2.0" % "test",
"junit" % "junit" % "4.12" % "test"
description := "The second reference implementation of Mu, the micro virtual machine",
antlr4PackageName in Antlr4 := Some("uvm.ir.textinput.gen")
licenses := Seq("CC BY-SA 4.0" -> url("https://creativecommons.org/licenses/by-sa/4.0/legalcode")),
antlr4GenListener in Antlr4 := false
scalaVersion := "2.11.7",
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"
testOptions in Test += Tests.Argument("-oF"), // print full stack trace when testing
antlr4PackageName in Antlr4 := Some("uvm.ir.textinput.gen"),
antlr4GenListener in Antlr4 := false,
antlr4GenVisitor in Antlr4 := false
antlr4GenVisitor in Antlr4 := false
EclipseKeys.createSrc := EclipseCreateSrc.Default + EclipseCreateSrc.Resource + EclipseCreateSrc.Managed
#ifndef __MUAPI_H__
#define __MUAPI_H__
#ifdef __cplusplus
extern "C" {
#include <stdint.h>
// MuValue and MuXxxValue type are opaque handles to values in the Mu type
// system.
// The actual values are held by MuCtx. MuValue opaquely refers to one such
// value. Copies of MuValue values refer to the same value. A MuValue instance
// can only be used in the MuCtx holding it.
// Values of subtypes can be cast to MuValue and back using the type cast
// expression in C, similar to casting one pointer to another.
typedef void *MuValue; // Any Mu value
typedef void *MuIntValue; // int<n>
typedef void *MuFloatValue; // float
typedef void *MuDoubleValue; // double
typedef void *MuRefValue; // ref<T>
typedef void *MuIRefValue; // iref<T>
typedef void *MuStructValue; // struct<...>
typedef void *MuArrayValue; // array<T l>
typedef void *MuVectorValue; // vector<T l>
typedef void *MuFuncRefValue; // funcref<sig>
typedef void *MuThreadRefValue; // threadref
typedef void *MuStackRefValue; // stackref
typedef void *MuFCRefValue; // framecursorref
typedef void *MuTagRef64Value; // tagref64
typedef void *MuUPtrValue; // uptr
typedef void *MuUFPValue; // ufuncptr
// Identifiers and names of Mu
typedef uint32_t MuID;
typedef char *MuName;
// Convenient types for the void* type and the void(*)() type in C
typedef void *MuCPtr;
typedef void (*MuCFP)();
// Result of a trap handler
typedef int MuTrapHandlerResult;
// Used by new_thread
typedef int MuHowToResume;
#define MU_THREAD_EXIT 0x00
#define MU_REBIND_THROW_EXC 0x02
// Declare the types here because they are used in the following signatures.
typedef struct MuVM MuVM;
typedef struct MuCtx MuCtx;
// Signature of the trap handler
typedef void (*MuTrapHandler)(MuCtx *ctx, MuThreadRefValue thread,
MuStackRefValue stack, int wpid, MuTrapHandlerResult *result,
MuStackRefValue *new_stack, MuValue *values, int *nvalues,
MuRefValue *exception,
MuCPtr userdata);
// Memory orders
typedef int MuMemOrd;
#define MU_NOT_ATOMIC 0x00
#define MU_RELAXED 0x01
#define MU_CONSUME 0x02
#define MU_ACQUIRE 0x03
#define MU_RELEASE 0x04
#define MU_ACQ_REL 0x05
#define MU_SEQ_CST 0x06
// Operations for the atomicrmw API function
typedef int MuAtomicRMWOp;
#define MU_XCHG 0x00
#define MU_ADD 0x01
#define MU_SUB 0x02
#define MU_AND 0x03
#define MU_NAND 0x04
#define MU_OR 0x05
#define MU_XOR 0x06
#define MU_MAX 0x07
#define MU_MIN 0x08
#define MU_UMAX 0x09
#define MU_UMIN 0x0A
// Calling conventions.
typedef int MuCallConv;
#define MU_DEFUALT 0x00
// Concrete Mu implementations may define more calling conventions.
// NOTE: MuVM and MuCtx are structures with many function pointers. This
// approach loosens the coupling between the client module and the Mu
// implementation. At compile time, the client does not need to link against
// any dynamic libraries. At run time, more than one Mu implementations can be
// used by the same client.
// A handle and method lists of a micro VM
struct MuVM {
void *header; // Refer to internal stuff
// Create context
MuCtx* (*new_context)(MuVM *mvm);
// Convert between IDs and names
MuID (*id_of )(MuVM *mvm, MuName name);
MuName (*name_of)(MuVM *mvm, MuID id);
// Set handlers
void (*set_trap_handler )(MuVM *mvm, MuTrapHandler trap_handler, MuCPtr userdata);
// A local context. It can only be used by one thread at a time. It holds many
// states which are typically held by a Mu thread, such as object references,
// local heap allocation pool, and an object-pinning set. It also holds many Mu
// values and expose them to the client as opaque handles (MuValue and its
// subtypes).
struct MuCtx {
void *header; // Refer to internal stuff
// Convert between IDs and names
MuID (*id_of )(MuCtx *ctx, MuName name);
MuName (*name_of)(MuCtx *ctx, MuID id);
// Close the current context, releasing all resources
void (*close_context)(MuCtx *ctx);
// Load bundles and HAIL scripts
void (*load_bundle)(MuCtx *ctx, char *buf, int sz);
void (*load_hail )(MuCtx *ctx, char *buf, int sz);
// Convert from C values to Mu values
MuIntValue (*handle_from_int8 )(MuCtx *ctx, int8_t num, int len);
MuIntValue (*handle_from_uint8 )(MuCtx *ctx, uint8_t num, int len);
MuIntValue (*handle_from_int16 )(MuCtx *ctx, int16_t num, int len);
MuIntValue (*handle_from_uint16)(MuCtx *ctx, uint16_t num, int len);
MuIntValue (*handle_from_int32 )(MuCtx *ctx, int32_t num, int len);
MuIntValue (*handle_from_uint32)(MuCtx *ctx, uint32_t num, int len);
MuIntValue (*handle_from_int64 )(MuCtx *ctx, int64_t num, int len);
MuIntValue (*handle_from_uint64)(MuCtx *ctx, uint64_t num, int len);
MuFloatValue (*handle_from_float )(MuCtx *ctx, float num);
MuDoubleValue (*handle_from_double)(MuCtx *ctx, double num);
MuUPtrValue (*handle_from_ptr )(MuCtx *ctx, MuID mu_type, MuCPtr ptr);
MuUFPValue (*handle_from_fp )(MuCtx *ctx, MuID mu_type, MuCFP fp);
// Convert from Mu values to C values
int8_t (*handle_to_sint8 )(MuCtx *ctx, MuIntValue opnd);
uint8_t (*handle_to_uint8 )(MuCtx *ctx, MuIntValue opnd);
int16_t (*handle_to_sint16)(MuCtx *ctx, MuIntValue opnd);
uint16_t (*handle_to_uint16)(MuCtx *ctx, MuIntValue opnd);
int32_t (*handle_to_sint32)(MuCtx *ctx, MuIntValue opnd);
uint32_t (*handle_to_uint32)(MuCtx *ctx, MuIntValue opnd);
int64_t (*handle_to_sint64)(MuCtx *ctx, MuIntValue opnd);
uint64_t (*handle_to_uint64)(MuCtx *ctx, MuIntValue opnd);
float (*handle_to_float )(MuCtx *ctx, MuFloatValue opnd);
double (*handle_to_double)(MuCtx *ctx, MuDoubleValue opnd);
MuCPtr (*handle_to_ptr )(MuCtx *ctx, MuUPtrValue opnd);
MuCFP (*handle_to_fp )(MuCtx *ctx, MuUFPValue opnd);
// Make MuValue instances from Mu global SSA variables
MuValue (*handle_from_const )(MuCtx *ctx, MuID id);
MuIRefValue (*handle_from_global)(MuCtx *ctx, MuID id);
MuFuncRefValue (*handle_from_func )(MuCtx *ctx, MuID id);
MuValue (*handle_from_expose)(MuCtx *ctx, MuID id);
// Delete the value held by the MuCtx, making it unusable, but freeing up
// the resource.
void (*delete_value)(MuCtx *ctx, MuValue opnd);
// Compare reference or general reference types.
// EQ. Available for ref, iref, funcref, threadref and stackref.
int (*ref_eq )(MuCtx *ctx, MuValue lhs, MuValue rhs);
// ULT. Available for iref only.
int (*ref_ult)(MuCtx *ctx, MuIRefValue lhs, MuIRefValue rhs);
// Manipulate Mu values of the struct<...> type
MuValue (*extract_value)(MuCtx *ctx, MuStructValue str, int index);
MuValue (*insert_value )(MuCtx *ctx, MuStructValue str, int index, MuValue newval);
// Manipulate Mu values of the array or vector type
// str can be MuArrayValue or MuVectorValue
MuValue (*extract_element)(MuCtx *ctx, MuValue str, MuIntValue index);
MuValue (*insert_element )(MuCtx *ctx, MuValue str, MuIntValue index, MuValue newval);
// Heap allocation
MuRefValue (*new_fixed )(MuCtx *ctx, MuID mu_type);
MuRefValue (*new_hybrid)(MuCtx *ctx, MuID mu_type, MuIntValue length);
// Change the T or sig in ref<T>, iref<T> or func<sig>
MuValue (*refcast)(MuCtx *ctx, MuValue opnd, MuID new_type);
// Memory addressing
MuIRefValue (*get_iref )(MuCtx *ctx, MuRefValue opnd);
MuIRefValue (*get_field_iref )(MuCtx *ctx, MuIRefValue opnd, int field);
MuIRefValue (*get_elem_iref )(MuCtx *ctx, MuIRefValue opnd, MuIntValue index);
MuIRefValue (*shift_iref )(MuCtx *ctx, MuIRefValue opnd, MuIntValue offset);
MuIRefValue (*get_var_part_iref )(MuCtx *ctx, MuIRefValue opnd);
// Memory accessing
MuValue (*load )(MuCtx *ctx, MuMemOrd ord, MuIRefValue loc);
void (*store )(MuCtx *ctx, MuMemOrd ord, MuIRefValue loc, MuValue newval);
MuValue (*cmpxchg )(MuCtx *ctx, MuMemOrd ord_succ, MuMemOrd ord_fail,
int weak, MuIRefValue loc, MuValue expected, MuValue desired,
int *is_succ);
MuValue (*atomicrmw)(MuCtx *ctx, MuMemOrd ord, MuAtomicRMWOp op,
MuIRefValue loc, MuValue opnd);
void (*fence )(MuCtx *ctx, MuMemOrd ord);
// Thread and stack creation and stack destruction
MuStackRefValue (*new_stack )(MuCtx *ctx, MuFuncRefValue func);
MuThreadRefValue (*new_thread)(MuCtx *ctx, MuStackRefValue stack,
MuHowToResume *htr, MuValue *vals, int nvals, MuRefValue *exc);
void (*kill_stack)(MuCtx *ctx, MuStackRefValue stack);
// Frame cursor operations
MuFCRefValue (*new_cursor )(MuCtx *ctx, MuStackRefValue stack);
void (*next_frame )(MuCtx *ctx, MuFCRefValue cursor);
MuFCRefValue (*copy_cursor )(MuCtx *ctx, MuFCRefValue cursor);
void (*close_cursor)(MuCtx *ctx, MuFCRefValue cursor);
// Stack introspection
MuID (*cur_func )(MuCtx *ctx, MuFCRefValue cursor);
MuID (*cur_func_ver )(MuCtx *ctx, MuFCRefValue cursor);
MuID (*cur_inst )(MuCtx *ctx, MuFCRefValue cursor);
void (*dump_keepalives)(MuCtx *ctx, MuFCRefValue cursor, MuValue *results);
// On-stack replacement
void (*pop_frames_to)(MuCtx *ctx, MuFCRefValue cursor);
void (*push_frame )(MuCtx *ctx, MuStackRefValue stack, MuFuncRefValue func);
// 64-bit tagged reference operations
int (*tr64_is_fp )(MuCtx *ctx, MuTagRef64Value value);
int (*tr64_is_int )(MuCtx *ctx, MuTagRef64Value value);
int (*tr64_is_ref )(MuCtx *ctx, MuTagRef64Value value);
MuDoubleValue (*tr64_to_fp )(MuCtx *ctx, MuTagRef64Value value);
MuIntValue (*tr64_to_int )(MuCtx *ctx, MuTagRef64Value value);
MuRefValue (*tr64_to_ref )(MuCtx *ctx, MuTagRef64Value value);
MuIntValue (*tr64_to_tag )(MuCtx *ctx, MuTagRef64Value value);
MuTagRef64Value (*tr64_from_fp )(MuCtx *ctx, MuDoubleValue value);
MuTagRef64Value (*tr64_from_int)(MuCtx *ctx, MuIntValue value);
MuTagRef64Value (*tr64_from_ref)(MuCtx *ctx, MuRefValue ref, MuIntValue tag);
// Watchpoint operations
void (*enable_watchpoint )(MuCtx *ctx, int wpid);
void (*disable_watchpoint)(MuCtx *ctx, int wpid);
// Mu memory pinning, usually object pinning
MuUPtrValue (*pin )(MuCtx *ctx, MuValue loc); // loc is either MuRefValue or MuIRefValue
void (*unpin)(MuCtx *ctx, MuValue loc); // loc is either MuRefValue or MuIRefValue
// Expose Mu functions as native callable things, usually function pointers
MuValue (*expose )(MuCtx *ctx, MuFuncRefValue func, MuCallConv call_conv, MuIntValue cookie);
void (*unexpose)(MuCtx *ctx, MuCallConv call_conv, MuValue value);
#ifdef __cplusplus
#endif // __MUAPI_H__
if [ x$SED == x ]; then
$SED -i 's/newClientAgent/newContext/g' $FN
$SED -i 's/ClientAgent/MuCtx/g' $FN
$SED -i 's/deleteHandle/deleteValue/g' $FN
$SED -i 's/\bca\b/ctx/g' $FN
$SED -i 's/ctx\.close()/ctx.closeContext()/g' $FN
$SED -i 's/Handle/MuValue/g' $FN
$SED -i 's/putInt("@i32",/handleFromInt32(/g' $FN
$SED -i 's/putInt("@i64",/handleFromInt64(/g' $FN
$SED -i 's/putInt("@i\(\d\+\)"\s*,\s*\([^)]*\))/handleFromInt(\2, \1)/g' $FN
$SED -i 's/putFloat("@float",/handleFromFloat(/g' $FN
$SED -i 's/putDouble("@double",/handleFromDouble(/g' $FN
$SED -i 's/putConstant/handleFromConst/g' $FN
$SED -i 's/putGlobal/handleFromGlobal/g' $FN
$SED -i 's/putFunction/handleFromFunc/g' $FN
$SED -i 's/putExpFunc/handleFromExpose/g' $FN
$SED -i 's/toInt(\(\w\+\),\s*\(signExt\s*=\s*\)\?true)/handleToSInt(\1.asInstanceOf[MuIntValue])/g' $FN
$SED -i 's/toInt(\(\w\+\))/handleToUInt(\1.asInstanceOf[MuIntValue])/g' $FN
$SED -i 's/toFloat/handleToFloat/g' $FN
$SED -i 's/toDouble/handleToDouble/g' $FN
$SED -i 's/toPointer/handleToPtr/g' $FN
$SED -i 's/refCast/refcast/g' $FN
$SED -i 's/currentInstruction/curInst/g' $FN
$SED -i 's/TrapRebindPassVoid/returnFromTrap/g' $FN
$SED -i 's/TrapRebindPassValue(\(\w\+\),\s*\(\w\+\)\s*)/Rebind(\1, PassValues(Seq(\2)))/g' $FN
if [ x$SED == x ]; then
$SED -i 's/\(%\w\+\)\s*=\s*TRAP/[\1] TRAP/g' $FN
$SED -i 's/NEWSTACK\s*<\(@[0-9a-zA-Z._-]\+\)>\s*\(@\w\+\)/COMMINST @uvm.new_stack <[\1]> (\2)/g' $FN
$SED -i 's/COMMINST\s*@uvm\.new_thread\s*(\([@%]\w\+\))/NEWTHREAD \1 PASS_VALUES /g' $FN
$SED -i 's/TRAP\s*<@void>/TRAP <>/g' $FN
$SED -i 's/noparamsnoret/v_v/g' $FN
$SED -i 's/@funcdumb/@frv_v/g' $FN
$SED -i '/\.funcsig/ {s/@void\s*(\([^)]*\))/(\1) -> ()/g}' $FN
$SED -i '/\.funcsig/ {s/=\s*\(@\w\+\)\s*(\([^)]*\))/= (\2) -> (\1)/}' $FN
$SED -i 's/@i_ii/@ii_i/g' $FN
$SED -i 's/RET @VOID/RET ()/g' $FN
$SED -i 's/hybrid\s*<@void\s*/hybrid</g' $FN
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "2.5.0")
addSbtPlugin("com.typesafe.sbteclipse" % "sbteclipse-plugin" % "4.0.0")
grammar HAIL;
: topLevelDef*
: fixedAlloc
| hybridAlloc
| memInit
: '.new' nam=HAIL_NAME '<' ty=type '>'
: '.newhybrid' nam=HAIL_NAME '<' ty=type '>' len=intExpr
: '.init' lv=lValue '=' rv=rValue
: nam=name (indices+=index)*
| intLiteral # RVInt
| floatLiteral # RVFloat
| doubleLiteral # RVDouble
| 'NULL' # RVNull
| '&' lValue # RVIRefOf
| '*' lValue # RVValueOf
| list # RVList
: '{' rv+=rValue* '}'
: '[' intExpr ']'
: intLiteral # IntLit
| GLOBAL_NAME # IntGlobal
: FP_NUM 'f' # FloatNumber
| INF 'f' # FloatInf
| NAN 'f' # FloatNan
| 'bitsf' '(' intLiteral ')' # FloatBits
: FP_NUM 'd' # DoubleNumber
| INF 'd' # DoubleInf
| NAN 'd' # DoubleNan
| 'bitsd' '(' intLiteral ')' # DoubleBits
: ('+'|'-')? DIGIT_NON_ZERO DIGIT*
: ('+'|'-')? '0' OCT_DIGIT*
: ('+'|'-')? '0x' HEX_DIGIT+
: ('+'|'-')? DIGIT+ '.' DIGIT+ ('e' ('+'|'-')? DIGIT+)?
: ('+'|'-') 'inf'
: 'nan'
: [0-9]
: [1-9]
: [0-7]
: [0-9a-fA-F]
: [a-z]
| [A-Z]
| [0-9]
| '-'
| '_'
| '.'
WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines
: '//' ~[\r\n]* -> skip
......@@ -11,7 +11,7 @@ topLevelDef
| globalDef
| funcDecl
| funcDef
| exposeDef
| funcExpDef
......@@ -35,44 +35,43 @@ funcDecl
: '.funcdef' nam=GLOBAL_NAME 'VERSION' ver=GLOBAL_NAME '<' sig=funcSig '>' params=paramList body=funcBody
: '.funcdef' nam=GLOBAL_NAME 'VERSION' ver=name '<' sig=funcSig '>' body=funcBody