1#![allow(clippy::upper_case_acronyms)]
4use crate::common_decl::{MachineState, MachineValue, RegisterIndex};
5use crate::location::CombinedRegister;
6use crate::location::Reg as AbstractReg;
7use std::collections::BTreeMap;
8use std::slice::Iter;
9use wasmer_types::{CompileError, Type, target::CallingConvention};
10
11#[repr(u8)]
13#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
14pub enum GPR {
15 RAX = 0,
16 RCX = 1,
17 RDX = 2,
18 RBX = 3,
19 RSP = 4,
20 RBP = 5,
21 RSI = 6,
22 RDI = 7,
23 R8 = 8,
24 R9 = 9,
25 R10 = 10,
26 R11 = 11,
27 R12 = 12,
28 R13 = 13,
29 R14 = 14,
30 R15 = 15,
31}
32
33impl From<GPR> for u8 {
34 fn from(val: GPR) -> Self {
35 val as u8
36 }
37}
38
39#[repr(u8)]
41#[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
42#[allow(dead_code)]
43pub enum XMM {
44 XMM0 = 0,
45 XMM1 = 1,
46 XMM2 = 2,
47 XMM3 = 3,
48 XMM4 = 4,
49 XMM5 = 5,
50 XMM6 = 6,
51 XMM7 = 7,
52 XMM8 = 8,
53 XMM9 = 9,
54 XMM10 = 10,
55 XMM11 = 11,
56 XMM12 = 12,
57 XMM13 = 13,
58 XMM14 = 14,
59 XMM15 = 15,
60}
61
62impl From<XMM> for u8 {
63 fn from(val: XMM) -> Self {
64 val as u8
65 }
66}
67
68impl AbstractReg for GPR {
69 fn is_callee_save(self) -> bool {
70 const IS_CALLEE_SAVE: [bool; 16] = [
71 false, false, false, true, true, true, false, false, false, false, false, false, true,
72 true, true, true,
73 ];
74 IS_CALLEE_SAVE[self as usize]
75 }
76 fn is_reserved(self) -> bool {
77 self == GPR::RSP || self == GPR::RBP || self == GPR::R10 || self == GPR::R15
78 }
79 fn into_index(self) -> usize {
80 self as usize
81 }
82 fn from_index(n: usize) -> Result<GPR, ()> {
83 match n {
84 0..=15 => Ok(*GPR::iterator().nth(n).unwrap()),
85 _ => Err(()),
86 }
87 }
88 fn iterator() -> Iter<'static, GPR> {
89 static GPRS: [GPR; 16] = [
90 GPR::RAX,
91 GPR::RCX,
92 GPR::RDX,
93 GPR::RBX,
94 GPR::RSP,
95 GPR::RBP,
96 GPR::RSI,
97 GPR::RDI,
98 GPR::R8,
99 GPR::R9,
100 GPR::R10,
101 GPR::R11,
102 GPR::R12,
103 GPR::R13,
104 GPR::R14,
105 GPR::R15,
106 ];
107 GPRS.iter()
108 }
109 #[cfg(feature = "unwind")]
110 fn to_dwarf(self) -> gimli::Register {
111 use gimli::X86_64;
112
113 match self {
114 GPR::RAX => X86_64::RAX,
115 GPR::RCX => X86_64::RCX,
116 GPR::RDX => X86_64::RDX,
117 GPR::RBX => X86_64::RBX,
118 GPR::RSP => X86_64::RSP,
119 GPR::RBP => X86_64::RBP,
120 GPR::RSI => X86_64::RSI,
121 GPR::RDI => X86_64::RDI,
122 GPR::R8 => X86_64::R8,
123 GPR::R9 => X86_64::R9,
124 GPR::R10 => X86_64::R10,
125 GPR::R11 => X86_64::R11,
126 GPR::R12 => X86_64::R12,
127 GPR::R13 => X86_64::R13,
128 GPR::R14 => X86_64::R14,
129 GPR::R15 => X86_64::R15,
130 }
131 }
132}
133
134impl AbstractReg for XMM {
135 fn is_callee_save(self) -> bool {
136 const IS_CALLEE_SAVE: [bool; 16] = [
137 false, false, false, false, false, false, false, false, true, true, true, true, true,
138 true, true, true,
139 ];
140 IS_CALLEE_SAVE[self as usize]
141 }
142 fn is_reserved(self) -> bool {
143 false
144 }
145 fn into_index(self) -> usize {
146 self as usize
147 }
148 fn from_index(n: usize) -> Result<XMM, ()> {
149 match n {
150 0..=15 => Ok(*XMM::iterator().nth(n).unwrap()),
151 _ => Err(()),
152 }
153 }
154 fn iterator() -> Iter<'static, XMM> {
155 static XMMS: [XMM; 16] = [
156 XMM::XMM0,
157 XMM::XMM1,
158 XMM::XMM2,
159 XMM::XMM3,
160 XMM::XMM4,
161 XMM::XMM5,
162 XMM::XMM6,
163 XMM::XMM7,
164 XMM::XMM8,
165 XMM::XMM9,
166 XMM::XMM10,
167 XMM::XMM11,
168 XMM::XMM12,
169 XMM::XMM13,
170 XMM::XMM14,
171 XMM::XMM15,
172 ];
173 XMMS.iter()
174 }
175 #[cfg(feature = "unwind")]
176 fn to_dwarf(self) -> gimli::Register {
177 use gimli::X86_64;
178
179 match self {
180 XMM::XMM0 => X86_64::XMM0,
181 XMM::XMM1 => X86_64::XMM1,
182 XMM::XMM2 => X86_64::XMM2,
183 XMM::XMM3 => X86_64::XMM3,
184 XMM::XMM4 => X86_64::XMM4,
185 XMM::XMM5 => X86_64::XMM5,
186 XMM::XMM6 => X86_64::XMM6,
187 XMM::XMM7 => X86_64::XMM7,
188 XMM::XMM8 => X86_64::XMM8,
189 XMM::XMM9 => X86_64::XMM9,
190 XMM::XMM10 => X86_64::XMM10,
191 XMM::XMM11 => X86_64::XMM11,
192 XMM::XMM12 => X86_64::XMM12,
193 XMM::XMM13 => X86_64::XMM13,
194 XMM::XMM14 => X86_64::XMM14,
195 XMM::XMM15 => X86_64::XMM15,
196 }
197 }
198}
199
200#[derive(Copy, Clone, Debug, Eq, PartialEq)]
202pub enum X64Register {
203 GPR(GPR),
205 XMM(XMM),
207}
208
209impl CombinedRegister for X64Register {
210 fn to_index(&self) -> RegisterIndex {
212 match *self {
213 X64Register::GPR(x) => RegisterIndex(x as usize),
214 X64Register::XMM(x) => RegisterIndex(x as usize + 16),
215 }
216 }
217 fn from_gpr(x: u16) -> Self {
219 X64Register::GPR(GPR::from_index(x as usize).unwrap())
220 }
221 fn from_simd(x: u16) -> Self {
223 X64Register::XMM(XMM::from_index(x as usize).unwrap())
224 }
225
226 }
260
261#[derive(Default)]
263pub struct ArgumentRegisterAllocator {
264 n_gprs: usize,
265 n_xmms: usize,
266}
267
268impl ArgumentRegisterAllocator {
269 pub fn next(
271 &mut self,
272 ty: Type,
273 calling_convention: CallingConvention,
274 ) -> Result<Option<X64Register>, CompileError> {
275 let ret = match calling_convention {
276 CallingConvention::WindowsFastcall => {
277 static GPR_SEQ: &[GPR] = &[GPR::RCX, GPR::RDX, GPR::R8, GPR::R9];
278 static XMM_SEQ: &[XMM] = &[XMM::XMM0, XMM::XMM1, XMM::XMM2, XMM::XMM3];
279 let idx = self.n_gprs + self.n_xmms;
280 match ty {
281 Type::I32 | Type::I64 => {
282 if idx < 4 {
283 let gpr = GPR_SEQ[idx];
284 self.n_gprs += 1;
285 Some(X64Register::GPR(gpr))
286 } else {
287 None
288 }
289 }
290 Type::F32 | Type::F64 => {
291 if idx < 4 {
292 let xmm = XMM_SEQ[idx];
293 self.n_xmms += 1;
294 Some(X64Register::XMM(xmm))
295 } else {
296 None
297 }
298 }
299 _ => {
300 return Err(CompileError::Codegen(format!(
301 "No register available for {calling_convention:?} and type {ty}"
302 )));
303 }
304 }
305 }
306 _ => {
307 static GPR_SEQ: &[GPR] =
308 &[GPR::RDI, GPR::RSI, GPR::RDX, GPR::RCX, GPR::R8, GPR::R9];
309 static XMM_SEQ: &[XMM] = &[
310 XMM::XMM0,
311 XMM::XMM1,
312 XMM::XMM2,
313 XMM::XMM3,
314 XMM::XMM4,
315 XMM::XMM5,
316 XMM::XMM6,
317 XMM::XMM7,
318 ];
319 match ty {
320 Type::I32 | Type::I64 => {
321 if self.n_gprs < GPR_SEQ.len() {
322 let gpr = GPR_SEQ[self.n_gprs];
323 self.n_gprs += 1;
324 Some(X64Register::GPR(gpr))
325 } else {
326 None
327 }
328 }
329 Type::F32 | Type::F64 => {
330 if self.n_xmms < XMM_SEQ.len() {
331 let xmm = XMM_SEQ[self.n_xmms];
332 self.n_xmms += 1;
333 Some(X64Register::XMM(xmm))
334 } else {
335 None
336 }
337 }
338 _ => {
339 return Err(CompileError::Codegen(format!(
340 "No register available for {calling_convention:?} and type {ty}"
341 )));
342 }
343 }
344 }
345 };
346
347 Ok(ret)
348 }
349}
350
351pub fn new_machine_state() -> MachineState {
353 MachineState {
354 stack_values: vec![],
355 register_values: vec![MachineValue::Undefined; 16 + 8],
356 prev_frame: BTreeMap::new(),
357 wasm_stack: vec![],
358 wasm_inst_offset: usize::MAX,
359 }
360}