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, Layout,
10    LayoutShape, PassMode, Primitive, Scalar, TagEncoding, TyAndLayout, ValueAbi, VariantsShape,
11    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::Arm(arm_call) => match arm_call {
105                ArmCall::Aapcs => CallConvention::ArmAapcs,
106                ArmCall::CCmseNonSecureCall => CallConvention::CCmseNonSecureCall,
107                ArmCall::CCmseNonSecureEntry => CallConvention::CCmseNonSecureEntry,
108            },
109            CanonAbi::GpuKernel => CallConvention::GpuKernel,
110            CanonAbi::Interrupt(interrupt_kind) => match interrupt_kind {
111                InterruptKind::Avr => CallConvention::AvrInterrupt,
112                InterruptKind::AvrNonBlocking => CallConvention::AvrNonBlockingInterrupt,
113                InterruptKind::Msp430 => CallConvention::Msp430Intr,
114                InterruptKind::RiscvMachine | InterruptKind::RiscvSupervisor => {
115                    CallConvention::RiscvInterrupt
116                }
117                InterruptKind::X86 => CallConvention::X86Intr,
118            },
119            CanonAbi::X86(x86_call) => match x86_call {
120                X86Call::Fastcall => CallConvention::X86Fastcall,
121                X86Call::Stdcall => CallConvention::X86Stdcall,
122                X86Call::SysV64 => CallConvention::X86_64SysV,
123                X86Call::Thiscall => CallConvention::X86ThisCall,
124                X86Call::Vectorcall => CallConvention::X86VectorCall,
125                X86Call::Win64 => CallConvention::X86_64Win64,
126            },
127        }
128    }
129}
130
131impl<'tcx> Stable<'tcx> for callconv::PassMode {
132    type T = PassMode;
133
134    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
135        match self {
136            callconv::PassMode::Ignore => PassMode::Ignore,
137            callconv::PassMode::Direct(attr) => PassMode::Direct(opaque(attr)),
138            callconv::PassMode::Pair(first, second) => {
139                PassMode::Pair(opaque(first), opaque(second))
140            }
141            callconv::PassMode::Cast { pad_i32, cast } => {
142                PassMode::Cast { pad_i32: *pad_i32, cast: opaque(cast) }
143            }
144            callconv::PassMode::Indirect { attrs, meta_attrs, on_stack } => PassMode::Indirect {
145                attrs: opaque(attrs),
146                meta_attrs: opaque(meta_attrs),
147                on_stack: *on_stack,
148            },
149        }
150    }
151}
152
153impl<'tcx> Stable<'tcx> for rustc_abi::FieldsShape<rustc_abi::FieldIdx> {
154    type T = FieldsShape;
155
156    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
157        match self {
158            rustc_abi::FieldsShape::Primitive => FieldsShape::Primitive,
159            rustc_abi::FieldsShape::Union(count) => FieldsShape::Union(*count),
160            rustc_abi::FieldsShape::Array { stride, count } => {
161                FieldsShape::Array { stride: stride.stable(tables), count: *count }
162            }
163            rustc_abi::FieldsShape::Arbitrary { offsets, .. } => {
164                FieldsShape::Arbitrary { offsets: offsets.iter().as_slice().stable(tables) }
165            }
166        }
167    }
168}
169
170impl<'tcx> Stable<'tcx> for rustc_abi::Variants<rustc_abi::FieldIdx, rustc_abi::VariantIdx> {
171    type T = VariantsShape;
172
173    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
174        match self {
175            rustc_abi::Variants::Single { index } => {
176                VariantsShape::Single { index: index.stable(tables) }
177            }
178            rustc_abi::Variants::Empty => VariantsShape::Empty,
179            rustc_abi::Variants::Multiple { tag, tag_encoding, tag_field, variants } => {
180                VariantsShape::Multiple {
181                    tag: tag.stable(tables),
182                    tag_encoding: tag_encoding.stable(tables),
183                    tag_field: tag_field.stable(tables),
184                    variants: variants.iter().as_slice().stable(tables),
185                }
186            }
187        }
188    }
189}
190
191impl<'tcx> Stable<'tcx> for rustc_abi::TagEncoding<rustc_abi::VariantIdx> {
192    type T = TagEncoding;
193
194    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
195        match self {
196            rustc_abi::TagEncoding::Direct => TagEncoding::Direct,
197            rustc_abi::TagEncoding::Niche { untagged_variant, niche_variants, niche_start } => {
198                TagEncoding::Niche {
199                    untagged_variant: untagged_variant.stable(tables),
200                    niche_variants: niche_variants.stable(tables),
201                    niche_start: *niche_start,
202                }
203            }
204        }
205    }
206}
207
208impl<'tcx> Stable<'tcx> for rustc_abi::BackendRepr {
209    type T = ValueAbi;
210
211    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
212        match *self {
213            rustc_abi::BackendRepr::Scalar(scalar) => ValueAbi::Scalar(scalar.stable(tables)),
214            rustc_abi::BackendRepr::ScalarPair(first, second) => {
215                ValueAbi::ScalarPair(first.stable(tables), second.stable(tables))
216            }
217            rustc_abi::BackendRepr::SimdVector { element, count } => {
218                ValueAbi::Vector { element: element.stable(tables), count }
219            }
220            rustc_abi::BackendRepr::Memory { sized } => ValueAbi::Aggregate { sized },
221        }
222    }
223}
224
225impl<'tcx> Stable<'tcx> for rustc_abi::Size {
226    type T = Size;
227
228    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
229        Size::from_bits(self.bits_usize())
230    }
231}
232
233impl<'tcx> Stable<'tcx> for rustc_abi::Align {
234    type T = Align;
235
236    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
237        self.bytes()
238    }
239}
240
241impl<'tcx> Stable<'tcx> for rustc_abi::Scalar {
242    type T = Scalar;
243
244    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
245        match self {
246            rustc_abi::Scalar::Initialized { value, valid_range } => Scalar::Initialized {
247                value: value.stable(tables),
248                valid_range: valid_range.stable(tables),
249            },
250            rustc_abi::Scalar::Union { value } => Scalar::Union { value: value.stable(tables) },
251        }
252    }
253}
254
255impl<'tcx> Stable<'tcx> for rustc_abi::Primitive {
256    type T = Primitive;
257
258    fn stable(&self, tables: &mut Tables<'_>) -> Self::T {
259        match self {
260            rustc_abi::Primitive::Int(length, signed) => {
261                Primitive::Int { length: length.stable(tables), signed: *signed }
262            }
263            rustc_abi::Primitive::Float(length) => {
264                Primitive::Float { length: length.stable(tables) }
265            }
266            rustc_abi::Primitive::Pointer(space) => Primitive::Pointer(space.stable(tables)),
267        }
268    }
269}
270
271impl<'tcx> Stable<'tcx> for rustc_abi::AddressSpace {
272    type T = AddressSpace;
273
274    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
275        AddressSpace(self.0)
276    }
277}
278
279impl<'tcx> Stable<'tcx> for rustc_abi::Integer {
280    type T = IntegerLength;
281
282    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
283        match self {
284            rustc_abi::Integer::I8 => IntegerLength::I8,
285            rustc_abi::Integer::I16 => IntegerLength::I16,
286            rustc_abi::Integer::I32 => IntegerLength::I32,
287            rustc_abi::Integer::I64 => IntegerLength::I64,
288            rustc_abi::Integer::I128 => IntegerLength::I128,
289        }
290    }
291}
292
293impl<'tcx> Stable<'tcx> for rustc_abi::Float {
294    type T = FloatLength;
295
296    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
297        match self {
298            rustc_abi::Float::F16 => FloatLength::F16,
299            rustc_abi::Float::F32 => FloatLength::F32,
300            rustc_abi::Float::F64 => FloatLength::F64,
301            rustc_abi::Float::F128 => FloatLength::F128,
302        }
303    }
304}
305
306impl<'tcx> Stable<'tcx> for rustc_abi::WrappingRange {
307    type T = WrappingRange;
308
309    fn stable(&self, _tables: &mut Tables<'_>) -> Self::T {
310        WrappingRange { start: self.start, end: self.end }
311    }
312}