Skip to content

Commit bb183e2

Browse files
nagisagereeter
authored andcommitted
Distinct CFG type for MIR, traversals to librustc
1 parent 763f923 commit bb183e2

File tree

21 files changed

+224
-130
lines changed

21 files changed

+224
-130
lines changed

src/librustc/lib.rs

+3
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#![cfg_attr(not(stage0), deny(warnings))]
2525

2626
#![feature(associated_consts)]
27+
#![feature(inclusive_range_syntax)]
2728
#![feature(box_patterns)]
2829
#![feature(box_syntax)]
2930
#![feature(collections)]
@@ -107,6 +108,8 @@ pub mod mir {
107108
pub mod visit;
108109
pub mod transform;
109110
pub mod mir_map;
111+
pub mod cfg;
112+
pub mod traversal;
110113
}
111114

112115
pub mod session;

src/librustc/mir/cfg.rs

+146
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
use mir::repr::*;
2+
3+
use std::ops::{Index, IndexMut};
4+
use syntax::codemap::Span;
5+
6+
#[derive(Clone, RustcEncodable, RustcDecodable)]
7+
pub struct CFG<'tcx> {
8+
pub basic_blocks: Vec<BasicBlockData<'tcx>>,
9+
}
10+
11+
pub struct PredecessorIter(::std::vec::IntoIter<BasicBlock>);
12+
impl Iterator for PredecessorIter {
13+
type Item = BasicBlock;
14+
fn next(&mut self) -> Option<BasicBlock> {
15+
self.0.next()
16+
}
17+
}
18+
19+
pub struct SuccessorIter(::std::vec::IntoIter<BasicBlock>);
20+
impl<'a> Iterator for SuccessorIter {
21+
type Item = BasicBlock;
22+
fn next(&mut self) -> Option<BasicBlock> {
23+
self.0.next()
24+
}
25+
}
26+
27+
pub struct SuccessorIterMut<'a>(::std::vec::IntoIter<&'a mut BasicBlock>);
28+
impl<'a> Iterator for SuccessorIterMut<'a> {
29+
type Item = &'a mut BasicBlock;
30+
fn next(&mut self) -> Option<&'a mut BasicBlock> {
31+
self.0.next()
32+
}
33+
}
34+
35+
impl<'tcx> CFG<'tcx> {
36+
pub fn len(&self) -> usize {
37+
self.basic_blocks.len()
38+
}
39+
40+
pub fn predecessors(&self, b: BasicBlock) -> PredecessorIter {
41+
let mut preds = vec![];
42+
for idx in 0..self.len() {
43+
let bb = BasicBlock::new(idx);
44+
if let Some(_) = self.successors(bb).find(|&x| x == b) {
45+
preds.push(bb)
46+
}
47+
}
48+
PredecessorIter(preds.into_iter())
49+
}
50+
51+
pub fn successors(&self, b: BasicBlock) -> SuccessorIter {
52+
let v: Vec<BasicBlock> = self[b].terminator().kind.successors().into_owned();
53+
SuccessorIter(v.into_iter())
54+
}
55+
56+
pub fn successors_mut(&mut self, b: BasicBlock) -> SuccessorIterMut {
57+
SuccessorIterMut(self[b].terminator_mut().kind.successors_mut().into_iter())
58+
}
59+
60+
61+
pub fn swap(&mut self, b1: BasicBlock, b2: BasicBlock) {
62+
// TODO: find all the branches to b2 from subgraph starting at b2 and replace them with b1.
63+
self.basic_blocks.swap(b1.index(), b2.index());
64+
}
65+
66+
pub fn start_new_block(&mut self) -> BasicBlock {
67+
let node_index = self.basic_blocks.len();
68+
self.basic_blocks.push(BasicBlockData::new(None));
69+
BasicBlock::new(node_index)
70+
}
71+
72+
pub fn start_new_cleanup_block(&mut self) -> BasicBlock {
73+
let bb = self.start_new_block();
74+
self[bb].is_cleanup = true;
75+
bb
76+
}
77+
78+
pub fn push(&mut self, block: BasicBlock, statement: Statement<'tcx>) {
79+
debug!("push({:?}, {:?})", block, statement);
80+
self[block].statements.push(statement);
81+
}
82+
83+
pub fn terminate(&mut self,
84+
block: BasicBlock,
85+
scope: ScopeId,
86+
span: Span,
87+
kind: TerminatorKind<'tcx>) {
88+
debug_assert!(self[block].terminator.is_none(),
89+
"terminate: block {:?} already has a terminator set", block);
90+
self[block].terminator = Some(Terminator {
91+
span: span,
92+
scope: scope,
93+
kind: kind,
94+
});
95+
}
96+
97+
pub fn push_assign(&mut self,
98+
block: BasicBlock,
99+
scope: ScopeId,
100+
span: Span,
101+
lvalue: &Lvalue<'tcx>,
102+
rvalue: Rvalue<'tcx>) {
103+
self.push(block, Statement {
104+
scope: scope,
105+
span: span,
106+
kind: StatementKind::Assign(lvalue.clone(), rvalue)
107+
});
108+
}
109+
110+
pub fn push_assign_constant(&mut self,
111+
block: BasicBlock,
112+
scope: ScopeId,
113+
span: Span,
114+
temp: &Lvalue<'tcx>,
115+
constant: Constant<'tcx>) {
116+
self.push_assign(block, scope, span, temp,
117+
Rvalue::Use(Operand::Constant(constant)));
118+
}
119+
120+
pub fn push_assign_unit(&mut self,
121+
block: BasicBlock,
122+
scope: ScopeId,
123+
span: Span,
124+
lvalue: &Lvalue<'tcx>) {
125+
self.push_assign(block, scope, span, lvalue, Rvalue::Aggregate(
126+
AggregateKind::Tuple, vec![]
127+
));
128+
}
129+
}
130+
131+
impl<'tcx> Index<BasicBlock> for CFG<'tcx> {
132+
type Output = BasicBlockData<'tcx>;
133+
134+
#[inline]
135+
fn index(&self, index: BasicBlock) -> &BasicBlockData<'tcx> {
136+
&self.basic_blocks[index.index()]
137+
}
138+
}
139+
140+
impl<'tcx> IndexMut<BasicBlock> for CFG<'tcx> {
141+
#[inline]
142+
fn index_mut(&mut self, index: BasicBlock) -> &mut BasicBlockData<'tcx> {
143+
&mut self.basic_blocks[index.index()]
144+
}
145+
}
146+

