1use std::fmt;
2
3use rustc_span::Symbol;
4
5use super::{InlineAsmArch, InlineAsmType, ModifierInfo};
6
7#[derive(
13 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::marker::Copy for AmdgpuInlineAsmRegClass { }Copy,
14 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::clone::Clone for AmdgpuInlineAsmRegClass {
#[inline]
fn clone(&self) -> AmdgpuInlineAsmRegClass {
let _: ::core::clone::AssertParamIsClone<u16>;
*self
}
}Clone,
15 const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for AmdgpuInlineAsmRegClass {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
AmdgpuInlineAsmRegClass::Sgpr(ref __binding_0) => { 0usize }
AmdgpuInlineAsmRegClass::Vgpr(ref __binding_0) => { 1usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
AmdgpuInlineAsmRegClass::Sgpr(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
AmdgpuInlineAsmRegClass::Vgpr(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
}
}
}
};rustc_macros::Encodable,
16 const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for AmdgpuInlineAsmRegClass {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => {
AmdgpuInlineAsmRegClass::Sgpr(::rustc_serialize::Decodable::decode(__decoder))
}
1usize => {
AmdgpuInlineAsmRegClass::Vgpr(::rustc_serialize::Decodable::decode(__decoder))
}
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `AmdgpuInlineAsmRegClass`, expected 0..2, actual {0}",
n));
}
}
}
}
};rustc_macros::Decodable,
17 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::fmt::Debug for AmdgpuInlineAsmRegClass {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
AmdgpuInlineAsmRegClass::Sgpr(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Sgpr",
&__self_0),
AmdgpuInlineAsmRegClass::Vgpr(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Vgpr",
&__self_0),
}
}
}Debug,
18 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::Eq for AmdgpuInlineAsmRegClass {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u16>;
}
}Eq,
19 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialEq for AmdgpuInlineAsmRegClass {
#[inline]
fn eq(&self, other: &AmdgpuInlineAsmRegClass) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(AmdgpuInlineAsmRegClass::Sgpr(__self_0),
AmdgpuInlineAsmRegClass::Sgpr(__arg1_0)) =>
__self_0 == __arg1_0,
(AmdgpuInlineAsmRegClass::Vgpr(__self_0),
AmdgpuInlineAsmRegClass::Vgpr(__arg1_0)) =>
__self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq,
20 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialOrd for AmdgpuInlineAsmRegClass {
#[inline]
fn partial_cmp(&self, other: &AmdgpuInlineAsmRegClass)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match (self, other) {
(AmdgpuInlineAsmRegClass::Sgpr(__self_0),
AmdgpuInlineAsmRegClass::Sgpr(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(AmdgpuInlineAsmRegClass::Vgpr(__self_0),
AmdgpuInlineAsmRegClass::Vgpr(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
_ =>
::core::cmp::PartialOrd::partial_cmp(&__self_discr,
&__arg1_discr),
}
}
}PartialOrd,
21 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::hash::Hash for AmdgpuInlineAsmRegClass {
#[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);
match self {
AmdgpuInlineAsmRegClass::Sgpr(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
AmdgpuInlineAsmRegClass::Vgpr(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
}
}
}Hash,
22 const _: () =
{
impl ::rustc_data_structures::stable_hash::StableHash for
AmdgpuInlineAsmRegClass {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
match *self {
AmdgpuInlineAsmRegClass::Sgpr(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
AmdgpuInlineAsmRegClass::Vgpr(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
}
}
}
};rustc_macros::StableHash
23)]
24#[allow(non_camel_case_types)]
25pub enum AmdgpuInlineAsmRegClass {
26 Sgpr(u16),
27 Vgpr(u16),
28}
29
30pub(super) fn regclass_map() -> rustc_data_structures::fx::FxHashMap<
31 super::InlineAsmRegClass,
32 rustc_data_structures::fx::FxIndexSet<super::InlineAsmReg>,
33> {
34 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
35
36 use super::InlineAsmRegClass;
37 let mut map = FxHashMap::default();
38
39 for i in [32, 64, 96, 128, 256, 512] {
41 map.insert(
42 InlineAsmRegClass::Amdgpu(AmdgpuInlineAsmRegClass::Sgpr(i)),
43 FxIndexSet::default(),
44 );
45 map.insert(
46 InlineAsmRegClass::Amdgpu(AmdgpuInlineAsmRegClass::Vgpr(i)),
47 FxIndexSet::default(),
48 );
49 }
50
51 for i in [16, 160, 192, 224, 288, 320, 352, 384, 1024] {
53 map.insert(
54 InlineAsmRegClass::Amdgpu(AmdgpuInlineAsmRegClass::Vgpr(i)),
55 FxIndexSet::default(),
56 );
57 }
58
59 map
60}
61
62impl AmdgpuInlineAsmRegClass {
64 fn prefix(self) -> &'static str {
66 match self {
67 Self::Sgpr(_) => "s",
68 Self::Vgpr(_) => "v",
69 }
70 }
71
72 fn bits(self) -> u16 {
74 let (Self::Sgpr(i) | Self::Vgpr(i)) = self;
75 i
76 }
77
78 fn bytes(self) -> u16 {
80 self.bits() / 8
81 }
82
83 fn try_get_name(self) -> Option<rustc_span::Symbol> {
85 let s = match self {
86 Self::Sgpr(32) => rustc_span::sym::sgpr32,
87 Self::Sgpr(64) => rustc_span::sym::sgpr64,
88 Self::Sgpr(96) => rustc_span::sym::sgpr96,
89 Self::Sgpr(128) => rustc_span::sym::sgpr128,
90 Self::Sgpr(256) => rustc_span::sym::sgpr256,
91 Self::Sgpr(512) => rustc_span::sym::sgpr512,
92 Self::Vgpr(16) => rustc_span::sym::vgpr16,
93 Self::Vgpr(32) => rustc_span::sym::vgpr32,
94 Self::Vgpr(64) => rustc_span::sym::vgpr64,
95 Self::Vgpr(96) => rustc_span::sym::vgpr96,
96 Self::Vgpr(128) => rustc_span::sym::vgpr128,
97 Self::Vgpr(160) => rustc_span::sym::vgpr160,
98 Self::Vgpr(192) => rustc_span::sym::vgpr192,
99 Self::Vgpr(224) => rustc_span::sym::vgpr224,
100 Self::Vgpr(256) => rustc_span::sym::vgpr256,
101 Self::Vgpr(288) => rustc_span::sym::vgpr288,
102 Self::Vgpr(320) => rustc_span::sym::vgpr320,
103 Self::Vgpr(352) => rustc_span::sym::vgpr352,
104 Self::Vgpr(384) => rustc_span::sym::vgpr384,
105 Self::Vgpr(512) => rustc_span::sym::vgpr512,
106 Self::Vgpr(1024) => rustc_span::sym::vgpr1024,
107 _ => return None,
108 };
109 Some(s)
110 }
111
112 pub fn name(self) -> rustc_span::Symbol {
113 self.try_get_name().expect("Invalid amdgpu register class")
114 }
115
116 pub fn parse(name: rustc_span::Symbol) -> Result<Self, &'static [rustc_span::Symbol]> {
117 match name {
118 rustc_span::sym::sgpr32 => Ok(Self::Sgpr(32)),
119 rustc_span::sym::sgpr64 => Ok(Self::Sgpr(64)),
120 rustc_span::sym::sgpr96 => Ok(Self::Sgpr(96)),
121 rustc_span::sym::sgpr128 => Ok(Self::Sgpr(128)),
122 rustc_span::sym::sgpr256 => Ok(Self::Sgpr(256)),
123 rustc_span::sym::sgpr512 => Ok(Self::Sgpr(512)),
124 rustc_span::sym::vgpr16 => Ok(Self::Vgpr(16)),
125 rustc_span::sym::vgpr32 => Ok(Self::Vgpr(32)),
126 rustc_span::sym::vgpr64 => Ok(Self::Vgpr(64)),
127 rustc_span::sym::vgpr96 => Ok(Self::Vgpr(96)),
128 rustc_span::sym::vgpr128 => Ok(Self::Vgpr(128)),
129 rustc_span::sym::vgpr160 => Ok(Self::Vgpr(160)),
130 rustc_span::sym::vgpr192 => Ok(Self::Vgpr(192)),
131 rustc_span::sym::vgpr224 => Ok(Self::Vgpr(224)),
132 rustc_span::sym::vgpr256 => Ok(Self::Vgpr(256)),
133 rustc_span::sym::vgpr288 => Ok(Self::Vgpr(288)),
134 rustc_span::sym::vgpr320 => Ok(Self::Vgpr(320)),
135 rustc_span::sym::vgpr352 => Ok(Self::Vgpr(352)),
136 rustc_span::sym::vgpr384 => Ok(Self::Vgpr(384)),
137 rustc_span::sym::vgpr512 => Ok(Self::Vgpr(512)),
138 rustc_span::sym::vgpr1024 => Ok(Self::Vgpr(1024)),
139 _ => Err(&[
140 rustc_span::sym::sgpr32,
141 rustc_span::sym::sgpr64,
142 rustc_span::sym::sgpr96,
143 rustc_span::sym::sgpr128,
144 rustc_span::sym::sgpr256,
145 rustc_span::sym::sgpr512,
146 rustc_span::sym::vgpr16,
147 rustc_span::sym::vgpr32,
148 rustc_span::sym::vgpr64,
149 rustc_span::sym::vgpr96,
150 rustc_span::sym::vgpr128,
151 rustc_span::sym::vgpr160,
152 rustc_span::sym::vgpr192,
153 rustc_span::sym::vgpr224,
154 rustc_span::sym::vgpr256,
155 rustc_span::sym::vgpr288,
156 rustc_span::sym::vgpr320,
157 rustc_span::sym::vgpr352,
158 rustc_span::sym::vgpr384,
159 rustc_span::sym::vgpr512,
160 rustc_span::sym::vgpr1024,
161 ]),
162 }
163 }
164
165 pub fn valid_modifiers(self, _arch: InlineAsmArch) -> &'static [char] {
166 &[]
167 }
168
169 pub fn suggest_class(self, _arch: InlineAsmArch, ty: InlineAsmType) -> Option<Self> {
170 if #[allow(non_exhaustive_omitted_patterns)] match ty {
InlineAsmType::I8 | InlineAsmType::VecI8(_) | InlineAsmType::F128 |
InlineAsmType::VecF128(_) => true,
_ => false,
}matches!(
172 ty,
173 InlineAsmType::I8
174 | InlineAsmType::VecI8(_)
175 | InlineAsmType::F128
176 | InlineAsmType::VecF128(_)
177 ) {
178 return None;
179 }
180
181 Some(Self::Vgpr(ty.size().bits().try_into().ok()?))
182 }
183
184 pub fn suggest_modifier(
185 self,
186 _arch: InlineAsmArch,
187 _ty: InlineAsmType,
188 ) -> Option<ModifierInfo> {
189 None
190 }
191
192 pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<ModifierInfo> {
193 None
194 }
195
196 pub fn supported_types(self, _arch: InlineAsmArch) -> Vec<(InlineAsmType, Option<Symbol>)> {
197 use InlineAsmType::*;
198 let mut types = Vec::new();
199 let mut add_types = |ts: &[_]| {
200 for t in ts {
201 types.push((*t, None))
202 }
203 };
204 let bits = self.bits() as u64;
205
206 match bits {
208 16 => add_types(&[I16, F16]),
209 32 => add_types(&[I16, F16, I32, F32]),
211 64 => add_types(&[I64, F64]),
212 128 => add_types(&[I128]),
213 _ => {}
214 }
215
216 if bits == 1024 {
218 add_types(&[VecF32(1024 / 32)]);
219 } else {
220 if bits > 16 && bits.is_power_of_two() {
221 add_types(&[VecI16(bits / 16), VecF16(bits / 16)]);
223 }
224 if bits > 32 {
225 add_types(&[VecI32(bits / 32), VecF32(bits / 32)]);
227 }
228 }
229
230 types
234 }
235
236 fn max_num(self) -> u16 {
240 if self == Self::Vgpr(16) {
241 return 512;
242 }
243 let size = self.bytes();
244 match self {
245 Self::Sgpr(_) => 106 - (size / 4 - 1),
246 Self::Vgpr(_) => 256 - (size / 4 - 1),
247 }
248 }
249
250 fn parse_with_prefix(prefix: char, bits: u16) -> Result<Self, &'static str> {
252 let res = match prefix {
253 's' => Self::Sgpr(bits),
254 'v' => Self::Vgpr(bits),
255 _ => return Err("unknown register prefix"),
256 };
257
258 if res.try_get_name().is_none() {
260 return Err("invalid register size for this class");
261 }
262
263 Ok(res)
264 }
265}
266
267#[derive(
271 #[automatically_derived]
impl ::core::marker::Copy for AmdgpuRegStart { }Copy,
272 #[automatically_derived]
impl ::core::clone::Clone for AmdgpuRegStart {
#[inline]
fn clone(&self) -> AmdgpuRegStart {
let _: ::core::clone::AssertParamIsClone<u16>;
*self
}
}Clone,
273 const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for AmdgpuRegStart {
fn encode(&self, __encoder: &mut __E) {
let disc =
match *self {
AmdgpuRegStart::Low(ref __binding_0) => { 0usize }
AmdgpuRegStart::High(ref __binding_0) => { 1usize }
AmdgpuRegStart::Full(ref __binding_0) => { 2usize }
};
::rustc_serialize::Encoder::emit_u8(__encoder, disc as u8);
match *self {
AmdgpuRegStart::Low(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
AmdgpuRegStart::High(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
AmdgpuRegStart::Full(ref __binding_0) => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
}
}
}
}
};rustc_macros::Encodable,
274 const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for AmdgpuRegStart {
fn decode(__decoder: &mut __D) -> Self {
match ::rustc_serialize::Decoder::read_u8(__decoder) as usize
{
0usize => {
AmdgpuRegStart::Low(::rustc_serialize::Decodable::decode(__decoder))
}
1usize => {
AmdgpuRegStart::High(::rustc_serialize::Decodable::decode(__decoder))
}
2usize => {
AmdgpuRegStart::Full(::rustc_serialize::Decodable::decode(__decoder))
}
n => {
::core::panicking::panic_fmt(format_args!("invalid enum variant tag while decoding `AmdgpuRegStart`, expected 0..3, actual {0}",
n));
}
}
}
}
};rustc_macros::Decodable,
275 #[automatically_derived]
impl ::core::fmt::Debug for AmdgpuRegStart {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
match self {
AmdgpuRegStart::Low(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Low",
&__self_0),
AmdgpuRegStart::High(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "High",
&__self_0),
AmdgpuRegStart::Full(__self_0) =>
::core::fmt::Formatter::debug_tuple_field1_finish(f, "Full",
&__self_0),
}
}
}Debug,
276 #[automatically_derived]
impl ::core::cmp::Eq for AmdgpuRegStart {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<u16>;
}
}Eq,
277 #[automatically_derived]
impl ::core::cmp::PartialEq for AmdgpuRegStart {
#[inline]
fn eq(&self, other: &AmdgpuRegStart) -> bool {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
__self_discr == __arg1_discr &&
match (self, other) {
(AmdgpuRegStart::Low(__self_0), AmdgpuRegStart::Low(__arg1_0))
=> __self_0 == __arg1_0,
(AmdgpuRegStart::High(__self_0),
AmdgpuRegStart::High(__arg1_0)) => __self_0 == __arg1_0,
(AmdgpuRegStart::Full(__self_0),
AmdgpuRegStart::Full(__arg1_0)) => __self_0 == __arg1_0,
_ => unsafe { ::core::intrinsics::unreachable() }
}
}
}PartialEq,
278 #[automatically_derived]
impl ::core::cmp::PartialOrd for AmdgpuRegStart {
#[inline]
fn partial_cmp(&self, other: &AmdgpuRegStart)
-> ::core::option::Option<::core::cmp::Ordering> {
let __self_discr = ::core::intrinsics::discriminant_value(self);
let __arg1_discr = ::core::intrinsics::discriminant_value(other);
match (self, other) {
(AmdgpuRegStart::Low(__self_0), AmdgpuRegStart::Low(__arg1_0)) =>
::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(AmdgpuRegStart::High(__self_0), AmdgpuRegStart::High(__arg1_0))
=> ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
(AmdgpuRegStart::Full(__self_0), AmdgpuRegStart::Full(__arg1_0))
=> ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0),
_ =>
::core::cmp::PartialOrd::partial_cmp(&__self_discr,
&__arg1_discr),
}
}
}PartialOrd,
279 #[automatically_derived]
impl ::core::hash::Hash for AmdgpuRegStart {
#[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);
match self {
AmdgpuRegStart::Low(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
AmdgpuRegStart::High(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
AmdgpuRegStart::Full(__self_0) =>
::core::hash::Hash::hash(__self_0, state),
}
}
}Hash,
280 const _: () =
{
impl ::rustc_data_structures::stable_hash::StableHash for
AmdgpuRegStart {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
::std::mem::discriminant(self).stable_hash(__hcx, __hasher);
match *self {
AmdgpuRegStart::Low(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
AmdgpuRegStart::High(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
AmdgpuRegStart::Full(ref __binding_0) => {
{ __binding_0.stable_hash(__hcx, __hasher); }
}
}
}
}
};rustc_macros::StableHash
281)]
282enum AmdgpuRegStart {
283 Low(u16),
285 High(u16),
287 Full(u16),
289}
290
291#[derive(
292 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::marker::Copy for AmdgpuInlineAsmReg { }Copy,
293 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::clone::Clone for AmdgpuInlineAsmReg {
#[inline]
fn clone(&self) -> AmdgpuInlineAsmReg {
let _: ::core::clone::AssertParamIsClone<AmdgpuInlineAsmRegClass>;
let _: ::core::clone::AssertParamIsClone<AmdgpuRegStart>;
*self
}
}Clone,
294 const _: () =
{
impl<__E: ::rustc_span::SpanEncoder> ::rustc_serialize::Encodable<__E>
for AmdgpuInlineAsmReg {
fn encode(&self, __encoder: &mut __E) {
match *self {
AmdgpuInlineAsmReg {
class: ref __binding_0, range: ref __binding_1 } => {
::rustc_serialize::Encodable::<__E>::encode(__binding_0,
__encoder);
::rustc_serialize::Encodable::<__E>::encode(__binding_1,
__encoder);
}
}
}
}
};rustc_macros::Encodable,
295 const _: () =
{
impl<__D: ::rustc_span::SpanDecoder> ::rustc_serialize::Decodable<__D>
for AmdgpuInlineAsmReg {
fn decode(__decoder: &mut __D) -> Self {
AmdgpuInlineAsmReg {
class: ::rustc_serialize::Decodable::decode(__decoder),
range: ::rustc_serialize::Decodable::decode(__decoder),
}
}
}
};rustc_macros::Decodable,
296 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::fmt::Debug for AmdgpuInlineAsmReg {
#[inline]
fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result {
::core::fmt::Formatter::debug_struct_field2_finish(f,
"AmdgpuInlineAsmReg", "class", &self.class, "range", &&self.range)
}
}Debug,
297 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::Eq for AmdgpuInlineAsmReg {
#[inline]
#[doc(hidden)]
#[coverage(off)]
fn assert_fields_are_eq(&self) {
let _: ::core::cmp::AssertParamIsEq<AmdgpuInlineAsmRegClass>;
let _: ::core::cmp::AssertParamIsEq<AmdgpuRegStart>;
}
}Eq,
298 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialEq for AmdgpuInlineAsmReg {
#[inline]
fn eq(&self, other: &AmdgpuInlineAsmReg) -> bool {
self.class == other.class && self.range == other.range
}
}PartialEq,
299 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::cmp::PartialOrd for AmdgpuInlineAsmReg {
#[inline]
fn partial_cmp(&self, other: &AmdgpuInlineAsmReg)
-> ::core::option::Option<::core::cmp::Ordering> {
match ::core::cmp::PartialOrd::partial_cmp(&self.class, &other.class)
{
::core::option::Option::Some(::core::cmp::Ordering::Equal) =>
::core::cmp::PartialOrd::partial_cmp(&self.range,
&other.range),
cmp => cmp,
}
}
}PartialOrd,
300 #[automatically_derived]
#[allow(non_camel_case_types)]
impl ::core::hash::Hash for AmdgpuInlineAsmReg {
#[inline]
fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) {
::core::hash::Hash::hash(&self.class, state);
::core::hash::Hash::hash(&self.range, state)
}
}Hash,
301 const _: () =
{
impl ::rustc_data_structures::stable_hash::StableHash for
AmdgpuInlineAsmReg {
#[inline]
fn stable_hash<__Hcx: ::rustc_data_structures::stable_hash::StableHashCtxt>(&self,
__hcx: &mut __Hcx,
__hasher:
&mut ::rustc_data_structures::stable_hash::StableHasher) {
match *self {
AmdgpuInlineAsmReg {
class: ref __binding_0, range: ref __binding_1 } => {
{ __binding_0.stable_hash(__hcx, __hasher); }
{ __binding_1.stable_hash(__hcx, __hasher); }
}
}
}
}
};rustc_macros::StableHash
302)]
303#[allow(non_camel_case_types)]
304pub struct AmdgpuInlineAsmReg {
305 class: AmdgpuInlineAsmRegClass,
306 range: AmdgpuRegStart,
307}
308
309impl AmdgpuInlineAsmReg {
310 pub fn name(self) -> String {
311 let c = self.class.prefix();
312 match self.range {
313 AmdgpuRegStart::Low(n) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}.l", c, n))
})format!("{c}{n}.l"),
314 AmdgpuRegStart::High(n) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}.h", c, n))
})format!("{c}{n}.h"),
315 AmdgpuRegStart::Full(n) if self.class.bytes() == 4 => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{0}{1}", c, n))
})format!("{c}{n}"),
316 AmdgpuRegStart::Full(n) => ::alloc::__export::must_use({
::alloc::fmt::format(format_args!("{1}[{2}:{0}]",
n + self.class.bytes() / 4 - 1, c, n))
})format!("{c}[{n}:{}]", n + self.class.bytes() / 4 - 1),
317 }
318 }
319
320 pub fn reg_class(self) -> AmdgpuInlineAsmRegClass {
321 self.class
322 }
323
324 pub fn parse(name: &str) -> Result<Self, &'static str> {
325 if name.is_empty() {
326 return Err("invalid empty register");
327 }
328 let prefix = name.chars().next().unwrap();
330 let res;
332 if name[1..].starts_with('[') {
333 if !name.ends_with(']') {
334 return Err("invalid register, missing closing bracket");
335 }
336 if let Some((start, end)) = name[2..name.len() - 1].split_once(':') {
337 let Ok(start) = start.parse() else {
338 return Err("invalid register range start");
339 };
340 let Ok(end) = end.parse() else {
341 return Err("invalid register range end");
342 };
343
344 if start > end {
346 return Err("invalid reversed register range");
347 }
348
349 let class =
350 AmdgpuInlineAsmRegClass::parse_with_prefix(prefix, ((end - start) + 1) * 32)?;
351 if end >= class.max_num() {
352 return Err("too large register for this class");
353 }
354 res = Self { class, range: AmdgpuRegStart::Full(start) };
355 } else {
356 return Err("invalid register range");
357 }
358 } else {
359 let parse_num = |core: &str| {
360 let Ok(start) = core.parse() else {
361 return Err("invalid register number");
362 };
363
364 let class = AmdgpuInlineAsmRegClass::parse_with_prefix(prefix, 32)?;
365 if start >= class.max_num() {
366 return Err("too large register for this class");
367 }
368
369 Ok(start)
370 };
371
372 let name = &name[1..];
373 let class;
374 let range = if let Some(name) = name.strip_suffix(".l") {
375 class = AmdgpuInlineAsmRegClass::parse_with_prefix(prefix, 16)?;
376 if #[allow(non_exhaustive_omitted_patterns)] match class {
AmdgpuInlineAsmRegClass::Sgpr(_) => true,
_ => false,
}matches!(class, AmdgpuInlineAsmRegClass::Sgpr(_)) {
377 return Err("invalid 16-bit SGPR register");
378 }
379 AmdgpuRegStart::Low(parse_num(name)?)
380 } else if let Some(name) = name.strip_suffix(".h") {
381 class = AmdgpuInlineAsmRegClass::parse_with_prefix(prefix, 16)?;
382 if #[allow(non_exhaustive_omitted_patterns)] match class {
AmdgpuInlineAsmRegClass::Sgpr(_) => true,
_ => false,
}matches!(class, AmdgpuInlineAsmRegClass::Sgpr(_)) {
383 return Err("invalid 16-bit SGPR register");
384 }
385 AmdgpuRegStart::High(parse_num(name)?)
386 } else {
387 class = AmdgpuInlineAsmRegClass::parse_with_prefix(prefix, 32)?;
388 let start = parse_num(name)?;
389 AmdgpuRegStart::Full(start)
390 };
391 res = Self { class, range };
392 }
393 Ok(res)
394 }
395
396 pub fn validate(
397 self,
398 _arch: super::InlineAsmArch,
399 _reloc_model: crate::spec::RelocModel,
400 _target_features: &rustc_data_structures::fx::FxIndexSet<Symbol>,
401 _target: &crate::spec::Target,
402 _is_clobber: bool,
403 ) -> Result<(), &'static str> {
404 Ok(())
405 }
406}
407
408pub(super) fn fill_reg_map(
409 _arch: super::InlineAsmArch,
410 _reloc_model: crate::spec::RelocModel,
411 _target_features: &rustc_data_structures::fx::FxIndexSet<Symbol>,
412 _target: &crate::spec::Target,
413 map: &mut rustc_data_structures::fx::FxHashMap<
414 super::InlineAsmRegClass,
415 rustc_data_structures::fx::FxIndexSet<super::InlineAsmReg>,
416 >,
417) {
418 use super::{InlineAsmReg, InlineAsmRegClass};
419
420 #[allow(rustc::potential_query_instability)]
421 for class in regclass_map().keys() {
422 let InlineAsmRegClass::Amdgpu(class) = *class else { {
::core::panicking::panic_fmt(format_args!("internal error: entered unreachable code: {0}",
format_args!("Must be amdgpu class")));
}unreachable!("Must be amdgpu class") };
423 if let Some(set) = map.get_mut(&InlineAsmRegClass::Amdgpu(class)) {
424 if class == AmdgpuInlineAsmRegClass::Vgpr(16) {
425 for i in 0..(class.max_num() / 2) {
426 set.insert(InlineAsmReg::Amdgpu(AmdgpuInlineAsmReg {
427 class,
428 range: AmdgpuRegStart::Low(i),
429 }));
430 set.insert(InlineAsmReg::Amdgpu(AmdgpuInlineAsmReg {
431 class,
432 range: AmdgpuRegStart::High(i),
433 }));
434 }
435 } else {
436 for i in 0..class.max_num() {
437 set.insert(InlineAsmReg::Amdgpu(AmdgpuInlineAsmReg {
438 class,
439 range: AmdgpuRegStart::Full(i),
440 }));
441 }
442 }
443 }
444 }
445}
446
447impl AmdgpuInlineAsmReg {
448 pub fn emit(
449 self,
450 out: &mut dyn fmt::Write,
451 _arch: InlineAsmArch,
452 _modifier: Option<char>,
453 ) -> fmt::Result {
454 out.write_str(&self.name())
455 }
456
457 pub fn overlapping_regs(self, mut cb: impl FnMut(AmdgpuInlineAsmReg)) {
458 if #[allow(non_exhaustive_omitted_patterns)] match self.class {
AmdgpuInlineAsmRegClass::Vgpr(_) => true,
_ => false,
}matches!(self.class, AmdgpuInlineAsmRegClass::Vgpr(_)) {
459 if let AmdgpuRegStart::Full(start) = self.range {
461 for i in start..(start + self.class.bytes().div_ceil(4) - 1) {
462 cb(AmdgpuInlineAsmReg {
463 class: AmdgpuInlineAsmRegClass::Vgpr(16),
464 range: AmdgpuRegStart::Low(i),
465 });
466 cb(AmdgpuInlineAsmReg {
467 class: AmdgpuInlineAsmRegClass::Vgpr(16),
468 range: AmdgpuRegStart::High(i),
469 });
470 }
471 }
472 }
473
474 for size in 1..=32 {
476 let (AmdgpuRegStart::Low(start)
477 | AmdgpuRegStart::High(start)
478 | AmdgpuRegStart::Full(start)) = self.range;
479
480 let size_range = size - 1;
481 for overlap_start in
482 start.saturating_sub(size_range)..=(start + self.class.bytes().div_ceil(4) - 1)
483 {
484 let class = match self.class {
485 AmdgpuInlineAsmRegClass::Sgpr(_) => AmdgpuInlineAsmRegClass::Sgpr(size * 32),
486 AmdgpuInlineAsmRegClass::Vgpr(_) => AmdgpuInlineAsmRegClass::Vgpr(size * 32),
487 };
488 cb(AmdgpuInlineAsmReg { class, range: AmdgpuRegStart::Full(overlap_start) });
489 }
490 }
491 }
492}