Skip to content

Commit c9dd1d9

Browse files
committedJul 7, 2022
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.
1 parent fac8fa5 commit c9dd1d9

21 files changed

+213
-195
lines changed
 

‎compiler/rustc_const_eval/src/transform/promote_consts.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -856,7 +856,8 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
856856
literal: ConstantKind::from_const(_const, tcx),
857857
}))
858858
};
859-
let (blocks, local_decls) = self.source.basic_blocks_and_local_decls_mut();
859+
let blocks = self.source.basic_blocks.as_mut();
860+
let local_decls = &mut self.source.local_decls;
860861
let loc = candidate.location;
861862
let statement = &mut blocks[loc.block].statements[loc.statement_index];
862863
match statement.kind {
@@ -865,7 +866,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> {
865866
Rvalue::Ref(ref mut region, borrow_kind, ref mut place),
866867
)) => {
867868
// Use the underlying local for this (necessarily interior) borrow.
868-
let ty = local_decls.local_decls()[place.local].ty;
869+
let ty = local_decls[place.local].ty;
869870
let span = statement.source_info.span;
870871

871872
let ref_ty = tcx.mk_ref(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
use crate::mir::graph_cyclic_cache::GraphIsCyclicCache;
2+
use crate::mir::predecessors::{PredecessorCache, Predecessors};
3+
use crate::mir::switch_sources::{SwitchSourceCache, SwitchSources};
4+
use crate::mir::traversal::PostorderCache;
5+
use crate::mir::{BasicBlock, BasicBlockData, Successors, START_BLOCK};
6+
7+
use rustc_data_structures::graph;
8+
use rustc_index::vec::IndexVec;
9+
10+
#[derive(Clone, TyEncodable, TyDecodable, Debug, HashStable, TypeFoldable, TypeVisitable)]
11+
pub struct BasicBlocks<'tcx> {
12+
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
13+
predecessor_cache: PredecessorCache,
14+
switch_source_cache: SwitchSourceCache,
15+
is_cyclic: GraphIsCyclicCache,
16+
postorder_cache: PostorderCache,
17+
}
18+
19+
impl<'tcx> BasicBlocks<'tcx> {
20+
#[inline]
21+
pub fn new(basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>) -> Self {
22+
BasicBlocks {
23+
basic_blocks,
24+
predecessor_cache: PredecessorCache::new(),
25+
switch_source_cache: SwitchSourceCache::new(),
26+
is_cyclic: GraphIsCyclicCache::new(),
27+
postorder_cache: PostorderCache::new(),
28+
}
29+
}
30+
31+
/// Returns true if control-flow graph contains a cycle reachable from the `START_BLOCK`.
32+
#[inline]
33+
pub fn is_cfg_cyclic(&self) -> bool {
34+
self.is_cyclic.is_cyclic(self)
35+
}
36+
37+
/// Returns predecessors for each basic block.
38+
#[inline]
39+
pub fn predecessors(&self) -> &Predecessors {
40+
self.predecessor_cache.compute(&self.basic_blocks)
41+
}
42+
43+
/// Returns basic blocks in a postorder.
44+
#[inline]
45+
pub fn postorder(&self) -> &[BasicBlock] {
46+
self.postorder_cache.compute(&self.basic_blocks)
47+
}
48+
49+
/// `switch_sources()[&(target, switch)]` returns a list of switch
50+
/// values that lead to a `target` block from a `switch` block.
51+
#[inline]
52+
pub fn switch_sources(&self) -> &SwitchSources {
53+
self.switch_source_cache.compute(&self.basic_blocks)
54+
}
55+
56+
/// Returns mutable reference to basic blocks. Invalidates CFG cache.
57+
#[inline]
58+
pub fn as_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
59+
self.invalidate_cfg_cache();
60+
&mut self.basic_blocks
61+
}
62+
63+
/// Get mutable access to basic blocks without invalidating the CFG cache.
64+
///
65+
/// By calling this method instead of e.g. [`BasicBlocks::as_mut`] you promise not to change
66+
/// the CFG. This means that
67+
///
68+
/// 1) The number of basic blocks remains unchanged
69+
/// 2) The set of successors of each terminator remains unchanged.
70+
/// 3) For each `TerminatorKind::SwitchInt`, the `targets` remains the same and the terminator
71+
/// kind is not changed.
72+
///
73+
/// If any of these conditions cannot be upheld, you should call [`BasicBlocks::invalidate_cfg_cache`].
74+
#[inline]
75+
pub fn as_mut_preserves_cfg(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
76+
&mut self.basic_blocks
77+
}
78+
79+
/// Invalidates cached information about the CFG.
80+
///
81+
/// You will only ever need this if you have also called [`BasicBlocks::as_mut_preserves_cfg`].
82+
/// All other methods that allow you to mutate the basic blocks also call this method
83+
/// themselves, thereby avoiding any risk of accidentaly cache invalidation.
84+
pub fn invalidate_cfg_cache(&mut self) {
85+
self.predecessor_cache.invalidate();
86+
self.switch_source_cache.invalidate();
87+
self.is_cyclic.invalidate();
88+
self.postorder_cache.invalidate();
89+
}
90+
}
91+
92+
impl<'tcx> std::ops::Deref for BasicBlocks<'tcx> {
93+
type Target = IndexVec<BasicBlock, BasicBlockData<'tcx>>;
94+
95+
#[inline]
96+
fn deref(&self) -> &IndexVec<BasicBlock, BasicBlockData<'tcx>> {
97+
&self.basic_blocks
98+
}
99+
}
100+
101+
impl<'tcx> graph::DirectedGraph for BasicBlocks<'tcx> {
102+
type Node = BasicBlock;
103+
}
104+
105+
impl<'tcx> graph::WithNumNodes for BasicBlocks<'tcx> {
106+
#[inline]
107+
fn num_nodes(&self) -> usize {
108+
self.basic_blocks.len()
109+
}
110+
}
111+
112+
impl<'tcx> graph::WithStartNode for BasicBlocks<'tcx> {
113+
#[inline]
114+
fn start_node(&self) -> Self::Node {
115+
START_BLOCK
116+
}
117+
}
118+
119+
impl<'tcx> graph::WithSuccessors for BasicBlocks<'tcx> {
120+
#[inline]
121+
fn successors(&self, node: Self::Node) -> <Self as graph::GraphSuccessors<'_>>::Iter {
122+
self.basic_blocks[node].terminator().successors()
123+
}
124+
}
125+
126+
impl<'a, 'b> graph::GraphSuccessors<'b> for BasicBlocks<'a> {
127+
type Item = BasicBlock;
128+
type Iter = Successors<'b>;
129+
}
130+
131+
impl<'tcx, 'graph> graph::GraphPredecessors<'graph> for BasicBlocks<'tcx> {
132+
type Item = BasicBlock;
133+
type Iter = std::iter::Copied<std::slice::Iter<'graph, BasicBlock>>;
134+
}
135+
136+
impl<'tcx> graph::WithPredecessors for BasicBlocks<'tcx> {
137+
#[inline]
138+
fn predecessors(&self, node: Self::Node) -> <Self as graph::GraphPredecessors<'_>>::Iter {
139+
self.predecessors()[node].iter().copied()
140+
}
141+
}