src/librustc/mir/repr.rs

+8-6
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@
88
// option. This file may not be copied, modified, or distributed
99
// except according to those terms.
1010

11+
pub use mir::cfg::*;
12+
1113
use graphviz::IntoCow;
1214
use middle::const_val::ConstVal;
1315
use rustc_const_math::{ConstUsize, ConstInt, ConstMathErr};
@@ -30,7 +32,7 @@ use syntax::codemap::Span;
3032
pub struct Mir<'tcx> {
3133
/// List of basic blocks. References to basic block use a newtyped index type `BasicBlock`
3234
/// that indexes into this vector.
33-
pub basic_blocks: Vec<BasicBlockData<'tcx>>,
35+
pub cfg: CFG<'tcx>,
3436

3537
/// List of lexical scopes; these are referenced by statements and
3638
/// used (eventually) for debuginfo. Indexed by a `ScopeId`.
@@ -70,17 +72,17 @@ pub const START_BLOCK: BasicBlock = BasicBlock(0);
7072

7173
impl<'tcx> Mir<'tcx> {
7274
pub fn all_basic_blocks(&self) -> Vec<BasicBlock> {
73-
(0..self.basic_blocks.len())
75+
(0..self.cfg.len())
7476
.map(|i| BasicBlock::new(i))
7577
.collect()
7678
}
7779

7880
pub fn basic_block_data(&self, bb: BasicBlock) -> &BasicBlockData<'tcx> {
79-
&self.basic_blocks[bb.index()]
81+
&self.cfg[bb]
8082
}
8183

