GitLab will continue to be upgraded from 11.4.5-ce.0 on November 25th 2019 at 4.00pm (AEDT) to 5.00pm (AEDT) due to Critical Security Patch Availability. During the update, GitLab and Mattermost services will not be available.

Commit baa25cdf authored by qinsoon's avatar qinsoon

allowing list operands of instructions. Defuse doesnt work. P<T>.clone() is…

allowing list operands of instructions. Defuse doesnt work. P<T>.clone() is creating new copies of old objects, thus updating cloned objs wont affect the original ones.
parent 495c8587
......@@ -37,6 +37,10 @@ pub struct BlockContent {
pub keepalives: Option<Vec<P<TreeNode>>>
}
pub trait OperandIteratable {
fn list_operands(&self) -> Vec<P<TreeNode>>;
}
#[derive(Clone)]
/// always use with P<TreeNode>
pub struct TreeNode {
......@@ -86,7 +90,7 @@ impl fmt::Debug for TreeNode {
TreeNode_::Value(ref pv) => {
match pv.v {
Value_::SSAVar => {
write!(f, "{:?} %{}#{}", pv.ty, self.tag, self.id)
write!(f, "{:?} %{}#{} (use: {})", pv.ty, self.tag, self.id, self.use_count.get())
},
Value_::Constant(ref c) => {
write!(f, "{:?} {:?}", pv.ty, c)
......@@ -159,6 +163,15 @@ impl fmt::Debug for Instruction {
}
}
impl OperandIteratable for Instruction {
fn list_operands(&self) -> Vec<P<TreeNode>> {
match self {
&Instruction::NonTerm(ref inst) => inst.list_operands(),
&Instruction::Term(ref inst) => inst.list_operands()
}
}
}
#[derive(Clone)]
pub enum Terminal {
Return(Vec<P<TreeNode>>),
......@@ -206,6 +219,71 @@ pub enum Terminal {
}
}
impl OperandIteratable for Terminal {
fn list_operands(&self) -> Vec<P<TreeNode>> {
use ast::ir::Terminal::*;
match self {
&Return(ref vals) => vals.to_vec(),
&Throw(ref vals) => vals.to_vec(),
&TailCall(ref call) => call.list_operands(),
&Branch1(ref dest) => dest.list_operands(),
&Branch2{ref cond, ref true_dest, ref false_dest} => {
let mut ret = vec![];
ret.push(cond.clone());
ret.append(&mut true_dest.list_operands());
ret.append(&mut false_dest.list_operands());
ret
},
&Watchpoint{ref disable_dest, ref resume, ..} => {
let mut ret = vec![];
if disable_dest.is_some() {
ret.append(&mut disable_dest.as_ref().unwrap().list_operands())
}
ret.append(&mut resume.list_operands());
ret
},
&WPBranch{ref disable_dest, ref enable_dest, ..} => {
let mut ret = vec![];
ret.append(&mut disable_dest.list_operands());
ret.append(&mut enable_dest.list_operands());
ret
},
&Call{ref data, ref resume} => {
let mut ret = vec![];
ret.append(&mut data.list_operands());
ret.append(&mut resume.list_operands());
ret
},
&SwapStack{ref stack, ref args, ref resume, ..} => {
let mut ret = vec![];
ret.push(stack.clone());
ret.append(&mut args.to_vec());
ret.append(&mut resume.list_operands());
ret
},
&Switch{ref cond, ref default, ref branches} => {
let mut ret = vec![];
ret.push(cond.clone());
ret.append(&mut default.list_operands());
for entry in branches.iter() {
ret.push(entry.0.clone());
ret.append(&mut entry.1.list_operands());
}
ret
},
&ExnInstruction{ref inner, ref resume} => {
let mut ret = vec![];
ret.append(&mut inner.list_operands());
ret.append(&mut resume.list_operands());
ret
},
&ThreadExit => vec![]
}
}
}
impl fmt::Debug for Terminal {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
......@@ -267,6 +345,15 @@ impl fmt::Debug for NonTermInstruction {
}
}
impl OperandIteratable for NonTermInstruction {
fn list_operands(&self) -> Vec<P<TreeNode>> {
match self {
&NonTermInstruction::Assign{ref right, ..} => right.list_operands(),
&NonTermInstruction::Fence(_) => vec![]
}
}
}
#[derive(Clone)]
pub enum Expression_ {
BinOp(BinOp, P<TreeNode>, P<TreeNode>),
......@@ -387,6 +474,38 @@ macro_rules! select {
}
}
impl OperandIteratable for Expression_ {
fn list_operands(&self) -> Vec<P<TreeNode>> {
match self {
&Expression_::BinOp(_, ref op1, ref op2) => vec![op1.clone(), op2.clone()],
&Expression_::CmpOp(_, ref op1, ref op2) => vec![op1.clone(), op2.clone()],
&Expression_::ExprCall{ref data, ..} => data.list_operands(),
&Expression_::Load{ref mem_loc, ..} => vec![mem_loc.clone()],
&Expression_::Store{ref value, ref mem_loc, ..} => vec![value.clone(), mem_loc.clone()],
&Expression_::CmpXchg{ref mem_loc, ref expected_value, ref desired_value, ..} => vec![mem_loc.clone(), expected_value.clone(), desired_value.clone()],
&Expression_::AtomicRMW{ref mem_loc, ref value, ..} => vec![mem_loc.clone(), value.clone()],
&Expression_::NewHybrid(_, ref len) => vec![len.clone()],
&Expression_::AllocAHybrid(_, ref len) => vec![len.clone()],
&Expression_::NewStack(ref func) => vec![func.clone()],
&Expression_::NewThread(ref stack, ref args) => {
let mut ret = vec![];
ret.push(stack.clone());
ret.append(&mut args.to_vec());
ret
},
&Expression_::NewThreadExn(ref stack, ref exception) => vec![stack.clone(), exception.clone()],
&Expression_::NewFrameCursor(ref stack) => vec![stack.clone()],
&Expression_::GetIRef(ref reference) => vec![reference.clone()],
&Expression_::GetFieldIRef{ref base, ref index, ..} => vec![base.clone(), index.clone()],
&Expression_::GetElementIRef{ref base, ref index, ..} => vec![base.clone(), index.clone()],
&Expression_::ShiftIRef{ref base, ref offset, ..} => vec![base.clone(), offset.clone()],
&Expression_::GetVarPartIRef{ref base, ..} => vec![base.clone()],
&Expression_::New(_) | &Expression_::AllocA(_) => vec![]
}
}
}
impl fmt::Debug for Expression_ {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
......@@ -479,6 +598,17 @@ impl fmt::Debug for CallData {
}
}
impl OperandIteratable for CallData {
fn list_operands(&self) -> Vec<P<TreeNode>> {
let mut ret = vec![];
ret.push(self.func.clone());
ret.append(&mut self.args.to_vec());
ret
}
}
#[derive(Clone)]
pub struct ResumptionData {
pub normal_dest: Destination,
......@@ -491,12 +621,37 @@ impl fmt::Debug for ResumptionData {
}
}
impl OperandIteratable for ResumptionData {
fn list_operands(&self) -> Vec<P<TreeNode>> {
let mut ret = vec![];
ret.append(&mut self.normal_dest.list_operands());
ret.append(&mut self.exn_dest.list_operands());
ret
}
}
#[derive(Clone)]
pub struct Destination {
pub target: MuTag,
pub args: Vec<DestArg>
}
impl OperandIteratable for Destination {
fn list_operands(&self) -> Vec<P<TreeNode>> {
let mut ret = vec![];
for arg in self.args.iter() {
match arg {
&DestArg::Normal(ref op) => ret.push(op.clone()),
_ => {}
}
}
ret
}
}
impl fmt::Debug for Destination {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}{:?}", self.target, self.args)
......
......@@ -39,6 +39,7 @@
use std::fmt::{self, Display, Debug};
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use std::ops::DerefMut;
/// An owned smart pointer.
pub struct P<T> {
......@@ -71,6 +72,12 @@ impl<T> Deref for 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> {
fn clone(&self) -> P<T> {
P((**self).clone())
......
......@@ -29,6 +29,7 @@ pub struct CompilerPolicy {
impl CompilerPolicy {
pub fn default() -> CompilerPolicy {
let mut passes : Vec<Box<CompilerPass>> = vec![];
passes.push(Box::new(passes::def_use::DefUsePass::new("DefUse")));
passes.push(Box::new(passes::tree_gen::TreeGenerationPass::new("Tree Generation")));
CompilerPolicy{passes: passes}
......@@ -49,8 +50,10 @@ pub trait CompilerPass {
debug!("block: {}", label);
for node in block.content.as_mut().unwrap().body.iter_mut() {
debug!("{:?}", node);
for inst in block.content.as_mut().unwrap().body.iter_mut() {
debug!("{:?}", inst);
self.visit_inst(vm_context, inst);
}
debug!("---finish---");
......@@ -59,5 +62,5 @@ pub trait CompilerPass {
fn visit_function(&mut self, vm_context: &VMContext, func: &mut MuFunction) {}
fn visit_block(&mut self, vm_context: &VMContext, block: &mut Block) {}
fn visit_node(&mut self, vm_context: &VMContext, node: &mut TreeNode) {}
fn visit_inst(&mut self, vm_context: &VMContext, node: &mut TreeNode) {}
}
......@@ -8,7 +8,7 @@ pub struct DefUsePass {
}
impl DefUsePass {
pub fn name(name: &'static str) -> DefUsePass {
pub fn new(name: &'static str) -> DefUsePass {
DefUsePass{name: name}
}
}
......@@ -18,7 +18,14 @@ impl CompilerPass for DefUsePass {
self.name
}
fn visit_node(&mut self, vm_context: &VMContext, node: &mut TreeNode) {
fn visit_inst(&mut self, vm_context: &VMContext, node: &mut TreeNode) {
match node.v {
TreeNode_::Instruction(ref inst) => {
for p_node in inst.list_operands() {
p_node.use_count.set(p_node.use_count.get() + 1)
}
},
TreeNode_::Value(_) => panic!("expected instruction node")
}
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment