luaur_code_gen/methods/
ir_lowering_a_64_finish_function.rs1use 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}