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:
parent
3ef1afcf6b
commit
9b8b8c6aeb
@ -153,4 +153,38 @@ impl<T: Idx> IdxSet<T> {
|
|||||||
pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
|
pub fn subtract(&mut self, other: &IdxSet<T>) -> bool {
|
||||||
bitwise(self.words_mut(), other.words(), &Subtract)
|
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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,6 @@
|
|||||||
use syntax::ast::NodeId;
|
use syntax::ast::NodeId;
|
||||||
use rustc::mir::{BasicBlock, Mir};
|
use rustc::mir::{BasicBlock, Mir};
|
||||||
use rustc_data_structures::bitslice::bits_to_string;
|
use rustc_data_structures::bitslice::bits_to_string;
|
||||||
use rustc_data_structures::indexed_set::{IdxSet};
|
|
||||||
use rustc_data_structures::indexed_vec::Idx;
|
use rustc_data_structures::indexed_vec::Idx;
|
||||||
|
|
||||||
use dot;
|
use dot;
|
||||||
@ -24,7 +23,6 @@ use std::fs::File;
|
|||||||
use std::io;
|
use std::io;
|
||||||
use std::io::prelude::*;
|
use std::io::prelude::*;
|
||||||
use std::marker::PhantomData;
|
use std::marker::PhantomData;
|
||||||
use std::mem;
|
|
||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
|
|
||||||
use util;
|
use util;
|
||||||
@ -32,54 +30,6 @@ use util;
|
|||||||
use super::{BitDenotation, DataflowState};
|
use super::{BitDenotation, DataflowState};
|
||||||
use super::DataflowBuilder;
|
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> {
|
pub trait MirWithFlowState<'tcx> {
|
||||||
type BD: BitDenotation;
|
type BD: BitDenotation;
|
||||||
fn node_id(&self) -> NodeId;
|
fn node_id(&self) -> NodeId;
|
||||||
|
@ -293,6 +293,28 @@ pub struct DataflowState<O: BitDenotation>
|
|||||||
pub(crate) operator: O,
|
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)]
|
#[derive(Debug)]
|
||||||
pub struct AllSets<E: Idx> {
|
pub struct AllSets<E: Idx> {
|
||||||
/// Analysis bitwidth for each block.
|
/// Analysis bitwidth for each block.
|
||||||
|
Loading…
Reference in New Issue
Block a user