1747ad3c4Slazypassion //! The `CFGPrinter` utility.
2747ad3c4Slazypassion 
310e226f9Sbjorn3 use alloc::vec::Vec;
4*bb8fa40eSbjorn3 use core::fmt::{Display, Formatter, Result, Write};
5747ad3c4Slazypassion 
66042ee6fSbjorn3 use crate::entity::SecondaryMap;
7747ad3c4Slazypassion use crate::flowgraph::{BasicBlock, ControlFlowGraph};
8747ad3c4Slazypassion use crate::ir::Function;
96042ee6fSbjorn3 use crate::write::{FuncWriter, PlainWriter};
10747ad3c4Slazypassion 
11747ad3c4Slazypassion /// A utility for pretty-printing the CFG of a `Function`.
12747ad3c4Slazypassion pub struct CFGPrinter<'a> {
13747ad3c4Slazypassion     func: &'a Function,
14747ad3c4Slazypassion     cfg: ControlFlowGraph,
15747ad3c4Slazypassion }
16747ad3c4Slazypassion 
17747ad3c4Slazypassion /// A utility for pretty-printing the CFG of a `Function`.
18747ad3c4Slazypassion impl<'a> CFGPrinter<'a> {
19747ad3c4Slazypassion     /// Create a new CFGPrinter.
20747ad3c4Slazypassion     pub fn new(func: &'a Function) -> Self {
21747ad3c4Slazypassion         Self {
22747ad3c4Slazypassion             func,
23747ad3c4Slazypassion             cfg: ControlFlowGraph::with_function(func),
24747ad3c4Slazypassion         }
25747ad3c4Slazypassion     }
26747ad3c4Slazypassion 
27747ad3c4Slazypassion     /// Write the CFG for this function to `w`.
28d7d48d5cSBenjamin Bouvier     pub fn write(&self, w: &mut dyn Write) -> Result {
29747ad3c4Slazypassion         self.header(w)?;
30747ad3c4Slazypassion         self.ebb_nodes(w)?;
31747ad3c4Slazypassion         self.cfg_connections(w)?;
32747ad3c4Slazypassion         writeln!(w, "}}")
33747ad3c4Slazypassion     }
34747ad3c4Slazypassion 
35d7d48d5cSBenjamin Bouvier     fn header(&self, w: &mut dyn Write) -> Result {
36747ad3c4Slazypassion         writeln!(w, "digraph \"{}\" {{", self.func.name)?;
37747ad3c4Slazypassion         if let Some(entry) = self.func.layout.entry_block() {
38747ad3c4Slazypassion             writeln!(w, "    {{rank=min; {}}}", entry)?;
39747ad3c4Slazypassion         }
40747ad3c4Slazypassion         Ok(())
41747ad3c4Slazypassion     }
42747ad3c4Slazypassion 
43d7d48d5cSBenjamin Bouvier     fn ebb_nodes(&self, w: &mut dyn Write) -> Result {
446042ee6fSbjorn3         let mut aliases = SecondaryMap::<_, Vec<_>>::new();
456042ee6fSbjorn3         for v in self.func.dfg.values() {
466042ee6fSbjorn3             // VADFS returns the immediate target of an alias
476042ee6fSbjorn3             if let Some(k) = self.func.dfg.value_alias_dest_for_serialization(v) {
486042ee6fSbjorn3                 aliases[k].push(v);
496042ee6fSbjorn3             }
506042ee6fSbjorn3         }
516042ee6fSbjorn3 
52747ad3c4Slazypassion         for ebb in &self.func.layout {
536042ee6fSbjorn3             write!(w, "    {} [shape=record, label=\"{{", ebb)?;
546042ee6fSbjorn3             crate::write::write_ebb_header(w, self.func, None, ebb, 4)?;
55747ad3c4Slazypassion             // Add all outgoing branch instructions to the label.
56747ad3c4Slazypassion             for inst in self.func.layout.ebb_insts(ebb) {
576042ee6fSbjorn3                 write!(w, " | <{}>", inst)?;
586042ee6fSbjorn3                 PlainWriter.write_instruction(w, self.func, &aliases, None, inst, 0)?;
59747ad3c4Slazypassion             }
60747ad3c4Slazypassion             writeln!(w, "}}\"]")?
61747ad3c4Slazypassion         }
62747ad3c4Slazypassion         Ok(())
63747ad3c4Slazypassion     }
64747ad3c4Slazypassion 
65d7d48d5cSBenjamin Bouvier     fn cfg_connections(&self, w: &mut dyn Write) -> Result {
66747ad3c4Slazypassion         for ebb in &self.func.layout {
67747ad3c4Slazypassion             for BasicBlock { ebb: parent, inst } in self.cfg.pred_iter(ebb) {
68747ad3c4Slazypassion                 writeln!(w, "    {}:{} -> {}", parent, inst, ebb)?;
69747ad3c4Slazypassion             }
70747ad3c4Slazypassion         }
71747ad3c4Slazypassion         Ok(())
72747ad3c4Slazypassion     }
73747ad3c4Slazypassion }
74747ad3c4Slazypassion 
75747ad3c4Slazypassion impl<'a> Display for CFGPrinter<'a> {
76747ad3c4Slazypassion     fn fmt(&self, f: &mut Formatter) -> Result {
77747ad3c4Slazypassion         self.write(f)
78747ad3c4Slazypassion     }
79747ad3c4Slazypassion }
80