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 3b88ae36 authored by qinsoon's avatar qinsoon

remove RwLock on MuEntityHeader.name (Issue#15), rewrite all tests in Rust with

macro.
parent 2026c567
Pipeline #389 passed with stage
in 69 minutes and 58 seconds
......@@ -9,7 +9,6 @@ use utils::LinkedHashSet;
use std::fmt;
use std::default;
use std::sync::RwLock;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
pub type WPID = usize;
......@@ -74,9 +73,9 @@ pub struct MuFunction {
}
impl MuFunction {
pub fn new(id: MuID, sig: P<MuFuncSig>) -> MuFunction {
pub fn new(entity: MuEntityHeader, sig: P<MuFuncSig>) -> MuFunction {
MuFunction {
hdr: MuEntityHeader::unnamed(id),
hdr: entity,
sig: sig,
cur_ver: None,
all_vers: vec![]
......@@ -143,9 +142,9 @@ impl fmt::Debug for MuFunctionVersion {
}
impl MuFunctionVersion {
pub fn new(id: MuID, func: MuID, sig: P<MuFuncSig>) -> MuFunctionVersion {
pub fn new(entity: MuEntityHeader, func: MuID, sig: P<MuFuncSig>) -> MuFunctionVersion {
MuFunctionVersion{
hdr: MuEntityHeader::unnamed(id),
hdr: entity,
func_id: func,
sig: sig,
orig_content: None,
......@@ -194,9 +193,10 @@ impl MuFunctionVersion {
self.is_compiled = true;
}
pub fn new_ssa(&mut self, id: MuID, ty: P<MuType>) -> P<TreeNode> {
pub fn new_ssa(&mut self, entity: MuEntityHeader, ty: P<MuType>) -> P<TreeNode> {
let id = entity.id();
let val = P(Value{
hdr: MuEntityHeader::unnamed(id),
hdr: entity,
ty: ty,
v: Value_::SSAVar(id)
});
......@@ -425,8 +425,8 @@ impl fmt::Debug for Block {
}
impl Block {
pub fn new(id: MuID) -> Block {
Block{hdr: MuEntityHeader::unnamed(id), content: None, control_flow: ControlFlow::default()}
pub fn new(entity: MuEntityHeader) -> Block {
Block{hdr: entity, content: None, control_flow: ControlFlow::default()}
}
pub fn is_receiving_exception_arg(&self) -> bool {
......@@ -1002,14 +1002,14 @@ impl fmt::Display for MemoryLocation {
#[derive(Debug)] // Display, PartialEq, Clone
pub struct MuEntityHeader {
id: MuID,
name: RwLock<Option<MuName>>
name: Option<MuName>
}
impl Clone for MuEntityHeader {
fn clone(&self) -> Self {
MuEntityHeader {
id: self.id,
name: RwLock::new(self.name.read().unwrap().clone())
name: self.name.clone()
}
}
}
......@@ -1020,7 +1020,7 @@ impl Encodable for MuEntityHeader {
s.emit_struct("MuEntityHeader", 2, |s| {
try!(s.emit_struct_field("id", 0, |s| self.id.encode(s)));
let name = &self.name.read().unwrap();
let name = &self.name;
try!(s.emit_struct_field("name", 1, |s| name.encode(s)));
Ok(())
......@@ -1036,7 +1036,7 @@ impl Decodable for MuEntityHeader {
Ok(MuEntityHeader{
id: id,
name: RwLock::new(name)
name: name
})
})
}
......@@ -1058,14 +1058,14 @@ impl MuEntityHeader {
pub fn unnamed(id: MuID) -> MuEntityHeader {
MuEntityHeader {
id: id,
name: RwLock::new(None)
name: None
}
}
pub fn named(id: MuID, name: MuName) -> MuEntityHeader {
MuEntityHeader {
id: id,
name: RwLock::new(Some(name_check(name)))
name: Some(name_check(name))
}
}
......@@ -1074,12 +1074,7 @@ impl MuEntityHeader {
}
pub fn name(&self) -> Option<MuName> {
self.name.read().unwrap().clone()
}
pub fn set_name(&self, name: MuName) {
let mut name_guard = self.name.write().unwrap();
*name_guard = Some(name_check(name));
self.name.clone()
}
fn abbreviate_name(&self) -> Option<MuName> {
......@@ -1129,7 +1124,6 @@ impl fmt::Display for MuEntityHeader {
pub trait MuEntity {
fn id(&self) -> MuID;
fn name(&self) -> Option<MuName>;
fn set_name(&self, name: MuName);
fn as_entity(&self) -> &MuEntity;
}
......@@ -1155,13 +1149,6 @@ impl MuEntity for TreeNode {
}
}
fn set_name(&self, name: MuName) {
match self.v {
TreeNode_::Instruction(ref inst) => inst.set_name(name),
TreeNode_::Value(ref pv) => pv.set_name(name)
}
}
fn as_entity(&self) -> &MuEntity {
match self.v {
TreeNode_::Instruction(ref inst) => inst.as_entity(),
......
#[macro_use]
extern crate log;
extern crate simple_logger;
#[macro_use]
......@@ -14,9 +13,6 @@ macro_rules! impl_mu_entity {
fn id(&self) -> MuID {self.hdr.id()}
#[inline(always)]
fn name(&self) -> Option<MuName> {self.hdr.name()}
fn set_name(&self, name: MuName) {
self.hdr.set_name(name);
}
fn as_entity(&self) -> &MuEntity {
let ref_ty : &$entity = self;
ref_ty as &MuEntity
......
......@@ -3555,7 +3555,7 @@ pub fn spill_rewrite(
// generate a random new temporary
let temp_ty = val_reg.ty.clone();
let temp = func.new_ssa(vm.next_id(), temp_ty.clone()).clone_value();
let temp = func.new_ssa(MuEntityHeader::unnamed(vm.next_id()), temp_ty.clone()).clone_value();
// maintain mapping
trace!("reg {} used in Inst{} is replaced as {}", val_reg, i, temp);
......@@ -3603,7 +3603,7 @@ pub fn spill_rewrite(
temp_for_cur_inst.get(&reg).unwrap().clone()
} else {
let temp_ty = val_reg.ty.clone();
let temp = func.new_ssa(vm.next_id(), temp_ty.clone()).clone_value();
let temp = func.new_ssa(MuEntityHeader::unnamed(vm.next_id()), temp_ty.clone()).clone_value();
spilled_scratch_temps.insert(temp.id(), reg);
......
......@@ -178,11 +178,11 @@ impl CompilerPass for GenMovPhi {
// insert new blocks here
for block_info in new_blocks_to_insert {
let block = {
let mut ret = Block::new(block_info.blk_id);
let target_id = block_info.target;
let name = format!("intermediate_block_{}_to_{}", block_info.blk_id, target_id);
vm.set_name(ret.as_entity(), name);
let mut ret = Block::new(MuEntityHeader::named(block_info.blk_id, name));
vm.set_name(ret.as_entity());
let mut target_block = f_content.get_block_mut(target_id);
......
......@@ -177,7 +177,10 @@ impl Inlining {
let old_name = cur_block.name().unwrap();
// start a new block
cur_block = Block::new(vm.next_id());
let new_name = format!("{}_cont_after_inline_{}", old_name, inst_id);
trace!("create continue block for EXPRCALL/CCALL: {}", &new_name);
cur_block = Block::new(MuEntityHeader::named(vm.next_id(), new_name));
cur_block.content = Some(BlockContent{
args: {
if inst.value.is_none() {
......@@ -190,9 +193,7 @@ impl Inlining {
body: vec![],
keepalives: None
});
let new_name = format!("{}_cont_after_inline_{}", old_name, inst_id);
trace!("create continue block for EXPRCALL/CCALL: {}", &new_name);
vm.set_name(cur_block.as_entity(), new_name);
vm.set_name(cur_block.as_entity());
// deal with the inlined function
copy_inline_blocks(&mut new_blocks, cur_block.id(),
......@@ -225,8 +226,9 @@ impl Inlining {
// other than the inlined function returns, we need an intermediate block to pass extra arguments
if resume.normal_dest.args.len() != inlined_fv_guard.sig.ret_tys.len() {
debug!("need an extra block for passing normal dest arguments");
let mut intermediate_block = Block::new(vm.next_id());
vm.set_name(intermediate_block.as_entity(), format!("inline_{}_arg_pass", inst_id));
let int_block_name = format!("inline_{}_arg_pass", inst_id);
let mut intermediate_block = Block::new(MuEntityHeader::named(vm.next_id(), int_block_name));
vm.set_name(intermediate_block.as_entity());
// branch to normal_dest with normal_dest arguments
let normal_dest_args = resume.normal_dest.get_arguments_as_node(&ops);
......
......@@ -573,9 +573,9 @@ impl <'a> VM {
self.is_running.load(Ordering::Relaxed)
}
pub fn set_name(&self, entity: &MuEntity, name: MuName) {
pub fn set_name(&self, entity: &MuEntity) {
let id = entity.id();
entity.set_name(name.clone());
let name = entity.name().unwrap();
let mut map = self.id_name_map.write().unwrap();
map.insert(id, name.clone());
......@@ -601,11 +601,11 @@ impl <'a> VM {
map.get(&id).unwrap().clone()
}
pub fn declare_const(&self, id: MuID, ty: P<MuType>, val: Constant) -> P<Value> {
pub fn declare_const(&self, entity: MuEntityHeader, ty: P<MuType>, val: Constant) -> P<Value> {
let mut constants = self.constants.write().unwrap();
let ret = P(Value{hdr: MuEntityHeader::unnamed(id), ty: ty, v: Value_::Constant(val)});
let ret = P(Value{hdr: entity, ty: ty, v: Value_::Constant(val)});
self.declare_const_internal(&mut constants, id, ret.clone());
self.declare_const_internal(&mut constants, ret.id(), ret.clone());
ret
}
......@@ -644,17 +644,17 @@ impl <'a> VM {
ValueLocation::Relocatable(backend::RegGroup::GPR, name)
}
pub fn declare_global(&self, id: MuID, ty: P<MuType>) -> P<Value> {
pub fn declare_global(&self, entity: MuEntityHeader, ty: P<MuType>) -> P<Value> {
let global = P(Value{
hdr: MuEntityHeader::unnamed(id),
ty: self.declare_type(self.next_id(), MuType_::iref(ty.clone())),
hdr: entity,
ty: self.declare_type(MuEntityHeader::unnamed(self.next_id()), MuType_::iref(ty.clone())),
v: Value_::Global(ty)
});
let mut globals = self.globals.write().unwrap();
let mut global_locs = self.global_locations.write().unwrap();
self.declare_global_internal(&mut globals, &mut global_locs, id, global.clone());
self.declare_global_internal(&mut globals, &mut global_locs, global.id(), global.clone());
global
}
......@@ -692,12 +692,12 @@ impl <'a> VM {
global_locs.insert(id, loc);
}
pub fn declare_type(&self, id: MuID, ty: MuType_) -> P<MuType> {
let ty = P(MuType{hdr: MuEntityHeader::unnamed(id), v: ty});
pub fn declare_type(&self, entity: MuEntityHeader, ty: MuType_) -> P<MuType> {
let ty = P(MuType{hdr: entity, v: ty});
let mut types = self.types.write().unwrap();
self.declare_type_internal(&mut types, id, ty.clone());
self.declare_type_internal(&mut types, ty.id(), ty.clone());
ty
}
......@@ -729,11 +729,11 @@ impl <'a> VM {
}
}
pub fn declare_func_sig(&self, id: MuID, ret_tys: Vec<P<MuType>>, arg_tys: Vec<P<MuType>>) -> P<MuFuncSig> {
let ret = P(MuFuncSig{hdr: MuEntityHeader::unnamed(id), ret_tys: ret_tys, arg_tys: arg_tys});
pub fn declare_func_sig(&self, entity: MuEntityHeader, ret_tys: Vec<P<MuType>>, arg_tys: Vec<P<MuType>>) -> P<MuFuncSig> {
let ret = P(MuFuncSig{hdr: entity, ret_tys: ret_tys, arg_tys: arg_tys});
let mut func_sigs = self.func_sigs.write().unwrap();
self.declare_func_sig_internal(&mut func_sigs, id, ret.clone());
self.declare_func_sig_internal(&mut func_sigs, ret.id(), ret.clone());
ret
}
......
This diff is collapsed.
......@@ -155,112 +155,53 @@ fn test_instruction_new_on_cur_thread() {
#[allow(unused_variables)]
pub fn alloc_new() -> VM {
let vm = VM::new();
typedef! ((vm) int64 = mu_int(64));
typedef! ((vm) ref_int64 = mu_ref(int64));
typedef! ((vm) iref_int64 = mu_iref(int64));
// .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());
constdef! ((vm) <int64> int64_0 = Constant::Int(0));
constdef! ((vm) <int64> int64_1 = Constant::Int(1));
funcsig! ((vm) alloc_new_sig = () -> (int64));
funcdecl! ((vm) <alloc_new_sig> alloc_new);
funcdef! ((vm) <alloc_new_sig> alloc_new VERSION alloc_new_v1);
// %blk_0():
let mut blk_0 = Block::new(vm.next_id());
vm.set_name(blk_0.as_entity(), "blk_0".to_string());
block! ((vm, alloc_new_v1) blk_0);
// %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())
});
ssa! ((vm, alloc_new_v1) <ref_int64> blk_0_a);
inst! ((vm, alloc_new_v1) blk_0_new:
blk_0_a = NEW <int64>
);
// %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)
});
ssa! ((vm, alloc_new_v1) <iref_int64> blk_0_a_iref);
inst! ((vm, alloc_new_v1) blk_0_getiref:
blk_0_a_iref = GETIREF blk_0_a
);
// 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
consta! ((vm, alloc_new_v1) int64_1_local = int64_1);
inst! ((vm, alloc_new_v1) blk_0_store:
STORE blk_0_a_iref int64_1_local (is_ptr: false, order: MemoryOrder::Relaxed)
);
inst! ((vm, alloc_new_v1) blk_0_term:
THREADEXIT
);
define_block!((vm, alloc_new_v1) blk_0() {
blk_0_new,
blk_0_getiref,
blk_0_store,
blk_0_term
});
define_func_ver!((vm) alloc_new_v1 (entry: blk_0) {
blk_0
});
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.
......@@ -46,105 +46,55 @@ fn test_ccall_exit() {
}
pub fn gen_ccall_exit(arg: P<TreeNode>, func_ver: &mut MuFunctionVersion, vm: &VM) -> Box<TreeNode> {
// .typedef @int32 = int<32>
let type_def_int32 = vm.declare_type(vm.next_id(), MuType_::int(32));
vm.set_name(type_def_int32.as_entity(), Mu("exit_int32"));
// .typedef @exit_sig = (@int32) -> !
let exit_sig = vm.declare_func_sig(vm.next_id(), vec![], vec![type_def_int32.clone()]);
vm.set_name(exit_sig.as_entity(), Mu("exit_sig"));
// .typedef @ufp_exit = ufuncptr(@exit_sig)
let type_def_ufp_exit = vm.declare_type(vm.next_id(), MuType_::UFuncPtr(exit_sig.clone()));
vm.set_name(type_def_ufp_exit.as_entity(), Mu("ufp_exit"));
typedef! ((vm) int32 = mu_int(32));
funcsig! ((vm) exit_sig = (int32) -> ());
typedef! ((vm) ufp_exit = mu_ufuncptr(exit_sig));
// .const @exit = EXTERN SYMBOL "exit"
let const_exit = vm.declare_const(vm.next_id(), type_def_ufp_exit.clone(), Constant::ExternSym(C("exit")));
vm.set_name(const_exit.as_entity(), Mu("exit"));
constdef! ((vm) <ufp_exit> const_exit = Constant::ExternSym(C("exit")));
consta! ((vm, func_ver) const_exit_local = const_exit);
// exprCCALL %const_exit (%const_int32_10)
let const_exit_local = func_ver.new_constant(const_exit.clone());
func_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![const_exit_local, arg]),
v: Instruction_::ExprCCall {
data: CallData {
func: 0,
args: vec![1],
convention: CallConvention::Foreign(ForeignFFI::C)
},
is_abort: false
}
})
inst! ((vm, func_ver) ret:
EXPRCCALL (CallConvention::Foreign(ForeignFFI::C), is_abort: false) const_exit_local (arg)
);
ret
}
fn ccall_exit() -> VM {
let vm = VM::new();
// .typedef @int32 = int<32>
let type_def_int32 = vm.declare_type(vm.next_id(), MuType_::int(32));
vm.set_name(type_def_int32.as_entity(), Mu("int32"));
// .const @int32_10 = 10
let const_int32_10 = vm.declare_const(vm.next_id(), type_def_int32.clone(), Constant::Int(10));
vm.set_name(const_int32_10.as_entity(), Mu("const_int32_10"));
// .const @int32_0 = 0
let const_int32_0 = vm.declare_const(vm.next_id(), type_def_int32.clone(), Constant::Int(0));
vm.set_name(const_int32_0.as_entity(), Mu("const_int32_0"));
typedef! ((vm) int32 = mu_int(32));
// .funcsig @ccall_exit_sig = () -> !
let ccall_exit_sig = vm.declare_func_sig(vm.next_id(), vec![], vec![]);
vm.set_name(ccall_exit_sig.as_entity(), Mu("ccall_exit_sig"));
constdef! ((vm) <int32> int32_10 = Constant::Int(10));
constdef! ((vm) <int32> int32_0 = Constant::Int(0));
// .funcdecl @ccall_exit <@ccall_exit_sig>
let func_id = vm.next_id();
let func = MuFunction::new(func_id, ccall_exit_sig.clone());
vm.set_name(func.as_entity(), Mu("ccall_exit"));
vm.declare_func(func);
// .funcdef @ccall_exit VERSION @ccall_exit_v1 <@ccall_exit_sig>
let mut func_ver = MuFunctionVersion::new(vm.next_id(), func_id, ccall_exit_sig.clone());
vm.set_name(func_ver.as_entity(), Mu("ccall_exit_v1"));
funcsig! ((vm) ccall_exit_sig = () -> ());
funcdecl! ((vm) <ccall_exit_sig> ccall_exit);
funcdef! ((vm) <ccall_exit_sig> ccall_exit VERSION ccall_exit_v1);
// %entry():
let mut blk_entry = Block::new(vm.next_id());
vm.set_name(blk_entry.as_entity(), Mu("entry"));
block! ((vm, ccall_exit_v1) blk_entry);
// exprCCALL %const_exit (%const_int32_10)
let const_int32_10_local = func_ver.new_constant(const_int32_10.clone());
let blk_entry_ccall = gen_ccall_exit(const_int32_10_local.clone(), &mut func_ver, &vm);
consta! ((vm, ccall_exit_v1) int32_10_local = int32_10);
let blk_entry_ccall = gen_ccall_exit(int32_10_local.clone(), &mut ccall_exit_v1, &vm);
// RET %const_int32_0
let const_int32_0_local = func_ver.new_constant(const_int32_0.clone());
consta! ((vm, ccall_exit_v1) int32_0_local = int32_0);
inst! ((vm, ccall_exit_v1) blk_entry_ret:
RET (int32_0_local)
);
let blk_entry_ret = func_ver.new_inst(Instruction{
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![const_int32_0_local]),
v: Instruction_::Return(vec![0])
define_block!((vm, ccall_exit_v1) blk_entry() {
blk_entry_ccall,
blk_entry_ret
});
blk_entry.content = Some(BlockContent {
args: vec![],
exn_arg: None,
body: vec![blk_entry_ccall, blk_entry_ret],
keepalives: None
define_func_ver!((vm) ccall_exit_v1 (entry: blk_entry) {
blk_entry
});
func_ver.define(FunctionContent::new(
blk_entry.id(),
{
let mut map = LinkedHashMap::new();
map.insert(blk_entry.id(), blk_entry);
map
}
));
vm.define_func_version(func_ver);
vm
}
......
......@@ -38,173 +38,103 @@ fn test_switch() {
fn switch() -> VM {
let vm = VM::new();
// .typedef @int64 = int<64>
let type_def_int64 = vm.declare_type(vm.next_id(), MuType_::int(64));
vm.set_name(type_def_int64.as_entity(), Mu("int64"));
// .const @int64_0 <@int64> = 0
let const_int64_0 = vm.declare_const(vm.next_id(), type_def_int64.clone(), Constant::Int(0));
// .const @int64_1 <@int64> = 1
let const_int64_1 = vm.declare_const(vm.next_id(), type_def_int64.clone(), Constant::Int(1));
// .const @int64_2 <@int64> = 2
let const_int64_2 = vm.declare_const(vm.next_id(), type_def_int64.clone(), Constant::Int(2));
// .const @int64_99 <@int64> = 99
let const_int64_99 = vm.declare_const(vm.next_id(), type_def_int64.clone(), Constant::Int(99));
// .funcsig @switch_sig = (@int64) -> (@int64)
let switch_sig = vm.declare_func_sig(vm.next_id(), vec![type_def_int64.clone()], vec![type_def_int64.clone()]);
vm.set_name(switch_sig.as_entity(), Mu("switch_sig"));
// .funcdecl @switch <@switch_sig>
let func_id = vm.next_id();
let func = MuFunction::new(func_id, switch_sig.clone());
vm.set_name(func.as_entity(), Mu("switch"));
vm.declare_func(func);
// .funcdef @switch VERSION @switch_v1 <@switch_sig>
let mut func_ver = MuFunctionVersion::new(vm.next_id(), func_id, switch_sig.clone());
vm.set_name(func_ver.as_entity(), Mu("switch_v1"));
typedef! ((vm) int64 = mu_int(64));
// %entry(<@int64> %a):
let mut blk_entry = Block::new(vm.next_id());
vm.set_name(blk_entry.as_entity(), Mu("entry"));
constdef! ((vm) <int64> int64_0 = Constant::Int(0));
constdef! ((vm) <int64> int64_1 = Constant::Int(1));
constdef! ((vm) <int64> int64_2 = Constant::Int(2));
constdef! ((vm) <int64> int64_99 = Constant::Int(99));
funcsig! ((vm) switch_sig = (int64) -> (int64));
funcdecl! ((vm) <switch_sig> switch);
funcdef! ((vm) <switch_sig> switch VERSION switch_v1);
let blk_entry_a = func_ver.new_ssa(vm.next_id(), type_def_int64.clone());
vm.set_name(blk_entry_a.as_entity(), Mu("blk_entry_a"));
// %entry(<@int64> %a):
block! ((vm, switch_v1) blk_entry);
ssa! ((vm, switch_v1) <int64> a);
// SWITCH %a %blk_default (0 -> %blk_ret0, 1 -> %blk_ret1, 2 -> %blk_ret2)
let const0 = func_ver.new_constant(const_int64_0.clone());
let const1 = func_ver.new_constant(const_int64_1.clone());
let const2 = func_ver.new_constant(const_int64_2.clone());
block! ((vm, switch_v1) blk_ret0);
block! ((vm, switch_v1) blk_ret1);
block! ((vm, switch_v1) blk_ret2);
block! ((vm, switch_v1) blk_default);
let blk_default_id = vm.next_id();
let blk_ret0_id = vm.next_id();
let blk_ret1_id = vm.next_id();
let blk_ret2_id = vm.next_id();
consta! ((vm, switch_v1) int64_0_local = int64_0);
consta! ((vm, switch_v1) int64_1_local = int64_1);
consta! ((vm, switch_v1) int64_2_local = int64_2);
let blk_entry_switch = func_ver.new_inst(Instruction {
let blk_entry_switch = switch_v1.new_inst(Instruction {
hdr: MuEntityHeader::unnamed(vm.next_id()),
value: None,
ops: RwLock::new(vec![
blk_entry_a.clone(), // 0
const0.clone(), // 1
const1.clone(), // 2
const2.clone(), // 3
a.clone(), // 0
int64_0_local.clone(), // 1
int64_1_local.clone(), // 2
int64_2_local.clone(), // 3
]),
v: Instruction_::Switch {
cond: 0,
default: Destination {
target: blk_default_id,
target: blk_default.id(),
args: vec![]
},
branches: vec![
(1, Destination{target: blk_ret0_id, args: vec![]}),
(2, Destination{target: blk_ret1_id, args: vec![]}),
(3, Destination{target: blk_ret2_id, args: vec![]})
(1, Destination{target: blk_ret0.id(), args: vec![]}),
(2, Destination{target: blk_ret1.id(), args: vec![]}),
(3, Destination{target: blk_ret2.id(), args: vec![]})