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 49e961dd authored by Isaac Oscar Gariano's avatar Isaac Oscar Gariano
Browse files

Converted line endings to UNIX style

parent 83f6e292
......@@ -7,7 +7,7 @@ Cargo.lock
*.log
*.DS_Store
*.swp
.idea
.idea
*.pyc
*.o
*.dylib
......
use ptr::P;
use types::*;
use inst::*;
use op::*;
use utils::vec_utils;
use utils::LinkedHashMap;
use utils::LinkedHashSet;
use std::fmt;
use std::default;
use std::sync::RwLock;
use std::sync::atomic::{AtomicUsize, ATOMIC_USIZE_INIT, Ordering};
pub type WPID = usize;
pub type MuID = usize;
pub type MuName = String;
pub type CName = MuName;
#[allow(non_snake_case)]
pub fn Mu(str: &'static str) -> MuName {str.to_string()}
#[allow(non_snake_case)]
pub fn C(str: &'static str) -> CName {str.to_string()}
pub type OpIndex = usize;
lazy_static! {
pub static ref MACHINE_ID : AtomicUsize = {
let a = ATOMIC_USIZE_INIT;
a.store(MACHINE_ID_START, Ordering::SeqCst);
a
};
pub static ref INTERNAL_ID : AtomicUsize = {
let a = ATOMIC_USIZE_INIT;
a.store(INTERNAL_ID_START, Ordering::SeqCst);
a
};
}
pub const MACHINE_ID_START : usize = 0;
pub const MACHINE_ID_END : usize = 200;
pub const INTERNAL_ID_START: usize = 201;
pub const INTERNAL_ID_END : usize = 500;
pub const USER_ID_START : usize = 1001;
#[deprecated]
#[allow(dead_code)]
/// it could happen that one same machine register get different IDs
/// during serialization and restoring
/// currently I hand-write fixed ID for each machine register
pub fn new_machine_id() -> MuID {
let ret = MACHINE_ID.fetch_add(1, Ordering::SeqCst);
if ret >= MACHINE_ID_END {
panic!("machine id overflow")
}
ret
}
pub fn new_internal_id() -> MuID {
let ret = INTERNAL_ID.fetch_add(1, Ordering::SeqCst);
if ret >= INTERNAL_ID_END {
panic!("internal id overflow")
}
ret
}
#[derive(Debug, RustcEncodable, RustcDecodable)]
pub struct MuFunction {
pub hdr: MuEntityHeader,
pub sig: P<MuFuncSig>,
pub cur_ver: Option<MuID>,
pub all_vers: Vec<MuID>
}
impl MuFunction {
pub fn new(id: MuID, sig: P<MuFuncSig>) -> MuFunction {
MuFunction {
hdr: MuEntityHeader::unnamed(id),
sig: sig,
cur_ver: None,
all_vers: vec![]
}
}
pub fn new_version(&mut self, fv: MuID) {
if self.cur_ver.is_some() {
let obsolete_ver = self.cur_ver.unwrap();
self.all_vers.push(obsolete_ver);
}
self.cur_ver = Some(fv);
}
}
impl fmt::Display for MuFunction {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Func {}", self.hdr)
}
}
#[derive(RustcEncodable, RustcDecodable)]
pub struct MuFunctionVersion {
pub hdr: MuEntityHeader,
pub func_id: MuID,
pub sig: P<MuFuncSig>,
orig_content: Option<FunctionContent>,
pub content: Option<FunctionContent>,
is_defined: bool,
is_compiled: bool,
pub context: FunctionContext,
pub force_inline: bool,
pub block_trace: Option<Vec<MuID>> // only available after Trace Generation Pass
}
impl fmt::Display for MuFunctionVersion {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "FuncVer {} of Func #{}", self.hdr, self.func_id)
}
}
impl fmt::Debug for MuFunctionVersion {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "FuncVer {} of Func #{}\n", self.hdr, self.func_id).unwrap();
write!(f, "Signature: {}\n", self.sig).unwrap();
write!(f, "IR:\n").unwrap();
if self.content.is_some() {
write!(f, "{:?}\n", self.content.as_ref().unwrap()).unwrap();
} else {
write!(f, "Empty\n").unwrap();
}
if self.block_trace.is_some() {
write!(f, "Block Trace: {:?}\n", self.block_trace.as_ref().unwrap())
} else {
write!(f, "Trace not available\n")
}
}
}
impl MuFunctionVersion {
pub fn new(id: MuID, func: MuID, sig: P<MuFuncSig>) -> MuFunctionVersion {
MuFunctionVersion{
hdr: MuEntityHeader::unnamed(id),
func_id: func,
sig: sig,
orig_content: None,
content: None,
is_defined: false,
is_compiled: false,
context: FunctionContext::new(),
block_trace: None,
force_inline: false
}
}
pub fn new_(hdr: MuEntityHeader, id: MuID, sig: P<MuFuncSig>, content: FunctionContent, context: FunctionContext) -> MuFunctionVersion {
MuFunctionVersion {
hdr: hdr,
func_id: id,
sig: sig,
orig_content: Some(content.clone()),
content: Some(content),
is_defined: true,
is_compiled: false,
context: context,
block_trace: None,
force_inline: false
}
}
pub fn get_orig_ir(&self) -> Option<&FunctionContent> {
self.orig_content.as_ref()
}
pub fn define(&mut self, content: FunctionContent) {
if self.is_defined {
panic!("alread defined the function: {}", self);
}
self.is_defined = true;
self.orig_content = Some(content.clone());
self.content = Some(content);
}
pub fn is_compiled(&self) -> bool {
self.is_compiled
}
pub fn set_compiled(&mut self) {
self.is_compiled = true;
}
pub fn new_ssa(&mut self, id: MuID, ty: P<MuType>) -> P<TreeNode> {
let val = P(Value{
hdr: MuEntityHeader::unnamed(id),
ty: ty,
v: Value_::SSAVar(id)
});
self.context.values.insert(id, SSAVarEntry::new(val.clone()));
P(TreeNode {
op: pick_op_code_for_ssa(&val.ty),
v: TreeNode_::Value(val)
})
}
pub fn new_constant(&mut self, v: P<Value>) -> P<TreeNode> {
P(TreeNode{
op: pick_op_code_for_value(&v.ty),
v: TreeNode_::Value(v)
})
}
pub fn new_global(&mut self, v: P<Value>) -> P<TreeNode> {
P(TreeNode{
op: pick_op_code_for_value(&v.ty),
v: TreeNode_::Value(v)
})
}
pub fn new_inst(&mut self, v: Instruction) -> Box<TreeNode> {
Box::new(TreeNode{
op: pick_op_code_for_inst(&v),
v: TreeNode_::Instruction(v),
})
}
/// get Map(CallSiteID -> FuncID) that are called by this function
pub fn get_static_call_edges(&self) -> LinkedHashMap<MuID, MuID> {
let mut ret = LinkedHashMap::new();
let f_content = self.content.as_ref().unwrap();
for (_, block) in f_content.blocks.iter() {
let block_content = block.content.as_ref().unwrap();
for inst in block_content.body.iter() {
match inst.v {
TreeNode_::Instruction(ref inst) => {
let ops = inst.ops.read().unwrap();
match inst.v {
Instruction_::ExprCall{ref data, ..}
| Instruction_::ExprCCall{ref data, ..}
| Instruction_::Call {ref data, ..}
| Instruction_::CCall {ref data, ..} => {
let ref callee = ops[data.func];
match callee.v {
TreeNode_::Instruction(_) => {},
TreeNode_::Value(ref pv) => match pv.v {
Value_::Constant(Constant::FuncRef(id)) => {ret.insert(inst.id(), id);},
_ => {}
}
}
},
_ => {
// do nothing
}
}
},
_ => {
unreachable!()
}
}
}
}
ret
}
pub fn has_throw(&self) -> bool {
let f_content = self.content.as_ref().unwrap();
for (_, block) in f_content.blocks.iter() {
let block_content = block.content.as_ref().unwrap();
for inst in block_content.body.iter() {
match inst.v {
TreeNode_::Instruction(ref inst) => {
match inst.v {
Instruction_::Throw(_) => {return true;}
_ => {
// do nothing
}
}
},
_ => {
unreachable!()
}
}
}
}
false
}
}
#[derive(Clone, RustcEncodable, RustcDecodable)]
pub struct FunctionContent {
pub entry: MuID,
pub blocks: LinkedHashMap<MuID, Block>,
// this field only valid after control flow analysis
pub exception_blocks: LinkedHashSet<MuID>
}
impl fmt::Debug for FunctionContent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
let entry = self.get_entry_block();
write!(f, "Entry block: ").unwrap();
write!(f, "{:?}\n", entry).unwrap();
write!(f, "Body:").unwrap();
for blk_id in self.blocks.keys() {
let block = self.get_block(*blk_id);
write!(f, "{:?}\n", block).unwrap();
}
Ok(())
}
}
impl FunctionContent {
pub fn new(entry: MuID, blocks: LinkedHashMap<MuID, Block>) -> FunctionContent {
FunctionContent {
entry: entry,
blocks: blocks,
exception_blocks: LinkedHashSet::new()
}
}
pub fn get_entry_block(&self) -> &Block {
self.get_block(self.entry)
}
pub fn get_entry_block_mut(&mut self) -> &mut Block {
let entry = self.entry;
self.get_block_mut(entry)
}
pub fn get_block(&self, id: MuID) -> &Block {
let ret = self.blocks.get(&id);
match ret {
Some(b) => b,
None => panic!("cannot find block #{}", id)
}
}
pub fn get_block_mut(&mut self, id: MuID) -> &mut Block {
let ret = self.blocks.get_mut(&id);
match ret {
Some(b) => b,
None => panic!("cannot find block #{}", id)
}
}
}
#[derive(Default, Debug, RustcEncodable, RustcDecodable)]
pub struct FunctionContext {
pub values: LinkedHashMap<MuID, SSAVarEntry>
}
impl FunctionContext {
fn new() -> FunctionContext {
FunctionContext {
values: LinkedHashMap::new()
}
}
pub fn make_temporary(&mut self, id: MuID, ty: P<MuType>) -> P<TreeNode> {
let val = P(Value{
hdr: MuEntityHeader::unnamed(id),
ty: ty,
v: Value_::SSAVar(id)
});
self.values.insert(id, SSAVarEntry::new(val.clone()));
P(TreeNode {
op: pick_op_code_for_ssa(&val.ty),
v: TreeNode_::Value(val)
})
}
pub fn get_temp_display(&self, id: MuID) -> String {
match self.get_value(id) {
Some(entry) => format!("{}", entry.value()),
None => "CANT_FOUND_ID".to_string()
}
}
pub fn get_value(&self, id: MuID) -> Option<&SSAVarEntry> {
self.values.get(&id)
}
pub fn get_value_mut(&mut self, id: MuID) -> Option<&mut SSAVarEntry> {
self.values.get_mut(&id)
}
}
#[derive(RustcEncodable, RustcDecodable, Clone)]
pub struct Block {
pub hdr: MuEntityHeader,
pub content: Option<BlockContent>,
pub control_flow: ControlFlow
}
impl fmt::Debug for Block {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "Block {}", self.hdr).unwrap();
writeln!(f, "with preds: {:?}", self.control_flow.preds).unwrap();
writeln!(f, " succs: {:?}", self.control_flow.succs).unwrap();
if self.content.is_some() {
writeln!(f, "{:?}", self.content.as_ref().unwrap()).unwrap();
} else {
writeln!(f, "Empty").unwrap();
}
Ok(())
}
}
impl Block {
pub fn new(id: MuID) -> Block {
Block{hdr: MuEntityHeader::unnamed(id), content: None, control_flow: ControlFlow::default()}
}
pub fn is_receiving_exception_arg(&self) -> bool {
return self.content.as_ref().unwrap().exn_arg.is_some()
}
pub fn number_of_irs(&self) -> usize {
if self.content.is_none() {
0
} else {
let content = self.content.as_ref().unwrap();
content.body.len()
}
}
}
#[derive(Debug, RustcEncodable, RustcDecodable, Clone)]
pub struct ControlFlow {
pub preds : Vec<MuID>,
pub succs : Vec<BlockEdge>
}
impl ControlFlow {
pub fn get_hottest_succ(&self) -> Option<MuID> {
if self.succs.len() == 0 {
None
} else {
let mut hot_blk = self.succs[0].target;
let mut hot_prob = self.succs[0].probability;
for edge in self.succs.iter() {
if edge.probability > hot_prob {
hot_blk = edge.target;
hot_prob = edge.probability;
}
}
Some(hot_blk)
}
}
}
impl fmt::Display for ControlFlow {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "preds: [{}], ", vec_utils::as_str(&self.preds)).unwrap();
write!(f, "succs: [{}]", vec_utils::as_str(&self.succs))
}
}
impl default::Default for ControlFlow {
fn default() -> ControlFlow {
ControlFlow {preds: vec![], succs: vec![]}
}
}
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub struct BlockEdge {
pub target: MuID,
pub kind: EdgeKind,
pub is_exception: bool,
pub probability: f32
}
impl fmt::Display for BlockEdge {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{} ({:?}{} - {})", self.target, self.kind, select_value!(self.is_exception, ", exceptional", ""), self.probability)
}
}
#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable)]
pub enum EdgeKind {
Forward, Backward
}
#[derive(RustcEncodable, RustcDecodable, Clone)]
pub struct BlockContent {
pub args: Vec<P<Value>>,
pub exn_arg: Option<P<Value>>,
pub body: Vec<Box<TreeNode>>,
pub keepalives: Option<Vec<P<Value>>>
}
impl fmt::Debug for BlockContent {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
writeln!(f, "args: {}", vec_utils::as_str(&self.args)).unwrap();
if self.exn_arg.is_some() {
writeln!(f, "exception arg: {}", self.exn_arg.as_ref().unwrap()).unwrap();
}
if self.keepalives.is_some() {
writeln!(f, "keepalives: {}", vec_utils::as_str(self.keepalives.as_ref().unwrap())).unwrap();
}
for node in self.body.iter() {
writeln!(f, "{}", node).unwrap();
}
Ok(())
}
}
impl BlockContent {
pub fn get_out_arguments(&self) -> Vec<P<Value>> {
let n_insts = self.body.len();
let ref last_inst = self.body[n_insts - 1];
let mut ret : Vec<P<Value>> = vec![];
match last_inst.v {
TreeNode_::Instruction(ref inst) => {
let ops = inst.ops.read().unwrap();
match inst.v {
Instruction_::Return(_)
| Instruction_::ThreadExit
| Instruction_::Throw(_)
| Instruction_::TailCall(_) => {
// they do not have explicit liveouts
}
Instruction_::Branch1(ref dest) => {
let mut live_outs = dest.get_arguments(&ops);
vec_utils::append_unique(&mut ret, &mut live_outs);
}
Instruction_::Branch2{ref true_dest, ref false_dest, ..} => {
let mut live_outs = true_dest.get_arguments(&ops);
live_outs.append(&mut false_dest.get_arguments(&ops));
vec_utils::append_unique(&mut ret, &mut live_outs);
}
Instruction_::Watchpoint{ref disable_dest, ref resume, ..} => {
let mut live_outs = vec![];
if disable_dest.is_some() {
live_outs.append(&mut disable_dest.as_ref().unwrap().get_arguments(&ops));
}
live_outs.append(&mut resume.normal_dest.get_arguments(&ops));
live_outs.append(&mut resume.exn_dest.get_arguments(&ops));
vec_utils::append_unique(&mut ret, &mut live_outs);
}
Instruction_::WPBranch{ref disable_dest, ref enable_dest, ..} => {
let mut live_outs = vec![];
live_outs.append(&mut disable_dest.get_arguments(&ops));
live_outs.append(&mut enable_dest.get_arguments(&ops));
vec_utils::append_unique(&mut ret, &mut live_outs);
}
Instruction_::Call{ref resume, ..}
| Instruction_::CCall{ref resume, ..}
| Instruction_::SwapStack{ref resume, ..}
| Instruction_::ExnInstruction{ref resume, ..} => {
let mut live_outs = vec![];
live_outs.append(&mut resume.normal_dest.get_arguments(&ops));
live_outs.append(&mut resume.exn_dest.get_arguments(&ops));
vec_utils::append_unique(&mut ret, &mut live_outs);
}
Instruction_::Switch{ref default, ref branches, ..} => {
let mut live_outs = vec![];
live_outs.append(&mut default.get_arguments(&ops));
for &(_, ref dest) in branches {
live_outs.append(&mut dest.get_arguments(&ops));
}
vec_utils::append_unique(&mut ret, &mut live_outs);