Skip to content

Commit 0cf5f10

Browse files
committed
Replaced use of interpret method in mir::dataflow::graphviz with a client-provided closure.
1 parent 221cce9 commit 0cf5f10

File tree

3 files changed

+94
-76
lines changed

3 files changed

+94
-76
lines changed

src/librustc_borrowck/borrowck/mir/dataflow/graphviz.rs

Lines changed: 76 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,73 @@ use std::fs::File;
2121
use std::io;
2222
use std::io::prelude::*;
2323
use std::marker::PhantomData;
24+
use std::mem;
2425
use std::path::Path;
2526

27+
use super::super::gather_moves::{MoveData};
2628
use super::super::MirBorrowckCtxtPreDataflow;
2729
use bitslice::bits_to_string;
30+
use indexed_set::{Idx, IdxSet};
2831
use super::{BitDenotation, DataflowState};
29-
use super::{HasMoveData};
32+
33+
impl<O: BitDenotation> DataflowState<O> {
34+
fn each_bit<F>(&self, ctxt: &O::Ctxt, words: &IdxSet<O::Idx>, mut f: F)
35+
where F: FnMut(O::Idx) {
36+
//! Helper for iterating over the bits in a bitvector.
37+
38+
let bits_per_block = self.operator.bits_per_block(ctxt);
39+
let usize_bits: usize = mem::size_of::<usize>() * 8;
40+
41+
for (word_index, &word) in words.words().iter().enumerate() {
42+
if word != 0 {
43+
let base_index = word_index * usize_bits;
44+
for offset in 0..usize_bits {
45+
let bit = 1 << offset;
46+
if (word & bit) != 0 {
47+
// NB: we round up the total number of bits
48+
// that we store in any given bit set so that
49+
// it is an even multiple of usize::BITS. This
50+
// means that there may be some stray bits at
51+
// the end that do not correspond to any
52+
// actual value; that's why we first check
53+
// that we are in range of bits_per_block.
54+
let bit_index = base_index + offset as usize;
55+
if bit_index >= bits_per_block {
56+
return;
57+
} else {
58+
f(O::Idx::new(bit_index));
59+
}
60+
}
61+
}
62+
}
63+
}
64+
}
65+
66+
pub fn interpret_set<'c, P>(&self,
67+
ctxt: &'c O::Ctxt,
68+
words: &IdxSet<O::Idx>,
69+
render_idx: &P)
70+
-> Vec<&'c Debug>
71+
where P: for <'b> Fn(&'b O::Ctxt, O::Idx) -> &'b Debug
72+
{
73+
let mut v = Vec::new();
74+
self.each_bit(ctxt, words, |i| {
75+
v.push(render_idx(ctxt, i));
76+
});
77+
v
78+
}
79+
}
3080

3181
pub trait MirWithFlowState<'tcx> {
32-
type BD: BitDenotation;
82+
type BD: BitDenotation<Ctxt=MoveData<'tcx>>;
3383
fn node_id(&self) -> NodeId;
3484
fn mir(&self) -> &Mir<'tcx>;
3585
fn analysis_ctxt(&self) -> &<Self::BD as BitDenotation>::Ctxt;
3686
fn flow_state(&self) -> &DataflowState<Self::BD>;
3787
}
3888

3989
impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
40-
where 'a, 'tcx: 'a, BD: BitDenotation, BD::Ctxt: HasMoveData<'tcx>
90+
where 'a, 'tcx: 'a, BD: BitDenotation<Ctxt=MoveData<'tcx>>
4191
{
4292
type BD = BD;
4393
fn node_id(&self) -> NodeId { self.node_id }
@@ -46,19 +96,23 @@ impl<'a, 'tcx: 'a, BD> MirWithFlowState<'tcx> for MirBorrowckCtxtPreDataflow<'a,
4696
fn flow_state(&self) -> &DataflowState<Self::BD> { &self.flow_state.flow_state }
4797
}
4898

49-
struct Graph<'a, 'tcx, MWF:'a> where MWF: MirWithFlowState<'tcx>,
99+
struct Graph<'a, 'tcx, MWF:'a, P> where
100+
MWF: MirWithFlowState<'tcx>
50101
{
51102
mbcx: &'a MWF,
52-
phantom: PhantomData<&'tcx ()>
103+
phantom: PhantomData<&'tcx ()>,
104+
render_idx: P,
53105
}
54106

