]> git.proxmox.com Git - rustc.git/blob - compiler/rustc_target/src/asm/mod.rs
New upstream version 1.54.0+dfsg1
[rustc.git] / compiler / rustc_target / src / asm / mod.rs
1 use crate::abi::Size;
2 use crate::spec::Target;
3 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
4 use rustc_macros::HashStable_Generic;
5 use rustc_span::Symbol;
6 use std::fmt;
7 use std::str::FromStr;
8
9 macro_rules! def_reg_class {
10 ($arch:ident $arch_regclass:ident {
11 $(
12 $class:ident,
13 )*
14 }) => {
15 #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, PartialOrd, Hash, HashStable_Generic)]
16 #[allow(non_camel_case_types)]
17 pub enum $arch_regclass {
18 $($class,)*
19 }
20
21 impl $arch_regclass {
22 pub fn name(self) -> rustc_span::Symbol {
23 match self {
24 $(Self::$class => rustc_span::symbol::sym::$class,)*
25 }
26 }
27
28 pub fn parse(_arch: super::InlineAsmArch, name: rustc_span::Symbol) -> Result<Self, &'static str> {
29 match name {
30 $(
31 rustc_span::sym::$class => Ok(Self::$class),
32 )*
33 _ => Err("unknown register class"),
34 }
35 }
36 }
37
38 pub(super) fn regclass_map() -> rustc_data_structures::fx::FxHashMap<
39 super::InlineAsmRegClass,
40 rustc_data_structures::fx::FxHashSet<super::InlineAsmReg>,
41 > {
42 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
43 use super::InlineAsmRegClass;
44 let mut map = FxHashMap::default();
45 $(
46 map.insert(InlineAsmRegClass::$arch($arch_regclass::$class), FxHashSet::default());
47 )*
48 map
49 }
50 }
51 }
52
53 macro_rules! def_regs {
54 ($arch:ident $arch_reg:ident $arch_regclass:ident {
55 $(
56 $reg:ident: $class:ident $(, $extra_class:ident)* = [$reg_name:literal $(, $alias:literal)*] $(% $filter:ident)?,
57 )*
58 $(
59 #error = [$($bad_reg:literal),+] => $error:literal,
60 )*
61 }) => {
62 #[allow(unreachable_code)]
63 #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, PartialOrd, Hash, HashStable_Generic)]
64 #[allow(non_camel_case_types)]
65 pub enum $arch_reg {
66 $($reg,)*
67 }
68
69 impl $arch_reg {
70 pub fn name(self) -> &'static str {
71 match self {
72 $(Self::$reg => $reg_name,)*
73 }
74 }
75
76 pub fn reg_class(self) -> $arch_regclass {
77 match self {
78 $(Self::$reg => $arch_regclass::$class,)*
79 }
80 }
81
82 pub fn parse(
83 _arch: super::InlineAsmArch,
84 mut _has_feature: impl FnMut(&str) -> bool,
85 _target: &crate::spec::Target,
86 name: &str,
87 ) -> Result<Self, &'static str> {
88 match name {
89 $(
90 $($alias)|* | $reg_name => {
91 $($filter(_arch, &mut _has_feature, _target)?;)?
92 Ok(Self::$reg)
93 }
94 )*
95 $(
96 $($bad_reg)|* => Err($error),
97 )*
98 _ => Err("unknown register"),
99 }
100 }
101 }
102
103 pub(super) fn fill_reg_map(
104 _arch: super::InlineAsmArch,
105 mut _has_feature: impl FnMut(&str) -> bool,
106 _target: &crate::spec::Target,
107 _map: &mut rustc_data_structures::fx::FxHashMap<
108 super::InlineAsmRegClass,
109 rustc_data_structures::fx::FxHashSet<super::InlineAsmReg>,
110 >,
111 ) {
112 #[allow(unused_imports)]
113 use super::{InlineAsmReg, InlineAsmRegClass};
114 $(
115 if $($filter(_arch, &mut _has_feature, _target).is_ok() &&)? true {
116 if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) {
117 set.insert(InlineAsmReg::$arch($arch_reg::$reg));
118 }
119 $(
120 if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$extra_class)) {
121 set.insert(InlineAsmReg::$arch($arch_reg::$reg));
122 }
123 )*
124 }
125 )*
126 }
127 }
128 }
129
130 macro_rules! types {
131 (
132 $(_ : $($ty:expr),+;)?
133 $($feature:literal: $($ty2:expr),+;)*
134 ) => {
135 {
136 use super::InlineAsmType::*;
137 &[
138 $($(
139 ($ty, None),
140 )*)?
141 $($(
142 ($ty2, Some($feature)),
143 )*)*
144 ]
145 }
146 };
147 }
148
149 mod aarch64;
150 mod arm;
151 mod bpf;
152 mod hexagon;
153 mod mips;
154 mod nvptx;
155 mod powerpc;
156 mod riscv;
157 mod spirv;
158 mod wasm;
159 mod x86;
160
161 pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass};
162 pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass};
163 pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass};
164 pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass};
165 pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass};
166 pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
167 pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass};
168 pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
169 pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
170 pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
171 pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
172
173 #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash)]
174 pub enum InlineAsmArch {
175 X86,
176 X86_64,
177 Arm,
178 AArch64,
179 RiscV32,
180 RiscV64,
181 Nvptx64,
182 Hexagon,
183 Mips,
184 Mips64,
185 PowerPC,
186 PowerPC64,
187 SpirV,
188 Wasm32,
189 Bpf,
190 }
191
192 impl FromStr for InlineAsmArch {
193 type Err = ();
194
195 fn from_str(s: &str) -> Result<InlineAsmArch, ()> {
196 match s {
197 "x86" => Ok(Self::X86),
198 "x86_64" => Ok(Self::X86_64),
199 "arm" => Ok(Self::Arm),
200 "aarch64" => Ok(Self::AArch64),
201 "riscv32" => Ok(Self::RiscV32),
202 "riscv64" => Ok(Self::RiscV64),
203 "nvptx64" => Ok(Self::Nvptx64),
204 "powerpc" => Ok(Self::PowerPC),
205 "powerpc64" => Ok(Self::PowerPC64),
206 "hexagon" => Ok(Self::Hexagon),
207 "mips" => Ok(Self::Mips),
208 "mips64" => Ok(Self::Mips64),
209 "spirv" => Ok(Self::SpirV),
210 "wasm32" => Ok(Self::Wasm32),
211 "bpf" => Ok(Self::Bpf),
212 _ => Err(()),
213 }
214 }
215 }
216
217 #[derive(
218 Copy,
219 Clone,
220 Encodable,
221 Decodable,
222 Debug,
223 Eq,
224 PartialEq,
225 PartialOrd,
226 Hash,
227 HashStable_Generic
228 )]
229 pub enum InlineAsmReg {
230 X86(X86InlineAsmReg),
231 Arm(ArmInlineAsmReg),
232 AArch64(AArch64InlineAsmReg),
233 RiscV(RiscVInlineAsmReg),
234 Nvptx(NvptxInlineAsmReg),
235 PowerPC(PowerPCInlineAsmReg),
236 Hexagon(HexagonInlineAsmReg),
237 Mips(MipsInlineAsmReg),
238 SpirV(SpirVInlineAsmReg),
239 Wasm(WasmInlineAsmReg),
240 Bpf(BpfInlineAsmReg),
241 // Placeholder for invalid register constraints for the current target
242 Err,
243 }
244
245 impl InlineAsmReg {
246 pub fn name(self) -> &'static str {
247 match self {
248 Self::X86(r) => r.name(),
249 Self::Arm(r) => r.name(),
250 Self::AArch64(r) => r.name(),
251 Self::RiscV(r) => r.name(),
252 Self::PowerPC(r) => r.name(),
253 Self::Hexagon(r) => r.name(),
254 Self::Mips(r) => r.name(),
255 Self::Bpf(r) => r.name(),
256 Self::Err => "<reg>",
257 }
258 }
259
260 pub fn reg_class(self) -> InlineAsmRegClass {
261 match self {
262 Self::X86(r) => InlineAsmRegClass::X86(r.reg_class()),
263 Self::Arm(r) => InlineAsmRegClass::Arm(r.reg_class()),
264 Self::AArch64(r) => InlineAsmRegClass::AArch64(r.reg_class()),
265 Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()),
266 Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()),
267 Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
268 Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
269 Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
270 Self::Err => InlineAsmRegClass::Err,
271 }
272 }
273
274 pub fn parse(
275 arch: InlineAsmArch,
276 has_feature: impl FnMut(&str) -> bool,
277 target: &Target,
278 name: Symbol,
279 ) -> Result<Self, &'static str> {
280 // FIXME: use direct symbol comparison for register names
281 // Use `Symbol::as_str` instead of `Symbol::with` here because `has_feature` may access `Symbol`.
282 let name = name.as_str();
283 Ok(match arch {
284 InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
285 Self::X86(X86InlineAsmReg::parse(arch, has_feature, target, &name)?)
286 }
287 InlineAsmArch::Arm => {
288 Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, target, &name)?)
289 }
290 InlineAsmArch::AArch64 => {
291 Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, target, &name)?)
292 }
293 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
294 Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, target, &name)?)
295 }
296 InlineAsmArch::Nvptx64 => {
297 Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, &name)?)
298 }
299 InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
300 Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, &name)?)
301 }
302 InlineAsmArch::Hexagon => {
303 Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, &name)?)
304 }
305 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
306 Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?)
307 }
308 InlineAsmArch::SpirV => {
309 Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?)
310 }
311 InlineAsmArch::Wasm32 => {
312 Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?)
313 }
314 InlineAsmArch::Bpf => {
315 Self::Bpf(BpfInlineAsmReg::parse(arch, has_feature, target, &name)?)
316 }
317 })
318 }
319
320 // NOTE: This function isn't used at the moment, but is needed to support
321 // falling back to an external assembler.
322 pub fn emit(
323 self,
324 out: &mut dyn fmt::Write,
325 arch: InlineAsmArch,
326 modifier: Option<char>,
327 ) -> fmt::Result {
328 match self {
329 Self::X86(r) => r.emit(out, arch, modifier),
330 Self::Arm(r) => r.emit(out, arch, modifier),
331 Self::AArch64(r) => r.emit(out, arch, modifier),
332 Self::RiscV(r) => r.emit(out, arch, modifier),
333 Self::PowerPC(r) => r.emit(out, arch, modifier),
334 Self::Hexagon(r) => r.emit(out, arch, modifier),
335 Self::Mips(r) => r.emit(out, arch, modifier),
336 Self::Bpf(r) => r.emit(out, arch, modifier),
337 Self::Err => unreachable!("Use of InlineAsmReg::Err"),
338 }
339 }
340
341 pub fn overlapping_regs(self, mut cb: impl FnMut(InlineAsmReg)) {
342 match self {
343 Self::X86(r) => r.overlapping_regs(|r| cb(Self::X86(r))),
344 Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))),
345 Self::AArch64(_) => cb(self),
346 Self::RiscV(_) => cb(self),
347 Self::PowerPC(_) => cb(self),
348 Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
349 Self::Mips(_) => cb(self),
350 Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
351 Self::Err => unreachable!("Use of InlineAsmReg::Err"),
352 }
353 }
354 }
355
356 #[derive(
357 Copy,
358 Clone,
359 Encodable,
360 Decodable,
361 Debug,
362 Eq,
363 PartialEq,
364 PartialOrd,
365 Hash,
366 HashStable_Generic
367 )]
368 pub enum InlineAsmRegClass {
369 X86(X86InlineAsmRegClass),
370 Arm(ArmInlineAsmRegClass),
371 AArch64(AArch64InlineAsmRegClass),
372 RiscV(RiscVInlineAsmRegClass),
373 Nvptx(NvptxInlineAsmRegClass),
374 PowerPC(PowerPCInlineAsmRegClass),
375 Hexagon(HexagonInlineAsmRegClass),
376 Mips(MipsInlineAsmRegClass),
377 SpirV(SpirVInlineAsmRegClass),
378 Wasm(WasmInlineAsmRegClass),
379 Bpf(BpfInlineAsmRegClass),
380 // Placeholder for invalid register constraints for the current target
381 Err,
382 }
383
384 impl InlineAsmRegClass {
385 pub fn name(self) -> Symbol {
386 match self {
387 Self::X86(r) => r.name(),
388 Self::Arm(r) => r.name(),
389 Self::AArch64(r) => r.name(),
390 Self::RiscV(r) => r.name(),
391 Self::Nvptx(r) => r.name(),
392 Self::PowerPC(r) => r.name(),
393 Self::Hexagon(r) => r.name(),
394 Self::Mips(r) => r.name(),
395 Self::SpirV(r) => r.name(),
396 Self::Wasm(r) => r.name(),
397 Self::Bpf(r) => r.name(),
398 Self::Err => rustc_span::symbol::sym::reg,
399 }
400 }
401
402 /// Returns a suggested register class to use for this type. This is called
403 /// after type checking via `supported_types` fails to give a better error
404 /// message to the user.
405 pub fn suggest_class(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option<Self> {
406 match self {
407 Self::X86(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::X86),
408 Self::Arm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Arm),
409 Self::AArch64(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::AArch64),
410 Self::RiscV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::RiscV),
411 Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx),
412 Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC),
413 Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon),
414 Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
415 Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
416 Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
417 Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
418 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
419 }
420 }
421
422 /// Returns a suggested template modifier to use for this type and an
423 /// example of a register named formatted with it.
424 ///
425 /// Such suggestions are useful if a type smaller than the full register
426 /// size is used and a modifier can be used to point to the subregister of
427 /// the correct size.
428 pub fn suggest_modifier(
429 self,
430 arch: InlineAsmArch,
431 ty: InlineAsmType,
432 ) -> Option<(char, &'static str)> {
433 match self {
434 Self::X86(r) => r.suggest_modifier(arch, ty),
435 Self::Arm(r) => r.suggest_modifier(arch, ty),
436 Self::AArch64(r) => r.suggest_modifier(arch, ty),
437 Self::RiscV(r) => r.suggest_modifier(arch, ty),
438 Self::Nvptx(r) => r.suggest_modifier(arch, ty),
439 Self::PowerPC(r) => r.suggest_modifier(arch, ty),
440 Self::Hexagon(r) => r.suggest_modifier(arch, ty),
441 Self::Mips(r) => r.suggest_modifier(arch, ty),
442 Self::SpirV(r) => r.suggest_modifier(arch, ty),
443 Self::Wasm(r) => r.suggest_modifier(arch, ty),
444 Self::Bpf(r) => r.suggest_modifier(arch, ty),
445 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
446 }
447 }
448
449 /// Returns the default modifier for this register and an example of a
450 /// register named formatted with it.
451 ///
452 /// This is only needed when the register class can suggest a modifier, so
453 /// that the user can be shown how to get the default behavior without a
454 /// warning.
455 pub fn default_modifier(self, arch: InlineAsmArch) -> Option<(char, &'static str)> {
456 match self {
457 Self::X86(r) => r.default_modifier(arch),
458 Self::Arm(r) => r.default_modifier(arch),
459 Self::AArch64(r) => r.default_modifier(arch),
460 Self::RiscV(r) => r.default_modifier(arch),
461 Self::Nvptx(r) => r.default_modifier(arch),
462 Self::PowerPC(r) => r.default_modifier(arch),
463 Self::Hexagon(r) => r.default_modifier(arch),
464 Self::Mips(r) => r.default_modifier(arch),
465 Self::SpirV(r) => r.default_modifier(arch),
466 Self::Wasm(r) => r.default_modifier(arch),
467 Self::Bpf(r) => r.default_modifier(arch),
468 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
469 }
470 }
471
472 /// Returns a list of supported types for this register class, each with a
473 /// options target feature required to use this type.
474 pub fn supported_types(
475 self,
476 arch: InlineAsmArch,
477 ) -> &'static [(InlineAsmType, Option<&'static str>)] {
478 match self {
479 Self::X86(r) => r.supported_types(arch),
480 Self::Arm(r) => r.supported_types(arch),
481 Self::AArch64(r) => r.supported_types(arch),
482 Self::RiscV(r) => r.supported_types(arch),
483 Self::Nvptx(r) => r.supported_types(arch),
484 Self::PowerPC(r) => r.supported_types(arch),
485 Self::Hexagon(r) => r.supported_types(arch),
486 Self::Mips(r) => r.supported_types(arch),
487 Self::SpirV(r) => r.supported_types(arch),
488 Self::Wasm(r) => r.supported_types(arch),
489 Self::Bpf(r) => r.supported_types(arch),
490 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
491 }
492 }
493
494 pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> {
495 Ok(match arch {
496 InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
497 Self::X86(X86InlineAsmRegClass::parse(arch, name)?)
498 }
499 InlineAsmArch::Arm => Self::Arm(ArmInlineAsmRegClass::parse(arch, name)?),
500 InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmRegClass::parse(arch, name)?),
501 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
502 Self::RiscV(RiscVInlineAsmRegClass::parse(arch, name)?)
503 }
504 InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?),
505 InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
506 Self::PowerPC(PowerPCInlineAsmRegClass::parse(arch, name)?)
507 }
508 InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(arch, name)?),
509 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
510 Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?)
511 }
512 InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?),
513 InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?),
514 InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?),
515 })
516 }
517
518 /// Returns the list of template modifiers that can be used with this
519 /// register class.
520 pub fn valid_modifiers(self, arch: InlineAsmArch) -> &'static [char] {
521 match self {
522 Self::X86(r) => r.valid_modifiers(arch),
523 Self::Arm(r) => r.valid_modifiers(arch),
524 Self::AArch64(r) => r.valid_modifiers(arch),
525 Self::RiscV(r) => r.valid_modifiers(arch),
526 Self::Nvptx(r) => r.valid_modifiers(arch),
527 Self::PowerPC(r) => r.valid_modifiers(arch),
528 Self::Hexagon(r) => r.valid_modifiers(arch),
529 Self::Mips(r) => r.valid_modifiers(arch),
530 Self::SpirV(r) => r.valid_modifiers(arch),
531 Self::Wasm(r) => r.valid_modifiers(arch),
532 Self::Bpf(r) => r.valid_modifiers(arch),
533 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
534 }
535 }
536 }
537
538 #[derive(
539 Copy,
540 Clone,
541 Encodable,
542 Decodable,
543 Debug,
544 Eq,
545 PartialEq,
546 PartialOrd,
547 Hash,
548 HashStable_Generic
549 )]
550 pub enum InlineAsmRegOrRegClass {
551 Reg(InlineAsmReg),
552 RegClass(InlineAsmRegClass),
553 }
554
555 impl InlineAsmRegOrRegClass {
556 pub fn reg_class(self) -> InlineAsmRegClass {
557 match self {
558 Self::Reg(r) => r.reg_class(),
559 Self::RegClass(r) => r,
560 }
561 }
562 }
563
564 impl fmt::Display for InlineAsmRegOrRegClass {
565 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
566 match self {
567 Self::Reg(r) => write!(f, "\"{}\"", r.name()),
568 Self::RegClass(r) => write!(f, "{}", r.name()),
569 }
570 }
571 }
572
573 /// Set of types which can be used with a particular register class.
574 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
575 pub enum InlineAsmType {
576 I8,
577 I16,
578 I32,
579 I64,
580 I128,
581 F32,
582 F64,
583 VecI8(u64),
584 VecI16(u64),
585 VecI32(u64),
586 VecI64(u64),
587 VecI128(u64),
588 VecF32(u64),
589 VecF64(u64),
590 }
591
592 impl InlineAsmType {
593 pub fn is_integer(self) -> bool {
594 matches!(self, Self::I8 | Self::I16 | Self::I32 | Self::I64 | Self::I128)
595 }
596
597 pub fn size(self) -> Size {
598 Size::from_bytes(match self {
599 Self::I8 => 1,
600 Self::I16 => 2,
601 Self::I32 => 4,
602 Self::I64 => 8,
603 Self::I128 => 16,
604 Self::F32 => 4,
605 Self::F64 => 8,
606 Self::VecI8(n) => n * 1,
607 Self::VecI16(n) => n * 2,
608 Self::VecI32(n) => n * 4,
609 Self::VecI64(n) => n * 8,
610 Self::VecI128(n) => n * 16,
611 Self::VecF32(n) => n * 4,
612 Self::VecF64(n) => n * 8,
613 })
614 }
615 }
616
617 impl fmt::Display for InlineAsmType {
618 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
619 match *self {
620 Self::I8 => f.write_str("i8"),
621 Self::I16 => f.write_str("i16"),
622 Self::I32 => f.write_str("i32"),
623 Self::I64 => f.write_str("i64"),
624 Self::I128 => f.write_str("i128"),
625 Self::F32 => f.write_str("f32"),
626 Self::F64 => f.write_str("f64"),
627 Self::VecI8(n) => write!(f, "i8x{}", n),
628 Self::VecI16(n) => write!(f, "i16x{}", n),
629 Self::VecI32(n) => write!(f, "i32x{}", n),
630 Self::VecI64(n) => write!(f, "i64x{}", n),
631 Self::VecI128(n) => write!(f, "i128x{}", n),
632 Self::VecF32(n) => write!(f, "f32x{}", n),
633 Self::VecF64(n) => write!(f, "f64x{}", n),
634 }
635 }
636 }
637
638 /// Returns the full set of allocatable registers for a given architecture.
639 ///
640 /// The registers are structured as a map containing the set of allocatable
641 /// registers in each register class. A particular register may be allocatable
642 /// from multiple register classes, in which case it will appear multiple times
643 /// in the map.
644 // NOTE: This function isn't used at the moment, but is needed to support
645 // falling back to an external assembler.
646 pub fn allocatable_registers(
647 arch: InlineAsmArch,
648 has_feature: impl FnMut(&str) -> bool,
649 target: &crate::spec::Target,
650 ) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> {
651 match arch {
652 InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
653 let mut map = x86::regclass_map();
654 x86::fill_reg_map(arch, has_feature, target, &mut map);
655 map
656 }
657 InlineAsmArch::Arm => {
658 let mut map = arm::regclass_map();
659 arm::fill_reg_map(arch, has_feature, target, &mut map);
660 map
661 }
662 InlineAsmArch::AArch64 => {
663 let mut map = aarch64::regclass_map();
664 aarch64::fill_reg_map(arch, has_feature, target, &mut map);
665 map
666 }
667 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
668 let mut map = riscv::regclass_map();
669 riscv::fill_reg_map(arch, has_feature, target, &mut map);
670 map
671 }
672 InlineAsmArch::Nvptx64 => {
673 let mut map = nvptx::regclass_map();
674 nvptx::fill_reg_map(arch, has_feature, target, &mut map);
675 map
676 }
677 InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
678 let mut map = powerpc::regclass_map();
679 powerpc::fill_reg_map(arch, has_feature, target, &mut map);
680 map
681 }
682 InlineAsmArch::Hexagon => {
683 let mut map = hexagon::regclass_map();
684 hexagon::fill_reg_map(arch, has_feature, target, &mut map);
685 map
686 }
687 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
688 let mut map = mips::regclass_map();
689 mips::fill_reg_map(arch, has_feature, target, &mut map);
690 map
691 }
692 InlineAsmArch::SpirV => {
693 let mut map = spirv::regclass_map();
694 spirv::fill_reg_map(arch, has_feature, target, &mut map);
695 map
696 }
697 InlineAsmArch::Wasm32 => {
698 let mut map = wasm::regclass_map();
699 wasm::fill_reg_map(arch, has_feature, target, &mut map);
700 map
701 }
702 InlineAsmArch::Bpf => {
703 let mut map = bpf::regclass_map();
704 bpf::fill_reg_map(arch, has_feature, target, &mut map);
705 map
706 }
707 }
708 }