]> git.lizzy.rs Git - rust.git/blob - src/librustc_mir/dataflow/impls/storage_liveness.rs
e4d5d6adfc17c06f6f51cc9821f13a7bd0bbb331
[rust.git] / src / librustc_mir / dataflow / impls / storage_liveness.rs
1 pub use super::*;
2
3 use crate::dataflow::BitDenotation;
4 use crate::dataflow::HaveBeenBorrowedLocals;
5 use crate::dataflow::{DataflowResults, DataflowResultsCursor, DataflowResultsRefCursor};
6 use rustc::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
7 use rustc::mir::*;
8 use std::cell::RefCell;
9
10 #[derive(Copy, Clone)]
11 pub struct MaybeStorageLive<'a, 'tcx> {
12     body: &'a Body<'tcx>,
13 }
14
15 impl<'a, 'tcx> MaybeStorageLive<'a, 'tcx> {
16     pub fn new(body: &'a Body<'tcx>) -> Self {
17         MaybeStorageLive { body }
18     }
19
20     pub fn body(&self) -> &Body<'tcx> {
21         self.body
22     }
23 }
24
25 impl<'a, 'tcx> BitDenotation<'tcx> for MaybeStorageLive<'a, 'tcx> {
26     type Idx = Local;
27     fn name() -> &'static str {
28         "maybe_storage_live"
29     }
30     fn bits_per_block(&self) -> usize {
31         self.body.local_decls.len()
32     }
33
34     fn start_block_effect(&self, _on_entry: &mut BitSet<Local>) {
35         // Nothing is live on function entry (generators only have a self
36         // argument, and we don't care about that)
37         assert_eq!(1, self.body.arg_count);
38     }
39
40     fn statement_effect(&self, trans: &mut GenKillSet<Local>, loc: Location) {
41         let stmt = &self.body[loc.block].statements[loc.statement_index];
42
43         match stmt.kind {
44             StatementKind::StorageLive(l) => trans.gen(l),
45             StatementKind::StorageDead(l) => trans.kill(l),
46             _ => (),
47         }
48     }
49
50     fn terminator_effect(&self, _trans: &mut GenKillSet<Local>, _loc: Location) {
51         // Terminators have no effect
52     }
53
54     fn propagate_call_return(
55         &self,
56         _in_out: &mut BitSet<Local>,
57         _call_bb: mir::BasicBlock,
58         _dest_bb: mir::BasicBlock,
59         _dest_place: &mir::Place<'tcx>,
60     ) {
61         // Nothing to do when a call returns successfully
62     }
63 }
64
65 impl<'a, 'tcx> BottomValue for MaybeStorageLive<'a, 'tcx> {
66     /// bottom = dead
67     const BOTTOM_VALUE: bool = false;
68 }
69
70 /// Dataflow analysis that determines whether each local requires storage at a
71 /// given location; i.e. whether its storage can go away without being observed.
72 pub struct RequiresStorage<'mir, 'tcx> {
73     body: ReadOnlyBodyAndCache<'mir, 'tcx>,
74     borrowed_locals:
75         RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
76 }
77
78 impl<'mir, 'tcx: 'mir> RequiresStorage<'mir, 'tcx> {
79     pub fn new(
80         body: ReadOnlyBodyAndCache<'mir, 'tcx>,
81         borrowed_locals: &'mir DataflowResults<'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>,
82     ) -> Self {
83         RequiresStorage {
84             body,
85             borrowed_locals: RefCell::new(DataflowResultsCursor::new(borrowed_locals, *body)),
86         }
87     }
88
89     pub fn body(&self) -> &Body<'tcx> {
90         &self.body
91     }
92 }
93
94 impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
95     type Idx = Local;
96     fn name() -> &'static str {
97         "requires_storage"
98     }
99     fn bits_per_block(&self) -> usize {
100         self.body.local_decls.len()
101     }
102
103     fn start_block_effect(&self, _sets: &mut BitSet<Local>) {
104         // Nothing is live on function entry (generators only have a self
105         // argument, and we don't care about that)
106         assert_eq!(1, self.body.arg_count);
107     }
108
109     fn before_statement_effect(&self, sets: &mut GenKillSet<Self::Idx>, loc: Location) {
110         // If we borrow or assign to a place then it needs storage for that
111         // statement.
112         self.check_for_borrow(sets, loc);
113
114         let stmt = &self.body[loc.block].statements[loc.statement_index];
115         match stmt.kind {
116             StatementKind::StorageDead(l) => sets.kill(l),
117             StatementKind::Assign(box (ref place, _))
118             | StatementKind::SetDiscriminant { box ref place, .. } => match place.base {
119                 PlaceBase::Local(local) => sets.gen(local),
120             },
121             StatementKind::InlineAsm(box InlineAsm { ref outputs, .. }) => {
122                 for p in &**outputs {
123                     match p.base {
124                         PlaceBase::Local(local) => sets.gen(local),
125                     }
126                 }
127             }
128             _ => (),
129         }
130     }
131
132     fn statement_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
133         // If we move from a place then only stops needing storage *after*
134         // that statement.
135         self.check_for_move(sets, loc);
136     }
137
138     fn before_terminator_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
139         self.check_for_borrow(sets, loc);
140
141         if let TerminatorKind::Call {
142             destination: Some((Place { base: PlaceBase::Local(local), .. }, _)),
143             ..
144         } = self.body[loc.block].terminator().kind
145         {
146             sets.gen(local);
147         }
148     }
149
150     fn terminator_effect(&self, sets: &mut GenKillSet<Local>, loc: Location) {
151         // For call terminators the destination requires storage for the call
152         // and after the call returns successfully, but not after a panic.
153         // Since `propagate_call_unwind` doesn't exist, we have to kill the
154         // destination here, and then gen it again in `propagate_call_return`.
155         if let TerminatorKind::Call { destination: Some((ref place, _)), .. } =
156             self.body[loc.block].terminator().kind
157         {
158             if let Some(local) = place.as_local() {
159                 sets.kill(local);
160             }
161         }
162         self.check_for_move(sets, loc);
163     }
164
165     fn propagate_call_return(
166         &self,
167         in_out: &mut BitSet<Local>,
168         _call_bb: mir::BasicBlock,
169         _dest_bb: mir::BasicBlock,
170         dest_place: &mir::Place<'tcx>,
171     ) {
172         match dest_place.base {
173             PlaceBase::Local(local) => {
174                 in_out.insert(local);
175             }
176         }
177     }
178 }
179
180 impl<'mir, 'tcx> RequiresStorage<'mir, 'tcx> {
181     /// Kill locals that are fully moved and have not been borrowed.
182     fn check_for_move(&self, sets: &mut GenKillSet<Local>, loc: Location) {
183         let mut visitor = MoveVisitor { sets, borrowed_locals: &self.borrowed_locals };
184         visitor.visit_location(self.body, loc);
185     }
186
187     /// Gen locals that are newly borrowed. This includes borrowing any part of
188     /// a local (we rely on this behavior of `HaveBeenBorrowedLocals`).
189     fn check_for_borrow(&self, sets: &mut GenKillSet<Local>, loc: Location) {
190         let mut borrowed_locals = self.borrowed_locals.borrow_mut();
191         borrowed_locals.seek(loc);
192         borrowed_locals.each_gen_bit(|l| sets.gen(l));
193     }
194 }
195
196 impl<'mir, 'tcx> BottomValue for RequiresStorage<'mir, 'tcx> {
197     /// bottom = dead
198     const BOTTOM_VALUE: bool = false;
199 }
200
201 struct MoveVisitor<'a, 'mir, 'tcx> {
202     borrowed_locals:
203         &'a RefCell<DataflowResultsRefCursor<'mir, 'tcx, HaveBeenBorrowedLocals<'mir, 'tcx>>>,
204     sets: &'a mut GenKillSet<Local>,
205 }
206
207 impl<'a, 'mir: 'a, 'tcx> Visitor<'tcx> for MoveVisitor<'a, 'mir, 'tcx> {
208     fn visit_local(&mut self, local: &Local, context: PlaceContext, loc: Location) {
209         if PlaceContext::NonMutatingUse(NonMutatingUseContext::Move) == context {
210             let mut borrowed_locals = self.borrowed_locals.borrow_mut();
211             borrowed_locals.seek(loc);
212             if !borrowed_locals.contains(*local) {
213                 self.sets.kill(*local);
214             }
215         }
216     }
217 }