@@ -15,7 +15,7 @@ use rustc_data_structures::indexed_vec::Idx;
1515use rustc_data_structures:: bitslice:: { bitwise, BitwiseOperator } ;
1616
1717use rustc:: ty:: { self , TyCtxt } ;
18- use rustc:: mir:: { self , Mir , BasicBlock , Location } ;
18+ use rustc:: mir:: { self , Mir , BasicBlock , BasicBlockData , Location , Statement , Terminator } ;
1919use rustc:: session:: Session ;
2020
2121use std:: fmt:: { self , Debug } ;
@@ -47,7 +47,19 @@ pub(crate) struct DataflowBuilder<'a, 'tcx: 'a, BD> where BD: BitDenotation
4747}
4848
4949pub 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 ) ;
5163}
5264
5365impl < ' 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>
5971 self . flow_state . propagate ( ) ;
6072 self . post_dataflow_instrumentation ( |c, i| p ( c, i) ) . unwrap ( ) ;
6173 }
74+
75+ fn build_sets ( & mut self ) { self . flow_state . build_sets ( ) ; }
76+ fn propagate ( & mut self ) { self . flow_state . propagate ( ) ; }
6277}
6378
6479pub ( crate ) fn has_rustc_mir_with ( attrs : & [ ast:: Attribute ] , name : & str ) -> Option < MetaItem > {
@@ -254,6 +269,93 @@ impl<E:Idx> Bits<E> {
254269 }
255270}
256271
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+
257359pub struct DataflowAnalysis < ' a , ' tcx : ' a , O >
258360 where O : BitDenotation
259361{
@@ -269,6 +371,8 @@ impl<'a, 'tcx: 'a, O> DataflowAnalysis<'a, 'tcx, O>
269371 DataflowResults ( self . flow_state )
270372 }
271373
374+ pub fn flow_state ( & self ) -> & DataflowState < O > { & self . flow_state }
375+
272376 pub fn mir ( & self ) -> & ' a Mir < ' tcx > { self . mir }
273377}
274378
@@ -278,10 +382,14 @@ impl<O: BitDenotation> DataflowResults<O> {
278382 pub fn sets ( & self ) -> & AllSets < O :: Idx > {
279383 & self . 0 . sets
280384 }
385+
386+ pub fn operator ( & self ) -> & O {
387+ & self . 0 . operator
388+ }
281389}
282390
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 .
285393pub struct DataflowState < O : BitDenotation >
286394{
287395 /// All the sets for the analysis. (Factored into its
0 commit comments