]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/type_.rs
Rollup merge of #60766 - vorner:weak-into-raw, r=sfackler
[rust.git] / src / librustc_codegen_llvm / type_.rs
1 #![allow(non_upper_case_globals)]
2
3 pub use crate::llvm::Type;
4
5 use crate::llvm;
6 use crate::llvm::{Bool, False, True};
7 use crate::context::CodegenCx;
8 use crate::value::Value;
9 use rustc_codegen_ssa::traits::*;
10
11 use crate::common;
12 use crate::type_of::LayoutLlvmExt;
13 use crate::abi::{LlvmType, FnTypeLlvmExt};
14 use syntax::ast;
15 use rustc::ty::Ty;
16 use rustc::ty::layout::{self, Align, Size, TyLayout};
17 use rustc_target::abi::call::{CastTarget, FnType, Reg};
18 use rustc_data_structures::small_c_str::SmallCStr;
19 use rustc_codegen_ssa::common::TypeKind;
20
21 use std::fmt;
22 use std::ptr;
23
24 use libc::c_uint;
25
26 impl PartialEq for Type {
27     fn eq(&self, other: &Self) -> bool {
28         ptr::eq(self, other)
29     }
30 }
31
32 impl fmt::Debug for Type {
33     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
34         f.write_str(&llvm::build_string(|s| unsafe {
35             llvm::LLVMRustWriteTypeToString(self, s);
36         }).expect("non-UTF8 type description from LLVM"))
37     }
38 }
39
40 impl CodegenCx<'ll, 'tcx> {
41     crate fn type_named_struct(&self, name: &str) -> &'ll Type {
42         let name = SmallCStr::new(name);
43         unsafe {
44             llvm::LLVMStructCreateNamed(self.llcx, name.as_ptr())
45         }
46     }
47
48     crate fn set_struct_body(&self, ty: &'ll Type, els: &[&'ll Type], packed: bool) {
49         unsafe {
50             llvm::LLVMStructSetBody(ty, els.as_ptr(),
51                                     els.len() as c_uint, packed as Bool)
52         }
53     }
54
55     crate fn type_void(&self) -> &'ll Type {
56         unsafe {
57             llvm::LLVMVoidTypeInContext(self.llcx)
58         }
59     }
60
61     crate fn type_metadata(&self) -> &'ll Type {
62         unsafe {
63             llvm::LLVMRustMetadataTypeInContext(self.llcx)
64         }
65     }
66
67     ///x Creates an integer type with the given number of bits, e.g., i24
68     crate fn type_ix(&self, num_bits: u64) -> &'ll Type {
69         unsafe {
70             llvm::LLVMIntTypeInContext(self.llcx, num_bits as c_uint)
71         }
72     }
73
74     crate fn type_x86_mmx(&self) -> &'ll Type {
75         unsafe {
76             llvm::LLVMX86MMXTypeInContext(self.llcx)
77         }
78     }
79
80     crate fn type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type {
81         unsafe {
82             llvm::LLVMVectorType(ty, len as c_uint)
83         }
84     }
85
86     crate fn func_params_types(&self, ty: &'ll Type) -> Vec<&'ll Type> {
87         unsafe {
88             let n_args = llvm::LLVMCountParamTypes(ty) as usize;
89             let mut args = Vec::with_capacity(n_args);
90             llvm::LLVMGetParamTypes(ty, args.as_mut_ptr());
91             args.set_len(n_args);
92             args
93         }
94     }
95
96     crate fn type_bool(&self) -> &'ll Type {
97         self.type_i8()
98     }
99
100     crate fn type_int_from_ty(&self, t: ast::IntTy) -> &'ll Type {
101         match t {
102             ast::IntTy::Isize => self.type_isize(),
103             ast::IntTy::I8 => self.type_i8(),
104             ast::IntTy::I16 => self.type_i16(),
105             ast::IntTy::I32 => self.type_i32(),
106             ast::IntTy::I64 => self.type_i64(),
107             ast::IntTy::I128 => self.type_i128(),
108         }
109     }
110
111     crate fn type_uint_from_ty(&self, t: ast::UintTy) -> &'ll Type {
112         match t {
113             ast::UintTy::Usize => self.type_isize(),
114             ast::UintTy::U8 => self.type_i8(),
115             ast::UintTy::U16 => self.type_i16(),
116             ast::UintTy::U32 => self.type_i32(),
117             ast::UintTy::U64 => self.type_i64(),
118             ast::UintTy::U128 => self.type_i128(),
119         }
120     }
121
122     crate fn type_float_from_ty(&self, t: ast::FloatTy) -> &'ll Type {
123         match t {
124             ast::FloatTy::F32 => self.type_f32(),
125             ast::FloatTy::F64 => self.type_f64(),
126         }
127     }
128
129     crate fn type_pointee_for_align(&self, align: Align) -> &'ll Type {
130         // FIXME(eddyb) We could find a better approximation if ity.align < align.
131         let ity = layout::Integer::approximate_align(self, align);
132         self.type_from_integer(ity)
133     }
134
135     /// Return a LLVM type that has at most the required alignment,
136     /// and exactly the required size, as a best-effort padding array.
137     crate fn type_padding_filler(&self, size: Size, align: Align) -> &'ll Type {
138         let unit = layout::Integer::approximate_align(self, align);
139         let size = size.bytes();
140         let unit_size = unit.size().bytes();
141         assert_eq!(size % unit_size, 0);
142         self.type_array(self.type_from_integer(unit), size / unit_size)
143     }
144
145     crate fn type_variadic_func(
146         &self,
147         args: &[&'ll Type],
148         ret: &'ll Type
149     ) -> &'ll Type {
150         unsafe {
151             llvm::LLVMFunctionType(ret, args.as_ptr(),
152                                    args.len() as c_uint, True)
153         }
154     }
155
156     crate fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type {
157         unsafe {
158             llvm::LLVMRustArrayType(ty, len)
159         }
160     }
161 }
162
163 impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
164     fn type_i1(&self) -> &'ll Type {
165         unsafe {
166             llvm::LLVMInt1TypeInContext(self.llcx)
167         }
168     }
169
170     fn type_i8(&self) -> &'ll Type {
171         unsafe {
172             llvm::LLVMInt8TypeInContext(self.llcx)
173         }
174     }
175
176
177     fn type_i16(&self) -> &'ll Type {
178         unsafe {
179             llvm::LLVMInt16TypeInContext(self.llcx)
180         }
181     }
182
183     fn type_i32(&self) -> &'ll Type {
184         unsafe {
185             llvm::LLVMInt32TypeInContext(self.llcx)
186         }
187     }
188
189     fn type_i64(&self) -> &'ll Type {
190         unsafe {
191             llvm::LLVMInt64TypeInContext(self.llcx)
192         }
193     }
194
195     fn type_i128(&self) -> &'ll Type {
196         unsafe {
197             llvm::LLVMIntTypeInContext(self.llcx, 128)
198         }
199     }
200
201     fn type_isize(&self) -> &'ll Type {
202         self.isize_ty
203     }
204
205     fn type_f32(&self) -> &'ll Type {
206         unsafe {
207             llvm::LLVMFloatTypeInContext(self.llcx)
208         }
209     }
210
211     fn type_f64(&self) -> &'ll Type {
212         unsafe {
213             llvm::LLVMDoubleTypeInContext(self.llcx)
214         }
215     }
216
217     fn type_func(
218         &self,
219         args: &[&'ll Type],
220         ret: &'ll Type
221     ) -> &'ll Type {
222         unsafe {
223             llvm::LLVMFunctionType(ret, args.as_ptr(),
224                                    args.len() as c_uint, False)
225         }
226     }
227
228     fn type_struct(
229         &self,
230         els: &[&'ll Type],
231         packed: bool
232     ) -> &'ll Type {
233         unsafe {
234             llvm::LLVMStructTypeInContext(self.llcx, els.as_ptr(),
235                                           els.len() as c_uint,
236                                           packed as Bool)
237         }
238     }
239
240     fn type_kind(&self, ty: &'ll Type) -> TypeKind {
241         unsafe {
242             llvm::LLVMRustGetTypeKind(ty).to_generic()
243         }
244     }
245
246     fn type_ptr_to(&self, ty: &'ll Type) -> &'ll Type {
247         assert_ne!(self.type_kind(ty), TypeKind::Function,
248                    "don't call ptr_to on function types, use ptr_to_llvm_type on FnType instead");
249         ty.ptr_to()
250     }
251
252     fn element_type(&self, ty: &'ll Type) -> &'ll Type {
253         unsafe {
254             llvm::LLVMGetElementType(ty)
255         }
256     }
257
258     fn vector_length(&self, ty: &'ll Type) -> usize {
259         unsafe {
260             llvm::LLVMGetVectorSize(ty) as usize
261         }
262     }
263
264     fn float_width(&self, ty: &'ll Type) -> usize {
265         match self.type_kind(ty) {
266             TypeKind::Float => 32,
267             TypeKind::Double => 64,
268             TypeKind::X86_FP80 => 80,
269             TypeKind::FP128 | TypeKind::PPC_FP128 => 128,
270             _ => bug!("llvm_float_width called on a non-float type")
271         }
272     }
273
274     fn int_width(&self, ty: &'ll Type) -> u64 {
275         unsafe {
276             llvm::LLVMGetIntTypeWidth(ty) as u64
277         }
278     }
279
280     fn val_ty(&self, v: &'ll Value) -> &'ll Type {
281         common::val_ty(v)
282     }
283 }
284
285 impl Type {
286     pub fn i8_llcx(llcx: &llvm::Context) -> &Type {
287         unsafe {
288             llvm::LLVMInt8TypeInContext(llcx)
289         }
290     }
291
292     // Creates an integer type with the given number of bits, e.g., i24
293     pub fn ix_llcx(
294         llcx: &llvm::Context,
295         num_bits: u64
296     ) -> &Type {
297         unsafe {
298             llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint)
299         }
300     }
301
302     pub fn i8p_llcx(llcx: &'ll llvm::Context) -> &'ll Type {
303         Type::i8_llcx(llcx).ptr_to()
304     }
305
306     fn ptr_to(&self) -> &Type {
307         unsafe {
308             llvm::LLVMPointerType(&self, 0)
309         }
310     }
311 }
312
313
314 impl LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
315     fn backend_type(&self, layout: TyLayout<'tcx>) -> &'ll Type {
316         layout.llvm_type(self)
317     }
318     fn immediate_backend_type(&self, layout: TyLayout<'tcx>) -> &'ll Type {
319         layout.immediate_llvm_type(self)
320     }
321     fn is_backend_immediate(&self, layout: TyLayout<'tcx>) -> bool {
322         layout.is_llvm_immediate()
323     }
324     fn is_backend_scalar_pair(&self, layout: TyLayout<'tcx>) -> bool {
325         layout.is_llvm_scalar_pair()
326     }
327     fn backend_field_index(&self, layout: TyLayout<'tcx>, index: usize) -> u64 {
328         layout.llvm_field_index(index)
329     }
330     fn scalar_pair_element_backend_type<'a>(
331         &self,
332         layout: TyLayout<'tcx>,
333         index: usize,
334         immediate: bool
335     ) -> &'ll Type {
336         layout.scalar_pair_element_llvm_type(self, index, immediate)
337     }
338     fn cast_backend_type(&self, ty: &CastTarget) -> &'ll Type {
339         ty.llvm_type(self)
340     }
341     fn fn_ptr_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> &'ll Type {
342         ty.ptr_to_llvm_type(self)
343     }
344     fn reg_backend_type(&self, ty: &Reg) -> &'ll Type {
345         ty.llvm_type(self)
346     }
347 }