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}