rustc_target/asm/
sparc.rs

1use std::fmt;
2
3use rustc_data_structures::fx::FxIndexSet;
4use rustc_span::Symbol;
5
6use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
7use crate::spec::{RelocModel, Target};
8
9#[allow(non_camel_case_types)]
pub enum SparcInlineAsmRegClass { reg, yreg, }
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::marker::Copy for SparcInlineAsmRegClass { }
#[automatically_derived]
#[doc(hidden)]
#[allow(non_camel_case_types)]
unsafe impl ::core::clone::TrivialClone for SparcInlineAsmRegClass { }
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::clone::Clone for SparcInlineAsmRegClass {
    #[inline]
    fn clone(&self) -> SparcInlineAsmRegClass { *self }
}
const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for SparcInlineAsmRegClass {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        SparcInlineAsmRegClass::reg => { 0usize }
                        SparcInlineAsmRegClass::yreg => { 1usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    SparcInlineAsmRegClass::reg => {}
                    SparcInlineAsmRegClass::yreg => {}
                }
            }
        }
    };
const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for SparcInlineAsmRegClass {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { SparcInlineAsmRegClass::reg }
                    1usize => { SparcInlineAsmRegClass::yreg }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `SparcInlineAsmRegClass`, expected 0..2, actual {0}",
                                n));
                    }
                }
            }
        }
    };
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::fmt::Debug for SparcInlineAsmRegClass {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                SparcInlineAsmRegClass::reg => "reg",
                SparcInlineAsmRegClass::yreg => "yreg",
            })
    }
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::Eq for SparcInlineAsmRegClass {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) -> () {}
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::marker::StructuralPartialEq for SparcInlineAsmRegClass { }
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialEq for SparcInlineAsmRegClass {
    #[inline]
    fn eq(&self, other: &SparcInlineAsmRegClass) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialOrd for SparcInlineAsmRegClass {
    #[inline]
    fn partial_cmp(&self, other: &SparcInlineAsmRegClass)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}
#[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::hash::Hash for SparcInlineAsmRegClass {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}
const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for SparcInlineAsmRegClass where __CTX: crate::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    SparcInlineAsmRegClass::reg => {}
                    SparcInlineAsmRegClass::yreg => {}
                }
            }
        }
    };
