WARNING! Access to this system is limited to authorised users only.
Unauthorised users may be subject to prosecution.
Unauthorised access to this system is a criminal offence under Australian law (Federal Crimes Act 1914 Part VIA)
It is a criminal offence to:
(1) Obtain access to data without authority. -Penalty 2 years imprisonment.
(2) Damage, delete, alter or insert data without authority. -Penalty 10 years imprisonment.
User activity is monitored and recorded. Anyone using this system expressly consents to such monitoring and recording.

To protect your data, the CISO officer has suggested users to enable 2FA as soon as possible.
Currently 2.6% of users enabled 2FA.

Commit b20cc1a4 authored by qinsoon's avatar qinsoon
Browse files

[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();