luaur_analysis/functions/
dump_cfg_json.rs1extern crate alloc;
2
3use crate::functions::dump_instruction::dump_instruction;
4use crate::functions::index_of_block::index_of_block;
5use crate::functions::json_escape::json_escape;
6use crate::records::control_flow_graph::ControlFlowGraph;
7use alloc::string::String;
8use alloc::vec;
9use alloc::vec::Vec;
10use core::fmt::Write;
11
12pub fn dump_cfg_json(cfg: &ControlFlowGraph) -> String {
13 let mut is_loop_header: Vec<bool> = vec![false; cfg.blocks.len()];
20 let mut is_backedge: Vec<bool> = vec![false; cfg.blocks.len()];
21 let mut backedges: Vec<(usize, usize)> = Vec::new(); for i in 0..cfg.blocks.len() {
23 unsafe {
24 for pred in (*cfg.blocks[i]).get_predecessors() {
25 let pred_idx = index_of_block(cfg, *pred);
26 if pred_idx > i {
27 is_loop_header[i] = true;
28 is_backedge[pred_idx] = true;
29 backedges.push((i, pred_idx));
30 }
31 }
32 }
33 }
34 let mut loop_depth: Vec<i32> = vec![0; cfg.blocks.len()];
35 for i in 0..cfg.blocks.len() {
36 for be in &backedges {
37 if be.0 <= i && i <= be.1 {
38 loop_depth[i] += 1;
39 }
40 }
41 }
42
43 let mut out = String::from(
44 "{\"functions\":[{\"name\":\"cfg\",\"passes\":[{\"name\":\"CFG\",\"mir\":{\"blocks\":[",
45 );
46
47 let mut next_instr_id: i32 = 1;
48 for i in 0..cfg.blocks.len() {
49 let block = cfg.blocks[i];
50 unsafe {
51 let block = &*block;
52 if i > 0 {
53 out.push(',');
54 }
55
56 let _ = write!(out, "{{\"number\":{}", i);
57 let _ = write!(out, ",\"loopDepth\":{}", loop_depth[i]);
58
59 out.push_str(",\"attributes\":[");
60 let mut first_attr = true;
61 if is_loop_header[i] {
62 out.push_str("\"loopheader\"");
63 first_attr = false;
64 }
65 if is_backedge[i] {
66 if !first_attr {
67 out.push(',');
68 }
69 out.push_str("\"backedge\"");
70 }
71 out.push(']');
72
73 out.push_str(",\"predecessors\":[");
74 let preds = block.get_predecessors();
75 for j in 0..preds.len() {
76 if j > 0 {
77 out.push(',');
78 }
79 let _ = write!(out, "{}", index_of_block(cfg, preds[j]));
80 }
81 out.push(']');
82
83 out.push_str(",\"successors\":[");
84 let succs = block.get_successors();
85 for j in 0..succs.len() {
86 if j > 0 {
87 out.push(',');
88 }
89 let _ = write!(out, "{}", index_of_block(cfg, succs[j]));
90 }
91 out.push(']');
92
93 out.push_str(",\"instructions\":[");
94 let instructions = block.get_instructions();
95 for j in 0..instructions.len() {
96 if j > 0 {
97 out.push(',');
98 }
99 let _ = write!(out, "{{\"id\":{}", next_instr_id);
100 next_instr_id += 1;
101 let _ = write!(
102 out,
103 ",\"opcode\":\"{}\"",
104 json_escape(&dump_instruction(instructions[j], &cfg.use_defs))
105 );
106 out.push_str(
107 ",\"attributes\":[],\"inputs\":[],\"uses\":[],\"memInputs\":[],\"type\":\"\"}",
108 );
109 }
110 out.push_str("]}");
111 }
112 }
113
114 out.push_str("]},\"lir\":{\"blocks\":[]}");
116 out.push_str("}]}]}");
118 out
119}