Skip to content

Commit 7aa45ff

Browse files
committed
mk_graph: extend GraphBuilder to pass statements, terminators, and call args
1 parent cab4f95 commit 7aa45ff

3 files changed

Lines changed: 53 additions & 40 deletions

File tree

src/mk_graph/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use crate::printer::collect_smir;
1818
pub mod context;
1919
pub mod index;
2020
pub mod output;
21-
pub mod util;
2221
pub mod traverse;
22+
pub mod util;
2323

2424
// Re-exports for convenience
2525
pub use context::GraphContext;

src/mk_graph/output/d2.rs

Lines changed: 36 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
//! D2 diagram format output for MIR graphs.
22
33
extern crate stable_mir;
4-
use stable_mir::mir::TerminatorKind;
4+
use stable_mir::mir::{Operand, Statement, Terminator, TerminatorKind};
55

66
use crate::printer::SmirJson;
77
use crate::MonoItemKind;
@@ -11,24 +11,28 @@ use crate::mk_graph::util::{
1111
escape_d2, is_unqualified, name_lines, short_name, terminator_targets,
1212
};
1313

14-
use crate::mk_graph::traverse::GraphBuilder;
1514
use crate::mk_graph::traverse::render_graph;
15+
use crate::mk_graph::traverse::GraphBuilder;
1616

1717
// =============================================================================
1818
// D2 Builder
1919
// =============================================================================
2020

21-
struct D2Builder {
21+
pub struct D2Builder<'a> {
22+
ctx: &'a GraphContext,
2223
buf: String,
2324
}
2425

