]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/type_.rs
Auto merge of #56462 - Zoxc:query-macro, r=oli-obk
[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, FnTypeExt};
14 use rustc::util::nodemap::FxHashMap;
15 use rustc::ty::Ty;
16 use rustc::ty::layout::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::cell::RefCell;
23 use std::ptr;
24
25 use libc::c_uint;
26
27 impl PartialEq for Type {
28     fn eq(&self, other: &Self) -> bool {
29         ptr::eq(self, other)
30     }
31 }
32
33 impl fmt::Debug for Type {
34     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
35         f.write_str(&llvm::build_string(|s| unsafe {
36             llvm::LLVMRustWriteTypeToString(self, s);
37         }).expect("non-UTF8 type description from LLVM"))
38     }
39 }
40
41 impl CodegenCx<'ll, 'tcx> {
42     crate fn type_named_struct(&self, name: &str) -> &'ll Type {
43         let name = SmallCStr::new(name);
44         unsafe {
45             llvm::LLVMStructCreateNamed(self.llcx, name.as_ptr())
46         }
47     }
48
49     crate fn set_struct_body(&self, ty: &'ll Type, els: &[&'ll Type], packed: bool) {
50         unsafe {
51             llvm::LLVMStructSetBody(ty, els.as_ptr(),
52                                     els.len() as c_uint, packed as Bool)
53         }
54     }
55 }
56
57 impl BaseTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
58     fn type_void(&self) -> &'ll Type {
59         unsafe {
60             llvm::LLVMVoidTypeInContext(self.llcx)
61         }
62     }
63
64     fn type_metadata(&self) -> &'ll Type {
65         unsafe {
66             llvm::LLVMRustMetadataTypeInContext(self.llcx)
67         }
68     }
69
70     fn type_i1(&self) -> &'ll Type {
71         unsafe {
72             llvm::LLVMInt1TypeInContext(self.llcx)
73         }
74     }
75
76     fn type_i8(&self) -> &'ll Type {
77         unsafe {
78             llvm::LLVMInt8TypeInContext(self.llcx)
79         }
80     }
81
82
83     fn type_i16(&self) -> &'ll Type {
84         unsafe {
85             llvm::LLVMInt16TypeInContext(self.llcx)
86         }
87     }
88
89     fn type_i32(&self) -> &'ll Type {
90         unsafe {
91             llvm::LLVMInt32TypeInContext(self.llcx)
92         }
93     }
94
95     fn type_i64(&self) -> &'ll Type {
96         unsafe {
97             llvm::LLVMInt64TypeInContext(self.llcx)
98         }
99     }
100
101     fn type_i128(&self) -> &'ll Type {
102         unsafe {
103             llvm::LLVMIntTypeInContext(self.llcx, 128)
104         }
105     }
106
107     fn type_ix(&self, num_bits: u64) -> &'ll Type {
108         unsafe {
109             llvm::LLVMIntTypeInContext(self.llcx, num_bits as c_uint)
110         }
111     }
112
113     fn type_isize(&self) -> &'ll Type {
114         self.isize_ty
115     }
116
117     fn type_f32(&self) -> &'ll Type {
118         unsafe {
119             llvm::LLVMFloatTypeInContext(self.llcx)
120         }
121     }
122
123     fn type_f64(&self) -> &'ll Type {
124         unsafe {
125             llvm::LLVMDoubleTypeInContext(self.llcx)
126         }
127     }
128
129     fn type_x86_mmx(&self) -> &'ll Type {
130         unsafe {
131             llvm::LLVMX86MMXTypeInContext(self.llcx)
132         }
133     }
134
135     fn type_func(
136         &self,
137         args: &[&'ll Type],
138         ret: &'ll Type
139     ) -> &'ll Type {
140         unsafe {
141             llvm::LLVMFunctionType(ret, args.as_ptr(),
142                                    args.len() as c_uint, False)
143         }
144     }
145
146     fn type_variadic_func(
147         &self,
148         args: &[&'ll Type],
149         ret: &'ll Type
150     ) -> &'ll Type {
151         unsafe {
152             llvm::LLVMFunctionType(ret, args.as_ptr(),
153                                    args.len() as c_uint, True)
154         }
155     }
156
157     fn type_struct(
158         &self,
159         els: &[&'ll Type],
160         packed: bool
161     ) -> &'ll Type {
162         unsafe {
163             llvm::LLVMStructTypeInContext(self.llcx, els.as_ptr(),
164                                           els.len() as c_uint,
165                                           packed as Bool)
166         }
167     }
168
169
170     fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type {
171         unsafe {
172             llvm::LLVMRustArrayType(ty, len)
173         }
174     }
175
176     fn type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type {
177         unsafe {
178             llvm::LLVMVectorType(ty, len as c_uint)
179         }
180     }
181
182     fn type_kind(&self, ty: &'ll Type) -> TypeKind {
183         unsafe {
184             llvm::LLVMRustGetTypeKind(ty).to_generic()
185         }
186     }
187
188     fn type_ptr_to(&self, ty: &'ll Type) -> &'ll Type {
189         assert_ne!(self.type_kind(ty), TypeKind::Function,
190                    "don't call ptr_to on function types, use ptr_to_llvm_type on FnType instead");
191         ty.ptr_to()
192     }
193
194     fn element_type(&self, ty: &'ll Type) -> &'ll Type {
195         unsafe {
196             llvm::LLVMGetElementType(ty)
197         }
198     }
199
200     fn vector_length(&self, ty: &'ll Type) -> usize {
201         unsafe {
202             llvm::LLVMGetVectorSize(ty) as usize
203         }
204     }
205
206     fn func_params_types(&self, ty: &'ll Type) -> Vec<&'ll Type> {
207         unsafe {
208             let n_args = llvm::LLVMCountParamTypes(ty) as usize;
209             let mut args = Vec::with_capacity(n_args);
210             llvm::LLVMGetParamTypes(ty, args.as_mut_ptr());
211             args.set_len(n_args);
212             args
213         }
214     }
215
216     fn float_width(&self, ty: &'ll Type) -> usize {
217         match self.type_kind(ty) {
218             TypeKind::Float => 32,
219             TypeKind::Double => 64,
220             TypeKind::X86_FP80 => 80,
221             TypeKind::FP128 | TypeKind::PPC_FP128 => 128,
222             _ => bug!("llvm_float_width called on a non-float type")
223         }
224     }
225
226     fn int_width(&self, ty: &'ll Type) -> u64 {
227         unsafe {
228             llvm::LLVMGetIntTypeWidth(ty) as u64
229         }
230     }
231
232     fn val_ty(&self, v: &'ll Value) -> &'ll Type {
233         common::val_ty(v)
234     }
235
236     fn scalar_lltypes(&self) -> &RefCell<FxHashMap<Ty<'tcx>, Self::Type>> {
237         &self.scalar_lltypes
238     }
239 }
240
241 impl Type {
242     pub fn i8_llcx(llcx: &llvm::Context) -> &Type {
243         unsafe {
244             llvm::LLVMInt8TypeInContext(llcx)
245         }
246     }
247
248     // Creates an integer type with the given number of bits, e.g., i24
249     pub fn ix_llcx(
250         llcx: &llvm::Context,
251         num_bits: u64
252     ) -> &Type {
253         unsafe {
254             llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint)
255         }
256     }
257
258     pub fn i8p_llcx(llcx: &'ll llvm::Context) -> &'ll Type {
259         Type::i8_llcx(llcx).ptr_to()
260     }
261
262     fn ptr_to(&self) -> &Type {
263         unsafe {
264             llvm::LLVMPointerType(&self, 0)
265         }
266     }
267 }
268
269
270 impl LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
271     fn backend_type(&self, layout: TyLayout<'tcx>) -> &'ll Type {
272         layout.llvm_type(self)
273     }
274     fn immediate_backend_type(&self, layout: TyLayout<'tcx>) -> &'ll Type {
275         layout.immediate_llvm_type(self)
276     }
277     fn is_backend_immediate(&self, layout: TyLayout<'tcx>) -> bool {
278         layout.is_llvm_immediate()
279     }
280     fn is_backend_scalar_pair(&self, layout: TyLayout<'tcx>) -> bool {
281         layout.is_llvm_scalar_pair()
282     }
283     fn backend_field_index(&self, layout: TyLayout<'tcx>, index: usize) -> u64 {
284         layout.llvm_field_index(index)
285     }
286     fn scalar_pair_element_backend_type<'a>(
287         &self,
288         layout: TyLayout<'tcx>,
289         index: usize,
290         immediate: bool
291     ) -> &'ll Type {
292         layout.scalar_pair_element_llvm_type(self, index, immediate)
293     }
294     fn cast_backend_type(&self, ty: &CastTarget) -> &'ll Type {
295         ty.llvm_type(self)
296     }
297     fn fn_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> &'ll Type {
298         ty.llvm_type(self)
299     }
300     fn fn_ptr_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> &'ll Type {
301         ty.ptr_to_llvm_type(self)
302     }
303     fn reg_backend_type(&self, ty: &Reg) -> &'ll Type {
304         ty.llvm_type(self)
305     }
306 }