Coverage Report

Created: 2024-10-16 07:58

/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
}