luaur_compiler/methods/
compiler_compile_export_table.rs1use crate::functions::sref_compiler::sref_ast_name;
2use crate::records::compile_error::CompileError;
3use crate::records::compiler::Compiler;
4use luaur_bytecode::methods::bytecode_builder_get_string_hash::bytecode_builder_get_string_hash;
5use luaur_common::enums::luau_opcode::LuauOpcode;
6use luaur_common::macros::luau_assert::LUAU_ASSERT;
7
8const K_DEFAULT_ALLOC_PC: u32 = !0u32;
9
10fn get_import_id_2(id0: i32, id1: i32) -> u32 {
11 LUAU_ASSERT!(((id0 | id1) as u32) < 1024);
12 (2u32 << 30) | ((id0 as u32) << 20) | ((id1 as u32) << 10)
13}
14
15impl Compiler {
16 pub fn compile_export_table(&mut self) {
17 LUAU_ASSERT!(!self.exported_locals.is_empty() || !self.exported_classes.is_empty());
18 LUAU_ASSERT!(!self.current_function.is_null());
19
20 let export_local = &mut self.export_table_local as *mut _;
21
22 if !self.locals.contains(&export_local) {
23 let table_reg = self.alloc_reg(self.current_function as *mut _, 1);
24 let hash_size = Compiler::encode_hash_size(
25 (self.exported_locals.len() + self.exported_classes.len()) as u32,
26 );
27
28 unsafe {
29 (*self.bytecode).emit_abc(LuauOpcode::LOP_NEWTABLE, table_reg, hash_size, 0);
30 (*self.bytecode).emit_aux(0);
31 }
32
33 self.push_local(export_local, table_reg, K_DEFAULT_ALLOC_PC);
34 }
35
36 let loc_node = self.current_function;
37 let table_reg = self.get_local_reg(export_local);
38 LUAU_ASSERT!(table_reg >= 0);
39 let table_reg = table_reg as u8;
40
41 if luaur_common::FFlag::DebugLuauUserDefinedClasses.get() {
42 let exported_classes = self.exported_classes.clone();
43 for (class_name, class_reg) in exported_classes {
44 let class_name_ref = sref_ast_name(class_name);
45 let class_name_cid =
46 unsafe { (*self.bytecode).add_constant_string(class_name_ref) };
47 if class_name_cid < 0 {
48 unsafe {
49 CompileError::raise(
50 &(*loc_node).base.base.location,
51 format_args!("Exceeded constant limit; simplify the code to compile"),
52 );
53 }
54 }
55
56 unsafe {
57 (*self.bytecode).emit_abc(
58 LuauOpcode::LOP_SETTABLEKS,
59 class_reg,
60 table_reg,
61 bytecode_builder_get_string_hash(class_name_ref) as u8,
62 );
63 (*self.bytecode).emit_aux(class_name_cid as u32);
64 }
65 }
66 }
67
68 let freeze_reg = self.alloc_reg(loc_node as *mut _, 2);
69 let freeze_name = unsafe { (*self.names).get_or_add_c_str(c"freeze".as_ptr()) };
70 let freeze_cid =
71 unsafe { (*self.bytecode).add_constant_string(sref_ast_name(freeze_name)) };
72 if freeze_cid < 0 {
73 unsafe {
74 CompileError::raise(
75 &(*loc_node).base.base.location,
76 format_args!("Exceeded constant limit; simplify the code to compile"),
77 );
78 }
79 }
80
81 let table_name = unsafe { (*self.names).get_or_add_c_str(c"table".as_ptr()) };
82 let table_cid = unsafe { (*self.bytecode).add_constant_string(sref_ast_name(table_name)) };
83 if table_cid < 0 {
84 unsafe {
85 CompileError::raise(
86 &(*loc_node).base.base.location,
87 format_args!("Exceeded constant limit; simplify the code to compile"),
88 );
89 }
90 }
91
92 let iid = get_import_id_2(table_cid, freeze_cid);
93 let cid = unsafe { (*self.bytecode).add_import(iid) };
94
95 if cid >= 0 && cid < 32768 {
96 unsafe {
97 (*self.bytecode).emit_ad(LuauOpcode::LOP_GETIMPORT, freeze_reg, cid as i16);
98 (*self.bytecode).emit_aux(iid);
99 }
100 } else {
101 unsafe {
102 CompileError::raise(
103 &(*loc_node).base.base.location,
104 format_args!("Exceeded constant limit; simplify the code to compile"),
105 );
106 }
107 }
108
109 unsafe {
110 (*self.bytecode).emit_abc(LuauOpcode::LOP_MOVE, freeze_reg + 1, table_reg, 0);
111 (*self.bytecode).emit_abc(LuauOpcode::LOP_CALL, freeze_reg, 2, 2);
112 }
113
114 self.close_locals(0);
115 unsafe {
116 (*self.bytecode).emit_abc(LuauOpcode::LOP_RETURN, freeze_reg, 2, 0);
117 }
118 }
119}