Skip to content

Commit 0295b0f

Browse files
Fix MIR passes to work with new StatementKind::Assert
1 parent 33d124f commit 0295b0f

File tree

21 files changed

+222
-119
lines changed

21 files changed

+222
-119
lines changed

src/librustc/mir/cache.rs

+38-2
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@ use rustc_serialize as serialize;
1717

1818
#[derive(Clone, Debug)]
1919
pub struct Cache {
20-
predecessors: RefCell<Option<IndexVec<Block, Vec<Block>>>>
20+
predecessors: RefCell<Option<IndexVec<Block, Vec<Block>>>>,
21+
successors: RefCell<Option<IndexVec<Block, Vec<Block>>>>,
2122
}
2223

2324

@@ -37,13 +38,15 @@ impl serialize::Decodable for Cache {
3738
impl Cache {
3839
pub fn new() -> Self {
3940
Cache {
40-
predecessors: RefCell::new(None)
41+
predecessors: RefCell::new(None),
42+
successors: RefCell::new(None)
4143
}
4244
}
4345

4446
pub fn invalidate(&self) {
4547
// FIXME: consider being more fine-grained
4648
*self.predecessors.borrow_mut() = None;
49+
*self.successors.borrow_mut() = None;
4750
}
4851

4952
pub fn predecessors(&self, mir: &Mir) -> Ref<IndexVec<Block, Vec<Block>>> {
@@ -53,11 +56,25 @@ impl Cache {
5356

5457
Ref::map(self.predecessors.borrow(), |p| p.as_ref().unwrap())
5558
}
59+
60+
pub fn successors(&self, mir: &Mir) -> Ref<IndexVec<Block, Vec<Block>>> {
61+
if self.successors.borrow().is_none() {
62+
*self.successors.borrow_mut() = Some(calculate_successors(mir));
63+
}
64+
65+
Ref::map(self.successors.borrow(), |p| p.as_ref().unwrap())
66+
}
5667
}
5768

5869
fn calculate_predecessors(mir: &Mir) -> IndexVec<Block, Vec<Block>> {
5970
let mut result = IndexVec::from_elem(vec![], mir.basic_blocks());
6071
for (bb, data) in mir.basic_blocks().iter_enumerated() {
72+
for stmt in &data.statements {
73+
for &tgt in stmt.successors().iter() {
74+
result[tgt].push(bb);
75+
}
76+
}
77+
6178
if let Some(ref term) = data.terminator {
6279
for &tgt in term.successors().iter() {
6380
result[tgt].push(bb);
@@ -67,3 +84,22 @@ fn calculate_predecessors(mir: &Mir) -> IndexVec<Block, Vec<Block>> {
6784

6885
result
6986
}
87+
88+
fn calculate_successors(mir: &Mir) -> IndexVec<Block, Vec<Block>> {
89+
let mut result = IndexVec::from_elem(vec![], mir.basic_blocks());
90+
for (bb, data) in mir.basic_blocks().iter_enumerated() {
91+
for stmt in &data.statements {
92+
for &tgt in stmt.successors().iter() {
93+
result[bb].push(tgt);
94+
}
95+
}
96+
97+
if let Some(ref term) = data.terminator {
98+
for &tgt in term.successors().iter() {
99+
result[bb].push(tgt);
100+
}
101+
}
102+
}
103+
104+
result
105+
}

src/librustc/mir/mod.rs

+29-1
Original file line numberDiff line numberDiff line change
@@ -162,11 +162,21 @@ impl<'tcx> Mir<'tcx> {
162162
self.cache.predecessors(self)
163163
}
164164

165+
#[inline]
166+
pub fn successors(&self) -> Ref<IndexVec<Block, Vec<Block>>> {
167+
self.cache.successors(self)
168+
}
169+
165170
#[inline]
166171
pub fn predecessors_for(&self, bb: Block) -> Ref<Vec<Block>> {
167172
Ref::map(self.predecessors(), |p| &p[bb])
168173
}
169174

175+
#[inline]
176+
pub fn successors_for(&self, bb: Block) -> Ref<Vec<Block>> {
177+
Ref::map(self.successors(), |p| &p[bb])
178+
}
179+
170180
#[inline]
171181
pub fn dominators(&self) -> Dominators<Block> {
172182
dominators(self)
@@ -724,6 +734,24 @@ impl<'tcx> Statement<'tcx> {
724734
pub fn make_nop(&mut self) {
725735
self.kind = StatementKind::Nop
726736
}
737+
738+
pub fn successors(&self) -> Cow<[Block]> {
739+
match self.kind {
740+
StatementKind::Assert { cleanup: Some(unwind), .. } => {
741+
vec![unwind].into_cow()
742+
}
743+
_ => (&[]).into_cow(),
744+
}
745+
}
746+
747+
pub fn successors_mut(&mut self) -> Vec<&mut Block> {
748+
match self.kind {
749+
StatementKind::Assert { cleanup: Some(ref mut unwind), .. } => {
750+
vec![unwind]
751+
}
752+
_ => Vec::new(),
753+
}
754+
}
727755
}
728756

729757
#[derive(Clone, Debug, RustcEncodable, RustcDecodable)]
@@ -1302,7 +1330,7 @@ impl<'tcx> ControlFlowGraph for Mir<'tcx> {
13021330
fn successors<'graph>(&'graph self, node: Self::Node)
13031331
-> <Self as GraphSuccessors<'graph>>::Iter
13041332
{
1305-
self.basic_blocks[node].terminator().successors().into_owned().into_iter()
1333+
self.successors_for(node).clone().into_iter()
13061334
}
13071335
}
13081336

src/librustc/mir/traversal.rs

+8-21
Original file line numberDiff line numberDiff line change
@@ -64,15 +64,11 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
6464
continue;
6565
}
6666

67-
let data = &self.mir[idx];
68-
69-
if let Some(ref term) = data.terminator {
70-
for &succ in term.successors().iter() {
71-
self.worklist.push(succ);
72-
}
67+
for &succ in self.mir.successors_for(idx).iter() {
68+
self.worklist.push(succ);
7369
}
7470

75-
return Some((idx, data));
71+
return Some((idx, &self.mir[idx]));
7672
}
7773

7874
None
@@ -111,17 +107,11 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
111107
visit_stack: Vec::new()
112108
};
113109

110+
po.visited.insert(root.index());
114111

115-
let data = &po.mir[root];
116-
117-
if let Some(ref term) = data.terminator {
118-
po.visited.insert(root.index());
119-
120-
let succs = term.successors().into_owned().into_iter();
121-
122-
po.visit_stack.push((root, succs));
123-
po.traverse_successor();
124-
}
112+
let succs = ControlFlowGraph::successors(&po.mir, root);
113+
po.visit_stack.push((root, succs));
114+
po.traverse_successor();
125115

126116
po
127117
}
@@ -186,10 +176,7 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
186176
};
187177

188178
if self.visited.insert(bb.index()) {
189-
if let Some(ref term) = self.mir[bb].terminator {
190-
let succs = term.successors().into_owned().into_iter();
191-
self.visit_stack.push((bb, succs));
192-
}
179+
self.visit_stack.push((bb, ControlFlowGraph::successors(&self.mir, bb)));
193180
}
194181
}
195182
}

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

