diff --git a/ykpack/src/types.rs b/ykpack/src/types.rs index 2b05d48dd..4425b0e19 100644 --- a/ykpack/src/types.rs +++ b/ykpack/src/types.rs @@ -92,6 +92,8 @@ impl Display for BasicBlock { #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)] pub enum Statement { Nop, + /// This is a special instruction used only in SSA generation. + SsaEntryDefs(Vec), Assign(Place, Rvalue), Unimplemented, // FIXME } @@ -102,12 +104,61 @@ impl Display for Statement { } } +impl Statement { + pub fn uses_vars_mut(&mut self) -> Vec<&mut LocalIndex> { + match self { + Statement::Nop | Statement::Unimplemented | Statement::SsaEntryDefs(_) => vec![], + Statement::Assign(_, rv) => rv.uses_vars_mut(), + } + } + + pub fn defs_vars_mut(&mut self) -> Vec<&mut LocalIndex> { + match self { + Statement::Nop | Statement::Unimplemented => vec![], + Statement::Assign(p, _) => p.defs_vars_mut(), + Statement::SsaEntryDefs(ref mut vs) => vs.iter_mut().collect(), + } + } + + pub fn is_phi(&self) -> bool { + if let Statement::Assign(_, Rvalue::Phi(..)) = self { + return true; + } + false + } + + pub fn phi_arg_mut(&mut self, j: usize) -> Option<&mut LocalIndex> { + if let Statement::Assign(_, Rvalue::Phi(ps)) = self { + if let Place::Local(ref mut l) = ps[j] { + return Some(l); + } + } + None + } +} + #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)] pub enum Place { Local(LocalIndex), Unimplemented, // FIXME } +impl Place { + fn uses_vars_mut(&mut self) -> Vec<&mut LocalIndex> { + match self { + Place::Local(l) => vec![l], + Place::Unimplemented => vec![], + } + } + + fn defs_vars_mut(&mut self) -> Vec<&mut LocalIndex> { + match self { + Place::Local(l) => vec![l], + Place::Unimplemented => vec![], + } + } +} + #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)] pub enum Rvalue { Place(Place), @@ -115,6 +166,23 @@ pub enum Rvalue { Unimplemented, // FIXME } +impl Rvalue { + fn uses_vars_mut(&mut self) -> Vec<&mut LocalIndex> { + match self { + Rvalue::Place(p) => p.uses_vars_mut(), + Rvalue::Phi(ps) => { + let mut res = Vec::new(); + ps.iter_mut().fold(&mut res, |r, p| { + r.extend(p.uses_vars_mut()); + r + }); + res + } + Rvalue::Unimplemented => vec![], + } + } +} + /// A call target. #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)] pub enum CallOperand { @@ -135,7 +203,10 @@ pub enum Terminator { }, Resume, Abort, - Return, + Return { + // Because TIR is in SSA, we have to say which SSA variable to return. + local: LocalIndex + }, Unreachable, Drop { target_bb: BasicBlockIndex, @@ -167,6 +238,25 @@ impl Display for Terminator { } } +impl Terminator { + pub fn uses_vars_mut(&mut self) -> Vec<&mut LocalIndex> { + match self { + Terminator::GeneratorDrop + | Terminator::DropAndReplace { .. } + | Terminator::Drop { .. } + | Terminator::Unreachable + | Terminator::Goto { .. } + | Terminator::Resume + | Terminator::Abort => Vec::new(), + Terminator::SwitchInt { .. } => Vec::new(), // FIXME has a condition which will use. + Terminator::Return { local: ref mut v } => vec![v], + Terminator::Call { .. } => Vec::new(), // FIXME, may use a local variable. + Terminator::Assert { .. } => Vec::new(), // FIXME has a condition var. + Terminator::Yield { .. } => Vec::new(), // FIXME check semantics of this terminator. + } + } +} + /// The top-level pack type. #[derive(Serialize, Deserialize, PartialEq, Eq, Debug, Clone)] pub enum Pack { @@ -179,3 +269,38 @@ impl Display for Pack { write!(f, "{}", mir) } } + +#[cfg(test)] +mod tests { + use super::{Place, Rvalue, Statement}; + + #[test] + fn assign_uses_vars_mut() { + let mut s = Statement::Assign(Place::Local(42), Rvalue::Place(Place::Local(43))); + assert_eq!(s.uses_vars_mut(), vec![&mut 43]); + } + + #[test] + fn assign_defs_vars_mut() { + let mut s = Statement::Assign(Place::Local(42), Rvalue::Place(Place::Local(43))); + assert_eq!(s.defs_vars_mut(), vec![&mut 42]); + } + + #[test] + fn phi_uses_vars_mut() { + let mut s = Statement::Assign( + Place::Local(44), + Rvalue::Phi(vec![Place::Local(100), Place::Local(200)]), + ); + assert_eq!(s.uses_vars_mut(), vec![&mut 100, &mut 200]); + } + + #[test] + fn phi_defs_vars_mut() { + let mut s = Statement::Assign( + Place::Local(44), + Rvalue::Phi(vec![Place::Local(100), Place::Local(200)]), + ); + assert_eq!(s.defs_vars_mut(), vec![&mut 44]); + } +}