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
//! 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() {

View File

@@ -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<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
//! 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),
}
}
}

View File

@@ -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() {

View File

@@ -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;

View File

@@ -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]

View File

@@ -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.

View File

@@ -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;

View File

@@ -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.
///

View File

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

View File

@@ -394,7 +394,7 @@ impl SparseMapValue<Value> 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;

View File

@@ -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;

View File

@@ -35,7 +35,8 @@
//! - `SparseMap` requires the values to implement `SparseMapValue<K>` 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<T> = SparseMap<T, T>;
#[cfg(test)]
mod tests {
use super::*;
use entity_map::EntityRef;
use entity_ref::EntityRef;
use ir::Inst;
// Mock key-value object for testing.