use std::fmt::{Debug, Formatter};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashMap;
use rustc_index::vec::IndexVec;
use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
use rustc_middle::mir::*;
filter: impl FnMut(Ty<'tcx>) -> bool,
) -> Self {
let mut map = Self::new();
- map.register_with_filter(tcx, body, filter, &escaped_places(body));
+ let exclude = excluded_locals(body);
+ map.register_with_filter(tcx, body, filter, &exclude);
debug!("registered {} places ({} nodes in total)", map.value_count, map.places.len());
map
}
tcx: TyCtxt<'tcx>,
body: &Body<'tcx>,
mut filter: impl FnMut(Ty<'tcx>) -> bool,
- exclude: &FxHashSet<Place<'tcx>>,
+ exclude: &IndexVec<Local, bool>,
) {
// We use this vector as stack, pushing and popping projections.
let mut projection = Vec::new();
for (local, decl) in body.local_decls.iter_enumerated() {
- self.register_with_filter_rec(
- tcx,
- local,
- &mut projection,
- decl.ty,
- &mut filter,
- exclude,
- );
+ if !exclude[local] {
+ self.register_with_filter_rec(tcx, local, &mut projection, decl.ty, &mut filter);
+ }
}
}
projection: &mut Vec<PlaceElem<'tcx>>,
ty: Ty<'tcx>,
filter: &mut impl FnMut(Ty<'tcx>) -> bool,
- exclude: &FxHashSet<Place<'tcx>>,
) {
- let place = Place { local, projection: tcx.intern_place_elems(projection) };
- if exclude.contains(&place) {
- // This will also exclude all projections of the excluded place.
- return;
- }
-
// Note: The framework supports only scalars for now.
if filter(ty) && ty.is_scalar() {
- trace!("registering place: {:?}", place);
+ // trace!("registering place {:?}", PlaceRef { local, projection: &*projection });
// We know that the projection only contains trackable elements.
let place = self.make_place(local, projection).unwrap();
return;
}
projection.push(PlaceElem::Field(field, ty));
- self.register_with_filter_rec(tcx, local, projection, ty, filter, exclude);
+ self.register_with_filter_rec(tcx, local, projection, ty, filter);
projection.pop();
});
}
}
}
-/// Returns all places, that have their reference or address taken.
-///
-/// This includes shared references, and also drops and `InlineAsm` out parameters.
-fn escaped_places<'tcx>(body: &Body<'tcx>) -> FxHashSet<Place<'tcx>> {
- struct Collector<'tcx> {
- result: FxHashSet<Place<'tcx>>,
+/// Returns all locals with projections that have their reference or address taken.
+fn excluded_locals<'tcx>(body: &Body<'tcx>) -> IndexVec<Local, bool> {
+ struct Collector {
+ result: IndexVec<Local, bool>,
}
- impl<'tcx> Visitor<'tcx> for Collector<'tcx> {
+ impl<'tcx> Visitor<'tcx> for Collector {
fn visit_place(&mut self, place: &Place<'tcx>, context: PlaceContext, _location: Location) {
if context.is_borrow()
|| context.is_address_of()
|| context.is_drop()
|| context == PlaceContext::MutatingUse(MutatingUseContext::AsmOutput)
{
- self.result.insert(*place);
+ // A pointer to a place could be used to access other places with the same local,
+ // hence we have to exclude the local completely.
+ self.result[place.local] = true;
}
}
}
- let mut collector = Collector { result: FxHashSet::default() };
+ let mut collector = Collector { result: IndexVec::from_elem(false, &body.local_decls) };
collector.visit_body(body);
collector.result
}
--- /dev/null
+- // MIR for `main` before DataflowConstProp
++ // MIR for `main` after DataflowConstProp
+
+ fn main() -> () {
+ let mut _0: (); // return place in scope 0 at $DIR/sibling_ptr.rs:+0:11: +0:11
+ let mut _1: (u8, u8); // in scope 0 at $DIR/sibling_ptr.rs:+1:9: +1:14
+ let _2: (); // in scope 0 at $DIR/sibling_ptr.rs:+2:5: +5:6
+ let mut _4: *mut u8; // in scope 0 at $DIR/sibling_ptr.rs:+4:10: +4:18
+ let mut _5: *mut u8; // in scope 0 at $DIR/sibling_ptr.rs:+4:10: +4:11
+ scope 1 {
+ debug x => _1; // in scope 1 at $DIR/sibling_ptr.rs:+1:9: +1:14
+ let _6: u8; // in scope 1 at $DIR/sibling_ptr.rs:+6:9: +6:11
+ scope 2 {
+ let _3: *mut u8; // in scope 2 at $DIR/sibling_ptr.rs:+3:13: +3:14
+ scope 3 {
+ debug p => _3; // in scope 3 at $DIR/sibling_ptr.rs:+3:13: +3:14
+ }
+ }
+ scope 4 {
+ debug x1 => _6; // in scope 4 at $DIR/sibling_ptr.rs:+6:9: +6:11
+ }
+ }
+
+ bb0: {
+ StorageLive(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:9: +1:14
+ Deinit(_1); // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
+ (_1.0: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
+ (_1.1: u8) = const 0_u8; // scope 0 at $DIR/sibling_ptr.rs:+1:27: +1:33
+ StorageLive(_2); // scope 1 at $DIR/sibling_ptr.rs:+2:5: +5:6
+ StorageLive(_3); // scope 2 at $DIR/sibling_ptr.rs:+3:13: +3:14
+ _3 = &raw mut (_1.0: u8); // scope 2 at $SRC_DIR/core/src/ptr/mod.rs:LL:COL
+ StorageLive(_4); // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18
+ StorageLive(_5); // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11
+ _5 = _3; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:11
+ _4 = ptr::mut_ptr::<impl *mut u8>::add(move _5, const 1_usize) -> bb1; // scope 3 at $DIR/sibling_ptr.rs:+4:10: +4:18
+ // mir::Constant
+ // + span: $DIR/sibling_ptr.rs:8:12: 8:15
+ // + literal: Const { ty: unsafe fn(*mut u8, usize) -> *mut u8 {ptr::mut_ptr::<impl *mut u8>::add}, val: Value(<ZST>) }
+ }
+
+ bb1: {
+ StorageDead(_5); // scope 3 at $DIR/sibling_ptr.rs:+4:17: +4:18
+ (*_4) = const 1_u8; // scope 3 at $DIR/sibling_ptr.rs:+4:9: +4:22
+ StorageDead(_4); // scope 3 at $DIR/sibling_ptr.rs:+4:22: +4:23
+ _2 = const (); // scope 2 at $DIR/sibling_ptr.rs:+2:5: +5:6
+ StorageDead(_3); // scope 2 at $DIR/sibling_ptr.rs:+5:5: +5:6
+ StorageDead(_2); // scope 1 at $DIR/sibling_ptr.rs:+5:5: +5:6
+ StorageLive(_6); // scope 1 at $DIR/sibling_ptr.rs:+6:9: +6:11
+ _6 = (_1.1: u8); // scope 1 at $DIR/sibling_ptr.rs:+6:14: +6:17
+ _0 = const (); // scope 0 at $DIR/sibling_ptr.rs:+0:11: +7:2
+ StorageDead(_6); // scope 1 at $DIR/sibling_ptr.rs:+7:1: +7:2
+ StorageDead(_1); // scope 0 at $DIR/sibling_ptr.rs:+7:1: +7:2
+ return; // scope 0 at $DIR/sibling_ptr.rs:+7:2: +7:2
+ }
+ }
+