Skip to content

Commit 65b65fe

Browse files
pnkfelixalexcrichton
authored andcommitted
Bugfixes for rustc::middle::cfg::construct.
1. Only insert non-dummy nodes into the exit map. 2. Revise handling of `break` and `continue` forms so that they are not treated as if control falls through to the next node (since it does not, it just jumps to the end or start of the loop body). 3. Fixed support for return expression in flow graph construction.
1 parent dbaf300 commit 65b65fe

File tree

1 file changed

+45
-15
lines changed

1 file changed

+45
-15
lines changed

src/librustc/middle/cfg/construct.rs

Lines changed: 45 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@ struct CFGBuilder<'a> {
2121
method_map: typeck::MethodMap,
2222
exit_map: NodeMap<CFGIndex>,
2323
graph: CFGGraph,
24-
loop_scopes: Vec<LoopScope> ,
24+
fn_exit: CFGIndex,
25+
loop_scopes: Vec<LoopScope>,
2526
}
2627

2728
struct LoopScope {
@@ -33,20 +34,35 @@ struct LoopScope {
3334
pub fn construct(tcx: &ty::ctxt,
3435
method_map: typeck::MethodMap,
3536
blk: &ast::Block) -> CFG {
37+
let mut graph = graph::Graph::new();
38+
let entry = add_initial_dummy_node(&mut graph);
39+
40+
// `fn_exit` is target of return exprs, which lies somewhere
41+
// outside input `blk`. (Distinguishing `fn_exit` and `block_exit`
42+
// also resolves chicken-and-egg problem that arises if you try to
43+
// have return exprs jump to `block_exit` during construction.)
44+
let fn_exit = add_initial_dummy_node(&mut graph);
45+
let block_exit;
46+
3647
let mut cfg_builder = CFGBuilder {
3748
exit_map: NodeMap::new(),
38-
graph: graph::Graph::new(),
49+
graph: graph,
50+
fn_exit: fn_exit,
3951
tcx: tcx,
4052
method_map: method_map,
4153
loop_scopes: Vec::new()
4254
};
43-
let entry = cfg_builder.add_node(0, []);
44-
let exit = cfg_builder.block(blk, entry);
55+
block_exit = cfg_builder.block(blk, entry);
56+
cfg_builder.add_contained_edge(block_exit, fn_exit);
4557
let CFGBuilder {exit_map, graph, ..} = cfg_builder;
4658
CFG {exit_map: exit_map,
4759
graph: graph,
4860
entry: entry,
49-
exit: exit}
61+
exit: fn_exit}
62+
}
63+
64+
fn add_initial_dummy_node(g: &mut CFGGraph) -> CFGIndex {
65+
g.add_node(CFGNodeData { id: ast::DUMMY_NODE_ID })
5066
}
5167

5268
impl<'a> CFGBuilder<'a> {
@@ -327,24 +343,25 @@ impl<'a> CFGBuilder<'a> {
327343

328344
ast::ExprRet(v) => {
329345
let v_exit = self.opt_expr(v, pred);
330-
let loop_scope = *self.loop_scopes.get(0);
331-
self.add_exiting_edge(expr, v_exit,
332-
loop_scope, loop_scope.break_index);
333-
self.add_node(expr.id, [])
346+
let b = self.add_node(expr.id, [v_exit]);
347+
self.add_returning_edge(expr, b);
348+
self.add_node(ast::DUMMY_NODE_ID, [])
334349
}
335350

336351
ast::ExprBreak(label) => {
337352
let loop_scope = self.find_scope(expr, label);
338-
self.add_exiting_edge(expr, pred,
353+
let b = self.add_node(expr.id, [pred]);
354+
self.add_exiting_edge(expr, b,
339355
loop_scope, loop_scope.break_index);
340-
self.add_node(expr.id, [])
356+
self.add_node(ast::DUMMY_NODE_ID, [])
341357
}
342358

343359
ast::ExprAgain(label) => {
344360
let loop_scope = self.find_scope(expr, label);
345-
self.add_exiting_edge(expr, pred,
361+
let a = self.add_node(expr.id, [pred]);
362+
self.add_exiting_edge(expr, a,
346363
loop_scope, loop_scope.continue_index);
347-
self.add_node(expr.id, [])
364+
self.add_node(ast::DUMMY_NODE_ID, [])
348365
}
349366

350367
ast::ExprVec(ref elems) => {
@@ -453,13 +470,16 @@ impl<'a> CFGBuilder<'a> {
453470
}
454471

455472
fn add_dummy_node(&mut self, preds: &[CFGIndex]) -> CFGIndex {
456-
self.add_node(0, preds)
473+
self.add_node(ast::DUMMY_NODE_ID, preds)
457474
}
458475

459476
fn add_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex {
460477
assert!(!self.exit_map.contains_key(&id));
461478
let node = self.graph.add_node(CFGNodeData {id: id});
462-
self.exit_map.insert(id, node);
479+
if id != ast::DUMMY_NODE_ID {
480+
assert!(!self.exit_map.contains_key(&id));
481+
self.exit_map.insert(id, node);
482+
}
463483
for &pred in preds.iter() {
464484
self.add_contained_edge(pred, node);
465485
}
@@ -488,6 +508,16 @@ impl<'a> CFGBuilder<'a> {
488508
self.graph.add_edge(from_index, to_index, data);
489509
}
490510

511+
fn add_returning_edge(&mut self,
512+
_from_expr: @ast::Expr,
513+
from_index: CFGIndex) {
514+
let mut data = CFGEdgeData {exiting_scopes: vec!() };
515+
for &LoopScope { loop_id: id, .. } in self.loop_scopes.iter().rev() {
516+
data.exiting_scopes.push(id);
517+
}
518+
self.graph.add_edge(from_index, self.fn_exit, data);
519+
}
520+
491521
fn find_scope(&self,
492522
expr: @ast::Expr,
493523
label: Option<ast::Ident>) -> LoopScope {

0 commit comments

Comments
 (0)