Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 37 additions & 14 deletions compiler/rustc_data_structures/src/graph/linked_graph/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
use std::fmt::Debug;

use rustc_index::bit_set::DenseBitSet;
use rustc_index::{Idx, IndexSlice, IndexVec};
use tracing::debug;

#[cfg(test)]
Expand All @@ -45,13 +46,13 @@ mod tests;
/// and does not implement those traits, so it has its own implementations of a
/// few basic graph algorithms.
pub struct LinkedGraph<N, E> {
nodes: Vec<Node<N>>,
nodes: IndexVec<NodeIndex, Node<N>>,
edges: Vec<Edge<E>>,
}

pub struct Node<N> {
first_edge: [EdgeIndex; 2], // see module comment
pub data: N,
pub data: Option<N>,
}

#[derive(Debug)]
Expand All @@ -62,7 +63,7 @@ pub struct Edge<E> {
pub data: E,
}

#[derive(Copy, Clone, PartialEq, Debug)]
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub struct NodeIndex(pub usize);

#[derive(Copy, Clone, PartialEq, Debug)]
Expand All @@ -87,19 +88,29 @@ impl NodeIndex {
}
}

impl Idx for NodeIndex {
fn new(idx: usize) -> NodeIndex {
NodeIndex(idx)
}

fn index(self) -> usize {
self.0
}
}

impl<N: Debug, E: Debug> LinkedGraph<N, E> {
pub fn new() -> Self {
Self { nodes: Vec::new(), edges: Vec::new() }
Self { nodes: IndexVec::new(), edges: Vec::new() }
}

pub fn with_capacity(nodes: usize, edges: usize) -> Self {
Self { nodes: Vec::with_capacity(nodes), edges: Vec::with_capacity(edges) }
Self { nodes: IndexVec::with_capacity(nodes), edges: Vec::with_capacity(edges) }
}

// # Simple accessors

#[inline]
pub fn all_nodes(&self) -> &[Node<N>] {
pub fn all_nodes(&self) -> &IndexSlice<NodeIndex, Node<N>> {
&self.nodes
}

Expand All @@ -124,22 +135,34 @@ impl<N: Debug, E: Debug> LinkedGraph<N, E> {
NodeIndex(self.nodes.len())
}

fn ensure_node(&mut self, idx: NodeIndex) -> &mut Node<N> {
self.nodes.ensure_contains_elem(idx, || Node {
first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX],
data: None,
})
}

pub fn add_node_with_idx(&mut self, idx: NodeIndex, data: N) {
let old_data = self.ensure_node(idx).data.replace(data);
debug_assert!(old_data.is_none());
}

pub fn add_node(&mut self, data: N) -> NodeIndex {
let idx = self.next_node_index();
self.nodes.push(Node { first_edge: [INVALID_EDGE_INDEX, INVALID_EDGE_INDEX], data });
self.add_node_with_idx(idx, data);
idx
}

pub fn mut_node_data(&mut self, idx: NodeIndex) -> &mut N {
&mut self.nodes[idx.0].data
self.nodes[idx].data.as_mut().unwrap()
}

pub fn node_data(&self, idx: NodeIndex) -> &N {
&self.nodes[idx.0].data
self.nodes[idx].data.as_ref().unwrap()
}

pub fn node(&self, idx: NodeIndex) -> &Node<N> {
&self.nodes[idx.0]
&self.nodes[idx]
}

// # Edge construction and queries
Expand All @@ -154,16 +177,16 @@ impl<N: Debug, E: Debug> LinkedGraph<N, E> {
let idx = self.next_edge_index();

// read current first of the list of edges from each node
let source_first = self.nodes[source.0].first_edge[OUTGOING.repr];
let target_first = self.nodes[target.0].first_edge[INCOMING.repr];
let source_first = self.ensure_node(source).first_edge[OUTGOING.repr];
let target_first = self.ensure_node(target).first_edge[INCOMING.repr];

// create the new edge, with the previous firsts from each node
// as the next pointers
self.edges.push(Edge { next_edge: [source_first, target_first], source, target, data });

// adjust the firsts for each node target be the next object.
self.nodes[source.0].first_edge[OUTGOING.repr] = idx;
self.nodes[target.0].first_edge[INCOMING.repr] = idx;
self.nodes[source].first_edge[OUTGOING.repr] = idx;
self.nodes[target].first_edge[INCOMING.repr] = idx;

idx
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ fn each_node() {
let expected = ["A", "B", "C", "D", "E", "F"];
graph.each_node(|idx, node| {
assert_eq!(&expected[idx.0], graph.node_data(idx));
assert_eq!(expected[idx.0], node.data);
assert_eq!(expected[idx.0], node.data.unwrap());
true
});
}
Expand Down
17 changes: 5 additions & 12 deletions compiler/rustc_middle/src/dep_graph/query.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::graph::linked_graph::{Direction, INCOMING, LinkedGraph, NodeIndex};
use rustc_index::IndexVec;

use super::{DepNode, DepNodeIndex};

pub struct DepGraphQuery {
pub graph: LinkedGraph<DepNode, ()>,
pub indices: FxHashMap<DepNode, NodeIndex>,
pub dep_index_to_index: IndexVec<DepNodeIndex, Option<NodeIndex>>,
}

impl DepGraphQuery {
Expand All @@ -17,27 +15,22 @@ impl DepGraphQuery {

let graph = LinkedGraph::with_capacity(node_count, edge_count);
let indices = FxHashMap::default();
let dep_index_to_index = IndexVec::new();

DepGraphQuery { graph, indices, dep_index_to_index }
DepGraphQuery { graph, indices }
}

pub fn push(&mut self, index: DepNodeIndex, node: DepNode, edges: &[DepNodeIndex]) {
let source = self.graph.add_node(node);
self.dep_index_to_index.insert(index, source);
let source = NodeIndex(index.as_usize());
self.graph.add_node_with_idx(source, node);
self.indices.insert(node, source);

for &target in edges.iter() {
// We may miss the edges that are pushed while the `DepGraphQuery` is being accessed.
// Skip them to issues.
if let Some(&Some(target)) = self.dep_index_to_index.get(target) {
self.graph.add_edge(source, target, ());
}
self.graph.add_edge(source, NodeIndex(target.as_usize()), ());
}
}

pub fn nodes(&self) -> Vec<&DepNode> {
self.graph.all_nodes().iter().map(|n| &n.data).collect()
self.graph.all_nodes().iter().map(|n| n.data.as_ref().unwrap()).collect()
}

pub fn edges(&self) -> Vec<(&DepNode, &DepNode)> {
Expand Down
Loading