8284
pub fn basic_block_data_mut(&mut self, bb: BasicBlock) -> &mut BasicBlockData<'tcx> {
83-
&mut self.basic_blocks[bb.index()]
85+
&mut self.cfg[bb]
8486
}
8587
}
8688

@@ -611,7 +613,7 @@ impl<'tcx> Debug for Statement<'tcx> {
611613

612614
/// A path to a value; something that can be evaluated without
613615
/// changing or disturbing program state.
614-
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
616+
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
615617
pub enum Lvalue<'tcx> {
616618
/// local variable declared by the user
617619
Var(u32),
@@ -796,7 +798,7 @@ pub struct ScopeData {
796798
/// These are values that can appear inside an rvalue (or an index
797799
/// lvalue). They are intentionally limited to prevent rvalues from
798800
/// being nested in one another.
799-
#[derive(Clone, PartialEq, RustcEncodable, RustcDecodable)]
801+
#[derive(Clone, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable)]
800802
pub enum Operand<'tcx> {
801803
Consume(Lvalue<'tcx>),
802804
Constant(Constant<'tcx>),
File renamed without changes.

src/librustc_mir/traversal.rs src/librustc/mir/traversal.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ use std::vec;
1212

1313
use rustc_data_structures::bitvec::BitVector;
1414

15-
use rustc::mir::repr::*;
15+
use mir::repr::*;
1616

1717
/// Preorder traversal of a graph.
1818
///
@@ -44,7 +44,7 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> {
4444

4545
Preorder {
4646
mir: mir,
47-
visited: BitVector::new(mir.basic_blocks.len()),
47+
visited: BitVector::new(mir.cfg.basic_blocks.len()),
4848
worklist: worklist
4949
}
5050
}
@@ -106,7 +106,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
106106
pub fn new(mir: &'a Mir<'tcx>, root: BasicBlock) -> Postorder<'a, 'tcx> {
107107
let mut po = Postorder {
108108
mir: mir,
109-
visited: BitVector::new(mir.basic_blocks.len()),
109+
visited: BitVector::new(mir.cfg.basic_blocks.len()),
110110
visit_stack: Vec::new()
111111
};
112112

src/librustc/mir/visit.rs

+5-1
Original file line numberDiff line numberDiff line change
@@ -247,7 +247,7 @@ macro_rules! make_mir_visitor {
247247
fn super_mir(&mut self,
248248
mir: & $($mutability)* Mir<'tcx>) {
249249
let Mir {
250-
ref $($mutability)* basic_blocks,
250+
ref $($mutability)* cfg,
251251
ref $($mutability)* scopes,
252252
promoted: _, // Visited by passes separately.
253253
ref $($mutability)* return_ty,
@@ -258,6 +258,10 @@ macro_rules! make_mir_visitor {
258258
ref $($mutability)* span,
259259
} = *mir;
260260

261+
let CFG {
262+
ref $($mutability)* basic_blocks
263+
} = *cfg;
264+
261265
for (index, data) in basic_blocks.into_iter().enumerate() {
262266
let block = BasicBlock::new(index);
263267
self.visit_basic_block_data(block, data);

src/librustc_borrowck/borrowck/mir/dataflow/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@ impl<'b, 'a: 'b, 'tcx: 'a, BD> PropagationContext<'b, 'a, 'tcx, BD>
112112

113113
fn walk_cfg(&mut self, in_out: &mut IdxSet<BD::Idx>) {
114114
let mir = self.builder.mir;
115-
for (bb_idx, bb_data) in mir.basic_blocks.iter().enumerate() {
115+
for (bb_idx, bb_data) in mir.cfg.basic_blocks.iter().enumerate() {
116116
let builder = &mut self.builder;
117117
{
118118
let sets = builder.flow_state.sets.for_block(bb_idx);
@@ -396,7 +396,7 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
396396
// (now rounded up to multiple of word size)
397397
let bits_per_block = words_per_block * usize_bits;
398398

399-
let num_blocks = mir.basic_blocks.len();
399+
let num_blocks = mir.cfg.basic_blocks.len();
400400
let num_overall = num_blocks * bits_per_block;
401401

402402
let zeroes = Bits::new(IdxSetBuf::new_empty(num_overall));

src/librustc_borrowck/borrowck/mir/patch.rs

+6-6
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ impl<'tcx> MirPatch<'tcx> {
3232
pub fn new(mir: &Mir<'tcx>) -> Self {
3333
let mut result = MirPatch {
3434
patch_map: iter::repeat(None)
35-
.take(mir.basic_blocks.len()).collect(),
35+
.take(mir.cfg.basic_blocks.len()).collect(),
3636
new_blocks: vec![],
3737
new_temps: vec![],
3838
new_statements: vec![],
@@ -86,7 +86,7 @@ impl<'tcx> MirPatch<'tcx> {
8686
}
8787

8888
pub fn terminator_loc(&self, mir: &Mir<'tcx>, bb: BasicBlock) -> Location {
89-
let offset = match bb.index().checked_sub(mir.basic_blocks.len()) {
89+
let offset = match bb.index().checked_sub(mir.cfg.basic_blocks.len()) {
9090
Some(index) => self.new_blocks[index].statements.len(),
9191
None => mir.basic_block_data(bb).statements.len()
9292
};
@@ -131,13 +131,13 @@ impl<'tcx> MirPatch<'tcx> {
131131
debug!("MirPatch: {:?} new temps, starting from index {}: {:?}",
132132
self.new_temps.len(), mir.temp_decls.len(), self.new_temps);
133133
debug!("MirPatch: {} new blocks, starting from index {}",
134-
self.new_blocks.len(), mir.basic_blocks.len());
135-
mir.basic_blocks.extend(self.new_blocks);
134+
self.new_blocks.len(), mir.cfg.basic_blocks.len());
135+
mir.cfg.basic_blocks.extend(self.new_blocks);
136136
mir.temp_decls.extend(self.new_temps);
137137
for (src, patch) in self.patch_map.into_iter().enumerate() {
138138
if let Some(patch) = patch {
139139
debug!("MirPatch: patching block {:?}", src);
140-
mir.basic_blocks[src].terminator_mut().kind = patch;
140+
mir.cfg.basic_blocks[src].terminator_mut().kind = patch;
141141
}
142142
}
143143

@@ -175,7 +175,7 @@ impl<'tcx> MirPatch<'tcx> {
175175
}
176176

177177
pub fn context_for_location(&self, mir: &Mir, loc: Location) -> (Span, ScopeId) {
178-
let data = match loc.block.index().checked_sub(mir.basic_blocks.len()) {
178+
let data = match loc.block.index().checked_sub(mir.cfg.basic_blocks.len()) {
179179
Some(new) => &self.new_blocks[new],
180180
None => mir.basic_block_data(loc.block)
181181
};

src/librustc_data_structures/bitvec.rs

+16
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,12 @@ impl BitVector {
2727
(self.data[word] & mask) != 0
2828
}
2929

30+
pub fn clear(&mut self) {
31+
for datum in &mut self.data {
32+
*datum = 0;
33+
}
34+
}
35+
3036
/// Returns true if the bit has changed.
3137
pub fn insert(&mut self, bit: usize) -> bool {
3238
let (word, mask) = word_mask(bit);
@@ -37,6 +43,16 @@ impl BitVector {
3743
new_value != value
3844
}
3945

46+
/// Returns true if the bit has changed.
47+
pub fn remove(&mut self, bit: usize) -> bool {
48+
let (word, mask) = word_mask(bit);
49+
let data = &mut self.data[word];
50+
let value = *data;
51+
let new_value = value & !mask;
52+
*data = new_value;
53+
new_value != value
54+
}
55+
4056
pub fn insert_all(&mut self, all: &BitVector) -> bool {
4157
assert!(self.data.len() == all.data.len());
4258
let mut changed = false;

0 commit comments

Comments
 (0)