55-
pub fn print_borrowck_graph_to<'a, 'tcx, BD>(
107+
pub fn print_borrowck_graph_to<'a, 'tcx, BD, P>(
56108
mbcx: &MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>,
57-
path: &Path)
109+
path: &Path,
110+
render_idx: P)
58111
-> io::Result<()>
59-
where BD: BitDenotation, BD::Bit: Debug, BD::Ctxt: HasMoveData<'tcx>,
112+
where BD: BitDenotation<Ctxt=MoveData<'tcx>>, BD::Bit: Debug,
113+
P: for <'b> Fn(&'b BD::Ctxt, BD::Idx) -> &'b Debug
60114
{
61-
let g = Graph { mbcx: mbcx, phantom: PhantomData };
115+
let g = Graph { mbcx: mbcx, phantom: PhantomData, render_idx: render_idx };
62116
let mut v = Vec::new();
63117
dot::render(&g, &mut v)?;
64118
debug!("print_borrowck_graph_to path: {} node_id: {}",
@@ -76,8 +130,9 @@ fn outgoing(mir: &Mir, bb: BasicBlock) -> Vec<Edge> {
76130
(0..succ_len).map(|index| Edge { source: bb, index: index}).collect()
77131
}
78132

79-
impl<'a, 'tcx, MWF> dot::Labeller<'a> for Graph<'a, 'tcx, MWF>
80-
where MWF: MirWithFlowState<'tcx>, <MWF::BD as BitDenotation>::Bit: Debug
133+
impl<'a, 'tcx, MWF, P> dot::Labeller<'a> for Graph<'a, 'tcx, MWF, P>
134+
where MWF: MirWithFlowState<'tcx>, <MWF::BD as BitDenotation>::Bit: Debug,
135+
P: for <'b> Fn(&'b <MWF::BD as BitDenotation>::Ctxt, <MWF::BD as BitDenotation>::Idx) -> &'b Debug,
81136
{
82137
type Node = Node;
83138
type Edge = Edge;
@@ -136,10 +191,10 @@ impl<'a, 'tcx, MWF> dot::Labeller<'a> for Graph<'a, 'tcx, MWF>
136191
const BG_FLOWCONTENT: &'static str = r#"bgcolor="pink""#;
137192
const ALIGN_RIGHT: &'static str = r#"align="right""#;
138193
const FACE_MONOSPACE: &'static str = r#"FACE="Courier""#;
139-
fn chunked_present_left<D: Debug, W:io::Write>(w: &mut W,
140-
interpreted: &[&D],
141-
chunk_size: usize)
142-
-> io::Result<()>
194+
fn chunked_present_left<W:io::Write>(w: &mut W,
195+
interpreted: &[&Debug],
196+
chunk_size: usize)
197+
-> io::Result<()>
143198
{
144199
// This function may emit a sequence of <tr>'s, but it
145200
// always finishes with an (unfinished)
@@ -171,7 +226,9 @@ impl<'a, 'tcx, MWF> dot::Labeller<'a> for Graph<'a, 'tcx, MWF>
171226
|w| {
172227
let ctxt = self.mbcx.analysis_ctxt();
173228
let flow = self.mbcx.flow_state();
174-
let entry_interp = flow.interpret_set(ctxt, flow.sets.on_entry_set_for(i));
229+
let entry_interp = flow.interpret_set(ctxt,
230+
flow.sets.on_entry_set_for(i),
231+
&self.render_idx);
175232
chunked_present_left(w, &entry_interp[..], chunk_size)?;
176233
let bits_per_block = flow.sets.bits_per_block();
177234
let entry = flow.sets.on_entry_set_for(i);
@@ -186,8 +243,8 @@ impl<'a, 'tcx, MWF> dot::Labeller<'a> for Graph<'a, 'tcx, MWF>
186243
|w| {
187244
let ctxt = self.mbcx.analysis_ctxt();
188245
let flow = self.mbcx.flow_state();
189-
let gen_interp = flow.interpret_set(ctxt, flow.sets.gen_set_for(i));
190-
let kill_interp = flow.interpret_set(ctxt, flow.sets.kill_set_for(i));
246+
let gen_interp = flow.interpret_set(ctxt, flow.sets.gen_set_for(i), &self.render_idx);
247+
let kill_interp = flow.interpret_set(ctxt, flow.sets.kill_set_for(i), &self.render_idx);
191248
chunked_present_left(w, &gen_interp[..], chunk_size)?;
192249
let bits_per_block = flow.sets.bits_per_block();
193250
{
@@ -245,7 +302,7 @@ impl<'a, 'tcx, MWF> dot::Labeller<'a> for Graph<'a, 'tcx, MWF>
245302
}
246303
}
247304

248-
impl<'a, 'tcx, MWF> dot::GraphWalk<'a> for Graph<'a, 'tcx, MWF>
305+
impl<'a, 'tcx, MWF, P> dot::GraphWalk<'a> for Graph<'a, 'tcx, MWF, P>
249306
where MWF: MirWithFlowState<'tcx>
250307
{
251308
type Node = Node;

src/librustc_borrowck/borrowck/mir/dataflow/mod.rs

Lines changed: 16 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,19 @@ mod graphviz;
3131
mod sanity_check;
3232
mod impls;
3333

34-
pub trait Dataflow {
35-
fn dataflow(&mut self);
34+
pub trait Dataflow<BD: BitDenotation> {
35+
fn dataflow<P>(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug;
3636
}
3737

38-
impl<'a, 'tcx: 'a, BD> Dataflow for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
39-
where BD: BitDenotation + DataflowOperator,
38+
impl<'a, 'tcx: 'a, BD> Dataflow<BD> for MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
39+
where BD: BitDenotation<Ctxt=MoveData<'tcx>> + DataflowOperator,
4040
BD::Bit: Debug,
41-
BD::Ctxt: HasMoveData<'tcx>
4241
{
43-
fn dataflow(&mut self) {
42+
fn dataflow<P>(&mut self, p: P) where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug {
4443
self.flow_state.build_sets();
45-
self.pre_dataflow_instrumentation().unwrap();
44+
self.pre_dataflow_instrumentation(|c,i| p(c,i)).unwrap();
4645
self.flow_state.propagate();
47-
self.post_dataflow_instrumentation().unwrap();
46+
self.post_dataflow_instrumentation(|c,i| p(c,i)).unwrap();
4847
}
4948
}
5049

@@ -142,21 +141,25 @@ fn dataflow_path(context: &str, prepost: &str, path: &str) -> PathBuf {
142141
}
143142

144143
impl<'a, 'tcx: 'a, BD> MirBorrowckCtxtPreDataflow<'a, 'tcx, BD>
145-
where BD: BitDenotation, BD::Bit: Debug, BD::Ctxt: HasMoveData<'tcx>
144+
where BD: BitDenotation<Ctxt=MoveData<'tcx>>, BD::Bit: Debug
146145
{
147-
fn pre_dataflow_instrumentation(&self) -> io::Result<()> {
146+
fn pre_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
147+
where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug
148+
{
148149
if let Some(ref path_str) = self.print_preflow_to {
149150
let path = dataflow_path(BD::name(), "preflow", path_str);
150-
graphviz::print_borrowck_graph_to(self, &path)
151+
graphviz::print_borrowck_graph_to(self, &path, p)
151152
} else {
152153
Ok(())
153154
}
154155
}
155156

156-
fn post_dataflow_instrumentation(&self) -> io::Result<()> {
157+
fn post_dataflow_instrumentation<P>(&self, p: P) -> io::Result<()>
158+
where P: Fn(&BD::Ctxt, BD::Idx) -> &Debug
159+
{
157160
if let Some(ref path_str) = self.print_postflow_to {
158161
let path = dataflow_path(BD::name(), "postflow", path_str);
159-
graphviz::print_borrowck_graph_to(self, &path)
162+
graphviz::print_borrowck_graph_to(self, &path, p)
160163
} else{
161164
Ok(())
162165
}
@@ -291,48 +294,6 @@ impl<E:Idx> AllSets<E> {
291294
}
292295
}
293296

294-
impl<O: BitDenotation> DataflowState<O> {
295-
fn each_bit<F>(&self, ctxt: &O::Ctxt, words: &IdxSet<O::Idx>, mut f: F)
296-
where F: FnMut(usize) {
297-
//! Helper for iterating over the bits in a bitvector.
298-
299-
let bits_per_block = self.operator.bits_per_block(ctxt);
300-
let usize_bits: usize = mem::size_of::<usize>() * 8;
301-
302-
for (word_index, &word) in words.words().iter().enumerate() {
303-
if word != 0 {
304-
let base_index = word_index * usize_bits;
305-
for offset in 0..usize_bits {
306-
let bit = 1 << offset;
307-
if (word & bit) != 0 {
308-
// NB: we round up the total number of bits
309-
// that we store in any given bit set so that
310-
// it is an even multiple of usize::BITS. This
311-
// means that there may be some stray bits at
312-
// the end that do not correspond to any
313-
// actual value; that's why we first check
314-
// that we are in range of bits_per_block.
315-
let bit_index = base_index + offset as usize;
316-
if bit_index >= bits_per_block {
317-
return;
318-
} else {
319-
f(bit_index);
320-
}
321-
}
322-
}
323-
}
324-
}
325-
}
326-
327-
pub fn interpret_set<'c>(&self, ctxt: &'c O::Ctxt, words: &IdxSet<O::Idx>) -> Vec<&'c O::Bit> {
328-
let mut v = Vec::new();
329-
self.each_bit(ctxt, words, |i| {
330-
v.push(self.operator.interpret(ctxt, i));
331-
});
332-
v
333-
}
334-
}
335-
336297
/// Parameterization for the precise form of data flow that is used.
337298
pub trait DataflowOperator: BitwiseOperator {
338299
/// Specifies the initial value for each bit in the `on_entry` set

src/librustc_borrowck/borrowck/mir/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
118118
attributes: &[ast::Attribute],
119119
ctxt: &BD::Ctxt,
120120
bd: BD) -> DataflowResults<BD>
121-
where BD: BitDenotation + DataflowOperator, BD::Bit: Debug, BD::Ctxt: HasMoveData<'tcx>
121+
where BD: BitDenotation<Idx=MovePathIndex, Ctxt=MoveData<'tcx>> + DataflowOperator, BD::Bit: Debug
122122
{
123123
use syntax::attr::AttrMetaMethods;
124124

@@ -148,7 +148,7 @@ fn do_dataflow<'a, 'tcx, BD>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
148148
flow_state: DataflowAnalysis::new(tcx, mir, ctxt, bd),
149149
};
150150

151-
mbcx.dataflow();
151+
mbcx.dataflow(|move_data, i| &move_data.move_paths[i]);
152152
mbcx.flow_state.results()
153153
}
154154

0 commit comments

Comments
 (0)