]> git.proxmox.com Git - rustc.git/blob - src/librustc_codegen_ssa/traits/type_.rs
New upstream version 1.34.2+dfsg1
[rustc.git] / src / librustc_codegen_ssa / traits / type_.rs
1 use super::misc::MiscMethods;
2 use super::Backend;
3 use super::HasCodegen;
4 use crate::common::{self, TypeKind};
5 use crate::mir::place::PlaceRef;
6 use rustc::ty::layout::{self, Align, Size, TyLayout};
7 use rustc::ty::{self, Ty};
8 use rustc::util::nodemap::FxHashMap;
9 use rustc_target::abi::call::{ArgType, CastTarget, FnType, Reg};
10 use std::cell::RefCell;
11 use syntax::ast;
12
13 // This depends on `Backend` and not `BackendTypes`, because consumers will probably want to use
14 // `LayoutOf` or `HasTyCtxt`. This way, they don't have to add a constraint on it themselves.
15 pub trait BaseTypeMethods<'tcx>: Backend<'tcx> {
16 fn type_void(&self) -> Self::Type;
17 fn type_metadata(&self) -> Self::Type;
18 fn type_i1(&self) -> Self::Type;
19 fn type_i8(&self) -> Self::Type;
20 fn type_i16(&self) -> Self::Type;
21 fn type_i32(&self) -> Self::Type;
22 fn type_i64(&self) -> Self::Type;
23 fn type_i128(&self) -> Self::Type;
24
25 // Creates an integer type with the given number of bits, e.g., i24
26 fn type_ix(&self, num_bits: u64) -> Self::Type;
27 fn type_isize(&self) -> Self::Type;
28
29 fn type_f32(&self) -> Self::Type;
30 fn type_f64(&self) -> Self::Type;
31 fn type_x86_mmx(&self) -> Self::Type;
32
33 fn type_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
34 fn type_variadic_func(&self, args: &[Self::Type], ret: Self::Type) -> Self::Type;
35 fn type_struct(&self, els: &[Self::Type], packed: bool) -> Self::Type;
36 fn type_array(&self, ty: Self::Type, len: u64) -> Self::Type;
37 fn type_vector(&self, ty: Self::Type, len: u64) -> Self::Type;
38 fn type_kind(&self, ty: Self::Type) -> TypeKind;
39 fn type_ptr_to(&self, ty: Self::Type) -> Self::Type;
40 fn element_type(&self, ty: Self::Type) -> Self::Type;
41
42 /// Returns the number of elements in `self` if it is a LLVM vector type.
43 fn vector_length(&self, ty: Self::Type) -> usize;
44
45 fn func_params_types(&self, ty: Self::Type) -> Vec<Self::Type>;
46 fn float_width(&self, ty: Self::Type) -> usize;
47
48 /// Retrieves the bit width of the integer type `self`.
49 fn int_width(&self, ty: Self::Type) -> u64;
50
51 fn val_ty(&self, v: Self::Value) -> Self::Type;
52 fn scalar_lltypes(&self) -> &RefCell<FxHashMap<Ty<'tcx>, Self::Type>>;
53 }
54
55 pub trait DerivedTypeMethods<'tcx>: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {
56 fn type_bool(&self) -> Self::Type {
57 self.type_i8()
58 }
59
60 fn type_i8p(&self) -> Self::Type {
61 self.type_ptr_to(self.type_i8())
62 }
63
64 fn type_int(&self) -> Self::Type {
65 match &self.sess().target.target.target_c_int_width[..] {
66 "16" => self.type_i16(),
67 "32" => self.type_i32(),
68 "64" => self.type_i64(),
69 width => bug!("Unsupported target_c_int_width: {}", width),
70 }
71 }
72
73 fn type_int_from_ty(&self, t: ast::IntTy) -> Self::Type {
74 match t {
75 ast::IntTy::Isize => self.type_isize(),
76 ast::IntTy::I8 => self.type_i8(),
77 ast::IntTy::I16 => self.type_i16(),
78 ast::IntTy::I32 => self.type_i32(),
79 ast::IntTy::I64 => self.type_i64(),
80 ast::IntTy::I128 => self.type_i128(),
81 }
82 }
83
84 fn type_uint_from_ty(&self, t: ast::UintTy) -> Self::Type {
85 match t {
86 ast::UintTy::Usize => self.type_isize(),
87 ast::UintTy::U8 => self.type_i8(),
88 ast::UintTy::U16 => self.type_i16(),
89 ast::UintTy::U32 => self.type_i32(),
90 ast::UintTy::U64 => self.type_i64(),
91 ast::UintTy::U128 => self.type_i128(),
92 }
93 }
94
95 fn type_float_from_ty(&self, t: ast::FloatTy) -> Self::Type {
96 match t {
97 ast::FloatTy::F32 => self.type_f32(),
98 ast::FloatTy::F64 => self.type_f64(),
99 }
100 }
101
102 fn type_from_integer(&self, i: layout::Integer) -> Self::Type {
103 use rustc::ty::layout::Integer::*;
104 match i {
105 I8 => self.type_i8(),
106 I16 => self.type_i16(),
107 I32 => self.type_i32(),
108 I64 => self.type_i64(),
109 I128 => self.type_i128(),
110 }
111 }
112
113 fn type_pointee_for_align(&self, align: Align) -> Self::Type {
114 // FIXME(eddyb) We could find a better approximation if ity.align < align.
115 let ity = layout::Integer::approximate_align(self, align);
116 self.type_from_integer(ity)
117 }
118
119 /// Return a LLVM type that has at most the required alignment,
120 /// and exactly the required size, as a best-effort padding array.
121 fn type_padding_filler(&self, size: Size, align: Align) -> Self::Type {
122 let unit = layout::Integer::approximate_align(self, align);
123 let size = size.bytes();
124 let unit_size = unit.size().bytes();
125 assert_eq!(size % unit_size, 0);
126 self.type_array(self.type_from_integer(unit), size / unit_size)
127 }
128
129 fn type_needs_drop(&self, ty: Ty<'tcx>) -> bool {
130 common::type_needs_drop(self.tcx(), ty)
131 }
132
133 fn type_is_sized(&self, ty: Ty<'tcx>) -> bool {
134 common::type_is_sized(self.tcx(), ty)
135 }
136
137 fn type_is_freeze(&self, ty: Ty<'tcx>) -> bool {
138 common::type_is_freeze(self.tcx(), ty)
139 }
140
141 fn type_has_metadata(&self, ty: Ty<'tcx>) -> bool {
142 use syntax_pos::DUMMY_SP;
143 if ty.is_sized(self.tcx().at(DUMMY_SP), ty::ParamEnv::reveal_all()) {
144 return false;
145 }
146
147 let tail = self.tcx().struct_tail(ty);
148 match tail.sty {
149 ty::Foreign(..) => false,
150 ty::Str | ty::Slice(..) | ty::Dynamic(..) => true,
151 _ => bug!("unexpected unsized tail: {:?}", tail.sty),
152 }
153 }
154 }
155
156 impl<T> DerivedTypeMethods<'tcx> for T where Self: BaseTypeMethods<'tcx> + MiscMethods<'tcx> {}
157
158 pub trait LayoutTypeMethods<'tcx>: Backend<'tcx> {
159 fn backend_type(&self, layout: TyLayout<'tcx>) -> Self::Type;
160 fn cast_backend_type(&self, ty: &CastTarget) -> Self::Type;
161 fn fn_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> Self::Type;
162 fn fn_ptr_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> Self::Type;
163 fn reg_backend_type(&self, ty: &Reg) -> Self::Type;
164 fn immediate_backend_type(&self, layout: TyLayout<'tcx>) -> Self::Type;
165 fn is_backend_immediate(&self, layout: TyLayout<'tcx>) -> bool;
166 fn is_backend_scalar_pair(&self, layout: TyLayout<'tcx>) -> bool;
167 fn backend_field_index(&self, layout: TyLayout<'tcx>, index: usize) -> u64;
168 fn scalar_pair_element_backend_type<'a>(
169 &self,
170 layout: TyLayout<'tcx>,
171 index: usize,
172 immediate: bool,
173 ) -> Self::Type;
174 }
175
176 pub trait ArgTypeMethods<'tcx>: HasCodegen<'tcx> {
177 fn store_fn_arg(
178 &mut self,
179 ty: &ArgType<'tcx, Ty<'tcx>>,
180 idx: &mut usize,
181 dst: PlaceRef<'tcx, Self::Value>,
182 );
183 fn store_arg_ty(
184 &mut self,
185 ty: &ArgType<'tcx, Ty<'tcx>>,
186 val: Self::Value,
187 dst: PlaceRef<'tcx, Self::Value>,
188 );
189 fn memory_ty(&self, ty: &ArgType<'tcx, Ty<'tcx>>) -> Self::Type;
190 }
191
192 pub trait TypeMethods<'tcx>: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {}
193
194 impl<T> TypeMethods<'tcx> for T where Self: DerivedTypeMethods<'tcx> + LayoutTypeMethods<'tcx> {}