Skip to main content

rapx/analysis/range/domain/constraint_graph/
debug.rs

1
2use super::ConstraintGraph;
3use crate::analysis::range::domain::domain::BasicOpKind;
4use crate::analysis::range::domain::domain::{ConstConvert, IntervalArithmetic};
5use crate::analysis::range::domain::symbolic_expr::IntervalTypeTrait;
6use rustc_middle::mir::Place;
7use std::collections::{HashMap, HashSet};
8use std::fmt::{Debug, Write};
9
10impl<'tcx, T> ConstraintGraph<'tcx, T>
11where
12    T: IntervalArithmetic + ConstConvert + Debug,
13{
14    pub fn to_dot(&self) -> String {
15        let mut dot = String::new();
16        writeln!(&mut dot, "digraph ConstraintGraph {{").unwrap();
17        writeln!(&mut dot, "    layout=neato;").unwrap();
18        writeln!(&mut dot, "    overlap=false;").unwrap();
19        writeln!(&mut dot, "    splines=true;").unwrap();
20        writeln!(&mut dot, "    sep=\"+1.0\";").unwrap();
21        writeln!(&mut dot, "    rankdir=TB;").unwrap();
22        writeln!(&mut dot, "    ranksep=1.8;").unwrap();
23        writeln!(&mut dot, "    nodesep=0.8;").unwrap();
24        writeln!(&mut dot, "    edge [len=2.0];").unwrap();
25        writeln!(&mut dot, "    node [fontname=\"Fira Code\"];").unwrap();
26        writeln!(&mut dot, "\n    // Variable Nodes").unwrap();
27        writeln!(&mut dot, "    subgraph cluster_vars {{").unwrap();
28        writeln!(&mut dot, "        rank=same;").unwrap();
29        for (place, _var_node) in &self.vars {
30            let place_id = format!("{:?}", place);
31            let label = format!("{:?}", place);
32            writeln!(
33                &mut dot,
34                "        \"{}\" [label=\"{}\", shape=ellipse, style=filled, fillcolor=lightblue, width=1.2, fixedsize=false];",
35                place_id, label
36            ).unwrap();
37        }
38        writeln!(&mut dot, "    }}").unwrap();
39
40        writeln!(&mut dot, "\n    // Operation Nodes").unwrap();
41        writeln!(&mut dot, "    subgraph cluster_ops {{").unwrap();
42        writeln!(&mut dot, "        rank=same;").unwrap();
43        for (op_idx, op) in self.oprs.iter().enumerate() {
44            let op_id = format!("op_{}", op_idx);
45            let label = match op {
46                BasicOpKind::Unary(o) => format!("Unary({:?})", o.op),
47                BasicOpKind::Binary(o) => format!("Binary({:?})", o.op),
48                BasicOpKind::Essa(_) => "Essa".to_string(),
49                BasicOpKind::ControlDep(_) => "ControlDep".to_string(),
50                BasicOpKind::Phi(_) => "Φ (Phi)".to_string(),
51                BasicOpKind::Use(_) => "Use".to_string(),
52                BasicOpKind::Call(c) => format!("Call({:?})", c.def_id),
53                BasicOpKind::Ref(r) => format!("Ref({:?})", r.borrowkind),
54                BasicOpKind::Aggregate(r) => format!("AggregateOp({:?})", r.unique_adt),
55            };
56            writeln!(
57                &mut dot,
58                "        \"{}\" [label=\"{}\", shape=box, style=filled, fillcolor=lightgrey, width=1.5, fixedsize=false];",
59                op_id, label
60            ).unwrap();
61        }
62        writeln!(&mut dot, "    }}").unwrap();
63
64        writeln!(&mut dot, "\n    // Definition Edges (op -> var)").unwrap();
65        for (place, op_idx) in &self.defmap {
66            writeln!(&mut dot, "    \"op_{}\" -> \"{:?}\";", op_idx, place).unwrap();
67        }
68
69        writeln!(&mut dot, "\n    // Use Edges (var -> op)").unwrap();
70        for (place, op_indices) in &self.usemap {
71            for op_idx in op_indices {
72                writeln!(&mut dot, "    \"{:?}\" -> \"op_{}\";", place, op_idx).unwrap();
73            }
74        }
75
76        writeln!(&mut dot, "\n    // Symbolic Bound Edges (var -> op)").unwrap();
77        for (place, op_indices) in &self.symbmap {
78            for op_idx in op_indices {
79                writeln!(
80                    &mut dot,
81                    "    \"{:?}\" -> \"op_{}\" [color=blue, style=dashed];",
82                    place, op_idx
83                ).unwrap();
84            }
85        }
86
87        writeln!(&mut dot, "}}").unwrap();
88        dot
89    }
90
91    pub fn print_vars(&self) {
92        for (&key, value) in &self.vars {
93            rap_trace!("Var: {:?}. {:?} ", key, value.get_range());
94        }
95    }
96
97    pub(crate) fn print_symbmap(&self) {
98        for (&key, value) in &self.symbmap {
99            for op in value.iter() {
100                if let Some(op) = self.oprs.get(*op) {
101                    rap_trace!("symbmap op: {:?}. {:?}\n ", key, op);
102                } else {
103                    rap_trace!("symbmap op: {:?} not found\n ", op);
104                }
105            }
106        }
107    }
108
109    pub(crate) fn print_defmap(&self) {
110        for (key, value) in self.defmap.clone() {
111            rap_trace!(
112                "place: {:?} def in stmt:{:?} {:?}",
113                key,
114                self.oprs[value].get_type_name(),
115                self.oprs[value].get_instruction()
116            );
117        }
118    }
119
120    pub(crate) fn print_compusemap(
121        &self,
122        component: &HashSet<&'tcx Place<'tcx>>,
123        comp_use_map: &HashMap<&'tcx Place<'tcx>, HashSet<usize>>,
124    ) {
125        for (key, value) in comp_use_map.clone() {
126            if component.contains(key) {
127                for v in value {
128                    rap_trace!(
129                        "compusemap place: {:?} use in stmt:{:?} {:?}",
130                        key,
131                        self.oprs[v].get_type_name(),
132                        self.oprs[v].get_instruction()
133                    );
134                }
135            }
136        }
137    }
138
139    pub(crate) fn print_usemap(&self) {
140        for (key, value) in self.usemap.clone() {
141            for v in value {
142                rap_trace!(
143                    "place: {:?} use in stmt:{:?} {:?}",
144                    key,
145                    self.oprs[v].get_type_name(),
146                    self.oprs[v].get_instruction()
147                );
148            }
149        }
150    }
151
152    pub(crate) fn print_symbexpr(&self) {
153        let mut vars: Vec<_> = self.vars.iter().collect();
154
155        vars.sort_by_key(|(local, _)| local.local.index());
156
157        for (&local, value) in vars {
158            rap_info!(
159                "Var: {:?}. [ {:?} , {:?} ]",
160                local,
161                value.interval.get_lower_expr(),
162                value.interval.get_upper_expr()
163            );
164        }
165    }
166}