impl SparcInlineAsmRegClass {
    pub fn name(self) -> rustc_span::Symbol {
        match self {
            Self::reg => rustc_span::sym::reg,
            Self::yreg => rustc_span::sym::yreg,
        }
    }
    pub fn parse(name: rustc_span::Symbol)
        -> Result<Self, &'static [rustc_span::Symbol]> {
        match name {
            rustc_span::sym::reg => Ok(Self::reg),
            rustc_span::sym::yreg => Ok(Self::yreg),
            _ => Err(&[rustc_span::sym::reg, rustc_span::sym::yreg]),
        }
    }
}
pub(super) fn regclass_map()
    ->
        rustc_data_structures::fx::FxHashMap<super::InlineAsmRegClass,
        rustc_data_structures::fx::FxIndexSet<super::InlineAsmReg>> {
    use rustc_data_structures::fx::FxHashMap;
    use rustc_data_structures::fx::FxIndexSet;
    use super::InlineAsmRegClass;
    let mut map = FxHashMap::default();
    map.insert(InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg),
        FxIndexSet::default());
    map.insert(InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg),
        FxIndexSet::default());
    map
}def_reg_class! {
10    Sparc SparcInlineAsmRegClass {
11        reg,
12        yreg,
13    }
14}
15
16impl SparcInlineAsmRegClass {
17    pub fn valid_modifiers(self, _arch: super::InlineAsmArch) -> &'static [char] {
18        &[]
19    }
20
21    pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
22        None
23    }
24
25    pub fn suggest_modifier(
26        self,
27        _arch: InlineAsmArch,
28        _ty: InlineAsmType,
29    ) -> Option<ModifierInfo> {
30        None
31    }
32
33    pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
34        None
35    }
36
37    pub fn supported_types(
38        self,
39        arch: InlineAsmArch,
40    ) -> &'static [(InlineAsmType, Option<Symbol>)] {
41        match self {
42            Self::reg => {
43                if arch == InlineAsmArch::Sparc {
44                    {
    use super::InlineAsmType::*;
    &[(I8, None), (I16, None), (I32, None)]
}types! {
45                        _: I8, I16, I32;
46                        // FIXME: i64 is ok for g*/o* registers on SPARC-V8+ ("h" constraint in GCC),
47                        //        but not yet supported in LLVM.
48                        // v8plus: I64;
49                    }
50                } else {
51                    {
    use super::InlineAsmType::*;
    &[(I8, None), (I16, None), (I32, None), (I64, None)]
}types! { _: I8, I16, I32, I64; }
52                }
53            }
54            Self::yreg => &[],
55        }
56    }
57}
58
59fn reserved_g5(
60    arch: InlineAsmArch,
61    _reloc_model: RelocModel,
62    _target_features: &FxIndexSet<Symbol>,
63    _target: &Target,
64    _is_clobber: bool,
65) -> Result<(), &'static str> {
66    if arch == InlineAsmArch::Sparc {
67        // FIXME: Section 2.1.5 "Function Registers with Unassigned Roles" of the V8+ Technical
68        // Specification says "%g5; no longer reserved for system software" [1], but LLVM always
69        // reserves it on SPARC32 [2].
70        // [1]: https://temlib.org/pub/SparcStation/Standards/V8plus.pdf
71        // [2]: https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp#L64-L66
72        Err("g5 is reserved for system on SPARC32")
73    } else {
74        Ok(())
75    }
76}
77
78#[allow(unreachable_code)]
#[allow(non_camel_case_types)]
pub enum SparcInlineAsmReg {
    r2,
    r3,
    r4,
    r5,
    r8,
    r9,
    r10,
    r11,
    r12,
    r13,
    r15,
    r16,
    r17,
    r18,
    r19,
    r20,
    r21,
    r22,
    r23,
    r24,
    r25,
    r26,
    r27,
    r28,
    r29,
    y,
}
#[automatically_derived]
#[allow(unreachable_code)]
#[allow(non_camel_case_types)]
impl ::core::marker::Copy for SparcInlineAsmReg { }
#[automatically_derived]
#[doc(hidden)]
#[allow(unreachable_code)]
#[allow(non_camel_case_types)]
unsafe impl ::core::clone::TrivialClone for SparcInlineAsmReg { }
#[automatically_derived]
#[allow(unreachable_code)]
#[allow(non_camel_case_types)]
impl ::core::clone::Clone for SparcInlineAsmReg {
    #[inline]
    fn clone(&self) -> SparcInlineAsmReg { *self }
}
const _: () =
    {
        impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
            for SparcInlineAsmReg {
            fn encode(&self, __encoder: &mut __E) {
                let disc =
                    match *self {
                        SparcInlineAsmReg::r2 => { 0usize }
                        SparcInlineAsmReg::r3 => { 1usize }
                        SparcInlineAsmReg::r4 => { 2usize }
                        SparcInlineAsmReg::r5 => { 3usize }
                        SparcInlineAsmReg::r8 => { 4usize }
                        SparcInlineAsmReg::r9 => { 5usize }
                        SparcInlineAsmReg::r10 => { 6usize }
                        SparcInlineAsmReg::r11 => { 7usize }
                        SparcInlineAsmReg::r12 => { 8usize }
                        SparcInlineAsmReg::r13 => { 9usize }
                        SparcInlineAsmReg::r15 => { 10usize }
                        SparcInlineAsmReg::r16 => { 11usize }
                        SparcInlineAsmReg::r17 => { 12usize }
                        SparcInlineAsmReg::r18 => { 13usize }
                        SparcInlineAsmReg::r19 => { 14usize }
                        SparcInlineAsmReg::r20 => { 15usize }
                        SparcInlineAsmReg::r21 => { 16usize }
                        SparcInlineAsmReg::r22 => { 17usize }
                        SparcInlineAsmReg::r23 => { 18usize }
                        SparcInlineAsmReg::r24 => { 19usize }
                        SparcInlineAsmReg::r25 => { 20usize }
                        SparcInlineAsmReg::r26 => { 21usize }
                        SparcInlineAsmReg::r27 => { 22usize }
                        SparcInlineAsmReg::r28 => { 23usize }
                        SparcInlineAsmReg::r29 => { 24usize }
                        SparcInlineAsmReg::y => { 25usize }
                    };
                ::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
                match *self {
                    SparcInlineAsmReg::r2 => {}
                    SparcInlineAsmReg::r3 => {}
                    SparcInlineAsmReg::r4 => {}
                    SparcInlineAsmReg::r5 => {}
                    SparcInlineAsmReg::r8 => {}
                    SparcInlineAsmReg::r9 => {}
                    SparcInlineAsmReg::r10 => {}
                    SparcInlineAsmReg::r11 => {}
                    SparcInlineAsmReg::r12 => {}
                    SparcInlineAsmReg::r13 => {}
                    SparcInlineAsmReg::r15 => {}
                    SparcInlineAsmReg::r16 => {}
                    SparcInlineAsmReg::r17 => {}
                    SparcInlineAsmReg::r18 => {}
                    SparcInlineAsmReg::r19 => {}
                    SparcInlineAsmReg::r20 => {}
                    SparcInlineAsmReg::r21 => {}
                    SparcInlineAsmReg::r22 => {}
                    SparcInlineAsmReg::r23 => {}
                    SparcInlineAsmReg::r24 => {}
                    SparcInlineAsmReg::r25 => {}
                    SparcInlineAsmReg::r26 => {}
                    SparcInlineAsmReg::r27 => {}
                    SparcInlineAsmReg::r28 => {}
                    SparcInlineAsmReg::r29 => {}
                    SparcInlineAsmReg::y => {}
                }
            }
        }
    };
