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}