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.

Commit d28af85a authored by qinsoon's avatar qinsoon
Browse files

serialization

parent d3c8e060
......@@ -6,15 +6,59 @@ use utils::vec_utils::as_str as vector_as_str;
use utils::vec_utils;
use std::fmt;
use std::cell::RefCell;
use std::sync::RwLock;
#[derive(Debug, Clone)]
#[derive(Debug)]
pub struct Instruction {
pub value : Option<Vec<P<Value>>>,
pub ops : RefCell<Vec<P<TreeNode>>>,
pub ops : RwLock<Vec<P<TreeNode>>>,
pub v: Instruction_
}
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
impl Encodable for Instruction {
fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
s.emit_struct("Instruction", 3, |s| {
try!(s.emit_struct_field("value", 0, |s| self.value.encode(s)));
let ops = &self.ops.read().unwrap();
try!(s.emit_struct_field("ops", 1, |s| ops.encode(s)));
try!(s.emit_struct_field("v", 2, |s| self.v.encode(s)));
Ok(())
})
}
}
impl Decodable for Instruction {
fn decode<D: Decoder>(d: &mut D) -> Result<Instruction, D::Error> {
d.read_struct("Instruction", 3, |d| {
let value = try!(d.read_struct_field("value", 0, |d| Decodable::decode(d)));
let ops = try!(d.read_struct_field("ops", 1, |d| Decodable::decode(d)));
let v = try!(d.read_struct_field("v", 2, |d| Decodable::decode(d)));
Ok(Instruction{
value: value,
ops: RwLock::new(ops),
v: v
})
})
}
}
impl Clone for Instruction {
fn clone(&self) -> Self {
Instruction {
value: self.value.clone(),
ops: RwLock::new(self.ops.read().unwrap().clone()),
v: self.v.clone()
}
}
}
impl Instruction {
fn debug_str(&self, ops: &Vec<P<TreeNode>>) -> String {
self.v.debug_str(ops)
......@@ -23,7 +67,7 @@ impl Instruction {
impl fmt::Display for Instruction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let ops = &self.ops.borrow();
let ops = &self.ops.read().unwrap();
if self.value.is_some() {
write!(f, "{} = {}", vector_as_str(self.value.as_ref().unwrap()), self.v.debug_str(ops))
} else {
......@@ -32,7 +76,7 @@ impl fmt::Display for Instruction {
}
}
#[derive(Debug, Clone)]
#[derive(Debug, Clone, RustcEncodable, RustcDecodable)]
pub enum Instruction_ {
// non-terminal instruction
......@@ -189,7 +233,7 @@ pub enum Instruction_ {
branches: Vec<(OpIndex, Destination)>
},
ExnInstruction{
inner: P<Instruction>,
inner: Box<Instruction>,
resume: ResumptionData
}
}
......@@ -297,7 +341,7 @@ impl Instruction_ {
}
}
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum MemoryOrder {
NotAtomic,
Relaxed,
......@@ -308,18 +352,18 @@ pub enum MemoryOrder {
SeqCst
}
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum CallConvention {
Mu,
Foreign(ForeignFFI)
}
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum ForeignFFI {
C
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct CallData {
pub func: OpIndex,
pub args: Vec<OpIndex>,
......@@ -332,7 +376,7 @@ impl CallData {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct ResumptionData {
pub normal_dest: Destination,
pub exn_dest: Destination
......@@ -344,7 +388,7 @@ impl ResumptionData {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct Destination {
pub target: MuID,
pub args: Vec<DestArg>
......@@ -377,7 +421,7 @@ impl Destination {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum DestArg {
Normal(OpIndex),
Freshbound(usize)
......
......@@ -54,7 +54,7 @@ pub fn new_internal_id() -> MuID {
ret
}
#[derive(Debug)]
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct MuFunction {
pub hdr: MuEntityHeader,
......@@ -89,7 +89,7 @@ impl fmt::Display for MuFunction {
}
}
#[derive(Debug)]
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct MuFunctionVersion {
pub hdr: MuEntityHeader,
......@@ -153,8 +153,8 @@ impl MuFunctionVersion {
})
}
pub fn new_inst(&mut self, id: MuID, v: Instruction) -> P<TreeNode> {
P(TreeNode{
pub fn new_inst(&mut self, id: MuID, v: Instruction) -> Box<TreeNode> {
Box::new(TreeNode{
hdr: MuEntityHeader::unnamed(id),
op: pick_op_code_for_inst(&v),
v: TreeNode_::Instruction(v),
......@@ -162,7 +162,7 @@ impl MuFunctionVersion {
}
}
#[derive(Debug)]
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct FunctionContent {
pub entry: MuID,
pub blocks: HashMap<MuID, Block>
......@@ -195,7 +195,7 @@ impl FunctionContent {
}
}
#[derive(Debug)]
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct FunctionContext {
pub value_tags: HashMap<MuName, MuID>,
pub values: HashMap<MuID, SSAVarEntry>
......@@ -234,7 +234,7 @@ impl FunctionContext {
}
}
#[derive(Debug)]
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct Block {
pub hdr: MuEntityHeader,
pub content: Option<BlockContent>,
......@@ -247,7 +247,7 @@ impl Block {
}
}
#[derive(Debug)]
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct ControlFlow {
pub preds : Vec<MuID>,
pub succs : Vec<BlockEdge>
......@@ -286,7 +286,7 @@ impl default::Default for ControlFlow {
}
}
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct BlockEdge {
pub target: MuID,
pub kind: EdgeKind,
......@@ -300,15 +300,15 @@ impl fmt::Display for BlockEdge {
}
}
#[derive(Copy, Clone, Debug)]
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum EdgeKind {
Forward, Backward
}
#[derive(Debug)]
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct BlockContent {
pub args: Vec<P<Value>>,
pub body: Vec<P<TreeNode>>,
pub body: Vec<Box<TreeNode>>,
pub keepalives: Option<Vec<P<Value>>>
}
......@@ -321,7 +321,7 @@ impl BlockContent {
match last_inst.v {
TreeNode_::Instruction(ref inst) => {
let ops = inst.ops.borrow();
let ops = inst.ops.read().unwrap();
match inst.v {
Instruction_::Return(_)
| Instruction_::ThreadExit
......@@ -383,7 +383,7 @@ impl BlockContent {
}
}
#[derive(Debug)]
#[derive(Debug, RustcEncodable, RustcDecodable)]
/// always use with P<TreeNode>
pub struct TreeNode {
pub hdr: MuEntityHeader,
......@@ -447,14 +447,14 @@ impl fmt::Display for TreeNode {
}
}
#[derive(Debug, Clone)]
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub enum TreeNode_ {
Value(P<Value>),
Instruction(Instruction)
}
/// always use with P<Value>
#[derive(Debug, PartialEq)]
#[derive(Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub struct Value {
pub hdr: MuEntityHeader,
pub ty: P<MuType>,
......@@ -528,7 +528,7 @@ impl fmt::Display for Value {
}
}
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub enum Value_ {
SSAVar(MuID),
Constant(Constant),
......@@ -536,7 +536,7 @@ pub enum Value_ {
Memory(MemoryLocation)
}
#[derive(Debug, Clone)]
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct SSAVarEntry {
pub id: MuID,
pub name: Option<MuName>,
......@@ -566,12 +566,12 @@ impl fmt::Display for SSAVarEntry {
}
}
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub enum Constant {
Int(u64),
Float(f32),
Double(f64),
IRef(Address),
// IRef(Address),
FuncRef(MuID),
UFuncRef(MuID),
Vector(Vec<Constant>),
......@@ -583,7 +583,7 @@ impl fmt::Display for Constant {
&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::IRef(v) => write!(f, "{}", v),
&Constant::FuncRef(v) => write!(f, "{}", v),
&Constant::UFuncRef(v) => write!(f, "{}", v),
&Constant::Vector(ref v) => {
......@@ -600,7 +600,7 @@ impl fmt::Display for Constant {
}
}
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone, PartialEq, RustcEncodable, RustcDecodable)]
pub enum MemoryLocation {
Address{
base: P<Value>,
......
......@@ -2,7 +2,7 @@ use ast::ptr::P;
use ast::types::*;
use ast::inst::*;
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum OpCode {
// SSA
RegI64,
......@@ -112,7 +112,7 @@ pub fn pick_op_code_for_value(ty: &P<MuType>) -> OpCode {
}
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum BinOp {
// Int(n) BinOp Int(n) -> Int(n)
Add,
......@@ -138,7 +138,7 @@ pub enum BinOp {
FRem
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum CmpOp {
// for Int comparison
EQ,
......@@ -171,7 +171,7 @@ pub enum CmpOp {
FUNO
}
#[derive(Copy, Clone, Debug, PartialEq)]
#[derive(Copy, Clone, Debug, PartialEq, RustcEncodable, RustcDecodable)]
pub enum AtomicRMWOp {
XCHG,
ADD,
......
......@@ -36,37 +36,28 @@
//! implementation changes (using a special thread-local heap, for example).
//! Moreover, a switch to, e.g. `P<'a, T>` would be easy and mostly automated.
//use std::fmt::{self, Display, Debug};
//use std::hash::{Hash, Hasher};
//use std::ops::Deref;
//use std::ops::DerefMut;
use std::fmt::{self, Display, Debug};
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
use std::sync::Arc;
pub type P<T> = Arc<T>;
use ast::ir::MuEntity;
///// An owned smart pointer.
//pub struct P<T> {
// ptr: Box<T>
pub type P<T> = Arc<T>;
//pub struct P<T: MuEntity> {
// ptr: Arc<T>
//}
#[allow(non_snake_case)]
/// Construct a `P<T>` from a `T` value.
pub fn P<T: 'static>(value: T) -> P<T> {
pub fn P<T: MuEntity>(value: T) -> P<T> {
// P {ptr: Arc::new(value)}
Arc::new(value)
}
//impl<T: 'static> P<T> {
// /// Move out of the pointer.
// /// Intended for chaining transformations not covered by `map`.
// pub fn and_then<U, F>(self, f: F) -> U where
// F: FnOnce(T) -> U,
// {
// f(*self.ptr)
// }
//}
//
//impl<T> Deref for P<T> {
//impl<T: MuEntity> Deref for P<T> {
// type Target = T;
//
// fn deref<'a>(&'a self) -> &'a T {
......@@ -74,45 +65,45 @@ pub fn P<T: 'static>(value: T) -> P<T> {
// }
//}
//
//impl<T> DerefMut for P<T> {
// fn deref_mut<'a>(&'a mut self) -> &'a mut T {
// &mut *self.ptr
// }
//}
//
//impl<T: 'static + Clone> Clone for P<T> {
//impl<T: MuEntity> Clone for P<T> {
// fn clone(&self) -> P<T> {
// P((**self).clone())
// P {ptr: self.ptr.clone()}
// }
//}
//
//impl<T: PartialEq> PartialEq for P<T> {
//impl<T: MuEntity + PartialEq> PartialEq for P<T> {
// fn eq(&self, other: &P<T>) -> bool {
// **self == **other
// }
//}
//
//impl<T: Eq> Eq for P<T> {}
//impl<T: MuEntity + Eq> Eq for P<T> {}
//
//impl<T: Debug> Debug for P<T> {
//impl<T: MuEntity + Debug> Debug for P<T> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Debug::fmt(&**self, f)
// }
//}
//impl<T: Display> Display for P<T> {
//impl<T: MuEntity + Display> Display for P<T> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// Display::fmt(&**self, f)
// }
//}
//
//impl<T> fmt::Pointer for P<T> {
//impl<T: MuEntity> fmt::Pointer for P<T> {
// fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
// fmt::Pointer::fmt(&self.ptr, f)
// }
//}
//
//impl<T: Hash> Hash for P<T> {
//impl<T: MuEntity + Hash> Hash for P<T> {
// fn hash<H: Hasher>(&self, state: &mut H) {
// (**self).hash(state);
// }
//}
//impl<T: MuEntity> Encodable for P<T> {
// fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
// s.emit_usize(self.id())
// }
//}
\ No newline at end of file
......@@ -8,7 +8,7 @@ use std::sync::RwLock;
use rustc_serialize::{Encodable, Encoder, Decodable, Decoder};
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
pub struct MuType {
pub hdr: MuEntityHeader,
pub v: MuType_
......@@ -23,17 +23,7 @@ impl MuType {
}
}
//impl Encodable for MuType {
// fn encode<S: Encoder> (&self, s: &mut S) -> Result<(), S::Error> {
// //serialize 2 fields
// s.emit_struct("MuType", 2, |s| {
// // hdr
// try!(s.emit_struct_field("hdr", 0, |s| hdr.encode(s)));
// })
// }
//}
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
pub enum MuType_ {
/// int <length>
Int (usize),
......@@ -117,7 +107,7 @@ lazy_static! {
pub static ref STRUCT_TAG_MAP : RwLock<HashMap<MuName, StructType_>> = RwLock::new(HashMap::new());
}
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
pub struct StructType_ {
tys: Vec<P<MuType>>
}
......@@ -335,7 +325,7 @@ macro_rules! is_type (
)
);
#[derive(PartialEq, Debug)]
#[derive(PartialEq, Debug, RustcEncodable, RustcDecodable)]
pub struct MuFuncSig {
pub hdr: MuEntityHeader,
pub ret_tys : Vec<P<MuType>>,
......
......@@ -38,7 +38,7 @@ impl <'a> InstructionSelection {
// 3. we need to backup/restore all the callee-saved registers
// if any of these assumption breaks, we will need to re-emit the code
#[allow(unused_variables)]
fn instruction_select(&mut self, node: &'a P<TreeNode>, cur_func: &MuFunctionVersion, vm: &VM) {
fn instruction_select(&mut self, node: &'a TreeNode, cur_func: &MuFunctionVersion, vm: &VM) {
trace!("instsel on node {}", node);
match node.v {
......@@ -55,7 +55,7 @@ impl <'a> InstructionSelection {
}
};
let ops = inst.ops.borrow();
let ops = inst.ops.read().unwrap();
self.process_dest(&ops, fallthrough_dest, cur_func, vm);
self.process_dest(&ops, branch_dest, cur_func, vm);
......@@ -94,7 +94,7 @@ impl <'a> InstructionSelection {
},
Instruction_::Branch1(ref dest) => {
let ops = inst.ops.borrow();
let ops = inst.ops.read().unwrap();
self.process_dest(&ops, dest, cur_func, vm);
......@@ -108,7 +108,7 @@ impl <'a> InstructionSelection {
Instruction_::ExprCall{ref data, is_abort} => {
trace!("deal with pre-call convention");
let ops = inst.ops.borrow();
let ops = inst.ops.read().unwrap();
let rets = inst.value.as_ref().unwrap();
let ref func = ops[data.func];
let ref func_sig = match func.v {
......@@ -206,7 +206,7 @@ impl <'a> InstructionSelection {
},
Instruction_::BinOp(op, op1, op2) => {
let ops = inst.ops.borrow();
let ops = inst.ops.read().unwrap();
match op {
op::BinOp::Add => {
......@@ -352,7 +352,7 @@ impl <'a> InstructionSelection {
// load on x64 generates mov inst (no matter what order is specified)
// https://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html
Instruction_::Load{is_ptr, order, mem_loc} => {
let ops = inst.ops.borrow();
let ops = inst.ops.read().unwrap();
let ref loc_op = ops[mem_loc];
// check order
......@@ -377,7 +377,7 @@ impl <'a> InstructionSelection {
}
Instruction_::Store{is_ptr, order, mem_loc, value} => {
let ops = inst.ops.borrow();
let ops = inst.ops.read().unwrap();
let ref loc_op = ops[mem_loc];
let ref val_op = ops[value];
......@@ -504,7 +504,7 @@ impl <'a> InstructionSelection {
// FIXME: this may change in the future
// prepare return regs
let ref ops = ret_inst.ops.borrow();
let ref ops = ret_inst.ops.read().unwrap();
let ret_val_indices = match ret_inst.v {
Instruction_::Return(ref vals) => vals,
_ => panic!("expected ret inst")
......@@ -556,7 +556,7 @@ impl <'a> InstructionSelection {
fn emit_cmp_res(&mut self, cond: &P<TreeNode>, cur_func: &MuFunctionVersion, vm: &VM) -> op::CmpOp {
match cond.v {
TreeNode_::Instruction(ref inst) => {
let ops = inst.ops.borrow();
let ops = inst.ops.read().unwrap();
match inst.v {
Instruction_::CmpOp(op, op1, op2) => {
......@@ -591,7 +591,7 @@ impl <'a> InstructionSelection {
}
}
fn match_ireg(&mut self, op: &P<TreeNode>) -> bool {
fn match_ireg(&mut self, op: &TreeNode) -> bool {
match op.v {
TreeNode_::Instruction(ref inst) => {
if inst.value.is_some() {
......@@ -737,7 +737,7 @@ impl <'a> InstructionSelection {
unimplemented!()
}
fn emit_get_result(&mut self, node: &P<TreeNode>) -> P<Value> {
fn emit_get_result(&mut self, node: &TreeNode) -> P<Value> {
match node.v {
TreeNode_::Instruction(ref inst) => {
if inst.value.is_some() {
......@@ -817,7 +817,7 @@ impl CompilerPass for InstructionSelection {
self.backend.set_block_liveout(block_label.clone(), &live_out);
for inst in block_content.body.iter() {
self.instruction_select(inst, func, vm);
self.instruction_select(&inst, func, vm);
}
self.backend.end_block(block_label);
......
......@@ -147,12 +147,12 @@ fn layout_struct(tys: &Vec<P<MuType>>, vm: &VM) -> BackendTypeInfo {
}
}
#[derive(Clone, Debug)]
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct BackendTypeInfo {
size: ByteSize,
alignment: ByteSize,
struct_layout: Option<Vec<ByteSize>>
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
pub enum RegGroup {GPR, FPR}
......@@ -54,7 +54,7 @@ impl CompilerPass for DefUse {
// if an SSA appears in operands of instrs, its use count increases
match node.v {
TreeNode_::Instruction(ref inst) => {
for op in inst.ops.borrow().iter() {