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

draft ir.rs

parent 241e50c3
use ast::types::*; use ast::types::*;
use std::sync::Arc;
pub type WPID = usize;
pub type MuID = usize;
pub type MuTag = &'static str;
pub type Address = usize; // TODO: replace this with Address(usize)
#[derive(Clone)]
pub struct SSAVar {
id: MuID,
tag:Option<MuTag>,
ty: Arc<MuType_>
}
#[derive(Copy, Clone)]
pub enum MemoryOrder { pub enum MemoryOrder {
NotAtomic, NotAtomic,
Relaxed, Relaxed,
...@@ -10,6 +24,218 @@ pub enum MemoryOrder { ...@@ -10,6 +24,218 @@ pub enum MemoryOrder {
SeqCst 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,
Foreign(ForeignFFI)
}
#[derive(Copy, Clone)]
pub enum ForeignFFI {
C
}
#[derive(Clone)]
pub struct CallData {
func: SSAVar,
args: Vec<SSAVar>,
convention: CallConvention
}
#[derive(Clone)]
pub struct Block<'func> {
args: Vec<SSAVar>,
body: Vec<Instruction>,
exit: Terminal<'func>,
keepalives: Vec<SSAVar>
}
#[derive(Clone)]
pub struct TerminationData<'func> {
normal_dest: Destination<'func>,
exn_dest: Destination<'func>
}
#[derive(Clone)]
pub enum DestArg {
Normal(SSAVar),
Freshbound(usize)
}
#[derive(Clone)]
pub struct Destination<'func> {
block: &'func Block<'func>,
args: Vec<DestArg>
}
#[derive(Clone)]
pub enum Value {
Int(usize, usize),
IRef(Arc<MuType_>, Address),
FloatV(f32),
DoubleV(f64),
VectorV(Vec<Value>),
FuncRefV(Address),
UFuncRefV(Address)
}
#[derive(Clone)]
pub enum Expression {
BinOp(BinOp, SSAVar, SSAVar),
Value(Value),
// memory operations
CmpXchg{
is_iref: bool, // T for iref, F for ptr
is_strong: bool,
success_order: MemoryOrder,
fail_order: MemoryOrder,
mem_loc: SSAVar,
expected_value: SSAVar,
desired_value: SSAVar
},
AtomicRMW{
is_iref: bool, // T for iref, F for ptr
order: MemoryOrder,
op: AtomicRMWOp,
mem_loc: SSAVar,
value: SSAVar // operand for op
},
Fence(MemoryOrder),
// allocation operations
New(Arc<MuType_>),
AllocA(Arc<MuType_>),
NewHybrid{ // hybrid type, var part length
ty: Arc<MuType_>,
var_len: SSAVar
},
AllocAHybrid{
ty: Arc<MuType_>,
var_len: SSAVar
},
NewStack{
func: SSAVar
},
NewThread{
stack: SSAVar,
args: Vec<SSAVar>
},
NewThreadExn{ // NewThreadExn SSAVar (* stack id *) SSAVar (* exception value *) ???
stack: SSAVar,
exn: SSAVar
},
PushFrame{
stack: SSAVar,
func: SSAVar
},
PopFrame{
stack: SSAVar
}
}
#[derive(Clone)]
pub enum Instruction {
Assign{
left: Vec<SSAVar>,
right: Expression
},
Load{
dest: SSAVar,
is_iref: bool,
mem_loc: SSAVar,
order: MemoryOrder
},
Store{
src: SSAVar,
is_iref: bool,
mem_loc: SSAVar,
order: MemoryOrder
}
}
#[derive(Clone)]
pub enum Terminal<'func> {
Return(Vec<SSAVar>),
ThreadExit,
Throw(Vec<SSAVar>),
TailCall(CallData),
Branch1(Destination<'func>),
Branch2{
cond: SSAVar,
true_dest: Destination<'func>,
false_dest: Destination<'func>
},
Watchpoint, // TODO: Watchpoint ((wpid # destination) option) termination_data
WPBranch{
wp: WPID,
disable_dest: Destination<'func>,
enable_dest: Destination<'func>
},
Call{
data: CallData,
normal_dest: Destination<'func>,
exn_dest: Destination<'func>
},
SwapStack{
stack: SSAVar,
args: Vec<SSAVar>,
normal_dest: Destination<'func>,
exn_dest: Destination<'func>
},
Switch{
cond: SSAVar,
default: Destination<'func>,
branches: Vec<(Value, Destination<'func>)>
},
ExnInstruction{
inner: Expression,
term: TerminationData<'func>
}
}
#[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>)>
}
}
#[derive(Copy, Clone)]
pub enum BinOp { pub enum BinOp {
// Int(n) BinOp Int(n) -> Int(n) // Int(n) BinOp Int(n) -> Int(n)
Add, Add,
...@@ -35,6 +261,7 @@ pub enum BinOp { ...@@ -35,6 +261,7 @@ pub enum BinOp {
FRem FRem
} }
#[derive(Copy, Clone)]
pub enum CmpOp { pub enum CmpOp {
// for Int comparison // for Int comparison
EQ, EQ,
...@@ -67,20 +294,17 @@ pub enum CmpOp { ...@@ -67,20 +294,17 @@ pub enum CmpOp {
FUNO FUNO
} }
pub enum Literal_ { #[derive(Copy, Clone)]
LitIntDec(usize, MuType_), pub enum AtomicRMWOp {
LitIntHex(usize, MuType_), XCHG,
ADD,
LitFP(f64, MuType_), SUB,
LitFPNaN(MuType_), AND,
LitFPInfPos(MuType_), NAND,
LitFPInfNeg(MuType_), OR,
XOR,
LitNull(MuType_) MAX,
} MIN,
UMAX,
pub struct SSAVar { UMIN
id: MuID,
tag:Option<MuTag>,
ty: MuType_
} }
\ No newline at end of file
pub mod types; pub mod types;
\ No newline at end of file pub mod ir;
\ No newline at end of file
extern crate std; extern crate std;
use ast::ir::*;
use std::collections::HashMap; use std::collections::HashMap;
use std::sync::RwLock; use std::sync::RwLock;
use std::sync::Arc;
pub type MuID = usize;
pub type MuTag = &'static str;
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
pub enum MuType { pub enum MuType_ {
/// int <length> /// int <length>
Int (usize), Int (usize),
/// float /// float
...@@ -16,23 +15,23 @@ pub enum MuType { ...@@ -16,23 +15,23 @@ pub enum MuType {
Double, Double,
/// ref<T> /// ref<T>
Ref (Box<MuType>), // Box is needed for non-recursive enum Ref (Arc<MuType_>), // Box is needed for non-recursive enum
/// iref<T>: internal reference /// iref<T>: internal reference
IRef (Box<MuType>), IRef (Arc<MuType_>),
/// weakref<T> /// weakref<T>
WeakRef (Box<MuType>), WeakRef (Arc<MuType_>),
/// uptr<T>: unsafe pointer /// uptr<T>: unsafe pointer
UPtr (Box<MuType>), UPtr (Arc<MuType_>),
/// struct<T1 T2 ...> /// struct<T1 T2 ...>
Struct (MuTag), Struct (MuTag),
/// array<T length> /// array<T length>
Array (Box<MuType>, usize), Array (Arc<MuType_>, usize),
/// hybrid<F1 F2 ... V>: a hybrid of fixed length parts and a variable length part /// hybrid<F1 F2 ... V>: a hybrid of fixed length parts and a variable length part
Hybrid (Vec<Box<MuType>>, Box<MuType>), Hybrid (Vec<Arc<MuType_>>, Arc<MuType_>),
/// void /// void
Void, Void,
...@@ -46,7 +45,7 @@ pub enum MuType { ...@@ -46,7 +45,7 @@ pub enum MuType {
Tagref64, Tagref64,
/// vector<T length> /// vector<T length>
Vector (Box<MuType>, usize), Vector (Arc<MuType_>, usize),
/// funcref<@sig> /// funcref<@sig>
FuncRef (MuFuncSig), FuncRef (MuFuncSig),
...@@ -62,49 +61,49 @@ lazy_static! { ...@@ -62,49 +61,49 @@ lazy_static! {
#[derive(Clone, PartialEq, Eq, Debug)] #[derive(Clone, PartialEq, Eq, Debug)]
pub struct StructType_ { pub struct StructType_ {
tys: Vec<Box<MuType>> tys: Vec<Arc<MuType_>>
} }
impl StructType_ { impl StructType_ {
pub fn set_tys(&mut self, list: Vec<&MuType>) { pub fn set_tys(&mut self, mut list: Vec<Arc<MuType_>>) {
self.tys.clear(); self.tys.clear();
self.tys.append(&mut list.into_iter().map(|t| Box::new(t.clone())).collect()); self.tys.append(&mut list);
} }
} }
impl MuType { impl MuType_ {
pub fn int(len: usize) -> MuType { pub fn int(len: usize) -> MuType_ {
MuType::Int(len) MuType_::Int(len)
} }
pub fn float() -> MuType { pub fn float() -> MuType_ {
MuType::Float MuType_::Float
} }
pub fn double() -> MuType { pub fn double() -> MuType_ {
MuType::Double MuType_::Double
} }
pub fn muref(referent: &MuType) -> MuType { pub fn muref(referent: Arc<MuType_>) -> MuType_ {
MuType::Ref(Box::new(referent.clone())) MuType_::Ref(referent)
} }
pub fn muref_void() -> MuType { pub fn muref_void() -> MuType_ {
MuType::Ref(Box::new(MuType::void())) MuType_::Ref(Arc::new(MuType_::void()))
} }
pub fn iref(referent: &MuType) -> MuType { pub fn iref(referent: Arc<MuType_>) -> MuType_ {
MuType::IRef(Box::new(referent.clone())) MuType_::IRef(referent)
} }
pub fn weakref(referent: &MuType) -> MuType { pub fn weakref(referent: Arc<MuType_>) -> MuType_ {
MuType::WeakRef(Box::new(referent.clone())) MuType_::WeakRef(referent)
} }
pub fn uptr(referent: &MuType) -> MuType { pub fn uptr(referent: Arc<MuType_>) -> MuType_ {
MuType::UPtr(Box::new(referent.clone())) MuType_::UPtr(referent)
} }
pub fn mustruct_empty(tag: MuTag) -> MuType { pub fn mustruct_empty(tag: MuTag) -> MuType_ {
let struct_ty_ = StructType_{tys: vec![]}; let struct_ty_ = StructType_{tys: vec![]};
STRUCT_TAG_MAP.write().unwrap().insert(tag, struct_ty_); STRUCT_TAG_MAP.write().unwrap().insert(tag, struct_ty_);
MuType::Struct(tag) MuType_::Struct(tag)
} }
pub fn mustruct(tag: MuTag, list: Vec<&MuType>) -> MuType { pub fn mustruct(tag: MuTag, list: Vec<Arc<MuType_>>) -> MuType_ {
let struct_ty_ = StructType_{tys: list.into_iter().map(|t| Box::new(t.clone())).collect()}; let struct_ty_ = StructType_{tys: list};
// if there is an attempt to use a same tag for different struct, // if there is an attempt to use a same tag for different struct,
// we panic // we panic
...@@ -121,93 +120,90 @@ impl MuType { ...@@ -121,93 +120,90 @@ impl MuType {
// otherwise, store the tag // otherwise, store the tag
STRUCT_TAG_MAP.write().unwrap().insert(tag, struct_ty_); STRUCT_TAG_MAP.write().unwrap().insert(tag, struct_ty_);
MuType::Struct(tag) MuType_::Struct(tag)
} }
pub fn array(ty: &MuType, len: usize) -> MuType { pub fn array(ty: Arc<MuType_>, len: usize) -> MuType_ {
MuType::Array(Box::new(ty.clone()), len) MuType_::Array(ty, len)
} }
pub fn hybrid(fix_tys: Vec<&MuType>, var_ty: &MuType) -> MuType { pub fn hybrid(fix_tys: Vec<Arc<MuType_>>, var_ty: Arc<MuType_>) -> MuType_ {
MuType::Hybrid( MuType_::Hybrid(fix_tys, var_ty)
fix_tys.into_iter().map(|t| Box::new(t.clone())).collect(),
Box::new(var_ty.clone())
)
} }
pub fn void() -> MuType { pub fn void() -> MuType_ {
MuType::Void MuType_::Void
} }
pub fn threadref() -> MuType { pub fn threadref() -> MuType_ {
MuType::ThreadRef MuType_::ThreadRef
} }
pub fn stackref() -> MuType { pub fn stackref() -> MuType_ {
MuType::StackRef MuType_::StackRef
} }
pub fn tagref64() -> MuType { pub fn tagref64() -> MuType_ {
MuType::Tagref64 MuType_::Tagref64
} }
pub fn vector(ty: &MuType, len: usize) -> MuType { pub fn vector(ty: Arc<MuType_>, len: usize) -> MuType_ {
MuType::Vector(Box::new(ty.clone()), len) MuType_::Vector(ty, len)
} }
pub fn funcref(sig: MuFuncSig) -> MuType { pub fn funcref(sig: MuFuncSig) -> MuType_ {
MuType::FuncRef(sig) MuType_::FuncRef(sig)
} }
pub fn ufuncptr(sig: MuFuncSig) -> MuType { pub fn ufuncptr(sig: MuFuncSig) -> MuType_ {
MuType::UFuncPtr(sig) MuType_::UFuncPtr(sig)
} }
} }
/// is a type floating-point type? /// is a type floating-point type?
pub fn is_fp(ty: &MuType) -> bool { pub fn is_fp(ty: &MuType_) -> bool {
match *ty { match *ty {
MuType::Float | MuType::Double => true, MuType_::Float | MuType_::Double => true,
_ => false _ => false
} }
} }
/// is a type raw pointer? /// is a type raw pointer?
pub fn is_ptr(ty: &MuType) -> bool { pub fn is_ptr(ty: &MuType_) -> bool {
match *ty { match *ty {
MuType::UPtr(_) | MuType::UFuncPtr(_) => true, MuType_::UPtr(_) | MuType_::UFuncPtr(_) => true,
_ => false _ => false
} }
} }
/// is a type scalar type? /// is a type scalar type?
pub fn is_scalar(ty: &MuType) -> bool { pub fn is_scalar(ty: &MuType_) -> bool {
match *ty { match *ty {
MuType::Int(_) MuType_::Int(_)
| MuType::Float | MuType_::Float
| MuType::Double | MuType_::Double
| MuType::Ref(_) | MuType_::Ref(_)
| MuType::IRef(_) | MuType_::IRef(_)
| MuType::WeakRef(_) | MuType_::WeakRef(_)
| MuType::FuncRef(_) | MuType_::FuncRef(_)
| MuType::UFuncPtr(_) | MuType_::UFuncPtr(_)
| MuType::ThreadRef | MuType_::ThreadRef
| MuType::StackRef | MuType_::StackRef
| MuType::Tagref64 | MuType_::Tagref64
| MuType::UPtr(_) => true, | MuType_::UPtr(_) => true,
_ => false _ => false
} }
} }
/// is a type traced by the garbage collector? /// is a type traced by the garbage collector?
/// Note: An aggregated type is traced if any of its part is traced. /// Note: An aggregated type is traced if any of its part is traced.
pub fn is_traced(ty: &MuType) -> bool { pub fn is_traced(ty: &MuType_) -> bool {
match *ty { match *ty {
MuType::Ref(_) => true, MuType_::Ref(_) => true,
MuType::IRef(_) => true, MuType_::IRef(_) => true,
MuType::WeakRef(_) => true, MuType_::WeakRef(_) => true,
MuType::Array(ref elem_ty, _) MuType_::Array(ref elem_ty, _)
| MuType::Vector(ref elem_ty, _) => is_traced(elem_ty), | MuType_::Vector(ref elem_ty, _) => is_traced(elem_ty),
MuType::ThreadRef MuType_::ThreadRef
| MuType::StackRef | MuType_::StackRef
| MuType::Tagref64 => true, | MuType_::Tagref64 => true,
MuType::Hybrid(ref fix_tys, ref var_ty) => { MuType_::Hybrid(ref fix_tys, ref var_ty) => {
is_traced(var_ty) || is_traced(var_ty) ||
fix_tys.into_iter().map(|ty| is_traced(ty)) fix_tys.into_iter().map(|ty| is_traced(ty))
.fold(false, |ret, this| ret || this) .fold(false, |ret, this| ret || this)
}, },
MuType::Struct(tag) => { MuType_::Struct(tag) => {
let map = STRUCT_TAG_MAP.read().unwrap();