Commit b20cc1a4 authored by qinsoon's avatar qinsoon

[wip] fixing tests

parent 116e0e2d
...@@ -9,6 +9,7 @@ use std::collections::HashMap; ...@@ -9,6 +9,7 @@ use std::collections::HashMap;
use std::fmt; use std::fmt;
use std::default; use std::default;
use std::cell::Cell; use std::cell::Cell;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
pub type WPID = usize; pub type WPID = usize;
pub type MuID = usize; pub type MuID = usize;
...@@ -17,11 +18,40 @@ pub type Address = usize; // TODO: replace this with Address(usize) ...@@ -17,11 +18,40 @@ pub type Address = usize; // TODO: replace this with Address(usize)
pub type OpIndex = usize; pub type OpIndex = usize;
pub const MACHINE_ID_START : usize = 0; lazy_static! {
pub const MACHINE_ID_END : usize = 100; pub static ref MACHINE_ID : AtomicUsize = {
pub const INTERNAL_ID_START: usize = 101; let a = ATOMIC_USIZE_INIT;
pub const INTERNAL_ID_END : usize = 200; a.store(MACHINE_ID_START, Ordering::SeqCst);
pub const USER_ID_START : usize = 201; a
};
pub static ref INTERNAL_ID : AtomicUsize = {
let a = ATOMIC_USIZE_INIT;
a.store(INTERNAL_ID_START, Ordering::SeqCst);
a
};
}
pub const MACHINE_ID_START : usize = 0;
pub const MACHINE_ID_END : usize = 100;
pub const INTERNAL_ID_START: usize = 101;
pub const INTERNAL_ID_END : usize = 200;
pub const USER_ID_START : usize = 201;
pub fn new_machine_id() -> MuID {
let ret = MACHINE_ID.fetch_add(1, Ordering::SeqCst);
if ret >= MACHINE_ID_END {
panic!("machine id overflow")
}
ret
}
pub fn new_internal_id() -> MuID {
let ret = INTERNAL_ID.fetch_add(1, Ordering::SeqCst);
if ret >= INTERNAL_ID_END {
panic!("internal id overflow")
}
ret
}
#[derive(Debug)] #[derive(Debug)]
pub struct MuFunction { pub struct MuFunction {
...@@ -560,8 +590,8 @@ pub enum Constant { ...@@ -560,8 +590,8 @@ pub enum Constant {
Float(f32), Float(f32),
Double(f64), Double(f64),
IRef(Address), IRef(Address),
FuncRef(MuName), FuncRef(MuID),
UFuncRef(MuName), UFuncRef(MuID),
Vector(Vec<Constant>), Vector(Vec<Constant>),
} }
...@@ -619,6 +649,42 @@ impl fmt::Display for MemoryLocation { ...@@ -619,6 +649,42 @@ impl fmt::Display for MemoryLocation {
} }
} }
pub trait MuEntity {
fn id(&self) -> MuID;
fn name(&self) -> Option<MuName>;
fn set_name(&mut self, name: MuName);
fn as_entity(&self) -> &MuEntity;
fn as_entity_mut(&mut self) -> &mut MuEntity;
}
macro_rules! impl_mu_entity {
($entity: ty) => {
impl MuEntity for $entity {
#[inline(always)]
fn id(&self) -> MuID {self.id}
#[inline(always)]
fn name(&self) -> Option<MuName> {self.name}
fn set_name(&mut self, name: MuName) {self.name = Some(name);}
fn as_entity(&self) -> &MuEntity {
let ref_ty : &$entity = self;
ref_ty as &MuEntity
}
fn as_entity_mut(&mut self) -> &mut MuEntity {
let ref_ty : &mut $entity = self;
ref_ty as &mut MuEntity
}
}
}
}
impl_mu_entity!(MuFunction);
impl_mu_entity!(MuFunctionVersion);
impl_mu_entity!(Block);
impl_mu_entity!(TreeNode);
impl_mu_entity!(MuType);
impl_mu_entity!(Value);
impl_mu_entity!(MuFuncSig);
pub fn op_vector_str(vec: &Vec<OpIndex>, ops: &Vec<P<TreeNode>>) -> String { pub fn op_vector_str(vec: &Vec<OpIndex>, ops: &Vec<P<TreeNode>>) -> String {
let mut ret = String::new(); let mut ret = String::new();
for i in 0..vec.len() { for i in 0..vec.len() {
......
...@@ -327,6 +327,8 @@ macro_rules! is_type ( ...@@ -327,6 +327,8 @@ macro_rules! is_type (
#[derive(Clone, PartialEq, Eq, Debug, Hash)] #[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct MuFuncSig { pub struct MuFuncSig {
pub id: MuID,
pub name: Option<MuName>,
pub ret_tys : Vec<P<MuType>>, pub ret_tys : Vec<P<MuType>>,
pub arg_tys: Vec<P<MuType>> pub arg_tys: Vec<P<MuType>>
} }
......
...@@ -1082,13 +1082,16 @@ fn create_emit_directory() { ...@@ -1082,13 +1082,16 @@ fn create_emit_directory() {
} }
} }
pub fn emit_code(func: &mut MuFunctionVersion, vm: &VM) { pub fn emit_code(fv: &mut MuFunctionVersion, vm: &VM) {
use std::io::prelude::*; use std::io::prelude::*;
use std::fs::File; use std::fs::File;
use std::path; use std::path;
let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&fv.func_id).unwrap().borrow();
let compiled_funcs = vm.compiled_funcs().read().unwrap(); let compiled_funcs = vm.compiled_funcs().read().unwrap();
let cf = compiled_funcs.get(&func.id).unwrap().borrow(); let cf = compiled_funcs.get(&fv.id).unwrap().borrow();
let code = cf.mc.emit(); let code = cf.mc.emit();
......
...@@ -159,9 +159,15 @@ impl <'a> InstructionSelection { ...@@ -159,9 +159,15 @@ impl <'a> InstructionSelection {
// check direct call or indirect // check direct call or indirect
if self.match_funcref_const(func) { if self.match_funcref_const(func) {
let target = self.emit_get_funcref_const(func); let target_id = self.emit_get_funcref_const(func);
let funcs = vm.funcs().read().unwrap();
self.backend.emit_call_near_rel32(target); let target = funcs.get(&target_id).unwrap().borrow();
if vm.is_running() {
unimplemented!()
} else {
self.backend.emit_call_near_rel32(target.name().unwrap());
}
} else if self.match_ireg(func) { } else if self.match_ireg(func) {
let target = self.emit_ireg(func, cur_func, vm); let target = self.emit_ireg(func, cur_func, vm);
...@@ -710,12 +716,12 @@ impl <'a> InstructionSelection { ...@@ -710,12 +716,12 @@ impl <'a> InstructionSelection {
} }
} }
fn emit_get_funcref_const(&mut self, op: &P<TreeNode>) -> MuName { fn emit_get_funcref_const(&mut self, op: &P<TreeNode>) -> MuID {
match op.v { match op.v {
TreeNode_::Value(ref pv) => { TreeNode_::Value(ref pv) => {
match pv.v { match pv.v {
Value_::Constant(Constant::FuncRef(tag)) Value_::Constant(Constant::FuncRef(id))
| Value_::Constant(Constant::UFuncRef(tag)) => tag, | Value_::Constant(Constant::UFuncRef(id)) => id,
_ => panic!("expected a (u)funcref const") _ => panic!("expected a (u)funcref const")
} }
}, },
...@@ -782,13 +788,15 @@ impl CompilerPass for InstructionSelection { ...@@ -782,13 +788,15 @@ impl CompilerPass for InstructionSelection {
} }
#[allow(unused_variables)] #[allow(unused_variables)]
fn start_function(&mut self, vm: &VM, func: &mut MuFunctionVersion) { fn start_function(&mut self, vm: &VM, func_ver: &mut MuFunctionVersion) {
debug!("{}", self.name()); debug!("{}", self.name());
self.backend.start_code(func.name.unwrap()); let funcs = vm.funcs().read().unwrap();
let func = funcs.get(&func_ver.func_id).unwrap().borrow();
self.backend.start_code(func.name().unwrap());
// prologue (get arguments from entry block first) // prologue (get arguments from entry block first)
let entry_block = func.content.as_ref().unwrap().get_entry_block(); let entry_block = func_ver.content.as_ref().unwrap().get_entry_block();
let ref args = entry_block.content.as_ref().unwrap().args; let ref args = entry_block.content.as_ref().unwrap().args;
self.emit_common_prologue(args); self.emit_common_prologue(args);
} }
...@@ -824,6 +832,7 @@ impl CompilerPass for InstructionSelection { ...@@ -824,6 +832,7 @@ impl CompilerPass for InstructionSelection {
let mc = self.backend.finish_code(); let mc = self.backend.finish_code();
let compiled_func = CompiledFunction { let compiled_func = CompiledFunction {
func_id: func.func_id,
func_ver_id: func.id, func_ver_id: func.id,
temps: HashMap::new(), temps: HashMap::new(),
mc: mc mc: mc
......
...@@ -17,52 +17,58 @@ use ast::types::*; ...@@ -17,52 +17,58 @@ use ast::types::*;
use compiler::backend::RegGroup; use compiler::backend::RegGroup;
macro_rules! GPR { macro_rules! GPR {
($name: expr, $id: expr) => { ($name: expr) => {
P(Value { {
id: $id, let id = new_machine_id();
name: Some($name), P(Value {
ty: GPR_TY.clone(), id: id,
v: Value_::SSAVar($id) name: Some($name),
}) ty: GPR_TY.clone(),
v: Value_::SSAVar(id)
})
}
}; };
} }
macro_rules! FPR { macro_rules! FPR {
($name: expr, $id: expr) => { ($name: expr) => {
P(Value { {
id: $id, let id = new_machine_id();
name: Some($name), P(Value {
ty: FPR_TY.clone(), id: id,
v: Value_::SSAVar($id) name: Some($name),
}) ty: FPR_TY.clone(),
v: Value_::SSAVar(id)
})
}
}; };
} }
lazy_static! { lazy_static! {
pub static ref GPR_TY : P<MuType> = P(MuType::new(INTERNAL_ID_START + 0, MuType_::int(64))); pub static ref GPR_TY : P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(64)));
pub static ref FPR_TY : P<MuType> = P(MuType::new(INTERNAL_ID_START + 1, MuType_::double())); pub static ref FPR_TY : P<MuType> = P(MuType::new(new_internal_id(), MuType_::double()));
} }
// put into several segments to avoid 'recursion limit reached' error // put into several segments to avoid 'recursion limit reached' error
lazy_static! { lazy_static! {
pub static ref RAX : P<Value> = GPR!("rax", 0); pub static ref RAX : P<Value> = GPR!("rax");
pub static ref RCX : P<Value> = GPR!("rcx", 1); pub static ref RCX : P<Value> = GPR!("rcx");
pub static ref RDX : P<Value> = GPR!("rdx", 2); pub static ref RDX : P<Value> = GPR!("rdx");
pub static ref RBX : P<Value> = GPR!("rbx", 3); pub static ref RBX : P<Value> = GPR!("rbx");
pub static ref RSP : P<Value> = GPR!("rsp", 4); pub static ref RSP : P<Value> = GPR!("rsp");
pub static ref RBP : P<Value> = GPR!("rbp", 5); pub static ref RBP : P<Value> = GPR!("rbp");
pub static ref RSI : P<Value> = GPR!("rsi", 6); pub static ref RSI : P<Value> = GPR!("rsi");
pub static ref RDI : P<Value> = GPR!("rdi", 7); pub static ref RDI : P<Value> = GPR!("rdi");
pub static ref R8 : P<Value> = GPR!("r8", 8); pub static ref R8 : P<Value> = GPR!("r8");
pub static ref R9 : P<Value> = GPR!("r9", 9); pub static ref R9 : P<Value> = GPR!("r9");
pub static ref R10 : P<Value> = GPR!("r10", 10); pub static ref R10 : P<Value> = GPR!("r10");
pub static ref R11 : P<Value> = GPR!("r11", 11); pub static ref R11 : P<Value> = GPR!("r11");
pub static ref R12 : P<Value> = GPR!("r12", 12); pub static ref R12 : P<Value> = GPR!("r12");
pub static ref R13 : P<Value> = GPR!("r13", 13); pub static ref R13 : P<Value> = GPR!("r13");
pub static ref R14 : P<Value> = GPR!("r14", 14); pub static ref R14 : P<Value> = GPR!("r14");
pub static ref R15 : P<Value> = GPR!("r15", 15); pub static ref R15 : P<Value> = GPR!("r15");
pub static ref RIP : P<Value> = GPR!("rip", 32); pub static ref RIP : P<Value> = GPR!("rip");
pub static ref RETURN_GPRs : [P<Value>; 2] = [ pub static ref RETURN_GPRs : [P<Value>; 2] = [
RAX.clone(), RAX.clone(),
...@@ -108,22 +114,22 @@ lazy_static! { ...@@ -108,22 +114,22 @@ lazy_static! {
} }
lazy_static!{ lazy_static!{
pub static ref XMM0 : P<Value> = FPR!("xmm0", 16); pub static ref XMM0 : P<Value> = FPR!("xmm0");
pub static ref XMM1 : P<Value> = FPR!("xmm1", 17); pub static ref XMM1 : P<Value> = FPR!("xmm1");
pub static ref XMM2 : P<Value> = FPR!("xmm2", 18); pub static ref XMM2 : P<Value> = FPR!("xmm2");
pub static ref XMM3 : P<Value> = FPR!("xmm3", 19); pub static ref XMM3 : P<Value> = FPR!("xmm3");
pub static ref XMM4 : P<Value> = FPR!("xmm4", 20); pub static ref XMM4 : P<Value> = FPR!("xmm4");
pub static ref XMM5 : P<Value> = FPR!("xmm5", 21); pub static ref XMM5 : P<Value> = FPR!("xmm5");
pub static ref XMM6 : P<Value> = FPR!("xmm6", 22); pub static ref XMM6 : P<Value> = FPR!("xmm6");
pub static ref XMM7 : P<Value> = FPR!("xmm7", 23); pub static ref XMM7 : P<Value> = FPR!("xmm7");
pub static ref XMM8 : P<Value> = FPR!("xmm8", 24); pub static ref XMM8 : P<Value> = FPR!("xmm8");
pub static ref XMM9 : P<Value> = FPR!("xmm9", 25); pub static ref XMM9 : P<Value> = FPR!("xmm9");
pub static ref XMM10 : P<Value> = FPR!("xmm10",26); pub static ref XMM10 : P<Value> = FPR!("xmm10");
pub static ref XMM11 : P<Value> = FPR!("xmm11",27); pub static ref XMM11 : P<Value> = FPR!("xmm11");
pub static ref XMM12 : P<Value> = FPR!("xmm12",28); pub static ref XMM12 : P<Value> = FPR!("xmm12");
pub static ref XMM13 : P<Value> = FPR!("xmm13",29); pub static ref XMM13 : P<Value> = FPR!("xmm13");
pub static ref XMM14 : P<Value> = FPR!("xmm14",30); pub static ref XMM14 : P<Value> = FPR!("xmm14");
pub static ref XMM15 : P<Value> = FPR!("xmm15",31); pub static ref XMM15 : P<Value> = FPR!("xmm15");
pub static ref RETURN_FPRs : [P<Value>; 2] = [ pub static ref RETURN_FPRs : [P<Value>; 2] = [
XMM0.clone(), XMM0.clone(),
......
...@@ -421,29 +421,4 @@ impl MuCtxInternal { ...@@ -421,29 +421,4 @@ impl MuCtxInternal {
vm: vm vm: vm
} }
} }
} }
\ No newline at end of file
pub trait MuEntity {
fn id(&self) -> MuID;
fn name(&self) -> Option<MuName>;
fn set_name(&mut self, name: MuName);
}
macro_rules! mu_entity {
($entity: ident) => {
impl MuEntity for $entity {
#[inline(always)]
fn id(&self) -> MuID {self.id}
#[inline(always)]
fn name(&self) -> Option<MuName> {self.name}
fn set_name(&mut self, name: MuName) {self.name = Some(name);}
}
}
}
mu_entity!(MuFunction);
mu_entity!(MuFunctionVersion);
mu_entity!(Block);
mu_entity!(TreeNode);
mu_entity!(MuType);
mu_entity!(Value);
\ No newline at end of file
...@@ -28,7 +28,8 @@ pub struct VM { ...@@ -28,7 +28,8 @@ pub struct VM {
constants: RwLock<HashMap<MuID, P<Value>>>, constants: RwLock<HashMap<MuID, P<Value>>>,
globals: RwLock<HashMap<MuID, P<Value>>>, globals: RwLock<HashMap<MuID, P<Value>>>,
func_sigs: RwLock<HashMap<MuName, P<MuFuncSig>>>, func_sigs: RwLock<HashMap<MuID, P<MuFuncSig>>>,
// key: (func_id, func_ver_id)
func_vers: RwLock<HashMap<(MuID, MuID), RefCell<MuFunctionVersion>>>, func_vers: RwLock<HashMap<(MuID, MuID), RefCell<MuFunctionVersion>>>,
funcs: RwLock<HashMap<MuID, RefCell<MuFunction>>>, funcs: RwLock<HashMap<MuID, RefCell<MuFunction>>>,
...@@ -78,6 +79,27 @@ impl <'a> VM { ...@@ -78,6 +79,27 @@ impl <'a> VM {
self.is_running.load(Ordering::Relaxed) self.is_running.load(Ordering::Relaxed)
} }
pub fn set_name(&self, entity: &mut MuEntity, name: MuName) {
let id = entity.id();
entity.set_name(name);
let mut map = self.id_name_map.write().unwrap();
map.insert(id, name);
let mut map2 = self.name_id_map.write().unwrap();
map2.insert(name, id);
}
pub fn id_of(&self, name: MuName) -> MuID {
let map = self.name_id_map.read().unwrap();
*map.get(name).unwrap()
}
pub fn name_of(&self, id: MuID) -> MuName {
let map = self.id_name_map.read().unwrap();
map.get(&id).unwrap()
}
pub fn declare_const(&self, id: MuID, ty: P<MuType>, val: Constant) -> P<Value> { pub fn declare_const(&self, id: MuID, ty: P<MuType>, val: Constant) -> P<Value> {
let mut constants = self.constants.write().unwrap(); let mut constants = self.constants.write().unwrap();
debug_assert!(!constants.contains_key(&id)); debug_assert!(!constants.contains_key(&id));
...@@ -113,24 +135,24 @@ impl <'a> VM { ...@@ -113,24 +135,24 @@ impl <'a> VM {
ty ty
} }
pub fn declare_func_sig(&self, sig_name: MuName, ret_tys: Vec<P<MuType>>, arg_tys: Vec<P<MuType>>) -> P<MuFuncSig> { 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(); let mut func_sigs = self.func_sigs.write().unwrap();
debug_assert!(!func_sigs.contains_key(&sig_name)); debug_assert!(!func_sigs.contains_key(&id));
let ret = P(MuFuncSig{ret_tys: ret_tys, arg_tys: arg_tys}); let ret = P(MuFuncSig{id: id, name: None, ret_tys: ret_tys, arg_tys: arg_tys});
func_sigs.insert(sig_name, ret.clone()); func_sigs.insert(id, ret.clone());
ret ret
} }
pub fn declare_func (&self, func: MuFunction) { pub fn declare_func (&self, func: MuFunction) {
info!("declare function {:?}", func); info!("declare function {}", func);
let mut funcs = self.funcs.write().unwrap(); let mut funcs = self.funcs.write().unwrap();
funcs.insert(func.id, RefCell::new(func)); funcs.insert(func.id, RefCell::new(func));
} }
pub fn define_func_version (&self, func_ver: MuFunctionVersion) { pub fn define_func_version (&self, func_ver: MuFunctionVersion) {
info!("define function {} with version {}", func_ver.func_id, func_ver.id); info!("define function version {}", func_ver);
// record this version // record this version
let func_ver_key = (func_ver.func_id, func_ver.id); let func_ver_key = (func_ver.func_id, func_ver.id);
{ {
...@@ -158,7 +180,8 @@ impl <'a> VM { ...@@ -158,7 +180,8 @@ impl <'a> VM {
} }
pub fn add_compiled_func (&self, func: CompiledFunction) { pub fn add_compiled_func (&self, func: CompiledFunction) {
debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_ver_id)); debug_assert!(self.funcs.read().unwrap().contains_key(&func.func_id));
debug_assert!(self.func_vers.read().unwrap().contains_key(&(func.func_id, func.func_ver_id)));
self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RefCell::new(func)); self.compiled_funcs.write().unwrap().insert(func.func_ver_id, RefCell::new(func));
} }
......
...@@ -3,6 +3,7 @@ use std::ops; ...@@ -3,6 +3,7 @@ use std::ops;
use std::collections::HashMap; use std::collections::HashMap;
pub struct CompiledFunction { pub struct CompiledFunction {
pub func_id: MuID,
pub func_ver_id: MuID, pub func_ver_id: MuID,
pub temps: HashMap<MuID, MuID>, // assumes one temperary maps to one register pub temps: HashMap<MuID, MuID>, // assumes one temperary maps to one register
pub mc: Box<MachineCode> pub mc: Box<MachineCode>
......
//mod test_pre_instsel; mod test_pre_instsel;
//mod test_instsel; mod test_instsel;
//mod test_regalloc; mod test_regalloc;
//mod test_global; //mod test_global;
...@@ -21,10 +21,11 @@ fn test_instsel_fac() { ...@@ -21,10 +21,11 @@ fn test_instsel_fac() {
Box::new(backend::inst_sel::InstructionSelection::new()) Box::new(backend::inst_sel::InstructionSelection::new())
]), vm.clone()); ]), vm.clone());
let func_id = vm.id_of("fac");
let funcs = vm.funcs().read().unwrap(); let funcs = vm.funcs().read().unwrap();
let factorial_func = funcs.get("fac").unwrap().borrow(); let func = funcs.get(&func_id).unwrap().borrow();
let func_vers = vm.func_vers().read().unwrap(); let func_vers = vm.func_vers().read().unwrap();
let mut factorial_func_ver = func_vers.get(&(factorial_func.fn_name, factorial_func.cur_ver.unwrap())).unwrap().borrow_mut(); let mut func_ver = func_vers.get(&(func.id, func.cur_ver.unwrap())).unwrap().borrow_mut();
compiler.compile(&mut factorial_func_ver); compiler.compile(&mut func_ver);
} }
...@@ -19,20 +19,21 @@ fn test_use_count() { ...@@ -19,20 +19,21 @@ fn test_use_count() {
vec![Box::new(passes::DefUse::new())] vec![Box::new(passes::DefUse::new())]
), vm.clone()); ), vm.clone());
let func_id = vm.id_of("fac");
let funcs = vm.funcs().read().unwrap(); let funcs = vm.funcs().read().unwrap();
let factorial_func = funcs.get("fac").unwrap().borrow(); let func = funcs.get(&func_id).unwrap().borrow();
let func_vers = vm.func_vers().read().unwrap(); let func_vers = vm.func_vers().read().unwrap();
let mut factorial_func_ver = func_vers.get(&(factorial_func.fn_name, factorial_func.cur_ver.unwrap())).unwrap().borrow_mut(); let mut func_ver = func_vers.get(&(func.id, func.cur_ver.unwrap())).unwrap().borrow_mut();
compiler.compile(&mut factorial_func_ver); compiler.compile(&mut func_ver);
assert!(factorial_func_ver.context.get_value_by_tag("blk_0_n_3").unwrap().use_count.get() == 2, "blk_0_n_3 use should be 2"); assert!(func_ver.context.get_value_by_tag("blk_0_n_3").unwrap().use_count.get() == 2, "blk_0_n_3 use should be 2");
assert!(factorial_func_ver.context.get_value_by_tag("blk_0_v48").unwrap().use_count.get() == 1, "blk_0_v48 use should be 1"); assert!(func_ver.context.get_value_by_tag("blk_0_v48").unwrap().use_count.get() == 1, "blk_0_v48 use should be 1");
assert!(factorial_func_ver.context.get_value_by_tag("blk_2_v53").unwrap().use_count.get() == 1, "blk_2_v53 use should be 1"); assert!(func_ver.context.get_value_by_tag("blk_2_v53").unwrap().use_count.get() == 1, "blk_2_v53 use should be 1");
assert!(factorial_func_ver.context.get_value_by_tag("blk_1_n_3").unwrap().use_count.get() == 2, "blk_1_n_3 use should be 2"); assert!(func_ver.context.get_value_by_tag("blk_1_n_3").unwrap().use_count.get() == 2, "blk_1_n_3 use should be 2");
assert!(factorial_func_ver.context.get_value_by_tag("blk_1_v50").unwrap().use_count.get() == 1, "blk_1_v50 use should be 1"); assert!(func_ver.context.get_value_by_tag("blk_1_v50").unwrap().use_count.get() == 1, "blk_1_v50 use should be 1");
assert!(factorial_func_ver.context.get_value_by_tag("blk_1_v51").unwrap().use_count.get() == 1, "blk_1_v51 use should be 1"); assert!(func_ver.context.get_value_by_tag("blk_1_v51").unwrap().use_count.get() == 1, "blk_1_v51 use should be 1");
assert!(factorial_func_ver.context.get_value_by_tag("blk_1_v52").unwrap().use_count.get() == 1, "blk_1_v52 use should be 1"); assert!(func_ver.context.get_value_by_tag("blk_1_v52").unwrap().use_count.get() == 1, "blk_1_v52 use should be 1");
} }
#[test] #[test]
...@@ -45,12 +46,13 @@ fn test_build_tree() { ...@@ -45,12 +46,13 @@ fn test_build_tree() {
Box::new(passes::TreeGen::new())] Box::new(passes::TreeGen::new())]
), vm.clone()); ), vm.clone());
let func_id = vm.id_of("fac");
let funcs = vm.funcs().read().unwrap(); let funcs = vm.funcs().read().unwrap();
let factorial_func = funcs.get("fac").unwrap().borrow(); let func = funcs.get(&func_id).unwrap().borrow();
let func_vers = vm.func_vers().read().unwrap(); let func_vers = vm.func_vers().read().unwrap();
let mut factorial_func_ver = func_vers.get(&(factorial_func.fn_name, factorial_func.cur_ver.unwrap())).unwrap().borrow_mut(); let mut func_ver = func_vers.get(&(func.id, func.cur_ver.unwrap())).unwrap().borrow_mut();
compiler.compile(&mut factorial_func_ver); compiler.compile(&mut func_ver);
} }
#[test] #[test]
...@@ -64,30 +66,33 @@ fn test_cfa_factorial() { ...@@ -64,30 +66,33 @@ fn test_cfa_factorial() {
Box::new(passes::ControlFlowAnalysis::new()) Box::new(passes::ControlFlowAnalysis::new())
]), vm.clone()); ]), vm.clone());
let func_id = vm.id_of("fac");
let funcs = vm.funcs().read().unwrap(); let funcs = vm.funcs().read().unwrap();
let factorial_func = funcs.get("fac").unwrap().borrow(); let func = funcs.get(&func_id).unwrap().borrow();
let func_vers = vm.func_vers().read().unwrap(); let func_vers = vm.func_vers().read().unwrap();
let mut factorial_func_ver = func_vers.get(&(factorial_func.fn_name, factorial_func.cur_ver.unwrap())).unwrap().borrow_mut(); let mut func_ver = func_vers.get(&(func.id, func.cur_ver.unwrap())).unwrap().borrow_mut();
compiler.compile(&mut factorial_func_ver); compiler.compile(&mut func_ver);
// assert cfa // assert cfa
let content = factorial_func_ver.content.as_ref().unwrap(); let content = func_ver.content.as_ref().unwrap();
// blk_0: preds=[], succs=[blk_2, blk_1] // blk_0: preds=[], succs=[blk_2, blk_1]
let blk_0 = content.get_block("blk_0"); let (blk_0_id, blk_1_id, blk_2_id) = (vm.id_of("blk_0"), vm.id_of("blk_1"), vm.id_of("blk_2"));
let blk_0 = content.get_block(blk_0_id);
assert_vector_no_order(&blk_0.control_flow.preds, &vec![]); assert_vector_no_order(&blk_0.control_flow.preds, &vec![]);
assert_vector_no_order(&block_edges_into_vec(&blk_0.control_flow.succs), &vec!["blk_2", "blk_1"]); assert_vector_no_order(&block_edges_into_vec(&blk_0.control_flow.succs), &vec![blk_2_id, blk_1_id]);
// blk_2: preds=[blk_0, blk_1], succs=[] // blk_2: preds=[blk_0, blk_1], succs=[]
let blk_2 = content.get_block("blk_2"); let blk_2 = content.get_block(blk_2_id);
assert_vector_no_order(&blk_2.control_flow.preds, &vec!["blk_0", "blk_1"]); assert_vector_no_order(&blk_2.control_flow.preds, &vec![blk_0_id, blk_1_id]);
assert_vector_no_order(&block_edges_into_vec(&blk_2.control_flow.succs), &vec![]); assert_vector_no_order(&block_edges_into_vec(&blk_2.control_flow.succs), &vec![]);
// blk_1: preds=[blk_0], succs=[blk_2] // blk_1: preds=[blk_0], succs=[blk_2]
let blk_1 = content.get_block("blk_1"); let blk_1 = content.get_block(blk_1_id);
assert_vector_no_order(&blk_1.control_flow.preds, &vec!["blk_0"]); assert_vector_no_order(&blk_1.control_flow.preds, &vec![blk_0_id]);
assert_vector_no_order(&block_edges_into_vec(&blk_1.control_flow.succs), &vec!["blk_2"]); assert_vector_no_order(&block_edges_into_vec(&blk_1.control_flow.succs), &vec![blk_2_id]);
}