luaur_code_gen/functions/
to_dot_dj_graph.rs1extern crate alloc;
2
3use crate::enums::ir_block_kind::IrBlockKind;
4use crate::functions::append::append;
5use crate::functions::dom_children::dom_children;
6use crate::functions::successors::successors;
7use crate::functions::to_string_ir_dump_alt_c::to_string_ir_to_string_context_ir_block_u32 as to_string_block;
8use crate::records::ir_function::IrFunction;
9use crate::records::ir_to_string_context::ir_to_string_context;
10use alloc::string::String;
11use core::ffi::c_void;
12
13pub fn to_dot_dj_graph(function: &IrFunction) -> String {
14 let mut result = String::new();
15
16 {
17 let mut ctx = ir_to_string_context {
18 result: &mut result,
19 blocks: &function.blocks,
20 constants: &function.constants,
21 cfg: &function.cfg,
22 vm_exit_info: &function.vm_exit_info,
23 proto: function.proto as *mut c_void,
24 };
25
26 ctx.result.push_str("digraph CFG {\n");
27
28 for i in 0..function.blocks.len() {
29 let block = function.blocks[i];
30
31 append(&mut ctx.result, format_args!("b{} [", i as u32));
32
33 if block.kind == IrBlockKind::Fallback {
34 append(
35 &mut ctx.result,
36 format_args!("style=filled;fillcolor=salmon;"),
37 );
38 } else if block.kind == IrBlockKind::Bytecode {
39 append(
40 &mut ctx.result,
41 format_args!("style=filled;fillcolor=palegreen;"),
42 );
43 }
44
45 ctx.result.push_str("label=\"");
46 to_string_block(&mut ctx, &block, i as u32);
47 ctx.result.push_str("\"];\n");
48 }
49
50 let cfg = ctx.cfg;
51
52 let mut depth: u32 = 0;
54 let mut found = true;
55
56 while found {
57 found = false;
58
59 ctx.result.push_str("{rank = same;");
60 for i in 0..cfg.dom_ordering.len() {
61 if cfg.dom_ordering[i].depth == depth {
62 append(&mut ctx.result, format_args!("b{};", i as u32));
63 found = true;
64 }
65 }
66 ctx.result.push_str("}\n");
67
68 depth += 1;
69 }
70
71 for i in 0..cfg.dom_children_offsets.len() {
72 let dom = dom_children(cfg, i as u32);
73
74 for target in dom {
75 append(
76 &mut ctx.result,
77 format_args!("b{} -> b{};\n", i as u32, target),
78 );
79 }
80
81 let succ = successors(cfg, i as u32);
83
84 for successor in succ {
85 let mut found_edge = false;
86
87 for target in dom {
88 if target == successor {
89 found_edge = true;
90 break;
91 }
92 }
93
94 if !found_edge {
95 append(
96 &mut ctx.result,
97 format_args!("b{} -> b{} [style=dotted];\n", i as u32, successor),
98 );
99 }
100 }
101 }
102
103 ctx.result.push_str("}\n");
104 }
105
106 result
107}