Commit 342e5511 authored by Kunshan Wang's avatar Kunshan Wang

More tests.

- Tested load_bundle, composite types and memory ops.
- Fixed a bug in insertelement.
parent ff2c290e
......@@ -14,6 +14,8 @@ import uvm.ssavariables.Flag
import uvm.refimpl.itpr.{ HowToResume => ItprHowToResume }
import scala.collection.mutable.Buffer
import java.nio.charset.Charset
import org.slf4j.LoggerFactory
import com.typesafe.scalalogging.Logger
object MuValue {
def apply(ty: Type, vb: ValueBox): MuValue = (ty, vb) match {
......@@ -95,6 +97,8 @@ trait UndefinedFunctionHandler {
}
object MuCtx {
val logger = Logger(LoggerFactory.getLogger(getClass.getName))
val US_ASCII = Charset.forName("US-ASCII")
}
......@@ -104,6 +108,7 @@ object MuCtx {
*/
class MuCtx(_mutator: Mutator)(
implicit microVM: MicroVM, memorySupport: MemorySupport) extends ObjectPinner {
import MuCtx._
implicit def mutator = _mutator
......@@ -310,7 +315,7 @@ class MuCtx(_mutator: Mutator)(
val st = seq.ty
val sb = seq.vb
val nsb = BoxSeq(for ((b, i) <- sb.values.zipWithIndex) yield if (i == index) newval.vb else b)
val nsb = BoxSeq(for ((b, i) <- sb.values.zipWithIndex) yield if (i == indexVal) newval.vb else b)
addHandle(MuValue(st, nsb).asInstanceOf[T])
}
......
......@@ -191,11 +191,13 @@ object NativeMuCtx {
def load_bundle(ctx: MuCtx, buf: CharArrayPtr, sz: Int): Unit = {
val str = theMemory.getString(buf, sz, StandardCharsets.US_ASCII)
logger.trace("Loading bundle:\n%s".format(str))
ctx.loadBundle(str)
}
def load_hail(ctx: MuCtx, buf: CharArrayPtr, sz: Int): Unit = {
val str = theMemory.getString(buf, sz, StandardCharsets.US_ASCII)
logger.trace("Loading hail:\n%s".format(str))
ctx.loadHail(str)
}
......@@ -244,13 +246,13 @@ object NativeMuCtx {
def extract_value(ctx: MuCtx, str: MuStructValue, index: Int): MuValueFak = exposeMuValue(ctx, ctx.extractValue(str, index))
def insert_value(ctx: MuCtx, str: MuStructValue, index: Int, newval: MuValue): MuValueFak = exposeMuValue(ctx, ctx.insertValue(str, index, newval))
def extract_element[T <: MuSeqValue](ctx: MuCtx, str: T, index: MuIntValue): MuValueFak = exposeMuValue(ctx, ctx.extractElement(str, index))
def insert_element[T <: MuSeqValue](ctx: MuCtx, str: T, index: MuIntValue, newval: MuValue): MuValueFak = exposeMuValue(ctx, ctx.insertElement(str, index, newval))
def extract_element(ctx: MuCtx, str: MuSeqValue, index: MuIntValue): MuValueFak = exposeMuValue(ctx, ctx.extractElement(str, index))
def insert_element(ctx: MuCtx, str: MuSeqValue, index: MuIntValue, newval: MuValue): MuValueFak = exposeMuValue(ctx, ctx.insertElement(str, index, newval))
def new_fixed(ctx: MuCtx, mu_type: MuID): MuValueFak = exposeMuValue(ctx, ctx.newFixed(mu_type))
def new_hybrid(ctx: MuCtx, mu_type: MuID, length: MuIntValue): MuValueFak = exposeMuValue(ctx, ctx.newHybrid(mu_type, length))
def refcast[T <: MuGenRefValue](ctx: MuCtx, opnd: T, new_type: MuID): MuValueFak = exposeMuValue(ctx, ctx.refcast(opnd, new_type))
def refcast(ctx: MuCtx, opnd: MuGenRefValue, new_type: MuID): MuValueFak = exposeMuValue(ctx, ctx.refcast(opnd, new_type))
def get_iref(ctx: MuCtx, opnd: MuRefValue): MuValueFak = exposeMuValue(ctx, ctx.getIRef(opnd))
def get_field_iref(ctx: MuCtx, opnd: MuIRefValue, field: Int): MuValueFak = exposeMuValue(ctx, ctx.getFieldIRef(opnd, field))
......@@ -416,6 +418,9 @@ object NativeMuHelpers {
object ClientAccessibleClassExposer {
// Reflection utils.
val mirror = ru.runtimeMirror(getClass.getClassLoader)
val MAX_NAME_SIZE = 65536
// Type objects for common types.
......@@ -442,7 +447,14 @@ object ClientAccessibleClassExposer {
def paramString(index: Int)(buffer: Buffer): Any = getStr(buffer, index)
def paramMicroVM(index: Int)(buffer: Buffer): Any = getObjFromFuncTableAddr(buffer, index, NativeClientSupport.microVMs)
def paramMuCtx(index: Int)(buffer: Buffer): Any = getObjFromFuncTableAddr(buffer, index, NativeClientSupport.muCtxs)
def paramMuValue(index: Int)(buffer: Buffer): Any = getMuValue(buffer, index)
def paramMuValue(index: Int, funcName: String, tpe: ru.Type)(buffer: Buffer): Any = {
val muValue = getMuValue(buffer, index)
val t = mirror.classSymbol(muValue.getClass).toType
require(t <:< tpe, "Argument %d of %s expect %s, found %s".format(index, funcName, tpe, t))
muValue
}
def retVoid(buffer: Buffer, v: Any): Unit = {}
def retByte(buffer: Buffer, v: Any): Unit = buffer.setByteReturn(v.asInstanceOf[Byte])
......@@ -480,9 +492,6 @@ object ClientAccessibleClassExposer {
NativeClientSupport.getObjFromFuncTableAddrNotNull(funcTableAddr, orm)
}
// Reflection utils.
val mirror = ru.runtimeMirror(getClass.getClassLoader)
// Convert to JFFI native types.
def toJFFIType(t: ru.Type): JType = t match {
case t if t =:= TUnit => JType.VOID
......@@ -545,7 +554,7 @@ class ClientAccessibleClassExposer[T: ru.TypeTag: ClassTag](obj: T) {
case t if t =:= TString => paramString(i) _
case t if t =:= TMicroVM => paramMicroVM(i) _
case t if t =:= TMuCtx => paramMuCtx(i) _
case t if t <:< TMuValue => paramMuValue(i) _
case t if t <:< TMuValue => paramMuValue(i, meth.name.toString, t) _
}
val returnSetter = returnType match {
......
......@@ -10,6 +10,7 @@ import NativeSupport._
class NativeClientSupportTest extends UvmBundleTesterBase {
setLogLevels(
ROOT_LOGGER_NAME -> INFO,
//"uvm.refimpl" -> DEBUG,
"uvm.refimpl.nat" -> DEBUG)
preloadBundles("tests/uvm-refimpl-test/primitives.uir",
......@@ -28,6 +29,9 @@ class NativeClientSupportTest extends UvmBundleTesterBase {
def test_basic_conv(mvm: Word): CBool
def test_global_vars(mvm: Word, the_plus_one_fp: Word): CBool
def test_traps(mvm: Word): CBool
def test_load_bundle(mvm: Word): CBool
def test_comp_types(mvm: Word): CBool
def test_memory_ops(mvm: Word): CBool
}
val ncs_tests = LibraryLoader.create(classOf[NcsTestsLib]).load(fileName)
......@@ -83,4 +87,19 @@ class NativeClientSupportTest extends UvmBundleTesterBase {
val result = ncs_tests.test_traps(microVMFuncTableAddr)
assertNativeSuccess(result)
}
it should "load bundles and HAIL" in {
val result = ncs_tests.test_load_bundle(microVMFuncTableAddr)
assertNativeSuccess(result)
}
it should "handle composite values" in {
val result = ncs_tests.test_comp_types(microVMFuncTableAddr)
assertNativeSuccess(result)
}
it should "perform memory operations" in {
val result = ncs_tests.test_memory_ops(microVMFuncTableAddr)
assertNativeSuccess(result)
}
}
\ No newline at end of file
......@@ -339,3 +339,205 @@ bool test_traps(MuVM *mvm) {
return true;
}
void load_bundle_trap_handler(MuCtx *ctx, MuThreadRefValue thread,
MuStackRefValue stack, int wpid, MuTrapHandlerResult *result,
MuStackRefValue *new_stack, MuValue **values, int *nvalues,
MuValuesFreer *freer, MuCPtr *freerdata, MuRefValue *exception,
MuCPtr userdata) {
muprintf("Hi! I am the native trap handler!\n");
MuFCRefValue *cursor = ctx->new_cursor(ctx, stack);
MuID fid = ctx->cur_func(ctx, cursor);
MuID fvid = ctx->cur_func_ver(ctx, cursor);
MuID iid = ctx->cur_inst(ctx, cursor);
MuID trap_id = ID("@made_in_c.v1.entry.trap");
MU_ASSERT_EQUALS_TRAP(fid , ID("@made_in_c"), "d");
MU_ASSERT_EQUALS_TRAP(fvid, ID("@made_in_c.v1"), "d");
MU_ASSERT_EQUALS_TRAP(iid , ID("@made_in_c.v1.entry.trap"), "d");
MuValue kas[1];
ctx->dump_keepalives(ctx, cursor, kas);
ctx->close_cursor(ctx, cursor);
int64_t n = ctx->handle_to_sint64(ctx, kas[0]);
muprintf("KA value %%n is %" PRId64 "\n", n);
MU_ASSERT_EQUALS_TRAP(n, 53LL, PRId64);
MuIRefValue hg_cmagic_iref = ctx->handle_from_global(ctx, ID("@g_cmagic"));
MuIntValue hg_cmagic_value = ctx->load(ctx, MU_NOT_ATOMIC, hg_cmagic_iref);
int64_t g_cmagic = ctx->handle_to_sint64(ctx, hg_cmagic_value);
muprintf("Global value @g_cmagic is %" PRId64 "\n", g_cmagic);
MU_ASSERT_EQUALS_TRAP(g_cmagic, 52LL, PRId64);
muprintf("Prepare to return from trap handler...\n");
*result = MU_REBIND_PASS_VALUES;
*new_stack = stack;
*values = NULL;
*nvalues = 0;
*freer = NULL;
*freerdata = NULL;
muprintf("Bye!\n");
return;
}
bool test_load_bundle(MuVM *mvm) {
mvm->set_trap_handler(mvm, load_bundle_trap_handler, NULL);
MuCtx *ctx = mvm->new_context(mvm);
char ir[] = ".funcdef @made_in_c VERSION %v1 <@i_i> {\n"
" %entry(<@i64> %n):\n"
" [%trap] TRAP <> KEEPALIVE (%n)\n"
" COMMINST @uvm.thread_exit\n"
"}\n"
".global @g_cmagic <@i64>\n"
;
char hail[] = ".init @g_cmagic = 52\n";
muprintf("Loading bundle...\n");
ctx->load_bundle(ctx, ir, strlen(ir));
muprintf("Loading HAIL...\n");
ctx->load_hail(ctx, hail, strlen(hail));
muprintf("All loaded.\n");
MuValue args[1];
args[0] = ctx->handle_from_sint64(ctx, 53LL, 64);
MuFuncRefValue func = ctx->handle_from_func(ctx, ID("@made_in_c"));
MuStackRefValue stack = ctx->new_stack(ctx, func);
MuThreadRefValue thread = ctx->new_thread(ctx, stack, MU_REBIND_PASS_VALUES,
args, 1, NULL);
mvm->execute(mvm);
ctx->close_context(ctx);
return true;
}
bool test_comp_types(MuVM *mvm) {
MuCtx *ctx = mvm->new_context(mvm);
MuStructValue s1 = ctx->handle_from_const(ctx, ID("@S1"));
MuIntValue s10 = ctx->extract_value(ctx, s1, 0);
int64_t s10_v = ctx->handle_to_sint64(ctx, s10);
MU_ASSERT_EQUALS(s10_v, 6LL, PRId64);
MuDoubleValue s11 = ctx->extract_value(ctx, s1, 1);
double s11_v = ctx->handle_to_double(ctx, s11);
MU_ASSERT_EQUALS(s11_v, 7.0, "lf");
MuIntValue I64_20 = ctx->handle_from_const(ctx, ID("@I64_20"));
MuStructValue s1m = ctx->insert_value(ctx, s1, 0, I64_20);
MuIntValue s10m = ctx->extract_value(ctx, s1m, 0);
int64_t s10m_v = ctx->handle_to_sint64(ctx, s10m);
MU_ASSERT_EQUALS(s10m_v, 20LL, PRId64);
MuArrayValue a1 = ctx->handle_from_const(ctx, ID("@A1"));
MuID i32 = ID("@i32");
for (int i=0; i<3; i++) {
MuIntValue hi = ctx->handle_from_sint32(ctx, i, 32);
MuIntValue a1i = ctx->extract_element(ctx, a1, hi);
int32_t a1i_v = ctx->handle_to_sint32(ctx, a1i);
MU_ASSERT_EQUALS(a1i_v, i+2, PRId32);
ctx->delete_value(ctx, hi);
ctx->delete_value(ctx, a1i);
}
MuIntValue I32_2 = ctx->handle_from_const(ctx, ID("@I32_2"));
MuIntValue I32_30 = ctx->handle_from_const(ctx, ID("@I32_30"));
MuArrayValue a1m = ctx->insert_element (ctx, a1, I32_2, I32_30);
MuIntValue a1m2 = ctx->extract_element(ctx, a1m, I32_2);
int32_t a1m2v = ctx->handle_to_sint32(ctx, a1m2);
MU_ASSERT_EQUALS(a1m2v, 30, PRId32);
ctx->close_context(ctx);
return true;
}
bool test_memory_ops(MuVM *mvm) {
MuCtx *ctx = mvm->new_context(mvm);
MuRefValue r1 = ctx->new_fixed(ctx, ID("@i64"));
MuRefValue r2 = ctx->new_fixed(ctx, ID("@i64"));
MuIntValue I64_3 = ctx->handle_from_const(ctx, ID("@I64_3"));
MuIntValue I64_4 = ctx->handle_from_const(ctx, ID("@I64_4"));
MuIntValue I64_10 = ctx->handle_from_const(ctx, ID("@I64_10"));
MuRefValue rh1 = ctx->new_hybrid(ctx, ID("@hyb"), I64_10);
MuRefValue rh2 = ctx->new_hybrid(ctx, ID("@hyb"), I64_10);
int r1r1 = ctx->ref_eq(ctx, r1, r1);
int r1r2 = ctx->ref_eq(ctx, r1, r2);
MU_ASSERT_EQUALS(r1r1, 1, "d");
MU_ASSERT_EQUALS(r1r2, 0, "d");
MuIRefValue rh1i = ctx->get_iref(ctx, rh1);
MuIRefValue rh1f = ctx->get_field_iref(ctx, rh1i, 0);
MuIRefValue rh1v = ctx->get_var_part_iref(ctx, rh1i);
MuIRefValue rh1v3 = ctx->shift_iref(ctx, rh1v, I64_3);
MuIRefValue rh1v4 = ctx->shift_iref(ctx, rh1v, I64_4);
int rh33 = ctx->ref_ult(ctx, rh1v3, rh1v3);
int rh34 = ctx->ref_ult(ctx, rh1v3, rh1v4);
MU_ASSERT_EQUALS(rh33, 0, "d");
MU_ASSERT_EQUALS(rh34, 1, "d");
MuRefValue r3 = ctx->new_fixed(ctx, ID("@a1"));
MuIRefValue r3i = ctx->get_iref(ctx, r3);
MuIRefValue r3i3 = ctx->get_elem_iref(ctx, r3i, I64_3);
MuRefValue r1i = ctx->get_iref(ctx, r1);
ctx->store(ctx, MU_SEQ_CST, r1i, I64_10);
MuIntValue l = ctx->load(ctx, MU_SEQ_CST, r1i);
int64_t lv = ctx->handle_to_sint64(ctx, l);
MU_ASSERT_EQUALS(lv, 10LL, PRId64);
int succ1;
int succ2;
MuIntValue res1 = ctx->cmpxchg(ctx, MU_SEQ_CST, MU_SEQ_CST, 0,
r1i, I64_10, I64_4, &succ1);
MuIntValue res2 = ctx->cmpxchg(ctx, MU_SEQ_CST, MU_SEQ_CST, 0,
r1i, I64_10, I64_3, &succ2);
MU_ASSERT_EQUALS(succ1, 1, "d");
MU_ASSERT_EQUALS(succ2, 0, "d");
int64_t res1v = ctx->handle_to_sint64(ctx, res1);
int64_t res2v = ctx->handle_to_sint64(ctx, res2);
MU_ASSERT_EQUALS(res1v, 10LL, PRId64);
MU_ASSERT_EQUALS(res2v, 4LL , PRId64);
MuIntValue res3 = ctx->atomicrmw(ctx, MU_SEQ_CST, MU_ADD, r1i, I64_10);
MuIntValue res4 = ctx->load(ctx, MU_SEQ_CST, r1i);
int64_t res3v = ctx->handle_to_sint64(ctx, res3);
int64_t res4v = ctx->handle_to_sint64(ctx, res4);
MU_ASSERT_EQUALS(res3v, 4LL , PRId64);
MU_ASSERT_EQUALS(res4v, 14LL, PRId64);
ctx->fence(ctx, MU_SEQ_CST);
ctx->close_context(ctx);
return true;
}
......@@ -16,3 +16,11 @@
[%trap2] TRAP <> KEEPALIVE (%v1)
COMMINST @uvm.thread_exit
}
.typedef @s1 = struct <@i64 @double>
.const @S1 <@s1> = {@I64_6 @D_7}
.typedef @a1 = array <@i32 3>
.const @A1 <@a1> = {@I32_2 @I32_3 @I32_4}
.typedef @hyb = hybrid <@i64 @i8>
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