Add iter() and values() functions to PrimaryMap and EntityMap.
`iter()` iterates over both keys and values, while `values()` iterates over just values. Also add `_mut()` versions. These replace the otherwise common idiom of iterating with `keys()` and using indexing to get the values, allowing for simpler code.
This commit is contained in:
109
lib/cretonne/src/entity/iter.rs
Normal file
109
lib/cretonne/src/entity/iter.rs
Normal file
@@ -0,0 +1,109 @@
|
||||
//! A double-ended iterator over entity references and entities.
|
||||
|
||||
use entity::EntityRef;
|
||||
use std::marker::PhantomData;
|
||||
use std::slice;
|
||||
|
||||
/// Iterate over all keys in order.
|
||||
pub struct Iter<'a, K: EntityRef, V>
|
||||
where
|
||||
V: 'a,
|
||||
{
|
||||
pos: usize,
|
||||
iter: slice::Iter<'a, V>,
|
||||
unused: PhantomData<K>,
|
||||
}
|
||||
|
||||
impl<'a, K: EntityRef, V> Iter<'a, K, V> {
|
||||
/// Create an `Iter` iterator that visits the `PrimaryMap` keys and values
|
||||
/// of `iter`.
|
||||
pub fn new(key: K, iter: slice::Iter<'a, V>) -> Self {
|
||||
Self {
|
||||
pos: key.index(),
|
||||
iter,
|
||||
unused: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: EntityRef, V> Iterator for Iter<'a, K, V> {
|
||||
type Item = (K, &'a V);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(next) = self.iter.next() {
|
||||
let pos = self.pos;
|
||||
self.pos += 1;
|
||||
Some((K::new(pos), next))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: EntityRef, V> DoubleEndedIterator for Iter<'a, K, V> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
if let Some(next_back) = self.iter.next_back() {
|
||||
Some((K::new(self.pos), next_back))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: EntityRef, V> ExactSizeIterator for Iter<'a, K, V> {}
|
||||
|
||||
/// Iterate over all keys in order.
|
||||
pub struct IterMut<'a, K: EntityRef, V>
|
||||
where
|
||||
V: 'a,
|
||||
{
|
||||
pos: usize,
|
||||
iter: slice::IterMut<'a, V>,
|
||||
unused: PhantomData<K>,
|
||||
}
|
||||
|
||||
impl<'a, K: EntityRef, V> IterMut<'a, K, V> {
|
||||
/// Create an `IterMut` iterator that visits the `PrimaryMap` keys and values
|
||||
/// of `iter`.
|
||||
pub fn new(key: K, iter: slice::IterMut<'a, V>) -> Self {
|
||||
Self {
|
||||
pos: key.index(),
|
||||
iter,
|
||||
unused: PhantomData,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: EntityRef, V> Iterator for IterMut<'a, K, V> {
|
||||
type Item = (K, &'a mut V);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
if let Some(next) = self.iter.next() {
|
||||
let pos = self.pos;
|
||||
self.pos += 1;
|
||||
Some((K::new(pos), next))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
self.iter.size_hint()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: EntityRef, V> DoubleEndedIterator for IterMut<'a, K, V> {
|
||||
fn next_back(&mut self) -> Option<Self::Item> {
|
||||
if let Some(next_back) = self.iter.next_back() {
|
||||
Some((K::new(self.pos), next_back))
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, K: EntityRef, V> ExactSizeIterator for IterMut<'a, K, V> {}
|
||||
@@ -1,9 +1,10 @@
|
||||
//! Densely numbered entity references as mapping keys.
|
||||
|
||||
use entity::{EntityRef, Keys};
|
||||
use entity::{EntityRef, Keys, Iter, IterMut};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::vec::Vec;
|
||||
use std::slice;
|
||||
|
||||
/// A mapping `K -> V` for densely indexed entity references.
|
||||
///
|
||||
@@ -68,11 +69,31 @@ where
|
||||
self.elems.clear()
|
||||
}
|
||||
|
||||
/// Iterate over all the keys and values in this map.
|
||||
pub fn iter(&self) -> Iter<K, V> {
|
||||
Iter::new(K::new(0), self.elems.iter())
|
||||
}
|
||||
|
||||
/// Iterate over all the keys and values in this map, mutable edition.
|
||||
pub fn iter_mut(&mut self) -> IterMut<K, V> {
|
||||
IterMut::new(K::new(0), self.elems.iter_mut())
|
||||
}
|
||||
|
||||
/// Iterate over all the keys in this map.
|
||||
pub fn keys(&self) -> Keys<K> {
|
||||
Keys::new(self.elems.len())
|
||||
}
|
||||
|
||||
/// Iterate over all the keys in this map.
|
||||
pub fn values(&self) -> slice::Iter<V> {
|
||||
self.elems.iter()
|
||||
}
|
||||
|
||||
/// Iterate over all the keys in this map, mutable edition.
|
||||
pub fn values_mut(&mut self) -> slice::IterMut<V> {
|
||||
self.elems.iter_mut()
|
||||
}
|
||||
|
||||
/// Resize the map to have `n` entries by adding default entries as needed.
|
||||
pub fn resize(&mut self, n: usize) {
|
||||
self.elems.resize(n, self.default.clone());
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
//! `Vec`.
|
||||
|
||||
mod keys;
|
||||
mod iter;
|
||||
mod list;
|
||||
mod map;
|
||||
mod primary;
|
||||
@@ -37,6 +38,7 @@ mod sparse;
|
||||
mod set;
|
||||
|
||||
pub use self::keys::Keys;
|
||||
pub use self::iter::{Iter, IterMut};
|
||||
pub use self::list::{EntityList, ListPool};
|
||||
pub use self::map::EntityMap;
|
||||
pub use self::primary::PrimaryMap;
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
//! Densely numbered entity references as mapping keys.
|
||||
use entity::{EntityRef, Keys};
|
||||
use entity::{EntityRef, Keys, Iter, IterMut};
|
||||
use std::marker::PhantomData;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::vec::Vec;
|
||||
use std::slice;
|
||||
|
||||
/// A primary mapping `K -> V` allocating dense entity references.
|
||||
///
|
||||
@@ -59,6 +60,26 @@ where
|
||||
Keys::new(self.elems.len())
|
||||
}
|
||||
|
||||
/// Iterate over all the values in this map.
|
||||
pub fn values(&self) -> slice::Iter<V> {
|
||||
self.elems.iter()
|
||||
}
|
||||
|
||||
/// Iterate over all the values in this map, mutable edition.
|
||||
pub fn values_mut(&mut self) -> slice::IterMut<V> {
|
||||
self.elems.iter_mut()
|
||||
}
|
||||
|
||||
/// Iterate over all the keys and values in this map.
|
||||
pub fn iter(&self) -> Iter<K, V> {
|
||||
Iter::new(K::new(0), self.elems.iter())
|
||||
}
|
||||
|
||||
/// Iterate over all the keys and values in this map, mutable edition.
|
||||
pub fn iter_mut(&mut self) -> IterMut<K, V> {
|
||||
IterMut::new(K::new(0), self.elems.iter_mut())
|
||||
}
|
||||
|
||||
/// Remove all entries from this map.
|
||||
pub fn clear(&mut self) {
|
||||
self.elems.clear()
|
||||
@@ -133,13 +154,80 @@ mod tests {
|
||||
#[test]
|
||||
fn push() {
|
||||
let mut m = PrimaryMap::new();
|
||||
let k1: E = m.push(12);
|
||||
let k2 = m.push(33);
|
||||
let k0: E = m.push(12);
|
||||
let k1 = m.push(33);
|
||||
|
||||
assert_eq!(m[k1], 12);
|
||||
assert_eq!(m[k2], 33);
|
||||
assert_eq!(m[k0], 12);
|
||||
assert_eq!(m[k1], 33);
|
||||
|
||||
let v: Vec<E> = m.keys().collect();
|
||||
assert_eq!(v, [k1, k2]);
|
||||
assert_eq!(v, [k0, k1]);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn iter() {
|
||||
let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
|
||||
m.push(12);
|
||||
m.push(33);
|
||||
|
||||
let mut i = 0;
|
||||
for (key, value) in m.iter() {
|
||||
assert_eq!(key.index(), i);
|
||||
match i {
|
||||
0 => assert_eq!(*value, 12),
|
||||
1 => assert_eq!(*value, 33),
|
||||
_ => panic!(),
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
i = 0;
|
||||
for (key_mut, value_mut) in m.iter_mut() {
|
||||
assert_eq!(key_mut.index(), i);
|
||||
match i {
|
||||
0 => assert_eq!(*value_mut, 12),
|
||||
1 => assert_eq!(*value_mut, 33),
|
||||
_ => panic!(),
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn keys() {
|
||||
let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
|
||||
m.push(12);
|
||||
m.push(33);
|
||||
|
||||
let mut i = 0;
|
||||
for key in m.keys() {
|
||||
assert_eq!(key.index(), i);
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn values() {
|
||||
let mut m: PrimaryMap<E, usize> = PrimaryMap::new();
|
||||
m.push(12);
|
||||
m.push(33);
|
||||
|
||||
let mut i = 0;
|
||||
for value in m.values() {
|
||||
match i {
|
||||
0 => assert_eq!(*value, 12),
|
||||
1 => assert_eq!(*value, 33),
|
||||
_ => panic!(),
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
i = 0;
|
||||
for value_mut in m.values_mut() {
|
||||
match i {
|
||||
0 => assert_eq!(*value_mut, 12),
|
||||
1 => assert_eq!(*value_mut, 33),
|
||||
_ => panic!(),
|
||||
}
|
||||
i += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,11 +3,12 @@
|
||||
//! The `StackSlotData` struct keeps track of a single stack slot in a function.
|
||||
//!
|
||||
|
||||
use entity::{PrimaryMap, Keys};
|
||||
use entity::{PrimaryMap, Keys, Iter, IterMut};
|
||||
use ir::{Type, StackSlot};
|
||||
use packed_option::PackedOption;
|
||||
use std::cmp;
|
||||
use std::fmt;
|
||||
use std::slice;
|
||||
use std::ops::{Index, IndexMut};
|
||||
use std::str::FromStr;
|
||||
use std::vec::Vec;
|
||||
@@ -208,6 +209,26 @@ impl StackSlots {
|
||||
self.slots[ss].offset = Some(offset);
|
||||
}
|
||||
|
||||
/// Get an iterator over all the stack slot keys.
|
||||
pub fn iter(&self) -> Iter<StackSlot, StackSlotData> {
|
||||
self.slots.iter()
|
||||
}
|
||||
|
||||
/// Get an iterator over all the stack slot keys, mutable edition.
|
||||
pub fn iter_mut(&mut self) -> IterMut<StackSlot, StackSlotData> {
|
||||
self.slots.iter_mut()
|
||||
}
|
||||
|
||||
/// Get an iterator over all the stack slot records.
|
||||
pub fn values(&self) -> slice::Iter<StackSlotData> {
|
||||
self.slots.values()
|
||||
}
|
||||
|
||||
/// Get an iterator over all the stack slot records, mutable edition.
|
||||
pub fn values_mut(&mut self) -> slice::IterMut<StackSlotData> {
|
||||
self.slots.values_mut()
|
||||
}
|
||||
|
||||
/// Get an iterator over all the stack slot keys.
|
||||
pub fn keys(&self) -> Keys<StackSlot> {
|
||||
self.slots.keys()
|
||||
|
||||
@@ -35,9 +35,9 @@ use std::vec::Vec;
|
||||
pub fn legalize_signatures(func: &mut Function, isa: &TargetIsa) {
|
||||
isa.legalize_signature(&mut func.signature, true);
|
||||
func.signature.compute_argument_bytes();
|
||||
for sig in func.dfg.signatures.keys() {
|
||||
isa.legalize_signature(&mut func.dfg.signatures[sig], false);
|
||||
func.dfg.signatures[sig].compute_argument_bytes();
|
||||
for sig_data in func.dfg.signatures.values_mut() {
|
||||
isa.legalize_signature(sig_data, false);
|
||||
sig_data.compute_argument_bytes();
|
||||
}
|
||||
|
||||
if let Some(entry) = func.layout.entry_block() {
|
||||
|
||||
@@ -29,8 +29,8 @@ pub fn expand_as_libcall(inst: ir::Inst, func: &mut ir::Function) -> bool {
|
||||
fn find_funcref(libcall: ir::LibCall, func: &ir::Function) -> Option<ir::FuncRef> {
|
||||
// We're assuming that all libcall function decls are at the end.
|
||||
// If we get this wrong, worst case we'll have duplicate libcall decls which is harmless.
|
||||
for fref in func.dfg.ext_funcs.keys().rev() {
|
||||
match func.dfg.ext_funcs[fref].name {
|
||||
for (fref, func_data) in func.dfg.ext_funcs.iter().rev() {
|
||||
match func_data.name {
|
||||
ir::ExternalName::LibCall(lc) => {
|
||||
if lc == libcall {
|
||||
return Some(fref);
|
||||
|
||||
@@ -39,9 +39,7 @@ pub fn layout_stack(frame: &mut StackSlots, alignment: StackSize) -> Result<Stac
|
||||
let mut outgoing_max = 0;
|
||||
let mut min_align = alignment;
|
||||
|
||||
for ss in frame.keys() {
|
||||
let slot = &frame[ss];
|
||||
|
||||
for slot in frame.values() {
|
||||
if slot.size > max_size {
|
||||
return Err(CtonError::ImplLimitExceeded);
|
||||
}
|
||||
@@ -72,9 +70,7 @@ pub fn layout_stack(frame: &mut StackSlots, alignment: StackSize) -> Result<Stac
|
||||
let mut offset = incoming_min;
|
||||
debug_assert!(min_align.is_power_of_two());
|
||||
while min_align <= alignment {
|
||||
for ss in frame.keys() {
|
||||
let slot = frame[ss].clone();
|
||||
|
||||
for slot in frame.values_mut() {
|
||||
// Pick out explicit and spill slots with exact alignment `min_align`.
|
||||
match slot.kind {
|
||||
StackSlotKind::SpillSlot |
|
||||
@@ -94,7 +90,7 @@ pub fn layout_stack(frame: &mut StackSlots, alignment: StackSize) -> Result<Stac
|
||||
|
||||
// Aligning the negative offset can never cause overflow. We're only clearing bits.
|
||||
offset &= -(min_align as StackOffset);
|
||||
frame.set_offset(ss, offset);
|
||||
slot.offset = Some(offset);
|
||||
}
|
||||
|
||||
// Move on to the next higher alignment.
|
||||
|
||||
@@ -44,44 +44,38 @@ fn write_preamble(
|
||||
) -> result::Result<bool, Error> {
|
||||
let mut any = false;
|
||||
|
||||
for ss in func.stack_slots.keys() {
|
||||
for (ss, slot) in func.stack_slots.iter() {
|
||||
any = true;
|
||||
writeln!(w, " {} = {}", ss, func.stack_slots[ss])?;
|
||||
writeln!(w, " {} = {}", ss, slot)?;
|
||||
}
|
||||
|
||||
for gv in func.global_vars.keys() {
|
||||
for (gv, gv_data) in func.global_vars.iter() {
|
||||
any = true;
|
||||
writeln!(w, " {} = {}", gv, func.global_vars[gv])?;
|
||||
writeln!(w, " {} = {}", gv, gv_data)?;
|
||||
}
|
||||
|
||||
for heap in func.heaps.keys() {
|
||||
for (heap, heap_data) in func.heaps.iter() {
|
||||
any = true;
|
||||
writeln!(w, " {} = {}", heap, func.heaps[heap])?;
|
||||
writeln!(w, " {} = {}", heap, heap_data)?;
|
||||
}
|
||||
|
||||
// Write out all signatures before functions since function declarations can refer to
|
||||
// signatures.
|
||||
for sig in func.dfg.signatures.keys() {
|
||||
for (sig, sig_data) in func.dfg.signatures.iter() {
|
||||
any = true;
|
||||
writeln!(
|
||||
w,
|
||||
" {} = {}",
|
||||
sig,
|
||||
func.dfg.signatures[sig].display(regs)
|
||||
)?;
|
||||
writeln!(w, " {} = {}", sig, sig_data.display(regs))?;
|
||||
}
|
||||
|
||||
for fnref in func.dfg.ext_funcs.keys() {
|
||||
for (fnref, ext_func) in func.dfg.ext_funcs.iter() {
|
||||
any = true;
|
||||
let ext_func = &func.dfg.ext_funcs[fnref];
|
||||
if ext_func.signature != SigRef::reserved_value() {
|
||||
writeln!(w, " {} = {}", fnref, ext_func)?;
|
||||
}
|
||||
}
|
||||
|
||||
for jt in func.jump_tables.keys() {
|
||||
for (jt, jt_data) in func.jump_tables.iter() {
|
||||
any = true;
|
||||
writeln!(w, " {} = {}", jt, func.jump_tables[jt])?;
|
||||
writeln!(w, " {} = {}", jt, jt_data)?;
|
||||
}
|
||||
|
||||
Ok(any)
|
||||
|
||||
@@ -130,8 +130,8 @@ impl SubTest for TestBinEmit {
|
||||
|
||||
// Fix the stack frame layout so we can test spill/fill encodings.
|
||||
let min_offset = func.stack_slots
|
||||
.keys()
|
||||
.map(|ss| func.stack_slots[ss].offset.unwrap())
|
||||
.values()
|
||||
.map(|slot| slot.offset.unwrap())
|
||||
.min();
|
||||
func.stack_slots.frame_size = min_offset.map(|off| (-off) as u32);
|
||||
|
||||
|
||||
@@ -439,14 +439,14 @@ where
|
||||
pub fn finalize(&mut self) {
|
||||
// Check that all the `Ebb`s are filled and sealed.
|
||||
debug_assert!(
|
||||
self.func_ctx.ebbs.keys().all(|ebb| {
|
||||
self.func_ctx.ebbs[ebb].pristine || self.func_ctx.ssa.is_sealed(ebb)
|
||||
self.func_ctx.ebbs.iter().all(|(ebb, ebb_data)| {
|
||||
ebb_data.pristine || self.func_ctx.ssa.is_sealed(ebb)
|
||||
}),
|
||||
"all blocks should be sealed before dropping a FunctionBuilder"
|
||||
);
|
||||
debug_assert!(
|
||||
self.func_ctx.ebbs.keys().all(|ebb| {
|
||||
self.func_ctx.ebbs[ebb].pristine || self.func_ctx.ebbs[ebb].filled
|
||||
self.func_ctx.ebbs.values().all(|ebb_data| {
|
||||
ebb_data.pristine || ebb_data.filled
|
||||
}),
|
||||
"all blocks should be filled before dropping a FunctionBuilder"
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user