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