Skip to main content

luaur_compiler/methods/
compiler_compile_export_table.rs

1use 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}