1 // Copyright 2014 The Rust Project Developers. See the COPYRIGHT
2 // file at the top-level directory of this distribution and at
3 // http://rust-lang.org/COPYRIGHT.
5 // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6 // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7 // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8 // option. This file may not be copied, modified, or distributed
9 // except according to those terms.
11 //! This module provides linkage between rustc::middle::graph and
12 //! libgraphviz traits, specialized to attaching borrowck analysis
13 //! data to rendered labels.
15 pub use self::Variant::*;
17 pub use rustc::middle::cfg::graphviz::{Node, Edge};
18 use rustc::middle::cfg::graphviz as cfg_dot;
21 use borrowck::{BorrowckCtxt, LoanPath};
23 use rustc::middle::cfg::{CFGIndex};
24 use rustc::middle::dataflow::{DataFlowOperator, DataFlowContext, EntryOrExit};
25 use rustc::middle::dataflow;
27 use std::borrow::IntoCow;
37 pub fn short_name(&self) -> &'static str {
46 pub struct DataflowLabeller<'a, 'tcx: 'a> {
47 pub inner: cfg_dot::LabelledCFG<'a, 'tcx>,
48 pub variants: Vec<Variant>,
49 pub borrowck_ctxt: &'a BorrowckCtxt<'a, 'tcx>,
50 pub analysis_data: &'a borrowck::AnalysisData<'a, 'tcx>,
53 impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> {
54 fn dataflow_for(&self, e: EntryOrExit, n: &Node<'a>) -> String {
56 debug!("dataflow_for({}, id={}) {}", e, id, self.variants);
57 let mut sets = "".to_string();
58 let mut seen_one = false;
59 for &variant in self.variants.iter() {
60 if seen_one { sets.push_str(" "); } else { seen_one = true; }
61 sets.push_str(variant.short_name());
63 sets.push_str(self.dataflow_for_variant(e, n, variant)[]);
68 fn dataflow_for_variant(&self, e: EntryOrExit, n: &Node, v: Variant) -> String {
71 Loans => self.dataflow_loans_for(e, cfgidx),
72 Moves => self.dataflow_moves_for(e, cfgidx),
73 Assigns => self.dataflow_assigns_for(e, cfgidx),
77 fn build_set<O:DataFlowOperator, F>(&self,
80 dfcx: &DataFlowContext<'a, 'tcx, O>,
81 mut to_lp: F) -> String where
82 F: FnMut(uint) -> Rc<LoanPath<'tcx>>,
84 let mut saw_some = false;
85 let mut set = "{".to_string();
86 dfcx.each_bit_for_node(e, cfgidx, |index| {
87 let lp = to_lp(index);
91 let loan_str = self.borrowck_ctxt.loan_path_to_string(&*lp);
92 set.push_str(loan_str[]);
100 fn dataflow_loans_for(&self, e: EntryOrExit, cfgidx: CFGIndex) -> String {
101 let dfcx = &self.analysis_data.loans;
102 let loan_index_to_path = |&mut: loan_index| {
103 let all_loans = &self.analysis_data.all_loans;
104 all_loans[loan_index].loan_path()
106 self.build_set(e, cfgidx, dfcx, loan_index_to_path)
109 fn dataflow_moves_for(&self, e: EntryOrExit, cfgidx: CFGIndex) -> String {
110 let dfcx = &self.analysis_data.move_data.dfcx_moves;
111 let move_index_to_path = |&mut: move_index| {
112 let move_data = &self.analysis_data.move_data.move_data;
113 let moves = move_data.moves.borrow();
114 let the_move = &(*moves)[move_index];
115 move_data.path_loan_path(the_move.path)
117 self.build_set(e, cfgidx, dfcx, move_index_to_path)
120 fn dataflow_assigns_for(&self, e: EntryOrExit, cfgidx: CFGIndex) -> String {
121 let dfcx = &self.analysis_data.move_data.dfcx_assign;
122 let assign_index_to_path = |&mut: assign_index| {
123 let move_data = &self.analysis_data.move_data.move_data;
124 let assignments = move_data.var_assignments.borrow();
125 let assignment = &(*assignments)[assign_index];
126 move_data.path_loan_path(assignment.path)
128 self.build_set(e, cfgidx, dfcx, assign_index_to_path)
132 impl<'a, 'tcx> dot::Labeller<'a, Node<'a>, Edge<'a>> for DataflowLabeller<'a, 'tcx> {
133 fn graph_id(&'a self) -> dot::Id<'a> { self.inner.graph_id() }
134 fn node_id(&'a self, n: &Node<'a>) -> dot::Id<'a> { self.inner.node_id(n) }
135 fn node_label(&'a self, n: &Node<'a>) -> dot::LabelText<'a> {
136 let prefix = self.dataflow_for(dataflow::Entry, n);
137 let suffix = self.dataflow_for(dataflow::Exit, n);
138 let inner_label = self.inner.node_label(n);
140 .prefix_line(dot::LabelText::LabelStr(prefix.into_cow()))
141 .suffix_line(dot::LabelText::LabelStr(suffix.into_cow()))
143 fn edge_label(&'a self, e: &Edge<'a>) -> dot::LabelText<'a> { self.inner.edge_label(e) }
146 impl<'a, 'tcx> dot::GraphWalk<'a, Node<'a>, Edge<'a>> for DataflowLabeller<'a, 'tcx> {
147 fn nodes(&'a self) -> dot::Nodes<'a, Node<'a>> { self.inner.nodes() }
148 fn edges(&'a self) -> dot::Edges<'a, Edge<'a>> { self.inner.edges() }
149 fn source(&'a self, edge: &Edge<'a>) -> Node<'a> { self.inner.source(edge) }
150 fn target(&'a self, edge: &Edge<'a>) -> Node<'a> { self.inner.target(edge) }