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.7% of users enabled 2FA.

Commit bed34cc1 authored by qinsoon's avatar qinsoon
Browse files

implemented Debug for tree nodes and types

parent e7ec3053
......@@ -42,7 +42,6 @@ pub struct TreeNode {
pub id: MuID,
pub tag: MuTag,
pub v: TreeNode_,
pub children: Vec<P<TreeNode>>,
}
impl TreeNode {
......@@ -50,16 +49,15 @@ impl TreeNode {
P(TreeNode{
id: id,
tag: tag,
v: TreeNode_::Value(P(Value{ty: ty, v: Value_::SSAVar})),
children: vec![]})
v: TreeNode_::Value(P(Value{ty: ty, v: Value_::SSAVar}))
})
}
pub fn new_constant(id: MuID, tag: MuTag, ty: P<MuType>, v: Constant) -> P<TreeNode> {
P(TreeNode{
id: id,
tag: tag,
v: TreeNode_::Value(P(Value{ty: ty, v: Value_::Constant(v)})),
children: vec![]
v: TreeNode_::Value(P(Value{ty: ty, v: Value_::Constant(v)}))
})
}
......@@ -67,68 +65,106 @@ impl TreeNode {
P(TreeNode{
id: id,
tag: tag,
v: TreeNode_::Value(v),
children: vec![]
v: TreeNode_::Value(v)
}
)
}
pub fn new_inst(id: MuID, tag: MuTag, v: Instruction) -> P<TreeNode> {
P(TreeNode{id: id, tag: tag, v: TreeNode_::Instruction(v), children: vec![]})
P(TreeNode{id: id, tag: tag, v: TreeNode_::Instruction(v)})
}
pub fn as_value(&self) -> Option<&P<Value>> {
match self.v {
TreeNode_::Value(ref pv) => Some(&pv),
_ => None
}
}
}
impl fmt::Debug for TreeNode {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}#{:?}: {:?}", self.tag, self.id, self.v).unwrap();
for child in self.children.iter() {
write!(f, " -> {:?}#{:?}\n", child.tag, child.id).unwrap();
match self.v {
TreeNode_::Value(ref pv) => {
match pv.v {
Value_::SSAVar => {
write!(f, "{:?} %{}#{}", pv.ty, self.tag, self.id)
},
Value_::Constant(ref c) => {
write!(f, "{:?} {:?}", pv.ty, c)
}
}
},
TreeNode_::Instruction(ref inst) => {
write!(f, "{:?}", inst)
}
}
write!(f, "")
}
}
#[derive(Clone, Debug)]
#[derive(Clone)]
pub enum TreeNode_ {
Value(P<Value>),
Instruction(Instruction),
}
/// always use with P<Value>
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct Value {
pub ty: P<MuType>,
pub v: Value_
}
#[derive(Clone, Debug)]
#[derive(Clone)]
pub enum Value_ {
SSAVar,
Constant(Constant)
}
#[derive(Clone, Debug)]
#[derive(Clone)]
pub enum Constant {
Int(usize, usize),
IRef(P<MuType>, Address),
FloatV(f32),
DoubleV(f64),
VectorV(Vec<Constant>),
FuncRefV(Address),
UFuncRefV(Address)
Int(usize),
Float(f32),
Double(f64),
IRef(Address),
FuncRef(Address),
UFuncRef(Address),
Vector(Vec<Constant>),
}
impl fmt::Debug for Constant {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Constant::Int(v) => write!(f, "{}", v),
&Constant::Float(v) => write!(f, "{}", v),
&Constant::Double(v) => write!(f, "{}", v),
&Constant::IRef(v) => write!(f, "{}", v),
&Constant::FuncRef(v) => write!(f, "{}", v),
&Constant::UFuncRef(v) => write!(f, "{}", v),
&Constant::Vector(ref v) => write!(f, "{:?}", v)
}
}
}
#[derive(Clone, Debug)]
#[derive(Clone)]
pub enum Instruction {
NonTerm(NonTermInstruction),
Term(Terminal)
}
#[derive(Clone, Debug)]
impl fmt::Debug for Instruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Instruction::NonTerm(ref inst) => write!(f, "{:?}", inst),
&Instruction::Term(ref inst) => write!(f, "{:?}", inst)
}
}
}
#[derive(Clone)]
pub enum Terminal {
Return(Vec<P<TreeNode>>),
ThreadExit,
ThreadExit, // TODO: common inst
Throw(Vec<P<TreeNode>>),
TailCall(CallData),
Branch1(Destination),
......@@ -164,7 +200,7 @@ pub enum Terminal {
Switch{
cond: P<TreeNode>,
default: Destination,
branches: Vec<(P<Constant>, Destination)>
branches: Vec<(P<TreeNode>, Destination)>
},
ExnInstruction{
inner: NonTermInstruction,
......@@ -172,7 +208,45 @@ pub enum Terminal {
}
}
#[derive(Clone, Debug)]
impl fmt::Debug for Terminal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Terminal::Return(ref vals) => write!(f, "RET {:?}", vals),
&Terminal::ThreadExit => write!(f, "THREADEXIT"),
&Terminal::Throw(ref vals) => write!(f, "THROW {:?}", vals),
&Terminal::TailCall(ref call) => write!(f, "TAILCALL {:?}", call),
&Terminal::Branch1(ref dest) => write!(f, "BRANCH {:?}", dest),
&Terminal::Branch2{ref cond, ref true_dest, ref false_dest} => {
write!(f, "BRANCH2 {:?} {:?} {:?}", cond, true_dest, false_dest)
},
&Terminal::Watchpoint{id, ref disable_dest, ref resume} => {
match id {
Some(id) => {
write!(f, "WATCHPOINT {:?} {:?} {:?}", id, disable_dest.as_ref().unwrap(), resume)
},
None => {
write!(f, "TRAP {:?}", resume)
}
}
},
&Terminal::WPBranch{wp, ref disable_dest, ref enable_dest} => {
write!(f, "WPBRANCH {:?} {:?} {:?}", wp, disable_dest, enable_dest)
},
&Terminal::Call{ref data, ref resume} => write!(f, "CALL {:?} {:?}", data, resume),
&Terminal::SwapStack{ref stack, is_exception, ref args, ref resume} => {
write!(f, "SWAPSTACK {:?} {:?} {:?} {:?}", stack, is_exception, args, resume)
},
&Terminal::Switch{ref cond, ref default, ref branches} => {
write!(f, "SWITCH {:?} {:?} {{{:?}}}", cond, default, branches)
},
&Terminal::ExnInstruction{ref inner, ref resume} => {
write!(f, "{:?} {:?}", inner, resume)
}
}
}
}
#[derive(Clone)]
pub enum NonTermInstruction {
Assign{
left: Vec<P<TreeNode>>,
......@@ -182,14 +256,24 @@ pub enum NonTermInstruction {
Fence(MemoryOrder),
}
#[derive(Clone, Debug)]
impl fmt::Debug for NonTermInstruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&NonTermInstruction::Assign{ref left, ref right} => {
write!(f, "{:?} = {:?}", left, right)
},
&NonTermInstruction::Fence(order) => {
write!(f, "FENCE {:?}", order)
}
}
}
}
#[derive(Clone)]
pub enum Expression_ {
BinOp(BinOp, P<TreeNode>, P<TreeNode>),
CmpOp(CmpOp, P<TreeNode>, P<TreeNode>),
// yields the constant value
Constant(P<Constant>),
// yields a tuple of results from the call
ExprCall{
data: CallData,
......@@ -198,22 +282,23 @@ pub enum Expression_ {
// yields the memory value
Load{
is_iref: bool,
mem_loc: P<Value>,
order: MemoryOrder
is_ptr: bool,
order: MemoryOrder,
mem_loc: P<TreeNode>
},
// yields nothing
Store{
is_iref: bool,
mem_loc: P<Value>,
order: MemoryOrder
is_ptr: bool,
order: MemoryOrder,
mem_loc: P<TreeNode>,
value: P<TreeNode>
},
// yields pair (oldvalue, boolean (T = success, F = failure))
CmpXchg{
is_iref: bool, // T for iref, F for ptr
is_strong: bool,
is_ptr: bool,
is_weak: bool,
success_order: MemoryOrder,
fail_order: MemoryOrder,
mem_loc: P<TreeNode>,
......@@ -223,7 +308,7 @@ pub enum Expression_ {
// yields old memory value
AtomicRMW{
is_iref: bool, // T for iref, F for ptr
is_ptr: bool, // T for iref, F for ptr
order: MemoryOrder,
op: AtomicRMWOp,
mem_loc: P<TreeNode>,
......@@ -237,55 +322,53 @@ pub enum Expression_ {
AllocA(P<MuType>),
// yields ref
NewHybrid{ // hybrid type, var part length
ty: P<MuType>,
var_len: P<TreeNode>
},
NewHybrid(P<MuType>, P<TreeNode>),
// yields iref
AllocAHybrid{
ty: P<MuType>,
var_len: P<TreeNode>
},
AllocAHybrid(P<MuType>, P<TreeNode>),
// yields stack ref
NewStack{
func: P<TreeNode>
},
NewStack(P<TreeNode>), // func
// TODO: common inst
// yields thread reference
NewThread{
stack: P<TreeNode>,
args: Vec<P<TreeNode>>
},
NewThread(P<TreeNode>, Vec<P<TreeNode>>), // stack, args
// yields thread reference (thread resumes with exceptional value)
NewThreadExn{
stack: P<TreeNode>,
exn: P<TreeNode>
},
NewThreadExn(P<TreeNode>, P<TreeNode>), // stack, exception
// yields frame cursor
NewFrameCursor(P<TreeNode>), // stack
// ref<T> -> iref<T>
GetIRef(P<TreeNode>),
// iref|uptr<struct|hybrid<T>> int<M> -> iref|uptr<U>
GetFieldIRef{
base: P<TreeNode>, // iref or ptr
index: P<Constant>
is_ptr: bool,
base: P<TreeNode>, // iref or uptr
index: P<TreeNode> // constant
},
// iref|uptr<array<T N>> int<M> -> iref|uptr<T>
GetElementIRef{
is_ptr: bool,
base: P<TreeNode>,
index: P<TreeNode>
index: P<TreeNode> // can be constant or ssa var
},
// iref|uptr<T> int<M> -> iref|uptr<T>
ShiftIRef{
is_ptr: bool,
base: P<TreeNode>,
offset: P<TreeNode>
},
GetVarPartIRef(P<TreeNode>),
// iref|uptr<hybrid<T U>> -> iref|uptr<U>
GetVarPartIRef{
is_ptr: bool,
base: P<TreeNode>
},
// PushFrame{
// stack: P<Value>,
......@@ -296,6 +379,73 @@ pub enum Expression_ {
// }
}
macro_rules! select {
($cond: expr, $res1 : expr, $res2 : expr) => {
if $cond {
$res1
} else {
$res2
}
}
}
impl fmt::Debug for Expression_ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&Expression_::BinOp(op, ref op1, ref op2) => write!(f, "{:?} {:?} {:?}", op, op1, op2),
&Expression_::CmpOp(op, ref op1, ref op2) => write!(f, "{:?} {:?} {:?}", op, op1, op2),
&Expression_::ExprCall{ref data, is_abort} => {
let abort = select!(is_abort, "ABORT_ON_EXN", "RETHROW");
write!(f, "CALL {:?} {}", data, abort)
},
&Expression_::Load{is_ptr, ref mem_loc, order} => {
let ptr = select!(is_ptr, "PTR", "");
write!(f, "LOAD {} {:?} {:?}", ptr, order, mem_loc)
},
&Expression_::Store{ref value, is_ptr, ref mem_loc, order} => {
let ptr = select!(is_ptr, "PTR", "");
write!(f, "STORE {} {:?} {:?} {:?}", ptr, order, mem_loc, value)
},
&Expression_::CmpXchg{is_ptr, is_weak, success_order, fail_order,
ref mem_loc, ref expected_value, ref desired_value} => {
let ptr = select!(is_ptr, "PTR", "");
let weak = select!(is_weak, "WEAK", "");
write!(f, "CMPXCHG {} {} {:?} {:?} {:?} {:?} {:?}",
ptr, weak, success_order, fail_order, mem_loc, expected_value, desired_value)
},
&Expression_::AtomicRMW{is_ptr, order, op, ref mem_loc, ref value} => {
let ptr = select!(is_ptr, "PTR", "");
write!(f, "ATOMICRMW {} {:?} {:?} {:?} {:?}", ptr, order, op, mem_loc, value)
},
&Expression_::New(ref ty) => write!(f, "NEW {:?}", ty),
&Expression_::AllocA(ref ty) => write!(f, "ALLOCA {:?}", ty),
&Expression_::NewHybrid(ref ty, ref len) => write!(f, "NEWHYBRID {:?} {:?}", ty, len),
&Expression_::AllocAHybrid(ref ty, ref len) => write!(f, "ALLOCAHYBRID {:?} {:?}", ty, len),
&Expression_::NewStack(ref func) => write!(f, "NEWSTACK {:?}", func),
&Expression_::NewThread(ref stack, ref args) => write!(f, "NEWTHREAD {:?} PASS_VALUES {:?}", stack, args),
&Expression_::NewThreadExn(ref stack, ref exn) => write!(f, "NEWTHREAD {:?} THROW_EXC {:?}", stack, exn),
&Expression_::NewFrameCursor(ref stack) => write!(f, "NEWFRAMECURSOR {:?}", stack),
&Expression_::GetIRef(ref reference) => write!(f, "GETIREF {:?}", reference),
&Expression_::GetFieldIRef{is_ptr, ref base, ref index} => {
let ptr = select!(is_ptr, "PTR", "");
write!(f, "GETFIELDIREF {} {:?} {:?}", ptr, base, index)
},
&Expression_::GetElementIRef{is_ptr, ref base, ref index} => {
let ptr = select!(is_ptr, "PTR", "");
write!(f, "GETELEMENTIREF {} {:?} {:?}", ptr, base, index)
},
&Expression_::ShiftIRef{is_ptr, ref base, ref offset} => {
let ptr = select!(is_ptr, "PTR", "");
write!(f, "SHIFTIREF {} {:?} {:?}", ptr, base, offset)
},
&Expression_::GetVarPartIRef{is_ptr, ref base} => {
let ptr = select!(is_ptr, "PTR", "");
write!(f, "GETVARPARTIREF {} {:?}", ptr, base)
}
}
}
}
#[derive(Copy, Clone, Debug)]
pub enum MemoryOrder {
NotAtomic,
......@@ -318,27 +468,54 @@ pub enum ForeignFFI {
C
}
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct CallData {
pub func: P<TreeNode>,
pub args: Vec<P<TreeNode>>,
pub convention: CallConvention
}
#[derive(Clone, Debug)]
impl fmt::Debug for CallData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?} {:?} ({:?})", self.convention, self.func, self.args)
}
}
#[derive(Clone)]
pub struct ResumptionData {
pub normal_dest: Destination,
pub exn_dest: Destination
}
#[derive(Clone, Debug)]
pub enum DestArg {
Normal(P<TreeNode>),
Freshbound(usize)
impl fmt::Debug for ResumptionData {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "normal: {:?}, exception: {:?}", self.normal_dest, self.exn_dest)
}
}
#[derive(Clone, Debug)]
#[derive(Clone)]
pub struct Destination {
pub target: MuTag,
pub args: Vec<DestArg>
}
impl fmt::Debug for Destination {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}{:?}", self.target, self.args)
}
}
#[derive(Clone)]
pub enum DestArg {
Normal(P<TreeNode>),
Freshbound(usize)
}
impl fmt::Debug for DestArg {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&DestArg::Normal(ref pv) => write!(f, "{:?}", pv),
&DestArg::Freshbound(n) => write!(f, "${}", n)
}
}
}
\ No newline at end of file
extern crate std;
use std::fmt;
use ast::ptr::P;
use ast::ir::*;
......@@ -7,7 +7,7 @@ use std::sync::RwLock;
pub type MuType = MuType_;
#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(Clone, PartialEq, Eq)]
enum MuType_ {
/// int <length>
Int (usize),
......@@ -56,16 +56,57 @@ enum MuType_ {
UFuncPtr (P<MuFuncSig>),
}
impl fmt::Debug for MuType_ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
&MuType_::Int(n) => write!(f, "<int<{}>>", n),
&MuType_::Float => write!(f, "<float>"),
&MuType_::Double => write!(f, "<double>"),
&MuType_::Ref(ref ty) => write!(f, "<ref<{:?}>>", ty),
&MuType_::IRef(ref ty) => write!(f, "<iref<{:?}>>", ty),
&MuType_::WeakRef(ref ty) => write!(f, "<weakref<{:?}>>", ty),
&MuType_::UPtr(ref ty) => write!(f, "<uptr<{:?}>>", ty),
&MuType_::Array(ref ty, size) => write!(f, "<array<{:?}, {:?}>", ty, size),
&MuType_::Hybrid(ref fix_tys, ref var_ty) => write!(f, "<hybrid<{:?} {:?}>>", fix_tys, var_ty),
&MuType_::Void => write!(f, "<void>"),
&MuType_::ThreadRef => write!(f, "<threadref>"),
&MuType_::StackRef => write!(f, "<stackref>"),
&MuType_::Tagref64 => write!(f, "<tagref64>"),
&MuType_::Vector(ref ty, size) => write!(f, "<vector<{:?} {:?}>>", ty, size),
&MuType_::FuncRef(ref sig) => write!(f, "<funcref<{:?}>>", sig),
&MuType_::UFuncPtr(ref sig) => write!(f, "<ufuncref<{:?}>>", sig),
&MuType_::Struct(tag) => {
write!(f, "<struct<").unwrap();
let struct_tag_map_lock = STRUCT_TAG_MAP.read().unwrap();
let struct_ty = struct_tag_map_lock.get(tag);
for ty in struct_ty {
write!(f, "{:?}", ty).unwrap()
}
write!(f, ">>")
}
}
}
}
lazy_static! {
/// storing a map from MuTag to StructType_
pub static ref STRUCT_TAG_MAP : RwLock<HashMap<MuTag, StructType_>> = RwLock::new(HashMap::new());
}
#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(Clone, PartialEq, Eq)]
pub struct StructType_ {
tys: Vec<P<MuType_>>
}
impl fmt::Debug for StructType_ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
for ty in self.tys.iter() {
write!(f, "{:?}", ty).unwrap();
}
write!(f, "")
}
}
impl StructType_ {
pub fn set_tys(&mut self, mut list: Vec<P<MuType>>) {
self.tys.clear();
......@@ -255,8 +296,14 @@ macro_rules! is_type (
)
);
#[derive(Clone, PartialEq, Eq, Debug)]
#[derive(Clone, PartialEq, Eq)]
pub struct MuFuncSig {
pub ret_tys : Vec<P<MuType>>,
pub arg_tys: Vec<P<MuType>>
}
impl fmt::Debug for MuFuncSig {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?} -> {:?}", self.ret_tys, self.arg_tys)
}
}
\ No newline at end of file
......@@ -13,13 +13,13 @@ impl TreeGenerationPass {
impl CompilerPass for TreeGenerationPass {
fn execute(&mut self, vm: &VMContext, func: &mut MuFunction) {
debug!("Generating Tree for {:?}", func.fn_name);
debug!("Generating Tree for {}", func.fn_name);
for entry in func.blocks.iter_mut() {
let label : MuTag = entry.0;
let ref mut block : &mut Block = &mut entry.1;
debug!(" block: {:?}", label);
debug!(" block: {}", label);
for inst in block.content.take().unwrap().body {
debug!(" {:?}", inst);
......
......@@ -32,7 +32,7 @@ pub fn factorial() -> VMContext {
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));
let const_def_int64_1 = vm.declare_const("int64_1", type_def_int64.clone(), Constant::Int(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()]);
......
Markdown is supported
0% or .