luaur_code_gen/functions/
build_entry_function_code_gen_a_64.rs1use crate::enums::address_kind_a_64::AddressKindA64;
2use crate::records::address_a_64::AddressA64;
3use crate::records::assembly_builder_a_64::AssemblyBuilderA64;
4use crate::records::entry_locations_code_gen_a_64::EntryLocations;
5use crate::records::register_a_64::RegisterA64;
6use crate::records::unwind_builder::UnwindBuilder;
7use luaur_vm::records::call_info::CallInfo as CallInfoRecord;
8use luaur_vm::records::lua_state::lua_State as lua_StateRecord;
9use luaur_vm::records::lua_t_value::lua_TValue as TValueRecord;
10use luaur_vm::records::proto::Proto as ProtoRecord;
11use luaur_vm::type_aliases::value::Value;
12
13fn mem(base: RegisterA64, data: i32) -> AddressA64 {
14 AddressA64 {
15 kind: AddressKindA64::imm,
16 base,
17 offset: RegisterA64::noreg,
18 data,
19 }
20}
21
22trait UnwindBuilderExt {
23 fn start_function(&mut self);
24 fn prologue_a_64(&mut self, prologue_size: u32, stack_size: u32, regs: &[RegisterA64]);
25 fn finish_function(&mut self, begin_offset: u32, end_offset: u32);
26}
27
28impl UnwindBuilderExt for UnwindBuilder {
29 fn start_function(&mut self) {}
30 fn prologue_a_64(&mut self, _prologue_size: u32, _stack_size: u32, _regs: &[RegisterA64]) {}
31 fn finish_function(&mut self, _begin_offset: u32, _end_offset: u32) {}
32}
33
34const SP: RegisterA64 = RegisterA64 {
35 bits: (31 << 3) | 0,
36};
37const X0: RegisterA64 = RegisterA64 { bits: (0 << 3) | 2 };
38const X1: RegisterA64 = RegisterA64 { bits: (1 << 3) | 2 };
39const X2: RegisterA64 = RegisterA64 { bits: (2 << 3) | 2 };
40const X3: RegisterA64 = RegisterA64 { bits: (3 << 3) | 2 };
41const X9: RegisterA64 = RegisterA64 { bits: (9 << 3) | 2 };
42const X19: RegisterA64 = RegisterA64 {
43 bits: (19 << 3) | 2,
44};
45const X20: RegisterA64 = RegisterA64 {
46 bits: (20 << 3) | 2,
47};
48const X21: RegisterA64 = RegisterA64 {
49 bits: (21 << 3) | 2,
50};
51const X22: RegisterA64 = RegisterA64 {
52 bits: (22 << 3) | 2,
53};
54const X23: RegisterA64 = RegisterA64 {
55 bits: (23 << 3) | 2,
56};
57const X24: RegisterA64 = RegisterA64 {
58 bits: (24 << 3) | 2,
59};
60const X25: RegisterA64 = RegisterA64 {
61 bits: (25 << 3) | 2,
62};
63const X29: RegisterA64 = RegisterA64 {
64 bits: (29 << 3) | 2,
65};
66const X30: RegisterA64 = RegisterA64 {
67 bits: (30 << 3) | 2,
68};
69
70const K_STACK_SIZE: u16 = 128;
71
72pub fn build_entry_function_assembly_builder_a_64_unwind_builder(
73 build: &mut AssemblyBuilderA64,
74 unwind: &mut UnwindBuilder,
75) -> EntryLocations {
76 let mut locations = EntryLocations::default();
77
78 locations.start = build.set_label();
79
80 build.sub_register_a_64_register_a_64_u16(SP, SP, K_STACK_SIZE);
81 build.stp(X29, X30, mem(SP, 0));
82
83 build.stp(X19, X20, mem(SP, 16));
84 build.stp(X21, X22, mem(SP, 32));
85 build.stp(X23, X24, mem(SP, 48));
86 build.str(X25, mem(SP, 64));
87
88 build.mov_register_a_64_register_a_64(X29, SP);
89
90 locations.prologueEnd = build.set_label();
91
92 let prologue_size =
93 build.get_label_offset(&locations.prologueEnd) - build.get_label_offset(&locations.start);
94
95 let r_state = X19;
96 let r_native_context = X20;
97 let r_global_state = X21;
98 let r_base = X22;
99 let r_constants = X23;
100 let r_code = X24;
101 let r_closure = X25;
102
103 build.mov_register_a_64_register_a_64(r_state, X0);
104 build.mov_register_a_64_register_a_64(r_native_context, X3);
105 build.ldr(
106 r_global_state,
107 mem(X0, core::mem::offset_of!(lua_StateRecord, global) as i32),
108 );
109 build.ldr(
110 r_base,
111 mem(X0, core::mem::offset_of!(lua_StateRecord, base) as i32),
112 );
113
114 build.ldp(
115 r_constants,
116 r_code,
117 mem(X1, core::mem::offset_of!(ProtoRecord, k) as i32),
118 );
119
120 build.ldr(
121 X9,
122 mem(X0, core::mem::offset_of!(lua_StateRecord, ci) as i32),
123 );
124 build.ldr(
125 X9,
126 mem(X9, core::mem::offset_of!(CallInfoRecord, func) as i32),
127 );
128 build.ldr(
129 r_closure,
130 mem(
131 X9,
132 core::mem::offset_of!(TValueRecord, value) as i32
133 + core::mem::offset_of!(Value, gc) as i32,
134 ),
135 );
136
137 build.br(X2);
138
139 locations.epilogueStart = build.set_label();
140
141 build.ldr(X25, mem(SP, 64));
142 build.ldp(X23, X24, mem(SP, 48));
143 build.ldp(X21, X22, mem(SP, 32));
144 build.ldp(X19, X20, mem(SP, 16));
145 build.ldp(X29, X30, mem(SP, 0));
146 build.add_register_a_64_register_a_64_u16(SP, SP, K_STACK_SIZE);
147
148 build.ret();
149
150 unwind.start_function();
151 unwind.prologue_a_64(
152 prologue_size as u32,
153 K_STACK_SIZE as u32,
154 &[X29, X30, X19, X20, X21, X22, X23, X24, X25],
155 );
156 unwind.finish_function(build.get_label_offset(&locations.start), 0xffffffff);
157
158 locations
159}