1 use crate::spec
::Target
;
2 use crate::{abi::Size, spec::RelocModel}
;
3 use rustc_data_structures
::fx
::{FxHashMap, FxHashSet}
;
4 use rustc_macros
::HashStable_Generic
;
5 use rustc_span
::Symbol
;
9 macro_rules
! def_reg_class
{
10 ($arch
:ident $arch_regclass
:ident
{
15 #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, PartialOrd, Hash, HashStable_Generic)]
16 #[allow(non_camel_case_types)]
17 pub enum $arch_regclass
{
22 pub fn name(self) -> rustc_span
::Symbol
{
24 $
(Self::$class
=> rustc_span
::symbol
::sym
::$class
,)*
28 pub fn parse(name
: rustc_span
::Symbol
) -> Result
<Self, &'
static str> {
31 rustc_span
::sym
::$class
=> Ok(Self::$class
),
33 _
=> Err("unknown register class"),
38 pub(super) fn regclass_map() -> rustc_data_structures
::fx
::FxHashMap
<
39 super::InlineAsmRegClass
,
40 rustc_data_structures
::fx
::FxHashSet
<super::InlineAsmReg
>,
42 use rustc_data_structures
::fx
::{FxHashMap, FxHashSet}
;
43 use super::InlineAsmRegClass
;
44 let mut map
= FxHashMap
::default();
46 map
.insert(InlineAsmRegClass
::$
arch($arch_regclass
::$class
), FxHashSet
::default());
53 macro_rules
! def_regs
{
54 ($arch
:ident $arch_reg
:ident $arch_regclass
:ident
{
56 $reg
:ident
: $class
:ident $
(, $extra_class
:ident
)* = [$reg_name
:literal $
(, $alias
:literal
)*] $
(% $filter
:ident
)?
,
59 #error = [$($bad_reg:literal),+] => $error:literal,
62 #[allow(unreachable_code)]
63 #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, PartialOrd, Hash, HashStable_Generic)]
64 #[allow(non_camel_case_types)]
70 pub fn name(self) -> &'
static str {
72 $
(Self::$reg
=> $reg_name
,)*
76 pub fn reg_class(self) -> $arch_regclass
{
78 $
(Self::$reg
=> $arch_regclass
::$class
,)*
82 pub fn parse(name
: &str) -> Result
<Self, &'
static str> {
85 $
($alias
)|* | $reg_name
=> Ok(Self::$reg
),
88 $
($bad_reg
)|* => Err($error
),
90 _
=> Err("unknown register"),
95 _arch
: super::InlineAsmArch
,
96 _reloc_model
: crate::spec
::RelocModel
,
97 _target_features
: &rustc_data_structures
::fx
::FxHashSet
<Symbol
>,
98 _target
: &crate::spec
::Target
,
100 ) -> Result
<(), &'
static str> {
118 pub(super) fn fill_reg_map(
119 _arch
: super::InlineAsmArch
,
120 _reloc_model
: crate::spec
::RelocModel
,
121 _target_features
: &rustc_data_structures
::fx
::FxHashSet
<Symbol
>,
122 _target
: &crate::spec
::Target
,
123 _map
: &mut rustc_data_structures
::fx
::FxHashMap
<
124 super::InlineAsmRegClass
,
125 rustc_data_structures
::fx
::FxHashSet
<super::InlineAsmReg
>,
128 #[allow(unused_imports)]
129 use super::{InlineAsmReg, InlineAsmRegClass}
;
131 if $
($
filter(_arch
, _reloc_model
, _target_features
, _target
, false).is_ok() &&)?
true {
132 if let Some(set
) = _map
.get_mut(&InlineAsmRegClass
::$
arch($arch_regclass
::$class
)) {
133 set
.insert(InlineAsmReg
::$
arch($arch_reg
::$reg
));
136 if let Some(set
) = _map
.get_mut(&InlineAsmRegClass
::$
arch($arch_regclass
::$extra_class
)) {
137 set
.insert(InlineAsmReg
::$
arch($arch_reg
::$reg
));
148 $
(_
: $
($ty
:expr
),+;)?
149 $
($feature
:ident
: $
($ty2
:expr
),+;)*
152 use super::InlineAsmType
::*;
158 ($ty2
, Some(rustc_span
::sym
::$feature
)),
180 pub use aarch64
::{AArch64InlineAsmReg, AArch64InlineAsmRegClass}
;
181 pub use arm
::{ArmInlineAsmReg, ArmInlineAsmRegClass}
;
182 pub use avr
::{AvrInlineAsmReg, AvrInlineAsmRegClass}
;
183 pub use bpf
::{BpfInlineAsmReg, BpfInlineAsmRegClass}
;
184 pub use hexagon
::{HexagonInlineAsmReg, HexagonInlineAsmRegClass}
;
185 pub use mips
::{MipsInlineAsmReg, MipsInlineAsmRegClass}
;
186 pub use msp430
::{Msp430InlineAsmReg, Msp430InlineAsmRegClass}
;
187 pub use nvptx
::{NvptxInlineAsmReg, NvptxInlineAsmRegClass}
;
188 pub use powerpc
::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass}
;
189 pub use riscv
::{RiscVInlineAsmReg, RiscVInlineAsmRegClass}
;
190 pub use s390x
::{S390xInlineAsmReg, S390xInlineAsmRegClass}
;
191 pub use spirv
::{SpirVInlineAsmReg, SpirVInlineAsmRegClass}
;
192 pub use wasm
::{WasmInlineAsmReg, WasmInlineAsmRegClass}
;
193 pub use x86
::{X86InlineAsmReg, X86InlineAsmRegClass}
;
195 #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash)]
196 pub enum InlineAsmArch
{
218 impl FromStr
for InlineAsmArch
{
221 fn from_str(s
: &str) -> Result
<InlineAsmArch
, ()> {
223 "x86" => Ok(Self::X86
),
224 "x86_64" => Ok(Self::X86_64
),
225 "arm" => Ok(Self::Arm
),
226 "aarch64" => Ok(Self::AArch64
),
227 "riscv32" => Ok(Self::RiscV32
),
228 "riscv64" => Ok(Self::RiscV64
),
229 "nvptx64" => Ok(Self::Nvptx64
),
230 "powerpc" => Ok(Self::PowerPC
),
231 "powerpc64" => Ok(Self::PowerPC64
),
232 "hexagon" => Ok(Self::Hexagon
),
233 "mips" => Ok(Self::Mips
),
234 "mips64" => Ok(Self::Mips64
),
235 "s390x" => Ok(Self::S390x
),
236 "spirv" => Ok(Self::SpirV
),
237 "wasm32" => Ok(Self::Wasm32
),
238 "wasm64" => Ok(Self::Wasm64
),
239 "bpf" => Ok(Self::Bpf
),
240 "avr" => Ok(Self::Avr
),
241 "msp430" => Ok(Self::Msp430
),
259 pub enum InlineAsmReg
{
260 X86(X86InlineAsmReg
),
261 Arm(ArmInlineAsmReg
),
262 AArch64(AArch64InlineAsmReg
),
263 RiscV(RiscVInlineAsmReg
),
264 Nvptx(NvptxInlineAsmReg
),
265 PowerPC(PowerPCInlineAsmReg
),
266 Hexagon(HexagonInlineAsmReg
),
267 Mips(MipsInlineAsmReg
),
268 S390x(S390xInlineAsmReg
),
269 SpirV(SpirVInlineAsmReg
),
270 Wasm(WasmInlineAsmReg
),
271 Bpf(BpfInlineAsmReg
),
272 Avr(AvrInlineAsmReg
),
273 Msp430(Msp430InlineAsmReg
),
274 // Placeholder for invalid register constraints for the current target
279 pub fn name(self) -> &'
static str {
281 Self::X86(r
) => r
.name(),
282 Self::Arm(r
) => r
.name(),
283 Self::AArch64(r
) => r
.name(),
284 Self::RiscV(r
) => r
.name(),
285 Self::PowerPC(r
) => r
.name(),
286 Self::Hexagon(r
) => r
.name(),
287 Self::Mips(r
) => r
.name(),
288 Self::S390x(r
) => r
.name(),
289 Self::Bpf(r
) => r
.name(),
290 Self::Avr(r
) => r
.name(),
291 Self::Msp430(r
) => r
.name(),
292 Self::Err
=> "<reg>",
296 pub fn reg_class(self) -> InlineAsmRegClass
{
298 Self::X86(r
) => InlineAsmRegClass
::X86(r
.reg_class()),
299 Self::Arm(r
) => InlineAsmRegClass
::Arm(r
.reg_class()),
300 Self::AArch64(r
) => InlineAsmRegClass
::AArch64(r
.reg_class()),
301 Self::RiscV(r
) => InlineAsmRegClass
::RiscV(r
.reg_class()),
302 Self::PowerPC(r
) => InlineAsmRegClass
::PowerPC(r
.reg_class()),
303 Self::Hexagon(r
) => InlineAsmRegClass
::Hexagon(r
.reg_class()),
304 Self::Mips(r
) => InlineAsmRegClass
::Mips(r
.reg_class()),
305 Self::S390x(r
) => InlineAsmRegClass
::S390x(r
.reg_class()),
306 Self::Bpf(r
) => InlineAsmRegClass
::Bpf(r
.reg_class()),
307 Self::Avr(r
) => InlineAsmRegClass
::Avr(r
.reg_class()),
308 Self::Msp430(r
) => InlineAsmRegClass
::Msp430(r
.reg_class()),
309 Self::Err
=> InlineAsmRegClass
::Err
,
313 pub fn parse(arch
: InlineAsmArch
, name
: Symbol
) -> Result
<Self, &'
static str> {
314 // FIXME: use direct symbol comparison for register names
315 // Use `Symbol::as_str` instead of `Symbol::with` here because `has_feature` may access `Symbol`.
316 let name
= name
.as_str();
318 InlineAsmArch
::X86
| InlineAsmArch
::X86_64
=> Self::X86(X86InlineAsmReg
::parse(name
)?
),
319 InlineAsmArch
::Arm
=> Self::Arm(ArmInlineAsmReg
::parse(name
)?
),
320 InlineAsmArch
::AArch64
=> Self::AArch64(AArch64InlineAsmReg
::parse(name
)?
),
321 InlineAsmArch
::RiscV32
| InlineAsmArch
::RiscV64
=> {
322 Self::RiscV(RiscVInlineAsmReg
::parse(name
)?
)
324 InlineAsmArch
::Nvptx64
=> Self::Nvptx(NvptxInlineAsmReg
::parse(name
)?
),
325 InlineAsmArch
::PowerPC
| InlineAsmArch
::PowerPC64
=> {
326 Self::PowerPC(PowerPCInlineAsmReg
::parse(name
)?
)
328 InlineAsmArch
::Hexagon
=> Self::Hexagon(HexagonInlineAsmReg
::parse(name
)?
),
329 InlineAsmArch
::Mips
| InlineAsmArch
::Mips64
=> {
330 Self::Mips(MipsInlineAsmReg
::parse(name
)?
)
332 InlineAsmArch
::S390x
=> Self::S390x(S390xInlineAsmReg
::parse(name
)?
),
333 InlineAsmArch
::SpirV
=> Self::SpirV(SpirVInlineAsmReg
::parse(name
)?
),
334 InlineAsmArch
::Wasm32
| InlineAsmArch
::Wasm64
=> {
335 Self::Wasm(WasmInlineAsmReg
::parse(name
)?
)
337 InlineAsmArch
::Bpf
=> Self::Bpf(BpfInlineAsmReg
::parse(name
)?
),
338 InlineAsmArch
::Avr
=> Self::Avr(AvrInlineAsmReg
::parse(name
)?
),
339 InlineAsmArch
::Msp430
=> Self::Msp430(Msp430InlineAsmReg
::parse(name
)?
),
346 reloc_model
: RelocModel
,
347 target_features
: &FxHashSet
<Symbol
>,
350 ) -> Result
<(), &'
static str> {
352 Self::X86(r
) => r
.validate(arch
, reloc_model
, target_features
, target
, is_clobber
),
353 Self::Arm(r
) => r
.validate(arch
, reloc_model
, target_features
, target
, is_clobber
),
354 Self::AArch64(r
) => r
.validate(arch
, reloc_model
, target_features
, target
, is_clobber
),
355 Self::RiscV(r
) => r
.validate(arch
, reloc_model
, target_features
, target
, is_clobber
),
356 Self::PowerPC(r
) => r
.validate(arch
, reloc_model
, target_features
, target
, is_clobber
),
357 Self::Hexagon(r
) => r
.validate(arch
, reloc_model
, target_features
, target
, is_clobber
),
358 Self::Mips(r
) => r
.validate(arch
, reloc_model
, target_features
, target
, is_clobber
),
359 Self::S390x(r
) => r
.validate(arch
, reloc_model
, target_features
, target
, is_clobber
),
360 Self::Bpf(r
) => r
.validate(arch
, reloc_model
, target_features
, target
, is_clobber
),
361 Self::Avr(r
) => r
.validate(arch
, reloc_model
, target_features
, target
, is_clobber
),
362 Self::Msp430(r
) => r
.validate(arch
, reloc_model
, target_features
, target
, is_clobber
),
363 Self::Err
=> unreachable
!(),
367 // NOTE: This function isn't used at the moment, but is needed to support
368 // falling back to an external assembler.
371 out
: &mut dyn fmt
::Write
,
373 modifier
: Option
<char>,
376 Self::X86(r
) => r
.emit(out
, arch
, modifier
),
377 Self::Arm(r
) => r
.emit(out
, arch
, modifier
),
378 Self::AArch64(r
) => r
.emit(out
, arch
, modifier
),
379 Self::RiscV(r
) => r
.emit(out
, arch
, modifier
),
380 Self::PowerPC(r
) => r
.emit(out
, arch
, modifier
),
381 Self::Hexagon(r
) => r
.emit(out
, arch
, modifier
),
382 Self::Mips(r
) => r
.emit(out
, arch
, modifier
),
383 Self::S390x(r
) => r
.emit(out
, arch
, modifier
),
384 Self::Bpf(r
) => r
.emit(out
, arch
, modifier
),
385 Self::Avr(r
) => r
.emit(out
, arch
, modifier
),
386 Self::Msp430(r
) => r
.emit(out
, arch
, modifier
),
387 Self::Err
=> unreachable
!("Use of InlineAsmReg::Err"),
391 pub fn overlapping_regs(self, mut cb
: impl FnMut(InlineAsmReg
)) {
393 Self::X86(r
) => r
.overlapping_regs(|r
| cb(Self::X86(r
))),
394 Self::Arm(r
) => r
.overlapping_regs(|r
| cb(Self::Arm(r
))),
395 Self::AArch64(_
) => cb(self),
396 Self::RiscV(_
) => cb(self),
397 Self::PowerPC(r
) => r
.overlapping_regs(|r
| cb(Self::PowerPC(r
))),
398 Self::Hexagon(r
) => r
.overlapping_regs(|r
| cb(Self::Hexagon(r
))),
399 Self::Mips(_
) => cb(self),
400 Self::S390x(_
) => cb(self),
401 Self::Bpf(r
) => r
.overlapping_regs(|r
| cb(Self::Bpf(r
))),
402 Self::Avr(r
) => r
.overlapping_regs(|r
| cb(Self::Avr(r
))),
403 Self::Msp430(_
) => cb(self),
404 Self::Err
=> unreachable
!("Use of InlineAsmReg::Err"),
421 pub enum InlineAsmRegClass
{
422 X86(X86InlineAsmRegClass
),
423 Arm(ArmInlineAsmRegClass
),
424 AArch64(AArch64InlineAsmRegClass
),
425 RiscV(RiscVInlineAsmRegClass
),
426 Nvptx(NvptxInlineAsmRegClass
),
427 PowerPC(PowerPCInlineAsmRegClass
),
428 Hexagon(HexagonInlineAsmRegClass
),
429 Mips(MipsInlineAsmRegClass
),
430 S390x(S390xInlineAsmRegClass
),
431 SpirV(SpirVInlineAsmRegClass
),
432 Wasm(WasmInlineAsmRegClass
),
433 Bpf(BpfInlineAsmRegClass
),
434 Avr(AvrInlineAsmRegClass
),
435 Msp430(Msp430InlineAsmRegClass
),
436 // Placeholder for invalid register constraints for the current target
440 impl InlineAsmRegClass
{
441 pub fn name(self) -> Symbol
{
443 Self::X86(r
) => r
.name(),
444 Self::Arm(r
) => r
.name(),
445 Self::AArch64(r
) => r
.name(),
446 Self::RiscV(r
) => r
.name(),
447 Self::Nvptx(r
) => r
.name(),
448 Self::PowerPC(r
) => r
.name(),
449 Self::Hexagon(r
) => r
.name(),
450 Self::Mips(r
) => r
.name(),
451 Self::S390x(r
) => r
.name(),
452 Self::SpirV(r
) => r
.name(),
453 Self::Wasm(r
) => r
.name(),
454 Self::Bpf(r
) => r
.name(),
455 Self::Avr(r
) => r
.name(),
456 Self::Msp430(r
) => r
.name(),
457 Self::Err
=> rustc_span
::symbol
::sym
::reg
,
461 /// Returns a suggested register class to use for this type. This is called
462 /// when `supported_types` fails to give a better error
463 /// message to the user.
464 pub fn suggest_class(self, arch
: InlineAsmArch
, ty
: InlineAsmType
) -> Option
<Self> {
466 Self::X86(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::X86
),
467 Self::Arm(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::Arm
),
468 Self::AArch64(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::AArch64
),
469 Self::RiscV(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::RiscV
),
470 Self::Nvptx(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::Nvptx
),
471 Self::PowerPC(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::PowerPC
),
472 Self::Hexagon(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::Hexagon
),
473 Self::Mips(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::Mips
),
474 Self::S390x(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::S390x
),
475 Self::SpirV(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::SpirV
),
476 Self::Wasm(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::Wasm
),
477 Self::Bpf(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::Bpf
),
478 Self::Avr(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::Avr
),
479 Self::Msp430(r
) => r
.suggest_class(arch
, ty
).map(InlineAsmRegClass
::Msp430
),
480 Self::Err
=> unreachable
!("Use of InlineAsmRegClass::Err"),
484 /// Returns a suggested template modifier to use for this type and an
485 /// example of a register named formatted with it.
487 /// Such suggestions are useful if a type smaller than the full register
488 /// size is used and a modifier can be used to point to the subregister of
489 /// the correct size.
490 pub fn suggest_modifier(
494 ) -> Option
<(char, &'
static str)> {
496 Self::X86(r
) => r
.suggest_modifier(arch
, ty
),
497 Self::Arm(r
) => r
.suggest_modifier(arch
, ty
),
498 Self::AArch64(r
) => r
.suggest_modifier(arch
, ty
),
499 Self::RiscV(r
) => r
.suggest_modifier(arch
, ty
),
500 Self::Nvptx(r
) => r
.suggest_modifier(arch
, ty
),
501 Self::PowerPC(r
) => r
.suggest_modifier(arch
, ty
),
502 Self::Hexagon(r
) => r
.suggest_modifier(arch
, ty
),
503 Self::Mips(r
) => r
.suggest_modifier(arch
, ty
),
504 Self::S390x(r
) => r
.suggest_modifier(arch
, ty
),
505 Self::SpirV(r
) => r
.suggest_modifier(arch
, ty
),
506 Self::Wasm(r
) => r
.suggest_modifier(arch
, ty
),
507 Self::Bpf(r
) => r
.suggest_modifier(arch
, ty
),
508 Self::Avr(r
) => r
.suggest_modifier(arch
, ty
),
509 Self::Msp430(r
) => r
.suggest_modifier(arch
, ty
),
510 Self::Err
=> unreachable
!("Use of InlineAsmRegClass::Err"),
514 /// Returns the default modifier for this register and an example of a
515 /// register named formatted with it.
517 /// This is only needed when the register class can suggest a modifier, so
518 /// that the user can be shown how to get the default behavior without a
520 pub fn default_modifier(self, arch
: InlineAsmArch
) -> Option
<(char, &'
static str)> {
522 Self::X86(r
) => r
.default_modifier(arch
),
523 Self::Arm(r
) => r
.default_modifier(arch
),
524 Self::AArch64(r
) => r
.default_modifier(arch
),
525 Self::RiscV(r
) => r
.default_modifier(arch
),
526 Self::Nvptx(r
) => r
.default_modifier(arch
),
527 Self::PowerPC(r
) => r
.default_modifier(arch
),
528 Self::Hexagon(r
) => r
.default_modifier(arch
),
529 Self::Mips(r
) => r
.default_modifier(arch
),
530 Self::S390x(r
) => r
.default_modifier(arch
),
531 Self::SpirV(r
) => r
.default_modifier(arch
),
532 Self::Wasm(r
) => r
.default_modifier(arch
),
533 Self::Bpf(r
) => r
.default_modifier(arch
),
534 Self::Avr(r
) => r
.default_modifier(arch
),
535 Self::Msp430(r
) => r
.default_modifier(arch
),
536 Self::Err
=> unreachable
!("Use of InlineAsmRegClass::Err"),
540 /// Returns a list of supported types for this register class, each with an
541 /// options target feature required to use this type.
542 pub fn supported_types(
545 ) -> &'
static [(InlineAsmType
, Option
<Symbol
>)] {
547 Self::X86(r
) => r
.supported_types(arch
),
548 Self::Arm(r
) => r
.supported_types(arch
),
549 Self::AArch64(r
) => r
.supported_types(arch
),
550 Self::RiscV(r
) => r
.supported_types(arch
),
551 Self::Nvptx(r
) => r
.supported_types(arch
),
552 Self::PowerPC(r
) => r
.supported_types(arch
),
553 Self::Hexagon(r
) => r
.supported_types(arch
),
554 Self::Mips(r
) => r
.supported_types(arch
),
555 Self::S390x(r
) => r
.supported_types(arch
),
556 Self::SpirV(r
) => r
.supported_types(arch
),
557 Self::Wasm(r
) => r
.supported_types(arch
),
558 Self::Bpf(r
) => r
.supported_types(arch
),
559 Self::Avr(r
) => r
.supported_types(arch
),
560 Self::Msp430(r
) => r
.supported_types(arch
),
561 Self::Err
=> unreachable
!("Use of InlineAsmRegClass::Err"),
565 pub fn parse(arch
: InlineAsmArch
, name
: Symbol
) -> Result
<Self, &'
static str> {
567 InlineAsmArch
::X86
| InlineAsmArch
::X86_64
=> {
568 Self::X86(X86InlineAsmRegClass
::parse(name
)?
)
570 InlineAsmArch
::Arm
=> Self::Arm(ArmInlineAsmRegClass
::parse(name
)?
),
571 InlineAsmArch
::AArch64
=> Self::AArch64(AArch64InlineAsmRegClass
::parse(name
)?
),
572 InlineAsmArch
::RiscV32
| InlineAsmArch
::RiscV64
=> {
573 Self::RiscV(RiscVInlineAsmRegClass
::parse(name
)?
)
575 InlineAsmArch
::Nvptx64
=> Self::Nvptx(NvptxInlineAsmRegClass
::parse(name
)?
),
576 InlineAsmArch
::PowerPC
| InlineAsmArch
::PowerPC64
=> {
577 Self::PowerPC(PowerPCInlineAsmRegClass
::parse(name
)?
)
579 InlineAsmArch
::Hexagon
=> Self::Hexagon(HexagonInlineAsmRegClass
::parse(name
)?
),
580 InlineAsmArch
::Mips
| InlineAsmArch
::Mips64
=> {
581 Self::Mips(MipsInlineAsmRegClass
::parse(name
)?
)
583 InlineAsmArch
::S390x
=> Self::S390x(S390xInlineAsmRegClass
::parse(name
)?
),
584 InlineAsmArch
::SpirV
=> Self::SpirV(SpirVInlineAsmRegClass
::parse(name
)?
),
585 InlineAsmArch
::Wasm32
| InlineAsmArch
::Wasm64
=> {
586 Self::Wasm(WasmInlineAsmRegClass
::parse(name
)?
)
588 InlineAsmArch
::Bpf
=> Self::Bpf(BpfInlineAsmRegClass
::parse(name
)?
),
589 InlineAsmArch
::Avr
=> Self::Avr(AvrInlineAsmRegClass
::parse(name
)?
),
590 InlineAsmArch
::Msp430
=> Self::Msp430(Msp430InlineAsmRegClass
::parse(name
)?
),
594 /// Returns the list of template modifiers that can be used with this
596 pub fn valid_modifiers(self, arch
: InlineAsmArch
) -> &'
static [char] {
598 Self::X86(r
) => r
.valid_modifiers(arch
),
599 Self::Arm(r
) => r
.valid_modifiers(arch
),
600 Self::AArch64(r
) => r
.valid_modifiers(arch
),
601 Self::RiscV(r
) => r
.valid_modifiers(arch
),
602 Self::Nvptx(r
) => r
.valid_modifiers(arch
),
603 Self::PowerPC(r
) => r
.valid_modifiers(arch
),
604 Self::Hexagon(r
) => r
.valid_modifiers(arch
),
605 Self::Mips(r
) => r
.valid_modifiers(arch
),
606 Self::S390x(r
) => r
.valid_modifiers(arch
),
607 Self::SpirV(r
) => r
.valid_modifiers(arch
),
608 Self::Wasm(r
) => r
.valid_modifiers(arch
),
609 Self::Bpf(r
) => r
.valid_modifiers(arch
),
610 Self::Avr(r
) => r
.valid_modifiers(arch
),
611 Self::Msp430(r
) => r
.valid_modifiers(arch
),
612 Self::Err
=> unreachable
!("Use of InlineAsmRegClass::Err"),
616 /// Returns whether registers in this class can only be used as clobbers
617 /// and not as inputs/outputs.
618 pub fn is_clobber_only(self, arch
: InlineAsmArch
) -> bool
{
619 self.supported_types(arch
).is_empty()
635 pub enum InlineAsmRegOrRegClass
{
637 RegClass(InlineAsmRegClass
),
640 impl InlineAsmRegOrRegClass
{
641 pub fn reg_class(self) -> InlineAsmRegClass
{
643 Self::Reg(r
) => r
.reg_class(),
644 Self::RegClass(r
) => r
,
649 impl fmt
::Display
for InlineAsmRegOrRegClass
{
650 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
652 Self::Reg(r
) => write
!(f
, "\"{}\"", r
.name()),
653 Self::RegClass(r
) => write
!(f
, "{}", r
.name()),
658 /// Set of types which can be used with a particular register class.
659 #[derive(Copy, Clone, Debug, Eq, PartialEq)]
660 pub enum InlineAsmType
{
678 pub fn is_integer(self) -> bool
{
679 matches
!(self, Self::I8
| Self::I16
| Self::I32
| Self::I64
| Self::I128
)
682 pub fn size(self) -> Size
{
683 Size
::from_bytes(match self {
691 Self::VecI8(n
) => n
* 1,
692 Self::VecI16(n
) => n
* 2,
693 Self::VecI32(n
) => n
* 4,
694 Self::VecI64(n
) => n
* 8,
695 Self::VecI128(n
) => n
* 16,
696 Self::VecF32(n
) => n
* 4,
697 Self::VecF64(n
) => n
* 8,
702 impl fmt
::Display
for InlineAsmType
{
703 fn fmt(&self, f
: &mut fmt
::Formatter
<'_
>) -> fmt
::Result
{
705 Self::I8
=> f
.write_str("i8"),
706 Self::I16
=> f
.write_str("i16"),
707 Self::I32
=> f
.write_str("i32"),
708 Self::I64
=> f
.write_str("i64"),
709 Self::I128
=> f
.write_str("i128"),
710 Self::F32
=> f
.write_str("f32"),
711 Self::F64
=> f
.write_str("f64"),
712 Self::VecI8(n
) => write
!(f
, "i8x{}", n
),
713 Self::VecI16(n
) => write
!(f
, "i16x{}", n
),
714 Self::VecI32(n
) => write
!(f
, "i32x{}", n
),
715 Self::VecI64(n
) => write
!(f
, "i64x{}", n
),
716 Self::VecI128(n
) => write
!(f
, "i128x{}", n
),
717 Self::VecF32(n
) => write
!(f
, "f32x{}", n
),
718 Self::VecF64(n
) => write
!(f
, "f64x{}", n
),
723 /// Returns the full set of allocatable registers for a given architecture.
725 /// The registers are structured as a map containing the set of allocatable
726 /// registers in each register class. A particular register may be allocatable
727 /// from multiple register classes, in which case it will appear multiple times
729 // NOTE: This function isn't used at the moment, but is needed to support
730 // falling back to an external assembler.
731 pub fn allocatable_registers(
733 reloc_model
: RelocModel
,
734 target_features
: &FxHashSet
<Symbol
>,
735 target
: &crate::spec
::Target
,
736 ) -> FxHashMap
<InlineAsmRegClass
, FxHashSet
<InlineAsmReg
>> {
738 InlineAsmArch
::X86
| InlineAsmArch
::X86_64
=> {
739 let mut map
= x86
::regclass_map();
740 x86
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
743 InlineAsmArch
::Arm
=> {
744 let mut map
= arm
::regclass_map();
745 arm
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
748 InlineAsmArch
::AArch64
=> {
749 let mut map
= aarch64
::regclass_map();
750 aarch64
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
753 InlineAsmArch
::RiscV32
| InlineAsmArch
::RiscV64
=> {
754 let mut map
= riscv
::regclass_map();
755 riscv
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
758 InlineAsmArch
::Nvptx64
=> {
759 let mut map
= nvptx
::regclass_map();
760 nvptx
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
763 InlineAsmArch
::PowerPC
| InlineAsmArch
::PowerPC64
=> {
764 let mut map
= powerpc
::regclass_map();
765 powerpc
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
768 InlineAsmArch
::Hexagon
=> {
769 let mut map
= hexagon
::regclass_map();
770 hexagon
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
773 InlineAsmArch
::Mips
| InlineAsmArch
::Mips64
=> {
774 let mut map
= mips
::regclass_map();
775 mips
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
778 InlineAsmArch
::S390x
=> {
779 let mut map
= s390x
::regclass_map();
780 s390x
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
783 InlineAsmArch
::SpirV
=> {
784 let mut map
= spirv
::regclass_map();
785 spirv
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
788 InlineAsmArch
::Wasm32
| InlineAsmArch
::Wasm64
=> {
789 let mut map
= wasm
::regclass_map();
790 wasm
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
793 InlineAsmArch
::Bpf
=> {
794 let mut map
= bpf
::regclass_map();
795 bpf
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
798 InlineAsmArch
::Avr
=> {
799 let mut map
= avr
::regclass_map();
800 avr
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
803 InlineAsmArch
::Msp430
=> {
804 let mut map
= msp430
::regclass_map();
805 msp430
::fill_reg_map(arch
, reloc_model
, target_features
, target
, &mut map
);
823 pub enum InlineAsmClobberAbi
{
833 impl InlineAsmClobberAbi
{
834 /// Parses a clobber ABI for the given target, or returns a list of supported
835 /// clobber ABIs for the target.
840 ) -> Result
<Self, &'
static [&'
static str]> {
841 let name
= name
.as_str();
843 InlineAsmArch
::X86
=> match name
{
844 "C" | "system" | "efiapi" | "cdecl" | "stdcall" | "fastcall" => {
845 Ok(InlineAsmClobberAbi
::X86
)
847 _
=> Err(&["C", "system", "efiapi", "cdecl", "stdcall", "fastcall"]),
849 InlineAsmArch
::X86_64
=> match name
{
850 "C" | "system" if !target
.is_like_windows
=> Ok(InlineAsmClobberAbi
::X86_64SysV
),
851 "C" | "system" if target
.is_like_windows
=> Ok(InlineAsmClobberAbi
::X86_64Win
),
852 "win64" | "efiapi" => Ok(InlineAsmClobberAbi
::X86_64Win
),
853 "sysv64" => Ok(InlineAsmClobberAbi
::X86_64SysV
),
854 _
=> Err(&["C", "system", "efiapi", "win64", "sysv64"]),
856 InlineAsmArch
::Arm
=> match name
{
857 "C" | "system" | "efiapi" | "aapcs" => Ok(InlineAsmClobberAbi
::Arm
),
858 _
=> Err(&["C", "system", "efiapi", "aapcs"]),
860 InlineAsmArch
::AArch64
=> match name
{
861 "C" | "system" | "efiapi" => Ok(if aarch64
::target_reserves_x18(target
) {
862 InlineAsmClobberAbi
::AArch64NoX18
864 InlineAsmClobberAbi
::AArch64
866 _
=> Err(&["C", "system", "efiapi"]),
868 InlineAsmArch
::RiscV32
| InlineAsmArch
::RiscV64
=> match name
{
869 "C" | "system" | "efiapi" => Ok(InlineAsmClobberAbi
::RiscV
),
870 _
=> Err(&["C", "system", "efiapi"]),
876 /// Returns the set of registers which are clobbered by this ABI.
877 pub fn clobbered_regs(self) -> &'
static [InlineAsmReg
] {
878 macro_rules
! clobbered_regs
{
879 ($arch
:ident $arch_reg
:ident
{
885 $
(InlineAsmReg
::$
arch($arch_reg
::$reg
),)*
890 InlineAsmClobberAbi
::X86
=> clobbered_regs
! {
891 X86 X86InlineAsmReg
{
894 xmm0
, xmm1
, xmm2
, xmm3
, xmm4
, xmm5
, xmm6
, xmm7
,
896 k0
, k1
, k2
, k3
, k4
, k5
, k6
, k7
,
898 mm0
, mm1
, mm2
, mm3
, mm4
, mm5
, mm6
, mm7
,
899 st0
, st1
, st2
, st3
, st4
, st5
, st6
, st7
,
902 InlineAsmClobberAbi
::X86_64SysV
=> clobbered_regs
! {
903 X86 X86InlineAsmReg
{
904 ax
, cx
, dx
, si
, di
, r8
, r9
, r10
, r11
,
906 xmm0
, xmm1
, xmm2
, xmm3
, xmm4
, xmm5
, xmm6
, xmm7
,
907 xmm8
, xmm9
, xmm10
, xmm11
, xmm12
, xmm13
, xmm14
, xmm15
,
908 zmm16
, zmm17
, zmm18
, zmm19
, zmm20
, zmm21
, zmm22
, zmm23
,
909 zmm24
, zmm25
, zmm26
, zmm27
, zmm28
, zmm29
, zmm30
, zmm31
,
911 k0
, k1
, k2
, k3
, k4
, k5
, k6
, k7
,
913 mm0
, mm1
, mm2
, mm3
, mm4
, mm5
, mm6
, mm7
,
914 st0
, st1
, st2
, st3
, st4
, st5
, st6
, st7
,
915 tmm0
, tmm1
, tmm2
, tmm3
, tmm4
, tmm5
, tmm6
, tmm7
,
918 InlineAsmClobberAbi
::X86_64Win
=> clobbered_regs
! {
919 X86 X86InlineAsmReg
{
920 // rdi and rsi are callee-saved on windows
921 ax
, cx
, dx
, r8
, r9
, r10
, r11
,
923 // xmm6-xmm15 are callee-saved on windows, but we need to
924 // mark them as clobbered anyways because the upper portions
925 // of ymm6-ymm15 are volatile.
926 xmm0
, xmm1
, xmm2
, xmm3
, xmm4
, xmm5
, xmm6
, xmm7
,
927 xmm8
, xmm9
, xmm10
, xmm11
, xmm12
, xmm13
, xmm14
, xmm15
,
928 zmm16
, zmm17
, zmm18
, zmm19
, zmm20
, zmm21
, zmm22
, zmm23
,
929 zmm24
, zmm25
, zmm26
, zmm27
, zmm28
, zmm29
, zmm30
, zmm31
,
931 k0
, k1
, k2
, k3
, k4
, k5
, k6
, k7
,
933 mm0
, mm1
, mm2
, mm3
, mm4
, mm5
, mm6
, mm7
,
934 st0
, st1
, st2
, st3
, st4
, st5
, st6
, st7
,
935 tmm0
, tmm1
, tmm2
, tmm3
, tmm4
, tmm5
, tmm6
, tmm7
,
938 InlineAsmClobberAbi
::AArch64
=> clobbered_regs
! {
939 AArch64 AArch64InlineAsmReg
{
940 x0
, x1
, x2
, x3
, x4
, x5
, x6
, x7
,
941 x8
, x9
, x10
, x11
, x12
, x13
, x14
, x15
,
944 // Technically the low 64 bits of v8-v15 are preserved, but
945 // we have no way of expressing this using clobbers.
946 v0
, v1
, v2
, v3
, v4
, v5
, v6
, v7
,
947 v8
, v9
, v10
, v11
, v12
, v13
, v14
, v15
,
948 v16
, v17
, v18
, v19
, v20
, v21
, v22
, v23
,
949 v24
, v25
, v26
, v27
, v28
, v29
, v30
, v31
,
951 p0
, p1
, p2
, p3
, p4
, p5
, p6
, p7
,
952 p8
, p9
, p10
, p11
, p12
, p13
, p14
, p15
,
957 InlineAsmClobberAbi
::AArch64NoX18
=> clobbered_regs
! {
958 AArch64 AArch64InlineAsmReg
{
959 x0
, x1
, x2
, x3
, x4
, x5
, x6
, x7
,
960 x8
, x9
, x10
, x11
, x12
, x13
, x14
, x15
,
963 // Technically the low 64 bits of v8-v15 are preserved, but
964 // we have no way of expressing this using clobbers.
965 v0
, v1
, v2
, v3
, v4
, v5
, v6
, v7
,
966 v8
, v9
, v10
, v11
, v12
, v13
, v14
, v15
,
967 v16
, v17
, v18
, v19
, v20
, v21
, v22
, v23
,
968 v24
, v25
, v26
, v27
, v28
, v29
, v30
, v31
,
970 p0
, p1
, p2
, p3
, p4
, p5
, p6
, p7
,
971 p8
, p9
, p10
, p11
, p12
, p13
, p14
, p15
,
976 InlineAsmClobberAbi
::Arm
=> clobbered_regs
! {
977 Arm ArmInlineAsmReg
{
978 // r9 is either platform-reserved or callee-saved. Either
979 // way we don't need to clobber it.
980 r0
, r1
, r2
, r3
, r12
, r14
,
982 // The finest-grained register variant is used here so that
983 // partial uses of larger registers are properly handled.
984 s0
, s1
, s2
, s3
, s4
, s5
, s6
, s7
,
985 s8
, s9
, s10
, s11
, s12
, s13
, s14
, s15
,
986 // s16-s31 are callee-saved
987 d16
, d17
, d18
, d19
, d20
, d21
, d22
, d23
,
988 d24
, d25
, d26
, d27
, d28
, d29
, d30
, d31
,
991 InlineAsmClobberAbi
::RiscV
=> clobbered_regs
! {
992 RiscV RiscVInlineAsmReg
{
998 x10
, x11
, x12
, x13
, x14
, x15
, x16
, x17
,
1002 f0
, f1
, f2
, f3
, f4
, f5
, f6
, f7
,
1004 f10
, f11
, f12
, f13
, f14
, f15
, f16
, f17
,
1008 v0
, v1
, v2
, v3
, v4
, v5
, v6
, v7
,
1009 v8
, v9
, v10
, v11
, v12
, v13
, v14
, v15
,
1010 v16
, v17
, v18
, v19
, v20
, v21
, v22
, v23
,
1011 v24
, v25
, v26
, v27
, v28
, v29
, v30
, v31
,