Skip to main content

luaur_code_gen/records/
native_module.rs

1//! Source: `CodeGen/include/Luau/SharedCodeAllocator.h:34-90`
2
3use crate::functions::get_native_proto_exec_data_header_native_proto_exec_data::get_native_proto_exec_data_header_mut;
4use crate::macros::codegen_assert::CODEGEN_ASSERT;
5use crate::records::code_allocation_data::CodeAllocationData;
6use crate::records::shared_code_allocator::SharedCodeAllocator;
7use crate::type_aliases::module_id::ModuleId;
8use crate::type_aliases::native_proto_exec_data_ptr::NativeProtoExecDataPtr;
9use alloc::vec::Vec;
10use core::sync::atomic::AtomicUsize;
11
12#[derive(Debug)]
13pub struct NativeModule {
14    pub(crate) refcount: AtomicUsize,
15    pub(crate) allocator: *mut SharedCodeAllocator,
16    pub(crate) module_id: Option<ModuleId>,
17    pub(crate) module_base_address_deprecated: *const u8,
18    pub(crate) code_allocation_data: CodeAllocationData,
19    pub(crate) native_protos: Vec<NativeProtoExecDataPtr>,
20}
21
22impl NativeModule {
23    pub fn native_module_shared_code_allocator_optional_module_id_u8_vector_native_proto_exec_data_ptr(
24        allocator: *mut SharedCodeAllocator,
25        module_id: &Option<ModuleId>,
26        module_base_address: *const u8,
27        native_protos: Vec<NativeProtoExecDataPtr>,
28    ) -> Self {
29        use luaur_common::FFlag;
30
31        CODEGEN_ASSERT!(!FFlag::LuauCodegenFreeBlocks.get());
32        CODEGEN_ASSERT!(!allocator.is_null());
33        CODEGEN_ASSERT!(!module_base_address.is_null());
34
35        let mut result = Self {
36            refcount: AtomicUsize::new(0),
37            allocator,
38            module_id: *module_id,
39            module_base_address_deprecated: module_base_address,
40            code_allocation_data: CodeAllocationData::default(),
41            native_protos,
42        };
43
44        result.bind_native_protos(module_base_address);
45        result
46    }
47
48    pub fn native_module_shared_code_allocator_optional_module_id_code_allocation_data_vector_native_proto_exec_data_ptr(
49        allocator: *mut SharedCodeAllocator,
50        module_id: &Option<ModuleId>,
51        code_allocation_data: CodeAllocationData,
52        native_protos: Vec<NativeProtoExecDataPtr>,
53    ) -> Self {
54        use luaur_common::FFlag;
55
56        CODEGEN_ASSERT!(FFlag::LuauCodegenFreeBlocks.get());
57        CODEGEN_ASSERT!(!allocator.is_null());
58        CODEGEN_ASSERT!(!code_allocation_data.start.is_null());
59
60        let mut result = Self {
61            refcount: AtomicUsize::new(0),
62            allocator,
63            module_id: *module_id,
64            module_base_address_deprecated: core::ptr::null(),
65            code_allocation_data,
66            native_protos,
67        };
68
69        result.bind_native_protos(code_allocation_data.code_start);
70        result
71    }
72
73    fn bind_native_protos(&mut self, code_base: *const u8) {
74        let native_module = self as *mut NativeModule;
75
76        for native_proto in &self.native_protos {
77            unsafe {
78                let header = get_native_proto_exec_data_header_mut(native_proto.as_ptr());
79                (*header).native_module = native_module;
80                (*header).entry_offset_or_address =
81                    code_base.add((*header).entry_offset_or_address as usize);
82            }
83        }
84
85        self.native_protos.sort_by_key(|native_proto| unsafe {
86            (*get_native_proto_exec_data_header_mut(native_proto.as_ptr())).bytecode_id
87        });
88
89        for pair in self.native_protos.windows(2) {
90            unsafe {
91                let left = (*get_native_proto_exec_data_header_mut(pair[0].as_ptr())).bytecode_id;
92                let right = (*get_native_proto_exec_data_header_mut(pair[1].as_ptr())).bytecode_id;
93                CODEGEN_ASSERT!(left != right);
94            }
95        }
96    }
97}