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 hexagon;
152 mod mips;
153 mod nvptx;
154 mod powerpc;
155 mod riscv;
156 mod spirv;
157 mod wasm;
158 mod x86;
159
160 pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass};
161 pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass};
162 pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass};
163 pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass};
164 pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
165 pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass};
166 pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
167 pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
168 pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
169 pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
170
171 #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash)]
172 pub enum InlineAsmArch {
173 X86,
174 X86_64,
175 Arm,
176 AArch64,
177 RiscV32,
178 RiscV64,
179 Nvptx64,
180 Hexagon,
181 Mips,
182 Mips64,
183 PowerPC,
184 PowerPC64,
185 SpirV,
186 Wasm32,
187 }
188
189 impl FromStr for InlineAsmArch {
190 type Err = ();
191
from_str(s: &str) -> Result<InlineAsmArch, ()>192 fn from_str(s: &str) -> Result<InlineAsmArch, ()> {
193 match s {
194 "x86" => Ok(Self::X86),
195 "x86_64" => Ok(Self::X86_64),
196 "arm" => Ok(Self::Arm),
197 "aarch64" => Ok(Self::AArch64),
198 "riscv32" => Ok(Self::RiscV32),
199 "riscv64" => Ok(Self::RiscV64),
200 "nvptx64" => Ok(Self::Nvptx64),
201 "powerpc" => Ok(Self::PowerPC),
202 "powerpc64" => Ok(Self::PowerPC64),
203 "hexagon" => Ok(Self::Hexagon),
204 "mips" => Ok(Self::Mips),
205 "mips64" => Ok(Self::Mips64),
206 "spirv" => Ok(Self::SpirV),
207 "wasm32" => Ok(Self::Wasm32),
208 _ => Err(()),
209 }
210 }
211 }
212
213 #[derive(
214 Copy,
215 Clone,
216 Encodable,
217 Decodable,
218 Debug,
219 Eq,
220 PartialEq,
221 PartialOrd,
222 Hash,
223 HashStable_Generic
224 )]
225 pub enum InlineAsmReg {
226 X86(X86InlineAsmReg),
227 Arm(ArmInlineAsmReg),
228 AArch64(AArch64InlineAsmReg),
229 RiscV(RiscVInlineAsmReg),
230 Nvptx(NvptxInlineAsmReg),
231 PowerPC(PowerPCInlineAsmReg),
232 Hexagon(HexagonInlineAsmReg),
233 Mips(MipsInlineAsmReg),
234 SpirV(SpirVInlineAsmReg),
235 Wasm(WasmInlineAsmReg),
236 // Placeholder for invalid register constraints for the current target
237 Err,
238 }
239
240 impl InlineAsmReg {
name(self) -> &'static str241 pub fn name(self) -> &'static str {
242 match self {
243 Self::X86(r) => r.name(),
244 Self::Arm(r) => r.name(),
245 Self::AArch64(r) => r.name(),
246 Self::RiscV(r) => r.name(),
247 Self::PowerPC(r) => r.name(),
248 Self::Hexagon(r) => r.name(),
249 Self::Mips(r) => r.name(),
250 Self::Err => "<reg>",
251 }
252 }
253
reg_class(self) -> InlineAsmRegClass254 pub fn reg_class(self) -> InlineAsmRegClass {
255 match self {
256 Self::X86(r) => InlineAsmRegClass::X86(r.reg_class()),
257 Self::Arm(r) => InlineAsmRegClass::Arm(r.reg_class()),
258 Self::AArch64(r) => InlineAsmRegClass::AArch64(r.reg_class()),
259 Self::RiscV(r) => InlineAsmRegClass::RiscV(r.reg_class()),
260 Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()),
261 Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
262 Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
263 Self::Err => InlineAsmRegClass::Err,
264 }
265 }
266
parse( arch: InlineAsmArch, has_feature: impl FnMut(&str) -> bool, target: &Target, name: Symbol, ) -> Result<Self, &'static str>267 pub fn parse(
268 arch: InlineAsmArch,
269 has_feature: impl FnMut(&str) -> bool,
270 target: &Target,
271 name: Symbol,
272 ) -> Result<Self, &'static str> {
273 // FIXME: use direct symbol comparison for register names
274 // Use `Symbol::as_str` instead of `Symbol::with` here because `has_feature` may access `Symbol`.
275 let name = name.as_str();
276 Ok(match arch {
277 InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
278 Self::X86(X86InlineAsmReg::parse(arch, has_feature, target, &name)?)
279 }
280 InlineAsmArch::Arm => {
281 Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, target, &name)?)
282 }
283 InlineAsmArch::AArch64 => {
284 Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, target, &name)?)
285 }
286 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
287 Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, target, &name)?)
288 }
289 InlineAsmArch::Nvptx64 => {
290 Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, &name)?)
291 }
292 InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
293 Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, &name)?)
294 }
295 InlineAsmArch::Hexagon => {
296 Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, &name)?)
297 }
298 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
299 Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?)
300 }
301 InlineAsmArch::SpirV => {
302 Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?)
303 }
304 InlineAsmArch::Wasm32 => {
305 Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?)
306 }
307 })
308 }
309
310 // NOTE: This function isn't used at the moment, but is needed to support
311 // falling back to an external assembler.
emit( self, out: &mut dyn fmt::Write, arch: InlineAsmArch, modifier: Option<char>, ) -> fmt::Result312 pub fn emit(
313 self,
314 out: &mut dyn fmt::Write,
315 arch: InlineAsmArch,
316 modifier: Option<char>,
317 ) -> fmt::Result {
318 match self {
319 Self::X86(r) => r.emit(out, arch, modifier),
320 Self::Arm(r) => r.emit(out, arch, modifier),
321 Self::AArch64(r) => r.emit(out, arch, modifier),
322 Self::RiscV(r) => r.emit(out, arch, modifier),
323 Self::PowerPC(r) => r.emit(out, arch, modifier),
324 Self::Hexagon(r) => r.emit(out, arch, modifier),
325 Self::Mips(r) => r.emit(out, arch, modifier),
326 Self::Err => unreachable!("Use of InlineAsmReg::Err"),
327 }
328 }
329
overlapping_regs(self, mut cb: impl FnMut(InlineAsmReg))330 pub fn overlapping_regs(self, mut cb: impl FnMut(InlineAsmReg)) {
331 match self {
332 Self::X86(r) => r.overlapping_regs(|r| cb(Self::X86(r))),
333 Self::Arm(r) => r.overlapping_regs(|r| cb(Self::Arm(r))),
334 Self::AArch64(_) => cb(self),
335 Self::RiscV(_) => cb(self),
336 Self::PowerPC(_) => cb(self),
337 Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
338 Self::Mips(_) => cb(self),
339 Self::Err => unreachable!("Use of InlineAsmReg::Err"),
340 }
341 }
342 }
343
344 #[derive(
345 Copy,
346 Clone,
347 Encodable,
348 Decodable,
349 Debug,
350 Eq,
351 PartialEq,
352 PartialOrd,
353 Hash,
354 HashStable_Generic
355 )]
356 pub enum InlineAsmRegClass {
357 X86(X86InlineAsmRegClass),
358 Arm(ArmInlineAsmRegClass),
359 AArch64(AArch64InlineAsmRegClass),
360 RiscV(RiscVInlineAsmRegClass),
361 Nvptx(NvptxInlineAsmRegClass),
362 PowerPC(PowerPCInlineAsmRegClass),
363 Hexagon(HexagonInlineAsmRegClass),
364 Mips(MipsInlineAsmRegClass),
365 SpirV(SpirVInlineAsmRegClass),
366 Wasm(WasmInlineAsmRegClass),
367 // Placeholder for invalid register constraints for the current target
368 Err,
369 }
370
371 impl InlineAsmRegClass {
name(self) -> Symbol372 pub fn name(self) -> Symbol {
373 match self {
374 Self::X86(r) => r.name(),
375 Self::Arm(r) => r.name(),
376 Self::AArch64(r) => r.name(),
377 Self::RiscV(r) => r.name(),
378 Self::Nvptx(r) => r.name(),
379 Self::PowerPC(r) => r.name(),
380 Self::Hexagon(r) => r.name(),
381 Self::Mips(r) => r.name(),
382 Self::SpirV(r) => r.name(),
383 Self::Wasm(r) => r.name(),
384 Self::Err => rustc_span::symbol::sym::reg,
385 }
386 }
387
388 /// Returns a suggested register class to use for this type. This is called
389 /// after type checking via `supported_types` fails to give a better error
390 /// message to the user.
suggest_class(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option<Self>391 pub fn suggest_class(self, arch: InlineAsmArch, ty: InlineAsmType) -> Option<Self> {
392 match self {
393 Self::X86(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::X86),
394 Self::Arm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Arm),
395 Self::AArch64(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::AArch64),
396 Self::RiscV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::RiscV),
397 Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx),
398 Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC),
399 Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon),
400 Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
401 Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
402 Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
403 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
404 }
405 }
406
407 /// Returns a suggested template modifier to use for this type and an
408 /// example of a register named formatted with it.
409 ///
410 /// Such suggestions are useful if a type smaller than the full register
411 /// size is used and a modifier can be used to point to the subregister of
412 /// the correct size.
suggest_modifier( self, arch: InlineAsmArch, ty: InlineAsmType, ) -> Option<(char, &'static str)>413 pub fn suggest_modifier(
414 self,
415 arch: InlineAsmArch,
416 ty: InlineAsmType,
417 ) -> Option<(char, &'static str)> {
418 match self {
419 Self::X86(r) => r.suggest_modifier(arch, ty),
420 Self::Arm(r) => r.suggest_modifier(arch, ty),
421 Self::AArch64(r) => r.suggest_modifier(arch, ty),
422 Self::RiscV(r) => r.suggest_modifier(arch, ty),
423 Self::Nvptx(r) => r.suggest_modifier(arch, ty),
424 Self::PowerPC(r) => r.suggest_modifier(arch, ty),
425 Self::Hexagon(r) => r.suggest_modifier(arch, ty),
426 Self::Mips(r) => r.suggest_modifier(arch, ty),
427 Self::SpirV(r) => r.suggest_modifier(arch, ty),
428 Self::Wasm(r) => r.suggest_modifier(arch, ty),
429 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
430 }
431 }
432
433 /// Returns the default modifier for this register and an example of a
434 /// register named formatted with it.
435 ///
436 /// This is only needed when the register class can suggest a modifier, so
437 /// that the user can be shown how to get the default behavior without a
438 /// warning.
default_modifier(self, arch: InlineAsmArch) -> Option<(char, &'static str)>439 pub fn default_modifier(self, arch: InlineAsmArch) -> Option<(char, &'static str)> {
440 match self {
441 Self::X86(r) => r.default_modifier(arch),
442 Self::Arm(r) => r.default_modifier(arch),
443 Self::AArch64(r) => r.default_modifier(arch),
444 Self::RiscV(r) => r.default_modifier(arch),
445 Self::Nvptx(r) => r.default_modifier(arch),
446 Self::PowerPC(r) => r.default_modifier(arch),
447 Self::Hexagon(r) => r.default_modifier(arch),
448 Self::Mips(r) => r.default_modifier(arch),
449 Self::SpirV(r) => r.default_modifier(arch),
450 Self::Wasm(r) => r.default_modifier(arch),
451 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
452 }
453 }
454
455 /// Returns a list of supported types for this register class, each with a
456 /// options target feature required to use this type.
supported_types( self, arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option<&'static str>)]457 pub fn supported_types(
458 self,
459 arch: InlineAsmArch,
460 ) -> &'static [(InlineAsmType, Option<&'static str>)] {
461 match self {
462 Self::X86(r) => r.supported_types(arch),
463 Self::Arm(r) => r.supported_types(arch),
464 Self::AArch64(r) => r.supported_types(arch),
465 Self::RiscV(r) => r.supported_types(arch),
466 Self::Nvptx(r) => r.supported_types(arch),
467 Self::PowerPC(r) => r.supported_types(arch),
468 Self::Hexagon(r) => r.supported_types(arch),
469 Self::Mips(r) => r.supported_types(arch),
470 Self::SpirV(r) => r.supported_types(arch),
471 Self::Wasm(r) => r.supported_types(arch),
472 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
473 }
474 }
475
parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str>476 pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> {
477 Ok(match arch {
478 InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
479 Self::X86(X86InlineAsmRegClass::parse(arch, name)?)
480 }
481 InlineAsmArch::Arm => Self::Arm(ArmInlineAsmRegClass::parse(arch, name)?),
482 InlineAsmArch::AArch64 => Self::AArch64(AArch64InlineAsmRegClass::parse(arch, name)?),
483 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
484 Self::RiscV(RiscVInlineAsmRegClass::parse(arch, name)?)
485 }
486 InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?),
487 InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
488 Self::PowerPC(PowerPCInlineAsmRegClass::parse(arch, name)?)
489 }
490 InlineAsmArch::Hexagon => Self::Hexagon(HexagonInlineAsmRegClass::parse(arch, name)?),
491 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
492 Self::Mips(MipsInlineAsmRegClass::parse(arch, name)?)
493 }
494 InlineAsmArch::SpirV => Self::SpirV(SpirVInlineAsmRegClass::parse(arch, name)?),
495 InlineAsmArch::Wasm32 => Self::Wasm(WasmInlineAsmRegClass::parse(arch, name)?),
496 })
497 }
498
499 /// Returns the list of template modifiers that can be used with this
500 /// register class.
valid_modifiers(self, arch: InlineAsmArch) -> &'static [char]501 pub fn valid_modifiers(self, arch: InlineAsmArch) -> &'static [char] {
502 match self {
503 Self::X86(r) => r.valid_modifiers(arch),
504 Self::Arm(r) => r.valid_modifiers(arch),
505 Self::AArch64(r) => r.valid_modifiers(arch),
506 Self::RiscV(r) => r.valid_modifiers(arch),
507 Self::Nvptx(r) => r.valid_modifiers(arch),
508 Self::PowerPC(r) => r.valid_modifiers(arch),
509 Self::Hexagon(r) => r.valid_modifiers(arch),
510 Self::Mips(r) => r.valid_modifiers(arch),
511 Self::SpirV(r) => r.valid_modifiers(arch),
512 Self::Wasm(r) => r.valid_modifiers(arch),
513 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
514 }
515 }
516 }
517
518 #[derive(
519 Copy,
520 Clone,
521 Encodable,
522 Decodable,
523 Debug,
524 Eq,
525 PartialEq,
526 PartialOrd,
527 Hash,
528 HashStable_Generic
529 )]
530 pub enum InlineAsmRegOrRegClass {
531 Reg(InlineAsmReg),
532 RegClass(InlineAsmRegClass),
533 }
534
535 impl InlineAsmRegOrRegClass {
reg_class(self) -> InlineAsmRegClass536 pub fn reg_class(self) -> InlineAsmRegClass {
537 match self {
538 Self::Reg(r) => r.reg_class(),
539 Self::RegClass(r) => r,
540 }
541 }
542 }
543
544 impl fmt::Display for InlineAsmRegOrRegClass {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result545 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546 match self {
547 Self::Reg(r) => write!(f, "\"{}\"", r.name()),
548 Self::RegClass(r) => write!(f, "{}", r.name()),
549 }
550 }
551 }
552
553 /// Set of types which can be used with a particular register class.
554 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
555 pub enum InlineAsmType {
556 I8,
557 I16,
558 I32,
559 I64,
560 I128,
561 F32,
562 F64,
563 VecI8(u64),
564 VecI16(u64),
565 VecI32(u64),
566 VecI64(u64),
567 VecI128(u64),
568 VecF32(u64),
569 VecF64(u64),
570 }
571
572 impl InlineAsmType {
is_integer(self) -> bool573 pub fn is_integer(self) -> bool {
574 matches!(self, Self::I8 | Self::I16 | Self::I32 | Self::I64 | Self::I128)
575 }
576
size(self) -> Size577 pub fn size(self) -> Size {
578 Size::from_bytes(match self {
579 Self::I8 => 1,
580 Self::I16 => 2,
581 Self::I32 => 4,
582 Self::I64 => 8,
583 Self::I128 => 16,
584 Self::F32 => 4,
585 Self::F64 => 8,
586 Self::VecI8(n) => n * 1,
587 Self::VecI16(n) => n * 2,
588 Self::VecI32(n) => n * 4,
589 Self::VecI64(n) => n * 8,
590 Self::VecI128(n) => n * 16,
591 Self::VecF32(n) => n * 4,
592 Self::VecF64(n) => n * 8,
593 })
594 }
595 }
596
597 impl fmt::Display for InlineAsmType {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result598 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
599 match *self {
600 Self::I8 => f.write_str("i8"),
601 Self::I16 => f.write_str("i16"),
602 Self::I32 => f.write_str("i32"),
603 Self::I64 => f.write_str("i64"),
604 Self::I128 => f.write_str("i128"),
605 Self::F32 => f.write_str("f32"),
606 Self::F64 => f.write_str("f64"),
607 Self::VecI8(n) => write!(f, "i8x{}", n),
608 Self::VecI16(n) => write!(f, "i16x{}", n),
609 Self::VecI32(n) => write!(f, "i32x{}", n),
610 Self::VecI64(n) => write!(f, "i64x{}", n),
611 Self::VecI128(n) => write!(f, "i128x{}", n),
612 Self::VecF32(n) => write!(f, "f32x{}", n),
613 Self::VecF64(n) => write!(f, "f64x{}", n),
614 }
615 }
616 }
617
618 /// Returns the full set of allocatable registers for a given architecture.
619 ///
620 /// The registers are structured as a map containing the set of allocatable
621 /// registers in each register class. A particular register may be allocatable
622 /// from multiple register classes, in which case it will appear multiple times
623 /// in the map.
624 // NOTE: This function isn't used at the moment, but is needed to support
625 // falling back to an external assembler.
allocatable_registers( arch: InlineAsmArch, has_feature: impl FnMut(&str) -> bool, target: &crate::spec::Target, ) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>>626 pub fn allocatable_registers(
627 arch: InlineAsmArch,
628 has_feature: impl FnMut(&str) -> bool,
629 target: &crate::spec::Target,
630 ) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> {
631 match arch {
632 InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
633 let mut map = x86::regclass_map();
634 x86::fill_reg_map(arch, has_feature, target, &mut map);
635 map
636 }
637 InlineAsmArch::Arm => {
638 let mut map = arm::regclass_map();
639 arm::fill_reg_map(arch, has_feature, target, &mut map);
640 map
641 }
642 InlineAsmArch::AArch64 => {
643 let mut map = aarch64::regclass_map();
644 aarch64::fill_reg_map(arch, has_feature, target, &mut map);
645 map
646 }
647 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
648 let mut map = riscv::regclass_map();
649 riscv::fill_reg_map(arch, has_feature, target, &mut map);
650 map
651 }
652 InlineAsmArch::Nvptx64 => {
653 let mut map = nvptx::regclass_map();
654 nvptx::fill_reg_map(arch, has_feature, target, &mut map);
655 map
656 }
657 InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
658 let mut map = powerpc::regclass_map();
659 powerpc::fill_reg_map(arch, has_feature, target, &mut map);
660 map
661 }
662 InlineAsmArch::Hexagon => {
663 let mut map = hexagon::regclass_map();
664 hexagon::fill_reg_map(arch, has_feature, target, &mut map);
665 map
666 }
667 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
668 let mut map = mips::regclass_map();
669 mips::fill_reg_map(arch, has_feature, target, &mut map);
670 map
671 }
672 InlineAsmArch::SpirV => {
673 let mut map = spirv::regclass_map();
674 spirv::fill_reg_map(arch, has_feature, target, &mut map);
675 map
676 }
677 InlineAsmArch::Wasm32 => {
678 let mut map = wasm::regclass_map();
679 wasm::fill_reg_map(arch, has_feature, target, &mut map);
680 map
681 }
682 }
683 }
684