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