/rust/registry/src/index.crates.io-6f17d22bba15001f/cranelift-codegen-0.91.1/src/isa/x64/inst/regs.rs
Line | Count | Source (jump to first uncovered line) |
1 | | //! Register definitions for regalloc2. |
2 | | //! |
3 | | //! We define 16 GPRs, with indices equal to the hardware encoding, |
4 | | //! and 16 XMM registers. |
5 | | //! |
6 | | //! Note also that we make use of pinned VRegs to refer to PRegs. |
7 | | |
8 | | use crate::machinst::{AllocationConsumer, RealReg, Reg}; |
9 | | use crate::settings; |
10 | | use alloc::string::ToString; |
11 | | use regalloc2::{MachineEnv, PReg, RegClass, VReg}; |
12 | | use std::string::String; |
13 | | |
14 | | // Hardware encodings (note the special rax, rcx, rdx, rbx order). |
15 | | |
16 | | pub const ENC_RAX: u8 = 0; |
17 | | pub const ENC_RCX: u8 = 1; |
18 | | pub const ENC_RDX: u8 = 2; |
19 | | pub const ENC_RBX: u8 = 3; |
20 | | pub const ENC_RSP: u8 = 4; |
21 | | pub const ENC_RBP: u8 = 5; |
22 | | pub const ENC_RSI: u8 = 6; |
23 | | pub const ENC_RDI: u8 = 7; |
24 | | pub const ENC_R8: u8 = 8; |
25 | | pub const ENC_R9: u8 = 9; |
26 | | pub const ENC_R10: u8 = 10; |
27 | | pub const ENC_R11: u8 = 11; |
28 | | pub const ENC_R12: u8 = 12; |
29 | | pub const ENC_R13: u8 = 13; |
30 | | pub const ENC_R14: u8 = 14; |
31 | | pub const ENC_R15: u8 = 15; |
32 | | |
33 | | // Constructors for Regs. |
34 | | |
35 | 2.53M | fn gpr(enc: u8) -> Reg { |
36 | 2.53M | let preg = gpr_preg(enc); |
37 | 2.53M | Reg::from(VReg::new(preg.index(), RegClass::Int)) |
38 | 2.53M | } |
39 | 2.53M | pub(crate) const fn gpr_preg(enc: u8) -> PReg { |
40 | 2.53M | PReg::new(enc as usize, RegClass::Int) |
41 | 2.53M | } |
42 | | |
43 | 136k | pub(crate) fn rsi() -> Reg { |
44 | 136k | gpr(ENC_RSI) |
45 | 136k | } |
46 | 209k | pub(crate) fn rdi() -> Reg { |
47 | 209k | gpr(ENC_RDI) |
48 | 209k | } |
49 | 51.9k | pub(crate) fn rax() -> Reg { |
50 | 51.9k | gpr(ENC_RAX) |
51 | 51.9k | } |
52 | 23.5k | pub(crate) fn rcx() -> Reg { |
53 | 23.5k | gpr(ENC_RCX) |
54 | 23.5k | } |
55 | 101k | pub(crate) fn rdx() -> Reg { |
56 | 101k | gpr(ENC_RDX) |
57 | 101k | } |
58 | 18.6k | pub(crate) fn r8() -> Reg { |
59 | 18.6k | gpr(ENC_R8) |
60 | 18.6k | } |
61 | 16.1k | pub(crate) fn r9() -> Reg { |
62 | 16.1k | gpr(ENC_R9) |
63 | 16.1k | } |
64 | 10.0k | pub(crate) fn r10() -> Reg { |
65 | 10.0k | gpr(ENC_R10) |
66 | 10.0k | } |
67 | 10.0k | pub(crate) fn r11() -> Reg { |
68 | 10.0k | gpr(ENC_R11) |
69 | 10.0k | } |
70 | 10.0k | pub(crate) fn r12() -> Reg { |
71 | 10.0k | gpr(ENC_R12) |
72 | 10.0k | } |
73 | 10.0k | pub(crate) fn r13() -> Reg { |
74 | 10.0k | gpr(ENC_R13) |
75 | 10.0k | } |
76 | 10.0k | pub(crate) fn r14() -> Reg { |
77 | 10.0k | gpr(ENC_R14) |
78 | 10.0k | } |
79 | 10.0k | pub(crate) fn rbx() -> Reg { |
80 | 10.0k | gpr(ENC_RBX) |
81 | 10.0k | } |
82 | | |
83 | 149k | pub(crate) fn r15() -> Reg { |
84 | 149k | gpr(ENC_R15) |
85 | 149k | } |
86 | | |
87 | 895k | pub(crate) fn rsp() -> Reg { |
88 | 895k | gpr(ENC_RSP) |
89 | 895k | } |
90 | 873k | pub(crate) fn rbp() -> Reg { |
91 | 873k | gpr(ENC_RBP) |
92 | 873k | } |
93 | | |
94 | | /// The pinned register on this architecture. |
95 | | /// It must be the same as Spidermonkey's HeapReg, as found in this file. |
96 | | /// https://searchfox.org/mozilla-central/source/js/src/jit/x64/Assembler-x64.h#99 |
97 | 139k | pub(crate) fn pinned_reg() -> Reg { |
98 | 139k | r15() |
99 | 139k | } |
100 | | |
101 | 333k | fn fpr(enc: u8) -> Reg { |
102 | 333k | let preg = fpr_preg(enc); |
103 | 333k | Reg::from(VReg::new(preg.index(), RegClass::Float)) |
104 | 333k | } |
105 | | |
106 | 333k | pub(crate) const fn fpr_preg(enc: u8) -> PReg { |
107 | 333k | PReg::new(enc as usize, RegClass::Float) |
108 | 333k | } |
109 | | |
110 | 93.5k | pub(crate) fn xmm0() -> Reg { |
111 | 93.5k | fpr(0) |
112 | 93.5k | } |
113 | 37.5k | pub(crate) fn xmm1() -> Reg { |
114 | 37.5k | fpr(1) |
115 | 37.5k | } |
116 | 26.4k | pub(crate) fn xmm2() -> Reg { |
117 | 26.4k | fpr(2) |
118 | 26.4k | } |
119 | 22.5k | pub(crate) fn xmm3() -> Reg { |
120 | 22.5k | fpr(3) |
121 | 22.5k | } |
122 | 20.1k | pub(crate) fn xmm4() -> Reg { |
123 | 20.1k | fpr(4) |
124 | 20.1k | } |
125 | 18.3k | pub(crate) fn xmm5() -> Reg { |
126 | 18.3k | fpr(5) |
127 | 18.3k | } |
128 | 17.6k | pub(crate) fn xmm6() -> Reg { |
129 | 17.6k | fpr(6) |
130 | 17.6k | } |
131 | 16.8k | pub(crate) fn xmm7() -> Reg { |
132 | 16.8k | fpr(7) |
133 | 16.8k | } |
134 | 10.0k | pub(crate) fn xmm8() -> Reg { |
135 | 10.0k | fpr(8) |
136 | 10.0k | } |
137 | 10.0k | pub(crate) fn xmm9() -> Reg { |
138 | 10.0k | fpr(9) |
139 | 10.0k | } |
140 | 10.0k | pub(crate) fn xmm10() -> Reg { |
141 | 10.0k | fpr(10) |
142 | 10.0k | } |
143 | 10.0k | pub(crate) fn xmm11() -> Reg { |
144 | 10.0k | fpr(11) |
145 | 10.0k | } |
146 | 10.0k | pub(crate) fn xmm12() -> Reg { |
147 | 10.0k | fpr(12) |
148 | 10.0k | } |
149 | 10.0k | pub(crate) fn xmm13() -> Reg { |
150 | 10.0k | fpr(13) |
151 | 10.0k | } |
152 | 10.0k | pub(crate) fn xmm14() -> Reg { |
153 | 10.0k | fpr(14) |
154 | 10.0k | } |
155 | 10.0k | pub(crate) fn xmm15() -> Reg { |
156 | 10.0k | fpr(15) |
157 | 10.0k | } |
158 | | |
159 | | /// Create the register environment for x64. |
160 | 10.0k | pub(crate) fn create_reg_env_systemv(flags: &settings::Flags) -> MachineEnv { |
161 | 300k | fn preg(r: Reg) -> PReg { |
162 | 300k | r.to_real_reg().unwrap().into() |
163 | 300k | } |
164 | 10.0k | |
165 | 10.0k | let mut env = MachineEnv { |
166 | 10.0k | preferred_regs_by_class: [ |
167 | 10.0k | // Preferred GPRs: caller-saved in the SysV ABI. |
168 | 10.0k | vec![ |
169 | 10.0k | preg(rsi()), |
170 | 10.0k | preg(rdi()), |
171 | 10.0k | preg(rax()), |
172 | 10.0k | preg(rcx()), |
173 | 10.0k | preg(rdx()), |
174 | 10.0k | preg(r8()), |
175 | 10.0k | preg(r9()), |
176 | 10.0k | preg(r10()), |
177 | 10.0k | preg(r11()), |
178 | 10.0k | ], |
179 | 10.0k | // Preferred XMMs: all of them. |
180 | 10.0k | vec![ |
181 | 10.0k | preg(xmm0()), |
182 | 10.0k | preg(xmm1()), |
183 | 10.0k | preg(xmm2()), |
184 | 10.0k | preg(xmm3()), |
185 | 10.0k | preg(xmm4()), |
186 | 10.0k | preg(xmm5()), |
187 | 10.0k | preg(xmm6()), |
188 | 10.0k | preg(xmm7()), |
189 | 10.0k | preg(xmm8()), |
190 | 10.0k | preg(xmm9()), |
191 | 10.0k | preg(xmm10()), |
192 | 10.0k | preg(xmm11()), |
193 | 10.0k | preg(xmm12()), |
194 | 10.0k | preg(xmm13()), |
195 | 10.0k | preg(xmm14()), |
196 | 10.0k | preg(xmm15()), |
197 | 10.0k | ], |
198 | 10.0k | ], |
199 | 10.0k | non_preferred_regs_by_class: [ |
200 | 10.0k | // Non-preferred GPRs: callee-saved in the SysV ABI. |
201 | 10.0k | vec![preg(rbx()), preg(r12()), preg(r13()), preg(r14())], |
202 | 10.0k | // Non-preferred XMMs: none. |
203 | 10.0k | vec![], |
204 | 10.0k | ], |
205 | 10.0k | fixed_stack_slots: vec![], |
206 | 10.0k | }; |
207 | 10.0k | |
208 | 10.0k | debug_assert_eq!(r15(), pinned_reg()); |
209 | 10.0k | if !flags.enable_pinned_reg() { |
210 | 10.0k | env.non_preferred_regs_by_class[0].push(preg(r15())); |
211 | 10.0k | } |
212 | | |
213 | 10.0k | env |
214 | 10.0k | } |
215 | | |
216 | | /// Give the name of a RealReg. |
217 | 0 | pub fn realreg_name(reg: RealReg) -> &'static str { |
218 | 0 | let preg = PReg::from(reg); |
219 | 0 | match preg.class() { |
220 | 0 | RegClass::Int => match preg.hw_enc() as u8 { |
221 | 0 | ENC_RAX => "%rax", |
222 | 0 | ENC_RBX => "%rbx", |
223 | 0 | ENC_RCX => "%rcx", |
224 | 0 | ENC_RDX => "%rdx", |
225 | 0 | ENC_RSI => "%rsi", |
226 | 0 | ENC_RDI => "%rdi", |
227 | 0 | ENC_RBP => "%rbp", |
228 | 0 | ENC_RSP => "%rsp", |
229 | 0 | ENC_R8 => "%r8", |
230 | 0 | ENC_R9 => "%r9", |
231 | 0 | ENC_R10 => "%r10", |
232 | 0 | ENC_R11 => "%r11", |
233 | 0 | ENC_R12 => "%r12", |
234 | 0 | ENC_R13 => "%r13", |
235 | 0 | ENC_R14 => "%r14", |
236 | 0 | ENC_R15 => "%r15", |
237 | 0 | _ => panic!("Invalid PReg: {:?}", preg), |
238 | | }, |
239 | 0 | RegClass::Float => match preg.hw_enc() { |
240 | 0 | 0 => "%xmm0", |
241 | 0 | 1 => "%xmm1", |
242 | 0 | 2 => "%xmm2", |
243 | 0 | 3 => "%xmm3", |
244 | 0 | 4 => "%xmm4", |
245 | 0 | 5 => "%xmm5", |
246 | 0 | 6 => "%xmm6", |
247 | 0 | 7 => "%xmm7", |
248 | 0 | 8 => "%xmm8", |
249 | 0 | 9 => "%xmm9", |
250 | 0 | 10 => "%xmm10", |
251 | 0 | 11 => "%xmm11", |
252 | 0 | 12 => "%xmm12", |
253 | 0 | 13 => "%xmm13", |
254 | 0 | 14 => "%xmm14", |
255 | 0 | 15 => "%xmm15", |
256 | 0 | _ => panic!("Invalid PReg: {:?}", preg), |
257 | | }, |
258 | | } |
259 | 0 | } |
260 | | |
261 | 0 | pub fn show_reg(reg: Reg) -> String { |
262 | 0 | if let Some(rreg) = reg.to_real_reg() { |
263 | 0 | realreg_name(rreg).to_string() |
264 | | } else { |
265 | 0 | format!("%{:?}", reg) |
266 | | } |
267 | 0 | } |
268 | | |
269 | | /// If `ireg` denotes an I64-classed reg, make a best-effort attempt to show its name at some |
270 | | /// smaller size (4, 2 or 1 bytes). |
271 | 0 | pub fn show_ireg_sized(reg: Reg, size: u8) -> String { |
272 | 0 | let mut s = show_reg(reg); |
273 | 0 |
|
274 | 0 | if reg.class() != RegClass::Int || size == 8 { |
275 | | // We can't do any better. |
276 | 0 | return s; |
277 | 0 | } |
278 | 0 |
|
279 | 0 | if reg.is_real() { |
280 | | // Change (eg) "rax" into "eax", "ax" or "al" as appropriate. This is something one could |
281 | | // describe diplomatically as "a kludge", but it's only debug code. |
282 | 0 | let remapper = match s.as_str() { |
283 | 0 | "%rax" => Some(["%eax", "%ax", "%al"]), |
284 | 0 | "%rbx" => Some(["%ebx", "%bx", "%bl"]), |
285 | 0 | "%rcx" => Some(["%ecx", "%cx", "%cl"]), |
286 | 0 | "%rdx" => Some(["%edx", "%dx", "%dl"]), |
287 | 0 | "%rsi" => Some(["%esi", "%si", "%sil"]), |
288 | 0 | "%rdi" => Some(["%edi", "%di", "%dil"]), |
289 | 0 | "%rbp" => Some(["%ebp", "%bp", "%bpl"]), |
290 | 0 | "%rsp" => Some(["%esp", "%sp", "%spl"]), |
291 | 0 | "%r8" => Some(["%r8d", "%r8w", "%r8b"]), |
292 | 0 | "%r9" => Some(["%r9d", "%r9w", "%r9b"]), |
293 | 0 | "%r10" => Some(["%r10d", "%r10w", "%r10b"]), |
294 | 0 | "%r11" => Some(["%r11d", "%r11w", "%r11b"]), |
295 | 0 | "%r12" => Some(["%r12d", "%r12w", "%r12b"]), |
296 | 0 | "%r13" => Some(["%r13d", "%r13w", "%r13b"]), |
297 | 0 | "%r14" => Some(["%r14d", "%r14w", "%r14b"]), |
298 | 0 | "%r15" => Some(["%r15d", "%r15w", "%r15b"]), |
299 | 0 | _ => None, |
300 | | }; |
301 | 0 | if let Some(smaller_names) = remapper { |
302 | 0 | match size { |
303 | 0 | 4 => s = smaller_names[0].into(), |
304 | 0 | 2 => s = smaller_names[1].into(), |
305 | 0 | 1 => s = smaller_names[2].into(), |
306 | 0 | _ => panic!("show_ireg_sized: real"), |
307 | | } |
308 | 0 | } |
309 | 0 | } else { |
310 | 0 | // Add a "l", "w" or "b" suffix to RegClass::I64 vregs used at narrower widths. |
311 | 0 | let suffix = match size { |
312 | 0 | 4 => "l", |
313 | 0 | 2 => "w", |
314 | 0 | 1 => "b", |
315 | 0 | _ => panic!("show_ireg_sized: virtual"), |
316 | | }; |
317 | 0 | s = s + suffix; |
318 | | } |
319 | | |
320 | 0 | s |
321 | 0 | } |
322 | | |
323 | | // N.B.: this is not an `impl PrettyPrint for Reg` because it is |
324 | | // specific to x64; other backends have analogous functions. The |
325 | | // disambiguation happens statically by virtue of higher-level, |
326 | | // x64-specific, types calling the right `pretty_print_reg`. (In other |
327 | | // words, we can't pretty-print a `Reg` all by itself in a build that |
328 | | // may have multiple backends; but we can pretty-print one as part of |
329 | | // an x64 Inst or x64 RegMemImm.) |
330 | 0 | pub fn pretty_print_reg(reg: Reg, size: u8, allocs: &mut AllocationConsumer<'_>) -> String { |
331 | 0 | let reg = allocs.next(reg); |
332 | 0 | show_ireg_sized(reg, size) |
333 | 0 | } |