rapx/analysis/range/domain/constraint_graph/
debug.rs1
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}