To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.7% of users enabled 2FA.

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

Merge branch 'master' of 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]( It
implements the [Mu Specification version
machine designed by [The Micro Virtual Machine Project](
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]( is the
previous reference implementation.
......@@ -21,7 +23,7 @@ How to compile
`brew install scala`.
* Install [sbt]( 0.13. If you use Mac and Homebrew,
`brew install sbt`.
* Install [Scala IDE]( 4.0 (Eclipse with pre-installed
* Install [Scala IDE]( 4.x (Eclipse with pre-installed
plugins for Scala).
* Clone this repository:
......@@ -32,9 +34,7 @@ git clone
* 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]( 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) { }
licenses := Seq("CC BY-SA 4.0" -> url(""))
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("")
licenses := Seq("CC BY-SA 4.0" -> url("")),
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(""),
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
: '.expose' nam=GLOBAL_NAME '=' funcName=GLOBAL_NAME callConv=flag cookie=GLOBAL_NAME