Make passes assert their dependencies consistently. (#156)
* Make passes assert their dependencies consistently. This avoids ambiguity about whose responsibility it is to run to compute cfg, domtree, and loop_analysis data. * Reset the `valid` flag in DominatorTree's `clear()`. * Remove the redundant assert from DominatorTree::with_function. * Remove the message strings from obvious asserts. This avoids having them spill out into multiple lines. * Refactor calls to `compute` on `Context` objects into helper functions.
This commit is contained in:
@@ -37,6 +37,8 @@ pub struct DominatorTree {
|
||||
|
||||
// Scratch memory used by `compute_postorder()`.
|
||||
stack: Vec<Ebb>,
|
||||
|
||||
valid: bool,
|
||||
}
|
||||
|
||||
/// Methods for querying the dominator tree.
|
||||
@@ -51,6 +53,7 @@ impl DominatorTree {
|
||||
/// Note that this post-order is not updated automatically when the CFG is modified. It is
|
||||
/// computed from scratch and cached by `compute()`.
|
||||
pub fn cfg_postorder(&self) -> &[Ebb] {
|
||||
debug_assert!(self.is_valid());
|
||||
&self.postorder
|
||||
}
|
||||
|
||||
@@ -203,6 +206,7 @@ impl DominatorTree {
|
||||
nodes: EntityMap::new(),
|
||||
postorder: Vec::new(),
|
||||
stack: Vec::new(),
|
||||
valid: false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,8 +219,10 @@ impl DominatorTree {
|
||||
|
||||
/// Reset and compute a CFG post-order and dominator tree.
|
||||
pub fn compute(&mut self, func: &Function, cfg: &ControlFlowGraph) {
|
||||
debug_assert!(cfg.is_valid());
|
||||
self.compute_postorder(func, cfg);
|
||||
self.compute_domtree(func, cfg);
|
||||
self.valid = true;
|
||||
}
|
||||
|
||||
/// Clear the data structures used to represent the dominator tree. This will leave the tree in
|
||||
@@ -225,6 +231,7 @@ impl DominatorTree {
|
||||
self.nodes.clear();
|
||||
self.postorder.clear();
|
||||
assert!(self.stack.is_empty());
|
||||
self.valid = false;
|
||||
}
|
||||
|
||||
/// Check if the dominator tree is in a valid state.
|
||||
@@ -233,15 +240,7 @@ impl DominatorTree {
|
||||
/// `compute()` method has been called since the last `clear()`. It does not check that the
|
||||
/// dominator tree is consistent with the CFG.
|
||||
pub fn is_valid(&self) -> bool {
|
||||
!self.nodes.is_empty()
|
||||
}
|
||||
|
||||
/// Conveneince function to call `compute` if `compute` hasn't been called
|
||||
/// since the last `clear()`.
|
||||
pub fn ensure(&mut self, func: &Function, cfg: &ControlFlowGraph) {
|
||||
if !self.is_valid() {
|
||||
self.compute(func, cfg)
|
||||
}
|
||||
self.valid
|
||||
}
|
||||
|
||||
/// Reset all internal data structures and compute a post-order for `cfg`.
|
||||
@@ -437,6 +436,7 @@ mod test {
|
||||
fn empty() {
|
||||
let func = Function::new();
|
||||
let cfg = ControlFlowGraph::with_function(&func);
|
||||
debug_assert!(cfg.is_valid());
|
||||
let dtree = DominatorTree::with_function(&func, &cfg);
|
||||
assert_eq!(0, dtree.nodes.keys().count());
|
||||
assert_eq!(dtree.cfg_postorder(), &[]);
|
||||
|
||||
Reference in New Issue
Block a user