const _: () =
    {
        impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
            for SparcInlineAsmReg {
            fn decode(__decoder: &mut __D) -> Self {
                match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
                    {
                    0usize => { SparcInlineAsmReg::r2 }
                    1usize => { SparcInlineAsmReg::r3 }
                    2usize => { SparcInlineAsmReg::r4 }
                    3usize => { SparcInlineAsmReg::r5 }
                    4usize => { SparcInlineAsmReg::r8 }
                    5usize => { SparcInlineAsmReg::r9 }
                    6usize => { SparcInlineAsmReg::r10 }
                    7usize => { SparcInlineAsmReg::r11 }
                    8usize => { SparcInlineAsmReg::r12 }
                    9usize => { SparcInlineAsmReg::r13 }
                    10usize => { SparcInlineAsmReg::r15 }
                    11usize => { SparcInlineAsmReg::r16 }
                    12usize => { SparcInlineAsmReg::r17 }
                    13usize => { SparcInlineAsmReg::r18 }
                    14usize => { SparcInlineAsmReg::r19 }
                    15usize => { SparcInlineAsmReg::r20 }
                    16usize => { SparcInlineAsmReg::r21 }
                    17usize => { SparcInlineAsmReg::r22 }
                    18usize => { SparcInlineAsmReg::r23 }
                    19usize => { SparcInlineAsmReg::r24 }
                    20usize => { SparcInlineAsmReg::r25 }
                    21usize => { SparcInlineAsmReg::r26 }
                    22usize => { SparcInlineAsmReg::r27 }
                    23usize => { SparcInlineAsmReg::r28 }
                    24usize => { SparcInlineAsmReg::r29 }
                    25usize => { SparcInlineAsmReg::y }
                    n => {
                        ::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `SparcInlineAsmReg`, expected 0..26, actual {0}",
                                n));
                    }
                }
            }
        }
    };
