Move DataFlowState::{each_bit,interpret_set} method definitions to parent module.

Refactored `each_bit`, which traverses a `IdxSet`, so that the bulk of
its implementation lives in `rustc_data_structures`.
This commit is contained in:
Felix S. Klock II 2017-07-04 15:12:11 +02:00
parent 3ef1afcf6b
commit 9b8b8c6aeb
3 changed files with 56 additions and 50 deletions

View File

@ -153,4 +153,38 @@ impl<T: Idx> IdxSet<T> {
pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
bitwise(self.words_mut(), other.words(), &Subtract)
}
/// Calls `f` on each index value held in this set, up to the
/// bound `max_bits` on the size of universe of indexes.
pub fn each_bit<F>(&self, max_bits: usize, f: F) where F: FnMut(T) {
each_bit(self, max_bits, f)
}
}
fn each_bit<T: Idx, F>(words: &IdxSet<T>, max_bits: usize, mut f: F) where F: FnMut(T) {
let usize_bits: usize = mem::size_of::<usize>() * 8;
for (word_index, &word) in words.words().iter().enumerate() {
if word != 0 {
let base_index = word_index * usize_bits;
for offset in 0..usize_bits {
let bit = 1 << offset;
if (word & bit) != 0 {
// NB: we round up the total number of bits
// that we store in any given bit set so that
// it is an even multiple of usize::BITS. This
// means that there may be some stray bits at
// the end that do not correspond to any
// actual value; that's why we first check
// that we are in range of bits_per_block.
let bit_index = base_index + offset as usize;
if bit_index >= max_bits {
return;
} else {
f(Idx::new(bit_index));
}
}
}
}
}
}

View File

@ -13,7 +13,6 @@
use syntax::ast::NodeId;
use rustc::mir::{BasicBlock, Mir};
use rustc_data_structures::bitslice::bits_to_string;
use rustc_data_structures::indexed_set::{IdxSet};
use rustc_data_structures::indexed_vec::Idx;
use dot;
@ -24,7 +23,6 @@ use std::fs::File;
use std::io;
use std::io::prelude::*;
use std::marker::PhantomData;
use std::mem;
use std::path::Path;
use util;
@ -32,54 +30,6 @@ use util;
use super::{BitDenotation, DataflowState};
use super::DataflowBuilder;
impl<O: BitDenotation> DataflowState<O> {
fn each_bit<F>(&self, words: &IdxSet<O::Idx>, mut f: F)
where F: FnMut(O::Idx) {
//! Helper for iterating over the bits in a bitvector.
let bits_per_block = self.operator.bits_per_block();
let usize_bits: usize = mem::size_of::<usize>() * 8;
for (word_index, &word) in words.words().iter().enumerate() {
if word != 0 {
let base_index = word_index * usize_bits;
for offset in 0..usize_bits {
let bit = 1 << offset;
if (word & bit) != 0 {
// NB: we round up the total number of bits
// that we store in any given bit set so that
// it is an even multiple of usize::BITS. This
// means that there may be some stray bits at
// the end that do not correspond to any
// actual value; that's why we first check
// that we are in range of bits_per_block.
let bit_index = base_index + offset as usize;
if bit_index >= bits_per_block {
return;
} else {
f(O::Idx::new(bit_index));
}
}
}
}
}
}
pub fn interpret_set<'c, P>(&self,
o: &'c O,
words: &IdxSet<O::Idx>,
render_idx: &P)
-> Vec<&'c Debug>
where P: Fn(&O, O::Idx) -> &Debug
{
let mut v = Vec::new();
self.each_bit(words, |i| {
v.push(render_idx(o, i));
});
v
}
}
pub trait MirWithFlowState<'tcx> {
type BD: BitDenotation;
fn node_id(&self) -> NodeId;

View File

@ -293,6 +293,28 @@ pub struct DataflowState<O: BitDenotation>
pub(crate) operator: O,
}
impl<O: BitDenotation> DataflowState<O> {
pub fn each_bit<F>(&self, words: &IdxSet<O::Idx>, f: F) where F: FnMut(O::Idx)
{
let bits_per_block = self.operator.bits_per_block();
words.each_bit(bits_per_block, f)
}
pub fn interpret_set<'c, P>(&self,
o: &'c O,
words: &IdxSet<O::Idx>,
render_idx: &P)
-> Vec<&'c Debug>
where P: Fn(&O, O::Idx) -> &Debug
{
let mut v = Vec::new();
self.each_bit(words, |i| {
v.push(render_idx(o, i));
});
v
}
}
#[derive(Debug)]
pub struct AllSets<E: Idx> {
/// Analysis bitwidth for each block.