@@ -15,7 +15,7 @@ use rustc_data_structures::indexed_vec::Idx;
15
15
use rustc_data_structures:: bitslice:: { bitwise, BitwiseOperator } ;
16
16
17
17
use rustc:: ty:: { self , TyCtxt } ;
18
- use rustc:: mir:: { self , Mir , BasicBlock , Location } ;
18
+ use rustc:: mir:: { self , Mir , BasicBlock , BasicBlockData , Location , Statement , Terminator } ;
19
19
use rustc:: session:: Session ;
20
20
21
21
use std:: fmt:: { self , Debug } ;
@@ -47,7 +47,19 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation
47
47
}
48
48
49
49
pub trait Dataflow < BD : BitDenotation > {
50
- fn dataflow < P > ( & mut self , p : P ) where P : Fn ( & BD , BD :: Idx ) -> & Debug ;
50
+ /// Sets up and runs the dataflow problem, using `p` to render results if
51
+ /// implementation so chooses.
52
+ fn dataflow < P > ( & mut self , p : P ) where P : Fn ( & BD , BD :: Idx ) -> & Debug {
53
+ let _ = p; // default implementation does not instrument process.
54
+ self . build_sets ( ) ;
55
+ self . propagate ( ) ;
56
+ }
57
+
58
+ /// Sets up the entry, gen, and kill sets for this instance of a dataflow problem.
59
+ fn build_sets ( & mut self ) ;
60
+
61
+ /// Finds a fixed-point solution to this instance of a dataflow problem.
62
+ fn propagate ( & mut self ) ;
51
63
}
52
64
53
65
impl < ' a , ' tcx : ' a , BD > Dataflow < BD > for DataflowBuilder < ' a , ' tcx , BD >
@@ -59,6 +71,9 @@ impl<'a, 'tcx: 'a, BD> Dataflow<BD> for DataflowBuilder<'a, 'tcx, BD>
59
71
self . flow_state . propagate ( ) ;
60
72
self . post_dataflow_instrumentation ( |c, i| p ( c, i) ) . unwrap ( ) ;
61
73
}
74
+
75
+ fn build_sets ( & mut self ) { self . flow_state . build_sets ( ) ; }
76
+ fn propagate ( & mut self ) { self . flow_state . propagate ( ) ; }
62
77
}
63
78
64
79
pub ( crate ) fn has_rustc_mir_with ( attrs : & [ ast:: Attribute ] , name : & str ) -> Option < MetaItem > {
@@ -254,6 +269,93 @@ impl<E:Idx> Bits<E> {
254
269
}
255
270
}
256
271
272
+ /// DataflowResultsConsumer abstracts over walking the MIR with some
273
+ /// already constructed dataflow results.
274
+ ///
275
+ /// It abstracts over the FlowState and also completely hides the
276
+ /// underlying flow analysis results, because it needs to handle cases
277
+ /// where we are combining the results of *multiple* flow analyses
278
+ /// (e.g. borrows + inits + uninits).
279
+ pub trait DataflowResultsConsumer < ' a , ' tcx : ' a > {
280
+ type FlowState ;
281
+
282
+ // Observation Hooks: override (at least one of) these to get analysis feedback.
283
+ fn visit_block_entry ( & mut self ,
284
+ _bb : BasicBlock ,
285
+ _flow_state : & Self :: FlowState ) { }
286
+
287
+ fn visit_statement_entry ( & mut self ,
288
+ _loc : Location ,
289
+ _stmt : & Statement < ' tcx > ,
290
+ _flow_state : & Self :: FlowState ) { }
291
+
292
+ fn visit_terminator_entry ( & mut self ,
293
+ _loc : Location ,
294
+ _term : & Terminator < ' tcx > ,
295
+ _flow_state : & Self :: FlowState ) { }
296
+
297
+ // Main entry point: this drives the processing of results.
298
+
299
+ fn analyze_results ( & mut self , flow_uninit : & mut Self :: FlowState ) {
300
+ let flow = flow_uninit;
301
+ for bb in self . mir ( ) . basic_blocks ( ) . indices ( ) {
302
+ self . reset_to_entry_of ( bb, flow) ;
303
+ self . process_basic_block ( bb, flow) ;
304
+ }
305
+ }
306
+
307
+ fn process_basic_block ( & mut self , bb : BasicBlock , flow_state : & mut Self :: FlowState ) {
308
+ let BasicBlockData { ref statements, ref terminator, is_cleanup : _ } =
309
+ self . mir ( ) [ bb] ;
310
+ let mut location = Location { block : bb, statement_index : 0 } ;
311
+ for stmt in statements. iter ( ) {
312
+ self . reconstruct_statement_effect ( location, flow_state) ;
313
+ self . visit_statement_entry ( location, stmt, flow_state) ;
314
+ self . apply_local_effect ( location, flow_state) ;
315
+ location. statement_index += 1 ;
316
+ }
317
+
318
+ if let Some ( ref term) = * terminator {
319
+ self . reconstruct_terminator_effect ( location, flow_state) ;
320
+ self . visit_terminator_entry ( location, term, flow_state) ;
321
+
322
+ // We don't need to apply the effect of the terminator,
323
+ // since we are only visiting dataflow state on control
324
+ // flow entry to the various nodes. (But we still need to
325
+ // reconstruct the effect, because the visit method might
326
+ // inspect it.)
327
+ }
328
+ }
329
+
330
+ // Delegated Hooks: Provide access to the MIR and process the flow state.
331
+
332
+ fn mir ( & self ) -> & ' a Mir < ' tcx > ;
333
+
334
+ // reset the state bitvector to represent the entry to block `bb`.
335
+ fn reset_to_entry_of ( & mut self ,
336
+ bb : BasicBlock ,
337
+ flow_state : & mut Self :: FlowState ) ;
338
+
339
+ // build gen + kill sets for statement at `loc`.
340
+ fn reconstruct_statement_effect ( & mut self ,
341
+ loc : Location ,
342
+ flow_state : & mut Self :: FlowState ) ;
343
+
344
+ // build gen + kill sets for terminator for `loc`.
345
+ fn reconstruct_terminator_effect ( & mut self ,
346
+ loc : Location ,
347
+ flow_state : & mut Self :: FlowState ) ;
348
+
349
+ // apply current gen + kill sets to `flow_state`.
350
+ //
351
+ // (`bb` and `stmt_idx` parameters can be ignored if desired by
352
+ // client. For the terminator, the `stmt_idx` will be the number
353
+ // of statements in the block.)
354
+ fn apply_local_effect ( & mut self ,
355
+ loc : Location ,
356
+ flow_state : & mut Self :: FlowState ) ;
357
+ }
358
+
257
359
pub struct DataflowAnalysis < ' a , ' tcx : ' a , O >
258
360
where O : BitDenotation
259
361
{
@@ -269,6 +371,8 @@ impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O>
269
371
DataflowResults ( self . flow_state )
270
372
}
271
373
374
+ pub fn flow_state ( & self ) -> & DataflowState < O > { & self . flow_state }
375
+
272
376
pub fn mir ( & self ) -> & ' a Mir < ' tcx > { self . mir }
273
377
}
274
378
@@ -278,10 +382,14 @@ impl<O: BitDenotation> DataflowResults<O> {
278
382
pub fn sets ( & self ) -> & AllSets < O :: Idx > {
279
383
& self . 0 . sets
280
384
}
385
+
386
+ pub fn operator ( & self ) -> & O {
387
+ & self . 0 . operator
388
+ }
281
389
}
282
390
283
- // FIXME: This type shouldn't be public, but the graphviz::MirWithFlowState trait
284
- // references it in a method signature. Look into using `pub(crate)` to address this .
391
+ /// State of a dataflow analysis; couples a collection of bit sets
392
+ /// with operator used to initialize and merge bits during analysis .
285
393
pub struct DataflowState < O : BitDenotation >
286
394
{
287
395
/// All the sets for the analysis. (Factored into its
0 commit comments