]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_target/src/abi/mod.rs
Auto merge of #104765 - chenyukang:yukang-fix-104639-lifetime-check, r=oli-obk
[rust.git] / compiler / rustc_target / src / abi / mod.rs
1 pub use Integer::*;
2 pub use Primitive::*;
3
4 use crate::json::{Json, ToJson};
5
6 use std::fmt;
7 use std::ops::Deref;
8
9 use rustc_data_structures::intern::Interned;
10 use rustc_macros::HashStable_Generic;
11
12 pub mod call;
13
14 pub use rustc_abi::*;
15
16 impl ToJson for Endian {
17     fn to_json(&self) -> Json {
18         self.as_str().to_json()
19     }
20 }
21
22 rustc_index::newtype_index! {
23     pub struct VariantIdx {
24         derive [HashStable_Generic]
25     }
26 }
27
28 #[derive(Copy, Clone, PartialEq, Eq, Hash, HashStable_Generic)]
29 #[rustc_pass_by_value]
30 pub struct Layout<'a>(pub Interned<'a, LayoutS<VariantIdx>>);
31
32 impl<'a> fmt::Debug for Layout<'a> {
33     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34         // See comment on `<LayoutS as Debug>::fmt` above.
35         self.0.0.fmt(f)
36     }
37 }
38
39 impl<'a> Layout<'a> {
40     pub fn fields(self) -> &'a FieldsShape {
41         &self.0.0.fields
42     }
43
44     pub fn variants(self) -> &'a Variants<VariantIdx> {
45         &self.0.0.variants
46     }
47
48     pub fn abi(self) -> Abi {
49         self.0.0.abi
50     }
51
52     pub fn largest_niche(self) -> Option<Niche> {
53         self.0.0.largest_niche
54     }
55
56     pub fn align(self) -> AbiAndPrefAlign {
57         self.0.0.align
58     }
59
60     pub fn size(self) -> Size {
61         self.0.0.size
62     }
63 }
64
65 /// The layout of a type, alongside the type itself.
66 /// Provides various type traversal APIs (e.g., recursing into fields).
67 ///
68 /// Note that the layout is NOT guaranteed to always be identical
69 /// to that obtained from `layout_of(ty)`, as we need to produce
70 /// layouts for which Rust types do not exist, such as enum variants
71 /// or synthetic fields of enums (i.e., discriminants) and fat pointers.
72 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash, HashStable_Generic)]
73 pub struct TyAndLayout<'a, Ty> {
74     pub ty: Ty,
75     pub layout: Layout<'a>,
76 }
77
78 impl<'a, Ty> Deref for TyAndLayout<'a, Ty> {
79     type Target = &'a LayoutS<VariantIdx>;
80     fn deref(&self) -> &&'a LayoutS<VariantIdx> {
81         &self.layout.0.0
82     }
83 }
84
85 /// Trait that needs to be implemented by the higher-level type representation
86 /// (e.g. `rustc_middle::ty::Ty`), to provide `rustc_target::abi` functionality.
87 pub trait TyAbiInterface<'a, C>: Sized {
88     fn ty_and_layout_for_variant(
89         this: TyAndLayout<'a, Self>,
90         cx: &C,
91         variant_index: VariantIdx,
92     ) -> TyAndLayout<'a, Self>;
93     fn ty_and_layout_field(this: TyAndLayout<'a, Self>, cx: &C, i: usize) -> TyAndLayout<'a, Self>;
94     fn ty_and_layout_pointee_info_at(
95         this: TyAndLayout<'a, Self>,
96         cx: &C,
97         offset: Size,
98     ) -> Option<PointeeInfo>;
99     fn is_adt(this: TyAndLayout<'a, Self>) -> bool;
100     fn is_never(this: TyAndLayout<'a, Self>) -> bool;
101     fn is_tuple(this: TyAndLayout<'a, Self>) -> bool;
102     fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
103 }
104
105 impl<'a, Ty> TyAndLayout<'a, Ty> {
106     pub fn for_variant<C>(self, cx: &C, variant_index: VariantIdx) -> Self
107     where
108         Ty: TyAbiInterface<'a, C>,
109     {
110         Ty::ty_and_layout_for_variant(self, cx, variant_index)
111     }
112
113     pub fn field<C>(self, cx: &C, i: usize) -> Self
114     where
115         Ty: TyAbiInterface<'a, C>,
116     {
117         Ty::ty_and_layout_field(self, cx, i)
118     }
119
120     pub fn pointee_info_at<C>(self, cx: &C, offset: Size) -> Option<PointeeInfo>
121     where
122         Ty: TyAbiInterface<'a, C>,
123     {
124         Ty::ty_and_layout_pointee_info_at(self, cx, offset)
125     }
126
127     pub fn is_single_fp_element<C>(self, cx: &C) -> bool
128     where
129         Ty: TyAbiInterface<'a, C>,
130         C: HasDataLayout,
131     {
132         match self.abi {
133             Abi::Scalar(scalar) => scalar.primitive().is_float(),
134             Abi::Aggregate { .. } => {
135                 if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
136                     self.field(cx, 0).is_single_fp_element(cx)
137                 } else {
138                     false
139                 }
140             }
141             _ => false,
142         }
143     }
144
145     pub fn is_adt<C>(self) -> bool
146     where
147         Ty: TyAbiInterface<'a, C>,
148     {
149         Ty::is_adt(self)
150     }
151
152     pub fn is_never<C>(self) -> bool
153     where
154         Ty: TyAbiInterface<'a, C>,
155     {
156         Ty::is_never(self)
157     }
158
159     pub fn is_tuple<C>(self) -> bool
160     where
161         Ty: TyAbiInterface<'a, C>,
162     {
163         Ty::is_tuple(self)
164     }
165
166     pub fn is_unit<C>(self) -> bool
167     where
168         Ty: TyAbiInterface<'a, C>,
169     {
170         Ty::is_unit(self)
171     }
172 }
173
174 impl<'a, Ty> TyAndLayout<'a, Ty> {
175     /// Returns `true` if the layout corresponds to an unsized type.
176     pub fn is_unsized(&self) -> bool {
177         self.abi.is_unsized()
178     }
179
180     #[inline]
181     pub fn is_sized(&self) -> bool {
182         self.abi.is_sized()
183     }
184
185     /// Returns `true` if the type is a ZST and not unsized.
186     pub fn is_zst(&self) -> bool {
187         match self.abi {
188             Abi::Scalar(_) | Abi::ScalarPair(..) | Abi::Vector { .. } => false,
189             Abi::Uninhabited => self.size.bytes() == 0,
190             Abi::Aggregate { sized } => sized && self.size.bytes() == 0,
191         }
192     }
193 }