]> git.proxmox.com Git - rustc.git/blame - compiler/rustc_target/src/asm/mod.rs
New upstream version 1.55.0+dfsg1
[rustc.git] / compiler / rustc_target / src / asm / mod.rs
CommitLineData
f9f354fc 1use crate::abi::Size;
f035d41b 2use crate::spec::Target;
f9f354fc
XL
3use rustc_data_structures::fx::{FxHashMap, FxHashSet};
4use rustc_macros::HashStable_Generic;
5use rustc_span::Symbol;
6use std::fmt;
7use std::str::FromStr;
8
f9f354fc
XL
9macro_rules! def_reg_class {
10 ($arch:ident $arch_regclass:ident {
11 $(
12 $class:ident,
13 )*
14 }) => {
6a06907d 15 #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, PartialOrd, Hash, HashStable_Generic)]
f9f354fc
XL
16 #[allow(non_camel_case_types)]
17 pub enum $arch_regclass {
18 $($class,)*
19 }
20
21 impl $arch_regclass {
fc512014 22 pub fn name(self) -> rustc_span::Symbol {
f9f354fc 23 match self {
fc512014 24 $(Self::$class => rustc_span::symbol::sym::$class,)*
f9f354fc
XL
25 }
26 }
27
fc512014 28 pub fn parse(_arch: super::InlineAsmArch, name: rustc_span::Symbol) -> Result<Self, &'static str> {
f9f354fc
XL
29 match name {
30 $(
fc512014 31 rustc_span::sym::$class => Ok(Self::$class),
f9f354fc
XL
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
f9f354fc
XL
53macro_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)]
6a06907d 63 #[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, PartialOrd, Hash, HashStable_Generic)]
f9f354fc
XL
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,
f035d41b 85 _target: &crate::spec::Target,
f9f354fc
XL
86 name: &str,
87 ) -> Result<Self, &'static str> {
88 match name {
89 $(
90 $($alias)|* | $reg_name => {
cdc7bbd5 91 $($filter(_arch, &mut _has_feature, _target)?;)?
f9f354fc
XL
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,
f035d41b 106 _target: &crate::spec::Target,
f9f354fc
XL
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 $(
cdc7bbd5 115 if $($filter(_arch, &mut _has_feature, _target).is_ok() &&)? true {
f9f354fc
XL
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
f9f354fc
XL
130macro_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
149mod aarch64;
150mod arm;
17df50a5 151mod bpf;
f035d41b 152mod hexagon;
1b1a35ee 153mod mips;
f9f354fc 154mod nvptx;
17df50a5 155mod powerpc;
f9f354fc 156mod riscv;
29967ef6 157mod spirv;
fc512014 158mod wasm;
f9f354fc
XL
159mod x86;
160
161pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass};
162pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass};
17df50a5 163pub use bpf::{BpfInlineAsmReg, BpfInlineAsmRegClass};
f035d41b 164pub use hexagon::{HexagonInlineAsmReg, HexagonInlineAsmRegClass};
1b1a35ee 165pub use mips::{MipsInlineAsmReg, MipsInlineAsmRegClass};
f9f354fc 166pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
17df50a5 167pub use powerpc::{PowerPCInlineAsmReg, PowerPCInlineAsmRegClass};
f9f354fc 168pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
29967ef6 169pub use spirv::{SpirVInlineAsmReg, SpirVInlineAsmRegClass};
fc512014 170pub use wasm::{WasmInlineAsmReg, WasmInlineAsmRegClass};
f9f354fc
XL
171pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
172
3dfed10e 173#[derive(Copy, Clone, Encodable, Decodable, Debug, Eq, PartialEq, Hash)]
f9f354fc
XL
174pub enum InlineAsmArch {
175 X86,
176 X86_64,
177 Arm,
178 AArch64,
179 RiscV32,
180 RiscV64,
181 Nvptx64,
f035d41b 182 Hexagon,
1b1a35ee 183 Mips,
29967ef6 184 Mips64,
17df50a5
XL
185 PowerPC,
186 PowerPC64,
29967ef6 187 SpirV,
fc512014 188 Wasm32,
17df50a5 189 Bpf,
f9f354fc
XL
190}
191
192impl 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),
17df50a5
XL
204 "powerpc" => Ok(Self::PowerPC),
205 "powerpc64" => Ok(Self::PowerPC64),
f035d41b 206 "hexagon" => Ok(Self::Hexagon),
1b1a35ee 207 "mips" => Ok(Self::Mips),
29967ef6
XL
208 "mips64" => Ok(Self::Mips64),
209 "spirv" => Ok(Self::SpirV),
fc512014 210 "wasm32" => Ok(Self::Wasm32),
17df50a5 211 "bpf" => Ok(Self::Bpf),
f9f354fc
XL
212 _ => Err(()),
213 }
214 }
215}
216
6a06907d
XL
217#[derive(
218 Copy,
219 Clone,
220 Encodable,
221 Decodable,
222 Debug,
223 Eq,
224 PartialEq,
225 PartialOrd,
226 Hash,
227 HashStable_Generic
228)]
f9f354fc
XL
229pub enum InlineAsmReg {
230 X86(X86InlineAsmReg),
231 Arm(ArmInlineAsmReg),
232 AArch64(AArch64InlineAsmReg),
233 RiscV(RiscVInlineAsmReg),
234 Nvptx(NvptxInlineAsmReg),
17df50a5 235 PowerPC(PowerPCInlineAsmReg),
f035d41b 236 Hexagon(HexagonInlineAsmReg),
1b1a35ee 237 Mips(MipsInlineAsmReg),
29967ef6 238 SpirV(SpirVInlineAsmReg),
fc512014 239 Wasm(WasmInlineAsmReg),
17df50a5 240 Bpf(BpfInlineAsmReg),
6a06907d
XL
241 // Placeholder for invalid register constraints for the current target
242 Err,
f9f354fc
XL
243}
244
245impl 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(),
17df50a5 252 Self::PowerPC(r) => r.name(),
f035d41b 253 Self::Hexagon(r) => r.name(),
1b1a35ee 254 Self::Mips(r) => r.name(),
17df50a5 255 Self::Bpf(r) => r.name(),
6a06907d 256 Self::Err => "<reg>",
f9f354fc
XL
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()),
17df50a5 266 Self::PowerPC(r) => InlineAsmRegClass::PowerPC(r.reg_class()),
f035d41b 267 Self::Hexagon(r) => InlineAsmRegClass::Hexagon(r.reg_class()),
1b1a35ee 268 Self::Mips(r) => InlineAsmRegClass::Mips(r.reg_class()),
17df50a5 269 Self::Bpf(r) => InlineAsmRegClass::Bpf(r.reg_class()),
6a06907d 270 Self::Err => InlineAsmRegClass::Err,
f9f354fc
XL
271 }
272 }
273
274 pub fn parse(
275 arch: InlineAsmArch,
276 has_feature: impl FnMut(&str) -> bool,
f035d41b 277 target: &Target,
f9f354fc
XL
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 => {
f035d41b
XL
285 Self::X86(X86InlineAsmReg::parse(arch, has_feature, target, &name)?)
286 }
287 InlineAsmArch::Arm => {
288 Self::Arm(ArmInlineAsmReg::parse(arch, has_feature, target, &name)?)
f9f354fc 289 }
f9f354fc 290 InlineAsmArch::AArch64 => {
f035d41b 291 Self::AArch64(AArch64InlineAsmReg::parse(arch, has_feature, target, &name)?)
f9f354fc
XL
292 }
293 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
f035d41b 294 Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, target, &name)?)
f9f354fc
XL
295 }
296 InlineAsmArch::Nvptx64 => {
f035d41b
XL
297 Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, target, &name)?)
298 }
17df50a5
XL
299 InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
300 Self::PowerPC(PowerPCInlineAsmReg::parse(arch, has_feature, target, &name)?)
301 }
f035d41b
XL
302 InlineAsmArch::Hexagon => {
303 Self::Hexagon(HexagonInlineAsmReg::parse(arch, has_feature, target, &name)?)
f9f354fc 304 }
29967ef6 305 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
1b1a35ee
XL
306 Self::Mips(MipsInlineAsmReg::parse(arch, has_feature, target, &name)?)
307 }
29967ef6
XL
308 InlineAsmArch::SpirV => {
309 Self::SpirV(SpirVInlineAsmReg::parse(arch, has_feature, target, &name)?)
310 }
fc512014
XL
311 InlineAsmArch::Wasm32 => {
312 Self::Wasm(WasmInlineAsmReg::parse(arch, has_feature, target, &name)?)
313 }
17df50a5
XL
314 InlineAsmArch::Bpf => {
315 Self::Bpf(BpfInlineAsmReg::parse(arch, has_feature, target, &name)?)
316 }
f9f354fc
XL
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),
17df50a5 333 Self::PowerPC(r) => r.emit(out, arch, modifier),
f035d41b 334 Self::Hexagon(r) => r.emit(out, arch, modifier),
1b1a35ee 335 Self::Mips(r) => r.emit(out, arch, modifier),
17df50a5 336 Self::Bpf(r) => r.emit(out, arch, modifier),
6a06907d 337 Self::Err => unreachable!("Use of InlineAsmReg::Err"),
f9f354fc
XL
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),
17df50a5 347 Self::PowerPC(_) => cb(self),
f035d41b 348 Self::Hexagon(r) => r.overlapping_regs(|r| cb(Self::Hexagon(r))),
1b1a35ee 349 Self::Mips(_) => cb(self),
17df50a5 350 Self::Bpf(r) => r.overlapping_regs(|r| cb(Self::Bpf(r))),
6a06907d 351 Self::Err => unreachable!("Use of InlineAsmReg::Err"),
f9f354fc
XL
352 }
353 }
354}
355
6a06907d
XL
356#[derive(
357 Copy,
358 Clone,
359 Encodable,
360 Decodable,
361 Debug,
362 Eq,
363 PartialEq,
364 PartialOrd,
365 Hash,
366 HashStable_Generic
367)]
f9f354fc
XL
368pub enum InlineAsmRegClass {
369 X86(X86InlineAsmRegClass),
370 Arm(ArmInlineAsmRegClass),
371 AArch64(AArch64InlineAsmRegClass),
372 RiscV(RiscVInlineAsmRegClass),
373 Nvptx(NvptxInlineAsmRegClass),
17df50a5 374 PowerPC(PowerPCInlineAsmRegClass),
f035d41b 375 Hexagon(HexagonInlineAsmRegClass),
1b1a35ee 376 Mips(MipsInlineAsmRegClass),
29967ef6 377 SpirV(SpirVInlineAsmRegClass),
fc512014 378 Wasm(WasmInlineAsmRegClass),
17df50a5 379 Bpf(BpfInlineAsmRegClass),
6a06907d
XL
380 // Placeholder for invalid register constraints for the current target
381 Err,
f9f354fc
XL
382}
383
384impl InlineAsmRegClass {
fc512014 385 pub fn name(self) -> Symbol {
f9f354fc
XL
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(),
17df50a5 392 Self::PowerPC(r) => r.name(),
f035d41b 393 Self::Hexagon(r) => r.name(),
1b1a35ee 394 Self::Mips(r) => r.name(),
29967ef6 395 Self::SpirV(r) => r.name(),
fc512014 396 Self::Wasm(r) => r.name(),
17df50a5 397 Self::Bpf(r) => r.name(),
6a06907d 398 Self::Err => rustc_span::symbol::sym::reg,
f9f354fc
XL
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),
17df50a5 412 Self::PowerPC(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::PowerPC),
f035d41b 413 Self::Hexagon(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Hexagon),
1b1a35ee 414 Self::Mips(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Mips),
29967ef6 415 Self::SpirV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::SpirV),
fc512014 416 Self::Wasm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Wasm),
17df50a5 417 Self::Bpf(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Bpf),
6a06907d 418 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
f9f354fc
XL
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),
17df50a5 439 Self::PowerPC(r) => r.suggest_modifier(arch, ty),
f035d41b 440 Self::Hexagon(r) => r.suggest_modifier(arch, ty),
1b1a35ee 441 Self::Mips(r) => r.suggest_modifier(arch, ty),
29967ef6 442 Self::SpirV(r) => r.suggest_modifier(arch, ty),
fc512014 443 Self::Wasm(r) => r.suggest_modifier(arch, ty),
17df50a5 444 Self::Bpf(r) => r.suggest_modifier(arch, ty),
6a06907d 445 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
f9f354fc
XL
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),
17df50a5 462 Self::PowerPC(r) => r.default_modifier(arch),
f035d41b 463 Self::Hexagon(r) => r.default_modifier(arch),
1b1a35ee 464 Self::Mips(r) => r.default_modifier(arch),
29967ef6 465 Self::SpirV(r) => r.default_modifier(arch),
fc512014 466 Self::Wasm(r) => r.default_modifier(arch),
17df50a5 467 Self::Bpf(r) => r.default_modifier(arch),
6a06907d 468 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
f9f354fc
XL
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),
17df50a5 484 Self::PowerPC(r) => r.supported_types(arch),
f035d41b 485 Self::Hexagon(r) => r.supported_types(arch),
1b1a35ee 486 Self::Mips(r) => r.supported_types(arch),
29967ef6 487 Self::SpirV(r) => r.supported_types(arch),
fc512014 488 Self::Wasm(r) => r.supported_types(arch),
17df50a5 489 Self::Bpf(r) => r.supported_types(arch),
6a06907d 490 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
f9f354fc
XL
491 }
492 }
493
494 pub fn parse(arch: InlineAsmArch, name: Symbol) -> Result<Self, &'static str> {
fc512014
XL
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)?),
17df50a5
XL
505 InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
506 Self::PowerPC(PowerPCInlineAsmRegClass::parse(arch, name)?)
507 }
fc512014
XL
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)?),
17df50a5 514 InlineAsmArch::Bpf => Self::Bpf(BpfInlineAsmRegClass::parse(arch, name)?),
f9f354fc
XL
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),
17df50a5 527 Self::PowerPC(r) => r.valid_modifiers(arch),
f035d41b 528 Self::Hexagon(r) => r.valid_modifiers(arch),
1b1a35ee 529 Self::Mips(r) => r.valid_modifiers(arch),
29967ef6 530 Self::SpirV(r) => r.valid_modifiers(arch),
fc512014 531 Self::Wasm(r) => r.valid_modifiers(arch),
17df50a5 532 Self::Bpf(r) => r.valid_modifiers(arch),
6a06907d 533 Self::Err => unreachable!("Use of InlineAsmRegClass::Err"),
f9f354fc
XL
534 }
535 }
136023e0
XL
536
537 /// Returns whether registers in this class can only be used as clobbers
538 /// and not as inputs/outputs.
539 pub fn is_clobber_only(self, arch: InlineAsmArch) -> bool {
540 self.supported_types(arch).is_empty()
541 }
f9f354fc
XL
542}
543
6a06907d
XL
544#[derive(
545 Copy,
546 Clone,
547 Encodable,
548 Decodable,
549 Debug,
550 Eq,
551 PartialEq,
552 PartialOrd,
553 Hash,
554 HashStable_Generic
555)]
f9f354fc
XL
556pub enum InlineAsmRegOrRegClass {
557 Reg(InlineAsmReg),
558 RegClass(InlineAsmRegClass),
559}
560
561impl InlineAsmRegOrRegClass {
562 pub fn reg_class(self) -> InlineAsmRegClass {
563 match self {
564 Self::Reg(r) => r.reg_class(),
565 Self::RegClass(r) => r,
566 }
567 }
568}
569
570impl fmt::Display for InlineAsmRegOrRegClass {
571 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
572 match self {
573 Self::Reg(r) => write!(f, "\"{}\"", r.name()),
fc512014 574 Self::RegClass(r) => write!(f, "{}", r.name()),
f9f354fc
XL
575 }
576 }
577}
578
579/// Set of types which can be used with a particular register class.
580#[derive(Copy, Clone, Debug, Eq, PartialEq)]
581pub enum InlineAsmType {
582 I8,
583 I16,
584 I32,
585 I64,
586 I128,
587 F32,
588 F64,
589 VecI8(u64),
590 VecI16(u64),
591 VecI32(u64),
592 VecI64(u64),
593 VecI128(u64),
594 VecF32(u64),
595 VecF64(u64),
596}
597
598impl InlineAsmType {
599 pub fn is_integer(self) -> bool {
29967ef6 600 matches!(self, Self::I8 | Self::I16 | Self::I32 | Self::I64 | Self::I128)
f9f354fc
XL
601 }
602
603 pub fn size(self) -> Size {
604 Size::from_bytes(match self {
605 Self::I8 => 1,
606 Self::I16 => 2,
607 Self::I32 => 4,
608 Self::I64 => 8,
609 Self::I128 => 16,
610 Self::F32 => 4,
611 Self::F64 => 8,
612 Self::VecI8(n) => n * 1,
613 Self::VecI16(n) => n * 2,
614 Self::VecI32(n) => n * 4,
615 Self::VecI64(n) => n * 8,
616 Self::VecI128(n) => n * 16,
617 Self::VecF32(n) => n * 4,
618 Self::VecF64(n) => n * 8,
619 })
620 }
621}
622
623impl fmt::Display for InlineAsmType {
624 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
625 match *self {
626 Self::I8 => f.write_str("i8"),
627 Self::I16 => f.write_str("i16"),
628 Self::I32 => f.write_str("i32"),
629 Self::I64 => f.write_str("i64"),
630 Self::I128 => f.write_str("i128"),
631 Self::F32 => f.write_str("f32"),
632 Self::F64 => f.write_str("f64"),
633 Self::VecI8(n) => write!(f, "i8x{}", n),
634 Self::VecI16(n) => write!(f, "i16x{}", n),
635 Self::VecI32(n) => write!(f, "i32x{}", n),
636 Self::VecI64(n) => write!(f, "i64x{}", n),
637 Self::VecI128(n) => write!(f, "i128x{}", n),
638 Self::VecF32(n) => write!(f, "f32x{}", n),
639 Self::VecF64(n) => write!(f, "f64x{}", n),
640 }
641 }
642}
643
644/// Returns the full set of allocatable registers for a given architecture.
645///
646/// The registers are structured as a map containing the set of allocatable
647/// registers in each register class. A particular register may be allocatable
648/// from multiple register classes, in which case it will appear multiple times
649/// in the map.
650// NOTE: This function isn't used at the moment, but is needed to support
651// falling back to an external assembler.
652pub fn allocatable_registers(
653 arch: InlineAsmArch,
654 has_feature: impl FnMut(&str) -> bool,
f035d41b 655 target: &crate::spec::Target,
f9f354fc
XL
656) -> FxHashMap<InlineAsmRegClass, FxHashSet<InlineAsmReg>> {
657 match arch {
658 InlineAsmArch::X86 | InlineAsmArch::X86_64 => {
659 let mut map = x86::regclass_map();
f035d41b 660 x86::fill_reg_map(arch, has_feature, target, &mut map);
f9f354fc
XL
661 map
662 }
663 InlineAsmArch::Arm => {
664 let mut map = arm::regclass_map();
f035d41b 665 arm::fill_reg_map(arch, has_feature, target, &mut map);
f9f354fc
XL
666 map
667 }
668 InlineAsmArch::AArch64 => {
669 let mut map = aarch64::regclass_map();
f035d41b 670 aarch64::fill_reg_map(arch, has_feature, target, &mut map);
f9f354fc
XL
671 map
672 }
673 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
674 let mut map = riscv::regclass_map();
f035d41b 675 riscv::fill_reg_map(arch, has_feature, target, &mut map);
f9f354fc
XL
676 map
677 }
678 InlineAsmArch::Nvptx64 => {
679 let mut map = nvptx::regclass_map();
f035d41b
XL
680 nvptx::fill_reg_map(arch, has_feature, target, &mut map);
681 map
682 }
17df50a5
XL
683 InlineAsmArch::PowerPC | InlineAsmArch::PowerPC64 => {
684 let mut map = powerpc::regclass_map();
685 powerpc::fill_reg_map(arch, has_feature, target, &mut map);
686 map
687 }
f035d41b
XL
688 InlineAsmArch::Hexagon => {
689 let mut map = hexagon::regclass_map();
690 hexagon::fill_reg_map(arch, has_feature, target, &mut map);
f9f354fc
XL
691 map
692 }
29967ef6 693 InlineAsmArch::Mips | InlineAsmArch::Mips64 => {
1b1a35ee
XL
694 let mut map = mips::regclass_map();
695 mips::fill_reg_map(arch, has_feature, target, &mut map);
696 map
697 }
29967ef6
XL
698 InlineAsmArch::SpirV => {
699 let mut map = spirv::regclass_map();
700 spirv::fill_reg_map(arch, has_feature, target, &mut map);
701 map
702 }
fc512014
XL
703 InlineAsmArch::Wasm32 => {
704 let mut map = wasm::regclass_map();
705 wasm::fill_reg_map(arch, has_feature, target, &mut map);
706 map
707 }
17df50a5
XL
708 InlineAsmArch::Bpf => {
709 let mut map = bpf::regclass_map();
710 bpf::fill_reg_map(arch, has_feature, target, &mut map);
711 map
712 }
f9f354fc
XL
713 }
714}