diff --git a/lib/cretonne/src/entity_list.rs b/lib/cretonne/src/entity_list.rs index 1ccddc3aed..4b535e3f56 100644 --- a/lib/cretonne/src/entity_list.rs +++ b/lib/cretonne/src/entity_list.rs @@ -46,12 +46,11 @@ //! 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. +use entity_ref::EntityRef; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::mem; -use entity_map::EntityRef; - /// 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 @@ -484,7 +483,7 @@ mod tests { use super::*; use super::{sclass_size, sclass_for_length}; use ir::Inst; - use entity_map::EntityRef; + use entity_ref::EntityRef; #[test] fn size_classes() { diff --git a/lib/cretonne/src/entity_map.rs b/lib/cretonne/src/entity_map.rs index 8227a19fb6..be73b790e1 100644 --- a/lib/cretonne/src/entity_map.rs +++ b/lib/cretonne/src/entity_map.rs @@ -1,8 +1,7 @@ //! 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. The `EntityMap` data structure uses the dense index space to implement a -//! map with a vector. There are primary and secondary entity maps: +//! The `EntityMap` data structure uses the dense index space to implement a 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 //! 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 //! values need to implement `Clone + Default` traits so the map can be grown with `ensure`. -use std::vec::Vec; -use std::default::Default; +use entity_ref::EntityRef; use std::marker::PhantomData; 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. #[derive(Debug, Clone)] pub struct EntityMap diff --git a/lib/cretonne/src/entity_ref.rs b/lib/cretonne/src/entity_ref.rs new file mode 100644 index 0000000000..9990b521f0 --- /dev/null +++ b/lib/cretonne/src/entity_ref.rs @@ -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) + } + } + } +} diff --git a/lib/cretonne/src/ir/entities.rs b/lib/cretonne/src/ir/entities.rs index 04b54e0488..98a29c7e61 100644 --- a/lib/cretonne/src/ir/entities.rs +++ b/lib/cretonne/src/ir/entities.rs @@ -19,46 +19,9 @@ //! The entity references all implement the `Display` trait in a way that matches the textual IL //! format. -use entity_map::EntityRef; -use packed_option::ReservedValue; -use std::fmt::{self, Display, Formatter}; +use std::fmt; 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. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)] pub struct Ebb(u32); @@ -138,17 +101,17 @@ pub enum AnyEntity { SigRef(SigRef), } -impl Display for AnyEntity { - fn fmt(&self, fmt: &mut Formatter) -> fmt::Result { +impl fmt::Display for AnyEntity { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { - AnyEntity::Function => write!(fmt, "function"), - AnyEntity::Ebb(r) => r.fmt(fmt), - AnyEntity::Inst(r) => r.fmt(fmt), - AnyEntity::Value(r) => r.fmt(fmt), - AnyEntity::StackSlot(r) => r.fmt(fmt), - AnyEntity::JumpTable(r) => r.fmt(fmt), - AnyEntity::FuncRef(r) => r.fmt(fmt), - AnyEntity::SigRef(r) => r.fmt(fmt), + AnyEntity::Function => write!(f, "function"), + AnyEntity::Ebb(r) => r.fmt(f), + AnyEntity::Inst(r) => r.fmt(f), + AnyEntity::Value(r) => r.fmt(f), + AnyEntity::StackSlot(r) => r.fmt(f), + AnyEntity::JumpTable(r) => r.fmt(f), + AnyEntity::FuncRef(r) => r.fmt(f), + AnyEntity::SigRef(r) => r.fmt(f), } } } diff --git a/lib/cretonne/src/ir/jumptable.rs b/lib/cretonne/src/ir/jumptable.rs index 24dad02056..aaaa694a50 100644 --- a/lib/cretonne/src/ir/jumptable.rs +++ b/lib/cretonne/src/ir/jumptable.rs @@ -122,7 +122,7 @@ impl Display for JumpTableData { mod tests { use super::JumpTableData; use ir::Ebb; - use entity_map::EntityRef; + use entity_ref::EntityRef; #[test] fn empty() { diff --git a/lib/cretonne/src/ir/layout.rs b/lib/cretonne/src/ir/layout.rs index 3d569adcc6..0fa48edc6f 100644 --- a/lib/cretonne/src/ir/layout.rs +++ b/lib/cretonne/src/ir/layout.rs @@ -982,7 +982,7 @@ impl<'f> Cursor<'f> { #[cfg(test)] mod tests { use super::{Layout, Cursor, CursorPosition}; - use entity_map::EntityRef; + use entity_ref::EntityRef; use ir::{Ebb, Inst, ProgramOrder}; use std::cmp::Ordering; diff --git a/lib/cretonne/src/ir/progpoint.rs b/lib/cretonne/src/ir/progpoint.rs index 3134a53603..373bc382ab 100644 --- a/lib/cretonne/src/ir/progpoint.rs +++ b/lib/cretonne/src/ir/progpoint.rs @@ -1,6 +1,6 @@ //! Program points. -use entity_map::EntityRef; +use entity_ref::EntityRef; use ir::{Ebb, Inst, ValueDef}; use std::fmt; use std::u32; @@ -122,7 +122,7 @@ pub trait ProgramOrder { #[cfg(test)] mod tests { use super::*; - use entity_map::EntityRef; + use entity_ref::EntityRef; use ir::{Inst, Ebb}; #[test] diff --git a/lib/cretonne/src/isa/registers.rs b/lib/cretonne/src/isa/registers.rs index 5549e98157..2823fbea37 100644 --- a/lib/cretonne/src/isa/registers.rs +++ b/lib/cretonne/src/isa/registers.rs @@ -1,6 +1,6 @@ //! Data structures describing the registers in an ISA. -use entity_map::EntityRef; +use entity_ref::EntityRef; use std::fmt; /// Register units are the smallest units of register allocation. diff --git a/lib/cretonne/src/lib.rs b/lib/cretonne/src/lib.rs index 6ac2f7993b..09bdfc9302 100644 --- a/lib/cretonne/src/lib.rs +++ b/lib/cretonne/src/lib.rs @@ -12,6 +12,8 @@ pub const VERSION: &'static str = env!("CARGO_PKG_VERSION"); #[macro_use] pub mod dbg; +#[macro_use] +pub mod entity_ref; pub mod binemit; pub mod dominator_tree; diff --git a/lib/cretonne/src/loop_analysis.rs b/lib/cretonne/src/loop_analysis.rs index 5ed5f8a4d8..d0a9d505bd 100644 --- a/lib/cretonne/src/loop_analysis.rs +++ b/lib/cretonne/src/loop_analysis.rs @@ -1,34 +1,16 @@ //! A loop analysis represented as mappings of loops to their header Ebb //! and parent in the loop tree. -use ir::{Function, Ebb, Layout}; -use flowgraph::ControlFlowGraph; use dominator_tree::DominatorTree; -use entity_map::{EntityMap, PrimaryEntityData}; -use packed_option::{PackedOption, ReservedValue}; -use entity_map::{EntityRef, Keys}; -use std::u32; +use entity_map::{EntityMap, PrimaryEntityData, Keys}; +use flowgraph::ControlFlowGraph; +use ir::{Function, Ebb, Layout}; +use packed_option::PackedOption; /// A opaque reference to a code loop. #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub struct Loop(u32); -impl EntityRef for 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) - } -} - +entity_impl!(Loop, "loop"); /// Loop tree information for a single function. /// diff --git a/lib/cretonne/src/regalloc/diversion.rs b/lib/cretonne/src/regalloc/diversion.rs index 89decad82f..e8e8d3d190 100644 --- a/lib/cretonne/src/regalloc/diversion.rs +++ b/lib/cretonne/src/regalloc/diversion.rs @@ -89,7 +89,7 @@ impl RegDiversions { mod tests { use super::*; use ir::Value; - use entity_map::EntityRef; + use entity_ref::EntityRef; #[test] fn inserts() { diff --git a/lib/cretonne/src/regalloc/liverange.rs b/lib/cretonne/src/regalloc/liverange.rs index 1cabd113dd..9866fabb20 100644 --- a/lib/cretonne/src/regalloc/liverange.rs +++ b/lib/cretonne/src/regalloc/liverange.rs @@ -394,7 +394,7 @@ impl SparseMapValue for LiveRange { mod tests { use super::LiveRange; use ir::{Inst, Ebb, Value}; - use entity_map::EntityRef; + use entity_ref::EntityRef; use ir::{ProgramOrder, ExpandedProgramPoint}; use std::cmp::Ordering; diff --git a/lib/cretonne/src/regalloc/solver.rs b/lib/cretonne/src/regalloc/solver.rs index d94cf3e72d..b2e73bf91f 100644 --- a/lib/cretonne/src/regalloc/solver.rs +++ b/lib/cretonne/src/regalloc/solver.rs @@ -675,7 +675,7 @@ impl Solver { #[cfg(test)] mod tests { - use entity_map::EntityRef; + use entity_ref::EntityRef; use ir::Value; use isa::{TargetIsa, RegClass, RegUnit}; use regalloc::AllocatableSet; diff --git a/lib/cretonne/src/sparse_map.rs b/lib/cretonne/src/sparse_map.rs index ad49ac49fa..b1e844b618 100644 --- a/lib/cretonne/src/sparse_map.rs +++ b/lib/cretonne/src/sparse_map.rs @@ -35,7 +35,8 @@ //! - `SparseMap` requires the values to implement `SparseMapValue` which means that they must //! contain their own key. -use entity_map::{EntityRef, EntityMap}; +use entity_map::EntityMap; +use entity_ref::EntityRef; use std::mem; use std::slice; use std::u32; @@ -215,7 +216,7 @@ pub type SparseSet = SparseMap; #[cfg(test)] mod tests { use super::*; - use entity_map::EntityRef; + use entity_ref::EntityRef; use ir::Inst; // Mock key-value object for testing.