luaur_bytecode/functions/
to_function_bytecode_bytecode_graph.rs1use crate::enums::bc_vm_const_kind::BcVmConstKind;
2use crate::records::bytecode_builder::BytecodeBuilder;
3use crate::records::comp_time_bytecode_graph_serializer::CompTimeBytecodeGraphSerializer;
4use crate::records::string_ref::StringRef;
5use crate::type_aliases::comp_time_bc_function::CompTimeBcFunction;
6use alloc::string::String;
7use alloc::vec::Vec;
8use luaur_common::macros::luau_assert::LUAU_ASSERT;
9
10fn string_ref(value: &str) -> StringRef {
11 StringRef {
12 data: value.as_ptr() as *const i8,
13 length: value.len(),
14 }
15}
16
17pub fn to_function_bytecode_bytecode_builder_comp_time_bc_function(
18 bcb: &mut BytecodeBuilder,
19 fn_: &mut CompTimeBcFunction,
20) -> String {
21 let function_id = bcb.begin_function(fn_.numparams, fn_.is_vararg);
22
23 if !fn_.debugname.is_empty() {
24 bcb.set_debug_function_name(string_ref(&fn_.debugname));
25 }
26
27 bcb.set_debug_function_line_defined(fn_.linedefined as i32);
28 bcb.set_function_type_info(fn_.type_info.clone());
29
30 for t in &fn_.upvalue_types {
31 bcb.push_upval_type_info(*t);
32 }
33
34 for upval in &fn_.upvalue_names {
35 bcb.push_debug_upval(string_ref(upval));
36 }
37
38 let mut consts: Vec<u16> = Vec::with_capacity(fn_.constants.len());
39
40 for c in &fn_.constants {
41 match c.kind {
42 BcVmConstKind::Nil => consts.push(bcb.add_constant_nil() as u16),
43 BcVmConstKind::Boolean => {
44 consts.push(bcb.add_constant_boolean(unsafe { c.value.valueBoolean }) as u16)
45 }
46 BcVmConstKind::Number => {
47 consts.push(bcb.add_constant_number(unsafe { c.value.valueNumber }) as u16)
48 }
49 BcVmConstKind::Vector => {
50 let value = unsafe { c.value.valueVector };
51 consts.push(bcb.add_constant_vector(value[0], value[1], value[2], value[3]) as u16);
52 }
53 BcVmConstKind::String => consts
54 .push(bcb.add_constant_string(string_ref(unsafe { c.value.valueString })) as u16),
55 BcVmConstKind::Import => {
56 consts.push(bcb.add_import(unsafe { c.value.valueImport }) as u16)
57 }
58 BcVmConstKind::Table => {
59 let value_table = unsafe { c.value.valueTable };
60 LUAU_ASSERT!(value_table < fn_.table_shapes.len() as u32);
61 consts.push(bcb.add_constant_table(&fn_.table_shapes[value_table as usize]) as u16);
62 }
63 BcVmConstKind::Closure => {
64 consts.push(bcb.add_constant_closure(unsafe { c.value.valueClosure }) as u16)
65 }
66 BcVmConstKind::Integer => {
67 consts.push(bcb.add_constant_integer(unsafe { c.value.valueInteger }) as u16)
68 }
69 }
70 }
71
72 for fid in &fn_.protos {
73 bcb.add_child_function(*fid);
74 }
75
76 let mut serializer = CompTimeBytecodeGraphSerializer::comp_time_bytecode_graph_serializer_comp_time_bytecode_graph_serializer(bcb, fn_, &mut consts);
77 let insns_pc = serializer.emit_bytecode();
78
79 for local in &fn_.local_types {
80 let startpc = if local.startpc < insns_pc.len() as u32 {
81 insns_pc[local.startpc as usize]
82 } else {
83 bcb.get_debug_pc()
84 };
85 let endpc = if local.endpc < insns_pc.len() as u32 {
86 insns_pc[local.endpc as usize]
87 } else {
88 bcb.get_debug_pc()
89 };
90 bcb.push_local_type_info(local.r#type, local.reg, startpc, endpc);
91 }
92
93 for local in &fn_.locals {
94 let startpc = if local.startpc < insns_pc.len() as u32 {
95 insns_pc[local.startpc as usize]
96 } else {
97 bcb.get_debug_pc()
98 };
99 let endpc = if local.endpc < insns_pc.len() as u32 {
100 insns_pc[local.endpc as usize]
101 } else {
102 bcb.get_debug_pc()
103 };
104 bcb.push_debug_local(string_ref(local.varname), local.reg, startpc, endpc);
105 }
106
107 bcb.fold_jumps();
108 bcb.expand_jumps();
109 bcb.end_function(fn_.maxstacksize, fn_.nups, fn_.flags);
110
111 if serializer.error() {
112 return String::new();
113 }
114
115 bcb.get_function_data(function_id)
116}