Commit be476b0d authored by qinsoon's avatar qinsoon

restructured tests dir. Added logger.

parent 06d5ccdc
......@@ -5,4 +5,6 @@ version = "0.0.1"
authors = [ "Your name <you@example.com>" ]
[dependencies]
lazy_static = "0.1.15"
\ No newline at end of file
lazy_static = "0.1.15"
log = "0.3.5"
simple_logger = "0.4.0"
\ No newline at end of file
......@@ -9,20 +9,20 @@ pub type MuID = usize;
pub type MuTag = &'static str;
pub type Address = usize; // TODO: replace this with Address(usize)
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct SSAVar {
pub id: MuID,
pub tag: MuTag,
pub ty: P<MuType_>
}
#[derive(Clone)]
#[derive(Clone, Debug)]
pub enum Value {
SSAVar(SSAVar),
Constant(MuConstant)
}
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
pub enum MemoryOrder {
NotAtomic,
Relaxed,
......@@ -33,23 +33,25 @@ pub enum MemoryOrder {
SeqCst
}
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
pub enum CallConvention {
Mu,
Foreign(ForeignFFI)
}
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
pub enum ForeignFFI {
C
}
#[derive(Debug)]
pub struct CallData {
pub func: P<SSAVar>,
pub args: Vec<P<Value>>,
pub convention: CallConvention
}
#[derive(Debug)]
pub struct Block {
label: MuTag,
content: Option<BlockContent>
......@@ -65,6 +67,7 @@ impl Block {
}
}
#[derive(Debug)]
pub struct BlockContent {
pub args: Vec<P<Value>>,
pub body: Vec<Instruction>,
......@@ -72,22 +75,25 @@ pub struct BlockContent {
pub keepalives: Option<Vec<P<SSAVar>>>
}
#[derive(Debug)]
pub struct ResumptionData {
pub normal_dest: Destination,
pub exn_dest: Destination
}
#[derive(Debug)]
pub enum DestArg {
Normal(P<Value>),
Freshbound(usize)
}
#[derive(Debug)]
pub struct Destination {
pub target: MuTag,
pub args: Vec<DestArg>
}
#[derive(Clone)]
#[derive(Clone, Debug)]
pub enum Constant {
Int(usize, usize),
IRef(P<MuType_>, Address),
......@@ -98,6 +104,7 @@ pub enum Constant {
UFuncRefV(Address)
}
#[derive(Debug)]
pub enum Expression {
BinOp(BinOp, P<Value>, P<Value>),
CmpOp(CmpOp, P<Value>, P<Value>),
......@@ -211,6 +218,7 @@ pub enum Expression {
// }
}
#[derive(Debug)]
pub enum Instruction {
Assign{
left: Vec<P<Value>>,
......@@ -220,6 +228,7 @@ pub enum Instruction {
Fence(MemoryOrder),
}
#[derive(Debug)]
pub enum Terminal {
Return(Vec<P<Value>>),
ThreadExit,
......@@ -261,17 +270,18 @@ pub enum Terminal {
branches: Vec<(P<Constant>, Destination)>
},
ExnInstruction{
inner: Expression,
inner: Instruction,
resume: ResumptionData
}
}
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct MuConstant{
pub ty: P<MuType_>,
pub val: Constant
}
#[derive(Debug)]
pub struct MuFunction {
pub fn_name: MuTag,
pub sig: P<MuFuncSig>,
......@@ -279,7 +289,7 @@ pub struct MuFunction {
pub blocks: Vec<(MuTag, Block)>
}
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
pub enum BinOp {
// Int(n) BinOp Int(n) -> Int(n)
Add,
......@@ -305,7 +315,7 @@ pub enum BinOp {
FRem
}
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
pub enum CmpOp {
// for Int comparison
EQ,
......@@ -338,7 +348,7 @@ pub enum CmpOp {
FUNO
}
#[derive(Copy, Clone)]
#[derive(Copy, Clone, Debug)]
pub enum AtomicRMWOp {
XCHG,
ADD,
......
......@@ -13,6 +13,13 @@ impl TreeGenerationPass {
impl CompilerPass for TreeGenerationPass {
fn execute(&mut self, vm: &VMContext, func: &mut MuFunction) {
debug!("Generating Tree for {:?}", func.fn_name);
for entry in func.blocks.iter_mut() {
let label : MuTag = entry.0;
let ref block : &mut Block = &mut entry.1;
debug!(" block: {:?}", label);
}
}
}
\ No newline at end of file
#[macro_use]
extern crate lazy_static;
#[macro_use]
extern crate log;
pub mod ast;
pub mod vm;
......
......@@ -4,11 +4,13 @@ use ast::ptr::P;
use ast::ir::*;
use ast::types::*;
use std::cell::RefCell;
pub struct VMContext {
constants: HashMap<MuTag, P<Value>>,
types: HashMap<MuTag, P<MuType_>>,
func_sigs: HashMap<MuTag, P<MuFuncSig>>,
funcs: HashMap<MuTag, MuFunction>
funcs: HashMap<MuTag, RefCell<MuFunction>>
}
impl VMContext {
......@@ -51,6 +53,10 @@ impl VMContext {
debug_assert!(!self.funcs.contains_key(fn_name));
let ret = MuFunction{fn_name: fn_name, sig: sig, entry: entry, blocks: blocks};
self.funcs.insert(fn_name, ret);
}
self.funcs.insert(fn_name, RefCell::new(ret));
}
pub fn get_func(&self, fn_name: MuTag) -> Option<&RefCell<MuFunction>> {
self.funcs.get(fn_name)
}
}
\ No newline at end of file
mod test_ir;
mod test_compiler;
\ No newline at end of file
mod test_tree_gen;
\ No newline at end of file
extern crate mu;
extern crate log;
extern crate simple_logger;
use test_ir::test_ir::factorial;
use self::mu::compiler::*;
use self::mu::vm::context::VMContext;
#[test]
fn test_tree_gen() {
simple_logger::init_with_level(log::LogLevel::Trace).unwrap();
let vm_context : VMContext = factorial();
let compiler = Compiler::new(CompilerPolicy::default());
let mut factorial_func = {
vm_context.get_func("fac").unwrap().borrow_mut()
};
compiler.compile(&vm_context, &mut factorial_func);
}
\ No newline at end of file
extern crate mu;
#[cfg(test)]
mod test_ir {
use mu::ast::types::*;
use mu::ast::ir::*;
use mu::ast::ptr::*;
use mu::vm::context::*;
#[test]
#[allow(unused_variables)]
fn test_factorial() {
let vm = factorial();
}
#[allow(unused_variables)]
fn factorial() -> VMContext {
let mut vm = VMContext::new();
// .typedef @int_64 = int<64>
// .typedef @int_1 = int<1>
// .typedef @float = float
// .typedef @double = double
// .typedef @void = void
// .typedef @int_8 = int<8>
// .typedef @int_32 = int<32>
let type_def_int64 = vm.declare_type("int_64", P(MuType_::int(64)));
let type_def_int1 = vm.declare_type("int_1", P(MuType_::int(1)));
let type_def_float = vm.declare_type("float", P(MuType_::float()));
let type_def_double = vm.declare_type("double", P(MuType_::double()));
let type_def_void = vm.declare_type("void", P(MuType_::void()));
let type_def_int8 = vm.declare_type("int8", P(MuType_::int(8)));
let type_def_int32 = vm.declare_type("int32", P(MuType_::int(32)));
// .const @int_64_1 <@int_64> = 1
let const_def_int64_1 = vm.declare_const("int64_1", type_def_int64.clone(), Constant::Int(64, 1));
// .funcsig @fac_sig = (@int_64) -> (@int_64)
let fac_sig = vm.declare_func_sig("fac_sig", vec![type_def_int64.clone()], vec![type_def_int64.clone()]);
// .funcdef @fac VERSION @fac_v1 <@fac_sig>
let fac_func_ref = P(MuType_::funcref(fac_sig.clone()));
// %blk_0(<@int_64> %n_3):
let mut blk_0 = Block::new("blk_0");
let blk_0_n_3 = P(Value::SSAVar(SSAVar{id: 0, tag: "n_3", ty: type_def_int64.clone()}));
// %v48 = EQ <@int_64> %n_3 @int_64_1
let blk_0_v48 = P(Value::SSAVar(SSAVar{id: 1, tag: "v48", ty: type_def_int64.clone()}));
let blk_0_v48_expr = Expression::CmpOp(
CmpOp::EQ,
blk_0_n_3.clone(),
const_def_int64_1.clone()
);
let blk_0_inst0 = Instruction::Assign{left: vec![blk_0_v48.clone()], right: blk_0_v48_expr};
// BRANCH2 %v48 %blk_2(@int_64_1) %blk_1(%n_3)
let blk_0_term = Terminal::Branch2{
cond: blk_0_v48.clone(),
true_dest: Destination {
target: "blk_2",
args: vec![DestArg::Normal(const_def_int64_1.clone())]
},
false_dest: Destination {
target: "blk_1",
args: vec![DestArg::Normal(blk_0_n_3.clone())]
}
};
let blk_0_content = BlockContent {
args: vec![blk_0_n_3.clone()],
body: vec![blk_0_inst0],
exit: blk_0_term,
keepalives: None
};
blk_0.set_content(blk_0_content);
// %blk_2(<@int_64> %v53):
let mut blk_2 = Block::new("blk_2");
let blk_2_v53 = P(Value::SSAVar(SSAVar{id: 2, tag: "v53", ty: type_def_int64.clone()}));
// RET %v53
let blk_2_term = Terminal::Return(vec![blk_2_v53.clone()]);
let blk_2_content = BlockContent {
args: vec![blk_2_v53.clone()],
body: vec![],
exit: blk_2_term,
keepalives: None
};
blk_2.set_content(blk_2_content);
// %blk_1(<@int_64> %n_3):
let mut blk_1 = Block::new("blk_1");
let blk_1_n_3 = P(Value::SSAVar(SSAVar{id: 3, tag: "n_3", ty: type_def_int64.clone()}));
// %v50 = SUB <@int_64> %n_3 @int_64_1
let blk_1_v50 = P(Value::SSAVar(SSAVar{id: 4, tag: "v50", ty: type_def_int64.clone()}));
let blk_1_v50_expr = Expression::BinOp(
BinOp::Sub,
blk_1_n_3.clone(),
const_def_int64_1.clone()
);
let blk_1_inst0 = Instruction::Assign{left: vec![blk_1_v50.clone()], right: blk_1_v50_expr};
// %v51 = CALL <@fac_sig> @fac (%v50)
let blk_1_v51 = P(Value::SSAVar(SSAVar{id: 5, tag: "v51", ty: type_def_int64.clone()}));
let blk_1_term = Terminal::Call {
data: CallData {
func: P(SSAVar{id: 6, tag: "fac", ty: fac_func_ref.clone()}),
args: vec![blk_1_v50.clone()],
convention: CallConvention::Mu
},
resume: ResumptionData {
normal_dest: Destination {
target: "blk_1_cont",
args: vec![DestArg::Normal(blk_1_n_3.clone()), DestArg::Freshbound(0)]
},
exn_dest: Destination {
target: "blk_1_cont",
args: vec![DestArg::Normal(blk_1_n_3.clone()), DestArg::Freshbound(0)]
}
}
};
let blk_1_content = BlockContent {
args: vec![blk_1_n_3.clone()],
body: vec![blk_1_inst0],
exit: blk_1_term,
keepalives: None
};
blk_1.set_content(blk_1_content);
// %blk_1_cont(<@int_64> %n_3, <@int_64> %v51):
let mut blk_1_cont = Block::new("blk_1_cont");
let blk_1_cont_n_3 = P(Value::SSAVar(SSAVar{id: 7, tag: "n_3", ty: type_def_int64.clone()}));
let blk_1_cont_v51 = P(Value::SSAVar(SSAVar{id: 8, tag: "v51", ty: type_def_int64.clone()}));
// %v52 = MUL <@int_64> %n_3 %v51
let blk_1_cont_v52 = P(Value::SSAVar(SSAVar{id: 9, tag: "v52", ty: type_def_int64.clone()}));
let blk_1_cont_v52_expr = Expression::BinOp(
BinOp::Mul,
blk_1_cont_n_3.clone(),
blk_1_cont_v52.clone()
);
let blk_1_cont_inst0 = Instruction::Assign{left: vec![blk_1_cont_v52.clone()], right: blk_1_cont_v52_expr};
let blk_1_cont_term = Terminal::Branch1 (
Destination {
target: "blk_2",
args: vec![DestArg::Normal(blk_1_cont_v52.clone())]
}
);
let blk_1_cont_content = BlockContent {
args: vec![blk_1_cont_n_3.clone(), blk_1_cont_v52.clone()],
body: vec![blk_1_cont_inst0],
exit: blk_1_cont_term,
keepalives: None
};
blk_1_cont.set_content(blk_1_cont_content);
// wrap into a function
vm.declare_func("fac", fac_sig.clone(), "blk_0", vec![
("blk_0", blk_0),
("blk_1", blk_1),
("blk_1_cont", blk_1_cont),
("blk_2", blk_2)
]
);
vm
}
}
\ No newline at end of file
pub mod test_ir;
mod test_types;
\ No newline at end of file
extern crate mu;
use self::mu::ast::types::*;
use self::mu::ast::ir::*;
use self::mu::ast::ptr::*;
use self::mu::vm::context::*;
#[test]
#[allow(unused_variables)]
fn test_factorial() {
let vm = factorial();
}
#[allow(unused_variables)]
pub fn factorial() -> VMContext {
let mut vm = VMContext::new();
// .typedef @int_64 = int<64>
// .typedef @int_1 = int<1>
// .typedef @float = float
// .typedef @double = double
// .typedef @void = void
// .typedef @int_8 = int<8>
// .typedef @int_32 = int<32>
let type_def_int64 = vm.declare_type("int_64", P(MuType_::int(64)));
let type_def_int1 = vm.declare_type("int_1", P(MuType_::int(1)));
let type_def_float = vm.declare_type("float", P(MuType_::float()));
let type_def_double = vm.declare_type("double", P(MuType_::double()));
let type_def_void = vm.declare_type("void", P(MuType_::void()));
let type_def_int8 = vm.declare_type("int8", P(MuType_::int(8)));
let type_def_int32 = vm.declare_type("int32", P(MuType_::int(32)));
// .const @int_64_1 <@int_64> = 1
let const_def_int64_1 = vm.declare_const("int64_1", type_def_int64.clone(), Constant::Int(64, 1));
// .funcsig @fac_sig = (@int_64) -> (@int_64)
let fac_sig = vm.declare_func_sig("fac_sig", vec![type_def_int64.clone()], vec![type_def_int64.clone()]);
// .funcdef @fac VERSION @fac_v1 <@fac_sig>
let fac_func_ref = P(MuType_::funcref(fac_sig.clone()));
// %blk_0(<@int_64> %n_3):
let mut blk_0 = Block::new("blk_0");
let blk_0_n_3 = P(Value::SSAVar(SSAVar{id: 0, tag: "n_3", ty: type_def_int64.clone()}));
// %v48 = EQ <@int_64> %n_3 @int_64_1
let blk_0_v48 = P(Value::SSAVar(SSAVar{id: 1, tag: "v48", ty: type_def_int64.clone()}));
let blk_0_v48_expr = Expression::CmpOp(
CmpOp::EQ,
blk_0_n_3.clone(),
const_def_int64_1.clone()
);
let blk_0_inst0 = Instruction::Assign{left: vec![blk_0_v48.clone()], right: blk_0_v48_expr};
// BRANCH2 %v48 %blk_2(@int_64_1) %blk_1(%n_3)
let blk_0_term = Terminal::Branch2{
cond: blk_0_v48.clone(),
true_dest: Destination {
target: "blk_2",
args: vec![DestArg::Normal(const_def_int64_1.clone())]
},
false_dest: Destination {
target: "blk_1",
args: vec![DestArg::Normal(blk_0_n_3.clone())]
}
};
let blk_0_content = BlockContent {
args: vec![blk_0_n_3.clone()],
body: vec![blk_0_inst0],
exit: blk_0_term,
keepalives: None
};
blk_0.set_content(blk_0_content);
// %blk_2(<@int_64> %v53):
let mut blk_2 = Block::new("blk_2");
let blk_2_v53 = P(Value::SSAVar(SSAVar{id: 2, tag: "v53", ty: type_def_int64.clone()}));
// RET %v53
let blk_2_term = Terminal::Return(vec![blk_2_v53.clone()]);
let blk_2_content = BlockContent {
args: vec![blk_2_v53.clone()],
body: vec![],
exit: blk_2_term,
keepalives: None
};
blk_2.set_content(blk_2_content);
// %blk_1(<@int_64> %n_3):
let mut blk_1 = Block::new("blk_1");
let blk_1_n_3 = P(Value::SSAVar(SSAVar{id: 3, tag: "n_3", ty: type_def_int64.clone()}));
// %v50 = SUB <@int_64> %n_3 @int_64_1
let blk_1_v50 = P(Value::SSAVar(SSAVar{id: 4, tag: "v50", ty: type_def_int64.clone()}));
let blk_1_v50_expr = Expression::BinOp(
BinOp::Sub,
blk_1_n_3.clone(),
const_def_int64_1.clone()
);
let blk_1_inst0 = Instruction::Assign{left: vec![blk_1_v50.clone()], right: blk_1_v50_expr};
// %v51 = CALL <@fac_sig> @fac (%v50)
let blk_1_v51 = P(Value::SSAVar(SSAVar{id: 5, tag: "v51", ty: type_def_int64.clone()}));
let blk_1_term = Terminal::Call {
data: CallData {
func: P(SSAVar{id: 6, tag: "fac", ty: fac_func_ref.clone()}),
args: vec![blk_1_v50.clone()],
convention: CallConvention::Mu
},
resume: ResumptionData {
normal_dest: Destination {
target: "blk_1_cont",
args: vec![DestArg::Normal(blk_1_n_3.clone()), DestArg::Freshbound(0)]
},
exn_dest: Destination {
target: "blk_1_cont",
args: vec![DestArg::Normal(blk_1_n_3.clone()), DestArg::Freshbound(0)]
}
}
};
let blk_1_content = BlockContent {
args: vec![blk_1_n_3.clone()],
body: vec![blk_1_inst0],
exit: blk_1_term,
keepalives: None
};
blk_1.set_content(blk_1_content);
// %blk_1_cont(<@int_64> %n_3, <@int_64> %v51):
let mut blk_1_cont = Block::new("blk_1_cont");
let blk_1_cont_n_3 = P(Value::SSAVar(SSAVar{id: 7, tag: "n_3", ty: type_def_int64.clone()}));
let blk_1_cont_v51 = P(Value::SSAVar(SSAVar{id: 8, tag: "v51", ty: type_def_int64.clone()}));
// %v52 = MUL <@int_64> %n_3 %v51
let blk_1_cont_v52 = P(Value::SSAVar(SSAVar{id: 9, tag: "v52", ty: type_def_int64.clone()}));
let blk_1_cont_v52_expr = Expression::BinOp(
BinOp::Mul,
blk_1_cont_n_3.clone(),
blk_1_cont_v52.clone()
);
let blk_1_cont_inst0 = Instruction::Assign{left: vec![blk_1_cont_v52.clone()], right: blk_1_cont_v52_expr};
let blk_1_cont_term = Terminal::Branch1 (
Destination {
target: "blk_2",
args: vec![DestArg::Normal(blk_1_cont_v52.clone())]
}
);
let blk_1_cont_content = BlockContent {
args: vec![blk_1_cont_n_3.clone(), blk_1_cont_v52.clone()],
body: vec![blk_1_cont_inst0],
exit: blk_1_cont_term,
keepalives: None
};
blk_1_cont.set_content(blk_1_cont_content);
// wrap into a function
vm.declare_func("fac", fac_sig.clone(), "blk_0", vec![
("blk_0", blk_0),
("blk_1", blk_1),
("blk_1_cont", blk_1_cont),
("blk_2", blk_2)
]
);
vm
}
\ No newline at end of file
extern crate mu;
use self::mu::ast::ptr::*;
use self::mu::ast::types::*;
macro_rules! assert_type (
($test:expr, $expect: expr) => (
assert_eq!(format!("{:?}", $test), $expect)
)
);
macro_rules! println_type (
($test:expr) => (
println!("{:?}", $test)
)
);
/// create one of each MuType_
fn create_types() -> Vec<P<MuType_>> {
let mut types = vec![];
let t0 = MuType_::int(8);
types.push(P(t0));
let t1 = MuType_::float();
types.push(P(t1));
let t2 = MuType_::double();
types.push(P(t2));
let t3 = MuType_::muref(types[0].clone());
types.push(P(t3));
let t4 = MuType_::iref(types[0].clone());
types.push(P(t4));
let t5 = MuType_::weakref(types[0].clone());
types.push(P(t5));
let t6 = MuType_::uptr(types[0].clone());
types.push(P(t6));
let t7 = MuType_::mustruct("MyStructTag1", vec![types[0].clone(), types[1].clone()]);
types.push(P(t7));
let t8 = MuType_::array(types[0].clone(), 5);
types.push(P(t8));
let t9 = MuType_::hybrid(vec![types[7].clone(), types[1].clone()], types[0].clone());
types.push(P(t9));
let t10 = MuType_::void();
types.push(P(t10));
let t11 = MuType_::threadref();
types.push(P(t11));
let t12 = MuType_::stackref();
types.push(P(t12));
let t13 = MuType_::tagref64();
types.push(P(t13));
let t14 = MuType_::vector(types[0].clone(), 5);
types.push(P(t14));
let sig = P(MuFuncSig{ret_tys: vec![types[10].clone()], arg_tys: vec![types[0].clone(), types[0].clone()]});
let t15 = MuType_::funcref(sig.clone());
types.push(P(t15));
let t16 = MuType_::ufuncptr(sig.clone());
types.push(P(t16));
types
}
#[test]
#[allow(unused_variables)]
fn test_type_constructors() {
let types = create_types();
assert_type!(*types[0], "Int(8)");
assert_type!(*types[1], "Float");
assert_type!(*types[2], "Double");
assert_type!(*types[3], "Ref(Int(8))");
assert_type!(*types[4], "IRef(Int(8))");
assert_type!(*types[5], "WeakRef(Int(8))");
assert_type!(*types[6], "UPtr(Int(8))");
assert_type!(*types[7], "Struct(\"MyStructTag1\")");
{
let map = STRUCT_TAG_MAP.read().unwrap();
let t7_struct_ty = map.get("MyStructTag1").unwrap();
assert_type!(t7_struct_ty, "StructType_ { tys: [Int(8), Float] }");
}
assert_type!(*types[8], "Array(Int(8), 5)");
assert_type!(*types[9], "Hybrid([Struct(\"MyStructTag1\"), Float], Int(8))");
assert_type!(*types[10], "Void");
assert_type!(*types[11], "ThreadRef");
assert_type!(*types[12], "StackRef");
assert_type!(*types[13], "Tagref64");
assert_type!(*types[14], "Vector(Int(8), 5)");
assert_type!(*types[15], "FuncRef(MuFuncSig { ret_tys: [Void], arg_tys: [Int(8), Int(8)] })");
assert_type!(*types[16], "UFuncPtr(MuFuncSig { ret_tys: [Void], arg_tys: [Int(8), Int(8)] })");
}
#[test]
fn test_cyclic_struct() {
// .typedef @cyclic_struct_ty = struct<ref<@cyclic_struct_ty> int<32>>
let ty = P(MuType_::mustruct_empty("MyStructTag2"));
let ref_ty = P(MuType_::muref(ty.clone()));
let i32_ty = P(MuType_::int(32));
{
STRUCT_TAG_MAP.write().unwrap().
get_mut("MyStructTag2").unwrap().set_tys(vec![ref_ty.clone(), i32_ty.clone()]);
}
let map = STRUCT_TAG_MAP.read().unwrap();
let struct_ty = map.get("MyStructTag2").unwrap();
assert_type!(struct_ty, "StructType_ { tys: [Ref(Struct(\"MyStructTag2\")), Int(32)] }");
}
#[test]
fn test_is_traced() {
let types = create_types();
assert_eq!(is_traced(&types[0]), false);
assert_eq!(is_traced(&types[1]), false);
assert_eq!(is_traced(&types[2]), false);
assert_eq!(is_traced(&types[3]), true);
assert_eq!(is_traced(&types[4]), true);
assert_eq!(is_traced(&types[5]), true);
assert_eq!(is_traced(&types[6]), false);
assert_eq!(is_traced(&types[7]), false);
let struct3 = MuType_::mustruct("MyStructTag3", vec![types[3].clone(), types[0].clone()]);
assert_eq!(is_traced(&struct3), true);