25-
impl D2Builder {
26-
fn new() -> Self {
27-
Self { buf: String::new() }
26+
impl<'a> D2Builder<'a> {
27+
pub fn new(ctx: &'a GraphContext) -> Self {
28+
Self {
29+
ctx,
30+
buf: String::new(),
31+
}
2832
}
2933
}
3034

31-
impl GraphBuilder for D2Builder {
35+
impl<'a> GraphBuilder for D2Builder<'a> {
3236
type Output = String;
3337

3438
fn begin_graph(&mut self, _name: &str) {
@@ -44,24 +48,28 @@ impl GraphBuilder for D2Builder {
4448
.map(|s| escape_d2(s))
4549
.collect::<Vec<_>>()
4650
.join("\\n");
47-
self.buf.push_str(&format!(" label: \"{}\"\n", legend_text));
51+
self.buf
52+
.push_str(&format!(" label: \"{}\"\n", legend_text));
4853
self.buf.push_str("}\n\n");
4954
}
5055

5156
fn type_legend(&mut self, _: &[String]) {}
5257

5358
fn begin_function(&mut self, id: &str, label: &str, _is_local: bool) {
5459
self.buf.push_str(&format!("{}: {{\n", id));
55-
self.buf.push_str(&format!(" label: \"{}\"\n", escape_d2(label)));
60+
self.buf
61+
.push_str(&format!(" label: \"{}\"\n", escape_d2(label)));
5662
self.buf.push_str(" style.fill: \"#e0e0ff\"\n");
5763
}
5864

59-
fn block( &mut self, _fn_id: &str, idx: usize, stmts: &[String], terminator: &str) {
65+
fn block(&mut self, _fn_id: &str, idx: usize, stmts: &[Statement], terminator: &Terminator) {
6066
let mut label = format!("bb{}:", idx);
6167
for stmt in stmts {
62-
label.push_str(&format!("\\n{}", escape_d2(stmt)));
68+
let s = self.ctx.render_stmt(stmt);
69+
label.push_str(&format!("\\n{}", escape_d2(&s)));
6370
}
64-
label.push_str(&format!("\\n---\\n{}", escape_d2(terminator)));
71+
let term_str = self.ctx.render_terminator(terminator);
72+
label.push_str(&format!("\\n---\\n{}", escape_d2(&term_str)));
6573

6674
self.buf.push_str(&format!(" bb{}: \"{}\"\n", idx, label));
6775
}
@@ -70,11 +78,20 @@ impl GraphBuilder for D2Builder {
7078
self.buf.push_str(&format!(" bb{} -> bb{}\n", from, to));
7179
}
7280

73-
fn call_edge(&mut self, fn_id: &str, block: usize, callee_id: &str, callee_name: &str) {
74-
self.buf.push_str(&format!("{}: \"{}\"\n", callee_id, escape_d2(callee_name)));
75-
self.buf.push_str(&format!("{}.style.fill: \"#ffe0e0\"\n", callee_id));
76-
self.buf.push_str(&format!("{}.bb{} -> {}: call\n", fn_id, block, callee_id
77-
));
81+
fn call_edge(
82+
&mut self,
83+
fn_id: &str,
84+
block: usize,
85+
callee_id: &str,
86+
callee_name: &str,
87+
_args: &[Operand],
88+
) {
89+
self.buf
90+
.push_str(&format!("{}: \"{}\"\n", callee_id, escape_d2(callee_name)));
91+
self.buf
92+
.push_str(&format!("{}.style.fill: \"#ffe0e0\"\n", callee_id));
93+
self.buf
94+
.push_str(&format!("{}.bb{} -> {}: call\n", fn_id, block, callee_id));
7895
}
7996

8097
fn end_function(&mut self, _id: &str) {
@@ -120,7 +137,8 @@ impl SmirJson<'_> {
120137

121138
/// Convert the MIR to D2 using GraphBuilder traversal (experimental)
122139
pub fn to_d2_file_new(&self) -> String {
123-
render_graph(self, D2Builder::new())
140+
let ctx = GraphContext::from_smir(self);
141+
render_graph(self, D2Builder::new(&ctx))
124142
}
125143
}
126144

src/mk_graph/traverse.rs

Lines changed: 16 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,13 @@
22
//!
33
//! This module owns the traversal order and graph semantics.
44
extern crate stable_mir;
5-
use stable_mir::mir::TerminatorKind;
5+
use stable_mir::mir::{Operand, Statement, Terminator, TerminatorKind};
66

77
use crate::printer::SmirJson;
88
use crate::MonoItemKind;
99

1010
use crate::mk_graph::context::GraphContext;
11-
use crate::mk_graph::util::{
12-
is_unqualified, name_lines, short_name, terminator_targets,
13-
};
11+
use crate::mk_graph::util::{is_unqualified, name_lines, short_name, terminator_targets};
1412

1513
/// Format agnostic graph sink.
1614
/// Implemented by all renderers.
@@ -25,11 +23,18 @@ pub trait GraphBuilder {
2523

2624
fn begin_function(&mut self, id: &str, label: &str, is_local: bool);
2725

28-
fn block(&mut self, fn_id: &str, idx: usize, stmts: &[String], terminator: &str);
26+
fn block(&mut self, fn_id: &str, idx: usize, stmts: &[Statement], terminator: &Terminator);
2927

3028
fn block_edge(&mut self, fn_id: &str, from: usize, to: usize, label: Option<&str>);
3129

32-
fn call_edge(&mut self, fn_id: &str, block: usize, callee_id: &str, callee_name: &str);
30+
fn call_edge(
31+
&mut self,
32+
fn_id: &str,
33+
block: usize,
34+
callee_id: &str,
35+
callee_name: &str,
36+
args: &[Operand],
37+
);
3338

3439
fn end_function(&mut self, id: &str);
3540

@@ -42,10 +47,7 @@ pub trait GraphBuilder {
4247

4348
/// Format-agnostic MIR graph traversal.
4449
/// Owns traversal order and graph semantics, delegates rendering to `GraphBuilder`.
45-
pub fn render_graph<B: GraphBuilder>(
46-
smir: &SmirJson,
47-
mut builder: B,
48-
) -> B::Output {
50+
pub fn render_graph<B: GraphBuilder>(smir: &SmirJson, mut builder: B) -> B::Output {
4951
let ctx = GraphContext::from_smir(smir);
5052

5153
builder.begin_graph(&smir.name);
@@ -89,15 +91,7 @@ fn render_function<B: GraphBuilder>(
8991
if let Some(body) = body {
9092
// blocks
9193
for (idx, block) in body.blocks.iter().enumerate() {
92-
let stmts = block
93-
.statements
94-
.iter()
95-
.map(|s| ctx.render_stmt(s))
96-
.collect::<Vec<_>>();
97-
98-
let term = ctx.render_terminator(&block.terminator);
99-
100-
builder.block(&fn_id, idx, &stmts, &term);
94+
builder.block(&fn_id, idx, &block.statements, &block.terminator);
10195
}
10296

10397
// CFG edges
@@ -113,7 +107,7 @@ fn render_function<B: GraphBuilder>(
113107
// Call edges (outside container)
114108
if let Some(body) = body {
115109
for (idx, block) in body.blocks.iter().enumerate() {
116-
let TerminatorKind::Call { func, .. } = &block.terminator.kind else {
110+
let TerminatorKind::Call { func, args, .. } = &block.terminator.kind else {
117111
continue;
118112
};
119113

@@ -126,7 +120,8 @@ fn render_function<B: GraphBuilder>(
126120
}
127121

128122
let callee_id = short_name(&callee_name);
129-
builder.call_edge(&fn_id, idx, &callee_id, &callee_name);
123+
124+
builder.call_edge(&fn_id, idx, &callee_id, &callee_name, args);
130125
}
131126
}
132127
}

0 commit comments

Comments
 (0)