+1-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ pub type Node = Block;
125125
pub struct Edge { source: Block, index: usize }
126126

127127
fn outgoing(mir: &Mir, bb: Block) -> Vec<Edge> {
128-
let succ_len = mir[bb].terminator().successors().len();
128+
let succ_len = mir.successors_for(bb).len();
129129
(0..succ_len).map(|index| Edge { source: bb, index: index}).collect()
130130
}
131131

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

+1
Original file line numberDiff line numberDiff line change
@@ -474,6 +474,7 @@ impl<'a, 'tcx> BitDenotation for MovingOutStatements<'a, 'tcx> {
474474
mir::StatementKind::StorageLive(_) |
475475
mir::StatementKind::StorageDead(_) |
476476
mir::StatementKind::InlineAsm { .. } |
477+
mir::StatementKind::Assert { .. } |
477478
mir::StatementKind::Nop => {}
478479
}
479480
}

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

-2
Original file line numberDiff line numberDiff line change
@@ -439,14 +439,12 @@ impl<'a, 'tcx: 'a, D> DataflowAnalysis<'a, 'tcx, D>
439439
mir::TerminatorKind::Resume |
440440
mir::TerminatorKind::Unreachable => {}
441441
mir::TerminatorKind::Goto { ref target } |
442-
mir::TerminatorKind::Assert { ref target, cleanup: None, .. } |
443442
mir::TerminatorKind::Drop { ref target, location: _, unwind: None } |
444443
mir::TerminatorKind::DropAndReplace {
445444
ref target, value: _, location: _, unwind: None
446445
} => {
447446
self.propagate_bits_into_entry_set_for(in_out, changed, target);
448447
}
449-
mir::TerminatorKind::Assert { ref target, cleanup: Some(ref unwind), .. } |
450448
mir::TerminatorKind::Drop { ref target, location: _, unwind: Some(ref unwind) } |
451449
mir::TerminatorKind::DropAndReplace {
452450
ref target, value: _, location: _, unwind: Some(ref unwind)

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

+1
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,7 @@ fn each_block<'a, 'tcx, O>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
105105
mir::StatementKind::StorageLive(_) |
106106
mir::StatementKind::StorageDead(_) |
107107
mir::StatementKind::InlineAsm { .. } |
108+
mir::StatementKind::Assert { .. } |
108109
mir::StatementKind::Nop => continue,
109110
mir::StatementKind::SetDiscriminant{ .. } =>
110111
span_bug!(stmt.source_info.span,

src/librustc_borrowck/borrowck/mir/gather_moves.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -413,6 +413,7 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
413413
"SetDiscriminant should not exist during borrowck");
414414
}
415415
StatementKind::InlineAsm { .. } |
416+
StatementKind::Assert { .. } |
416417
StatementKind::Nop => {}
417418
}
418419
}
@@ -464,7 +465,6 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
464465
self.gather_move(loc, &Lvalue::Local(RETURN_POINTER));
465466
}
466467

