Commit 3b88ae36 authored by qinsoon's avatar qinsoon

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

macro.
parent 2026c567
......@@ -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![]})