Skip to main content

rustc_public/unstable/convert/stable/
abi.rs

1//! Conversion of internal Rust compiler `rustc_target` and `rustc_abi` items to stable ones.
2
3#![allow(rustc::usage_of_qualified_ty)]
4
5use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call};
6use rustc_middle::ty;
7use rustc_public_bridge::Tables;
8use rustc_public_bridge::context::CompilerCtxt;
9use rustc_target::callconv;
10
11use crate::IndexedVal;
12use crate::abi::{
13    AddressSpace, ArgAbi, ArgAttributeFlags, ArgAttributes, ArgExtension, CallConvention,
14    CastTarget, FieldsShape, FloatLength, FnAbi, IndirectMode, IntegerLength, IntegerType, Layout,
15    LayoutShape, NumScalableVectors, PassMode, Primitive, Reg, RegKind, ReprFlags, ReprOptions,
16    Scalar, TagEncoding, TyAndLayout, Uniform, ValueRepr, VariantFields, VariantsShape,
17    WrappingRange,
18};
19use crate::compiler_interface::BridgeTys;
20use crate::target::MachineSize as Size;
21use crate::ty::{Align, VariantIdx};
22use crate::unstable::Stable;
23
24impl<'tcx> Stable<'tcx> for rustc_abi::VariantIdx {
25    type T = VariantIdx;
26    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
27        VariantIdx::to_val(self.as_usize())
28    }
29}
30
31impl<'tcx> Stable<'tcx> for rustc_abi::Endian {
32    type T = crate::target::Endian;
33
34    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
35        match self {
36            rustc_abi::Endian::Little => crate::target::Endian::Little,
37            rustc_abi::Endian::Big => crate::target::Endian::Big,
38        }
39    }
40}
41
42impl<'tcx> Stable<'tcx> for rustc_abi::TyAndLayout<'tcx, ty::Ty<'tcx>> {
43    type T = TyAndLayout;
44
45    fn stable<'cx>(
46        &self,
47        tables: &mut Tables<'cx, BridgeTys>,
48        cx: &CompilerCtxt<'cx, BridgeTys>,
49    ) -> Self::T {
50        TyAndLayout { ty: self.ty.stable(tables, cx), layout: self.layout.stable(tables, cx) }
51    }
52}
53
54impl<'tcx> Stable<'tcx> for rustc_abi::Layout<'tcx> {
55    type T = Layout;
56
57    fn stable<'cx>(
58        &self,
59        tables: &mut Tables<'cx, BridgeTys>,
60        cx: &CompilerCtxt<'cx, BridgeTys>,
61    ) -> Self::T {
62        tables.layout_id(cx.lift(*self))
63    }
64}
65
66impl<'tcx> Stable<'tcx> for rustc_abi::LayoutData<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
67    type T = LayoutShape;
68
69    fn stable<'cx>(
70        &self,
71        tables: &mut Tables<'cx, BridgeTys>,
72        cx: &CompilerCtxt<'cx, BridgeTys>,
73    ) -> Self::T {
74        LayoutShape {
75            fields: self.fields.stable(tables, cx),
76            variants: self.variants.stable(tables, cx),
77            value_repr: self.backend_repr.stable(tables, cx),
78            abi_align: self.align.abi.stable(tables, cx),
79            size: self.size.stable(tables, cx),
80        }
81    }
82}
83
84impl<'tcx> Stable<'tcx> for callconv::FnAbi<'tcx, ty::Ty<'tcx>> {
85    type T = FnAbi;
86
87    fn stable<'cx>(
88        &self,
89        tables: &mut Tables<'cx, BridgeTys>,
90        cx: &CompilerCtxt<'cx, BridgeTys>,
91    ) -> Self::T {
92        if !(self.args.len() >= self.fixed_count as usize) {
    ::core::panicking::panic("assertion failed: self.args.len() >= self.fixed_count as usize")
};assert!(self.args.len() >= self.fixed_count as usize);
93        if !(!self.c_variadic ||
            #[allow(non_exhaustive_omitted_patterns)] match self.conv {
                CanonAbi::C => true,
                _ => false,
            }) {
    ::core::panicking::panic("assertion failed: !self.c_variadic || matches!(self.conv, CanonAbi::C)")
};assert!(!self.c_variadic || matches!(self.conv, CanonAbi::C));
94        FnAbi {
95            args: self.args.as_ref().stable(tables, cx),
96            ret: self.ret.stable(tables, cx),
97            fixed_count: self.fixed_count,
98            conv: self.conv.stable(tables, cx),
99            c_variadic: self.c_variadic,
100        }
101    }
102}
103
104impl<'tcx> Stable<'tcx> for callconv::ArgAbi<'tcx, ty::Ty<'tcx>> {
105    type T = ArgAbi;
106
107    fn stable<'cx>(
108        &self,
109        tables: &mut Tables<'cx, BridgeTys>,
110        cx: &CompilerCtxt<'cx, BridgeTys>,
111    ) -> Self::T {
112        ArgAbi {
113            ty: self.layout.ty.stable(tables, cx),
114            layout: self.layout.layout.stable(tables, cx),
115            mode: self.mode.stable(tables, cx),
116        }
117    }
118}
119
120impl<'tcx> Stable<'tcx> for CanonAbi {
121    type T = CallConvention;
122
123    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
124        match self {
125            CanonAbi::C => CallConvention::C,
126            CanonAbi::Rust => CallConvention::Rust,
127            CanonAbi::RustCold => CallConvention::Cold,
128            CanonAbi::RustPreserveNone => CallConvention::PreserveNone,
129            CanonAbi::RustTail => CallConvention::Tail,
130            CanonAbi::Custom => CallConvention::Custom,
131            CanonAbi::Swift => CallConvention::Swift,
132            CanonAbi::Arm(arm_call) => match arm_call {
133                ArmCall::Aapcs => CallConvention::ArmAapcs,
134                ArmCall::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall,
135                ArmCall::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry,
136            },
137            CanonAbi::GpuKernel => CallConvention::GpuKernel,
138            CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind {
139                InterruptKind::Avr => CallConvention::AvrInterrupt,
140                InterruptKind::AvrNonBlocking => CallConvention::AvrNonBlockingInterrupt,
141                InterruptKind::Msp430 => CallConvention::Msp430Intr,
142                InterruptKind::RiscvMachine | InterruptKind::RiscvSupervisor => {
143                    CallConvention::RiscvInterrupt
144                }
145                InterruptKind::X86 => CallConvention::X86Intr,
146            },
147            CanonAbi::X86(x86_call) => match x86_call {
148                X86Call::Fastcall => CallConvention::X86Fastcall,
149                X86Call::Stdcall => CallConvention::X86Stdcall,
150                X86Call::SysV64 => CallConvention::X86_64SysV,
151                X86Call::Thiscall => CallConvention::X86ThisCall,
152                X86Call::Vectorcall => CallConvention::X86VectorCall,
153                X86Call::Win64 => CallConvention::X86_64Win64,
154            },
155        }
156    }
157}
158
159impl<'tcx> Stable<'tcx> for callconv::IndirectMode {
160    type T = IndirectMode;
161
162    fn stable<'cx>(
163        &self,
164        _tables: &mut Tables<'cx, BridgeTys>,
165        _cx: &CompilerCtxt<'cx, BridgeTys>,
166    ) -> Self::T {
167        match self {
168            callconv::IndirectMode::Pointer => IndirectMode::Pointer,
169            callconv::IndirectMode::OnStack => IndirectMode::OnStack,
170            callconv::IndirectMode::AmdgpuKernelArg => IndirectMode::AmdgpuKernelArg,
171        }
172    }
173}
174
175impl<'tcx> Stable<'tcx> for callconv::PassMode {
176    type T = PassMode;
177
178    fn stable<'cx>(
179        &self,
180        tables: &mut Tables<'cx, BridgeTys>,
181        cx: &CompilerCtxt<'cx, BridgeTys>,
182    ) -> Self::T {
183        match self {
184            callconv::PassMode::Ignore => PassMode::Ignore,
185            callconv::PassMode::Direct(attr) => PassMode::Direct(attr.stable(tables, cx)),
186            callconv::PassMode::Pair(first, second) => {
187                PassMode::Pair(first.stable(tables, cx), second.stable(tables, cx))
188            }
189            callconv::PassMode::Cast { pad_i32_count, cast } => {
190                PassMode::Cast { pad_i32_count: *pad_i32_count, cast: cast.stable(tables, cx) }
191            }
192            callconv::PassMode::Indirect { attrs, address_space, mode } => PassMode::Indirect {
193                attrs: attrs.stable(tables, cx),
194                address_space: address_space.stable(tables, cx),
195                mode: mode.stable(tables, cx),
196            },
197            callconv::PassMode::IndirectUnsized { attrs, meta_attrs } => {
198                PassMode::IndirectUnsized {
199                    attrs: attrs.stable(tables, cx),
200                    meta_attrs: meta_attrs.stable(tables, cx),
201                }
202            }
203        }
204    }
205}
206
207impl<'tcx> Stable<'tcx> for callconv::CastTarget {
208    type T = CastTarget;
209
210    fn stable<'cx>(
211        &self,
212        tables: &mut Tables<'cx, BridgeTys>,
213        cx: &CompilerCtxt<'cx, BridgeTys>,
214    ) -> Self::T {
215        CastTarget {
216            prefix: self.prefix.iter().map(|reg| reg.stable(tables, cx)).collect(),
217            rest_offset: self.rest_offset.map(|offset| Size::from_bits(offset.bits_usize())),
218            rest: self.rest.stable(tables, cx),
219        }
220    }
221}
222
223impl<'tcx> Stable<'tcx> for callconv::Uniform {
224    type T = Uniform;
225
226    fn stable<'cx>(
227        &self,
228        tables: &mut Tables<'cx, BridgeTys>,
229        cx: &CompilerCtxt<'cx, BridgeTys>,
230    ) -> Self::T {
231        Uniform {
232            unit: self.unit.stable(tables, cx),
233            total: Size::from_bits(self.total.bits_usize()),
234            is_consecutive: self.is_consecutive,
235        }
236    }
237}
238
239impl<'tcx> Stable<'tcx> for rustc_abi::Reg {
240    type T = Reg;
241
242    fn stable<'cx>(
243        &self,
244        _: &mut Tables<'cx, BridgeTys>,
245        _: &CompilerCtxt<'cx, BridgeTys>,
246    ) -> Self::T {
247        Reg {
248            kind: match self.kind {
249                rustc_abi::RegKind::Integer => RegKind::Integer,
250                rustc_abi::RegKind::Float => RegKind::Float,
251                rustc_abi::RegKind::PpcF128 => RegKind::Float,
252                rustc_abi::RegKind::Vector { .. } => RegKind::Vector,
253            },
254            size: Size::from_bits(self.size.bits_usize()),
255        }
256    }
257}
258
259impl<'tcx> Stable<'tcx> for callconv::ArgAttributes {
260    type T = ArgAttributes;
261
262    fn stable<'cx>(
263        &self,
264        _: &mut Tables<'cx, BridgeTys>,
265        _: &CompilerCtxt<'cx, BridgeTys>,
266    ) -> Self::T {
267        ArgAttributes {
268            regular: ArgAttributeFlags {
269                captures_none: self.regular.contains(callconv::ArgAttribute::CapturesNone),
270                captures_address: self.regular.contains(callconv::ArgAttribute::CapturesAddress),
271                captures_read_only: self.regular.contains(callconv::ArgAttribute::CapturesReadOnly),
272                no_alias: self.regular.contains(callconv::ArgAttribute::NoAlias),
273                non_null: self.regular.contains(callconv::ArgAttribute::NonNull),
274                read_only: self.regular.contains(callconv::ArgAttribute::ReadOnly),
275                in_reg: self.regular.contains(callconv::ArgAttribute::InReg),
276                no_undef: self.regular.contains(callconv::ArgAttribute::NoUndef),
277                writable: self.regular.contains(callconv::ArgAttribute::Writable),
278                no_free: self.regular.contains(callconv::ArgAttribute::NoFree),
279            },
280            arg_ext: match self.arg_ext {
281                callconv::ArgExtension::None => ArgExtension::None,
282                callconv::ArgExtension::Zext => ArgExtension::Zext,
283                callconv::ArgExtension::Sext => ArgExtension::Sext,
284            },
285            pointee_size: Size::from_bits(self.pointee_size.bits_usize()),
286            pointee_align: self.pointee_align.map(|a| a.bytes()),
287        }
288    }
289}
290
291impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape<rustc_abi::FieldIdx> {
292    type T = FieldsShape;
293
294    fn stable<'cx>(
295        &self,
296        tables: &mut Tables<'cx, BridgeTys>,
297        cx: &CompilerCtxt<'cx, BridgeTys>,
298    ) -> Self::T {
299        match self {
300            rustc_abi::FieldsShape::Primitive => FieldsShape::Primitive,
301            rustc_abi::FieldsShape::Union(count) => FieldsShape::Union(*count),
302            rustc_abi::FieldsShape::Array { stride, count } => {
303                FieldsShape::Array { stride: stride.stable(tables, cx), count: *count }
304            }
305            rustc_abi::FieldsShape::Arbitrary { offsets, .. } => {
306                FieldsShape::Arbitrary { offsets: offsets.iter().as_slice().stable(tables, cx) }
307            }
308        }
309    }
310}
311
312impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
313    type T = VariantsShape;
314
315    fn stable<'cx>(
316        &self,
317        tables: &mut Tables<'cx, BridgeTys>,
318        cx: &CompilerCtxt<'cx, BridgeTys>,
319    ) -> Self::T {
320        match self {
321            rustc_abi::Variants::Single { index } => {
322                VariantsShape::Single { index: index.stable(tables, cx) }
323            }
324            rustc_abi::Variants::Empty => VariantsShape::Empty,
325            rustc_abi::Variants::Multiple { tag, tag_encoding, tag_field, variants } => {
326                VariantsShape::Multiple {
327                    tag: tag.stable(tables, cx),
328                    tag_encoding: tag_encoding.stable(tables, cx),
329                    tag_field: tag_field.stable(tables, cx),
330                    variants: variants
331                        .iter()
332                        .map(|v| VariantFields {
333                            offsets: v.field_offsets.iter().as_slice().stable(tables, cx),
334                        })
335                        .collect(),
336                }
337            }
338        }
339    }
340}
341
342impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_abi::VariantIdx> {
343    type T = TagEncoding;
344
345    fn stable<'cx>(
346        &self,
347        tables: &mut Tables<'cx, BridgeTys>,
348        cx: &CompilerCtxt<'cx, BridgeTys>,
349    ) -> Self::T {
350        match self {
351            rustc_abi::TagEncoding::Direct => TagEncoding::Direct,
352            rustc_abi::TagEncoding::Niche { untagged_variant, niche_variants, niche_start } => {
353                TagEncoding::Niche {
354                    untagged_variant: untagged_variant.stable(tables, cx),
355                    niche_variants: niche_variants.stable(tables, cx),
356                    niche_start: *niche_start,
357                }
358            }
359        }
360    }
361}
362
363impl<'tcx> Stable<'tcx> for rustc_abi::NumScalableVectors {
364    type T = NumScalableVectors;
365
366    fn stable<'cx>(
367        &self,
368        _tables: &mut Tables<'cx, BridgeTys>,
369        _cx: &CompilerCtxt<'cx, BridgeTys>,
370    ) -> Self::T {
371        NumScalableVectors(self.0)
372    }
373}
374
375impl<'tcx> Stable<'tcx> for rustc_abi::BackendLaneCount {
376    type T = u64;
377
378    fn stable<'cx>(
379        &self,
380        _tables: &mut Tables<'cx, BridgeTys>,
381        _cx: &CompilerCtxt<'cx, BridgeTys>,
382    ) -> Self::T {
383        self.as_u64()
384    }
385}
386
387impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
388    type T = ValueRepr;
389
390    fn stable<'cx>(
391        &self,
392        tables: &mut Tables<'cx, BridgeTys>,
393        cx: &CompilerCtxt<'cx, BridgeTys>,
394    ) -> Self::T {
395        match *self {
396            rustc_abi::BackendRepr::Scalar(scalar) => ValueRepr::Scalar(scalar.stable(tables, cx)),
397            rustc_abi::BackendRepr::ScalarPair { a: first, b: second, b_offset: second_offset } => {
398                ValueRepr::ScalarPair {
399                    a: first.stable(tables, cx),
400                    b: second.stable(tables, cx),
401                    b_offset: second_offset.stable(tables, cx),
402                }
403            }
404            rustc_abi::BackendRepr::SimdVector { element, count } => ValueRepr::Vector {
405                element: element.stable(tables, cx),
406                count: count.stable(tables, cx),
407            },
408            rustc_abi::BackendRepr::SimdScalableVector { element, count, number_of_vectors } => {
409                ValueRepr::ScalableVector {
410                    element: element.stable(tables, cx),
411                    count: count.stable(tables, cx),
412                    number_of_vectors: number_of_vectors.stable(tables, cx),
413                }
414            }
415            rustc_abi::BackendRepr::Memory { sized } => ValueRepr::Aggregate { sized },
416        }
417    }
418}
419
420impl<'tcx> Stable<'tcx> for rustc_abi::Size {
421    type T = Size;
422
423    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
424        Size::from_bits(self.bits_usize())
425    }
426}
427
428impl<'tcx> Stable<'tcx> for rustc_abi::Align {
429    type T = Align;
430
431    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
432        self.bytes()
433    }
434}
435
436impl<'tcx> Stable<'tcx> for rustc_abi::Scalar {
437    type T = Scalar;
438
439    fn stable<'cx>(
440        &self,
441        tables: &mut Tables<'cx, BridgeTys>,
442        cx: &CompilerCtxt<'cx, BridgeTys>,
443    ) -> Self::T {
444        match self {
445            rustc_abi::Scalar::Initialized { value, valid_range } => Scalar::Initialized {
446                value: value.stable(tables, cx),
447                valid_range: valid_range.stable(tables, cx),
448            },
449            rustc_abi::Scalar::Union { value } => Scalar::Union { value: value.stable(tables, cx) },
450        }
451    }
452}
453
454impl<'tcx> Stable<'tcx> for rustc_abi::Primitive {
455    type T = Primitive;
456
457    fn stable<'cx>(
458        &self,
459        tables: &mut Tables<'cx, BridgeTys>,
460        cx: &CompilerCtxt<'cx, BridgeTys>,
461    ) -> Self::T {
462        match self {
463            rustc_abi::Primitive::Int(length, signed) => {
464                Primitive::Int { length: length.stable(tables, cx), signed: *signed }
465            }
466            rustc_abi::Primitive::Float(length) => {
467                Primitive::Float { length: length.stable(tables, cx) }
468            }
469            rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables, cx)),
470        }
471    }
472}
473
474impl<'tcx> Stable<'tcx> for rustc_abi::AddressSpace {
475    type T = AddressSpace;
476
477    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
478        AddressSpace(self.0)
479    }
480}
481
482impl<'tcx> Stable<'tcx> for rustc_abi::Integer {
483    type T = IntegerLength;
484
485    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
486        match self {
487            rustc_abi::Integer::I8 => IntegerLength::I8,
488            rustc_abi::Integer::I16 => IntegerLength::I16,
489            rustc_abi::Integer::I32 => IntegerLength::I32,
490            rustc_abi::Integer::I64 => IntegerLength::I64,
491            rustc_abi::Integer::I128 => IntegerLength::I128,
492        }
493    }
494}
495
496impl<'tcx> Stable<'tcx> for rustc_abi::Float {
497    type T = FloatLength;
498
499    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
500        match self {
501            rustc_abi::Float::F16 => FloatLength::F16,
502            rustc_abi::Float::F16B => FloatLength::F16B,
503            rustc_abi::Float::F32 => FloatLength::F32,
504            rustc_abi::Float::F64 => FloatLength::F64,
505            rustc_abi::Float::F128 => FloatLength::F128,
506            rustc_abi::Float::PpcF128 => FloatLength::PpcF128,
507        }
508    }
509}
510
511impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange {
512    type T = WrappingRange;
513
514    fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T {
515        WrappingRange { start: self.start, end: self.end }
516    }
517}
518
519impl<'tcx> Stable<'tcx> for rustc_abi::ReprFlags {
520    type T = ReprFlags;
521
522    fn stable<'cx>(
523        &self,
524        _tables: &mut Tables<'cx, BridgeTys>,
525        _cx: &CompilerCtxt<'cx, BridgeTys>,
526    ) -> Self::T {
527        ReprFlags {
528            is_simd: self.intersects(Self::IS_SIMD),
529            is_c: self.intersects(Self::IS_C),
530            is_transparent: self.intersects(Self::IS_TRANSPARENT),
531            is_linear: self.intersects(Self::IS_LINEAR),
532        }
533    }
534}
535
536impl<'tcx> Stable<'tcx> for rustc_abi::IntegerType {
537    type T = IntegerType;
538
539    fn stable<'cx>(
540        &self,
541        tables: &mut Tables<'cx, BridgeTys>,
542        cx: &CompilerCtxt<'cx, BridgeTys>,
543    ) -> Self::T {
544        match self {
545            rustc_abi::IntegerType::Pointer(signed) => IntegerType::Pointer { is_signed: *signed },
546            rustc_abi::IntegerType::Fixed(integer, signed) => {
547                IntegerType::Fixed { length: integer.stable(tables, cx), is_signed: *signed }
548            }
549        }
550    }
551}
552
553impl<'tcx> Stable<'tcx> for rustc_abi::ReprOptions {
554    type T = ReprOptions;
555
556    fn stable<'cx>(
557        &self,
558        tables: &mut Tables<'cx, BridgeTys>,
559        cx: &CompilerCtxt<'cx, BridgeTys>,
560    ) -> Self::T {
561        ReprOptions {
562            int: self.int.map(|int| int.stable(tables, cx)),
563            align: self.align.map(|align| align.stable(tables, cx)),
564            pack: self.pack.map(|pack| pack.stable(tables, cx)),
565            flags: self.flags.stable(tables, cx),
566        }
567    }
568}