467-
TerminatorKind::Assert { .. } |
468468
TerminatorKind::SwitchInt { .. } => {
469469
// branching terminators - these don't move anything
470470
}

src/librustc_borrowck/borrowck/mir/mod.rs

+1
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,7 @@ fn drop_flag_effects_for_location<'a, 'tcx, F>(
364364
mir::StatementKind::StorageLive(_) |
365365
mir::StatementKind::StorageDead(_) |
366366
mir::StatementKind::InlineAsm { .. } |
367+
mir::StatementKind::Assert { .. } |
367368
mir::StatementKind::Nop => {}
368369
},
369370
None => {

src/librustc_mir/build/expr/as_lvalue.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -75,15 +75,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
7575
len: Operand::Consume(len),
7676
index: idx.clone()
7777
};
78-
this.cfg.push(block, Statement {
79-
source_info: this.source_info(expr_span),
78+
let stmt = Statement {
79+
source_info: source_info,
8080
kind: StatementKind::Assert {
8181
cond: Operand::Consume(lt),
8282
expected: true,
8383
msg: msg,
8484
cleanup: this.diverge_cleanup(),
8585
}
86-
});
86+
};
87+
this.cfg.push(block, stmt);
8788
block.and(slice.index(idx))
8889
}
8990
ExprKind::SelfRef => {

src/librustc_mir/build/expr/as_rvalue.rs

+17-13
Original file line numberDiff line numberDiff line change
@@ -89,15 +89,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
8989
Rvalue::BinaryOp(BinOp::Eq, arg.clone(), minval));
9090

9191
let err = ConstMathErr::Overflow(Op::Neg);
92-
this.cfg.push(block, Statement {
93-
source_info: this.source_info(expr_span),
92+
let stmt = Statement {
93+
source_info: source_info,
9494
kind: StatementKind::Assert {
9595
cond: Operand::Consume(is_min),
9696
expected: false,
9797
msg: AssertMessage::Math(err),
9898
cleanup: this.diverge_cleanup(),
9999
},
100-
});
100+
};
101+
this.cfg.push(block, stmt);
101102
}
102103
block.and(Rvalue::UnaryOp(op, arg))
103104
}
@@ -261,7 +262,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
261262
}
262263
}
263264

264-
pub fn build_binary_op(&mut self, mut block: Block,
265+
pub fn build_binary_op(&mut self, block: Block,
265266
op: BinOp, span: Span, ty: ty::Ty<'tcx>,
266267
lhs: Operand<'tcx>, rhs: Operand<'tcx>) -> BlockAnd<Rvalue<'tcx>> {
267268
let source_info = self.source_info(span);
@@ -291,15 +292,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
291292
}
292293
});
293294

294-
self.cfg.push(block, Statement {
295-
source_info: self.source_info(span),
295+
let stmt = Statement {
296+
source_info: source_info,
296297
kind: StatementKind::Assert {
297298
cond: Operand::Consume(of),
298299
expected: false,
299300
msg: AssertMessage::Math(err),
300301
cleanup: self.diverge_cleanup(),
301302
},
302-
});
303+
};
304+
self.cfg.push(block, stmt);
303305
block.and(Rvalue::Use(Operand::Consume(val)))
304306
} else {
305307
if ty.is_integral() && (op == BinOp::Div || op == BinOp::Rem) {
@@ -320,15 +322,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
320322
self.cfg.push_assign(block, source_info, &is_zero,
321323
Rvalue::BinaryOp(BinOp::Eq, rhs.clone(), zero));
322324

323-
self.cfg.push(block, Statement {
324-
source_info: self.source_info(span),
325+
let stmt = Statement {
326+
source_info: source_info,
325327
kind: StatementKind::Assert {
326328
cond: Operand::Consume(is_zero),
327329
expected: false,
328330
msg: AssertMessage::Math(zero_err),
329331
cleanup: self.diverge_cleanup(),
330332
},
331-
});
333+
};
334+
self.cfg.push(block, stmt);
332335

333336
// We only need to check for the overflow in one case:
334337
// MIN / -1, and only for signed values.
@@ -352,15 +355,16 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
352355
self.cfg.push_assign(block, source_info, &of,
353356
Rvalue::BinaryOp(BinOp::BitAnd, is_neg_1, is_min));
354357

355-
self.cfg.push(block, Statement {
356-
source_info: self.source_info(span),
358+
let stmt = Statement {
359+
source_info: source_info,
357360
kind: StatementKind::Assert {
358361
cond: Operand::Consume(of),
359362
expected: false,
360363
msg: AssertMessage::Math(overflow_err),
361364
cleanup: self.diverge_cleanup(),
362365
},
363-
});
366+
};
367+
self.cfg.push(block, stmt);
364368
}
365369
}
366370

0 commit comments

Comments
 (0)