Move EntityRef and entity_impl! into a new module.

The EntityRef trait is used by more than just the EntityMap now, so it
should live in its own module.

Also move the entity_impl! macro into the new module so it can be used
for defining new entity references anywhere.
This commit is contained in:
Jakob Stoklund Olesen
2017-06-20 10:07:23 -07:00
parent 61a0844b24
commit b4e785d0f5
14 changed files with 85 additions and 100 deletions

View File

@@ -46,12 +46,11 @@
//! The index stored in an `EntityList` points to part 2, the list elements. The value 0 is //! The index stored in an `EntityList` points to part 2, the list elements. The value 0 is
//! reserved for the empty list which isn't allocated in the vector. //! reserved for the empty list which isn't allocated in the vector.
use entity_ref::EntityRef;
use std::hash::{Hash, Hasher}; use std::hash::{Hash, Hasher};
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem; use std::mem;
use entity_map::EntityRef;
/// A small list of entity references allocated from a pool. /// A small list of entity references allocated from a pool.
/// ///
/// All of the list methods that take a pool reference must be given the same pool reference every /// All of the list methods that take a pool reference must be given the same pool reference every
@@ -484,7 +483,7 @@ mod tests {
use super::*; use super::*;
use super::{sclass_size, sclass_for_length}; use super::{sclass_size, sclass_for_length};
use ir::Inst; use ir::Inst;
use entity_map::EntityRef; use entity_ref::EntityRef;
#[test] #[test]
fn size_classes() { fn size_classes() {

View File

@@ -1,8 +1,7 @@
//! Densely numbered entity references as mapping keys. //! Densely numbered entity references as mapping keys.
//! //!
//! This module defines an `EntityRef` trait that should be implemented by reference types wrapping //! The `EntityMap` data structure uses the dense index space to implement a map with a vector.
//! a small integer index. The `EntityMap` data structure uses the dense index space to implement a //! There are primary and secondary entity maps:
//! map with a vector. There are primary and secondary entity maps:
//! //!
//! - A *primary* `EntityMap` contains the main definition of an entity, and it can be used to //! - A *primary* `EntityMap` contains the main definition of an entity, and it can be used to
//! allocate new entity references with the `push` method. The values stores in a primary map //! allocate new entity references with the `push` method. The values stores in a primary map
@@ -10,22 +9,10 @@
//! - A *secondary* `EntityMap` contains additional data about entities kept in a primary map. The //! - A *secondary* `EntityMap` contains additional data about entities kept in a primary map. The
//! values need to implement `Clone + Default` traits so the map can be grown with `ensure`. //! values need to implement `Clone + Default` traits so the map can be grown with `ensure`.
use std::vec::Vec; use entity_ref::EntityRef;
use std::default::Default;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::ops::{Index, IndexMut}; use std::ops::{Index, IndexMut};
/// A type wrapping a small integer index should implement `EntityRef` so it can be used as the key
/// of an `EntityMap`.
pub trait EntityRef: Copy + Eq {
/// Create a new entity reference from a small integer.
/// This should crash if the requested index is not representable.
fn new(usize) -> Self;
/// Get the index that was used to create this entity reference.
fn index(self) -> usize;
}
/// A mapping `K -> V` for densely indexed entity references. /// A mapping `K -> V` for densely indexed entity references.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EntityMap<K, V> pub struct EntityMap<K, V>

View File

@@ -0,0 +1,51 @@
//! Densely numbered entity references as mapping keys.
//!
//! This module defines an `EntityRef` trait that should be implemented by reference types wrapping
//! a small integer index.
/// A type wrapping a small integer index should implement `EntityRef` so it can be used as the key
/// of an `EntityMap` or `SparseMap`.
pub trait EntityRef: Copy + Eq {
/// Create a new entity reference from a small integer.
/// This should crash if the requested index is not representable.
fn new(usize) -> Self;
/// Get the index that was used to create this entity reference.
fn index(self) -> usize;
}
/// Macro which provides the common implementation of a 32-bit entity reference.
#[macro_export]
macro_rules! entity_impl {
// Basic traits.
($entity:ident) => {
impl $crate::entity_ref::EntityRef for $entity {
fn new(index: usize) -> Self {
assert!(index < (::std::u32::MAX as usize));
$entity(index as u32)
}
fn index(self) -> usize {
self.0 as usize
}
}
impl $crate::packed_option::ReservedValue for $entity {
fn reserved_value() -> $entity {
$entity(::std::u32::MAX)
}
}
};
// Include basic `Display` impl using the given display prefix.
// Display an `Ebb` reference as "ebb12".
($entity:ident, $display_prefix:expr) => {
entity_impl!($entity);
impl ::std::fmt::Display for $entity {
fn fmt(&self, f: &mut ::std::fmt::Formatter) -> ::std::fmt::Result {
write!(f, "{}{}", $display_prefix, self.0)
}
}
}
}

View File

@@ -19,46 +19,9 @@
//! The entity references all implement the `Display` trait in a way that matches the textual IL //! The entity references all implement the `Display` trait in a way that matches the textual IL
//! format. //! format.
use entity_map::EntityRef; use std::fmt;
use packed_option::ReservedValue;
use std::fmt::{self, Display, Formatter};
use std::u32; use std::u32;
// Implement the common traits for a 32-bit entity reference.
macro_rules! entity_impl {
// Basic traits.
($entity:ident) => {
impl EntityRef for $entity {
fn new(index: usize) -> Self {
assert!(index < (u32::MAX as usize));
$entity(index as u32)
}
fn index(self) -> usize {
self.0 as usize
}
}
impl ReservedValue for $entity {
fn reserved_value() -> $entity {
$entity(u32::MAX)
}
}
};
// Include basic `Display` impl using the given display prefix.
// Display an `Ebb` reference as "ebb12".
($entity:ident, $display_prefix:expr) => {
entity_impl!($entity);
impl Display for $entity {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result {
write!(fmt, "{}{}", $display_prefix, self.0)
}
}
}
}
/// An opaque reference to an extended basic block in a function. /// An opaque reference to an extended basic block in a function.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
pub struct Ebb(u32); pub struct Ebb(u32);
@@ -138,17 +101,17 @@ pub enum AnyEntity {
SigRef(SigRef), SigRef(SigRef),
} }
impl Display for AnyEntity { impl fmt::Display for AnyEntity {
fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self { match *self {
AnyEntity::Function => write!(fmt, "function"), AnyEntity::Function => write!(f, "function"),
AnyEntity::Ebb(r) => r.fmt(fmt), AnyEntity::Ebb(r) => r.fmt(f),
AnyEntity::Inst(r) => r.fmt(fmt), AnyEntity::Inst(r) => r.fmt(f),
AnyEntity::Value(r) => r.fmt(fmt), AnyEntity::Value(r) => r.fmt(f),
AnyEntity::StackSlot(r) => r.fmt(fmt), AnyEntity::StackSlot(r) => r.fmt(f),
AnyEntity::JumpTable(r) => r.fmt(fmt), AnyEntity::JumpTable(r) => r.fmt(f),
AnyEntity::FuncRef(r) => r.fmt(fmt), AnyEntity::FuncRef(r) => r.fmt(f),
AnyEntity::SigRef(r) => r.fmt(fmt), AnyEntity::SigRef(r) => r.fmt(f),
} }
} }
} }