‎compiler/rustc_middle/src/mir/mod.rs

+13-138
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
use crate::mir::interpret::{
66
AllocRange, ConstAllocation, ConstValue, GlobalAlloc, LitToConstInput, Scalar,
77
};
8-
use crate::mir::traversal::PostorderCache;
98
use crate::mir::visit::MirVisitable;
109
use crate::ty::codec::{TyDecoder, TyEncoder};
1110
use crate::ty::fold::{FallibleTypeFolder, TypeFoldable, TypeSuperFoldable};
@@ -28,7 +27,6 @@ use polonius_engine::Atom;
2827
pub use rustc_ast::Mutability;
2928
use rustc_data_structures::fx::FxHashSet;
3029
use rustc_data_structures::graph::dominators::{dominators, Dominators};
31-
use rustc_data_structures::graph::{self, GraphSuccessors};
3230
use rustc_index::bit_set::BitMatrix;
3331
use rustc_index::vec::{Idx, IndexVec};
3432
use rustc_serialize::{Decodable, Encodable};
@@ -43,11 +41,12 @@ use std::fmt::{self, Debug, Display, Formatter, Write};
4341
use std::ops::{ControlFlow, Index, IndexMut};
4442
use std::{iter, mem};
4543

46-
use self::graph_cyclic_cache::GraphIsCyclicCache;
47-
use self::predecessors::{PredecessorCache, Predecessors};
44+
use self::predecessors::Predecessors;
4845
pub use self::query::*;
49-
use self::switch_sources::{SwitchSourceCache, SwitchSources};
46+
use self::switch_sources::SwitchSources;
47+
pub use basic_blocks::BasicBlocks;
5048

49+
mod basic_blocks;
5150
pub mod coverage;
5251
mod generic_graph;
5352
pub mod generic_graphviz;
@@ -189,7 +188,7 @@ pub struct GeneratorInfo<'tcx> {
189188
pub struct Body<'tcx> {
190189
/// A list of basic blocks. References to basic block use a newtyped index type [`BasicBlock`]
191190
/// that indexes into this vector.
192-
basic_blocks: IndexVec<BasicBlock, BasicBlockData<'tcx>>,
191+
pub basic_blocks: BasicBlocks<'tcx>,
193192

