Skip to main content

luaur_code_gen/methods/
unwind_builder_win_finish_function.rs

1use crate::macros::codegen_assert::CODEGEN_ASSERT;
2use crate::records::unwind_builder_win::UnwindBuilderWin;
3use crate::records::unwind_code_win::UnwindCodeWin;
4use crate::records::unwind_info_win::UnwindInfoWin;
5
6impl UnwindBuilderWin {
7    pub fn finish_function(&mut self, begin_offset: u32, end_offset: u32) {
8        let last = self
9            .unwind_functions
10            .last_mut()
11            .expect("finish_function without start_function");
12        last.begin_offset = begin_offset;
13        last.end_offset = end_offset;
14
15        CODEGEN_ASSERT!(self.unwind_codes.len() < 256);
16
17        let mut info = UnwindInfoWin::default();
18        info.set_version(1);
19        info.set_flags(0);
20        info.prologsize = self.prolog_size;
21        info.unwindcodecount = self.unwind_codes.len() as u8;
22
23        CODEGEN_ASSERT!(self.frame_reg.index() < 16);
24        info.set_framereg(self.frame_reg.index());
25
26        CODEGEN_ASSERT!(self.frame_reg_offset < 16);
27        info.set_frameregoff(self.frame_reg_offset);
28
29        unsafe {
30            let raw_end = self
31                .raw_data
32                .as_mut_ptr()
33                .add(UnwindBuilderWin::kRawDataLimit as usize);
34            CODEGEN_ASSERT!(
35                self.raw_data_pos.add(core::mem::size_of::<UnwindInfoWin>()) <= raw_end
36            );
37
38            core::ptr::copy_nonoverlapping(
39                &info as *const UnwindInfoWin as *const u8,
40                self.raw_data_pos,
41                core::mem::size_of::<UnwindInfoWin>(),
42            );
43            self.raw_data_pos = self.raw_data_pos.add(core::mem::size_of::<UnwindInfoWin>());
44
45            if !self.unwind_codes.is_empty() {
46                let mut unwind_code_pos = self
47                    .raw_data_pos
48                    .add(core::mem::size_of::<UnwindCodeWin>() * (self.unwind_codes.len() - 1));
49                CODEGEN_ASSERT!(unwind_code_pos <= raw_end);
50
51                for code in &self.unwind_codes {
52                    core::ptr::copy_nonoverlapping(
53                        code as *const UnwindCodeWin as *const u8,
54                        unwind_code_pos,
55                        core::mem::size_of::<UnwindCodeWin>(),
56                    );
57                    unwind_code_pos = unwind_code_pos.sub(core::mem::size_of::<UnwindCodeWin>());
58                }
59            }
60
61            self.raw_data_pos = self
62                .raw_data_pos
63                .add(core::mem::size_of::<UnwindCodeWin>() * self.unwind_codes.len());
64
65            if self.unwind_codes.len() % 2 != 0 {
66                self.raw_data_pos = self.raw_data_pos.add(core::mem::size_of::<UnwindCodeWin>());
67            }
68
69            CODEGEN_ASSERT!(self.raw_data_pos <= raw_end);
70        }
71    }
72}