Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
bytecodealliance
GitHub Repository: bytecodealliance/wasmtime
Path: blob/main/cranelift/codegen/src/cfg_printer.rs
1693 views
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
85