Commit beb9d46a authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano

Deleting local changes to tests.

parent 49e961dd
This diff is collapsed.
#[macro_use]
extern crate mu;
#[macro_use]
extern crate utils;
#[macro_use]
extern crate log;
#[macro_use]
extern crate maplit;
#[macro_use]
mod ir_macros;
mod test_ir;
mod test_compiler;
mod test_runtime;
mod test_api;
mod common {
use std::fmt;
#[allow(dead_code)]
pub fn assert_vector_ordered <T: fmt::Debug> (left: &Vec<T>, right: &Vec<T>) {
assert_debug_str(left, right);
}
#[allow(dead_code)]
pub fn assert_vector_no_order <T: Ord + fmt::Debug + Clone> (left: &Vec<T>, right: &Vec<T>) {
let mut left_clone = left.clone();
left_clone.sort();
let mut right_clone = right.clone();
right_clone.sort();
assert_debug_str(left_clone, right_clone);
}
#[allow(dead_code)]
pub fn assert_debug_str<T: fmt::Debug, U: fmt::Debug> (left: T, right: U) {
assert_eq!(format!("{:?}", left), format!("{:?}", right))
}
}
mod test_vm_serialize;
extern crate rustc_serialize;
use test_ir::test_ir::factorial;
use mu::vm::*;
use std::sync::Arc;
use self::rustc_serialize::json;
use self::rustc_serialize::base64::ToBase64;
use self::rustc_serialize::hex::ToHex;
use self::rustc_serialize::base64::STANDARD;
#[test]
fn test_vm_serialize_factorial() {
VM::start_logging_trace();
let vm = Arc::new(factorial());
let serialized_json = json::encode(&vm).unwrap();
println!("JSON(len={}):", serialized_json.len());
println!("{}", serialized_json);
let base64 = serialized_json.as_bytes().to_base64(STANDARD);
println!("base64(len={}):", base64.len());
println!("{}", base64);
let hex = serialized_json.as_bytes().to_hex();
println!("hex(len={}):", hex.len());
println!("{}", hex);
let reconstruct_vm : VM = json::decode(&serialized_json).unwrap();
let serialized_again = json::encode(&reconstruct_vm).unwrap();
println!("JSON for reconstructed VM(len={}):", serialized_again.len());
println!("{}", serialized_again);
// check_string_eq_char_by_char(serialized, serialized_again);
}
#[allow(dead_code)]
fn check_string_eq_char_by_char(str1: String, str2: String) {
use std::cmp;
let min_len = cmp::min(str1.len(), str2.len());
println!("str1_len = {}, str2_len = {}", str1.len(), str2.len());
let b1 = str1.into_bytes();
let b2 = str2.into_bytes();
for i in 0..min_len {
if b1[i] != b2[i] {
println!("different here ({}):", i);
print!("str1: ..");
for j in 0..20 {
print!("{}", b1[i + j] as char);
}
println!("..");
print!("str2: ..");
for j in 0..20 {
print!("{}", b2[i + j] as char);
}
println!("..");
panic!("found difference in two strings");
}
}
}
mod test_pre_instsel;
mod test_instsel;
mod test_regalloc;
mod test_global;
mod test_compiler;
mod test_alloc;
mod test_exception;
mod test_thread;
mod test_floatingpoint;
mod test_int;
mod test_binop;
mod test_controlflow;
mod test_call;
mod test_mem_inst;
mod test_inline;
mod test_convop;
\ No newline at end of file
extern crate log;
extern crate libloading;
extern crate mu;
use self::mu::ast::types::*;
use self::mu::ast::ir::*;
use self::mu::ast::inst::*;
use self::mu::vm::*;
use self::mu::compiler::*;
use self::mu::runtime::thread::MuThread;
use self::mu::utils::Address;
use self::mu::utils::LinkedHashMap;
use std::sync::Arc;
use std::sync::RwLock;
use self::mu::testutil;
use self::mu::testutil::aot;
#[test]
fn test_allocation_fastpath() {
VM::start_logging_trace();
let vm = Arc::new(allocation_fastpath());
let compiler = Compiler::new(CompilerPolicy::default(), &vm);
let func_id = vm.id_of("allocation_fastpath");
{
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&func_id).unwrap().read().unwrap();
let func_vers = vm.func_vers().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
vm.make_primordial_thread(func_id, true, vec![]);
backend::emit_context(&vm);
let executable = aot::link_primordial(vec!["allocation_fastpath".to_string()], "allocation_fastpath_test", &vm);
aot::execute(executable);
}
fn allocation_fastpath() -> VM {
let vm = VM::new();
typedef! ((vm) int1 = mu_int(1));
typedef! ((vm) int64 = mu_int(64));
typedef! ((vm) ref_int64 = mu_ref(int64));
typedef! ((vm) struct_t = mu_struct(int64, int64, ref_int64));
typedef! ((vm) ref_struct_t = mu_ref(struct_t));
funcsig! ((vm) sig = () -> ());
funcdecl! ((vm) <sig> allocation_fastpath);
funcdef! ((vm) <sig> allocation_fastpath VERSION allocation_fastpath_v1);
block! ((vm, allocation_fastpath_v1) blk_entry);
// a = NEW <struct_t>
ssa! ((vm, allocation_fastpath_v1) <ref_struct_t> a);
inst! ((vm, allocation_fastpath_v1) blk_entry_new1:
a = NEW <struct_t>
);
inst! ((vm, allocation_fastpath_v1) blk_entry_print1:
PRINTHEX a
);
ssa! ((vm, allocation_fastpath_v1) <ref_struct_t> b);
inst! ((vm, allocation_fastpath_v1) blk_entry_new2:
b = NEW <struct_t>
);
inst! ((vm, allocation_fastpath_v1) blk_entry_print2:
PRINTHEX b
);
inst! ((vm, allocation_fastpath_v1) blk_entry_threadexit:
THREADEXIT
);
define_block! ((vm, allocation_fastpath_v1) blk_entry() {
blk_entry_new1, blk_entry_print1,
blk_entry_new2, blk_entry_print2,
blk_entry_threadexit
});
define_func_ver!((vm) allocation_fastpath_v1 (entry: blk_entry) {blk_entry});
vm
}
#[test]
fn test_instruction_new() {
VM::start_logging_trace();
let vm = Arc::new(alloc_new());
let compiler = Compiler::new(CompilerPolicy::default(), &vm);
let func_id = vm.id_of("alloc_new");
{
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&func_id).unwrap().read().unwrap();
let func_vers = vm.func_vers().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
vm.make_primordial_thread(func_id, true, vec![]);
backend::emit_context(&vm);
let executable = aot::link_primordial(vec!["alloc_new".to_string()], "alloc_new_test", &vm);
aot::execute(executable);
}
#[allow(dead_code)]
//#[test]
// The test won't work, since the generated dylib wants to use 'alloc_slow'.
// but in current process, there is no 'alloc_slow' (rust mangles it)
// The solution would be starting mu vm with libmu.so, then create IR from there.
// test_jit should contains a test for it. So I do not test it here
fn test_instruction_new_on_cur_thread() {
VM::start_logging_trace();
// compile
let vm = Arc::new(alloc_new());
let compiler = Compiler::new(CompilerPolicy::default(), &vm);
let func_id = vm.id_of("alloc_new");
{
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&func_id).unwrap().read().unwrap();
let func_vers = vm.func_vers().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
backend::emit_context(&vm);
// link
let libname = &testutil::get_dylib_name("alloc_new_on_cur_thread");
let dylib = aot::link_dylib(vec![Mu("alloc_new")], libname, &vm);
let lib = libloading::Library::new(dylib.as_os_str()).unwrap();
unsafe {
MuThread::current_thread_as_mu_thread(Address::zero(), vm.clone());
let func : libloading::Symbol<unsafe extern fn() -> ()> = lib.get(b"alloc_new").unwrap();
func();
}
}
#[allow(unused_variables)]
pub fn alloc_new() -> VM {
let vm = VM::new();
// .typedef @int64 = int<64>
// .typedef @iref_int64 = iref<int<64>>
let type_def_int64 = vm.declare_type(vm.next_id(), MuType_::int(64));
vm.set_name(type_def_int64.as_entity(), "int64".to_string());
let type_def_iref_int64 = vm.declare_type(vm.next_id(), MuType_::iref(type_def_int64.clone()));
vm.set_name(type_def_iref_int64.as_entity(), "iref_int64".to_string());
let type_def_ref_int64 = vm.declare_type(vm.next_id(), MuType_::muref(type_def_int64.clone()));
vm.set_name(type_def_ref_int64.as_entity(), "ref_int64".to_string());
// .const @int_64_0 <@int_64> = 0
// .const @int_64_1 <@int_64> = 1
let const_def_int64_0 = vm.declare_const(vm.next_id(), type_def_int64.clone(), Constant::Int(0));
vm.set_name(const_def_int64_0.as_entity(), "int64_0".to_string());
let const_def_int64_1 = vm.declare_const(vm.next_id(), type_def_int64.clone(), Constant::Int(1));
vm.set_name(const_def_int64_1.as_entity(), "int64_1".to_string());
// .funcsig @alloc_new_sig = () -> (@int64)
let func_sig = vm.declare_func_sig(vm.next_id(), vec![type_def_int64.clone()], vec![]);
vm.set_name(func_sig.as_entity(), "alloc_new_sig".to_string());
// .funcdecl @alloc_new <@alloc_new_sig>
let func = MuFunction::new(vm.next_id(), func_sig.clone());
vm.set_name(func.as_entity(), "alloc_new".to_string());
let func_id = func.id();
vm.declare_func(func);
// .funcdef @alloc VERSION @v1 <@alloc_new_sig>
let mut func_ver = MuFunctionVersion::new(vm.next_id(), func_id, func_sig.clone());
// %blk_0():
let mut blk_0 = Block::new(vm.next_id());
vm.set_name(blk_0.as_entity(), "blk_0".to_string());
// %a = NEW <@int64_t>
let blk_0_a = func_ver.new_ssa(vm.next_id(), type_def_ref_int64.clone());
vm.set_name(blk_0_a.as_entity(), "blk_0_a".to_string());
let blk_0_inst0 = func_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![blk_0_a.clone_value()]),
ops: RwLock::new(vec![]),
v: Instruction_::New(type_def_int64.clone())
});
// %a_iref = GETIREF <@int_64> @a
let blk_0_a_iref = func_ver.new_ssa(vm.next_id(), type_def_iref_int64.clone());
vm.set_name(blk_0_a.as_entity(), "blk_0_a_iref".to_string());
let blk_0_inst1 = func_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: Some(vec![blk_0_a_iref.clone_value()]),
ops: RwLock::new(vec![blk_0_a.clone()]),
v: Instruction_::GetIRef(0)
});
// STORE <@int_64> @a_iref @int_64_1
let blk_0_const_int64_1 = func_ver.new_constant(const_def_int64_1.clone());
let blk_0_inst2 = func_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![blk_0_a_iref.clone(), blk_0_const_int64_1.clone()]),
v: Instruction_::Store{
is_ptr: false,
order: MemoryOrder::Relaxed,
mem_loc: 0,
value: 1
}
});
// // %x = LOAD <@int_64> @a_iref
// let blk_0_x = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
// vm.set_name(blk_0_x.as_entity(), "blk_0_x".to_string());
// let blk_0_inst3 = func_ver.new_inst(vm.next_id(), Instruction{
// value: Some(vec![blk_0_x.clone_value()]),
// ops: RwLock::new(vec![blk_0_a_iref.clone()]),
// v: Instruction_::Load{
// is_ptr: false,
// order: MemoryOrder::Relaxed,
// mem_loc: 0
// }
// });
let blk_0_term = func_ver.new_inst(Instruction {
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![]),
v: Instruction_::ThreadExit
});
let blk_0_content = BlockContent {
args: vec![],
exn_arg: None,
body: vec![blk_0_inst0, blk_0_inst1, blk_0_inst2, blk_0_term],
keepalives: None
};
blk_0.content = Some(blk_0_content);
func_ver.define(FunctionContent::new(
blk_0.id(),
{
let mut ret = LinkedHashMap::new();
ret.insert(blk_0.id(), blk_0);
ret
}
));
vm.define_func_version(func_ver);
vm
}
This diff is collapsed.
This diff is collapsed.
extern crate libloading as ll;
extern crate mu;
use test_ir::test_ir::sum;
use test_ir::test_ir::factorial;
use mu::testutil;
#[test]
fn test_factorial() {
let lib = testutil::compile_fnc("fac", &factorial);
unsafe {
let fac: ll::Symbol<unsafe extern fn (u64) -> u64> = lib.get(b"fac").unwrap();
println!("fac(10) = {}", fac(10));
assert!(fac(10) == 3628800);
}
}
#[test]
fn test_sum() {
let lib = testutil::compile_fnc("sum", &sum);
unsafe {
let sumptr: ll::Symbol<unsafe extern fn (u64) -> u64> = lib.get(b"sum").unwrap();
println!("sum(5) = {}", sumptr(5));
assert!(sumptr(5) == 15);
println!("sun(10) = {}", sumptr(10));
assert!(sumptr(10) == 55);
}
}
This diff is collapsed.
extern crate mu;
extern crate log;
extern crate libloading;
use self::mu::ast::types::*;
use self::mu::ast::ir::*;
use self::mu::ast::inst::*;
use self::mu::ast::op::*;
use self::mu::vm::*;
use self::mu::testutil;
use mu::utils::LinkedHashMap;
use std::sync::RwLock;
#[test]
fn test_truncate_then_call() {
let lib = testutil::compile_fncs("truncate_then_call", vec!["truncate_then_call", "dummy_call"], &truncate_then_call);
unsafe {
let truncate_then_call : libloading::Symbol<unsafe extern fn(u64) -> u32> = lib.get(b"truncate_then_call").unwrap();
let res = truncate_then_call(1);
println!("truncate_then_call(1) = {}", res);
assert!(res == 1);
}
}
fn truncate_then_call() -> VM {
let vm = VM::new_with_opts("init_mu --disable-inline");
typedef! ((vm) u64 = mu_int(64));
typedef! ((vm) u32 = mu_int(32));
funcsig! ((vm) dummy_call_sig = (u32) -> (u32));
funcdecl!((vm) <dummy_call_sig> dummy_call);
{
// --- dummy call ---
funcdef! ((vm) <dummy_call_sig> dummy_call VERSION dummy_call_v1);
// entry
block! ((vm, dummy_call_v1) blk_entry);
ssa! ((vm, dummy_call_v1) <u32> x);
inst! ((vm, dummy_call_v1) ret:
RET (x)
);
define_block!((vm, dummy_call_v1) blk_entry(x) {
ret
});
define_func_ver!((vm) dummy_call_v1 (entry: blk_entry) {
blk_entry
});
}
{
// --- truncate_then_call ---
typedef! ((vm) funcref_to_dummy = mu_funcref(dummy_call_sig));
constdef!((vm) <funcref_to_dummy> funcref_dummy = Constant::FuncRef(dummy_call));
funcsig! ((vm) sig = (u64) -> (u32));
funcdecl!((vm) <sig> truncate_then_call);
funcdef! ((vm) <sig> truncate_then_call VERSION truncate_then_call_v1);
// entry
block!((vm, truncate_then_call_v1) blk_entry);
ssa! ((vm, truncate_then_call_v1) <u64> arg);
// %arg_u32 = TRUNC <u64 u32> arg
ssa! ((vm, truncate_then_call_v1) <u32> arg_u32);
inst!((vm, truncate_then_call_v1) blk_entry_truncate:
arg_u32 = CONVOP (ConvOp::TRUNC) <u64 u32> arg
);
// %ret = CALL dummy_call (arg_u32)
ssa! ((vm, truncate_then_call_v1) <u32> res);
consta! ((vm, truncate_then_call_v1) funcref_dummy_local = funcref_dummy);
inst! ((vm, truncate_then_call_v1) blk_entry_call:
res = EXPRCALL (CallConvention::Mu, is_abort: false) funcref_dummy_local (arg_u32)
);
inst!((vm, truncate_then_call_v1) blk_entry_ret:
RET (arg)
);
define_block!((vm, truncate_then_call_v1) blk_entry(arg) {
blk_entry_truncate,
blk_entry_call,
blk_entry_ret
});
define_func_ver!((vm) truncate_then_call_v1 (entry: blk_entry) {
blk_entry
});
}
vm
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
extern crate libloading;
use mu::ast::types::*;
use mu::ast::ir::*;
use mu::ast::inst::*;
use mu::ast::op::*;
use mu::vm::*;
use mu::testutil;
use mu::utils::LinkedHashMap;
use std::sync::RwLock;
#[test]
fn test_inline_add_simple() {
let lib = testutil::compile_fncs("add_trampoline", vec!["add_trampoline", "add"], &inline_add);
unsafe {
let inline_add : libloading::Symbol<unsafe extern fn(u64, u64) -> u64> = lib.get(b"add_trampoline").unwrap();
let inline_add_1_1 = inline_add(1, 1);
println!("add(1, 1) = {}", inline_add_1_1);
assert!(inline_add_1_1 == 2);
}
}
fn inline_add() -> VM {
let vm = VM::new();
typedef! ((vm) int64 = mu_int(64));
funcsig! ((vm) sig = (int64, int64) -> (int64));
funcdecl! ((vm) <sig> add);
{
// add
funcdef! ((vm) <sig> add VERSION add_v1);
block! ((vm, add_v1) blk_entry);
ssa! ((vm, add_v1) <int64> x);
ssa! ((vm, add_v1) <int64> y);
ssa! ((vm, add_v1) <int64> res);
inst! ((vm, add_v1) blk_entry_add:
res = BINOP (BinOp::Add) x y
);
inst! ((vm, add_v1) blk_entry_ret:
RET (res)
);
define_block! ((vm, add_v1) blk_entry(x, y) {blk_entry_add, blk_entry_ret});
define_func_ver!((vm) add_v1 (entry: blk_entry) {blk_entry});
}
{
// add_trampoline
typedef! ((vm) funcref_to_sig = mu_funcref(sig));
constdef! ((vm) <funcref_to_sig> funcref_add = Constant::FuncRef(add));
funcdecl! ((vm) <sig> add_trampoline);
funcdef! ((vm) <sig> add_trampoline VERSION add_trampoline_v1);
block! ((vm, add_trampoline_v1) tramp_blk_entry);
ssa! ((vm, add_trampoline_v1) <int64> tramp_x);
ssa! ((vm, add_trampoline_v1) <int64> tramp_y);
consta! ((vm, add_trampoline_v1) funcref_add_local = funcref_add);
ssa! ((vm, add_trampoline_v1) <int64> tramp_res);
inst! ((vm, add_trampoline_v1) tramp_blk_call:
tramp_res = EXPRCALL (CallConvention::Mu, is_abort: false) funcref_add_local (tramp_x, tramp_y)
);
inst! ((vm, add_trampoline_v1) tramp_blk_ret:
RET (tramp_res)
);
define_block! ((vm, add_trampoline_v1) tramp_blk_entry(tramp_x, tramp_y) {tramp_blk_call, tramp_blk_ret});
define_func_ver!((vm) add_trampoline_v1 (entry: tramp_blk_entry) {tramp_blk_entry});
}
vm
}
#[test]
fn test_inline_add_twice() {
let lib = testutil::compile_fncs("add_twice", vec!["add_twice", "add"], &inline_add_twice);
unsafe {
let add_twice : libloading::Symbol<unsafe extern fn(u64, u64, u64) -> u64> = lib.get(b"add_twice").unwrap();
let res = add_twice(1, 1, 1);
println!("add(1, 1, 1) = {}", res);
assert!(res == 3);
}
}
fn inline_add_twice() -> VM {
let vm = VM::new();
typedef! ((vm) int64 = mu_int(64));
funcsig! ((vm) sig = (int64, int64) -> (int64));
funcdecl! ((vm) <sig> add);
{
// add
funcdef! ((vm) <sig> add VERSION add_v1);
block! ((vm, add_v1) blk_entry);
ssa! ((vm, add_v1) <int64> x);
ssa! ((vm, add_v1) <int64> y);
ssa! ((vm, add_v1) <int64> res);
inst! ((vm, add_v1) blk_entry_add:
res = BINOP (BinOp::Add) x y
);
inst! ((vm, add_v1) blk_entry_ret:
RET (res)
);