diff --git a/src/analysis/pointsto/mod.rs b/src/analysis/pointsto/mod.rs index f9a4b27..975b39e 100644 --- a/src/analysis/pointsto/mod.rs +++ b/src/analysis/pointsto/mod.rs @@ -20,7 +20,6 @@ use rustc_middle::mir::{ Body, ConstOperand, Local, Location, Operand, Place, PlaceElem, PlaceRef, ProjectionElem, Rvalue, Statement, StatementKind, Terminator, TerminatorKind, }; -use rustc_middle::ty::ConstKind; use rustc_middle::mir::Const; use rustc_middle::ty::{Instance, TyCtxt, TyKind}; @@ -159,8 +158,8 @@ impl<'a, 'tcx> Andersen<'a, 'tcx> { pub enum ConstraintNode<'tcx> { Alloc(PlaceRef<'tcx>), Place(PlaceRef<'tcx>), - Constant(ConstKind<'tcx>), - ConstantDeref(ConstKind<'tcx>), + Constant(Const<'tcx>), + ConstantDeref(Const<'tcx>), } /// The assignments in MIR with default `mir-opt-level` (level 1) are simplified @@ -189,11 +188,12 @@ enum ConstraintEdge { AliasCopy, // Special: y=Arc::clone(x) or y=ptr::read(x) } +#[derive(Debug)] enum AccessPattern<'tcx> { Ref(PlaceRef<'tcx>), Indirect(PlaceRef<'tcx>), Direct(PlaceRef<'tcx>), - Constant(ConstKind<'tcx>), + Constant(Const<'tcx>), } #[derive(Default)] @@ -225,7 +225,7 @@ impl<'tcx> ConstraintGraph<'tcx> { self.graph.add_edge(rhs, lhs, ConstraintEdge::Address); } - fn add_constant(&mut self, constant: ConstKind<'tcx>) { + fn add_constant(&mut self, constant: Const<'tcx>) { let lhs = ConstraintNode::Constant(constant); let rhs = ConstraintNode::ConstantDeref(constant); let lhs = self.get_or_insert_node(lhs); @@ -252,7 +252,7 @@ impl<'tcx> ConstraintGraph<'tcx> { self.graph.add_edge(rhs, lhs, ConstraintEdge::Copy); } - fn add_copy_constant(&mut self, lhs: PlaceRef<'tcx>, rhs: ConstKind<'tcx>) { + fn add_copy_constant(&mut self, lhs: PlaceRef<'tcx>, rhs: Const<'tcx>) { let lhs = ConstraintNode::Place(lhs); let rhs = ConstraintNode::Constant(rhs); let lhs = self.get_or_insert_node(lhs); @@ -276,7 +276,7 @@ impl<'tcx> ConstraintGraph<'tcx> { self.graph.add_edge(rhs, lhs, ConstraintEdge::Store); } - fn add_store_constant(&mut self, lhs: PlaceRef<'tcx>, rhs: ConstKind<'tcx>) { + fn add_store_constant(&mut self, lhs: PlaceRef<'tcx>, rhs: Const<'tcx>) { let lhs = ConstraintNode::Place(lhs); let rhs = ConstraintNode::Constant(rhs); let lhs = self.get_or_insert_node(lhs); @@ -430,33 +430,36 @@ impl<'a, 'tcx> ConstraintGraphCollector<'a, 'tcx> { fn process_assignment(&mut self, place: &Place<'tcx>, rvalue: &Rvalue<'tcx>) { let lhs_pattern = Self::process_place(place.as_ref()); - let rhs_pattern = Self::process_rvalue(rvalue); - match (lhs_pattern, rhs_pattern) { - // a = &b - (AccessPattern::Direct(lhs), Some(AccessPattern::Ref(rhs))) => { - self.graph.add_address(lhs, rhs); - } - // a = b - (AccessPattern::Direct(lhs), Some(AccessPattern::Direct(rhs))) => { - self.graph.add_copy(lhs, rhs); - } - // a = Constant - (AccessPattern::Direct(lhs), Some(AccessPattern::Constant(rhs))) => { - self.graph.add_copy_constant(lhs, rhs); - } - // a = *b - (AccessPattern::Direct(lhs), Some(AccessPattern::Indirect(rhs))) => { - self.graph.add_load(lhs, rhs); - } - // *a = b - (AccessPattern::Indirect(lhs), Some(AccessPattern::Direct(rhs))) => { - self.graph.add_store(lhs, rhs); - } - // *a = Constant - (AccessPattern::Indirect(lhs), Some(AccessPattern::Constant(rhs))) => { - self.graph.add_store_constant(lhs, rhs); + let rhs_patterns = Self::process_rvalue(rvalue); + + for rhs_pattern in rhs_patterns.into_iter() { + match (&lhs_pattern, rhs_pattern) { + // a = &b + (AccessPattern::Direct(lhs), Some(AccessPattern::Ref(rhs))) => { + self.graph.add_address(*lhs, rhs); + } + // a = b + (AccessPattern::Direct(lhs), Some(AccessPattern::Direct(rhs))) => { + self.graph.add_copy(*lhs, rhs); + } + // a = Constant + (AccessPattern::Direct(lhs), Some(AccessPattern::Constant(rhs))) => { + self.graph.add_copy_constant(*lhs, rhs); + } + // a = *b + (AccessPattern::Direct(lhs), Some(AccessPattern::Indirect(rhs))) => { + self.graph.add_load(*lhs, rhs); + } + // *a = b + (AccessPattern::Indirect(lhs), Some(AccessPattern::Direct(rhs))) => { + self.graph.add_store(*lhs, rhs); + } + // *a = Constant + (AccessPattern::Indirect(lhs), Some(AccessPattern::Constant(rhs))) => { + self.graph.add_store_constant(*lhs, rhs); + } + _ => {} } - _ => {} } } @@ -473,38 +476,40 @@ impl<'a, 'tcx> ConstraintGraphCollector<'a, 'tcx> { } } - fn process_rvalue(rvalue: &Rvalue<'tcx>) -> Option> { + fn process_operand(operand: &Operand<'tcx>) -> Option> { + match operand { + Operand::Move(place) | Operand::Copy(place) => { + Some(AccessPattern::Direct(place.as_ref())) + } + Operand::Constant(box ConstOperand { + span: _, + user_ty: _, + const_, + }) => Some(AccessPattern::Constant(*const_)), + } + } + + fn process_rvalue(rvalue: &Rvalue<'tcx>) -> Vec>> { match rvalue { Rvalue::Use(operand) | Rvalue::Repeat(operand, _) | Rvalue::Cast(_, operand, _) => { - match operand { - Operand::Move(place) | Operand::Copy(place) => { - Some(AccessPattern::Direct(place.as_ref())) - } - Operand::Constant(box ConstOperand { - span: _, - user_ty: _, - const_, - }) => { - if let Const::Ty(const_) = *const_ { - Some(AccessPattern::Constant(const_.kind())) - } else { - None - } - } - } + vec![Self::process_operand(operand)] } // Regard `p = &*q` as `p = q` Rvalue::Ref(_, _, place) | Rvalue::AddressOf(_, place) => match place.as_ref() { PlaceRef { local: l, projection: [ProjectionElem::Deref, ref remain @ ..], - } => Some(AccessPattern::Direct(PlaceRef { + } => vec![Some(AccessPattern::Direct(PlaceRef { local: l, projection: remain, - })), - _ => Some(AccessPattern::Ref(place.as_ref())), + }))], + _ => vec![Some(AccessPattern::Ref(place.as_ref()))], }, - _ => None, + Rvalue::Aggregate(_, fields) => { + let fields = fields.iter().map(Self::process_operand).collect::>(); + fields + } + _ => vec![], } }