Skip to main content

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

1use super::ConstraintGraph;
2use crate::analysis::range::domain::domain::BasicOpKind;
3use crate::analysis::range::domain::domain::{ConstConvert, IntervalArithmetic};
4use crate::analysis::range::domain::symbolic_expr::IntervalTypeTrait;
5use rustc_middle::mir::Place;
6use std::collections::{HashMap, HashSet};
7use std::fmt::{Debug, Write};
8
9impl<'tcx, T> ConstraintGraph<'tcx, T>
10where
11    T: IntervalArithmetic + ConstConvert + Debug,
12{
13    pub fn to_dot(&self) -> String {
14        let mut dot = String::new();
15        writeln!(&mut dot, "digraph ConstraintGraph {{").unwrap();
16        writeln!(&mut dot, "    layout=neato;").unwrap();
17        writeln!(&mut dot, "    overlap=false;").unwrap();
18        writeln!(&mut dot, "    splines=true;").unwrap();
19        writeln!(&mut dot, "    sep=\"+1.0\";").unwrap();
20        writeln!(&mut dot, "    rankdir=TB;").unwrap();
21        writeln!(&mut dot, "    ranksep=1.8;").unwrap();
22        writeln!(&mut dot, "    nodesep=0.8;").unwrap();
23        writeln!(&mut dot, "    edge [len=2.0];").unwrap();
24        writeln!(&mut dot, "    node [fontname=\"Fira Code\"];").unwrap();
25        writeln!(&mut dot, "\n    // Variable Nodes").unwrap();
26        writeln!(&mut dot, "    subgraph cluster_vars {{").unwrap();
27        writeln!(&mut dot, "        rank=same;").unwrap();
28        for (place, _var_node) in &self.vars {
29            let place_id = format!("{:?}", place);
30            let label = format!("{:?}", place);
31            writeln!(
32                &mut dot,
33                "        \"{}\" [label=\"{}\", shape=ellipse, style=filled, fillcolor=lightblue, width=1.2, fixedsize=false];",
34                place_id, label
35            ).unwrap();
36        }
37        writeln!(&mut dot, "    }}").unwrap();
38
39        writeln!(&mut dot, "\n    // Operation Nodes").unwrap();
40        writeln!(&mut dot, "    subgraph cluster_ops {{").unwrap();
41        writeln!(&mut dot, "        rank=same;").unwrap();
42        for (op_idx, op) in self.oprs.iter().enumerate() {
43            let op_id = format!("op_{}", op_idx);
44            let label = match op {
45                BasicOpKind::Unary(o) => format!("Unary({:?})", o.op),
46                BasicOpKind::Binary(o) => format!("Binary({:?})", o.op),
47                BasicOpKind::Essa(_) => "Essa".to_string(),
48                BasicOpKind::ControlDep(_) => "ControlDep".to_string(),
49                BasicOpKind::Phi(_) => "Φ (Phi)".to_string(),
50                BasicOpKind::Use(_) => "Use".to_string(),
51                BasicOpKind::Call(c) => format!("Call({:?})", c.def_id),
52                BasicOpKind::Ref(r) => format!("Ref({:?})", r.borrowkind),
53                BasicOpKind::Aggregate(r) => format!("AggregateOp({:?})", r.unique_adt),
54            };
55            writeln!(
56                &mut dot,
57                "        \"{}\" [label=\"{}\", shape=box, style=filled, fillcolor=lightgrey, width=1.5, fixedsize=false];",
58                op_id, label
59            ).unwrap();
60        }
61        writeln!(&mut dot, "    }}").unwrap();
62
63        writeln!(&mut dot, "\n    // Definition Edges (op -> var)").unwrap();
64        for (place, op_idx) in &self.defmap {
65            writeln!(&mut dot, "    \"op_{}\" -> \"{:?}\";", op_idx, place).unwrap();
66        }
67
68        writeln!(&mut dot, "\n    // Use Edges (var -> op)").unwrap();
69        for (place, op_indices) in &self.usemap {
70            for op_idx in op_indices {
71                writeln!(&mut dot, "    \"{:?}\" -> \"op_{}\";", place, op_idx).unwrap();
72            }
73        }
74
75        writeln!(&mut dot, "\n    // Symbolic Bound Edges (var -> op)").unwrap();
76        for (place, op_indices) in &self.symbmap {
77            for op_idx in op_indices {
78                writeln!(
79                    &mut dot,
80                    "    \"{:?}\" -> \"op_{}\" [color=blue, style=dashed];",
81                    place, op_idx
82                )
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}