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