1 //! The `CFGPrinter` utility. 2 3 use alloc::vec::Vec; 4 use core::fmt::{Display, Formatter, Result, Write}; 5 6 use crate::entity::SecondaryMap; 7 use crate::flowgraph::{BlockPredecessor, ControlFlowGraph}; 8 use crate::ir::Function; 9 use crate::write::{FuncWriter, PlainWriter}; 10 11 /// A utility for pretty-printing the CFG of a `Function`. 12 pub struct CFGPrinter<'a> { 13 func: &'a Function, 14 cfg: ControlFlowGraph, 15 } 16 17 /// A utility for pretty-printing the CFG of a `Function`. 18 impl<'a> CFGPrinter<'a> { 19 /// Create a new CFGPrinter. 20 pub fn new(func: &'a Function) -> Self { 21 Self { 22 func, 23 cfg: ControlFlowGraph::with_function(func), 24 } 25 } 26 27 /// Write the CFG for this function to `w`. 28 pub fn write(&self, w: &mut dyn Write) -> Result { 29 self.header(w)?; 30 self.block_nodes(w)?; 31 self.cfg_connections(w)?; 32 writeln!(w, "}}") 33 } 34 35 fn header(&self, w: &mut dyn Write) -> Result { 36 writeln!(w, "digraph \"{}\" {{", self.func.name)?; 37 if let Some(entry) = self.func.layout.entry_block() { 38 writeln!(w, " {{rank=min; {entry}}}")?; 39 } 40 Ok(()) 41 } 42 43 fn block_nodes(&self, w: &mut dyn Write) -> Result { 44 let mut aliases = SecondaryMap::<_, Vec<_>>::new(); 45 for v in self.func.dfg.values() { 46 // VADFS returns the immediate target of an alias 47 if let Some(k) = self.func.dfg.value_alias_dest_for_serialization(v) { 48 aliases[k].push(v); 49 } 50 } 51 52 for block in &self.func.layout { 53 write!(w, " {block} [shape=record, label=\"{{")?; 54 crate::write::write_block_header(w, self.func, block, 4)?; 55 // Add all outgoing branch instructions to the label. 56 if let Some(inst) = self.func.layout.last_inst(block) { 57 write!(w, " | <{inst}>")?; 58 PlainWriter.write_instruction(w, self.func, &aliases, inst, 0)?; 59 } 60 writeln!(w, "}}\"]")? 61 } 62 Ok(()) 63 } 64 65 fn cfg_connections(&self, w: &mut dyn Write) -> Result { 66 for block in &self.func.layout { 67 for BlockPredecessor { 68 block: parent, 69 inst, 70 } in self.cfg.pred_iter(block) 71 { 72 writeln!(w, " {parent}:{inst} -> {block}")?; 73 } 74 } 75 Ok(()) 76 } 77 } 78 79 impl<'a> Display for CFGPrinter<'a> { 80 fn fmt(&self, f: &mut Formatter) -> Result { 81 self.write(f) 82 } 83 } 84