rustc_codegen_ssa/traits/
type_.rs

1use rustc_abi::{AddressSpace, Float, Integer, Reg};
2use rustc_middle::bug;
3use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout};
4use rustc_middle::ty::{self, Ty};
5use rustc_target::callconv::{ArgAbi, CastTarget, FnAbi};
6
7use super::BackendTypes;
8use super::misc::MiscCodegenMethods;
9use crate::common::TypeKind;
10use crate::mir::place::PlaceRef;
11
12pub trait BaseTypeCodegenMethods<'tcx>: BackendTypes {
13    fn type_i8(&self) -> Self::Type;
14    fn type_i16(&self) -> Self::Type;
15    fn type_i32(&self) -> Self::Type;
16    fn type_i64(&self) -> Self::Type;
17    fn type_i128(&self) -> Self::Type;
18    fn type_isize(&self) -> Self::Type;
19
20    fn type_f16(&self) -> Self::Type;
21    fn type_f32(&self) -> Self::Type;
22    fn type_f64(&self) -> Self::Type;
23    fn type_f128(&self) -> Self::Type;
24
25    fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type;
26    fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
27    fn type_kind(&self, ty: Self::Type) -> TypeKind;
28    fn type_ptr(&self) -> Self::Type;
29    fn type_ptr_ext(&self, address_space: AddressSpace) -> Self::Type;
30    fn element_type(&self, ty: Self::Type) -> Self::Type;
31
32    /// Returns the number of elements in `self` if it is an LLVM vector type.
33    fn vector_length(&self, ty: Self::Type) -> usize;
34
35    fn float_width(&self, ty: Self::Type) -> usize;
36
37    /// Retrieves the bit width of the integer type `self`.
38    fn int_width(&self, ty: Self::Type) -> u64;
39
40    fn val_ty(&self, v: Self::Value) -> Self::Type;
41}
42
43pub trait DerivedTypeCodegenMethods<'tcx>:
44    BaseTypeCodegenMethods<'tcx> + MiscCodegenMethods<'tcx> + HasTyCtxt<'tcx> + HasTypingEnv<'tcx>
45{
46    fn type_int(&self) -> Self::Type {
47        match &self.sess().target.c_int_width[..] {
48            "16" => self.type_i16(),
49            "32" => self.type_i32(),
50            "64" => self.type_i64(),
51            width => bug!("Unsupported c_int_width: {}", width),
52        }
53    }
54
55    fn type_from_integer(&self, i: Integer) -> Self::Type {
56        use Integer::*;
57        match i {
58            I8 => self.type_i8(),
59            I16 => self.type_i16(),
60            I32 => self.type_i32(),
61            I64 => self.type_i64(),
62            I128 => self.type_i128(),
63        }
64    }
65
66    fn type_from_float(&self, f: Float) -> Self::Type {
67        use Float::*;
68        match f {
69            F16 => self.type_f16(),
70            F32 => self.type_f32(),
71            F64 => self.type_f64(),
72            F128 => self.type_f128(),
73        }
74    }
75
76    fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
77        ty.needs_drop(self.tcx(), self.typing_env())
78    }
79
80    fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
81        ty.is_sized(self.tcx(), self.typing_env())
82    }
83
84    fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
85        ty.is_freeze(self.tcx(), self.typing_env())
86    }
87
88    fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
89        if ty.is_sized(self.tcx(), self.typing_env()) {
90            return false;
91        }
92
93        let tail = self.tcx().struct_tail_for_codegen(ty, self.typing_env());
94        match tail.kind() {
95            ty::Foreign(..) => false,
96            ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
97            _ => bug!("unexpected unsized tail: {:?}", tail),
98        }
99    }
100}
101
102impl<'tcx, T> DerivedTypeCodegenMethods<'tcx> for T where
103    Self: BaseTypeCodegenMethods<'tcx>
104        + MiscCodegenMethods<'tcx>
105        + HasTyCtxt<'tcx>
106        + HasTypingEnv<'tcx>
107{
108}
109
110pub trait LayoutTypeCodegenMethods<'tcx>: BackendTypes {
111    /// The backend type used for a rust type when it's in memory,
112    /// such as when it's stack-allocated or when it's being loaded or stored.
113    fn backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type;
114    fn cast_backend_type(&self, ty: &CastTarget) -> Self::Type;
115    fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Type;
116    fn fn_ptr_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Type;
117    fn reg_backend_type(&self, ty: &Reg) -> Self::Type;
118    /// The backend type used for a rust type when it's in an SSA register.
119    ///
120    /// For nearly all types this is the same as the [`Self::backend_type`], however
121    /// `bool` (and other `0`-or-`1` values) are kept as `i1` in registers but as
122    /// [`BaseTypeCodegenMethods::type_i8`] in memory.
123    ///
124    /// Converting values between the two different backend types is done using
125    /// [`from_immediate`](super::BuilderMethods::from_immediate) and
126    /// [`to_immediate_scalar`](super::BuilderMethods::to_immediate_scalar).
127    fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type;
128    fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool;
129    fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool;
130    fn scalar_pair_element_backend_type(
131        &self,
132        layout: TyAndLayout<'tcx>,
133        index: usize,
134        immediate: bool,
135    ) -> Self::Type;
136
137    /// A type that produces an [`OperandValue::Ref`] when loaded.
138    ///
139    /// AKA one that's not a ZST, not `is_backend_immediate`, and
140    /// not `is_backend_scalar_pair`. For such a type, a
141    /// [`load_operand`] doesn't actually `load` anything.
142    ///
143    /// [`OperandValue::Ref`]: crate::mir::operand::OperandValue::Ref
144    /// [`load_operand`]: super::BuilderMethods::load_operand
145    fn is_backend_ref(&self, layout: TyAndLayout<'tcx>) -> bool {
146        !(layout.is_zst()
147            || self.is_backend_immediate(layout)
148            || self.is_backend_scalar_pair(layout))
149    }
150}
151
152// For backends that support CFI using type membership (i.e., testing whether a given pointer is
153// associated with a type identifier).
154pub trait TypeMembershipCodegenMethods<'tcx>: BackendTypes {
155    fn add_type_metadata(&self, _function: Self::Function, _typeid: String) {}
156    fn set_type_metadata(&self, _function: Self::Function, _typeid: String) {}
157    fn typeid_metadata(&self, _typeid: String) -> Option<Self::Metadata> {
158        None
159    }
160    fn add_kcfi_type_metadata(&self, _function: Self::Function, _typeid: u32) {}
161    fn set_kcfi_type_metadata(&self, _function: Self::Function, _typeid: u32) {}
162}
163
164pub trait ArgAbiBuilderMethods<'tcx>: BackendTypes {
165    fn store_fn_arg(
166        &mut self,
167        arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
168        idx: &mut usize,
169        dst: PlaceRef<'tcx, Self::Value>,
170    );
171    fn store_arg(
172        &mut self,
173        arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
174        val: Self::Value,
175        dst: PlaceRef<'tcx, Self::Value>,
176    );
177    fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> Self::Type;
178}
179
180pub trait TypeCodegenMethods<'tcx> = DerivedTypeCodegenMethods<'tcx>
181    + LayoutTypeCodegenMethods<'tcx>
182    + TypeMembershipCodegenMethods<'tcx>;