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