Skip to main content

luaur_compile_cli/functions/
serialize_function_stats.rs

1// EXTERNAL_CRATE_REQUIRED: libc - provides FILE and fprintf for native CLI output
2use crate::macros::write_name::WRITE_NAME;
3use crate::macros::write_pair::WRITE_PAIR;
4use crate::macros::write_pair_string::WRITE_PAIR_STRING;
5use luaur_code_gen::records::function_stats::FunctionStats;
6
7pub fn serialize_function_stats(fp: *mut core::ffi::c_void, stats: &FunctionStats) {
8    unsafe {
9        extern "C" {
10            fn fprintf(
11                stream: *mut core::ffi::c_void,
12                format: *const core::ffi::c_char,
13                ...
14            ) -> core::ffi::c_int;
15        }
16
17        fprintf(fp, c"                {\n".as_ptr());
18
19        // The macros WRITE_PAIR_STRING, WRITE_PAIR, and WRITE_NAME are defined in this crate
20        // and they internally call libc::fprintf. Since we cannot rely on the 'libc' crate
21        // being linked, we must ensure the macros use the local extern "C" fprintf or
22        // we must provide a wrapper. However, the macros are already translated and
23        // fixed in the crate. Based on the example 'serializeBlockLinearizationStats',
24        // we define fprintf locally.
25
26        macro_rules! local_fprintf {
27            ($($arg:tt)*) => {
28                fprintf($($arg)*)
29            };
30        }
31
32        // We redefine the logic of the macros here to avoid the unresolved 'libc' dependency
33        // in the pre-translated macros, or we assume the environment provides a way to call it.
34        // Given the constraints and the failure, we will implement the serialization manually
35        // using the local fprintf to ensure it compiles.
36
37        fprintf(
38            fp,
39            c"                    \"name\": \"%s\",\n".as_ptr(),
40            stats.name.as_ptr(),
41        );
42        fprintf(
43            fp,
44            c"                    \"line\": %d,\n".as_ptr(),
45            stats.line,
46        );
47        fprintf(
48            fp,
49            c"                    \"bcode_count\": %u,\n".as_ptr(),
50            stats.bcode_count,
51        );
52        fprintf(
53            fp,
54            c"                    \"ir_count\": %u,\n".as_ptr(),
55            stats.ir_count,
56        );
57        fprintf(
58            fp,
59            c"                    \"asm_count\": %u,\n".as_ptr(),
60            stats.asm_count,
61        );
62        fprintf(
63            fp,
64            c"                    \"asm_size\": %u,\n".as_ptr(),
65            stats.asm_size,
66        );
67
68        fprintf(fp, c"                    \"bytecode_summary\": ".as_ptr());
69
70        let nesting_limit = stats.bytecode_summary.len();
71
72        if nesting_limit == 0 {
73            fprintf(fp, c"[]".as_ptr());
74        } else {
75            fprintf(fp, c"[\n".as_ptr());
76            for i in 0..nesting_limit {
77                let counts = &stats.bytecode_summary[i];
78                fprintf(fp, c"                        [".as_ptr());
79                for j in 0..counts.len() {
80                    fprintf(fp, c"%u".as_ptr(), counts[j]);
81                    if j < counts.len() - 1 {
82                        fprintf(fp, c", ".as_ptr());
83                    }
84                }
85                fprintf(fp, c"]".as_ptr());
86                if i < nesting_limit - 1 {
87                    fprintf(fp, c",\n".as_ptr());
88                }
89            }
90            fprintf(fp, c"\n                    ]".as_ptr());
91        }
92
93        fprintf(fp, c"\n                }".as_ptr());
94    }
95}