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