1
1
pub use super :: * ;
2
2
3
- use crate :: dataflow:: generic:: { Results , ResultsRefCursor } ;
4
- use crate :: dataflow:: BitDenotation ;
5
- use crate :: dataflow:: MaybeBorrowedLocals ;
3
+ use crate :: dataflow:: generic:: { self as dataflow, GenKill , Results , ResultsRefCursor } ;
4
+ use crate :: dataflow:: BottomValue ;
6
5
use rustc:: mir:: visit:: { NonMutatingUseContext , PlaceContext , Visitor } ;
7
6
use rustc:: mir:: * ;
8
7
use std:: cell:: RefCell ;
9
8
10
9
#[ derive( Copy , Clone ) ]
11
- pub struct MaybeStorageLive < ' a , ' tcx > {
12
- body : & ' a Body < ' tcx > ,
13
- }
10
+ pub struct MaybeStorageLive ;
14
11
15
- impl < ' a , ' tcx > MaybeStorageLive < ' a , ' tcx > {
16
- pub fn new ( body : & ' a Body < ' tcx > ) -> Self {
17
- MaybeStorageLive { body }
18
- }
12
+ impl dataflow:: AnalysisDomain < ' tcx > for MaybeStorageLive {
13
+ type Idx = Local ;
19
14
20
- pub fn body ( & self ) -> & Body < ' tcx > {
21
- self . body
22
- }
23
- }
15
+ const NAME : & ' static str = "maybe_storage_live" ;
24
16
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 ( )
17
+ fn bits_per_block ( & self , body : & mir:: Body < ' tcx > ) -> usize {
18
+ body. local_decls . len ( )
32
19
}
33
20
34
- fn start_block_effect ( & self , on_entry : & mut BitSet < Local > ) {
21
+ fn initialize_start_block ( & self , body : & mir :: Body < ' tcx > , on_entry : & mut BitSet < Self :: Idx > ) {
35
22
// The resume argument is live on function entry (we don't care about
36
23
// the `self` argument)
37
- for arg in self . body . args_iter ( ) . skip ( 1 ) {
24
+ for arg in body. args_iter ( ) . skip ( 1 ) {
38
25
on_entry. insert ( arg) ;
39
26
}
40
27
}
28
+ }
41
29
42
- fn statement_effect ( & self , trans : & mut GenKillSet < Local > , loc : Location ) {
43
- let stmt = & self . body [ loc. block ] . statements [ loc. statement_index ] ;
44
-
30
+ impl dataflow:: GenKillAnalysis < ' tcx > for MaybeStorageLive {
31
+ fn statement_effect (
32
+ & self ,
33
+ trans : & mut impl GenKill < Self :: Idx > ,
34
+ stmt : & mir:: Statement < ' tcx > ,
35
+ _: Location ,
36
+ ) {
45
37
match stmt. kind {
46
38
StatementKind :: StorageLive ( l) => trans. gen ( l) ,
47
39
StatementKind :: StorageDead ( l) => trans. kill ( l) ,
48
40
_ => ( ) ,
49
41
}
50
42
}
51
43
52
- fn terminator_effect ( & self , _trans : & mut GenKillSet < Local > , _loc : Location ) {
44
+ fn terminator_effect (
45
+ & self ,
46
+ _trans : & mut impl GenKill < Self :: Idx > ,
47
+ _: & mir:: Terminator < ' tcx > ,
48
+ _: Location ,
49
+ ) {
53
50
// Terminators have no effect
54
51
}
55
52
56
- fn propagate_call_return (
53
+ fn call_return_effect (
57
54
& self ,
58
- _in_out : & mut BitSet < Local > ,
59
- _call_bb : mir:: BasicBlock ,
60
- _dest_bb : mir:: BasicBlock ,
61
- _dest_place : & mir:: Place < ' tcx > ,
55
+ _trans : & mut impl GenKill < Self :: Idx > ,
56
+ _block : BasicBlock ,
57
+ _func : & mir:: Operand < ' tcx > ,
58
+ _args : & [ mir:: Operand < ' tcx > ] ,
59
+ _return_place : & mir:: Place < ' tcx > ,
62
60
) {
63
61
// Nothing to do when a call returns successfully
64
62
}
65
63
}
66
64
67
- impl < ' a , ' tcx > BottomValue for MaybeStorageLive < ' a , ' tcx > {
65
+ impl BottomValue for MaybeStorageLive {
68
66
/// bottom = dead
69
67
const BOTTOM_VALUE : bool = false ;
70
68
}
@@ -73,60 +71,62 @@ type BorrowedLocalsResults<'a, 'tcx> = ResultsRefCursor<'a, 'a, 'tcx, MaybeBorro
73
71
74
72
/// Dataflow analysis that determines whether each local requires storage at a
75
73
/// given location; i.e. whether its storage can go away without being observed.
76
- pub struct RequiresStorage < ' mir , ' tcx > {
74
+ pub struct MaybeRequiresStorage < ' mir , ' tcx > {
77
75
body : ReadOnlyBodyAndCache < ' mir , ' tcx > ,
78
76
borrowed_locals : RefCell < BorrowedLocalsResults < ' mir , ' tcx > > ,
79
77
}
80
78
81
- impl < ' mir , ' tcx : ' mir > RequiresStorage < ' mir , ' tcx > {
79
+ impl < ' mir , ' tcx > MaybeRequiresStorage < ' mir , ' tcx > {
82
80
pub fn new (
83
81
body : ReadOnlyBodyAndCache < ' mir , ' tcx > ,
84
82
borrowed_locals : & ' mir Results < ' tcx , MaybeBorrowedLocals > ,
85
83
) -> Self {
86
- RequiresStorage {
84
+ MaybeRequiresStorage {
87
85
body,
88
86
borrowed_locals : RefCell :: new ( ResultsRefCursor :: new ( * body, borrowed_locals) ) ,
89
87
}
90
88
}
91
-
92
- pub fn body ( & self ) -> & Body < ' tcx > {
93
- & self . body
94
- }
95
89
}
96
90
97
- impl < ' mir , ' tcx > BitDenotation < ' tcx > for RequiresStorage < ' mir , ' tcx > {
91
+ impl < ' mir , ' tcx > dataflow :: AnalysisDomain < ' tcx > for MaybeRequiresStorage < ' mir , ' tcx > {
98
92
type Idx = Local ;
99
- fn name ( ) -> & ' static str {
100
- "requires_storage"
101
- }
102
- fn bits_per_block ( & self ) -> usize {
103
- self . body . local_decls . len ( )
93
+
94
+ const NAME : & ' static str = "requires_storage" ;
95
+
96
+ fn bits_per_block ( & self , body : & mir :: Body < ' tcx > ) -> usize {
97
+ body. local_decls . len ( )
104
98
}
105
99
106
- fn start_block_effect ( & self , on_entry : & mut BitSet < Local > ) {
100
+ fn initialize_start_block ( & self , body : & mir :: Body < ' tcx > , on_entry : & mut BitSet < Self :: Idx > ) {
107
101
// The resume argument is live on function entry (we don't care about
108
102
// the `self` argument)
109
- for arg in self . body . args_iter ( ) . skip ( 1 ) {
103
+ for arg in body. args_iter ( ) . skip ( 1 ) {
110
104
on_entry. insert ( arg) ;
111
105
}
112
106
}
107
+ }
113
108
114
- fn before_statement_effect ( & self , sets : & mut GenKillSet < Self :: Idx > , loc : Location ) {
115
- let stmt = & self . body [ loc. block ] . statements [ loc. statement_index ] ;
116
-
109
+ impl < ' mir , ' tcx > dataflow:: GenKillAnalysis < ' tcx > for MaybeRequiresStorage < ' mir , ' tcx > {
110
+ fn before_statement_effect (
111
+ & self ,
112
+ trans : & mut impl GenKill < Self :: Idx > ,
113
+ stmt : & mir:: Statement < ' tcx > ,
114
+ loc : Location ,
115
+ ) {
117
116
// If a place is borrowed in a statement, it needs storage for that statement.
118
- self . borrowed_locals . borrow ( ) . analysis ( ) . statement_effect ( sets , stmt, loc) ;
117
+ self . borrowed_locals . borrow ( ) . analysis ( ) . statement_effect ( trans , stmt, loc) ;
119
118
120
- // If a place is assigned to in a statement, it needs storage for that statement.
121
119
match & stmt. kind {
122
- StatementKind :: StorageDead ( l) => sets. kill ( * l) ,
120
+ StatementKind :: StorageDead ( l) => trans. kill ( * l) ,
121
+
122
+ // If a place is assigned to in a statement, it needs storage for that statement.
123
123
StatementKind :: Assign ( box ( place, _) )
124
124
| StatementKind :: SetDiscriminant { box place, .. } => {
125
- sets . gen ( place. local ) ;
125
+ trans . gen ( place. local ) ;
126
126
}
127
- StatementKind :: InlineAsm ( box InlineAsm { outputs , .. } ) => {
128
- for place in & * * outputs {
129
- sets . gen ( place. local ) ;
127
+ StatementKind :: InlineAsm ( asm ) => {
128
+ for place in & * asm . outputs {
129
+ trans . gen ( place. local ) ;
130
130
}
131
131
}
132
132
@@ -140,22 +140,30 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
140
140
}
141
141
}
142
142
143
- fn statement_effect ( & self , sets : & mut GenKillSet < Local > , loc : Location ) {
143
+ fn statement_effect (
144
+ & self ,
145
+ trans : & mut impl GenKill < Self :: Idx > ,
146
+ _: & mir:: Statement < ' tcx > ,
147
+ loc : Location ,
148
+ ) {
144
149
// If we move from a place then only stops needing storage *after*
145
150
// that statement.
146
- self . check_for_move ( sets , loc) ;
151
+ self . check_for_move ( trans , loc) ;
147
152
}
148
153
149
- fn before_terminator_effect ( & self , sets : & mut GenKillSet < Local > , loc : Location ) {
150
- let terminator = self . body [ loc. block ] . terminator ( ) ;
151
-
154
+ fn before_terminator_effect (
155
+ & self ,
156
+ trans : & mut impl GenKill < Self :: Idx > ,
157
+ terminator : & mir:: Terminator < ' tcx > ,
158
+ loc : Location ,
159
+ ) {
152
160
// If a place is borrowed in a terminator, it needs storage for that terminator.
153
- self . borrowed_locals . borrow ( ) . analysis ( ) . terminator_effect ( sets , terminator, loc) ;
161
+ self . borrowed_locals . borrow ( ) . analysis ( ) . terminator_effect ( trans , terminator, loc) ;
154
162
155
163
match & terminator. kind {
156
- TerminatorKind :: Call { destination : Some ( ( Place { local , .. } , _) ) , .. }
157
- | TerminatorKind :: Yield { resume_arg : Place { local , .. } , .. } => {
158
- sets . gen ( * local) ;
164
+ TerminatorKind :: Call { destination : Some ( ( place , _) ) , .. }
165
+ | TerminatorKind :: Yield { resume_arg : place , .. } => {
166
+ trans . gen ( place . local ) ;
159
167
}
160
168
161
169
// Nothing to do for these. Match exhaustively so this fails to compile when new
@@ -176,14 +184,19 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
176
184
}
177
185
}
178
186
179
- fn terminator_effect ( & self , sets : & mut GenKillSet < Local > , loc : Location ) {
180
- match & self . body [ loc. block ] . terminator ( ) . kind {
187
+ fn terminator_effect (
188
+ & self ,
189
+ trans : & mut impl GenKill < Self :: Idx > ,
190
+ terminator : & mir:: Terminator < ' tcx > ,
191
+ loc : Location ,
192
+ ) {
193
+ match & terminator. kind {
181
194
// For call terminators the destination requires storage for the call
182
195
// and after the call returns successfully, but not after a panic.
183
196
// Since `propagate_call_unwind` doesn't exist, we have to kill the
184
- // destination here, and then gen it again in `propagate_call_return `.
185
- TerminatorKind :: Call { destination : Some ( ( Place { local , .. } , _) ) , .. } => {
186
- sets . kill ( * local) ;
197
+ // destination here, and then gen it again in `call_return_effect `.
198
+ TerminatorKind :: Call { destination : Some ( ( place , _) ) , .. } => {
199
+ trans . kill ( place . local ) ;
187
200
}
188
201
189
202
// Nothing to do for these. Match exhaustively so this fails to compile when new
@@ -204,45 +217,49 @@ impl<'mir, 'tcx> BitDenotation<'tcx> for RequiresStorage<'mir, 'tcx> {
204
217
| TerminatorKind :: Unreachable => { }
205
218
}
206
219
207
- self . check_for_move ( sets , loc) ;
220
+ self . check_for_move ( trans , loc) ;
208
221
}
209
222
210
- fn propagate_call_return (
223
+ fn call_return_effect (
211
224
& self ,
212
- in_out : & mut BitSet < Local > ,
213
- _call_bb : mir:: BasicBlock ,
214
- _dest_bb : mir:: BasicBlock ,
215
- dest_place : & mir:: Place < ' tcx > ,
225
+ trans : & mut impl GenKill < Self :: Idx > ,
226
+ _block : BasicBlock ,
227
+ _func : & mir:: Operand < ' tcx > ,
228
+ _args : & [ mir:: Operand < ' tcx > ] ,
229
+ return_place : & mir:: Place < ' tcx > ,
216
230
) {
217
- in_out . insert ( dest_place . local ) ;
231
+ trans . gen ( return_place . local ) ;
218
232
}
219
233
}
220
234
221
- impl < ' mir , ' tcx > RequiresStorage < ' mir , ' tcx > {
235
+ impl < ' mir , ' tcx > MaybeRequiresStorage < ' mir , ' tcx > {
222
236
/// Kill locals that are fully moved and have not been borrowed.
223
- fn check_for_move ( & self , sets : & mut GenKillSet < Local > , loc : Location ) {
224
- let mut visitor = MoveVisitor { sets , borrowed_locals : & self . borrowed_locals } ;
237
+ fn check_for_move ( & self , trans : & mut impl GenKill < Local > , loc : Location ) {
238
+ let mut visitor = MoveVisitor { trans , borrowed_locals : & self . borrowed_locals } ;
225
239
visitor. visit_location ( self . body , loc) ;
226
240
}
227
241
}
228
242
229
- impl < ' mir , ' tcx > BottomValue for RequiresStorage < ' mir , ' tcx > {
243
+ impl < ' mir , ' tcx > BottomValue for MaybeRequiresStorage < ' mir , ' tcx > {
230
244
/// bottom = dead
231
245
const BOTTOM_VALUE : bool = false ;
232
246
}
233
247
234
- struct MoveVisitor < ' a , ' mir , ' tcx > {
248
+ struct MoveVisitor < ' a , ' mir , ' tcx , T > {
235
249
borrowed_locals : & ' a RefCell < BorrowedLocalsResults < ' mir , ' tcx > > ,
236
- sets : & ' a mut GenKillSet < Local > ,
250
+ trans : & ' a mut T ,
237
251
}
238
252
239
- impl < ' a , ' mir : ' a , ' tcx > Visitor < ' tcx > for MoveVisitor < ' a , ' mir , ' tcx > {
253
+ impl < ' a , ' mir , ' tcx , T > Visitor < ' tcx > for MoveVisitor < ' a , ' mir , ' tcx , T >
254
+ where
255
+ T : GenKill < Local > ,
256
+ {
240
257
fn visit_local ( & mut self , local : & Local , context : PlaceContext , loc : Location ) {
241
258
if PlaceContext :: NonMutatingUse ( NonMutatingUseContext :: Move ) == context {
242
259
let mut borrowed_locals = self . borrowed_locals . borrow_mut ( ) ;
243
260
borrowed_locals. seek_before ( loc) ;
244
261
if !borrowed_locals. contains ( * local) {
245
- self . sets . kill ( * local) ;
262
+ self . trans . kill ( * local) ;
246
263
}
247
264
}
248
265
}
0 commit comments