mirror of
https://github.com/rust-lang/rust.git
synced 2024-12-20 04:24:41 +00:00
Distinguish between AST and various Dummy nodes in CFG.
(Factoring of aatch CFG code, Part 1.)
This commit is contained in:
parent
eb1b500a9a
commit
97c1711894
@ -1848,7 +1848,7 @@ impl LintPass for UnconditionalRecursion {
|
||||
continue
|
||||
}
|
||||
visited.insert(cfg_id);
|
||||
let node_id = cfg.graph.node_data(idx).id;
|
||||
let node_id = cfg.graph.node_data(idx).id();
|
||||
|
||||
// is this a recursive call?
|
||||
if node_id != ast::DUMMY_NODE_ID && checker(cx.tcx, impl_node_id, id, name, node_id) {
|
||||
|
@ -36,13 +36,13 @@ struct LoopScope {
|
||||
pub fn construct(tcx: &ty::ctxt,
|
||||
blk: &ast::Block) -> CFG {
|
||||
let mut graph = graph::Graph::new();
|
||||
let entry = add_initial_dummy_node(&mut graph);
|
||||
let entry = graph.add_node(CFGNodeData::Entry);
|
||||
|
||||
// `fn_exit` is target of return exprs, which lies somewhere
|
||||
// outside input `blk`. (Distinguishing `fn_exit` and `block_exit`
|
||||
// also resolves chicken-and-egg problem that arises if you try to
|
||||
// have return exprs jump to `block_exit` during construction.)
|
||||
let fn_exit = add_initial_dummy_node(&mut graph);
|
||||
let fn_exit = graph.add_node(CFGNodeData::Exit);
|
||||
let block_exit;
|
||||
|
||||
let mut cfg_builder = CFGBuilder {
|
||||
@ -61,10 +61,6 @@ pub fn construct(tcx: &ty::ctxt,
|
||||
exit: fn_exit}
|
||||
}
|
||||
|
||||
fn add_initial_dummy_node(g: &mut CFGGraph) -> CFGIndex {
|
||||
g.add_node(CFGNodeData { id: ast::DUMMY_NODE_ID })
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
fn block(&mut self, blk: &ast::Block, pred: CFGIndex) -> CFGIndex {
|
||||
let mut stmts_exit = pred;
|
||||
@ -74,19 +70,19 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
|
||||
let expr_exit = self.opt_expr(&blk.expr, stmts_exit);
|
||||
|
||||
self.add_node(blk.id, &[expr_exit])
|
||||
self.add_ast_node(blk.id, &[expr_exit])
|
||||
}
|
||||
|
||||
fn stmt(&mut self, stmt: &ast::Stmt, pred: CFGIndex) -> CFGIndex {
|
||||
match stmt.node {
|
||||
ast::StmtDecl(ref decl, id) => {
|
||||
let exit = self.decl(&**decl, pred);
|
||||
self.add_node(id, &[exit])
|
||||
self.add_ast_node(id, &[exit])
|
||||
}
|
||||
|
||||
ast::StmtExpr(ref expr, id) | ast::StmtSemi(ref expr, id) => {
|
||||
let exit = self.expr(&**expr, pred);
|
||||
self.add_node(id, &[exit])
|
||||
self.add_ast_node(id, &[exit])
|
||||
}
|
||||
|
||||
ast::StmtMac(..) => {
|
||||
@ -115,33 +111,33 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
ast::PatLit(..) |
|
||||
ast::PatRange(..) |
|
||||
ast::PatWild(_) => {
|
||||
self.add_node(pat.id, &[pred])
|
||||
self.add_ast_node(pat.id, &[pred])
|
||||
}
|
||||
|
||||
ast::PatBox(ref subpat) |
|
||||
ast::PatRegion(ref subpat, _) |
|
||||
ast::PatIdent(_, _, Some(ref subpat)) => {
|
||||
let subpat_exit = self.pat(&**subpat, pred);
|
||||
self.add_node(pat.id, &[subpat_exit])
|
||||
self.add_ast_node(pat.id, &[subpat_exit])
|
||||
}
|
||||
|
||||
ast::PatEnum(_, Some(ref subpats)) |
|
||||
ast::PatTup(ref subpats) => {
|
||||
let pats_exit = self.pats_all(subpats.iter(), pred);
|
||||
self.add_node(pat.id, &[pats_exit])
|
||||
self.add_ast_node(pat.id, &[pats_exit])
|
||||
}
|
||||
|
||||
ast::PatStruct(_, ref subpats, _) => {
|
||||
let pats_exit =
|
||||
self.pats_all(subpats.iter().map(|f| &f.node.pat), pred);
|
||||
self.add_node(pat.id, &[pats_exit])
|
||||
self.add_ast_node(pat.id, &[pats_exit])
|
||||
}
|
||||
|
||||
ast::PatVec(ref pre, ref vec, ref post) => {
|
||||
let pre_exit = self.pats_all(pre.iter(), pred);
|
||||
let vec_exit = self.pats_all(vec.iter(), pre_exit);
|
||||
let post_exit = self.pats_all(post.iter(), vec_exit);
|
||||
self.add_node(pat.id, &[post_exit])
|
||||
self.add_ast_node(pat.id, &[post_exit])
|
||||
}
|
||||
|
||||
ast::PatMac(_) => {
|
||||
@ -178,7 +174,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
match expr.node {
|
||||
ast::ExprBlock(ref blk) => {
|
||||
let blk_exit = self.block(&**blk, pred);
|
||||
self.add_node(expr.id, &[blk_exit])
|
||||
self.add_ast_node(expr.id, &[blk_exit])
|
||||
}
|
||||
|
||||
ast::ExprIf(ref cond, ref then, None) => {
|
||||
@ -198,7 +194,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
//
|
||||
let cond_exit = self.expr(&**cond, pred); // 1
|
||||
let then_exit = self.block(&**then, cond_exit); // 2
|
||||
self.add_node(expr.id, &[cond_exit, then_exit]) // 3,4
|
||||
self.add_ast_node(expr.id, &[cond_exit, then_exit]) // 3,4
|
||||
}
|
||||
|
||||
ast::ExprIf(ref cond, ref then, Some(ref otherwise)) => {
|
||||
@ -219,7 +215,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
let cond_exit = self.expr(&**cond, pred); // 1
|
||||
let then_exit = self.block(&**then, cond_exit); // 2
|
||||
let else_exit = self.expr(&**otherwise, cond_exit); // 3
|
||||
self.add_node(expr.id, &[then_exit, else_exit]) // 4, 5
|
||||
self.add_ast_node(expr.id, &[then_exit, else_exit]) // 4, 5
|
||||
}
|
||||
|
||||
ast::ExprIfLet(..) => {
|
||||
@ -247,7 +243,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
// Is the condition considered part of the loop?
|
||||
let loopback = self.add_dummy_node(&[pred]); // 1
|
||||
let cond_exit = self.expr(&**cond, loopback); // 2
|
||||
let expr_exit = self.add_node(expr.id, &[cond_exit]); // 3
|
||||
let expr_exit = self.add_ast_node(expr.id, &[cond_exit]); // 3
|
||||
self.loop_scopes.push(LoopScope {
|
||||
loop_id: expr.id,
|
||||
continue_index: loopback,
|
||||
@ -283,7 +279,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
// may cause additional edges.
|
||||
|
||||
let loopback = self.add_dummy_node(&[pred]); // 1
|
||||
let expr_exit = self.add_node(expr.id, &[]); // 2
|
||||
let expr_exit = self.add_ast_node(expr.id, &[]); // 2
|
||||
self.loop_scopes.push(LoopScope {
|
||||
loop_id: expr.id,
|
||||
continue_index: loopback,
|
||||
@ -323,7 +319,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
//
|
||||
let discr_exit = self.expr(&**discr, pred); // 1
|
||||
|
||||
let expr_exit = self.add_node(expr.id, &[]);
|
||||
let expr_exit = self.add_ast_node(expr.id, &[]);
|
||||
let mut cond_exit = discr_exit;
|
||||
for arm in arms {
|
||||
cond_exit = self.add_dummy_node(&[cond_exit]); // 2
|
||||
@ -354,30 +350,30 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
//
|
||||
let l_exit = self.expr(&**l, pred); // 1
|
||||
let r_exit = self.expr(&**r, l_exit); // 2
|
||||
self.add_node(expr.id, &[l_exit, r_exit]) // 3,4
|
||||
self.add_ast_node(expr.id, &[l_exit, r_exit]) // 3,4
|
||||
}
|
||||
|
||||
ast::ExprRet(ref v) => {
|
||||
let v_exit = self.opt_expr(v, pred);
|
||||
let b = self.add_node(expr.id, &[v_exit]);
|
||||
let b = self.add_ast_node(expr.id, &[v_exit]);
|
||||
self.add_returning_edge(expr, b);
|
||||
self.add_node(ast::DUMMY_NODE_ID, &[])
|
||||
self.add_unreachable_node()
|
||||
}
|
||||
|
||||
ast::ExprBreak(label) => {
|
||||
let loop_scope = self.find_scope(expr, label);
|
||||
let b = self.add_node(expr.id, &[pred]);
|
||||
let b = self.add_ast_node(expr.id, &[pred]);
|
||||
self.add_exiting_edge(expr, b,
|
||||
loop_scope, loop_scope.break_index);
|
||||
self.add_node(ast::DUMMY_NODE_ID, &[])
|
||||
self.add_unreachable_node()
|
||||
}
|
||||
|
||||
ast::ExprAgain(label) => {
|
||||
let loop_scope = self.find_scope(expr, label);
|
||||
let a = self.add_node(expr.id, &[pred]);
|
||||
let a = self.add_ast_node(expr.id, &[pred]);
|
||||
self.add_exiting_edge(expr, a,
|
||||
loop_scope, loop_scope.continue_index);
|
||||
self.add_node(ast::DUMMY_NODE_ID, &[])
|
||||
self.add_unreachable_node()
|
||||
}
|
||||
|
||||
ast::ExprVec(ref elems) => {
|
||||
@ -454,7 +450,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
let &(_, ref expr, _) = a;
|
||||
&**expr
|
||||
}), post_inputs);
|
||||
self.add_node(expr.id, &[post_outputs])
|
||||
self.add_ast_node(expr.id, &[post_outputs])
|
||||
}
|
||||
|
||||
ast::ExprMac(..) |
|
||||
@ -481,7 +477,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
|
||||
let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
|
||||
if return_ty.diverges() {
|
||||
self.add_node(ast::DUMMY_NODE_ID, &[])
|
||||
self.add_unreachable_node()
|
||||
} else {
|
||||
ret
|
||||
}
|
||||
@ -508,17 +504,26 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
|
||||
//! Handles case of an expression that evaluates `subexprs` in order
|
||||
|
||||
let subexprs_exit = self.exprs(subexprs, pred);
|
||||
self.add_node(expr.id, &[subexprs_exit])
|
||||
self.add_ast_node(expr.id, &[subexprs_exit])
|
||||
}
|
||||
|
||||
fn add_dummy_node(&mut self, preds: &[CFGIndex]) -> CFGIndex {
|
||||
self.add_node(ast::DUMMY_NODE_ID, preds)
|
||||
self.add_node(CFGNodeData::Dummy, preds)
|
||||
}
|
||||
|
||||
fn add_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex {
|
||||
fn add_ast_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex {
|
||||
assert!(!self.exit_map.contains_key(&id));
|
||||
let node = self.graph.add_node(CFGNodeData {id: id});
|
||||
if id != ast::DUMMY_NODE_ID {
|
||||
assert!(id != ast::DUMMY_NODE_ID);
|
||||
self.add_node(CFGNodeData::AST(id), preds)
|
||||
}
|
||||
|
||||
fn add_unreachable_node(&mut self) -> CFGIndex {
|
||||
self.add_node(CFGNodeData::Unreachable, &[])
|
||||
}
|
||||
|
||||
fn add_node(&mut self, data: CFGNodeData, preds: &[CFGIndex]) -> CFGIndex {
|
||||
let node = self.graph.add_node(data);
|
||||
if let CFGNodeData::AST(id) = data {
|
||||
assert!(!self.exit_map.contains_key(&id));
|
||||
self.exit_map.insert(id, node);
|
||||
}
|
||||
|
@ -65,10 +65,10 @@ impl<'a, 'ast> dot::Labeller<'a, Node<'a>, Edge<'a>> for LabelledCFG<'a, 'ast> {
|
||||
dot::LabelText::LabelStr("entry".into_cow())
|
||||
} else if i == self.cfg.exit {
|
||||
dot::LabelText::LabelStr("exit".into_cow())
|
||||
} else if n.data.id == ast::DUMMY_NODE_ID {
|
||||
} else if n.data.id() == ast::DUMMY_NODE_ID {
|
||||
dot::LabelText::LabelStr("(dummy_node)".into_cow())
|
||||
} else {
|
||||
let s = self.ast_map.node_to_string(n.data.id);
|
||||
let s = self.ast_map.node_to_string(n.data.id());
|
||||
// left-aligns the lines
|
||||
let s = replace_newline_with_backslash_l(s);
|
||||
dot::LabelText::EscStr(s.into_cow())
|
||||
|
@ -26,9 +26,23 @@ pub struct CFG {
|
||||
pub exit: CFGIndex,
|
||||
}
|
||||
|
||||
#[derive(Copy)]
|
||||
pub struct CFGNodeData {
|
||||
pub id: ast::NodeId
|
||||
#[derive(Copy, PartialEq)]
|
||||
pub enum CFGNodeData {
|
||||
AST(ast::NodeId),
|
||||
Entry,
|
||||
Exit,
|
||||
Dummy,
|
||||
Unreachable,
|
||||
}
|
||||
|
||||
impl CFGNodeData {
|
||||
pub fn id(&self) -> ast::NodeId {
|
||||
if let CFGNodeData::AST(id) = *self {
|
||||
id
|
||||
} else {
|
||||
ast::DUMMY_NODE_ID
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct CFGEdgeData {
|
||||
@ -50,6 +64,6 @@ impl CFG {
|
||||
}
|
||||
|
||||
pub fn node_is_reachable(&self, id: ast::NodeId) -> bool {
|
||||
self.graph.depth_traverse(self.entry).any(|node| node.id == id)
|
||||
self.graph.depth_traverse(self.entry).any(|node| node.id() == id)
|
||||
}
|
||||
}
|
||||
|
@ -157,8 +157,8 @@ fn build_nodeid_to_index(decl: Option<&ast::FnDecl>,
|
||||
}
|
||||
|
||||
cfg.graph.each_node(|node_idx, node| {
|
||||
if node.data.id != ast::DUMMY_NODE_ID {
|
||||
index.insert(node.data.id, node_idx);
|
||||
if node.data.id() != ast::DUMMY_NODE_ID {
|
||||
index.insert(node.data.id(), node_idx);
|
||||
}
|
||||
true
|
||||
});
|
||||
@ -482,7 +482,7 @@ impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> {
|
||||
|
||||
cfg.graph.each_node(|node_index, node| {
|
||||
debug!("DataFlowContext::walk_cfg idx={:?} id={} begin in_out={}",
|
||||
node_index, node.data.id, bits_to_string(in_out));
|
||||
node_index, node.data.id(), bits_to_string(in_out));
|
||||
|
||||
let (start, end) = self.dfcx.compute_id_range(node_index);
|
||||
|
||||
|
@ -52,7 +52,7 @@ pub struct DataflowLabeller<'a, 'tcx: 'a> {
|
||||
|
||||
impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> {
|
||||
fn dataflow_for(&self, e: EntryOrExit, n: &Node<'a>) -> String {
|
||||
let id = n.1.data.id;
|
||||
let id = n.1.data.id();
|
||||
debug!("dataflow_for({:?}, id={}) {:?}", e, id, self.variants);
|
||||
let mut sets = "".to_string();
|
||||
let mut seen_one = false;
|
||||
|
@ -1353,7 +1353,7 @@ fn build_cfg(tcx: &ty::ctxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>)
|
||||
// the clobbering of the existing value in the return slot.
|
||||
fn has_nested_returns(tcx: &ty::ctxt, cfg: &cfg::CFG, blk_id: ast::NodeId) -> bool {
|
||||
for n in cfg.graph.depth_traverse(cfg.entry) {
|
||||
match tcx.map.find(n.id) {
|
||||
match tcx.map.find(n.id()) {
|
||||
Some(ast_map::NodeExpr(ex)) => {
|
||||
if let ast::ExprRet(Some(ref ret_expr)) = ex.node {
|
||||
let mut visitor = FindNestedReturn::new();
|
||||
|
Loading…
Reference in New Issue
Block a user