GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

Commit e408366b authored by qinsoon's avatar qinsoon

[wip] added a test for simple throw-catch

going to implement exception
parent a451bb23
......@@ -194,7 +194,7 @@ pub enum Instruction_ {
// terminal instruction
Return(Vec<OpIndex>),
ThreadExit, // TODO: common inst
Throw(Vec<OpIndex>),
Throw(OpIndex),
TailCall(CallData),
Branch1(Destination),
Branch2{
......@@ -298,7 +298,7 @@ impl Instruction_ {
&Instruction_::Return(ref vals) => format!("RET {}", op_vector_str(vals, ops)),
&Instruction_::ThreadExit => "THREADEXIT".to_string(),
&Instruction_::Throw(ref vals) => format!("THROW {}", op_vector_str(vals, ops)),
&Instruction_::Throw(ref val) => format!("THROW {}", val),
&Instruction_::TailCall(ref call) => format!("TAILCALL {}", call.debug_str(ops)),
&Instruction_::Branch1(ref dest) => format!("BRANCH {}", dest.debug_str(ops)),
&Instruction_::Branch2{cond, ref true_dest, ref false_dest, ..} => {
......
......@@ -305,6 +305,7 @@ pub enum EdgeKind {
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct BlockContent {
pub args: Vec<P<Value>>,
pub exn_arg: Option<P<Value>>,
pub body: Vec<Box<TreeNode>>,
pub keepalives: Option<Vec<P<Value>>>
}
......
......@@ -344,6 +344,14 @@ impl <'a> VM {
ret
}
pub fn get_const(&self, id: MuID) -> P<Value> {
let const_lock = self.constants.read().unwrap();
match const_lock.get(&id) {
Some(ret) => ret.clone(),
None => panic!("cannot find const #{}", id)
}
}
pub fn declare_global(&self, id: MuID, ty: P<MuType>) -> P<Value> {
let global = P(Value{
hdr: MuEntityHeader::unnamed(id),
......@@ -368,6 +376,14 @@ impl <'a> VM {
ty
}
pub fn get_type(&self, id: MuID) -> P<MuType> {
let type_lock = self.types.read().unwrap();
match type_lock.get(&id) {
Some(ret) => ret.clone(),
None => panic!("cannot find type #{}", id)
}
}
pub fn declare_func_sig(&self, id: MuID, ret_tys: Vec<P<MuType>>, arg_tys: Vec<P<MuType>>) -> P<MuFuncSig> {
let mut func_sigs = self.func_sigs.write().unwrap();
debug_assert!(!func_sigs.contains_key(&id));
......@@ -378,6 +394,14 @@ impl <'a> VM {
ret
}
pub fn get_func_sig(&self, id: MuID) -> P<MuFuncSig> {
let func_sig_lock = self.func_sigs.read().unwrap();
match func_sig_lock.get(&id) {
Some(ret) => ret.clone(),
None => panic!("cannot find func sig #{}", id)
}
}
pub fn declare_func (&self, func: MuFunction) {
info!("declare function {}", func);
let mut funcs = self.funcs.write().unwrap();
......
......@@ -3,4 +3,6 @@ mod test_instsel;
mod test_regalloc;
mod test_global;
mod test_compiler;
mod test_alloc;
\ No newline at end of file
mod test_alloc;
mod test_exception;
mod test_thread;
\ No newline at end of file
......@@ -146,6 +146,7 @@ pub fn alloc_new() -> VM {
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
};
......
extern crate log;
extern crate simple_logger;
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;
use self::mu::runtime::thread::MuThread;
use self::mu::runtime::mm;
use self::mu::utils::ByteSize;
use aot;
use std::sync::Arc;
use std::sync::RwLock;
use std::collections::HashMap;
#[test]
fn test_exception_simple_throw_catch() {
simple_logger::init_with_level(log::LogLevel::Trace).ok();
let vm = Arc::new(simple_throw_catch());
let compiler = Compiler::new(CompilerPolicy::default(), vm.clone());
let func_throw = vm.id_of("throw_exception");
let func_catch = vm.id_of("catch_exception");
{
let funcs = vm.funcs().read().unwrap();
let func_vers = vm.func_vers().read().unwrap();
{
let func = funcs.get(&func_throw).unwrap().read().unwrap();
let mut func_ver = func_vers.get(&func.cur_ver.unwrap()).unwrap().write().unwrap();
compiler.compile(&mut func_ver);
}
{
let func = funcs.get(&func_catch).unwrap().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_catch, vec![]);
backend::emit_context(&vm);
let executable = aot::link_primordial(vec![Mu("throw_exception"), Mu("catch_exception")], "simple_throw_catch_test");
aot::execute(executable);
}
fn simple_throw_catch() -> VM {
let vm = VM::new();
// .typedef @int64 = int<64>
// .typedef @ref_int64 = ref<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_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());
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());
// .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());
create_throw_exception_func(&vm);
create_catch_exception_func(&vm);
vm
}
fn create_catch_exception_func (vm: &VM) {
// .typedef @funcref_throw_exception <@throw_exception_sig>
let throw_exception_sig = vm.get_func_sig(vm.id_of("throw_exception_sig"));
let throw_exception_id = vm.id_of("throw_exception");
let type_funcref_throw_exception = vm.declare_type(vm.next_id(), MuType_::funcref(throw_exception_sig));
// .const @throw_exception_func
let const_funcref_throw_exception = vm.declare_const(vm.next_id(), type_funcref_throw_exception, Constant::FuncRef(throw_exception_id));
// .funcsig @catch_exception_sig = () -> ()
let func_sig = vm.declare_func_sig(vm.next_id(), vec![], vec![]);
vm.set_name(func_sig.as_entity(), Mu("catch_exception_sig"));
// .funcdecl @catch_exception <@catch_exception_sig>
let func = MuFunction::new(vm.next_id(), func_sig.clone());
vm.set_name(func.as_entity(), Mu("catch_exception"));
let func_id = func.id();
vm.declare_func(func);
// .funcdef @catch_exception VERSION @v1 <@catch_exception_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(), Mu("blk_0"));
let blk_normal_cont_id = vm.next_id();
let blk_exn_cont_id = vm.next_id();
let blk_0_throw = func_ver.new_constant(vm.next_id(), const_funcref_throw_exception.clone());
let blk_0_term = func_ver.new_inst(vm.next_id(), Instruction {
value: None,
ops: RwLock::new(vec![blk_0_throw]),
v: Instruction_::Call {
data: CallData {
func: 0,
args: vec![],
convention: CallConvention::Mu
},
resume: ResumptionData {
normal_dest: Destination {
target: blk_normal_cont_id,
args: vec![]
},
exn_dest: Destination {
target: blk_exn_cont_id,
args: vec![]
}
}
}
});
let blk_0_content = BlockContent {
args: vec![],
exn_arg: None,
body: vec![blk_0_term],
keepalives: None
};
blk_0.content = Some(blk_0_content);
// %blk_normal_cont():
let mut blk_normal_cont = Block::new(blk_normal_cont_id);
vm.set_name(blk_normal_cont.as_entity(), Mu("blk_normal_cont"));
let blk_normal_cont_thread_exit = func_ver.new_inst(vm.next_id(), Instruction {
value: None,
ops: RwLock::new(vec![]),
v: Instruction_::ThreadExit
});
blk_normal_cont.content = Some(BlockContent {
args: vec![],
exn_arg: None,
body: vec![blk_normal_cont_thread_exit],
keepalives: None
});
// %blk_exn_cont() %EXN:
let mut blk_exn_cont = Block::new(blk_exn_cont_id);
vm.set_name(blk_exn_cont.as_entity(), Mu("blk_exn_cont"));
let blk_exn_cont_thread_exit = func_ver.new_inst(vm.next_id(), Instruction {
value: None,
ops: RwLock::new(vec![]),
v: Instruction_::ThreadExit
});
blk_exn_cont.content = Some(BlockContent {
args: vec![],
exn_arg: None,
body: vec![blk_exn_cont_thread_exit],
keepalives: None
});
func_ver.define(FunctionContent{
entry: blk_0.id(),
blocks: {
let mut ret = HashMap::new();
ret.insert(blk_0.id(), blk_0);
ret.insert(blk_normal_cont.id(), blk_normal_cont);
ret.insert(blk_exn_cont.id(), blk_exn_cont);
ret
}
});
vm.define_func_version(func_ver);
}
fn create_throw_exception_func (vm: &VM) {
let type_int64 = vm.get_type(vm.id_of("int64"));
let type_ref_int64 = vm.get_type(vm.id_of("ref_int64"));
let type_iref_int64 = vm.get_type(vm.id_of("iref_int64"));
// .funcsig @throw_exception = () -> ()
let func_sig = vm.declare_func_sig(vm.next_id(), vec![], vec![]);
vm.set_name(func_sig.as_entity(), Mu("throw_exception_sig"));
// .funcdecl @catch_exception <@throw_exception>
let func = MuFunction::new(vm.next_id(), func_sig.clone());
vm.set_name(func.as_entity(), Mu("throw_exception"));
let func_id = func.id();
vm.declare_func(func);
// .funcdef @catch_exception VERSION @v1 <@throw_exception>
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(), Mu("blk_0"));
// %exception_obj = NEW <@int64>
let blk_0_exception_obj = func_ver.new_ssa(vm.next_id(), type_ref_int64.clone());
vm.set_name(blk_0_exception_obj.as_entity(), Mu("blk_0_exception_obj"));
let blk_0_inst0 = func_ver.new_inst(vm.next_id(), Instruction {
value: Some(vec![blk_0_exception_obj.clone_value()]),
ops: RwLock::new(vec![]),
v: Instruction_::New(type_ref_int64.clone())
});
// %exception_obj_iref = GETIREF <@int64> %exception_obj
let blk_0_exception_obj_iref = func_ver.new_ssa(vm.next_id(), type_iref_int64.clone());
vm.set_name(blk_0_exception_obj_iref.as_entity(), Mu("blk_0_exception_obj_iref"));
let blk_0_inst1 = func_ver.new_inst(vm.next_id(), Instruction {
value: Some(vec![blk_0_exception_obj_iref.clone_value()]),
ops: RwLock::new(vec![blk_0_exception_obj.clone()]),
v: Instruction_::GetIRef(0)
});
// STORE <@int64> %exception_obj_iref @int64_1
let const_int64_1 = vm.get_const(vm.id_of("int64_1"));
let blk_0_const_int64_1 = func_ver.new_constant(vm.next_id(), const_int64_1);
let blk_0_inst2 = func_ver.new_inst(vm.next_id(), Instruction {
value: None,
ops: RwLock::new(vec![blk_0_exception_obj_iref.clone(), blk_0_const_int64_1.clone()]),
v: Instruction_::Store {
is_ptr: false,
order: MemoryOrder::Relaxed,
mem_loc: 0,
value: 1
}
});
let blk_0_term = func_ver.new_inst(vm.next_id(), Instruction {
value: None,
ops: RwLock::new(vec![blk_0_exception_obj.clone()]),
v: Instruction_::Throw(0)
});
func_ver.define(FunctionContent {
entry: blk_0.id(),
blocks: {
let mut ret = HashMap::new();
ret.insert(blk_0.id(), blk_0);
ret
}
});
vm.define_func_version(func_ver);
}
\ No newline at end of file
......@@ -63,6 +63,7 @@ fn primordial_main() -> VM {
let blk_entry_content = BlockContent {
args: vec![],
exn_arg: None,
body: vec![thread_exit],
keepalives: None
};
......
......@@ -68,6 +68,7 @@ pub fn sum() -> VM {
let blk_entry_content = BlockContent {
args: vec![blk_entry_n.clone_value()],
exn_arg: None,
body: vec![blk_entry_term],
keepalives: None
};
......@@ -131,6 +132,7 @@ pub fn sum() -> VM {
let blk_head_content = BlockContent {
args: vec![blk_head_n.clone_value(), blk_head_s.clone_value(), blk_head_i.clone_value()],
exn_arg: None,
body: vec![blk_head_inst0, blk_head_inst1, blk_head_inst2, blk_head_term],
keepalives: None
};
......@@ -149,6 +151,7 @@ pub fn sum() -> VM {
let blk_ret_content = BlockContent {
args: vec![blk_ret_s.clone_value()],
exn_arg: None,
body: vec![blk_ret_term],
keepalives: None
};
......@@ -263,6 +266,7 @@ pub fn factorial() -> VM {
let blk_0_content = BlockContent {
args: vec![blk_0_n_3.clone_value()],
exn_arg: None,
body: vec![blk_0_inst0, blk_0_term],
keepalives: None
};
......@@ -281,6 +285,7 @@ pub fn factorial() -> VM {
let blk_2_content = BlockContent {
args: vec![blk_2_v53.clone_value()],
exn_arg: None,
body: vec![blk_2_term],
keepalives: None
};
......@@ -337,6 +342,7 @@ pub fn factorial() -> VM {
let blk_1_content = BlockContent {
args: vec![blk_1_n_3.clone_value()],
exn_arg: None,
body: vec![blk_1_inst0, blk_1_inst1, blk_1_inst2, blk_1_term],
keepalives: None
};
......@@ -439,6 +445,7 @@ pub fn global_access() -> VM {
let blk_0_content = BlockContent {
args: vec![],
exn_arg: None,
body: vec![blk_0_inst0, blk_0_inst1, blk_0_term],
keepalives: None
};
......
mod test_thread;
mod test_gc_harness;
mod test_gc;
......
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