#[automatically_derived]
#[allow(unreachable_code)]
#[allow(non_camel_case_types)]
impl ::core::fmt::Debug for SparcInlineAsmReg {
    #[inline]
    fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
        ::core::fmt::Formatter::write_str(f,
            match self {
                SparcInlineAsmReg::r2 => "r2",
                SparcInlineAsmReg::r3 => "r3",
                SparcInlineAsmReg::r4 => "r4",
                SparcInlineAsmReg::r5 => "r5",
                SparcInlineAsmReg::r8 => "r8",
                SparcInlineAsmReg::r9 => "r9",
                SparcInlineAsmReg::r10 => "r10",
                SparcInlineAsmReg::r11 => "r11",
                SparcInlineAsmReg::r12 => "r12",
                SparcInlineAsmReg::r13 => "r13",
                SparcInlineAsmReg::r15 => "r15",
                SparcInlineAsmReg::r16 => "r16",
                SparcInlineAsmReg::r17 => "r17",
                SparcInlineAsmReg::r18 => "r18",
                SparcInlineAsmReg::r19 => "r19",
                SparcInlineAsmReg::r20 => "r20",
                SparcInlineAsmReg::r21 => "r21",
                SparcInlineAsmReg::r22 => "r22",
                SparcInlineAsmReg::r23 => "r23",
                SparcInlineAsmReg::r24 => "r24",
                SparcInlineAsmReg::r25 => "r25",
                SparcInlineAsmReg::r26 => "r26",
                SparcInlineAsmReg::r27 => "r27",
                SparcInlineAsmReg::r28 => "r28",
                SparcInlineAsmReg::r29 => "r29",
                SparcInlineAsmReg::y => "y",
            })
    }
}
#[automatically_derived]
#[allow(unreachable_code)]
#[allow(non_camel_case_types)]
impl ::core::cmp::Eq for SparcInlineAsmReg {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_receiver_is_total_eq(&self) -> () {}
}
#[automatically_derived]
#[allow(unreachable_code)]
#[allow(non_camel_case_types)]
impl ::core::marker::StructuralPartialEq for SparcInlineAsmReg { }
#[automatically_derived]
#[allow(unreachable_code)]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialEq for SparcInlineAsmReg {
    #[inline]
    fn eq(&self, other: &SparcInlineAsmReg) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}
#[automatically_derived]
#[allow(unreachable_code)]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialOrd for SparcInlineAsmReg {
    #[inline]
    fn partial_cmp(&self, other: &SparcInlineAsmReg)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}
#[automatically_derived]
#[allow(unreachable_code)]
#[allow(non_camel_case_types)]
impl ::core::hash::Hash for SparcInlineAsmReg {
    #[inline]
    fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) -> () {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        ::core::hash::Hash::hash(&__self_discr, state)
    }
}
const _: () =
    {
        impl<__CTX> ::rustc_data_structures::stable_hasher::HashStable<__CTX>
            for SparcInlineAsmReg where __CTX: crate::HashStableContext {
            #[inline]
            fn hash_stable(&self, __hcx: &mut __CTX,
                __hasher:
                    &mut ::rustc_data_structures::stable_hasher::StableHasher) {
                ::std::mem::discriminant(self).hash_stable(__hcx, __hasher);
                match *self {
                    SparcInlineAsmReg::r2 => {}
                    SparcInlineAsmReg::r3 => {}
                    SparcInlineAsmReg::r4 => {}
                    SparcInlineAsmReg::r5 => {}
                    SparcInlineAsmReg::r8 => {}
                    SparcInlineAsmReg::r9 => {}
                    SparcInlineAsmReg::r10 => {}
                    SparcInlineAsmReg::r11 => {}
                    SparcInlineAsmReg::r12 => {}
                    SparcInlineAsmReg::r13 => {}
                    SparcInlineAsmReg::r15 => {}
                    SparcInlineAsmReg::r16 => {}
                    SparcInlineAsmReg::r17 => {}
                    SparcInlineAsmReg::r18 => {}
                    SparcInlineAsmReg::r19 => {}
                    SparcInlineAsmReg::r20 => {}
                    SparcInlineAsmReg::r21 => {}
                    SparcInlineAsmReg::r22 => {}
                    SparcInlineAsmReg::r23 => {}
                    SparcInlineAsmReg::r24 => {}
                    SparcInlineAsmReg::r25 => {}
                    SparcInlineAsmReg::r26 => {}
                    SparcInlineAsmReg::r27 => {}
                    SparcInlineAsmReg::r28 => {}
                    SparcInlineAsmReg::r29 => {}
                    SparcInlineAsmReg::y => {}
                }
            }
        }
    };
