Skip to content

Commit

Permalink
Compute control flow graph once per function
Browse files Browse the repository at this point in the history
  • Loading branch information
k0aki committed Aug 14, 2023
1 parent 25c1429 commit 9a80406
Show file tree
Hide file tree
Showing 3 changed files with 26 additions and 16 deletions.
11 changes: 6 additions & 5 deletions crates/ir/src/graphviz/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,26 +9,27 @@ use super::function::DUMMY_BLOCK;
#[derive(Debug, Clone, Copy)]
pub(super) struct BlockNode<'a> {
pub(super) func: &'a Function,
pub(super) cfg: &'a ControlFlowGraph,
pub(super) block: Block,
}

impl<'a> BlockNode<'a> {
pub(super) fn new(func: &'a Function, block: Block) -> Self {
Self { func, block }
pub(super) fn new(func: &'a Function, cfg: &'a ControlFlowGraph, block: Block) -> Self {
Self { func, cfg, block }
}

pub(super) fn succs(self) -> Vec<Self> {
let mut cfg = ControlFlowGraph::new();
cfg.compute(self.func);
cfg.succs_of(self.block)
.map(|block| BlockNode::new(self.func, *block))
.map(|block| BlockNode::new(self.func, self.cfg, *block))
.collect()
}
}

impl<'a> BlockNode<'a> {
pub(super) fn label(self) -> label::Text<'static> {
let Self { block, func } = self;
let Self { block, cfg, func } = self;
let Function {
sig, dfg, layout, ..
} = func;
Expand All @@ -50,7 +51,7 @@ impl<'a> BlockNode<'a> {
// Write block body.
write!(label, r#"<tr><td align="left" balign="left">"#).unwrap();
for insn in layout.iter_insn(self.block) {
let display_insn = DisplayInsn::new(insn, dfg);
let display_insn = DisplayInsn::new(insn, func);
let mut insn_string = String::new();
write!(&mut insn_string, "{}", display_insn).unwrap();

Expand Down
25 changes: 16 additions & 9 deletions crates/ir/src/graphviz/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,25 @@ use super::block::BlockNode;

pub(super) const DUMMY_BLOCK: Block = Block(u32::MAX);

pub(super) struct FunctionGraph<'a>(pub(super) &'a Function);
pub(super) struct FunctionGraph<'a> {
func: &'a Function,
cfg: &'a ControlFlowGraph,
}

impl<'a> FunctionGraph<'a> {
pub fn new(func: &'a Function, cfg: &'a ControlFlowGraph) -> Self {
Self { func, cfg }
}
}

impl<'a> FunctionGraph<'a> {
pub(super) fn blocks(&self) -> Vec<BlockNode<'a>> {
let Self(func) = *self;
let mut cfg = ControlFlowGraph::new();
cfg.compute(func);
let Self { func, cfg } = self;
// Dummy block is needed to label the graph with the function signature. Returns a vector
// with the dummy block as a last element.
cfg.post_order()
.map(|block| BlockNode::new(func, block))
.chain(iter::once(BlockNode::new(func, DUMMY_BLOCK)))
.map(|block| BlockNode::new(func, cfg, block))
.chain(iter::once(BlockNode::new(func, cfg, DUMMY_BLOCK)))
.collect()
}
}
Expand All @@ -30,7 +37,7 @@ impl<'a> Labeller<'a> for FunctionGraph<'a> {
type Subgraph = ();

fn graph_id(&self) -> dot2::Result<Id<'a>> {
let Self(func) = *self;
let Self { func, cfg } = *self;
let sig_name = func.sig.name().to_string();
Id::new(sig_name)
}
Expand Down Expand Up @@ -74,13 +81,13 @@ impl<'a> GraphWalk<'a> for FunctionGraph<'a> {
}

fn edges(&'a self) -> dot2::Edges<'a, Self::Edge> {
let Self(func) = *self;
let Self { func, cfg } = self;
let mut blocks = self.blocks();

let dummy_block = blocks.pop().unwrap();
let mut edges = vec![BlockEdge {
from: dummy_block,
to: BlockNode::new(func, Block(0u32)),
to: BlockNode::new(func, cfg, Block(0u32)),
func,
}];
for block in blocks {
Expand Down
6 changes: 4 additions & 2 deletions crates/ir/src/graphviz/mod.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
use std::io;

use crate::Function;
use crate::{ControlFlowGraph, Function};

mod block;
mod function;

use function::FunctionGraph;

pub fn render_to<W: io::Write>(func: &Function, output: &mut W) -> io::Result<()> {
let func_graph = FunctionGraph(func);
let mut cfg = ControlFlowGraph::new();
cfg.compute(func);
let func_graph = FunctionGraph::new(func, &cfg);
dot2::render(&func_graph, output).map_err(|err| match err {
dot2::Error::Io(err) => err,
_ => panic!("invalid graphviz id"),
Expand Down

0 comments on commit 9a80406

Please sign in to comment.