stable_mir/unstable/convert/stable/
abi.rs1#![allow(rustc::usage_of_qualified_ty)]
4
5use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call};
6use rustc_middle::ty;
7use rustc_smir::Tables;
8use rustc_smir::context::SmirCtxt;
9use rustc_target::callconv;
10
11use crate::abi::{
12 AddressSpace, ArgAbi, CallConvention, FieldsShape, FloatLength, FnAbi, IntegerLength,
13 IntegerType, Layout, LayoutShape, PassMode, Primitive, ReprFlags, ReprOptions, Scalar,
14 TagEncoding, TyAndLayout, ValueAbi, VariantsShape, WrappingRange,
15};
16use crate::compiler_interface::BridgeTys;
17use crate::target::MachineSize as Size;
18use crate::ty::{Align, VariantIdx};
19use crate::unstable::Stable;
20use crate::{IndexedVal, opaque};
21
22impl<'tcx> Stable<'tcx> for rustc_abi::VariantIdx {
23 type T = VariantIdx;
24 fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
25 VariantIdx::to_val(self.as_usize())
26 }
27}
28
29impl<'tcx> Stable<'tcx> for rustc_abi::Endian {
30 type T = crate::target::Endian;
31
32 fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
33 match self {
34 rustc_abi::Endian::Little => crate::target::Endian::Little,
35 rustc_abi::Endian::Big => crate::target::Endian::Big,
36 }
37 }
38}
39
40impl<'tcx> Stable<'tcx> for rustc_abi::TyAndLayout<'tcx, ty::Ty<'tcx>> {
41 type T = TyAndLayout;
42
43 fn stable<'cx>(
44 &self,
45 tables: &mut Tables<'cx, BridgeTys>,
46 cx: &SmirCtxt<'cx, BridgeTys>,
47 ) -> Self::T {
48 TyAndLayout { ty: self.ty.stable(tables, cx), layout: self.layout.stable(tables, cx) }
49 }
50}
51
52impl<'tcx> Stable<'tcx> for rustc_abi::Layout<'tcx> {
53 type T = Layout;
54
55 fn stable<'cx>(
56 &self,
57 tables: &mut Tables<'cx, BridgeTys>,
58 cx: &SmirCtxt<'cx, BridgeTys>,
59 ) -> Self::T {
60 tables.layout_id(cx.lift(*self).unwrap())
61 }
62}
63
64impl<'tcx> Stable<'tcx> for rustc_abi::LayoutData<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
65 type T = LayoutShape;
66
67 fn stable<'cx>(
68 &self,
69 tables: &mut Tables<'cx, BridgeTys>,
70 cx: &SmirCtxt<'cx, BridgeTys>,
71 ) -> Self::T {
72 LayoutShape {
73 fields: self.fields.stable(tables, cx),
74 variants: self.variants.stable(tables, cx),
75 abi: self.backend_repr.stable(tables, cx),
76 abi_align: self.align.abi.stable(tables, cx),
77 size: self.size.stable(tables, cx),
78 }
79 }
80}
81
82impl<'tcx> Stable<'tcx> for callconv::FnAbi<'tcx, ty::Ty<'tcx>> {
83 type T = FnAbi;
84
85 fn stable<'cx>(
86 &self,
87 tables: &mut Tables<'cx, BridgeTys>,
88 cx: &SmirCtxt<'cx, BridgeTys>,
89 ) -> Self::T {
90 assert!(self.args.len() >= self.fixed_count as usize);
91 assert!(!self.c_variadic || matches!(self.conv, CanonAbi::C));
92 FnAbi {
93 args: self.args.as_ref().stable(tables, cx),
94 ret: self.ret.stable(tables, cx),
95 fixed_count: self.fixed_count,
96 conv: self.conv.stable(tables, cx),
97 c_variadic: self.c_variadic,
98 }
99 }
100}
101
102impl<'tcx> Stable<'tcx> for callconv::ArgAbi<'tcx, ty::Ty<'tcx>> {
103 type T = ArgAbi;
104
105 fn stable<'cx>(
106 &self,
107 tables: &mut Tables<'cx, BridgeTys>,
108 cx: &SmirCtxt<'cx, BridgeTys>,
109 ) -> Self::T {
110 ArgAbi {
111 ty: self.layout.ty.stable(tables, cx),
112 layout: self.layout.layout.stable(tables, cx),
113 mode: self.mode.stable(tables, cx),
114 }
115 }
116}
117
118impl<'tcx> Stable<'tcx> for CanonAbi {
119 type T = CallConvention;
120
121 fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
122 match self {
123 CanonAbi::C => CallConvention::C,
124 CanonAbi::Rust => CallConvention::Rust,
125 CanonAbi::RustCold => CallConvention::Cold,
126 CanonAbi::Custom => CallConvention::Custom,
127 CanonAbi::Arm(arm_call) => match arm_call {
128 ArmCall::Aapcs => CallConvention::ArmAapcs,
129 ArmCall::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall,
130 ArmCall::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry,
131 },
132 CanonAbi::GpuKernel => CallConvention::GpuKernel,
133 CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind {
134 InterruptKind::Avr => CallConvention::AvrInterrupt,
135 InterruptKind::AvrNonBlocking => CallConvention::AvrNonBlockingInterrupt,
136 InterruptKind::Msp430 => CallConvention::Msp430Intr,
137 InterruptKind::RiscvMachine | InterruptKind::RiscvSupervisor => {
138 CallConvention::RiscvInterrupt
139 }
140 InterruptKind::X86 => CallConvention::X86Intr,
141 },
142 CanonAbi::X86(x86_call) => match x86_call {
143 X86Call::Fastcall => CallConvention::X86Fastcall,
144 X86Call::Stdcall => CallConvention::X86Stdcall,
145 X86Call::SysV64 => CallConvention::X86_64SysV,
146 X86Call::Thiscall => CallConvention::X86ThisCall,
147 X86Call::Vectorcall => CallConvention::X86VectorCall,
148 X86Call::Win64 => CallConvention::X86_64Win64,
149 },
150 }
151 }
152}
153
154impl<'tcx> Stable<'tcx> for callconv::PassMode {
155 type T = PassMode;
156
157 fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
158 match self {
159 callconv::PassMode::Ignore => PassMode::Ignore,
160 callconv::PassMode::Direct(attr) => PassMode::Direct(opaque(attr)),
161 callconv::PassMode::Pair(first, second) => {
162 PassMode::Pair(opaque(first), opaque(second))
163 }
164 callconv::PassMode::Cast { pad_i32, cast } => {
165 PassMode::Cast { pad_i32: *pad_i32, cast: opaque(cast) }
166 }
167 callconv::PassMode::Indirect { attrs, meta_attrs, on_stack } => PassMode::Indirect {
168 attrs: opaque(attrs),
169 meta_attrs: opaque(meta_attrs),
170 on_stack: *on_stack,
171 },
172 }
173 }
174}
175
176impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape<rustc_abi::FieldIdx> {
177 type T = FieldsShape;
178
179 fn stable<'cx>(
180 &self,
181 tables: &mut Tables<'cx, BridgeTys>,
182 cx: &SmirCtxt<'cx, BridgeTys>,
183 ) -> Self::T {
184 match self {
185 rustc_abi::FieldsShape::Primitive => FieldsShape::Primitive,
186 rustc_abi::FieldsShape::Union(count) => FieldsShape::Union(*count),
187 rustc_abi::FieldsShape::Array { stride, count } => {
188 FieldsShape::Array { stride: stride.stable(tables, cx), count: *count }
189 }
190 rustc_abi::FieldsShape::Arbitrary { offsets, .. } => {
191 FieldsShape::Arbitrary { offsets: offsets.iter().as_slice().stable(tables, cx) }
192 }
193 }
194 }
195}
196
197impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
198 type T = VariantsShape;
199
200 fn stable<'cx>(
201 &self,
202 tables: &mut Tables<'cx, BridgeTys>,
203 cx: &SmirCtxt<'cx, BridgeTys>,
204 ) -> Self::T {
205 match self {
206 rustc_abi::Variants::Single { index } => {
207 VariantsShape::Single { index: index.stable(tables, cx) }
208 }
209 rustc_abi::Variants::Empty => VariantsShape::Empty,
210 rustc_abi::Variants::Multiple { tag, tag_encoding, tag_field, variants } => {
211 VariantsShape::Multiple {
212 tag: tag.stable(tables, cx),
213 tag_encoding: tag_encoding.stable(tables, cx),
214 tag_field: tag_field.stable(tables, cx),
215 variants: variants.iter().as_slice().stable(tables, cx),
216 }
217 }
218 }
219 }
220}
221
222impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_abi::VariantIdx> {
223 type T = TagEncoding;
224
225 fn stable<'cx>(
226 &self,
227 tables: &mut Tables<'cx, BridgeTys>,
228 cx: &SmirCtxt<'cx, BridgeTys>,
229 ) -> Self::T {
230 match self {
231 rustc_abi::TagEncoding::Direct => TagEncoding::Direct,
232 rustc_abi::TagEncoding::Niche { untagged_variant, niche_variants, niche_start } => {
233 TagEncoding::Niche {
234 untagged_variant: untagged_variant.stable(tables, cx),
235 niche_variants: niche_variants.stable(tables, cx),
236 niche_start: *niche_start,
237 }
238 }
239 }
240 }
241}
242
243impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
244 type T = ValueAbi;
245
246 fn stable<'cx>(
247 &self,
248 tables: &mut Tables<'cx, BridgeTys>,
249 cx: &SmirCtxt<'cx, BridgeTys>,
250 ) -> Self::T {
251 match *self {
252 rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables, cx)),
253 rustc_abi::BackendRepr::ScalarPair(first, second) => {
254 ValueAbi::ScalarPair(first.stable(tables, cx), second.stable(tables, cx))
255 }
256 rustc_abi::BackendRepr::SimdVector { element, count } => {
257 ValueAbi::Vector { element: element.stable(tables, cx), count }
258 }
259 rustc_abi::BackendRepr::Memory { sized } => ValueAbi::Aggregate { sized },
260 }
261 }
262}
263
264impl<'tcx> Stable<'tcx> for rustc_abi::Size {
265 type T = Size;
266
267 fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
268 Size::from_bits(self.bits_usize())
269 }
270}
271
272impl<'tcx> Stable<'tcx> for rustc_abi::Align {
273 type T = Align;
274
275 fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
276 self.bytes()
277 }
278}
279
280impl<'tcx> Stable<'tcx> for rustc_abi::Scalar {
281 type T = Scalar;
282
283 fn stable<'cx>(
284 &self,
285 tables: &mut Tables<'cx, BridgeTys>,
286 cx: &SmirCtxt<'cx, BridgeTys>,
287 ) -> Self::T {
288 match self {
289 rustc_abi::Scalar::Initialized { value, valid_range } => Scalar::Initialized {
290 value: value.stable(tables, cx),
291 valid_range: valid_range.stable(tables, cx),
292 },
293 rustc_abi::Scalar::Union { value } => Scalar::Union { value: value.stable(tables, cx) },
294 }
295 }
296}
297
298impl<'tcx> Stable<'tcx> for rustc_abi::Primitive {
299 type T = Primitive;
300
301 fn stable<'cx>(
302 &self,
303 tables: &mut Tables<'cx, BridgeTys>,
304 cx: &SmirCtxt<'cx, BridgeTys>,
305 ) -> Self::T {
306 match self {
307 rustc_abi::Primitive::Int(length, signed) => {
308 Primitive::Int { length: length.stable(tables, cx), signed: *signed }
309 }
310 rustc_abi::Primitive::Float(length) => {
311 Primitive::Float { length: length.stable(tables, cx) }
312 }
313 rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables, cx)),
314 }
315 }
316}
317
318impl<'tcx> Stable<'tcx> for rustc_abi::AddressSpace {
319 type T = AddressSpace;
320
321 fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
322 AddressSpace(self.0)
323 }
324}
325
326impl<'tcx> Stable<'tcx> for rustc_abi::Integer {
327 type T = IntegerLength;
328
329 fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
330 match self {
331 rustc_abi::Integer::I8 => IntegerLength::I8,
332 rustc_abi::Integer::I16 => IntegerLength::I16,
333 rustc_abi::Integer::I32 => IntegerLength::I32,
334 rustc_abi::Integer::I64 => IntegerLength::I64,
335 rustc_abi::Integer::I128 => IntegerLength::I128,
336 }
337 }
338}
339
340impl<'tcx> Stable<'tcx> for rustc_abi::Float {
341 type T = FloatLength;
342
343 fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
344 match self {
345 rustc_abi::Float::F16 => FloatLength::F16,
346 rustc_abi::Float::F32 => FloatLength::F32,
347 rustc_abi::Float::F64 => FloatLength::F64,
348 rustc_abi::Float::F128 => FloatLength::F128,
349 }
350 }
351}
352
353impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange {
354 type T = WrappingRange;
355
356 fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &SmirCtxt<'_, BridgeTys>) -> Self::T {
357 WrappingRange { start: self.start, end: self.end }
358 }
359}
360
361impl<'tcx> Stable<'tcx> for rustc_abi::ReprFlags {
362 type T = ReprFlags;
363
364 fn stable<'cx>(
365 &self,
366 _tables: &mut Tables<'cx, BridgeTys>,
367 _cx: &SmirCtxt<'cx, BridgeTys>,
368 ) -> Self::T {
369 ReprFlags {
370 is_simd: self.intersects(Self::IS_SIMD),
371 is_c: self.intersects(Self::IS_C),
372 is_transparent: self.intersects(Self::IS_TRANSPARENT),
373 is_linear: self.intersects(Self::IS_LINEAR),
374 }
375 }
376}
377
378impl<'tcx> Stable<'tcx> for rustc_abi::IntegerType {
379 type T = IntegerType;
380
381 fn stable<'cx>(
382 &self,
383 tables: &mut Tables<'cx, BridgeTys>,
384 cx: &SmirCtxt<'cx, BridgeTys>,
385 ) -> Self::T {
386 match self {
387 rustc_abi::IntegerType::Pointer(signed) => IntegerType::Pointer { is_signed: *signed },
388 rustc_abi::IntegerType::Fixed(integer, signed) => {
389 IntegerType::Fixed { length: integer.stable(tables, cx), is_signed: *signed }
390 }
391 }
392 }
393}
394
395impl<'tcx> Stable<'tcx> for rustc_abi::ReprOptions {
396 type T = ReprOptions;
397
398 fn stable<'cx>(
399 &self,
400 tables: &mut Tables<'cx, BridgeTys>,
401 cx: &SmirCtxt<'cx, BridgeTys>,
402 ) -> Self::T {
403 ReprOptions {
404 int: self.int.map(|int| int.stable(tables, cx)),
405 align: self.align.map(|align| align.stable(tables, cx)),
406 pack: self.pack.map(|pack| pack.stable(tables, cx)),
407 flags: self.flags.stable(tables, cx),
408 }
409 }
410}