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