Make MIR basic blocks field public
This makes it possible to mutably borrow different fields of the MIR body without resorting to methods like `basic_blocks_local_decls_mut_and_var_debug_info`. To preserve validity of control flow graph caches in the presence of modifications, a new struct `BasicBlocks` wraps together basic blocks and control flow graph caches. The `BasicBlocks` dereferences to `IndexVec<BasicBlock, BasicBlockData>`. On the other hand a mutable access requires explicit `as_mut()` call.
This commit is contained in:
parent
fac8fa5672
commit
c9dd1d9983
21 changed files with 213 additions and 195 deletions
|
@ -104,22 +104,25 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
|
|||
///
|
||||
/// A Postorder traversal of this graph is `D B C A` or `D C B A`
|
||||
pub struct Postorder<'a, 'tcx> {
|
||||
body: &'a Body<'tcx>,
|
||||
basic_blocks: &'a IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
||||
visited: BitSet<BasicBlock>,
|
||||
visit_stack: Vec<(BasicBlock, Successors<'a>)>,
|
||||
root_is_start_block: bool,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Postorder<'a, 'tcx> {
|
||||
pub fn new(body: &'a Body<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> {
|
||||
pub fn new(
|
||||
basic_blocks: &'a IndexVec<BasicBlock, BasicBlockData<'tcx>>,
|
||||
root: BasicBlock,
|
||||
) -> Postorder<'a, 'tcx> {
|
||||
let mut po = Postorder {
|
||||
body,
|
||||
visited: BitSet::new_empty(body.basic_blocks().len()),
|
||||
basic_blocks,
|
||||
visited: BitSet::new_empty(basic_blocks.len()),
|
||||
visit_stack: Vec::new(),
|
||||
root_is_start_block: root == START_BLOCK,
|
||||
};
|
||||
|
||||
let data = &po.body[root];
|
||||
let data = &po.basic_blocks[root];
|
||||
|
||||
if let Some(ref term) = data.terminator {
|
||||
po.visited.insert(root);
|
||||
|
@ -190,7 +193,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
|
|||
};
|
||||
|
||||
if self.visited.insert(bb) {
|
||||
if let Some(term) = &self.body[bb].terminator {
|
||||
if let Some(term) = &self.basic_blocks[bb].terminator {
|
||||
self.visit_stack.push((bb, term.successors()));
|
||||
}
|
||||
}
|
||||
|
@ -199,7 +202,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
|
|||
}
|
||||
|
||||
pub fn postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> Postorder<'a, 'tcx> {
|
||||
Postorder::new(body, START_BLOCK)
|
||||
Postorder::new(&body.basic_blocks, START_BLOCK)
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
|
||||
|
@ -211,12 +214,12 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
|
|||
self.traverse_successor();
|
||||
}
|
||||
|
||||
next.map(|(bb, _)| (bb, &self.body[bb]))
|
||||
next.map(|(bb, _)| (bb, &self.basic_blocks[bb]))
|
||||
}
|
||||
|
||||
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||
// All the blocks, minus the number of blocks we've visited.
|
||||
let upper = self.body.basic_blocks().len() - self.visited.count();
|
||||
let upper = self.basic_blocks.len() - self.visited.count();
|
||||
|
||||
let lower = if self.root_is_start_block {
|
||||
// We will visit all remaining blocks exactly once.
|
||||
|
@ -263,10 +266,8 @@ pub struct ReversePostorder<'a, 'tcx> {
|
|||
|
||||
impl<'a, 'tcx> ReversePostorder<'a, 'tcx> {
|
||||
pub fn new(body: &'a Body<'tcx>, root: BasicBlock) -> ReversePostorder<'a, 'tcx> {
|
||||
let blocks: Vec<_> = Postorder::new(body, root).map(|(bb, _)| bb).collect();
|
||||
|
||||
let blocks: Vec<_> = Postorder::new(&body.basic_blocks, root).map(|(bb, _)| bb).collect();
|
||||
let len = blocks.len();
|
||||
|
||||
ReversePostorder { body, blocks, idx: len }
|
||||
}
|
||||
}
|
||||
|
@ -334,10 +335,8 @@ impl<'a, 'tcx> Iterator for ReversePostorderIter<'a, 'tcx> {
|
|||
impl<'a, 'tcx> ExactSizeIterator for ReversePostorderIter<'a, 'tcx> {}
|
||||
|
||||
pub fn reverse_postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> ReversePostorderIter<'a, 'tcx> {
|
||||
let blocks = body.postorder_cache.compute(body);
|
||||
|
||||
let blocks = body.basic_blocks.postorder();
|
||||
let len = blocks.len();
|
||||
|
||||
ReversePostorderIter { body, blocks, idx: len }
|
||||
}
|
||||
|
||||
|
@ -360,7 +359,7 @@ impl PostorderCache {
|
|||
|
||||
/// Returns the `&[BasicBlocks]` represents the postorder graph for this MIR.
|
||||
#[inline]
|
||||
pub(super) fn compute(&self, body: &Body<'_>) -> &[BasicBlock] {
|
||||
pub(super) fn compute(&self, body: &IndexVec<BasicBlock, BasicBlockData<'_>>) -> &[BasicBlock] {
|
||||
self.cache.get_or_init(|| Postorder::new(body, START_BLOCK).map(|(bb, _)| bb).collect())
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue