avoid IdxSets containing garbage above the universe length
This makes sure that all bits in each IdxSet between the universe length and the end of the word are all zero instead of being in an indeterminate state. This fixes a crash with RUST_LOG=rustc_mir, and is probably a good idea anyway.
This commit is contained in:
parent
d2235f20b5
commit
8f9ec1cb06
@ -121,7 +121,9 @@ impl<T: Idx> IdxSetBuf<T> {
|
||||
|
||||
/// Creates set holding every element whose index falls in range 0..universe_size.
|
||||
pub fn new_filled(universe_size: usize) -> Self {
|
||||
Self::new(!0, universe_size)
|
||||
let mut result = Self::new(!0, universe_size);
|
||||
result.trim_to(universe_size);
|
||||
result
|
||||
}
|
||||
|
||||
/// Creates set holding no elements.
|
||||
@ -168,6 +170,36 @@ impl<T: Idx> IdxSet<T> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Sets all elements up to `universe_size`
|
||||
pub fn set_up_to(&mut self, universe_size: usize) {
|
||||
for b in &mut self.bits {
|
||||
*b = !0;
|
||||
}
|
||||
self.trim_to(universe_size);
|
||||
}
|
||||
|
||||
/// Clear all elements above `universe_size`.
|
||||
fn trim_to(&mut self, universe_size: usize) {
|
||||
let word_bits = mem::size_of::<Word>() * 8;
|
||||
|
||||
// `trim_block` is the first block where some bits have
|
||||
// to be cleared.
|
||||
let trim_block = universe_size / word_bits;
|
||||
|
||||
// all the blocks above it have to be completely cleared.
|
||||
if trim_block < self.bits.len() {
|
||||
for b in &mut self.bits[trim_block+1..] {
|
||||
*b = 0;
|
||||
}
|
||||
|
||||
// at that block, the `universe_size % word_bits` lsbs
|
||||
// should remain.
|
||||
let remaining_bits = universe_size % word_bits;
|
||||
let mask = (1<<remaining_bits)-1;
|
||||
self.bits[trim_block] &= mask;
|
||||
}
|
||||
}
|
||||
|
||||
/// Removes `elem` from the set `self`; returns true iff this changed `self`.
|
||||
pub fn remove(&mut self, elem: &T) -> bool {
|
||||
self.bits.clear_bit(elem.index())
|
||||
@ -252,3 +284,43 @@ impl<'a, T: Idx> Iterator for Iter<'a, T> {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_trim_to() {
|
||||
use std::cmp;
|
||||
|
||||
for i in 0..256 {
|
||||
let mut idx_buf: IdxSetBuf<usize> = IdxSetBuf::new_filled(128);
|
||||
idx_buf.trim_to(i);
|
||||
|
||||
let elems: Vec<usize> = idx_buf.iter().collect();
|
||||
let expected: Vec<usize> = (0..cmp::min(i, 128)).collect();
|
||||
assert_eq!(elems, expected);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_set_up_to() {
|
||||
for i in 0..128 {
|
||||
for mut idx_buf in
|
||||
vec![IdxSetBuf::new_empty(128), IdxSetBuf::new_filled(128)]
|
||||
.into_iter()
|
||||
{
|
||||
idx_buf.set_up_to(i);
|
||||
|
||||
let elems: Vec<usize> = idx_buf.iter().collect();
|
||||
let expected: Vec<usize> = (0..i).collect();
|
||||
assert_eq!(elems, expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_new_filled() {
|
||||
for i in 0..128 {
|
||||
let mut idx_buf = IdxSetBuf::new_filled(i);
|
||||
let elems: Vec<usize> = idx_buf.iter().collect();
|
||||
let expected: Vec<usize> = (0..i).collect();
|
||||
assert_eq!(elems, expected);
|
||||
}
|
||||
}
|
||||
|
@ -389,7 +389,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for MaybeUninitializedPlaces<'a, 'gcx, 'tcx>
|
||||
// sets on_entry bits for Arg places
|
||||
fn start_block_effect(&self, entry_set: &mut IdxSet<MovePathIndex>) {
|
||||
// set all bits to 1 (uninit) before gathering counterevidence
|
||||
for e in entry_set.words_mut() { *e = !0; }
|
||||
entry_set.set_up_to(self.bits_per_block());
|
||||
|
||||
drop_flag_effects_for_function_entry(
|
||||
self.tcx, self.mir, self.mdpe,
|
||||
@ -443,7 +443,7 @@ impl<'a, 'gcx, 'tcx> BitDenotation for DefinitelyInitializedPlaces<'a, 'gcx, 'tc
|
||||
|
||||
// sets on_entry bits for Arg places
|
||||
fn start_block_effect(&self, entry_set: &mut IdxSet<MovePathIndex>) {
|
||||
for e in entry_set.words_mut() { *e = 0; }
|
||||
entry_set.clear();
|
||||
|
||||
drop_flag_effects_for_function_entry(
|
||||
self.tcx, self.mir, self.mdpe,
|
||||
|
Loading…
x
Reference in New Issue
Block a user