impl SparcInlineAsmReg {
    pub fn name(self) -> &'static str {
        match self {
            Self::r2 => "r2",
            Self::r3 => "r3",
            Self::r4 => "r4",
            Self::r5 => "r5",
            Self::r8 => "r8",
            Self::r9 => "r9",
            Self::r10 => "r10",
            Self::r11 => "r11",
            Self::r12 => "r12",
            Self::r13 => "r13",
            Self::r15 => "r15",
            Self::r16 => "r16",
            Self::r17 => "r17",
            Self::r18 => "r18",
            Self::r19 => "r19",
            Self::r20 => "r20",
            Self::r21 => "r21",
            Self::r22 => "r22",
            Self::r23 => "r23",
            Self::r24 => "r24",
            Self::r25 => "r25",
            Self::r26 => "r26",
            Self::r27 => "r27",
            Self::r28 => "r28",
            Self::r29 => "r29",
            Self::y => "y",
        }
    }
    pub fn reg_class(self) -> SparcInlineAsmRegClass {
        match self {
            Self::r2 => SparcInlineAsmRegClass::reg,
            Self::r3 => SparcInlineAsmRegClass::reg,
            Self::r4 => SparcInlineAsmRegClass::reg,
            Self::r5 => SparcInlineAsmRegClass::reg,
            Self::r8 => SparcInlineAsmRegClass::reg,
            Self::r9 => SparcInlineAsmRegClass::reg,
            Self::r10 => SparcInlineAsmRegClass::reg,
            Self::r11 => SparcInlineAsmRegClass::reg,
            Self::r12 => SparcInlineAsmRegClass::reg,
            Self::r13 => SparcInlineAsmRegClass::reg,
            Self::r15 => SparcInlineAsmRegClass::reg,
            Self::r16 => SparcInlineAsmRegClass::reg,
            Self::r17 => SparcInlineAsmRegClass::reg,
            Self::r18 => SparcInlineAsmRegClass::reg,
            Self::r19 => SparcInlineAsmRegClass::reg,
            Self::r20 => SparcInlineAsmRegClass::reg,
            Self::r21 => SparcInlineAsmRegClass::reg,
            Self::r22 => SparcInlineAsmRegClass::reg,
            Self::r23 => SparcInlineAsmRegClass::reg,
            Self::r24 => SparcInlineAsmRegClass::reg,
            Self::r25 => SparcInlineAsmRegClass::reg,
            Self::r26 => SparcInlineAsmRegClass::reg,
            Self::r27 => SparcInlineAsmRegClass::reg,
            Self::r28 => SparcInlineAsmRegClass::reg,
            Self::r29 => SparcInlineAsmRegClass::reg,
            Self::y => SparcInlineAsmRegClass::yreg,
        }
    }
    pub fn parse(name: &str) -> Result<Self, &'static str> {
        match name {
            "g2" | "r2" => Ok(Self::r2),
            "g3" | "r3" => Ok(Self::r3),
            "g4" | "r4" => Ok(Self::r4),
            "g5" | "r5" => Ok(Self::r5),
            "o0" | "r8" => Ok(Self::r8),
            "o1" | "r9" => Ok(Self::r9),
            "o2" | "r10" => Ok(Self::r10),
            "o3" | "r11" => Ok(Self::r11),
            "o4" | "r12" => Ok(Self::r12),
            "o5" | "r13" => Ok(Self::r13),
            "o7" | "r15" => Ok(Self::r15),
            "l0" | "r16" => Ok(Self::r16),
            "l1" | "r17" => Ok(Self::r17),
            "l2" | "r18" => Ok(Self::r18),
            "l3" | "r19" => Ok(Self::r19),
            "l4" | "r20" => Ok(Self::r20),
            "l5" | "r21" => Ok(Self::r21),
            "l6" | "r22" => Ok(Self::r22),
            "l7" | "r23" => Ok(Self::r23),
            "i0" | "r24" => Ok(Self::r24),
            "i1" | "r25" => Ok(Self::r25),
            "i2" | "r26" => Ok(Self::r26),
            "i3" | "r27" => Ok(Self::r27),
            "i4" | "r28" => Ok(Self::r28),
            "i5" | "r29" => Ok(Self::r29),
            "y" => Ok(Self::y),
            "r0" | "g0" =>
                Err("g0 is always zero and cannot be used as an operand for inline asm"),
            "r1" | "g1" =>
                Err("reserved by LLVM and cannot be used as an operand for inline asm"),
            "r6" | "g6" | "r7" | "g7" =>
                Err("reserved for system and cannot be used as an operand for inline asm"),
            "sp" | "r14" | "o6" =>
                Err("the stack pointer cannot be used as an operand for inline asm"),
            "fp" | "r30" | "i6" =>
                Err("the frame pointer cannot be used as an operand for inline asm"),
            "r31" | "i7" =>
                Err("the return address register cannot be used as an operand for inline asm"),
            _ => Err("unknown register"),
        }
    }
    pub fn validate(self, _arch: super::InlineAsmArch,
        _reloc_model: crate::spec::RelocModel,
        _target_features: &rustc_data_structures::fx::FxIndexSet<Symbol>,
        _target: &crate::spec::Target, _is_clobber: bool)
        -> Result<(), &'static str> {
        match self {
            Self::r2 => { Ok(()) }
            Self::r3 => { Ok(()) }
            Self::r4 => { Ok(()) }
            Self::r5 => {
                reserved_g5(_arch, _reloc_model, _target_features, _target,
                        _is_clobber)?;
                Ok(())
            }
            Self::r8 => { Ok(()) }
            Self::r9 => { Ok(()) }
            Self::r10 => { Ok(()) }
            Self::r11 => { Ok(()) }
            Self::r12 => { Ok(()) }
            Self::r13 => { Ok(()) }
            Self::r15 => { Ok(()) }
            Self::r16 => { Ok(()) }
            Self::r17 => { Ok(()) }
            Self::r18 => { Ok(()) }
            Self::r19 => { Ok(()) }
            Self::r20 => { Ok(()) }
            Self::r21 => { Ok(()) }
            Self::r22 => { Ok(()) }
            Self::r23 => { Ok(()) }
            Self::r24 => { Ok(()) }
            Self::r25 => { Ok(()) }
            Self::r26 => { Ok(()) }
            Self::r27 => { Ok(()) }
            Self::r28 => { Ok(()) }
            Self::r29 => { Ok(()) }
            Self::y => { Ok(()) }
        }
    }
}
pub(super) fn fill_reg_map(_arch: super::InlineAsmArch,
    _reloc_model: crate::spec::RelocModel,
    _target_features: &rustc_data_structures::fx::FxIndexSet<Symbol>,
    _target: &crate::spec::Target,
    _map:
        &mut rustc_data_structures::fx::FxHashMap<super::InlineAsmRegClass,
        rustc_data_structures::fx::FxIndexSet<super::InlineAsmReg>>) {
    #[allow(unused_imports)]
    use super::{InlineAsmReg, InlineAsmRegClass};
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r2));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r3));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r4));
        }
    }
    if reserved_g5(_arch, _reloc_model, _target_features, _target,
                    false).is_ok() && true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r5));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r8));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r9));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r10));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r11));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r12));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r13));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r15));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r16));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r17));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r18));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r19));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r20));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r21));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r22));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r23));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r24));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r25));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r26));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r27));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r28));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::r29));
        }
    }
    if true {
        if let Some(set) =
                _map.get_mut(&InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg))
            {
            set.insert(InlineAsmReg::Sparc(SparcInlineAsmReg::y));
        }
    }
}def_regs! {
79    Sparc SparcInlineAsmReg SparcInlineAsmRegClass {
80        // FIXME:
81        // - LLVM has reserve-{g,o,l,i}N feature to reserve each general-purpose registers.
82        // - g2-g4 are reserved for application (optional in both LLVM and GCC, and GCC has -mno-app-regs option to reserve them).
83        // There are currently no builtin targets that use them, but in the future they may need to
84        // be supported via options similar to AArch64's -Z fixed-x18.
85        r2: reg = ["r2", "g2"], // % reserved_g2
86        r3: reg = ["r3", "g3"], // % reserved_g3
87        r4: reg = ["r4", "g4"], // % reserved_g4
88        r5: reg = ["r5", "g5"] % reserved_g5,
89        r8: reg = ["r8", "o0"], // % reserved_o0
90        r9: reg = ["r9", "o1"], // % reserved_o1
91        r10: reg = ["r10", "o2"], // % reserved_o2
92        r11: reg = ["r11", "o3"], // % reserved_o3
93        r12: reg = ["r12", "o4"], // % reserved_o4
94        r13: reg = ["r13", "o5"], // % reserved_o5
95        r15: reg = ["r15", "o7"], // % reserved_o7
96        r16: reg = ["r16", "l0"], // % reserved_l0
97        r17: reg = ["r17", "l1"], // % reserved_l1
98        r18: reg = ["r18", "l2"], // % reserved_l2
99        r19: reg = ["r19", "l3"], // % reserved_l3
100        r20: reg = ["r20", "l4"], // % reserved_l4
101        r21: reg = ["r21", "l5"], // % reserved_l5
102        r22: reg = ["r22", "l6"], // % reserved_l6
103        r23: reg = ["r23", "l7"], // % reserved_l7
104        r24: reg = ["r24", "i0"], // % reserved_i0
105        r25: reg = ["r25", "i1"], // % reserved_i1
106        r26: reg = ["r26", "i2"], // % reserved_i2
107        r27: reg = ["r27", "i3"], // % reserved_i3
108        r28: reg = ["r28", "i4"], // % reserved_i4
109        r29: reg = ["r29", "i5"], // % reserved_i5
110        y: yreg = ["y"],
111        #error = ["r0", "g0"] =>
112            "g0 is always zero and cannot be used as an operand for inline asm",
113        // FIXME: %g1 is volatile in ABI, but used internally by LLVM.
114        // https://github.com/llvm/llvm-project/blob/llvmorg-19.1.0/llvm/lib/Target/Sparc/SparcRegisterInfo.cpp#L55-L56
115        // > FIXME: G1 reserved for now for large imm generation by frame code.
116        #error = ["r1", "g1"] =>
117            "reserved by LLVM and cannot be used as an operand for inline asm",
118        #error = ["r6", "g6", "r7", "g7"] =>
119            "reserved for system and cannot be used as an operand for inline asm",
120        #error = ["sp", "r14", "o6"] =>
121            "the stack pointer cannot be used as an operand for inline asm",
122        #error = ["fp", "r30", "i6"] =>
123            "the frame pointer cannot be used as an operand for inline asm",
124        #error = ["r31", "i7"] =>
125            "the return address register cannot be used as an operand for inline asm",
126    }
127}
128
129impl SparcInlineAsmReg {
130    pub fn emit(
131        self,
132        out: &mut dyn fmt::Write,
133        _arch: InlineAsmArch,
134        _modifier: Option<char>,
135    ) -> fmt::Result {
136        out.write_fmt(format_args!("%{0}", self.name()))write!(out, "%{}", self.name())
137    }
138}