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