summaryrefslogtreecommitdiffstats
path: root/third_party/rust/cranelift-codegen/src/cfg_printer.rs
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /third_party/rust/cranelift-codegen/src/cfg_printer.rs
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'third_party/rust/cranelift-codegen/src/cfg_printer.rs')
-rw-r--r--third_party/rust/cranelift-codegen/src/cfg_printer.rs83
1 files changed, 83 insertions, 0 deletions
diff --git a/third_party/rust/cranelift-codegen/src/cfg_printer.rs b/third_party/rust/cranelift-codegen/src/cfg_printer.rs
new file mode 100644
index 0000000000..4ceae473b2
--- /dev/null
+++ b/third_party/rust/cranelift-codegen/src/cfg_printer.rs
@@ -0,0 +1,83 @@
+//! The `CFGPrinter` utility.
+
+use alloc::vec::Vec;
+use core::fmt::{Display, Formatter, Result, Write};
+
+use crate::entity::SecondaryMap;
+use crate::flowgraph::{BlockPredecessor, ControlFlowGraph};
+use crate::ir::Function;
+use crate::write::{FuncWriter, PlainWriter};
+
+/// A utility for pretty-printing the CFG of a `Function`.
+pub struct CFGPrinter<'a> {
+ func: &'a Function,
+ cfg: ControlFlowGraph,
+}
+
+/// A utility for pretty-printing the CFG of a `Function`.
+impl<'a> CFGPrinter<'a> {
+ /// Create a new CFGPrinter.
+ pub fn new(func: &'a Function) -> Self {
+ Self {
+ func,
+ cfg: ControlFlowGraph::with_function(func),
+ }
+ }
+
+ /// Write the CFG for this function to `w`.
+ pub fn write(&self, w: &mut dyn Write) -> Result {
+ self.header(w)?;
+ self.block_nodes(w)?;
+ self.cfg_connections(w)?;
+ writeln!(w, "}}")
+ }
+
+ fn header(&self, w: &mut dyn Write) -> Result {
+ writeln!(w, "digraph \"{}\" {{", self.func.name)?;
+ if let Some(entry) = self.func.layout.entry_block() {
+ writeln!(w, " {{rank=min; {}}}", entry)?;
+ }
+ Ok(())
+ }
+
+ fn block_nodes(&self, w: &mut dyn Write) -> Result {
+ let mut aliases = SecondaryMap::<_, Vec<_>>::new();
+ for v in self.func.dfg.values() {
+ // VADFS returns the immediate target of an alias
+ if let Some(k) = self.func.dfg.value_alias_dest_for_serialization(v) {
+ aliases[k].push(v);
+ }
+ }
+
+ for block in &self.func.layout {
+ write!(w, " {} [shape=record, label=\"{{", block)?;
+ crate::write::write_block_header(w, self.func, None, block, 4)?;
+ // Add all outgoing branch instructions to the label.
+ for inst in self.func.layout.block_likely_branches(block) {
+ write!(w, " | <{}>", inst)?;
+ PlainWriter.write_instruction(w, self.func, &aliases, None, inst, 0)?;
+ }
+ writeln!(w, "}}\"]")?
+ }
+ Ok(())
+ }
+
+ fn cfg_connections(&self, w: &mut dyn Write) -> Result {
+ for block in &self.func.layout {
+ for BlockPredecessor {
+ block: parent,
+ inst,
+ } in self.cfg.pred_iter(block)
+ {
+ writeln!(w, " {}:{} -> {}", parent, inst, block)?;
+ }
+ }
+ Ok(())
+ }
+}
+
+impl<'a> Display for CFGPrinter<'a> {
+ fn fmt(&self, f: &mut Formatter) -> Result {
+ self.write(f)
+ }
+}