testing rodal alternatives

parent a7336ae4
......@@ -57,3 +57,4 @@ extprim = "*"
num-traits = "*"
built = "*"
mu_gc = { path = "src/gc"}
cfg-if = "*"
......@@ -53,5 +53,6 @@ fn main() {
}
fn built() {
built::write_built_file().expect("Failed to acquire build-time information");
built::write_built_file()
.expect("Failed to acquire build-time information");
}
#trailing_comma = "Never"
max_width = 80
wrap_comments = true
trailing_comma = "Never"
......@@ -85,6 +85,17 @@ impl Instruction {
| NewStack(_)
| NewThread { .. }
| NewRTThread { .. }
| AllocAU(_)
| NewReg(_)
| DeleteReg(_)
| rAlloc(_, _)
| rAllocHybrid(_, _, _)
// | rAllocT(_)
| eAlloc(_)
| eAllocHybrid(_, _)
// | eAllocT(_)
| eDelete(_)
// | eDeleteT(_)
| NotifyThread(_) // TODO remove - not needed anymore
| SetPriority(_,_)
| GetPriority(_)
......@@ -150,6 +161,17 @@ impl Instruction {
| AllocA(_)
| NewHybrid(_, _)
| AllocAHybrid(_, _)
| AllocAU(_)
| NewReg(_)
| DeleteReg(_)
| rAlloc(_, _)
| rAllocHybrid(_,_,_)
// | rAllocT(_)
| eAlloc(_)
| eAllocHybrid(_,_)
// | eAllocT(_)
| eDelete(_)
// | eDeleteT(_)
| NewStack(_)
| NewThread { .. }
| NewRTThread { .. }
......@@ -239,6 +261,17 @@ impl Instruction {
| NewHybrid(_, _)
| AllocAHybrid(_, _)
| NewStack(_)
| AllocAU(_)
| NewReg(_)
| DeleteReg(_)
| rAlloc(_, _)
| rAllocHybrid(_,_, _)
// | rAllocT(_)
| eAlloc(_)
| eAllocHybrid(_,_)
// | eAllocT(_)
| eDelete(_)
// | eDeleteT(_)
| NewThread { .. }
| NewRTThread { .. }
| NotifyThread(_)
......@@ -320,6 +353,17 @@ impl Instruction {
| New(_)
| AllocA(_)
| NewHybrid(_, _)
| AllocAU(_)
| NewReg(_)
| DeleteReg(_)
| rAlloc(_, _)
| rAllocHybrid(_,_,_)
// | rAllocT(_)
| eAlloc(_)
| eAllocHybrid(_,_)
// | eAllocT(_)
| eDelete(_)
// | eDeleteT(_)
| AllocAHybrid(_, _)
| NewStack(_)
| NewThread { .. }
......@@ -572,6 +616,55 @@ impl Instruction {
ops[func].ty().get_sig().unwrap(),
ops[func]
),
&Instruction_::NewReg(size) => format!(
"COMMINST @uvm.new_region({})",
ops[size]
),
&Instruction_::DeleteReg(regref) => format!(
"COMMINST @uvm.delete_region({})",
ops[regref]
),
&Instruction_::AllocAU(ref ty) => format!(
"COMMINST @uvm.AllocAU({})",
ty.id()
),
&Instruction_::rAlloc(regref, ref ty) => format!(
"COMMINST @uvm.rAlloc({}, {})",
ops[regref],
ty.id()
),
&Instruction_::rAllocHybrid(regref, ref ty, var_len) => format!(
"COMMINST @uvm.rAllocHybrid({}, {}, {})",
ops[regref],
ty.id(),
ops[var_len]
),
// &Instruction_::rAllocT(regref, ty) => format!(
// "COMMINST @uvm.rAllocT({}, {})",
// ops[regref],
// ops[ty]
// ),
&Instruction_::eAlloc( ref ty) => format!(
"COMMINST @uvm.eAlloc({})",
ty.id()
),
&Instruction_::eAllocHybrid( ref ty, var_len) => format!(
"COMMINST @uvm.eAllocHybrid({}, {})",
ty.id(),
ops[var_len]
),
// &Instruction_::eAllocT( ty) => format!(
// "COMMINST @uvm.eAllocT({})",
// ops[ty]
// ),
&Instruction_::eDelete(obj) => format!(
"COMMINST @uvm.eDelete({})",
ops[obj]
),
// &Instruction_::eDeleteT( obj) => format!(
// "COMMINST @uvm.eDeleteT({})",
// ops[obj]
// ),
&Instruction_::NewThread {
stack,
thread_local,
......@@ -995,14 +1088,62 @@ pub enum Instruction_ {
/// allocate an object (non hybrid type) on the stack, yields an iref of the type
AllocA(P<MuType>),
/// allocate an object (non hybrid type) on the stack, yields an uptr of the type
AllocAU(P<MuType>),
/// allocate a hybrid type object in the heap, yields ref
/// args: the type of the hybrid, hybrid part length
NewHybrid(P<MuType>, OpIndex),
/// allocate an emm region
/// args: region size
NewReg(OpIndex),
/// deallocate a whole emm region
/// args: regionref to the target region
DeleteReg(OpIndex),
/// allocates an untraced object on an emm region
/// args: 1. a regionref to the target emm region
/// args: 2. the object type
/// returns: a uptr to the allocated object
rAlloc(OpIndex, P<MuType>),
rAllocHybrid(OpIndex, P<MuType>, OpIndex),
// /// allocates a traced object on an emm region
// /// args: 1. a regionref to the target emm region
// /// args: 2. the object type
// /// returns: an iref to the allocated object
// rAllocT(OpIndex, P<MuType>),
/// allocate an untraced object on the emm
/// args: type of the object
/// returns: a uptr to the object
eAlloc(P<MuType>),
eAllocHybrid(P<MuType>, OpIndex),
/// deallocate an untraced emm object
/// args: an uptr to the object
eDelete(OpIndex),
// /// allocate a traced object on the emm
// /// args: type of the object
// /// returns: an iref to the object
// eAllocT(P<MuType>),
// /// deallocate a traced emm object
// /// args: an iref to the object
// eDeleteT(OpIndex),
/// allocate a hybrid type object on the stack, yields iref
/// args: the type of the hybrid, hybrid part length
AllocAHybrid(P<MuType>, OpIndex),
// TODO add hybrid versions
// /// allocate a hybrid type object on the stack, yields uptr
// /// args: the type of the hybrid, hybrid part length
// AllocAUHybrid(P<MuType>, OpIndex),
/// create a new Mu stack, yields stack ref
/// args: functionref of the entry function
NewStack(OpIndex),
......
......@@ -745,6 +745,10 @@ impl fmt::Debug for BlockContent {
}
impl BlockContent {
pub fn get_own_args(&self, index: usize) -> &P<Value> {
&self.args[index]
}
/// returns all the arguments passed to its successors
pub fn get_out_arguments(&self) -> Vec<P<Value>> {
let n_insts = self.body.len();
......
......@@ -32,15 +32,24 @@ lazy_static! {
new_internal_id(),
MuType_::int(POINTER_SIZE * 8)
));
pub static ref UINT1_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(1)));
pub static ref UINT8_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(8)));
pub static ref UINT16_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(16)));
pub static ref UINT32_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(32)));
pub static ref UINT64_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(64)));
pub static ref UINT128_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::int(128)));
pub static ref FLOAT_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::float()));
pub static ref DOUBLE_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::double()));
pub static ref VOID_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::void()));
pub static ref UINT1_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::int(1)));
pub static ref UINT8_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::int(8)));
pub static ref UINT16_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::int(16)));
pub static ref UINT32_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::int(32)));
pub static ref UINT64_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::int(64)));
pub static ref UINT128_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::int(128)));
pub static ref FLOAT_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::float()));
pub static ref DOUBLE_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::double()));
pub static ref VOID_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::void()));
pub static ref REF_VOID_TYPE: P<MuType> = P(MuType::new(
new_internal_id(),
MuType_::muref(VOID_TYPE.clone())
......@@ -88,11 +97,14 @@ lazy_static! {
#[cfg(feature = "realtime")]
lazy_static! {
pub static ref RTATTR_TYPE: P<MuType> = P(MuType::new(new_internal_id(), MuType_::rtattr()));
pub static ref RTATTR_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::rtattr()));
pub static ref UPTR_RTATTR_TYPE: P<MuType> = P(MuType::new(
new_internal_id(),
MuType_::uptr(RTATTR_TYPE.clone())
));
pub static ref REGREF_TYPE: P<MuType> =
P(MuType::new(new_internal_id(), MuType_::regionref()));
pub static ref INTERNAL_TYPES: Vec<P<MuType>> = vec![
ADDRESS_TYPE.clone(),
UINT1_TYPE.clone(),
......@@ -112,7 +124,8 @@ lazy_static! {
UPTR_U8_TYPE.clone(),
UPTR_U64_TYPE.clone(),
RTATTR_TYPE.clone(),
UPTR_RTATTR_TYPE.clone()
UPTR_RTATTR_TYPE.clone(),
REGREF_TYPE.clone(),
];
}
......@@ -133,7 +146,7 @@ pub fn init_types() {
#[derive(Debug)]
pub struct MuType {
pub hdr: MuEntityHeader,
pub v: MuType_,
pub v: MuType_
}
rodal_struct!(MuType { hdr, v });
......@@ -152,28 +165,28 @@ impl MuType {
pub fn new(id: MuID, v: MuType_) -> MuType {
MuType {
hdr: MuEntityHeader::unnamed(id),
v: v,
v: v
}
}
pub fn is_tagref64(&self) -> bool {
match self.v {
MuType_::Tagref64 => true,
_ => false,
_ => false
}
}
pub fn is_stackref(&self) -> bool {
match self.v {
MuType_::StackRef => true,
_ => false,
_ => false
}
}
pub fn is_funcref(&self) -> bool {
match self.v {
MuType_::FuncRef(_) => true,
_ => false,
_ => false
}
}
......@@ -181,14 +194,14 @@ impl MuType {
pub fn is_struct(&self) -> bool {
match self.v {
MuType_::Struct(_) => true,
_ => false,
_ => false
}
}
pub fn is_void(&self) -> bool {
match self.v {
MuType_::Void => true,
_ => false,
_ => false
}
}
......@@ -196,7 +209,7 @@ impl MuType {
pub fn is_hybrid(&self) -> bool {
match self.v {
MuType_::Hybrid(_) => true,
_ => false,
_ => false
}
}
......@@ -204,7 +217,7 @@ impl MuType {
pub fn is_int(&self) -> bool {
match self.v {
MuType_::Int(_) => true,
_ => false,
_ => false
}
}
......@@ -221,14 +234,20 @@ impl MuType {
pub fn is_fp(&self) -> bool {
match self.v {
MuType_::Float | MuType_::Double => true,
_ => false,
_ => false
}
}
pub fn is_opaque_reference(&self) -> bool {
match self.v {
MuType_::FuncRef(_) | MuType_::StackRef | MuType_::ThreadRef => true,
_ => false,
MuType_::FuncRef(_) | MuType_::StackRef | MuType_::ThreadRef => {
true
}
#[cfg(feature = "realtime")]
MuType_::RegionRef => true,
_ => false
}
}
......@@ -237,7 +256,7 @@ impl MuType {
match self.v {
// #[cfg(realtime)]
MuType_::RTAttr => true,
_ => false,
_ => false
}
}
......@@ -257,7 +276,7 @@ impl MuType {
pub fn is_float(&self) -> bool {
match self.v {
MuType_::Float => true,
_ => false,
_ => false
}
}
......@@ -265,7 +284,7 @@ impl MuType {
pub fn is_double(&self) -> bool {
match self.v {
MuType_::Double => true,
_ => false,
_ => false
}
}
......@@ -285,34 +304,39 @@ impl MuType {
| MuType_::Tagref64
| MuType_::UPtr(_) => true,
#[cfg(feature = "realtime")]
MuType_::RTAttr => true,
_ => false,
MuType_::RTAttr | MuType_::RegionRef => true,
_ => false
}
}
/// gets the tag of a struct/hybrid type, returns None if the type is not hybrid/struct
/// We use tag to resolve recursive types, and maintains a map between tag and struct types
/// gets the tag of a struct/hybrid type, returns None if the type is not
/// hybrid/struct We use tag to resolve recursive types, and maintains a
/// map between tag and struct types
pub fn get_struct_hybrid_tag(&self) -> Option<MuName> {
match self.v {
MuType_::Hybrid(ref name) | MuType_::Struct(ref name) => Some(name.clone()),
_ => None,
MuType_::Hybrid(ref name) | MuType_::Struct(ref name) => {
Some(name.clone())
}
_ => None
}
}
/// is this type a reference type?
/// (only reference type, which does not include iref, or other opaque reference types)
/// (only reference type, which does not include iref, or other opaque
/// reference types)
pub fn is_ref(&self) -> bool {
match self.v {
MuType_::Ref(_) => true,
_ => false,
_ => false
}
}
/// is this type any reference type pointing to the heap? (including ref/iref/weakref)
/// is this type any reference type pointing to the heap? (including
/// ref/iref/weakref)
pub fn is_heap_reference(&self) -> bool {
match self.v {
MuType_::Ref(_) | MuType_::IRef(_) | MuType_::WeakRef(_) => true,
_ => false,
_ => false
}
}
......@@ -320,7 +344,7 @@ impl MuType {
pub fn is_iref(&self) -> bool {
match self.v {
MuType_::IRef(_) => true,
_ => false,
_ => false
}
}
......@@ -328,15 +352,17 @@ impl MuType {
pub fn is_ptr(&self) -> bool {
match self.v {
MuType_::UPtr(_) | MuType_::UFuncPtr(_) => true,
_ => false,
_ => false
}
}
/// is this type an aggregated type? (consisted of other types)
pub fn is_aggregate(&self) -> bool {
match self.v {
MuType_::Struct(_) | MuType_::Hybrid(_) | MuType_::Array(_, _) => true,
_ => false,
MuType_::Struct(_) | MuType_::Hybrid(_) | MuType_::Array(_, _) => {
true
}
_ => false
}
}
......@@ -348,7 +374,8 @@ impl MuType {
MuType_::Ref(_) => true,
MuType_::IRef(_) => true,
MuType_::WeakRef(_) => true,
MuType_::Array(ref elem_ty, _) | MuType_::Vector(ref elem_ty, _) => elem_ty.is_traced(),
MuType_::Array(ref elem_ty, _)
| MuType_::Vector(ref elem_ty, _) => elem_ty.is_traced(),
MuType_::ThreadRef | MuType_::StackRef | MuType_::Tagref64 => true,
MuType_::Hybrid(ref tag) => {
let map = HYBRID_TAG_MAP.read().unwrap();
......@@ -373,12 +400,13 @@ impl MuType {
.map(|ty| ty.is_traced())
.fold(false, |ret, this| ret || this)
}
_ => false,
_ => false
}
}
/// is this type native safe?
/// Note: An aggregated type is native safe if all of its parts are native safe.
/// Note: An aggregated type is native safe if all of its parts are native
/// safe.
#[allow(dead_code)]
pub fn is_native_safe(&self) -> bool {
match self.v {
......@@ -386,9 +414,8 @@ impl MuType {
MuType_::Float => true,
MuType_::Double => true,
MuType_::Void => true,
MuType_::Array(ref elem_ty, _) | MuType_::Vector(ref elem_ty, _) => {
elem_ty.is_native_safe()
}
MuType_::Array(ref elem_ty, _)
| MuType_::Vector(ref elem_ty, _) => elem_ty.is_native_safe(),
MuType_::UPtr(_) => true,
MuType_::UFuncPtr(_) => true,
MuType_::Hybrid(ref tag) => {
......@@ -414,23 +441,26 @@ impl MuType {
.map(|ty| ty.is_native_safe())
.fold(true, |ret, this| ret && this)
}
_ => false,
_ => false
}
}
/// gets the element type of an array type, returns None if the type is not an array type
/// gets the element type of an array type, returns None if the type is not
/// an array type
pub fn get_elem_ty(&self) -> Option<P<MuType>> {
match self.v {
MuType_::Array(ref elem_ty, _) => Some(elem_ty.clone()),
_ => None,
_ => None
}
}
/// gets the signature of a funcref or ufuncptr type
pub fn get_sig(&self) -> Option<P<MuFuncSig>> {
match self.v {
MuType_::FuncRef(ref sig) | MuType_::UFuncPtr(ref sig) => Some(sig.clone()),
_ => None,
MuType_::FuncRef(ref sig) | MuType_::UFuncPtr(ref sig) => {
Some(sig.clone())
}
_ => None
}
}
......@@ -450,11 +480,12 @@ impl MuType {
Some(hybrid_inner.fix_tys[index].clone())
}
_ => None,
_ => None
}
}
/// gets the var part type of a hybrid type, returns None if the type is not a hybrid type
/// gets the var part type of a hybrid type, returns None if the type is not
/// a hybrid type
pub fn get_hybrid_varpart_ty(&self) -> Option<P<MuType>> {
match self.v {
MuType_::Hybrid(ref tag) => {
......@@ -463,38 +494,48 @@ impl MuType {
Some(hybrid_inner.var_ty.clone())
}
_ => None,
_ => None
}
}
/// gets the referent type for Ref/IRef/WeakRef/UPtr, returns None if the type is
/// not any mentioned type.
/// gets the referent type for Ref/IRef/WeakRef/UPtr, returns None if the
/// type is not any mentioned type.
pub fn get_referent_ty(&self) -> Option<P<MuType>> {
use types::MuType_::*;
match self.v {
Ref(ref ty) | IRef(ref ty) | WeakRef(ref ty) | UPtr(ref ty) => Some(ty.clone()),
_ => None,
Ref(ref ty) | IRef(ref ty) | WeakRef(ref ty) | UPtr(ref ty) => {
Some(ty.clone())
}
_ => None
}
}
/// gets the function signature for FuncRef or UFuncPtr, return None if the type is not
/// those two types
/// gets the function signature for FuncRef or UFuncPtr, return None if the
/// type is not those two types
pub fn get_func_sig(&self) -> Option<P<MuFuncSig>> {
match self.v {
MuType_::FuncRef(ref sig) | MuType_::UFuncPtr(ref sig) => Some(sig.clone()),
_ => None,
MuType_::FuncRef(ref sig) | MuType_::UFuncPtr(ref sig) => {
Some(sig.clone())
}
_ => None
}
}
/// gets the length (in bit) of a integer/pointer type (assume pointer types are always 64 bits)
// FIXME: should deprecate this function, and get the length from BackendType
/// gets the length (in bit) of a integer/pointer type (assume pointer types
/// are always 64 bits)
// FIXME: should deprecate this function, and get the length from
// BackendType
pub fn get_int_length(&self) -> Option<usize> {
use types::MuType_::*;
match self.v {
Int(len) => Some(len),
Ref(_) | IRef(_) | WeakRef(_) | UPtr(_) | ThreadRef | StackRef | Tagref64
| FuncRef(_) | UFuncPtr(_) => Some(64),
_ => None,
Ref(_) | IRef(_) | WeakRef(_) | UPtr(_) | ThreadRef | StackRef
| Tagref64 | FuncRef(_) | UFuncPtr(_) => Some(64),
#[cfg(feature = "realtime")]
RegionRef => Some(64),
_ => None
}
}
......@@ -509,16 +550,58 @@ impl MuType {
let lock = HYBRID_TAG_MAP.read().unwrap();
format!("{} = {}", tag, lock.get(tag).unwrap())
}
_ => format!("{}", self),
_ => format!("{}", self)
}
}
/// prints a struct type
pub fn print_hybrid(&self) -> String {
match self.v {
_ => panic!(),
_ => panic!()
}
}
// #[cfg(feature = "realtime")]
pub fn containsIRef(&self) -> bool {
let res = match &self.v {
MuType_::IRef(_) => true,
MuType_::Array(ty, size) => ty.is_iref() && *size > 0,
MuType_::Struct(tag) => {
let structMap = STRUCT_TAG_MAP.read().unwrap();
let _struct: &StructType_ = structMap.get(tag).unwrap();
let _types = _struct.get_tys();
for _type in _types {
if _type.is_iref() || _type.containsIRef() {
return true
}
}
false
}
MuType_::Hybrid(tag) => {
let _hybrid_tag_map = HYBRID_TAG_MAP.read().unwrap();
let _hybrid = _hybrid_tag_map.get(tag).unwrap();
let fix_tys = _hybrid.get_fix_tys();
let var_ty = _hybrid.get_var_ty();
for _type in fix_tys.iter() {
if _type.is_iref() || _type.containsIRef() {
return true
}
}
if var_ty.is_iref() || var_ty.containsIRef() {
return true
}
false
}
_ => false