]> git.lizzy.rs Git - rust.git/blob - compiler/rustc_codegen_ssa/src/traits/type_.rs
Auto merge of #103691 - michaelwoerister:consistent-slice-and-str-cpp-like-debuginfo...
[rust.git] / compiler / rustc_codegen_ssa / src / traits / type_.rs
1 use super::misc::MiscMethods;
2 use super::Backend;
3 use super::HasCodegen;
4 use crate::common::TypeKind;
5 use crate::mir::place::PlaceRef;
6 use rustc_middle::ty::layout::TyAndLayout;
7 use rustc_middle::ty::{self, Ty};
8 use rustc_target::abi::call::{ArgAbi, CastTarget, FnAbi, Reg};
9 use rustc_target::abi::{AddressSpace, Integer};
10
11 // This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
12 // `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
13 pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
14     fn type_i1(&self) -> Self::Type;
15     fn type_i8(&self) -> Self::Type;
16     fn type_i16(&self) -> Self::Type;
17     fn type_i32(&self) -> Self::Type;
18     fn type_i64(&self) -> Self::Type;
19     fn type_i128(&self) -> Self::Type;
20     fn type_isize(&self) -> Self::Type;
21
22     fn type_f32(&self) -> Self::Type;
23     fn type_f64(&self) -> Self::Type;
24
25     fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
26     fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type;
27     fn type_kind(&self, ty: Self::Type) -> TypeKind;
28     fn type_ptr_to(&self, ty: Self::Type) -> Self::Type;
29     fn type_ptr_to_ext(&self, ty: Self::Type, 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 a 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
43 pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
44     fn type_i8p(&self) -> Self::Type {
45         self.type_i8p_ext(AddressSpace::DATA)
46     }
47
48     fn type_i8p_ext(&self, address_space: AddressSpace) -> Self::Type {
49         self.type_ptr_to_ext(self.type_i8(), address_space)
50     }
51
52     fn type_int(&self) -> Self::Type {
53         match &self.sess().target.c_int_width[..] {
54             "16" => self.type_i16(),
55             "32" => self.type_i32(),
56             "64" => self.type_i64(),
57             width => bug!("Unsupported c_int_width: {}", width),
58         }
59     }
60
61     fn type_from_integer(&self, i: Integer) -> Self::Type {
62         use Integer::*;
63         match i {
64             I8 => self.type_i8(),
65             I16 => self.type_i16(),
66             I32 => self.type_i32(),
67             I64 => self.type_i64(),
68             I128 => self.type_i128(),
69         }
70     }
71
72     fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
73         ty.needs_drop(self.tcx(), ty::ParamEnv::reveal_all())
74     }
75
76     fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
77         ty.is_sized(self.tcx(), ty::ParamEnv::reveal_all())
78     }
79
80     fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
81         ty.is_freeze(self.tcx(), ty::ParamEnv::reveal_all())
82     }
83
84     fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
85         let param_env = ty::ParamEnv::reveal_all();
86         if ty.is_sized(self.tcx(), param_env) {
87             return false;
88         }
89
90         let tail = self.tcx().struct_tail_erasing_lifetimes(ty, param_env);
91         match tail.kind() {
92             ty::Foreign(..) => false,
93             ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
94             _ => bug!("unexpected unsized tail: {:?}", tail),
95         }
96     }
97 }
98
99 impl<'tcx, T> DerivedTypeMethods<'tcx> for T where Self: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {}
100
101 pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> {
102     fn backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type;
103     fn cast_backend_type(&self, ty: &CastTarget) -> Self::Type;
104     fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Type;
105     fn fn_ptr_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Self::Type;
106     fn reg_backend_type(&self, ty: &Reg) -> Self::Type;
107     fn immediate_backend_type(&self, layout: TyAndLayout<'tcx>) -> Self::Type;
108     fn is_backend_immediate(&self, layout: TyAndLayout<'tcx>) -> bool;
109     fn is_backend_scalar_pair(&self, layout: TyAndLayout<'tcx>) -> bool;
110     fn backend_field_index(&self, layout: TyAndLayout<'tcx>, index: usize) -> u64;
111     fn scalar_pair_element_backend_type(
112         &self,
113         layout: TyAndLayout<'tcx>,
114         index: usize,
115         immediate: bool,
116     ) -> Self::Type;
117 }
118
119 // For backends that support CFI using type membership (i.e., testing whether a given  pointer is
120 // associated with a type identifier).
121 pub trait TypeMembershipMethods<'tcx>: Backend<'tcx> {
122     fn set_type_metadata(&self, function: Self::Function, typeid: String);
123     fn typeid_metadata(&self, typeid: String) -> Self::Value;
124 }
125
126 pub trait ArgAbiMethods<'tcx>: HasCodegen<'tcx> {
127     fn store_fn_arg(
128         &mut self,
129         arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
130         idx: &mut usize,
131         dst: PlaceRef<'tcx, Self::Value>,
132     );
133     fn store_arg(
134         &mut self,
135         arg_abi: &ArgAbi<'tcx, Ty<'tcx>>,
136         val: Self::Value,
137         dst: PlaceRef<'tcx, Self::Value>,
138     );
139     fn arg_memory_ty(&self, arg_abi: &ArgAbi<'tcx, Ty<'tcx>>) -> Self::Type;
140 }
141
142 pub trait TypeMethods<'tcx>:
143     DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> + TypeMembershipMethods<'tcx>
144 {
145 }
146
147 impl<'tcx, T> TypeMethods<'tcx> for T where
148     Self: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> + TypeMembershipMethods<'tcx>
149 {
150 }