Add PrimaryEntityData marker trait.
Require this trait on the value type stored in an EntityMap to 'unlock' the methods intended for primary entity maps that are allowed to create references with the 'push method. This prevents accidentally depending on these methods in secondary maps.
This commit is contained in:
@@ -2,7 +2,13 @@
|
|||||||
//!
|
//!
|
||||||
//! This module defines an `EntityRef` trait that should be implemented by reference types wrapping
|
//! 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
|
//! a small integer index. The `EntityMap` data structure uses the dense index space to implement a
|
||||||
//! map with a vector.
|
//! 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
|
||||||
|
//! must implement the `PrimaryEntityData` marker trait.
|
||||||
|
//! - 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::vec::Vec;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
@@ -39,13 +45,6 @@ pub trait EntityRef: Copy + Eq {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// A mapping `K -> V` for densely indexed entity references.
|
/// A mapping `K -> V` for densely indexed entity references.
|
||||||
///
|
|
||||||
/// A *primary* `EntityMap` contains the main definition of an entity, and it can be used to
|
|
||||||
/// allocate new entity references with the `push` method.
|
|
||||||
///
|
|
||||||
/// 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`.
|
|
||||||
///
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct EntityMap<K, V>
|
pub struct EntityMap<K, V>
|
||||||
where K: EntityRef
|
where K: EntityRef
|
||||||
@@ -71,17 +70,6 @@ impl<K, V> EntityMap<K, V>
|
|||||||
k.index() < self.elems.len()
|
k.index() < self.elems.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Append `v` to the mapping, assigning a new key which is returned.
|
|
||||||
pub fn push(&mut self, v: V) -> K {
|
|
||||||
let k = K::new(self.elems.len());
|
|
||||||
self.elems.push(v);
|
|
||||||
k
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn len(&self) -> usize {
|
|
||||||
self.elems.len()
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterate over all the keys in this map.
|
/// Iterate over all the keys in this map.
|
||||||
pub fn keys(&self) -> Keys<K> {
|
pub fn keys(&self) -> Keys<K> {
|
||||||
Keys {
|
Keys {
|
||||||
@@ -92,6 +80,33 @@ impl<K, V> EntityMap<K, V>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A marker trait for data stored in primary entity maps.
|
||||||
|
///
|
||||||
|
/// A primary entity map can be used to allocate new entity references with the `push` method. It
|
||||||
|
/// is important that entity references can't be created anywhere else, so the data stored in a
|
||||||
|
/// primary entity map must be tagged as `PrimaryEntityData` to unlock the `push` method.
|
||||||
|
pub trait PrimaryEntityData {}
|
||||||
|
|
||||||
|
/// Additional methods for primary entry maps only.
|
||||||
|
///
|
||||||
|
/// These are identified by the `PrimaryEntityData` marker trait.
|
||||||
|
impl<K, V> EntityMap<K, V>
|
||||||
|
where K: EntityRef,
|
||||||
|
V: PrimaryEntityData
|
||||||
|
{
|
||||||
|
/// Append `v` to the mapping, assigning a new key which is returned.
|
||||||
|
pub fn push(&mut self, v: V) -> K {
|
||||||
|
let k = K::new(self.elems.len());
|
||||||
|
self.elems.push(v);
|
||||||
|
k
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get the total number of entity references created.
|
||||||
|
pub fn len(&self) -> usize {
|
||||||
|
self.elems.len()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Additional methods for value types that implement `Clone` and `Default`.
|
/// Additional methods for value types that implement `Clone` and `Default`.
|
||||||
///
|
///
|
||||||
/// When the value type implements these additional traits, the `EntityMap` can be resized
|
/// When the value type implements these additional traits, the `EntityMap` can be resized
|
||||||
@@ -193,6 +208,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PrimaryEntityData for isize {}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn basic() {
|
fn basic() {
|
||||||
let r0 = E(0);
|
let r0 = E(0);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
//! Data flow graph tracking Instructions, Values, and EBBs.
|
//! Data flow graph tracking Instructions, Values, and EBBs.
|
||||||
|
|
||||||
use entity_map::EntityMap;
|
use entity_map::{EntityMap, PrimaryEntityData};
|
||||||
use ir::entities::{Ebb, Inst, Value, NO_VALUE, ExpandedValue};
|
use ir::entities::{Ebb, Inst, Value, NO_VALUE, ExpandedValue};
|
||||||
use ir::instructions::InstructionData;
|
use ir::instructions::InstructionData;
|
||||||
use ir::types::Type;
|
use ir::types::Type;
|
||||||
@@ -33,6 +33,9 @@ pub struct DataFlowGraph {
|
|||||||
extended_values: Vec<ValueData>,
|
extended_values: Vec<ValueData>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl PrimaryEntityData for InstructionData {}
|
||||||
|
impl PrimaryEntityData for EbbData {}
|
||||||
|
|
||||||
impl DataFlowGraph {
|
impl DataFlowGraph {
|
||||||
/// Create a new empty `DataFlowGraph`.
|
/// Create a new empty `DataFlowGraph`.
|
||||||
pub fn new() -> DataFlowGraph {
|
pub fn new() -> DataFlowGraph {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ pub mod dfg;
|
|||||||
pub mod layout;
|
pub mod layout;
|
||||||
|
|
||||||
use ir::types::{FunctionName, Signature};
|
use ir::types::{FunctionName, Signature};
|
||||||
use entity_map::{EntityRef, EntityMap};
|
use entity_map::{EntityRef, EntityMap, PrimaryEntityData};
|
||||||
use ir::entities::{StackSlot, JumpTable};
|
use ir::entities::{StackSlot, JumpTable};
|
||||||
use ir::jumptable::JumpTableData;
|
use ir::jumptable::JumpTableData;
|
||||||
use ir::dfg::DataFlowGraph;
|
use ir::dfg::DataFlowGraph;
|
||||||
@@ -39,6 +39,9 @@ pub struct Function {
|
|||||||
pub layout: Layout,
|
pub layout: Layout,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Tag JumpTableData as a primary entity so jump_tables above .
|
||||||
|
impl PrimaryEntityData for JumpTableData {}
|
||||||
|
|
||||||
impl Function {
|
impl Function {
|
||||||
/// Create a function with the given name and signature.
|
/// Create a function with the given name and signature.
|
||||||
pub fn with_name_signature(name: FunctionName, sig: Signature) -> Function {
|
pub fn with_name_signature(name: FunctionName, sig: Signature) -> Function {
|
||||||
|
|||||||
Reference in New Issue
Block a user