luaur-code-gen 0.1.3

Native (A64/X64) code generation for Luau (Rust).
Documentation
use crate::macros::codegen_assert::CODEGEN_ASSERT;
use crate::records::unwind_builder_win::UnwindBuilderWin;
use crate::records::unwind_code_win::UnwindCodeWin;
use crate::records::unwind_info_win::UnwindInfoWin;

impl UnwindBuilderWin {
    pub fn finish_function(&mut self, begin_offset: u32, end_offset: u32) {
        let last = self
            .unwind_functions
            .last_mut()
            .expect("finish_function without start_function");
        last.begin_offset = begin_offset;
        last.end_offset = end_offset;

        CODEGEN_ASSERT!(self.unwind_codes.len() < 256);

        let mut info = UnwindInfoWin::default();
        info.set_version(1);
        info.set_flags(0);
        info.prologsize = self.prolog_size;
        info.unwindcodecount = self.unwind_codes.len() as u8;

        CODEGEN_ASSERT!(self.frame_reg.index() < 16);
        info.set_framereg(self.frame_reg.index());

        CODEGEN_ASSERT!(self.frame_reg_offset < 16);
        info.set_frameregoff(self.frame_reg_offset);

        unsafe {
            let raw_end = self
                .raw_data
                .as_mut_ptr()
                .add(UnwindBuilderWin::kRawDataLimit as usize);
            CODEGEN_ASSERT!(
                self.raw_data_pos.add(core::mem::size_of::<UnwindInfoWin>()) <= raw_end
            );

            core::ptr::copy_nonoverlapping(
                &info as *const UnwindInfoWin as *const u8,
                self.raw_data_pos,
                core::mem::size_of::<UnwindInfoWin>(),
            );
            self.raw_data_pos = self.raw_data_pos.add(core::mem::size_of::<UnwindInfoWin>());

            if !self.unwind_codes.is_empty() {
                let mut unwind_code_pos = self
                    .raw_data_pos
                    .add(core::mem::size_of::<UnwindCodeWin>() * (self.unwind_codes.len() - 1));
                CODEGEN_ASSERT!(unwind_code_pos <= raw_end);

                for code in &self.unwind_codes {
                    core::ptr::copy_nonoverlapping(
                        code as *const UnwindCodeWin as *const u8,
                        unwind_code_pos,
                        core::mem::size_of::<UnwindCodeWin>(),
                    );
                    unwind_code_pos = unwind_code_pos.sub(core::mem::size_of::<UnwindCodeWin>());
                }
            }

            self.raw_data_pos = self
                .raw_data_pos
                .add(core::mem::size_of::<UnwindCodeWin>() * self.unwind_codes.len());

            if self.unwind_codes.len() % 2 != 0 {
                self.raw_data_pos = self.raw_data_pos.add(core::mem::size_of::<UnwindCodeWin>());
            }

            CODEGEN_ASSERT!(self.raw_data_pos <= raw_end);
        }
    }
}