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