View File

@@ -122,7 +122,7 @@ impl Display for JumpTableData {
mod tests { mod tests {
use super::JumpTableData; use super::JumpTableData;
use ir::Ebb; use ir::Ebb;
use entity_map::EntityRef; use entity_ref::EntityRef;
#[test] #[test]
fn empty() { fn empty() {

View File

@@ -982,7 +982,7 @@ impl<'f> Cursor<'f> {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{Layout, Cursor, CursorPosition}; use super::{Layout, Cursor, CursorPosition};
use entity_map::EntityRef; use entity_ref::EntityRef;
use ir::{Ebb, Inst, ProgramOrder}; use ir::{Ebb, Inst, ProgramOrder};
use std::cmp::Ordering; use std::cmp::Ordering;

View File

@@ -1,6 +1,6 @@
//! Program points. //! Program points.
use entity_map::EntityRef; use entity_ref::EntityRef;
use ir::{Ebb, Inst, ValueDef}; use ir::{Ebb, Inst, ValueDef};
use std::fmt; use std::fmt;
use std::u32; use std::u32;
@@ -122,7 +122,7 @@ pub trait ProgramOrder {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use entity_map::EntityRef; use entity_ref::EntityRef;
use ir::{Inst, Ebb}; use ir::{Inst, Ebb};
#[test] #[test]

View File

@@ -1,6 +1,6 @@
//! Data structures describing the registers in an ISA. //! Data structures describing the registers in an ISA.
use entity_map::EntityRef; use entity_ref::EntityRef;
use std::fmt; use std::fmt;
/// Register units are the smallest units of register allocation. /// Register units are the smallest units of register allocation.

View File

@@ -12,6 +12,8 @@ pub const VERSION: &'static str = env!("CARGO_PKG_VERSION");
#[macro_use] #[macro_use]
pub mod dbg; pub mod dbg;
#[macro_use]
pub mod entity_ref;
pub mod binemit; pub mod binemit;
pub mod dominator_tree; pub mod dominator_tree;

View File

@@ -1,34 +1,16 @@
//! A loop analysis represented as mappings of loops to their header Ebb //! A loop analysis represented as mappings of loops to their header Ebb
//! and parent in the loop tree. //! and parent in the loop tree.
use ir::{Function, Ebb, Layout};
use flowgraph::ControlFlowGraph;
use dominator_tree::DominatorTree; use dominator_tree::DominatorTree;
use entity_map::{EntityMap, PrimaryEntityData}; use entity_map::{EntityMap, PrimaryEntityData, Keys};
use packed_option::{PackedOption, ReservedValue}; use flowgraph::ControlFlowGraph;
use entity_map::{EntityRef, Keys}; use ir::{Function, Ebb, Layout};
use std::u32; use packed_option::PackedOption;
/// A opaque reference to a code loop. /// A opaque reference to a code loop.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct Loop(u32); pub struct Loop(u32);
impl EntityRef for Loop { entity_impl!(Loop, "loop");
fn new(index: usize) -> Self {
assert!(index < (u32::MAX as usize));
Loop(index as u32)
}
fn index(self) -> usize {
self.0 as usize
}
}
impl ReservedValue for Loop {
fn reserved_value() -> Loop {
Loop(u32::MAX)
}
}
/// Loop tree information for a single function. /// Loop tree information for a single function.
/// ///

View File

@@ -89,7 +89,7 @@ impl RegDiversions {
mod tests { mod tests {
use super::*; use super::*;
use ir::Value; use ir::Value;
use entity_map::EntityRef; use entity_ref::EntityRef;
#[test] #[test]
fn inserts() { fn inserts() {

View File

@@ -394,7 +394,7 @@ impl SparseMapValue<Value> for LiveRange {
mod tests { mod tests {
use super::LiveRange; use super::LiveRange;
use ir::{Inst, Ebb, Value}; use ir::{Inst, Ebb, Value};
use entity_map::EntityRef; use entity_ref::EntityRef;
use ir::{ProgramOrder, ExpandedProgramPoint}; use ir::{ProgramOrder, ExpandedProgramPoint};
use std::cmp::Ordering; use std::cmp::Ordering;

View File

@@ -675,7 +675,7 @@ impl Solver {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use entity_map::EntityRef; use entity_ref::EntityRef;
use ir::Value; use ir::Value;
use isa::{TargetIsa, RegClass, RegUnit}; use isa::{TargetIsa, RegClass, RegUnit};
use regalloc::AllocatableSet; use regalloc::AllocatableSet;

View File

@@ -35,7 +35,8 @@
//! - `SparseMap` requires the values to implement `SparseMapValue<K>` which means that they must //! - `SparseMap` requires the values to implement `SparseMapValue<K>` which means that they must
//! contain their own key. //! contain their own key.
use entity_map::{EntityRef, EntityMap}; use entity_map::EntityMap;
use entity_ref::EntityRef;
use std::mem; use std::mem;
use std::slice; use std::slice;
use std::u32; use std::u32;
@@ -215,7 +216,7 @@ pub type SparseSet<T> = SparseMap<T, T>;
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::*; use super::*;
use entity_map::EntityRef; use entity_ref::EntityRef;
use ir::Inst; use ir::Inst;
// Mock key-value object for testing. // Mock key-value object for testing.