mincaml
mincaml copied to clipboard
Generate graphviz for lowered program
Here's an example .dot generated by rustc:
cfg.dot
digraph __crate__ {
subgraph cluster_Mir_0_4 {
graph [fontname="monospace"];
node [fontname="monospace"];
edge [fontname="monospace"];
label=<fn foo::{{closure}}#0(_1: &[[email protected]:2:15: 2:22], _2: u64) -> ()<br align="left"/>>;
bb0__0_4 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">0</td></tr><tr><td align="left" balign="left">_0 = const ()<br/></td></tr><tr><td align="left">return</td></tr></table>>];
}
subgraph cluster_Mir_0_5 {
graph [fontname="monospace"];
node [fontname="monospace"];
edge [fontname="monospace"];
label=<fn main() -> ()<br align="left"/>let mut _1: u64;<br align="left"/>let mut _2: std::ops::Range<i32>;<br align="left"/>let mut _3: std::ops::Range<i32>;<br align="left"/>let mut _4: std::ops::Range<i32>;<br align="left"/>let mut _5: i32;<br align="left"/>let mut _6: std::option::Option<i32>;<br align="left"/>let mut _7: &mut std::ops::Range<i32>;<br align="left"/>let mut _8: &mut std::ops::Range<i32>;<br align="left"/>let mut _9: isize;<br align="left"/>let _10: i32;<br align="left"/>let mut _11: i32;<br align="left"/>let _12: i32;<br align="left"/>let mut _13: u64;<br align="left"/>let mut _14: i32;<br align="left"/>let mut _15: (u64, bool);<br align="left"/>let _16: ();<br align="left"/>let mut _17: u64;<br align="left"/>debug x => _1;<br align="left"/>debug iter => _4;<br align="left"/>debug __next => _5;<br align="left"/>debug val => _10;<br align="left"/>debug i => _12;<br align="left"/>>;
bb0__0_5 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">0</td></tr><tr><td align="left" balign="left">StorageLive(_1)<br/>_1 = const 0u64<br/>StorageLive(_2)<br/>StorageLive(_3)<br/>(_3.0: i32) = const 0i32<br/>(_3.1: i32) = const 100i32<br/></td></tr><tr><td align="left">_2 = const <std::ops::Range<i32> as std::iter::IntoIterator>::into_iter(move _3)</td></tr></table>>];
bb1__0_5 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">1</td></tr><tr><td align="left" balign="left">StorageDead(_3)<br/>StorageLive(_4)<br/>_4 = move _2<br/></td></tr><tr><td align="left">goto</td></tr></table>>];
bb2__0_5 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">2</td></tr><tr><td align="left" balign="left">StorageLive(_5)<br/>StorageLive(_6)<br/>StorageLive(_7)<br/>StorageLive(_8)<br/>_8 = &mut _4<br/>_7 = move _8<br/></td></tr><tr><td align="left">_6 = const <std::ops::Range<i32> as std::iter::Iterator>::next(move _7)</td></tr></table>>];
bb3__0_5 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">3</td></tr><tr><td align="left" balign="left">StorageDead(_7)<br/>_9 = discriminant(_6)<br/></td></tr><tr><td align="left">switchInt(move _9)</td></tr></table>>];
bb4__0_5 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">4</td></tr><tr><td align="left" balign="left">_0 = const ()<br/>StorageDead(_8)<br/>StorageDead(_6)<br/>StorageDead(_5)<br/>StorageDead(_4)<br/>StorageDead(_2)<br/>StorageDead(_1)<br/></td></tr><tr><td align="left">return</td></tr></table>>];
bb5__0_5 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">5</td></tr><tr><td align="left">unreachable</td></tr></table>>];
bb6__0_5 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">6</td></tr><tr><td align="left" balign="left">StorageLive(_10)<br/>_10 = ((_6 as Some).0: i32)<br/>StorageLive(_11)<br/>_11 = _10<br/>_5 = move _11<br/>StorageDead(_11)<br/>StorageDead(_10)<br/>StorageDead(_8)<br/>StorageDead(_6)<br/>StorageLive(_12)<br/>_12 = _5<br/>StorageLive(_13)<br/>StorageLive(_14)<br/>_14 = _12<br/>_13 = move _14 as u64 (Misc)<br/>StorageDead(_14)<br/>_15 = CheckedAdd(_1, move _13)<br/></td></tr><tr><td align="left">assert(!move (_15.1: bool), "attempt to add with overflow")</td></tr></table>>];
bb7__0_5 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">7</td></tr><tr><td align="left" balign="left">_1 = move (_15.0: u64)<br/>StorageDead(_13)<br/>StorageLive(_16)<br/>StorageLive(_17)<br/>_17 = _1<br/></td></tr><tr><td align="left">_16 = const foo(move _17)</td></tr></table>>];
bb8__0_5 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">8</td></tr><tr><td align="left" balign="left">StorageDead(_17)<br/>StorageDead(_16)<br/>StorageDead(_12)<br/>StorageDead(_5)<br/></td></tr><tr><td align="left">goto</td></tr></table>>];
bb0__0_5 -> bb1__0_5 [label="return"];
bb1__0_5 -> bb2__0_5 [label=""];
bb2__0_5 -> bb3__0_5 [label="return"];
bb3__0_5 -> bb4__0_5 [label="0isize"];
bb3__0_5 -> bb6__0_5 [label="1isize"];
bb3__0_5 -> bb5__0_5 [label="otherwise"];
bb6__0_5 -> bb7__0_5 [label=""];
bb7__0_5 -> bb8__0_5 [label="return"];
bb8__0_5 -> bb2__0_5 [label=""];
}
subgraph cluster_Mir_0_3 {
graph [fontname="monospace"];
node [fontname="monospace"];
edge [fontname="monospace"];
label=<fn foo(_1: u64) -> ()<br align="left"/>let _2: [[email protected]:2:15: 2:22];<br align="left"/>let mut _3: ();<br align="left"/>let mut _4: &[[email protected]:2:15: 2:22];<br align="left"/>let mut _5: (u64,);<br align="left"/>let mut _6: u64;<br align="left"/>debug x => _1;<br align="left"/>debug bar => _2;<br align="left"/>>;
bb0__0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">0</td></tr><tr><td align="left" balign="left">StorageLive(_2)<br/>StorageLive(_3)<br/>StorageLive(_4)<br/>_4 = &_2<br/>StorageLive(_5)<br/>StorageLive(_6)<br/>_6 = _1<br/>(_5.0: u64) = move _6<br/></td></tr><tr><td align="left">_3 = const <[[email protected]:2:15: 2:22] as std::ops::Fn<(u64,)>>::call(move _4, move _5)</td></tr></table>>];
bb1__0_3 [shape="none", label=<<table border="0" cellborder="1" cellspacing="0"><tr><td bgcolor="gray" align="center" colspan="1">1</td></tr><tr><td align="left" balign="left">StorageDead(_6)<br/>StorageDead(_5)<br/>StorageDead(_4)<br/>StorageDead(_3)<br/>_0 = const ()<br/>StorageDead(_2)<br/></td></tr><tr><td align="left">return</td></tr></table>>];
bb0__0_3 -> bb1__0_3 [label="return"];
}
}
Rendered:

What does "lowered program" mean here?
It's been a while since I worked on this project so I don't remember all the details, but I think this refers to the IR before final code (assembly) generation in one of the branches (not in master branch, we use cranelift for code gen in master).
Oh ok, I was looking for any issues to get my hands dirty