1 use crate::borrow_check::nll::region_infer::values::{PointIndex, RegionValueElements};
2 use crate::util::liveness::{categorize, DefUse};
3 use rustc::mir::visit::{PlaceContext, Visitor};
4 use rustc::mir::{Local, Location, Body};
5 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
6 use rustc_data_structures::vec_linked_list as vll;
8 /// A map that cross references each local with the locations where it
9 /// is defined (assigned), used, or dropped. Used during liveness
12 /// We keep track only of `Local`s we'll do the liveness analysis later,
13 /// this means that our internal `IndexVec`s will only be sparsely populated.
14 /// In the time-memory trade-off between keeping compact vectors with new
15 /// indexes (and needing to continuously map the `Local` index to its compact
16 /// counterpart) and having `IndexVec`s that we only use a fraction of, time
17 /// (and code simplicity) was favored. The rationale is that we only keep
18 /// a small number of `IndexVec`s throughout the entire analysis while, in
19 /// contrast, we're accessing each `Local` *many* times.
20 crate struct LocalUseMap {
21 /// Head of a linked list of **definitions** of each variable --
22 /// definition in this context means assignment, e.g., `x` is
23 /// defined in `x = y` but not `y`; that first def is the head of
24 /// a linked list that lets you enumerate all places the variable
26 first_def_at: IndexVec<Local, Option<AppearanceIndex>>,
28 /// Head of a linked list of **uses** of each variable -- use in
29 /// this context means that the existing value of the variable is
30 /// read or modified. e.g., `y` is used in `x = y` but not `x`.
31 /// Note that `DROP(x)` terminators are excluded from this list.
32 first_use_at: IndexVec<Local, Option<AppearanceIndex>>,
34 /// Head of a linked list of **drops** of each variable -- these
35 /// are a special category of uses corresponding to the drop that
36 /// we add for each local variable.
37 first_drop_at: IndexVec<Local, Option<AppearanceIndex>>,
39 appearances: IndexVec<AppearanceIndex, Appearance>,
43 point_index: PointIndex,
44 next: Option<AppearanceIndex>,
48 pub struct AppearanceIndex { .. }
51 impl vll::LinkElem for Appearance {
52 type LinkIndex = AppearanceIndex;
54 fn next(elem: &Self) -> Option<AppearanceIndex> {
61 live_locals: &Vec<Local>,
62 elements: &RegionValueElements,
65 let nones = IndexVec::from_elem_n(None, mir.local_decls.len());
66 let mut local_use_map = LocalUseMap {
67 first_def_at: nones.clone(),
68 first_use_at: nones.clone(),
70 appearances: IndexVec::new(),
73 let mut locals_with_use_data: IndexVec<Local, bool> =
74 IndexVec::from_elem_n(false, mir.local_decls.len());
77 .for_each(|&local| locals_with_use_data[local] = true);
80 local_use_map: &mut local_use_map,
89 crate fn defs(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
90 vll::iter(self.first_def_at[local], &self.appearances)
91 .map(move |aa| self.appearances[aa].point_index)
94 crate fn uses(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
95 vll::iter(self.first_use_at[local], &self.appearances)
96 .map(move |aa| self.appearances[aa].point_index)
99 crate fn drops(&self, local: Local) -> impl Iterator<Item = PointIndex> + '_ {
100 vll::iter(self.first_drop_at[local], &self.appearances)
101 .map(move |aa| self.appearances[aa].point_index)
105 struct LocalUseMapBuild<'me> {
106 local_use_map: &'me mut LocalUseMap,
107 elements: &'me RegionValueElements,
109 // Vector used in `visit_local` to signal which `Local`s do we need
110 // def/use/drop information on, constructed from `live_locals` (that
111 // contains the variables we'll do the liveness analysis for).
112 // This vector serves optimization purposes only: we could have
113 // obtained the same information from `live_locals` but we want to
114 // avoid repeatedly calling `Vec::contains()` (see `LocalUseMap` for
115 // the rationale on the time-memory trade-off we're favoring here).
116 locals_with_use_data: IndexVec<Local, bool>,
119 impl LocalUseMapBuild<'_> {
120 fn insert_def(&mut self, local: Local, location: Location) {
123 &mut self.local_use_map.first_def_at[local],
124 &mut self.local_use_map.appearances,
129 fn insert_use(&mut self, local: Local, location: Location) {
132 &mut self.local_use_map.first_use_at[local],
133 &mut self.local_use_map.appearances,
138 fn insert_drop(&mut self, local: Local, location: Location) {
141 &mut self.local_use_map.first_drop_at[local],
142 &mut self.local_use_map.appearances,
148 elements: &RegionValueElements,
149 first_appearance: &mut Option<AppearanceIndex>,
150 appearances: &mut IndexVec<AppearanceIndex, Appearance>,
153 let point_index = elements.point_from_location(location);
154 let appearance_index = appearances.push(Appearance {
156 next: *first_appearance,
158 *first_appearance = Some(appearance_index);
162 impl Visitor<'tcx> for LocalUseMapBuild<'_> {
163 fn visit_local(&mut self, &local: &Local, context: PlaceContext, location: Location) {
164 if self.locals_with_use_data[local] {
165 match categorize(context) {
166 Some(DefUse::Def) => self.insert_def(local, location),
167 Some(DefUse::Use) => self.insert_use(local, location),
168 Some(DefUse::Drop) => self.insert_drop(local, location),