Skip to main content

luaur_code_gen/methods/
function_bytecode_summary_from_proto.rs

1use crate::records::function_bytecode_summary::FunctionBytecodeSummary;
2use crate::type_aliases::instruction_ir_builder::Instruction;
3use alloc::string::String;
4use core::ffi::c_char;
5use luaur_common::enums::luau_opcode::LuauOpcode;
6use luaur_common::macros::luau_insn_op::LUAU_INSN_OP;
7use luaur_vm::macros::getstr::getstr;
8
9impl FunctionBytecodeSummary {
10    pub fn from_proto(proto: *mut luaur_vm::records::proto::Proto, nesting_limit: u32) -> Self {
11        unsafe {
12            let source_ptr = getstr((*proto).source);
13            let source_cstr = core::ffi::CStr::from_ptr(source_ptr);
14            let mut source = source_cstr.to_string_lossy().into_owned();
15
16            // Strip leading '=' or '@' if present
17            if source.starts_with('=') || source.starts_with('@') {
18                source = source[1..].to_string();
19            } else {
20                source = "[string]".to_string();
21            }
22
23            let name = if !(*proto).debugname.is_null() {
24                let name_ptr = getstr((*proto).debugname);
25                core::ffi::CStr::from_ptr(name_ptr)
26                    .to_string_lossy()
27                    .into_owned()
28            } else {
29                String::new()
30            };
31
32            let line = (*proto).linedefined;
33
34            let mut summary = Self::new(source, name, line, nesting_limit);
35
36            let mut i: usize = 0;
37            while i < (*proto).sizecode as usize {
38                let insn: Instruction = *(*proto).code.add(i);
39                let op = LUAU_INSN_OP(insn) as u8;
40                summary.inc_count(0, op);
41                i += crate::functions::get_op_length::get_op_length(LuauOpcode::from(op)) as usize;
42            }
43
44            summary
45        }
46    }
47}