Skip to main content

luaur_code_gen/methods/
ir_lowering_a_64_finish_function.rs

1use crate::enums::code_gen_counter::CodeGenCounter;
2use crate::enums::kind_a_64::KindA64;
3use crate::records::ir_lowering_a_64::IrLoweringA64;
4use crate::records::register_a_64::RegisterA64;
5use crate::type_aliases::instruction_ir_builder::Instruction;
6
7const K_VM_EXIT_ENTRY_GUARD_PC: u32 = (1u32 << 28) - 1;
8
9const fn reg(kind: KindA64, index: u8) -> RegisterA64 {
10    RegisterA64 {
11        bits: kind as u8 | (index << 3),
12    }
13}
14
15const X0: RegisterA64 = reg(KindA64::x, 0);
16const X1: RegisterA64 = reg(KindA64::x, 1);
17
18impl IrLoweringA64 {
19    pub fn ir_lowering_a_64_finish_function(&mut self) {
20        unsafe {
21            if (*self.build).log_text {
22                (*self.build).log_append(format_args!("; interrupt handlers\n"));
23            }
24
25            for i in 0..self.interrupt_handlers.len() {
26                let mut handler = self.interrupt_handlers[i];
27                (*self.build).set_label_label(&mut handler.self_);
28                (*self.build).mov_register_a_64_i32(
29                    X0,
30                    ((handler.pcpos + 1) * core::mem::size_of::<Instruction>() as u32) as i32,
31                );
32                (*self.build).adr_register_a_64_label(X1, &mut handler.next);
33                (*self.build).b_label(&mut (*self.helpers).interrupt);
34            }
35
36            if (*self.build).log_text {
37                (*self.build).log_append(format_args!("; exit handlers\n"));
38            }
39
40            for i in 0..self.exit_handlers.len() {
41                let mut handler = self.exit_handlers[i];
42                if handler.pcpos == K_VM_EXIT_ENTRY_GUARD_PC {
43                    (*self.build).set_label_label(&mut handler.self_);
44
45                    self.ir_lowering_a_64_alloc_and_increment_counter_at(
46                        CodeGenCounter::VmExitTaken,
47                        !0u32,
48                    );
49
50                    (*self.build).b_label(&mut (*self.helpers).exitContinueVmClearNativeFlag);
51                } else {
52                    (*self.build).set_label_label(&mut handler.self_);
53
54                    self.ir_lowering_a_64_alloc_and_increment_counter_at(
55                        CodeGenCounter::VmExitTaken,
56                        handler.pcpos,
57                    );
58
59                    (*self.build).mov_register_a_64_i32(
60                        X0,
61                        (handler.pcpos * core::mem::size_of::<Instruction>() as u32) as i32,
62                    );
63                    (*self.build).b_label(&mut (*self.helpers).updatePcAndContinueInVm);
64                }
65            }
66
67            let end = (*self.build).set_label();
68            (*self.function).end_location = (*self.build).get_label_offset(&end);
69            (*self.build).udf();
70
71            if !self.stats.is_null() {
72                if (*self).error {
73                    (*self.stats).lowering_errors += 1;
74                }
75
76                if self.regs.error {
77                    (*self.stats).reg_alloc_errors += 1;
78                }
79            }
80        }
81    }
82}