1use crate::{
4 common_decl::{MachineState, MachineValue, RegisterIndex},
5 location::{CombinedRegister, Reg as AbstractReg},
6};
7use std::collections::BTreeMap;
8use std::slice::Iter;
9use wasmer_types::target::CallingConvention;
10use wasmer_types::{CompileError, Type};
11
12#[repr(u8)]
14#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
15#[allow(clippy::upper_case_acronyms)]
16pub enum GPR {
17 X0 = 0,
18 X1 = 1,
19 X2 = 2,
20 X3 = 3,
21 X4 = 4,
22 X5 = 5,
23 X6 = 6,
24 X7 = 7,
25 X8 = 8,
26 X9 = 9,
27 X10 = 10,
28 X11 = 11,
29 X12 = 12,
30 X13 = 13,
31 X14 = 14,
32 X15 = 15,
33 X16 = 16,
34 X17 = 17,
35 X18 = 18,
36 X19 = 19,
37 X20 = 20,
38 X21 = 21,
39 X22 = 22,
40 X23 = 23,
41 X24 = 24,
42 X25 = 25,
43 X26 = 26,
44 X27 = 27,
45 X28 = 28,
46 X29 = 29,
47 X30 = 30,
48 XzrSp = 31,
49}
50
51impl From<GPR> for u8 {
52 fn from(val: GPR) -> Self {
53 val as u8
54 }
55}
56
57#[repr(u8)]
59#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
60#[allow(dead_code)]
61#[allow(clippy::upper_case_acronyms)]
62pub enum NEON {
63 V0 = 0,
64 V1 = 1,
65 V2 = 2,
66 V3 = 3,
67 V4 = 4,
68 V5 = 5,
69 V6 = 6,
70 V7 = 7,
71 V8 = 8,
72 V9 = 9,
73 V10 = 10,
74 V11 = 11,
75 V12 = 12,
76 V13 = 13,
77 V14 = 14,
78 V15 = 15,
79 V16 = 16,
80 V17 = 17,
81 V18 = 18,
82 V19 = 19,
83 V20 = 20,
84 V21 = 21,
85 V22 = 22,
86 V23 = 23,
87 V24 = 24,
88 V25 = 25,
89 V26 = 26,
90 V27 = 27,
91 V28 = 28,
92 V29 = 29,
93 V30 = 30,
94 V31 = 31,
95}
96
97impl From<NEON> for u8 {
98 fn from(val: NEON) -> Self {
99 val as u8
100 }
101}
102
103impl AbstractReg for GPR {
104 fn is_callee_save(self) -> bool {
105 self as usize > 18
106 }
107 fn is_reserved(self) -> bool {
108 !matches!(self.into_index(), 0..=16 | 19..=27)
109 }
110 fn into_index(self) -> usize {
111 self as usize
112 }
113 fn from_index(n: usize) -> Result<GPR, ()> {
114 match n {
115 0..=31 => Ok(*GPR::iterator().nth(n).unwrap()),
116 _ => Err(()),
117 }
118 }
119 fn iterator() -> Iter<'static, GPR> {
120 static GPRS: [GPR; 32] = [
121 GPR::X0,
122 GPR::X1,
123 GPR::X2,
124 GPR::X3,
125 GPR::X4,
126 GPR::X5,
127 GPR::X6,
128 GPR::X7,
129 GPR::X8,
130 GPR::X9,
131 GPR::X10,
132 GPR::X11,
133 GPR::X12,
134 GPR::X13,
135 GPR::X14,
136 GPR::X15,
137 GPR::X16,
138 GPR::X17,
139 GPR::X18,
140 GPR::X19,
141 GPR::X20,
142 GPR::X21,
143 GPR::X22,
144 GPR::X23,
145 GPR::X24,
146 GPR::X25,
147 GPR::X26,
148 GPR::X27,
149 GPR::X28,
150 GPR::X29,
151 GPR::X30,
152 GPR::XzrSp,
153 ];
154 GPRS.iter()
155 }
156 #[cfg(feature = "unwind")]
157 fn to_dwarf(self) -> gimli::Register {
158 use gimli::AArch64;
159
160 match self {
161 GPR::X0 => AArch64::X0,
162 GPR::X1 => AArch64::X1,
163 GPR::X2 => AArch64::X2,
164 GPR::X3 => AArch64::X3,
165 GPR::X4 => AArch64::X4,
166 GPR::X5 => AArch64::X5,
167 GPR::X6 => AArch64::X6,
168 GPR::X7 => AArch64::X7,
169 GPR::X8 => AArch64::X8,
170 GPR::X9 => AArch64::X9,
171 GPR::X10 => AArch64::X10,
172 GPR::X11 => AArch64::X11,
173 GPR::X12 => AArch64::X12,
174 GPR::X13 => AArch64::X13,
175 GPR::X14 => AArch64::X14,
176 GPR::X15 => AArch64::X15,
177 GPR::X16 => AArch64::X16,
178 GPR::X17 => AArch64::X17,
179 GPR::X18 => AArch64::X18,
180 GPR::X19 => AArch64::X19,
181 GPR::X20 => AArch64::X20,
182 GPR::X21 => AArch64::X21,
183 GPR::X22 => AArch64::X22,
184 GPR::X23 => AArch64::X23,
185 GPR::X24 => AArch64::X24,
186 GPR::X25 => AArch64::X25,
187 GPR::X26 => AArch64::X26,
188 GPR::X27 => AArch64::X27,
189 GPR::X28 => AArch64::X28,
190 GPR::X29 => AArch64::X29,
191 GPR::X30 => AArch64::X30,
192 GPR::XzrSp => AArch64::SP,
193 }
194 }
195}
196
197impl AbstractReg for NEON {
198 fn is_callee_save(self) -> bool {
199 self as usize > 16
200 }
201 fn is_reserved(self) -> bool {
202 false
203 }
204 fn into_index(self) -> usize {
205 self as usize
206 }
207 fn from_index(n: usize) -> Result<NEON, ()> {
208 match n {
209 0..=31 => Ok(*NEON::iterator().nth(n).unwrap()),
210 _ => Err(()),
211 }
212 }
213 fn iterator() -> Iter<'static, NEON> {
214 const NEONS: [NEON; 32] = [
215 NEON::V0,
216 NEON::V1,
217 NEON::V2,
218 NEON::V3,
219 NEON::V4,
220 NEON::V5,
221 NEON::V6,
222 NEON::V7,
223 NEON::V8,
224 NEON::V9,
225 NEON::V10,
226 NEON::V11,
227 NEON::V12,
228 NEON::V13,
229 NEON::V14,
230 NEON::V15,
231 NEON::V16,
232 NEON::V17,
233 NEON::V18,
234 NEON::V19,
235 NEON::V20,
236 NEON::V21,
237 NEON::V22,
238 NEON::V23,
239 NEON::V24,
240 NEON::V25,
241 NEON::V26,
242 NEON::V27,
243 NEON::V28,
244 NEON::V29,
245 NEON::V30,
246 NEON::V31,
247 ];
248 NEONS.iter()
249 }
250 #[cfg(feature = "unwind")]
251 fn to_dwarf(self) -> gimli::Register {
252 use gimli::AArch64;
253
254 match self {
255 NEON::V0 => AArch64::V0,
256 NEON::V1 => AArch64::V1,
257 NEON::V2 => AArch64::V2,
258 NEON::V3 => AArch64::V3,
259 NEON::V4 => AArch64::V4,
260 NEON::V5 => AArch64::V5,
261 NEON::V6 => AArch64::V6,
262 NEON::V7 => AArch64::V7,
263 NEON::V8 => AArch64::V8,
264 NEON::V9 => AArch64::V9,
265 NEON::V10 => AArch64::V10,
266 NEON::V11 => AArch64::V11,
267 NEON::V12 => AArch64::V12,
268 NEON::V13 => AArch64::V13,
269 NEON::V14 => AArch64::V14,
270 NEON::V15 => AArch64::V15,
271 NEON::V16 => AArch64::V16,
272 NEON::V17 => AArch64::V17,
273 NEON::V18 => AArch64::V18,
274 NEON::V19 => AArch64::V19,
275 NEON::V20 => AArch64::V20,
276 NEON::V21 => AArch64::V21,
277 NEON::V22 => AArch64::V22,
278 NEON::V23 => AArch64::V23,
279 NEON::V24 => AArch64::V24,
280 NEON::V25 => AArch64::V25,
281 NEON::V26 => AArch64::V26,
282 NEON::V27 => AArch64::V27,
283 NEON::V28 => AArch64::V28,
284 NEON::V29 => AArch64::V29,
285 NEON::V30 => AArch64::V30,
286 NEON::V31 => AArch64::V31,
287 }
288 }
289}
290
291#[derive(Copy, Clone, Debug, Eq, PartialEq)]
293#[allow(clippy::upper_case_acronyms)]
294pub enum ARM64Register {
295 GPR(GPR),
297 NEON(NEON),
299}
300
301impl CombinedRegister for ARM64Register {
302 fn to_index(&self) -> RegisterIndex {
304 match *self {
305 ARM64Register::GPR(x) => RegisterIndex(x as usize),
306 ARM64Register::NEON(x) => RegisterIndex(x as usize + 64),
307 }
308 }
309 fn from_gpr(x: u16) -> Self {
311 ARM64Register::GPR(GPR::from_index(x as usize).unwrap())
312 }
313 fn from_simd(x: u16) -> Self {
315 ARM64Register::NEON(NEON::from_index(x as usize).unwrap())
316 }
317}
318
319#[derive(Default)]
321pub struct ArgumentRegisterAllocator {
322 n_gprs: usize,
323 n_neons: usize,
324}
325
326impl ArgumentRegisterAllocator {
327 pub fn next(
329 &mut self,
330 ty: Type,
331 calling_convention: CallingConvention,
332 ) -> Result<Option<ARM64Register>, CompileError> {
333 let ret = match calling_convention {
334 CallingConvention::SystemV | CallingConvention::AppleAarch64 => {
335 static GPR_SEQ: &[GPR] = &[
336 GPR::X0,
337 GPR::X1,
338 GPR::X2,
339 GPR::X3,
340 GPR::X4,
341 GPR::X5,
342 GPR::X6,
343 GPR::X7,
344 ];
345 static NEON_SEQ: &[NEON] = &[
346 NEON::V0,
347 NEON::V1,
348 NEON::V2,
349 NEON::V3,
350 NEON::V4,
351 NEON::V5,
352 NEON::V6,
353 NEON::V7,
354 ];
355 match ty {
356 Type::I32 | Type::I64 => {
357 if self.n_gprs < GPR_SEQ.len() {
358 let gpr = GPR_SEQ[self.n_gprs];
359 self.n_gprs += 1;
360 Some(ARM64Register::GPR(gpr))
361 } else {
362 None
363 }
364 }
365 Type::F32 | Type::F64 => {
366 if self.n_neons < NEON_SEQ.len() {
367 let neon = NEON_SEQ[self.n_neons];
368 self.n_neons += 1;
369 Some(ARM64Register::NEON(neon))
370 } else {
371 None
372 }
373 }
374 _ => {
375 return Err(CompileError::Codegen(format!(
376 "No register available for {calling_convention:?} and type {ty}"
377 )));
378 }
379 }
380 }
381 _ => {
382 return Err(CompileError::Codegen(format!(
383 "No register available for {calling_convention:?} and type {ty}"
384 )));
385 }
386 };
387
388 Ok(ret)
389 }
390}
391
392pub fn new_machine_state() -> MachineState {
394 MachineState {
395 stack_values: vec![],
396 register_values: vec![MachineValue::Undefined; 32 + 32],
397 prev_frame: BTreeMap::new(),
398 wasm_stack: vec![],
399 wasm_inst_offset: usize::MAX,
400 }
401}