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