Skip to main content

luaur_code_gen/functions/
init_header_functions_code_gen_a_64.rs

1use crate::enums::arch::Arch;
2use crate::functions::build_entry_function_code_gen_a_64::build_entry_function_assembly_builder_a_64_unwind_builder;
3use crate::macros::codegen_assert::CODEGEN_ASSERT;
4use crate::records::assembly_builder_a_64::AssemblyBuilderA64;
5use crate::records::base_code_gen_context::BaseCodeGenContext;
6use crate::records::unwind_builder::UnwindBuilder;
7use alloc::string::String;
8use alloc::vec::Vec;
9
10pub fn init_header_functions(code_gen_context: &mut BaseCodeGenContext) -> bool {
11    let mut build = AssemblyBuilderA64 {
12        data: Vec::new(),
13        code: Vec::new(),
14        text: String::new(),
15        log_text: false,
16        features: 0,
17        next_label: 1,
18        pending_labels: Vec::new(),
19        label_locations: Vec::new(),
20        finalized: false,
21        overflowed: false,
22        data_pos: 0,
23        code_pos: core::ptr::null_mut(),
24        code_end: core::ptr::null_mut(),
25    };
26    build.assembly_builder_a_64_assembly_builder_a_64(false, 0);
27
28    unsafe {
29        start_info(&mut *code_gen_context.unwind_builder, Arch::A64);
30    }
31
32    let entry_locations = unsafe {
33        build_entry_function_assembly_builder_a_64_unwind_builder(
34            &mut build,
35            &mut *code_gen_context.unwind_builder,
36        )
37    };
38
39    build.finalize();
40
41    unsafe {
42        finish_info(&mut *code_gen_context.unwind_builder);
43    }
44
45    CODEGEN_ASSERT!(build.data.is_empty());
46
47    let mut code_start: *mut u8 = core::ptr::null_mut();
48    let code_ptr = build.code.as_ptr().cast::<u8>();
49    let code_size = build.code.len() * core::mem::size_of::<u32>();
50
51    if luaur_common::FFlag::LuauCodegenFreeBlocks.get() {
52        code_gen_context.gate_allocation_data = code_gen_context.code_allocator.allocate(
53            build.data.as_ptr(),
54            build.data.len(),
55            code_ptr,
56            code_size,
57        );
58
59        if code_gen_context.gate_allocation_data.start.is_null() {
60            return false;
61        }
62
63        code_start = code_gen_context.gate_allocation_data.code_start;
64    } else if !code_gen_context.code_allocator.allocate_deprecated(
65        build.data.as_ptr(),
66        build.data.len(),
67        code_ptr,
68        code_size,
69        &mut code_gen_context.gate_data_deprecated,
70        &mut code_gen_context.gate_data_size_deprecated,
71        &mut code_start,
72    ) {
73        return false;
74    }
75
76    unsafe {
77        set_begin_offset(
78            &mut *code_gen_context.unwind_builder,
79            build.get_label_offset(&entry_locations.prologueEnd) as usize,
80        );
81
82        code_gen_context.context.gateEntry =
83            code_start.add(build.get_label_offset(&entry_locations.start) as usize);
84        code_gen_context.context.gateExit =
85            code_start.add(build.get_label_offset(&entry_locations.epilogueStart) as usize);
86    }
87
88    true
89}
90
91#[cfg(target_os = "windows")]
92unsafe fn start_info(unwind: &mut UnwindBuilder, arch: Arch) {
93    (&mut *(unwind as *mut UnwindBuilder)
94        .cast::<crate::records::unwind_builder_win::UnwindBuilderWin>())
95        .start_info(arch);
96}
97
98#[cfg(not(target_os = "windows"))]
99unsafe fn start_info(unwind: &mut UnwindBuilder, arch: Arch) {
100    (&mut *(unwind as *mut UnwindBuilder)
101        .cast::<crate::records::unwind_builder_dwarf_2::UnwindBuilderDwarf2>())
102        .start_info(arch);
103}
104
105#[cfg(target_os = "windows")]
106unsafe fn finish_info(unwind: &mut UnwindBuilder) {
107    (&mut *(unwind as *mut UnwindBuilder)
108        .cast::<crate::records::unwind_builder_win::UnwindBuilderWin>())
109        .finish_info();
110}
111
112#[cfg(not(target_os = "windows"))]
113unsafe fn finish_info(unwind: &mut UnwindBuilder) {
114    (&mut *(unwind as *mut UnwindBuilder)
115        .cast::<crate::records::unwind_builder_dwarf_2::UnwindBuilderDwarf2>())
116        .finish_info();
117}
118
119#[cfg(target_os = "windows")]
120unsafe fn set_begin_offset(unwind: &mut UnwindBuilder, begin_offset: usize) {
121    (&mut *(unwind as *mut UnwindBuilder)
122        .cast::<crate::records::unwind_builder_win::UnwindBuilderWin>())
123        .set_begin_offset(begin_offset);
124}
125
126#[cfg(not(target_os = "windows"))]
127unsafe fn set_begin_offset(unwind: &mut UnwindBuilder, begin_offset: usize) {
128    (&mut *(unwind as *mut UnwindBuilder)
129        .cast::<crate::records::unwind_builder_dwarf_2::UnwindBuilderDwarf2>())
130        .set_begin_offset(begin_offset);
131}