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 47b56f7d authored by qinsoon's avatar qinsoon
Browse files

a test to construct a factorial fucntion

parent af6c5e98
#![allow(dead_code)]
#![allow(unused_variables)]
use ast::ptr::P;
use ast::types::*;
use std::sync::Arc;
pub type WPID = usize;
pub type MuID = usize;
......@@ -8,9 +11,15 @@ pub type Address = usize; // TODO: replace this with Address(usize)
#[derive(Clone)]
pub struct SSAVar {
id: MuID,
tag:Option<MuTag>,
ty: Arc<MuType_>
pub id: MuID,
pub tag: MuTag,
pub ty: P<MuType_>
}
#[derive(Clone)]
pub enum Value {
SSAVar(SSAVar),
Constant(MuConstant)
}
#[derive(Copy, Clone)]
......@@ -24,18 +33,6 @@ pub enum MemoryOrder {
SeqCst
}
#[derive(Clone)]
pub enum Literal {
LitInt(usize, Arc<MuType_>),
LitFP(f64, Arc<MuType_>),
LitFPNaN(Arc<MuType_>),
LitFPInfPos(Arc<MuType_>),
LitFPInfNeg(Arc<MuType_>),
LitNull(Arc<MuType_>)
}
#[derive(Copy, Clone)]
pub enum CallConvention {
Mu,
......@@ -47,54 +44,64 @@ pub enum ForeignFFI {
C
}
#[derive(Clone)]
pub struct CallData {
func: SSAVar,
args: Vec<SSAVar>,
convention: CallConvention
pub func: P<SSAVar>,
pub args: Vec<P<Value>>,
pub convention: CallConvention
}
#[derive(Clone)]
pub struct Block<'func> {
args: Vec<SSAVar>,
body: Vec<Instruction>,
exit: Terminal<'func>,
keepalives: Vec<SSAVar>
pub struct Block {
label: MuTag,
content: Option<BlockContent>
}
#[derive(Clone)]
pub struct TerminationData<'func> {
normal_dest: Destination<'func>,
exn_dest: Destination<'func>
impl Block {
pub fn new(label: MuTag) -> Block {
Block{label: label, content: None}
}
pub fn set_content(&mut self, v: BlockContent) {
self.content = Some(v);
}
}
pub struct BlockContent {
pub args: Vec<P<Value>>,
pub body: Vec<Instruction>,
pub exit: Terminal,
pub keepalives: Option<Vec<P<SSAVar>>>
}
pub struct TerminationData {
normal_dest: Destination,
exn_dest: Destination
}
#[derive(Clone)]
pub enum DestArg {
Normal(SSAVar),
Normal(P<Value>),
Freshbound(usize)
}
#[derive(Clone)]
pub struct Destination<'func> {
block: &'func Block<'func>,
args: Vec<DestArg>
pub struct Destination {
pub target: MuTag,
pub args: Vec<DestArg>
}
#[derive(Clone)]
pub enum Value {
pub enum Constant {
Int(usize, usize),
IRef(Arc<MuType_>, Address),
IRef(P<MuType_>, Address),
FloatV(f32),
DoubleV(f64),
VectorV(Vec<Value>),
VectorV(Vec<Constant>),
FuncRefV(Address),
UFuncRefV(Address)
}
#[derive(Clone)]
pub enum Expression {
BinOp(BinOp, SSAVar, SSAVar),
Value(Value),
BinOp(BinOp, P<Value>, P<Value>),
CmpOp(CmpOp, P<Value>, P<Value>),
Constant(P<Constant>),
// memory operations
......@@ -103,136 +110,136 @@ pub enum Expression {
is_strong: bool,
success_order: MemoryOrder,
fail_order: MemoryOrder,
mem_loc: SSAVar,
expected_value: SSAVar,
desired_value: SSAVar
mem_loc: P<SSAVar>,
expected_value: P<Value>,
desired_value: P<Value>
},
AtomicRMW{
is_iref: bool, // T for iref, F for ptr
order: MemoryOrder,
op: AtomicRMWOp,
mem_loc: SSAVar,
value: SSAVar // operand for op
mem_loc: P<Value>,
value: P<Value> // operand for op
},
Fence(MemoryOrder),
// allocation operations
New(Arc<MuType_>),
AllocA(Arc<MuType_>),
New(P<MuType_>),
AllocA(P<MuType_>),
NewHybrid{ // hybrid type, var part length
ty: Arc<MuType_>,
var_len: SSAVar
ty: P<MuType_>,
var_len: P<Value>
},
AllocAHybrid{
ty: Arc<MuType_>,
var_len: SSAVar
ty: P<MuType_>,
var_len: P<Value>
},
NewStack{
func: SSAVar
func: P<Value>
},
NewThread{
stack: SSAVar,
args: Vec<SSAVar>
stack: P<Value>,
args: Vec<P<Value>>
},
NewThreadExn{ // NewThreadExn SSAVar (* stack id *) SSAVar (* exception value *) ???
stack: SSAVar,
exn: SSAVar
stack: P<Value>,
exn: P<Value>
},
PushFrame{
stack: SSAVar,
func: SSAVar
stack: P<Value>,
func: P<Value>
},
PopFrame{
stack: SSAVar
stack: P<Value>
}
}
#[derive(Clone)]
pub enum Instruction {
Assign{
left: Vec<SSAVar>,
left: Vec<P<Value>>,
right: Expression
},
Load{
dest: SSAVar,
dest: P<SSAVar>,
is_iref: bool,
mem_loc: SSAVar,
mem_loc: P<Value>,
order: MemoryOrder
},
Store{
src: SSAVar,
src: P<SSAVar>,
is_iref: bool,
mem_loc: SSAVar,
mem_loc: P<Value>,
order: MemoryOrder
}
}
#[derive(Clone)]
pub enum Terminal<'func> {
Return(Vec<SSAVar>),
pub enum Terminal {
Return(Vec<P<Value>>),
ThreadExit,
Throw(Vec<SSAVar>),
Throw(Vec<P<Value>>),
TailCall(CallData),
Branch1(Destination<'func>),
Branch1(Destination),
Branch2{
cond: SSAVar,
true_dest: Destination<'func>,
false_dest: Destination<'func>
cond: P<Value>,
true_dest: Destination,
false_dest: Destination
},
Watchpoint, // TODO: Watchpoint ((wpid # destination) option) termination_data
WPBranch{
wp: WPID,
disable_dest: Destination<'func>,
enable_dest: Destination<'func>
disable_dest: Destination,
enable_dest: Destination
},
Call{
data: CallData,
normal_dest: Destination<'func>,
exn_dest: Destination<'func>
normal_dest: Destination,
exn_dest: Option<Destination>
},
SwapStack{
stack: SSAVar,
args: Vec<SSAVar>,
normal_dest: Destination<'func>,
exn_dest: Destination<'func>
stack: P<Value>,
args: Vec<P<Value>>,
normal_dest: Destination,
exn_dest: Destination
},
Switch{
cond: SSAVar,
default: Destination<'func>,
branches: Vec<(Value, Destination<'func>)>
cond: P<Value>,
default: Destination,
branches: Vec<(P<Constant>, Destination)>
},
ExnInstruction{
inner: Expression,
term: TerminationData<'func>
term: TerminationData
}
}
#[derive(Clone)]
pub enum Declaration<'global> {
ConstDecl{
const_name: MuTag,
ty: Arc<MuType_>,
val: Value
},
TypeDef{
type_name: MuTag,
ty: Arc<MuType_>
},
FunctionSignature{
sig_name: MuTag,
ret_tys: Vec<Arc<MuType_>>,
arg_tys: Vec<Arc<MuType_>>
},
FuncDef{
fn_name: MuTag,
sig_name: MuTag,
label: MuTag, // ?
blocks: Vec<(MuTag, Block<'global>)>
}
pub struct MuConstant{
ty: P<MuType_>,
val: Constant
}
pub struct MuFunction {
pub fn_name: MuTag,
pub sig: P<MuFuncSig>,
pub entry: MuTag,
pub blocks: Vec<(MuTag, Block)>
}
pub fn declare_const(const_name: MuTag, ty: P<MuType_>, val: Constant) -> Value {
Value::Constant(MuConstant{ty: ty, val: val})
}
pub fn declare_type(type_name: MuTag, ty: P<MuType_>) -> P<MuType_> {
ty
}
pub fn declare_func_sig(sig_name: MuTag, ret_tys: Vec<P<MuType_>>, arg_tys: Vec<P<MuType_>>) -> MuFuncSig {
MuFuncSig::new(ret_tys, arg_tys)
}
pub fn declare_func (fn_name: MuTag, sig: P<MuFuncSig>, entry: MuTag, blocks: Vec<(MuTag, Block)>) -> MuFunction {
MuFunction{fn_name: fn_name, sig: sig, entry: entry, blocks: blocks}
}
#[derive(Copy, Clone)]
......
pub mod types;
pub mod ir;
\ No newline at end of file
pub mod ir;
pub mod ptr;
\ No newline at end of file
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
//! The AST pointer
//!
//! Provides `P<T>`, a frozen owned smart pointer, as a replacement for `@T` in
//! the AST.
//!
//! # Motivations and benefits
//!
//! * **Identity**: sharing AST nodes is problematic for the various analysis
//! passes (e.g. one may be able to bypass the borrow checker with a shared
//! `ExprAddrOf` node taking a mutable borrow). The only reason `@T` in the
//! AST hasn't caused issues is because of inefficient folding passes which
//! would always deduplicate any such shared nodes. Even if the AST were to
//! switch to an arena, this would still hold, i.e. it couldn't use `&'a T`,
//! but rather a wrapper like `P<'a, T>`.
//!
//! * **Immutability**: `P<T>` disallows mutating its inner `T`, unlike `Box<T>`
//! (unless it contains an `Unsafe` interior, but that may be denied later).
//! This mainly prevents mistakes, but can also enforces a kind of "purity".
//!
//! * **Efficiency**: folding can reuse allocation space for `P<T>` and `Vec<T>`,
//! the latter even when the input and output types differ (as it would be the
//! case with arenas or a GADT AST using type parameters to toggle features).
//!
//! * **Maintainability**: `P<T>` provides a fixed interface - `Deref`,
//! `and_then` and `map` - which can remain fully functional even if the
//! 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::ptr;
/// An owned smart pointer.
pub struct P<T> {
ptr: Box<T>
}
#[allow(non_snake_case)]
/// Construct a `P<T>` from a `T` value.
pub fn P<T: 'static>(value: T) -> P<T> {
P {
ptr: Box::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> {
type Target = T;
fn deref<'a>(&'a self) -> &'a T {
&*self.ptr
}
}
impl<T: 'static + Clone> Clone for P<T> {
fn clone(&self) -> P<T> {
P((**self).clone())
}
}
impl<T: PartialEq> PartialEq for P<T> {
fn eq(&self, other: &P<T>) -> bool {
**self == **other
}
}
impl<T: Eq> Eq for P<T> {}
impl<T: 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> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
Display::fmt(&**self, f)
}
}
impl<T> 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> {
fn hash<H: Hasher>(&self, state: &mut H) {
(**self).hash(state);
}
}
extern crate std;
use ast::ptr::*;
use ast::ir::*;
use std::collections::HashMap;
use std::sync::RwLock;
use std::sync::Arc;
#[derive(Clone, PartialEq, Eq, Debug)]
pub enum MuType_ {
......@@ -15,23 +15,23 @@ pub enum MuType_ {
Double,
/// ref<T>
Ref (Arc<MuType_>), // Box is needed for non-recursive enum
Ref (P<MuType_>), // Box is needed for non-recursive enum
/// iref<T>: internal reference
IRef (Arc<MuType_>),
IRef (P<MuType_>),
/// weakref<T>
WeakRef (Arc<MuType_>),
WeakRef (P<MuType_>),
/// uptr<T>: unsafe pointer
UPtr (Arc<MuType_>),
UPtr (P<MuType_>),
/// struct<T1 T2 ...>
Struct (MuTag),
/// array<T length>
Array (Arc<MuType_>, usize),
Array (P<MuType_>, usize),
/// hybrid<F1 F2 ... V>: a hybrid of fixed length parts and a variable length part
Hybrid (Vec<Arc<MuType_>>, Arc<MuType_>),
Hybrid (Vec<P<MuType_>>, P<MuType_>),
/// void
Void,
......@@ -45,27 +45,27 @@ pub enum MuType_ {
Tagref64,
/// vector<T length>
Vector (Arc<MuType_>, usize),
Vector (P<MuType_>, usize),
/// funcref<@sig>
FuncRef (MuFuncSig),
FuncRef (P<MuFuncSig>),
/// ufuncptr<@sig>
UFuncPtr (MuFuncSig),
UFuncPtr (P<MuFuncSig>),
}
lazy_static! {
/// storing a map from MuTag to StructType_
static ref STRUCT_TAG_MAP : RwLock<HashMap<MuTag, StructType_>> = RwLock::new(HashMap::new());
pub static ref STRUCT_TAG_MAP : RwLock<HashMap<MuTag, StructType_>> = RwLock::new(HashMap::new());
}
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct StructType_ {
tys: Vec<Arc<MuType_>>
tys: Vec<P<MuType_>>
}
impl StructType_ {
pub fn set_tys(&mut self, mut list: Vec<Arc<MuType_>>) {
pub fn set_tys(&mut self, mut list: Vec<P<MuType_>>) {
self.tys.clear();
self.tys.append(&mut list);
}
......@@ -81,19 +81,19 @@ impl MuType_ {
pub fn double() -> MuType_ {
MuType_::Double
}
pub fn muref(referent: Arc<MuType_>) -> MuType_ {
pub fn muref(referent: P<MuType_>) -> MuType_ {
MuType_::Ref(referent)
}
pub fn muref_void() -> MuType_ {
MuType_::Ref(Arc::new(MuType_::void()))
MuType_::Ref(P(MuType_::void()))
}
pub fn iref(referent: Arc<MuType_>) -> MuType_ {
pub fn iref(referent: P<MuType_>) -> MuType_ {
MuType_::IRef(referent)
}
pub fn weakref(referent: Arc<MuType_>) -> MuType_ {
pub fn weakref(referent: P<MuType_>) -> MuType_ {
MuType_::WeakRef(referent)
}
pub fn uptr(referent: Arc<MuType_>) -> MuType_ {
pub fn uptr(referent: P<MuType_>) -> MuType_ {
MuType_::UPtr(referent)
}
pub fn mustruct_empty(tag: MuTag) -> MuType_ {
......@@ -102,7 +102,7 @@ impl MuType_ {
MuType_::Struct(tag)
}
pub fn mustruct(tag: MuTag, list: Vec<Arc<MuType_>>) -> MuType_ {
pub fn mustruct(tag: MuTag, list: Vec<P<MuType_>>) -> MuType_ {
let struct_ty_ = StructType_{tys: list};
// if there is an attempt to use a same tag for different struct,
......@@ -122,10 +122,10 @@ impl MuType_ {
MuType_::Struct(tag)
}
pub fn array(ty: Arc<MuType_>, len: usize) -> MuType_ {
pub fn array(ty: P<MuType_>, len: usize) -> MuType_ {
MuType_::Array(ty, len)
}
pub fn hybrid(fix_tys: Vec<Arc<MuType_>>, var_ty: Arc<MuType_>) -> MuType_ {
pub fn hybrid(fix_tys: Vec<P<MuType_>>, var_ty: P<MuType_>) -> MuType_ {
MuType_::Hybrid(fix_tys, var_ty)
}
pub fn void() -> MuType_ {
......@@ -140,13 +140,13 @@ impl MuType_ {
pub fn tagref64() -> MuType_ {
MuType_::Tagref64
}
pub fn vector(ty: Arc<MuType_>, len: usize) -> MuType_ {
pub fn vector(ty: P<MuType_>, len: usize) -> MuType_ {
MuType_::Vector(ty, len)
}
pub fn funcref(sig: MuFuncSig) -> MuType_ {
pub fn funcref(sig: P<MuFuncSig>) -> MuType_ {
MuType_::FuncRef(sig)
}
pub fn ufuncptr(sig: MuFuncSig) -> MuType_ {
pub fn ufuncptr(sig: P<MuFuncSig>) -> MuType_ {
MuType_::UFuncPtr(sig)
}
}
......@@ -255,204 +255,12 @@ macro_rules! is_type (
#[derive(Clone, PartialEq, Eq, Debug)]
pub struct MuFuncSig {
ret_tys : Vec<Arc<MuType_>>,
args_tys: Vec<Arc<MuType_>>
ret_tys : Vec<P<MuType_>>,
arg_tys: Vec<P<MuType_>>
}
impl MuFuncSig {
pub fn new(ret_tys: Vec<Arc<MuType_>>, args_tys: Vec<Arc<MuType_>>) -> MuFuncSig {
MuFuncSig {ret_tys : ret_tys, args_tys: args_tys}
}
}
#[cfg(test)]
mod tests {
use super::*;
use super::STRUCT_TAG_MAP;
use std::sync::Arc;
macro_rules! assert_type (
($test:expr, $expect: expr) => (
assert_eq!(format!("{:?}", $test), $expect)
)
);
macro_rules! println_type (