33
33
//! generator yield points, all pre-existing references are invalidated, so this
34
34
//! doesn't matter).
35
35
36
- use rustc:: mir:: * ;
36
+ use rustc:: mir:: visit :: MirVisitable ;
37
37
use rustc:: mir:: visit:: { PlaceContext , Visitor } ;
38
- use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
38
+ use rustc:: mir:: Local ;
39
+ use rustc:: mir:: * ;
40
+ use rustc:: ty:: item_path;
41
+ use rustc:: ty:: TyCtxt ;
39
42
use rustc_data_structures:: indexed_set:: IdxSetBuf ;
43
+ use rustc_data_structures:: indexed_vec:: { Idx , IndexVec } ;
40
44
use rustc_data_structures:: work_queue:: WorkQueue ;
41
- use util:: pretty:: { dump_enabled, write_basic_block, write_mir_intro} ;
42
- use rustc:: ty:: item_path;
43
- use rustc:: mir:: Local ;
44
- use rustc:: mir:: visit:: MirVisitable ;
45
- use std:: path:: { Path , PathBuf } ;
46
45
use std:: fs;
47
- use rustc:: ty:: TyCtxt ;
48
46
use std:: io:: { self , Write } ;
47
+ use std:: path:: { Path , PathBuf } ;
49
48
use transform:: MirSource ;
49
+ use util:: pretty:: { dump_enabled, write_basic_block, write_mir_intro} ;
50
50
51
- pub type LocalSet < V : LiveVariableMap > = IdxSetBuf < V :: LiveVar > ;
51
+ pub type LocalSet < V > = IdxSetBuf < V > ;
52
52
53
53
/// This gives the result of the liveness analysis at the boundary of
54
54
/// basic blocks. You can use `simulate_block` to obtain the
55
55
/// intra-block results.
56
- pub struct LivenessResult < V : LiveVariableMap > {
56
+ ///
57
+ /// The `V` type defines the set of variables that we computed
58
+ /// liveness for. This is often `Local`, in which case we computed
59
+ /// liveness for all variables -- but it can also be some other type,
60
+ /// which indicates a subset of the variables within the graph.
61
+ pub struct LivenessResult < V : Idx > {
57
62
/// Liveness mode in use when these results were computed.
58
63
pub mode : LivenessMode ,
59
64
60
65
/// Live variables on exit to each basic block. This is equal to
61
66
/// the union of the `ins` for each successor.
62
- pub outs : IndexVec < BasicBlock , LocalSet < V :: LiveVar > > ,
67
+ pub outs : IndexVec < BasicBlock , LocalSet < V > > ,
63
68
}
64
69
65
- pub ( crate ) trait LiveVariableMap {
70
+ /// Defines the mapping to/from the MIR local variables (`Local`) to
71
+ /// the "live variable indices" we are using in a particular
72
+ /// computation.
73
+ pub trait LiveVariableMap {
66
74
type LiveVar ;
67
75
68
76
fn from_local ( & self , local : Local ) -> Option < Self :: LiveVar > ;
69
77
fn from_live_var ( & self , local : Self :: LiveVar ) -> Local ;
78
+ fn num_variables ( & self ) -> usize ;
70
79
}
71
80
72
- #[ derive( Eq , PartialEq , Clone ) ]
73
- struct IdentityMap ;
81
+ #[ derive( Debug ) ]
82
+ pub struct IdentityMap < ' a , ' tcx : ' a > {
83
+ mir : & ' a Mir < ' tcx > ,
84
+ }
74
85
75
- impl LiveVariableMap for IdentityMap {
86
+ impl < ' a , ' tcx > IdentityMap < ' a , ' tcx > {
87
+ pub fn new ( mir : & ' a Mir < ' tcx > ) -> Self {
88
+ Self { mir }
89
+ }
90
+ }
91
+
92
+ impl < ' a , ' tcx > LiveVariableMap for IdentityMap < ' a , ' tcx > {
76
93
type LiveVar = Local ;
77
94
78
95
fn from_local ( & self , local : Local ) -> Option < Self :: LiveVar > {
@@ -82,6 +99,10 @@ impl LiveVariableMap for IdentityMap {
82
99
fn from_live_var ( & self , local : Self :: LiveVar ) -> Local {
83
100
local
84
101
}
102
+
103
+ fn num_variables ( & self ) -> usize {
104
+ self . mir . local_decls . len ( )
105
+ }
85
106
}
86
107
87
108
#[ derive( Copy , Clone , Debug ) ]
@@ -103,7 +124,7 @@ pub struct LivenessMode {
103
124
}
104
125
105
126
/// A combination of liveness results, used in NLL.
106
- pub struct LivenessResults < V > {
127
+ pub struct LivenessResults < V : Idx > {
107
128
/// Liveness results where a regular use makes a variable X live,
108
129
/// but not a drop.
109
130
pub regular : LivenessResult < V > ,
@@ -113,15 +134,19 @@ pub struct LivenessResults<V> {
113
134
pub drop : LivenessResult < V > ,
114
135
}
115
136
116
- impl < V , M : LiveVariableMap < LiveVar = V > > LivenessResults < V > {
117
- pub fn compute < ' tcx > ( mir : & Mir < ' tcx > , map : & M ) -> LivenessResults < V > {
137
+ impl < V : Idx > LivenessResults < V > {
138
+ pub fn compute < ' tcx > (
139
+ mir : & Mir < ' tcx > ,
140
+ map : & impl LiveVariableMap < LiveVar = V > ,
141
+ ) -> LivenessResults < V > {
118
142
LivenessResults {
119
143
regular : liveness_of_locals (
120
144
& mir,
121
145
LivenessMode {
122
146
include_regular_use : true ,
123
147
include_drops : false ,
124
148
} ,
149
+ map,
125
150
) ,
126
151
127
152
drop : liveness_of_locals (
@@ -130,6 +155,7 @@ impl<V, M: LiveVariableMap<LiveVar = V>> LivenessResults<V> {
130
155
include_regular_use : false ,
131
156
include_drops : true ,
132
157
} ,
158
+ map,
133
159
) ,
134
160
}
135
161
}
@@ -138,14 +164,21 @@ impl<V, M: LiveVariableMap<LiveVar = V>> LivenessResults<V> {
138
164
/// Compute which local variables are live within the given function
139
165
/// `mir`. The liveness mode `mode` determines what sorts of uses are
140
166
/// considered to make a variable live (e.g., do drops count?).
141
- pub fn liveness_of_locals < ' tcx , V > ( mir : & Mir < ' tcx > , mode : LivenessMode ) -> LivenessResult < V > {
142
- let locals = mir. local_decls . len ( ) ;
143
- let def_use: IndexVec < _ , _ > = mir. basic_blocks ( )
167
+ pub fn liveness_of_locals < ' tcx , V : Idx > (
168
+ mir : & Mir < ' tcx > ,
169
+ mode : LivenessMode ,
170
+ map : & impl LiveVariableMap < LiveVar = V > ,
171
+ ) -> LivenessResult < V > {
172
+ let locals = map. num_variables ( ) ;
173
+
174
+ let def_use: IndexVec < _ , DefsUses < V > > = mir
175
+ . basic_blocks ( )
144
176
. iter ( )
145
- . map ( |b| block ( mode, b, locals) )
177
+ . map ( |b| block ( mode, map , b, locals) )
146
178
. collect ( ) ;
147
179
148
- let mut outs: IndexVec < _ , _ > = mir. basic_blocks ( )
180
+ let mut outs: IndexVec < _ , LocalSet < V > > = mir
181
+ . basic_blocks ( )
149
182
. indices ( )
150
183
. map ( |_| LocalSet :: new_empty ( locals) )
151
184
. collect ( ) ;
@@ -179,14 +212,18 @@ pub fn liveness_of_locals<'tcx, V>(mir: &Mir<'tcx>, mode: LivenessMode) -> Liven
179
212
LivenessResult { mode, outs }
180
213
}
181
214
182
- impl < V : LiveVariableMap > LivenessResult < V >
183
- {
215
+ impl < V : Idx > LivenessResult < V > {
184
216
/// Walks backwards through the statements/terminator in the given
185
217
/// basic block `block`. At each point within `block`, invokes
186
218
/// the callback `op` with the current location and the set of
187
219
/// variables that are live on entry to that location.
188
- pub fn simulate_block < ' tcx , OP > ( & self , mir : & Mir < ' tcx > , block : BasicBlock , mut callback : OP )
189
- where
220
+ pub fn simulate_block < ' tcx , OP > (
221
+ & self ,
222
+ mir : & Mir < ' tcx > ,
223
+ block : BasicBlock ,
224
+ map : & impl LiveVariableMap < LiveVar = V > ,
225
+ mut callback : OP ,
226
+ ) where
190
227
OP : FnMut ( Location , & LocalSet < V > ) ,
191
228
{
192
229
let data = & mir[ block] ;
@@ -206,16 +243,20 @@ impl<V: LiveVariableMap> LivenessResult<V>
206
243
let locals = mir. local_decls . len ( ) ;
207
244
let mut visitor = DefsUsesVisitor {
208
245
mode : self . mode ,
246
+ map,
209
247
defs_uses : DefsUses {
210
248
defs : LocalSet :: new_empty ( locals) ,
211
249
uses : LocalSet :: new_empty ( locals) ,
212
- map : & IdentityMap { } ,
213
250
} ,
214
251
} ;
215
252
// Visit the various parts of the basic block in reverse. If we go
216
253
// forward, the logic in `add_def` and `add_use` would be wrong.
217
- visitor. update_bits_and_do_callback ( terminator_location, & data. terminator , & mut bits,
218
- & mut callback) ;
254
+ visitor. update_bits_and_do_callback (
255
+ terminator_location,
256
+ & data. terminator ,
257
+ & mut bits,
258
+ & mut callback,
259
+ ) ;
219
260
220
261
// Compute liveness before each statement (in rev order) and invoke callback.
221
262
for statement in data. statements . iter ( ) . rev ( ) {
@@ -225,8 +266,12 @@ impl<V: LiveVariableMap> LivenessResult<V>
225
266
statement_index,
226
267
} ;
227
268
visitor. defs_uses . clear ( ) ;
228
- visitor. update_bits_and_do_callback ( statement_location, statement, & mut bits,
229
- & mut callback) ;
269
+ visitor. update_bits_and_do_callback (
270
+ statement_location,
271
+ statement,
272
+ & mut bits,
273
+ & mut callback,
274
+ ) ;
230
275
}
231
276
}
232
277
}
@@ -306,30 +351,33 @@ pub fn categorize<'tcx>(context: PlaceContext<'tcx>, mode: LivenessMode) -> Opti
306
351
}
307
352
}
308
353
309
- struct DefsUsesVisitor < ' lv > {
354
+ struct DefsUsesVisitor < ' lv , V , M >
355
+ where
356
+ V : Idx ,
357
+ M : LiveVariableMap < LiveVar = V > + ' lv ,
358
+ {
310
359
mode : LivenessMode ,
311
- defs_uses : DefsUses < ' lv > ,
360
+ map : & ' lv M ,
361
+ defs_uses : DefsUses < V > ,
312
362
}
313
363
314
364
#[ derive( Eq , PartialEq , Clone ) ]
315
- struct DefsUses < ' lv >
316
- {
317
- defs : LocalSet < Local > ,
318
- uses : LocalSet < Local > ,
319
- map : & ' lv dyn LiveVariableMap < LiveVar =Local > ,
365
+ struct DefsUses < V : Idx > {
366
+ defs : LocalSet < V > ,
367
+ uses : LocalSet < V > ,
320
368
}
321
369
322
- impl < ' lv > DefsUses < ' lv > {
370
+ impl < V : Idx > DefsUses < V > {
323
371
fn clear ( & mut self ) {
324
372
self . uses . clear ( ) ;
325
373
self . defs . clear ( ) ;
326
374
}
327
375
328
- fn apply ( & self , bits : & mut LocalSet < Local > ) -> bool {
376
+ fn apply ( & self , bits : & mut LocalSet < V > ) -> bool {
329
377
bits. subtract ( & self . defs ) | bits. union ( & self . uses )
330
378
}
331
379
332
- fn add_def ( & mut self , index : Local ) {
380
+ fn add_def ( & mut self , index : V ) {
333
381
// If it was used already in the block, remove that use
334
382
// now that we found a definition.
335
383
//
@@ -339,13 +387,11 @@ impl<'lv> DefsUses<'lv> {
339
387
// X = 5
340
388
// // Defs = {}, Uses = {X}
341
389
// use(X)
342
- if let Some ( v_index) = self . map . from_local ( index) {
343
- self . uses . remove ( & v_index) ;
344
- self . defs . add ( & v_index) ;
345
- }
390
+ self . uses . remove ( & index) ;
391
+ self . defs . add ( & index) ;
346
392
}
347
393
348
- fn add_use ( & mut self , index : Local ) {
394
+ fn add_use ( & mut self , index : V ) {
349
395
// Inverse of above.
350
396
//
351
397
// Example:
@@ -356,53 +402,62 @@ impl<'lv> DefsUses<'lv> {
356
402
// X = 5
357
403
// // Defs = {}, Uses = {X}
358
404
// use(X)
359
- if let Some ( v_index) = self . map . from_local ( index) {
360
- self . defs . remove ( & v_index) ;
361
- self . uses . add ( & v_index) ;
362
- }
405
+ self . defs . remove ( & index) ;
406
+ self . uses . add ( & index) ;
363
407
}
364
408
}
365
409
366
- impl < ' lv > DefsUsesVisitor < ' lv >
410
+ impl < ' lv , V , M > DefsUsesVisitor < ' lv , V , M >
411
+ where
412
+ V : Idx ,
413
+ M : LiveVariableMap < LiveVar = V > ,
367
414
{
368
415
/// Update `bits` with the effects of `value` and call `callback`. We
369
416
/// should always visit in reverse order. This method assumes that we have
370
417
/// not visited anything before; if you have, clear `bits` first.
371
- fn update_bits_and_do_callback < ' tcx , OP > ( & mut self , location : Location ,
372
- value : & impl MirVisitable < ' tcx > , bits : & mut LocalSet < Local > ,
373
- callback : & mut OP )
374
- where
375
- OP : FnMut ( Location , & LocalSet < Local > ) ,
418
+ fn update_bits_and_do_callback < ' tcx , OP > (
419
+ & mut self ,
420
+ location : Location ,
421
+ value : & impl MirVisitable < ' tcx > ,
422
+ bits : & mut LocalSet < V > ,
423
+ callback : & mut OP ,
424
+ ) where
425
+ OP : FnMut ( Location , & LocalSet < V > ) ,
376
426
{
377
427
value. apply ( location, self ) ;
378
428
self . defs_uses . apply ( bits) ;
379
429
callback ( location, bits) ;
380
430
}
381
431
}
382
432
383
- impl < ' tcx , ' lv > Visitor < ' tcx > for DefsUsesVisitor < ' lv > {
433
+ impl < ' tcx , ' lv , V , M > Visitor < ' tcx > for DefsUsesVisitor < ' lv , V , M >
434
+ where
435
+ V : Idx ,
436
+ M : LiveVariableMap < LiveVar = V > ,
437
+ {
384
438
fn visit_local ( & mut self , & local: & Local , context : PlaceContext < ' tcx > , _: Location ) {
385
- match categorize ( context, self . mode ) {
386
- Some ( DefUse :: Def ) => {
387
- self . defs_uses . add_def ( local) ;
439
+ if let Some ( v_index) = self . map . from_local ( local) {
440
+ match categorize ( context, self . mode ) {
441
+ Some ( DefUse :: Def ) => self . defs_uses . add_def ( v_index) ,
442
+ Some ( DefUse :: Use ) => self . defs_uses . add_use ( v_index) ,
443
+ None => ( ) ,
388
444
}
389
-
390
- Some ( DefUse :: Use ) => {
391
- self . defs_uses . add_use ( local) ;
392
- }
393
-
394
- None => { }
395
445
}
396
446
}
397
447
}
398
448
399
- fn block < ' tcx , ' lv > ( mode : LivenessMode , b : & BasicBlockData < ' tcx > , locals : usize ) -> DefsUses < ' lv > {
449
+ fn block < ' tcx , V : Idx > (
450
+ mode : LivenessMode ,
451
+ map : & impl LiveVariableMap < LiveVar = V > ,
452
+ b : & BasicBlockData < ' tcx > ,
453
+ locals : usize ,
454
+ ) -> DefsUses < V > {
400
455
let mut visitor = DefsUsesVisitor {
401
456
mode,
457
+ map,
402
458
defs_uses : DefsUses {
403
459
defs : LocalSet :: new_empty ( locals) ,
404
460
uses : LocalSet :: new_empty ( locals) ,
405
- map : & IdentityMap { } ,
406
461
} ,
407
462
} ;
408
463
@@ -421,13 +476,13 @@ fn block<'tcx, 'lv>(mode: LivenessMode, b: &BasicBlockData<'tcx>, locals: usize)
421
476
visitor. defs_uses
422
477
}
423
478
424
- pub fn dump_mir < ' a , ' tcx , V : LiveVariableMap > (
479
+ pub fn dump_mir < ' a , ' tcx , V : Idx > (
425
480
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
426
481
pass_name : & str ,
427
482
source : MirSource ,
428
483
mir : & Mir < ' tcx > ,
429
- result : & LivenessResult < Local > ,
430
- map : & impl LiveVariableMap < LiveVar = V >
484
+ map : & impl LiveVariableMap < LiveVar = V > ,
485
+ result : & LivenessResult < V > ,
431
486
) {
432
487
if !dump_enabled ( tcx, pass_name, source) {
433
488
return ;
@@ -436,16 +491,17 @@ pub fn dump_mir<'a, 'tcx, V: LiveVariableMap>(
436
491
// see notes on #41697 below
437
492
tcx. item_path_str ( source. def_id )
438
493
} ) ;
439
- dump_matched_mir_node ( tcx, pass_name, & node_path, source, mir, result) ;
494
+ dump_matched_mir_node ( tcx, pass_name, & node_path, source, mir, map , result) ;
440
495
}
441
496
442
- fn dump_matched_mir_node < ' a , ' tcx , V : LiveVariableMap > (
497
+ fn dump_matched_mir_node < ' a , ' tcx , V : Idx > (
443
498
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
444
499
pass_name : & str ,
445
500
node_path : & str ,
446
501
source : MirSource ,
447
502
mir : & Mir < ' tcx > ,
448
- result : & LivenessResult < V :: LiveVar > ,
503
+ map : & dyn LiveVariableMap < LiveVar = V > ,
504
+ result : & LivenessResult < V > ,
449
505
) {
450
506
let mut file_path = PathBuf :: new ( ) ;
451
507
file_path. push ( Path :: new ( & tcx. sess . opts . debugging_opts . dump_mir_dir ) ) ;
@@ -457,25 +513,25 @@ fn dump_matched_mir_node<'a, 'tcx, V: LiveVariableMap>(
457
513
writeln ! ( file, "// source = {:?}" , source) ?;
458
514
writeln ! ( file, "// pass_name = {}" , pass_name) ?;
459
515
writeln ! ( file, "" ) ?;
460
- write_mir_fn ( tcx, source, mir, & mut file, result) ?;
516
+ write_mir_fn ( tcx, source, mir, map , & mut file, result) ?;
461
517
Ok ( ( ) )
462
518
} ) ;
463
519
}
464
520
465
- pub fn write_mir_fn < ' a , ' tcx , V : LiveVariableMap > (
521
+ pub fn write_mir_fn < ' a , ' tcx , V : Idx > (
466
522
tcx : TyCtxt < ' a , ' tcx , ' tcx > ,
467
523
src : MirSource ,
468
524
mir : & Mir < ' tcx > ,
525
+ map : & dyn LiveVariableMap < LiveVar = V > ,
469
526
w : & mut dyn Write ,
470
- result : & LivenessResult < V :: LiveVar > ,
527
+ result : & LivenessResult < V > ,
471
528
) -> io:: Result < ( ) > {
472
529
write_mir_intro ( tcx, src, mir, w) ?;
473
530
for block in mir. basic_blocks ( ) . indices ( ) {
474
- let print = |w : & mut dyn Write , prefix, result : & IndexVec < BasicBlock , LocalSet < Local > > | {
475
- let live: Vec < String > = mir. local_decls
476
- . indices ( )
477
- . filter ( |i| result[ block] . contains ( i) )
478
- . map ( |i| format ! ( "{:?}" , i) )
531
+ let print = |w : & mut dyn Write , prefix, result : & IndexVec < BasicBlock , LocalSet < V > > | {
532
+ let live: Vec < String > = result[ block] . iter ( )
533
+ . map ( |v| map. from_live_var ( v) )
534
+ . map ( |local| format ! ( "{:?}" , local) )
479
535
. collect ( ) ;
480
536
writeln ! ( w, "{} {{{}}}" , prefix, live. join( ", " ) )
481
537
} ;
0 commit comments