Commit b20cc1a4 authored by qinsoon's avatar qinsoon

[wip] fixing tests

parent 116e0e2d
......@@ -9,6 +9,7 @@ use std::collections::HashMap;
use std::fmt;
use std::default;
use std::cell::Cell;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
pub type WPID = usize;
pub type MuID = usize;
......@@ -17,11 +18,40 @@ pub type Address = usize; // TODO: replace this with Address(usize)
pub type OpIndex = usize;
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;
lazy_static! {
pub static ref MACHINE_ID : AtomicUsize = {
let a = ATOMIC_USIZE_INIT;
a.store(MACHINE_ID_START, Ordering::SeqCst);
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)]
pub struct MuFunction {
......@@ -560,8 +590,8 @@ pub enum Constant {
Float(f32),
Double(f64),
IRef(Address),
FuncRef(MuName),
UFuncRef(MuName),
FuncRef(MuID),
UFuncRef(MuID),
Vector(Vec<Constant>),
}
......@@ -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 {
let mut ret = String::new();
for i in 0..vec.len() {
......
......@@ -327,6 +327,8 @@ macro_rules! is_type (
#[derive(Clone, PartialEq, Eq, Debug, Hash)]
pub struct MuFuncSig {
pub id: MuID,
pub name: Option<MuName>,
pub ret_tys : Vec<P<MuType>>,
pub arg_tys: Vec<P<MuType>>
}
......
......@@ -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::fs::File;
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 cf = compiled_funcs.get(&func.id).unwrap().borrow();
let cf = compiled_funcs.get(&fv.id).unwrap().borrow();
let code = cf.mc.emit();
......
......@@ -159,9 +159,15 @@ impl <'a> InstructionSelection {
// check direct call or indirect
if self.match_funcref_const(func) {
let target = self.emit_get_funcref_const(func);
self.backend.emit_call_near_rel32(target);
let target_id = self.emit_get_funcref_const(func);
let funcs = vm.funcs().read().unwrap();
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) {
let target = self.emit_ireg(func, cur_func, vm);
......@@ -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 {
TreeNode_::Value(ref pv) => {
match pv.v {
Value_::Constant(Constant::FuncRef(tag))
| Value_::Constant(Constant::UFuncRef(tag)) => tag,
Value_::Constant(Constant::FuncRef(id))
| Value_::Constant(Constant::UFuncRef(id)) => id,
_ => panic!("expected a (u)funcref const")
}
},
......@@ -782,13 +788,15 @@ impl CompilerPass for InstructionSelection {
}
#[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());
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)
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;
self.emit_common_prologue(args);
}
......@@ -824,6 +832,7 @@ impl CompilerPass for InstructionSelection {
let mc = self.backend.finish_code();
let compiled_func = CompiledFunction {
func_id: func.func_id,
func_ver_id: func.id,
temps: HashMap::new(),
mc: mc
......
......@@ -17,52 +17,58 @@ use ast::types::*;
use compiler::backend::RegGroup;
macro_rules! GPR {
($name: expr, $id: expr) => {
P(Value {
id: $id,
name: Some($name),
ty: GPR_TY.clone(),
v: Value_::SSAVar($id)
})
($name: expr) => {
{
let id = new_machine_id();
P(Value {
id: id,
name: Some($name),
ty: GPR_TY.clone(),
v: Value_::SSAVar(id)
})
}
};
}
macro_rules! FPR {
($name: expr, $id: expr) => {
P(Value {
id: $id,
name: Some($name),
ty: FPR_TY.clone(),
v: Value_::SSAVar($id)
})
($name: expr) => {
{
let id = new_machine_id();
P(Value {
id: id,
name: Some($name),
ty: FPR_TY.clone(),
v: Value_::SSAVar(id)
})
}
};
}
lazy_static! {
pub static ref GPR_TY : P<MuType> = P(MuType::new(INTERNAL_ID_START + 0, MuType_::int(64)));
pub static ref FPR_TY : P<MuType> = P(MuType::new(INTERNAL_ID_START + 1, MuType_::double()));
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(new_internal_id(), MuType_::double()));
}
// put into several segments to avoid 'recursion limit reached' error
lazy_static! {
pub static ref RAX : P<Value> = GPR!("rax", 0);
pub static ref RCX : P<Value> = GPR!("rcx", 1);
pub static ref RDX : P<Value> = GPR!("rdx", 2);
pub static ref RBX : P<Value> = GPR!("rbx", 3);
pub static ref RSP : P<Value> = GPR!("rsp", 4);
pub static ref RBP : P<Value> = GPR!("rbp", 5);
pub static ref RSI : P<Value> = GPR!("rsi", 6);
pub static ref RDI : P<Value> = GPR!("rdi", 7);
pub static ref R8 : P<Value> = GPR!("r8", 8);
pub static ref R9 : P<Value> = GPR!("r9", 9);
pub static ref R10 : P<Value> = GPR!("r10", 10);
pub static ref R11 : P<Value> = GPR!("r11", 11);
pub static ref R12 : P<Value> = GPR!("r12", 12);
pub static ref R13 : P<Value> = GPR!("r13", 13);
pub static ref R14 : P<Value> = GPR!("r14", 14);
pub static ref R15 : P<Value> = GPR!("r15", 15);
pub static ref RAX : P<Value> = GPR!("rax");
pub static ref RCX : P<Value> = GPR!("rcx");
pub static ref RDX : P<Value> = GPR!("rdx");
pub static ref RBX : P<Value> = GPR!("rbx");
pub static ref RSP : P<Value> = GPR!("rsp");
pub static ref RBP : P<Value> = GPR!("rbp");
pub static ref RSI : P<Value> = GPR!("rsi");
pub static ref RDI : P<Value> = GPR!("rdi");
pub static ref R8 : P<Value> = GPR!("r8");
pub static ref R9 : P<Value> = GPR!("r9");
pub static ref R10 : P<Value> = GPR!("r10");
pub static ref R11 : P<Value> = GPR!("r11");
pub static ref R12 : P<Value> = GPR!("r12");
pub static ref R13 : P<Value> = GPR!("r13");
pub static ref R14 : P<Value> = GPR!("r14");
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] = [
RAX.clone(),
......@@ -108,22 +114,22 @@ lazy_static! {
}
lazy_static!{
pub static ref XMM0 : P<Value> = FPR!("xmm0", 16);
pub static ref XMM1 : P<Value> = FPR!("xmm1", 17);
pub static ref XMM2 : P<Value> = FPR!("xmm2", 18);
pub static ref XMM3 : P<Value> = FPR!("xmm3", 19);
pub static ref XMM4 : P<Value> = FPR!("xmm4", 20);
pub static ref XMM5 : P<Value> = FPR!("xmm5", 21);
pub static ref XMM6 : P<Value> = FPR!("xmm6", 22);
pub static ref XMM7 : P<Value> = FPR!("xmm7", 23);
pub static ref XMM8 : P<Value> = FPR!("xmm8", 24);
pub static ref XMM9 : P<Value> = FPR!("xmm9", 25);
pub static ref XMM10 : P<Value> = FPR!("xmm10",26);
pub static ref XMM11 : P<Value> = FPR!("xmm11",27);
pub static ref XMM12 : P<Value> = FPR!("xmm12",28);
pub static ref XMM13 : P<Value> = FPR!("xmm13",29);
pub static ref XMM14 : P<Value> = FPR!("xmm14",30);
pub static ref XMM15 : P<Value> = FPR!("xmm15",31);
pub static ref XMM0 : P<Value> = FPR!("xmm0");
pub static ref XMM1 : P<Value> = FPR!("xmm1");
pub static ref XMM2 : P<Value> = FPR!("xmm2");
pub static ref XMM3 : P<Value> = FPR!("xmm3");
pub static ref XMM4 : P<Value> = FPR!("xmm4");
pub static ref XMM5 : P<Value> = FPR!("xmm5");
pub static ref XMM6 : P<Value> = FPR!("xmm6");
pub static ref XMM7 : P<Value> = FPR!("xmm7");
pub static ref XMM8 : P<Value> = FPR!("xmm8");
pub static ref XMM9 : P<Value> = FPR!("xmm9");
pub static ref XMM10 : P<Value> = FPR!("xmm10");
pub static ref XMM11 : P<Value> = FPR!("xmm11");
pub static ref XMM12 : P<Value> = FPR!("xmm12");
pub static ref XMM13 : P<Value> = FPR!("xmm13");
pub static ref XMM14 : P<Value> = FPR!("xmm14");
pub static ref XMM15 : P<Value> = FPR!("xmm15");
pub static ref RETURN_FPRs : [P<Value>; 2] = [
XMM0.clone(),
......
......@@ -421,29 +421,4 @@ impl MuCtxInternal {
vm: vm
}
}
}
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
}
\ No newline at end of file
......@@ -28,7 +28,8 @@ pub struct VM {
constants: 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>>>,
funcs: RwLock<HashMap<MuID, RefCell<MuFunction>>>,
......@@ -78,6 +79,27 @@ impl <'a> VM {
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> {
let mut constants = self.constants.write().unwrap();
debug_assert!(!constants.contains_key(&id));
......@@ -113,24 +135,24 @@ impl <'a> VM {
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();
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});
func_sigs.insert(sig_name, ret.clone());
let ret = P(MuFuncSig{id: id, name: None, ret_tys: ret_tys, arg_tys: arg_tys});
func_sigs.insert(id, ret.clone());
ret
}
pub fn declare_func (&self, func: MuFunction) {
info!("declare function {:?}", func);
info!("declare function {}", func);
let mut funcs = self.funcs.write().unwrap();
funcs.insert(func.id, RefCell::new(func));
}
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
let func_ver_key = (func_ver.func_id, func_ver.id);
{
......@@ -158,7 +180,8 @@ impl <'a> VM {
}
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));
}
......
......@@ -3,6 +3,7 @@ use std::ops;
use std::collections::HashMap;
pub struct CompiledFunction {
pub func_id: MuID,
pub func_ver_id: MuID,
pub temps: HashMap<MuID, MuID>, // assumes one temperary maps to one register
pub mc: Box<MachineCode>
......
//mod test_pre_instsel;
//mod test_instsel;
//mod test_regalloc;
mod test_pre_instsel;
mod test_instsel;
mod test_regalloc;
//mod test_global;
......@@ -21,10 +21,11 @@ fn test_instsel_fac() {
Box::new(backend::inst_sel::InstructionSelection::new())
]), vm.clone());
let func_id = vm.id_of("fac");
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 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() {
vec![Box::new(passes::DefUse::new())]
), vm.clone());
let func_id = vm.id_of("fac");
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 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!(factorial_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!(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!(factorial_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!(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_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_v48").unwrap().use_count.get() == 1, "blk_0_v48 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!(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_v50").unwrap().use_count.get() == 1, "blk_1_v50 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!(func_ver.context.get_value_by_tag("blk_1_v52").unwrap().use_count.get() == 1, "blk_1_v52 use should be 1");
}
#[test]
......@@ -45,12 +46,13 @@ fn test_build_tree() {
Box::new(passes::TreeGen::new())]
), vm.clone());
let func_id = vm.id_of("fac");
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 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]
......@@ -64,30 +66,33 @@ fn test_cfa_factorial() {
Box::new(passes::ControlFlowAnalysis::new())
]), vm.clone());
let func_id = vm.id_of("fac");
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 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
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]
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(&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=[]
let blk_2 = content.get_block("blk_2");
assert_vector_no_order(&blk_2.control_flow.preds, &vec!["blk_0", "blk_1"]);
let blk_2 = content.get_block(blk_2_id);
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![]);
// blk_1: preds=[blk_0], succs=[blk_2]
let blk_1 = content.get_block("blk_1");
assert_vector_no_order(&blk_1.control_flow.preds, &vec!["blk_0"]);
assert_vector_no_order(&block_edges_into_vec(&blk_1.control_flow.succs), &vec!["blk_2"]);
let blk_1 = content.get_block(blk_1_id);
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_id]);
}
#[test]
......@@ -101,33 +106,38 @@ fn test_cfa_sum() {
Box::new(passes::ControlFlowAnalysis::new())
]), vm.clone());
let func_id = vm.id_of("sum");
let funcs = vm.funcs().read().unwrap();
let sum_func = funcs.get("sum").unwrap().borrow();
let func = funcs.get(&func_id).unwrap().borrow();
let func_vers = vm.func_vers().read().unwrap();
let mut sum_func_ver = func_vers.get(&(sum_func.fn_name, sum_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 sum_func_ver);
compiler.compile(&mut func_ver);
// assert cfa
let content = sum_func_ver.content.as_ref().unwrap();
let content = func_ver.content.as_ref().unwrap();
let entry_id = vm.id_of("entry");
let head_id = vm.id_of("head");
let ret_id = vm.id_of("ret");
// entry: preds=[], succs=[head]
let entry = content.get_block("entry");
let entry = content.get_block(entry_id);
assert_vector_no_order(&entry.control_flow.preds, &vec![]);
assert_vector_no_order(&block_edges_into_vec(&entry.control_flow.succs), &vec!["head"]);
assert_vector_no_order(&block_edges_into_vec(&entry.control_flow.succs), &vec![head_id]);
// head: preds=[entry, head], succs=[head, ret]
let head = content.get_block("head");
assert_vector_no_order(&head.control_flow.preds, &vec!["entry", "head"]);
assert_vector_no_order(&block_edges_into_vec(&head.control_flow.succs), &vec!["ret", "head"]);
let head = content.get_block(head_id);
assert_vector_no_order(&head.control_flow.preds, &vec![entry_id, head_id]);
assert_vector_no_order(&block_edges_into_vec(&head.control_flow.succs), &vec![ret_id, head_id]);
// ret: preds=[head], succs=[]
let ret = content.get_block("ret");
assert_vector_no_order(&ret.control_flow.preds, &vec!["head"]);
let ret = content.get_block(ret_id);
assert_vector_no_order(&ret.control_flow.preds, &vec![head_id]);
assert_vector_no_order(&block_edges_into_vec(&ret.control_flow.succs), &vec![]);
}
fn block_edges_into_vec(edges: &Vec<BlockEdge>) -> Vec<&str> {
fn block_edges_into_vec(edges: &Vec<BlockEdge>) -> Vec<MuID> {
let mut ret = vec![];
for edge in edges {
ret.push(edge.target);
......@@ -147,14 +157,15 @@ fn test_trace_factorial() {
Box::new(passes::TraceGen::new())
]), vm.clone());
let func_id = vm.id_of("fac");
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 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_vector_ordered(factorial_func_ver.block_trace.as_ref().unwrap(), &vec!["blk_0", "blk_1", "blk_2"]);
assert_vector_ordered(func_ver.block_trace.as_ref().unwrap(), &vec![vm.id_of("blk_0"), vm.id_of("blk_1"), vm.id_of("blk_2")]);
}
#[test]
......@@ -169,12 +180,13 @@ fn test_trace_sum() {
Box::new(passes::TraceGen::new())
]), vm.clone());
let func_id = vm.id_of("sum");
let funcs = vm.funcs().read().unwrap();
let sum_func = funcs.get("sum").unwrap().borrow();
let func = funcs.get(&func_id).unwrap().borrow();
let func_vers = vm.func_vers().read().unwrap();
let mut sum_func_ver = func_vers.get(&(sum_func.fn_name, sum_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 sum_func_ver);
compiler.compile(&mut func_ver);
assert_vector_ordered(sum_func_ver.block_trace.as_ref().unwrap(), &vec!["entry", "head", "ret"]);
assert_vector_ordered(func_ver.block_trace.as_ref().unwrap(), &vec![vm.id_of("entry"), vm.id_of("head"), vm.id_of("ret")]);
}
......@@ -23,20 +23,21 @@ fn test_ir_liveness_fac() {
Box::new(backend::inst_sel::InstructionSelection::new()),
]), vm.clone());
let func_id = vm.id_of("fac");
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 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);