194193
/// Records how far through the "desugaring and optimization" process this particular
195194
/// MIR has traversed. This is particularly useful when inlining, since in that context
@@ -257,11 +256,6 @@ pub struct Body<'tcx> {
257256
/// potentially allow things like `[u8; std::mem::size_of::<T>() * 0]` due to this.
258257
pub is_polymorphic: bool,
259258

260-
predecessor_cache: PredecessorCache,
261-
switch_source_cache: SwitchSourceCache,
262-
is_cyclic: GraphIsCyclicCache,
263-
postorder_cache: PostorderCache,
264-
265259
pub tainted_by_errors: Option<ErrorGuaranteed>,
266260
}
267261

@@ -289,7 +283,7 @@ impl<'tcx> Body<'tcx> {
289283
let mut body = Body {
290284
phase: MirPhase::Built,
291285
source,
292-
basic_blocks,
286+
basic_blocks: BasicBlocks::new(basic_blocks),
293287
source_scopes,
294288
generator: generator_kind.map(|generator_kind| {
295289
Box::new(GeneratorInfo {
@@ -307,10 +301,6 @@ impl<'tcx> Body<'tcx> {
307301
span,
308302
required_consts: Vec::new(),
309303
is_polymorphic: false,
310-
predecessor_cache: PredecessorCache::new(),
311-
switch_source_cache: SwitchSourceCache::new(),
312-
is_cyclic: GraphIsCyclicCache::new(),
313-
postorder_cache: PostorderCache::new(),
314304
tainted_by_errors,
315305
};
316306
body.is_polymorphic = body.has_param_types_or_consts();
@@ -326,7 +316,7 @@ impl<'tcx> Body<'tcx> {
326316
let mut body = Body {
327317
phase: MirPhase::Built,
328318
source: MirSource::item(CRATE_DEF_ID.to_def_id()),
329-
basic_blocks,
319+
basic_blocks: BasicBlocks::new(basic_blocks),
330320
source_scopes: IndexVec::new(),
331321
generator: None,
332322
local_decls: IndexVec::new(),
@@ -337,10 +327,6 @@ impl<'tcx> Body<'tcx> {
337327
required_consts: Vec::new(),
338328
var_debug_info: Vec::new(),
339329
is_polymorphic: false,
340-
predecessor_cache: PredecessorCache::new(),
341-
switch_source_cache: SwitchSourceCache::new(),
342-
is_cyclic: GraphIsCyclicCache::new(),
343-
postorder_cache: PostorderCache::new(),
344330
tainted_by_errors: None,
345331
};
346332
body.is_polymorphic = body.has_param_types_or_consts();
@@ -354,74 +340,13 @@ impl<'tcx> Body<'tcx> {
354340

355341
#[inline]
356342
pub fn basic_blocks_mut(&mut self) -> &mut IndexVec<BasicBlock, BasicBlockData<'tcx>> {
357-
// Because the user could mutate basic block terminators via this reference, we need to
358-
// invalidate the caches.
359-
//
360-
// FIXME: Use a finer-grained API for this, so only transformations that alter terminators
361-
// invalidate the caches.
362-
self.invalidate_cfg_cache();
363-
&mut self.basic_blocks
364-
}
365-
366-
#[inline]
367-
pub fn basic_blocks_and_local_decls_mut(
368-
&mut self,
369-
) -> (&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>, &mut LocalDecls<'tcx>) {
370-
self.invalidate_cfg_cache();
371-
(&mut self.basic_blocks, &mut self.local_decls)
372-
}
373-
374-
#[inline]
375-
pub fn basic_blocks_local_decls_mut_and_var_debug_info(
376-
&mut self,
377-
) -> (
378-
&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
379-
&mut LocalDecls<'tcx>,
380-
&mut Vec<VarDebugInfo<'tcx>>,
381-
) {
382-
self.invalidate_cfg_cache();
383-
(&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info)
384-
}
385-
386-
/// Get mutable access to parts of the Body without invalidating the CFG cache.
387-
///
388-
/// By calling this method instead of eg [`Body::basic_blocks_mut`], you promise not to change
389-
/// the CFG. This means that
390-
///
391-
/// 1) The number of basic blocks remains unchanged
392-
/// 2) The set of successors of each terminator remains unchanged.
393-
/// 3) For each `TerminatorKind::SwitchInt`, the `targets` remains the same and the terminator
394-
/// kind is not changed.
395-
///
396-
/// If any of these conditions cannot be upheld, you should call [`Body::invalidate_cfg_cache`].
397-
#[inline]
398-
pub fn basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate(
399-
&mut self,
400-
) -> (
401-
&mut IndexVec<BasicBlock, BasicBlockData<'tcx>>,
402-
&mut LocalDecls<'tcx>,
403-
&mut Vec<VarDebugInfo<'tcx>>,
404-
) {
405-
(&mut self.basic_blocks, &mut self.local_decls, &mut self.var_debug_info)
406-
}
407-
408-
/// Invalidates cached information about the CFG.
409-
///
410-
/// You will only ever need this if you have also called
411-
/// [`Body::basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate`]. All other methods
412-
/// that allow you to mutate the body also call this method themselves, thereby avoiding any
413-
/// risk of accidentaly cache invalidation.
414-
pub fn invalidate_cfg_cache(&mut self) {
415-
self.predecessor_cache.invalidate();
416-
self.switch_source_cache.invalidate();
417-
self.is_cyclic.invalidate();
418-
self.postorder_cache.invalidate();
343+
self.basic_blocks.as_mut()
419344
}
420345

421346
/// Returns `true` if a cycle exists in the control-flow graph that is reachable from the
422347
/// `START_BLOCK`.
423348
pub fn is_cfg_cyclic(&self) -> bool {
424-
self.is_cyclic.is_cyclic(self)
349+
self.basic_blocks.is_cfg_cyclic()
425350
}
426351

427352
#[inline]
@@ -495,14 +420,6 @@ impl<'tcx> Body<'tcx> {
495420
self.local_decls.drain(self.arg_count + 1..)
496421
}
497422

498-
/// Changes a statement to a nop. This is both faster than deleting instructions and avoids
499-
/// invalidating statement indices in `Location`s.
500-
pub fn make_statement_nop(&mut self, location: Location) {
501-
let block = &mut self.basic_blocks[location.block];
502-
debug_assert!(location.statement_index < block.statements.len());
503-
block.statements[location.statement_index].make_nop()
504-
}
505-
506423
/// Returns the source info associated with `location`.
507424
pub fn source_info(&self, location: Location) -> &SourceInfo {
508425
let block = &self[location.block];
@@ -540,19 +457,19 @@ impl<'tcx> Body<'tcx> {
540457

541458
#[inline]
542459
pub fn predecessors(&self) -> &Predecessors {
543-
self.predecessor_cache.compute(&self.basic_blocks)
460+
self.basic_blocks.predecessors()
544461
}
545462

546463
/// `body.switch_sources()[&(target, switch)]` returns a list of switch
547464
/// values that lead to a `target` block from a `switch` block.
548465
#[inline]
549466
pub fn switch_sources(&self) -> &SwitchSources {
550-
self.switch_source_cache.compute(&self.basic_blocks)
467+
self.basic_blocks.switch_sources()
551468
}
552469

553470
#[inline]
554471
pub fn dominators(&self) -> Dominators<BasicBlock> {
555-
dominators(self)
472+
dominators(&self.basic_blocks)
556473
}
557474

558475
#[inline]
@@ -599,7 +516,7 @@ impl<'tcx> Index<BasicBlock> for Body<'tcx> {
599516
impl<'tcx> IndexMut<BasicBlock> for Body<'tcx> {
600517
#[inline]
601518
fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
602-
&mut self.basic_blocks_mut()[index]
519+
&mut self.basic_blocks.as_mut()[index]
603520
}
604521
}
605522

@@ -2890,48 +2807,6 @@ fn pretty_print_const_value<'tcx>(
28902807
})
28912808
}
28922809

2893-
impl<'tcx> graph::DirectedGraph for Body<'tcx> {
2894-
type Node = BasicBlock;
2895-
}
2896-
2897-
impl<'tcx> graph::WithNumNodes for Body<'tcx> {
2898-
#[inline]
2899-
fn num_nodes(&self) -> usize {
2900-
self.basic_blocks.len()
2901-
}
2902-
}
2903-
2904-
impl<'tcx> graph::WithStartNode for Body<'tcx> {
2905-
#[inline]
2906-
fn start_node(&self) -> Self::Node {
2907-
START_BLOCK
2908-
}
2909-
}
2910-
2911-
impl<'tcx> graph::WithSuccessors for Body<'tcx> {
2912-
#[inline]
2913-
fn successors(&self, node: Self::Node) -> <Self as GraphSuccessors<'_>>::Iter {
2914-
self.basic_blocks[node].terminator().successors()
2915-
}
2916-
}
2917-
2918-
impl<'a, 'b> graph::GraphSuccessors<'b> for Body<'a> {
2919-
type Item = BasicBlock;
2920-
type Iter = Successors<'b>;
2921-
}
2922-
2923-
impl<'tcx, 'graph> graph::GraphPredecessors<'graph> for Body<'tcx> {
2924-
type Item = BasicBlock;
2925-
type Iter = std::iter::Copied<std::slice::Iter<'graph, BasicBlock>>;
2926-
}
2927-
2928-
impl<'tcx> graph::WithPredecessors for Body<'tcx> {
2929-
#[inline]
2930-
fn predecessors(&self, node: Self::Node) -> <Self as graph::GraphPredecessors<'_>>::Iter {
2931-
self.predecessors()[node].iter().copied()
2932-
}
2933-
}
2934-
29352810
/// `Location` represents the position of the start of the statement; or, if
29362811
/// `statement_index` equals the number of statements, then the start of the
29372812
/// terminator.

‎compiler/rustc_middle/src/mir/traversal.rs

+15-16
Original file line numberDiff line numberDiff line change
@@ -104,22 +104,25 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
104104
///
105105
/// A Postorder traversal of this graph is `D B C A` or `D C B A`
106106
pub struct Postorder<'a, 'tcx> {
107-
body: &'a Body<'tcx>,
107+
basic_blocks: &'a IndexVec<BasicBlock, BasicBlockData<'tcx>>,
108108
visited: BitSet<BasicBlock>,
109109
visit_stack: Vec<(BasicBlock, Successors<'a>)>,
110110
root_is_start_block: bool,
111111
}
112112

113113
impl<'a, 'tcx> Postorder<'a, 'tcx> {
114-
pub fn new(body: &'a Body<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> {
114+
pub fn new(
115+
basic_blocks: &'a IndexVec<BasicBlock, BasicBlockData<'tcx>>,
116+
root: BasicBlock,
117+
) -> Postorder<'a, 'tcx> {
115118
let mut po = Postorder {
116-
body,
117-
visited: BitSet::new_empty(body.basic_blocks().len()),
119+
basic_blocks,
120+
visited: BitSet::new_empty(basic_blocks.len()),
118121
visit_stack: Vec::new(),
119122
root_is_start_block: root == START_BLOCK,
120123
};
121124

122-
let data = &po.body[root];
125+
let data = &po.basic_blocks[root];
123126

124127
if let Some(ref term) = data.terminator {
125128
po.visited.insert(root);
@@ -190,7 +193,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
190193
};
191194

192195
if self.visited.insert(bb) {
193-
if let Some(term) = &self.body[bb].terminator {
196+
if let Some(term) = &self.basic_blocks[bb].terminator {
194197
self.visit_stack.push((bb, term.successors()));
195198
}
196199
}
@@ -199,7 +202,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
199202
}
200203

201204
pub fn postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> Postorder<'a, 'tcx> {
202-
Postorder::new(body, START_BLOCK)
205+
Postorder::new(&body.basic_blocks, START_BLOCK)
203206
}
204207

205208
impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
@@ -211,12 +214,12 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
211214
self.traverse_successor();
212215
}
213216

214-
next.map(|(bb, _)| (bb, &self.body[bb]))
217+
next.map(|(bb, _)| (bb, &self.basic_blocks[bb]))
215218
}
216219

217220
fn size_hint(&self) -> (usize, Option<usize>) {
218221
// All the blocks, minus the number of blocks we've visited.
219-
let upper = self.body.basic_blocks().len() - self.visited.count();
222+
let upper = self.basic_blocks.len() - self.visited.count();
220223

221224
let lower = if self.root_is_start_block {
222225
// We will visit all remaining blocks exactly once.
@@ -263,10 +266,8 @@ pub struct ReversePostorder<'a, 'tcx> {
263266

264267
impl<'a, 'tcx> ReversePostorder<'a, 'tcx> {
265268
pub fn new(body: &'a Body<'tcx>, root: BasicBlock) -> ReversePostorder<'a, 'tcx> {
266-
let blocks: Vec<_> = Postorder::new(body, root).map(|(bb, _)| bb).collect();
267-
269+
let blocks: Vec<_> = Postorder::new(&body.basic_blocks, root).map(|(bb, _)| bb).collect();
268270
let len = blocks.len();
269-
270271
ReversePostorder { body, blocks, idx: len }
271272
}
272273
}
@@ -334,10 +335,8 @@ impl<'a, 'tcx> Iterator for ReversePostorderIter<'a, 'tcx> {
334335
impl<'a, 'tcx> ExactSizeIterator for ReversePostorderIter<'a, 'tcx> {}
335336

336337
pub fn reverse_postorder<'a, 'tcx>(body: &'a Body<'tcx>) -> ReversePostorderIter<'a, 'tcx> {
337-
let blocks = body.postorder_cache.compute(body);
338-
338+
let blocks = body.basic_blocks.postorder();
339339
let len = blocks.len();
340-
341340
ReversePostorderIter { body, blocks, idx: len }
342341
}
343342

@@ -360,7 +359,7 @@ impl PostorderCache {
360359

361360
/// Returns the `&[BasicBlocks]` represents the postorder graph for this MIR.
362361
#[inline]
363-
pub(super) fn compute(&self, body: &Body<'_>) -> &[BasicBlock] {
362+
pub(super) fn compute(&self, body: &IndexVec<BasicBlock, BasicBlockData<'_>>) -> &[BasicBlock] {
364363
self.cache.get_or_init(|| Postorder::new(body, START_BLOCK).map(|(bb, _)| bb).collect())
365364
}
366365
}

‎compiler/rustc_mir_build/src/lints.rs

+5-3
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ use rustc_data_structures::graph::iterate::{
22
NodeStatus, TriColorDepthFirstSearch, TriColorVisitor,
33
};
44
use rustc_hir::intravisit::FnKind;
5-
use rustc_middle::mir::{BasicBlock, Body, Operand, TerminatorKind};
5+
use rustc_middle::mir::{BasicBlock, BasicBlocks, Body, Operand, TerminatorKind};
66
use rustc_middle::ty::subst::{GenericArg, InternalSubsts};
77
use rustc_middle::ty::{self, AssocItem, AssocItemContainer, Instance, TyCtxt};
88
use rustc_session::lint::builtin::UNCONDITIONAL_RECURSION;
@@ -30,7 +30,9 @@ pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) {
3030
};
3131

3232
let mut vis = Search { tcx, body, reachable_recursive_calls: vec![], trait_substs };
33-
if let Some(NonRecursive) = TriColorDepthFirstSearch::new(&body).run_from_start(&mut vis) {
33+
if let Some(NonRecursive) =
34+
TriColorDepthFirstSearch::new(&body.basic_blocks).run_from_start(&mut vis)
35+
{
3436
return;
3537
}
3638
if vis.reachable_recursive_calls.is_empty() {
@@ -101,7 +103,7 @@ impl<'mir, 'tcx> Search<'mir, 'tcx> {
101103
}
102104
}
103105

104-
impl<'mir, 'tcx> TriColorVisitor<&'mir Body<'tcx>> for Search<'mir, 'tcx> {
106+
impl<'mir, 'tcx> TriColorVisitor<BasicBlocks<'tcx>> for Search<'mir, 'tcx> {
105107
type BreakVal = NonRecursive;
106108

107109
fn node_examined(

‎compiler/rustc_mir_transform/src/add_retag.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,8 @@ impl<'tcx> MirPass<'tcx> for AddRetag {
9191
super::add_call_guards::AllCallEdges.run_pass(tcx, body);
9292

9393
let (span, arg_count) = (body.span, body.arg_count);
94-
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
94+
let basic_blocks = body.basic_blocks.as_mut();
95+
let local_decls = &body.local_decls;
9596
let needs_retag = |place: &Place<'tcx>| {
9697
// FIXME: Instead of giving up for unstable places, we should introduce
9798
// a temporary and retag on that.

‎compiler/rustc_mir_transform/src/coverage/graph.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ impl CoverageGraph {
8080
IndexVec<BasicCoverageBlock, BasicCoverageBlockData>,
8181
IndexVec<BasicBlock, Option<BasicCoverageBlock>>,
8282
) {
83-
let num_basic_blocks = mir_body.num_nodes();
83+
let num_basic_blocks = mir_body.basic_blocks.len();
8484
let mut bcbs = IndexVec::with_capacity(num_basic_blocks);
8585
let mut bb_to_bcb = IndexVec::from_elem_n(None, num_basic_blocks);
8686

‎compiler/rustc_mir_transform/src/coverage/spans.rs

+2-1
Original file line numberDiff line numberDiff line change
@@ -321,7 +321,8 @@ impl<'a, 'tcx> CoverageSpans<'a, 'tcx> {
321321
}
322322

323323
fn mir_to_initial_sorted_coverage_spans(&self) -> Vec<CoverageSpan> {
324-
let mut initial_spans = Vec::<CoverageSpan>::with_capacity(self.mir_body.num_nodes() * 2);
324+
let mut initial_spans =
325+
Vec::<CoverageSpan>::with_capacity(self.mir_body.basic_blocks.len() * 2);
325326
for (bcb, bcb_data) in self.basic_coverage_blocks.iter_enumerated() {
326327
initial_spans.extend(self.bcb_to_initial_coverage_spans(bcb, bcb_data));
327328
}

‎compiler/rustc_mir_transform/src/coverage/tests.rs

+1
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,7 @@ fn print_mir_graphviz(name: &str, mir_body: &Body<'_>) {
222222
bb,
223223
debug::term_type(&data.terminator().kind),
224224
mir_body
225+
.basic_blocks
225226
.successors(bb)
226227
.map(|successor| { format!(" {:?} -> {:?};", bb, successor) })
227228
.join("\n")

‎compiler/rustc_mir_transform/src/dead_store_elimination.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ pub fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>, borrowed: &BitS
6666
return;
6767
}
6868

69-
let bbs = body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate().0;
69+
let bbs = body.basic_blocks.as_mut_preserves_cfg();
7070
for Location { block, statement_index } in patch {
7171
bbs[block].statements[statement_index].make_nop();
7272
}

‎compiler/rustc_mir_transform/src/deaggregator.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,7 @@ impl<'tcx> MirPass<'tcx> for Deaggregator {
1111
}
1212

1313
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
14-
let (basic_blocks, local_decls, _) =
15-
body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate();
16-
let local_decls = &*local_decls;
14+
let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
1715
for bb in basic_blocks {
1816
bb.expand_statements(|stmt| {
1917
// FIXME(eddyb) don't match twice on `stmt.kind` (post-NLL).
@@ -38,7 +36,7 @@ impl<'tcx> MirPass<'tcx> for Deaggregator {
3836
Some(expand_aggregate(
3937
lhs,
4038
operands.into_iter().map(|op| {
41-
let ty = op.ty(local_decls, tcx);
39+
let ty = op.ty(&body.local_decls, tcx);
4240
(op, ty)
4341
}),
4442
*kind,

‎compiler/rustc_mir_transform/src/elaborate_box_derefs.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,13 @@ impl<'tcx> MirPass<'tcx> for ElaborateBoxDerefs {
110110

111111
let patch = MirPatch::new(body);
112112

113-
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
113+
let local_decls = &mut body.local_decls;
114114

115115
let mut visitor =
116116
ElaborateBoxDerefVisitor { tcx, unique_did, nonnull_did, local_decls, patch };
117117

118118
for (block, BasicBlockData { statements, terminator, .. }) in
119-
basic_blocks.iter_enumerated_mut()
119+
body.basic_blocks.as_mut().iter_enumerated_mut()
120120
{
121121
let mut index = 0;
122122
for statement in statements {

‎compiler/rustc_mir_transform/src/instcombine.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,8 @@ impl<'tcx> MirPass<'tcx> for InstCombine {
1616
}
1717

1818
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
19-
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
20-
let ctx = InstCombineContext { tcx, local_decls };
21-
for block in basic_blocks.iter_mut() {
19+
let ctx = InstCombineContext { tcx, local_decls: &body.local_decls };
20+
for block in body.basic_blocks.as_mut() {
2221
for statement in block.statements.iter_mut() {
2322
match statement.kind {
2423
StatementKind::Assign(box (_place, ref mut rvalue)) => {

‎compiler/rustc_mir_transform/src/lower_intrinsics.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ pub struct LowerIntrinsics;
1111

1212
impl<'tcx> MirPass<'tcx> for LowerIntrinsics {
1313
fn run_pass(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
14-
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
15-
for block in basic_blocks {
14+
let local_decls = &body.local_decls;
15+
for block in body.basic_blocks.as_mut() {
1616
let terminator = block.terminator.as_mut().unwrap();
1717
if let TerminatorKind::Call { func, args, destination, target, .. } =
1818
&mut terminator.kind

‎compiler/rustc_mir_transform/src/lower_slice_len.rs

+2-4
Original file line numberDiff line numberDiff line change
@@ -27,12 +27,10 @@ pub fn lower_slice_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
2727
};
2828

2929
// The one successor remains unchanged, so no need to invalidate
30-
let (basic_blocks, local_decls, _) =
31-
body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate();
32-
30+
let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
3331
for block in basic_blocks {
3432
// lower `<[_]>::len` calls
35-
lower_slice_len_call(tcx, block, &*local_decls, slice_len_fn_item_def_id);
33+
lower_slice_len_call(tcx, block, &body.local_decls, slice_len_fn_item_def_id);
3634
}
3735
}
3836

‎compiler/rustc_mir_transform/src/match_branches.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
4848
let def_id = body.source.def_id();
4949
let param_env = tcx.param_env(def_id);
5050

51-
let (bbs, local_decls) = body.basic_blocks_and_local_decls_mut();
51+
let bbs = body.basic_blocks.as_mut();
5252
let mut should_cleanup = false;
5353
'outer: for bb_idx in bbs.indices() {
5454
if !tcx.consider_optimizing(|| format!("MatchBranchSimplification {:?} ", def_id)) {
@@ -108,7 +108,7 @@ impl<'tcx> MirPass<'tcx> for MatchBranchSimplification {
108108

109109
// Introduce a temporary for the discriminant value.
110110
let source_info = bbs[bb_idx].terminator().source_info;
111-
let discr_local = local_decls.push(LocalDecl::new(switch_ty, source_info.span));
111+
let discr_local = body.local_decls.push(LocalDecl::new(switch_ty, source_info.span));
112112

113113
// We already checked that first and second are different blocks,
114114
// and bb_idx has a different terminator from both of them.

‎compiler/rustc_mir_transform/src/normalize_array_len.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ impl<'tcx> MirPass<'tcx> for NormalizeArrayLen {
3333

3434
pub fn normalize_array_len_calls<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
3535
// We don't ever touch terminators, so no need to invalidate the CFG cache
36-
let (basic_blocks, local_decls, _) =
37-
body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate();
36+
let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
37+
let local_decls = &mut body.local_decls;
3838

3939
// do a preliminary analysis to see if we ever have locals of type `[T;N]` or `&[T;N]`
4040
let mut interesting_locals = BitSet::new_empty(local_decls.len());

‎compiler/rustc_mir_transform/src/remove_storage_markers.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ impl<'tcx> MirPass<'tcx> for RemoveStorageMarkers {
1717
}
1818

1919
trace!("Running RemoveStorageMarkers on {:?}", body.source);
20-
for data in body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate().0 {
20+
for data in body.basic_blocks.as_mut_preserves_cfg() {
2121
data.statements.retain(|statement| match statement.kind {
2222
StatementKind::StorageLive(..)
2323
| StatementKind::StorageDead(..)

‎compiler/rustc_mir_transform/src/remove_unneeded_drops.rs

+2-3
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,10 @@ impl<'tcx> MirPass<'tcx> for RemoveUnneededDrops {
2020
let param_env = tcx.param_env_reveal_all_normalized(did);
2121
let mut should_simplify = false;
2222

23-
let (basic_blocks, local_decls) = body.basic_blocks_and_local_decls_mut();
24-
for block in basic_blocks {
23+
for block in body.basic_blocks.as_mut() {
2524
let terminator = block.terminator_mut();
2625
if let TerminatorKind::Drop { place, target, .. } = terminator.kind {
27-
let ty = place.ty(local_decls, tcx);
26+
let ty = place.ty(&body.local_decls, tcx);
2827
if ty.ty.needs_drop(tcx, param_env) {
2928
continue;
3029
}

‎compiler/rustc_mir_transform/src/remove_zsts.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@ impl<'tcx> MirPass<'tcx> for RemoveZsts {
1818
return;
1919
}
2020
let param_env = tcx.param_env(body.source.def_id());
21-
let (basic_blocks, local_decls, _) =
22-
body.basic_blocks_local_decls_mut_and_var_debug_info_no_invalidate();
23-
for block in basic_blocks.iter_mut() {
21+
let basic_blocks = body.basic_blocks.as_mut_preserves_cfg();
22+
let local_decls = &body.local_decls;
23+
for block in basic_blocks {
2424
for statement in block.statements.iter_mut() {
2525
if let StatementKind::Assign(box (place, _)) | StatementKind::Deinit(box place) =
2626
statement.kind

‎compiler/rustc_mir_transform/src/simplify_try.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -386,14 +386,17 @@ impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
386386
trace!("running SimplifyArmIdentity on {:?}", source);
387387

388388
let local_uses = LocalUseCounter::get_local_uses(body);
389-
let (basic_blocks, local_decls, debug_info) =
390-
body.basic_blocks_local_decls_mut_and_var_debug_info();
391-
for bb in basic_blocks {
389+
for bb in body.basic_blocks.as_mut() {
392390
if let Some(opt_info) =
393-
get_arm_identity_info(&bb.statements, local_decls.len(), debug_info)
391+
get_arm_identity_info(&bb.statements, body.local_decls.len(), &body.var_debug_info)
394392
{
395393
trace!("got opt_info = {:#?}", opt_info);
396-
if !optimization_applies(&opt_info, local_decls, &local_uses, &debug_info) {
394+
if !optimization_applies(
395+
&opt_info,
396+
&body.local_decls,
397+
&local_uses,
398+
&body.var_debug_info,
399+
) {
397400
debug!("optimization skipped for {:?}", source);
398401
continue;
399402
}
@@ -431,7 +434,7 @@ impl<'tcx> MirPass<'tcx> for SimplifyArmIdentity {
431434

432435
// Fix the debug info to point to the right local
433436
for dbg_index in opt_info.dbg_info_to_adjust {
434-
let dbg_info = &mut debug_info[dbg_index];
437+
let dbg_info = &mut body.var_debug_info[dbg_index];
435438
assert!(
436439
matches!(dbg_info.value, VarDebugInfoContents::Place(_)),
437440
"value was not a Place"

0 commit comments

Comments
 (0)
Please sign in to comment.