]> git.lizzy.rs Git - rust.git/blob - src/librustc_codegen_llvm/type_.rs
Don't default on std crate when manipulating browser history
[rust.git] / src / librustc_codegen_llvm / type_.rs
1 #![allow(non_upper_case_globals)]
2
3 pub use llvm::Type;
4
5 use llvm;
6 use llvm::{Bool, False, True};
7 use context::CodegenCx;
8 use rustc_codegen_ssa::traits::*;
9 use value::Value;
10
11 use rustc::util::nodemap::FxHashMap;
12 use rustc::ty::Ty;
13 use rustc::ty::layout::TyLayout;
14 use rustc_target::abi::call::{CastTarget, FnType, Reg};
15 use rustc_data_structures::small_c_str::SmallCStr;
16 use common;
17 use rustc_codegen_ssa::common::TypeKind;
18 use type_of::LayoutLlvmExt;
19 use abi::{LlvmType, FnTypeExt};
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
86             llvm::LLVMInt16TypeInContext(self.llcx)
87         }
88     }
89
90     fn type_i32(&self) -> &'ll Type {
91         unsafe {
92             llvm::LLVMInt32TypeInContext(self.llcx)
93         }
94     }
95
96     fn type_i64(&self) -> &'ll Type {
97         unsafe {
98             llvm::LLVMInt64TypeInContext(self.llcx)
99         }
100     }
101
102     fn type_i128(&self) -> &'ll Type {
103         unsafe {
104             llvm::LLVMIntTypeInContext(self.llcx, 128)
105         }
106     }
107
108     fn type_ix(&self, num_bits: u64) -> &'ll Type {
109         unsafe {
110             llvm::LLVMIntTypeInContext(self.llcx, num_bits as c_uint)
111         }
112     }
113
114     fn type_isize(&self) -> &'ll Type {
115         self.isize_ty
116     }
117
118     fn type_f32(&self) -> &'ll Type {
119         unsafe {
120             llvm::LLVMFloatTypeInContext(self.llcx)
121         }
122     }
123
124     fn type_f64(&self) -> &'ll Type {
125         unsafe {
126             llvm::LLVMDoubleTypeInContext(self.llcx)
127         }
128     }
129
130     fn type_x86_mmx(&self) -> &'ll Type {
131         unsafe {
132             llvm::LLVMX86MMXTypeInContext(self.llcx)
133         }
134     }
135
136     fn type_func(
137         &self,
138         args: &[&'ll Type],
139         ret: &'ll Type
140     ) -> &'ll Type {
141         unsafe {
142             llvm::LLVMFunctionType(ret, args.as_ptr(),
143                                    args.len() as c_uint, False)
144         }
145     }
146
147     fn type_variadic_func(
148         &self,
149         args: &[&'ll Type],
150         ret: &'ll Type
151     ) -> &'ll Type {
152         unsafe {
153             llvm::LLVMFunctionType(ret, args.as_ptr(),
154                                    args.len() as c_uint, True)
155         }
156     }
157
158     fn type_struct(
159         &self,
160         els: &[&'ll Type],
161         packed: bool
162     ) -> &'ll Type {
163         unsafe {
164             llvm::LLVMStructTypeInContext(self.llcx, els.as_ptr(),
165                                           els.len() as c_uint,
166                                           packed as Bool)
167         }
168     }
169
170
171     fn type_array(&self, ty: &'ll Type, len: u64) -> &'ll Type {
172         unsafe {
173             llvm::LLVMRustArrayType(ty, len)
174         }
175     }
176
177     fn type_vector(&self, ty: &'ll Type, len: u64) -> &'ll Type {
178         unsafe {
179             llvm::LLVMVectorType(ty, len as c_uint)
180         }
181     }
182
183     fn type_kind(&self, ty: &'ll Type) -> TypeKind {
184         unsafe {
185             llvm::LLVMRustGetTypeKind(ty).to_generic()
186         }
187     }
188
189     fn type_ptr_to(&self, ty: &'ll Type) -> &'ll Type {
190         assert_ne!(self.type_kind(ty), TypeKind::Function,
191                    "don't call ptr_to on function types, use ptr_to_llvm_type on FnType instead");
192         ty.ptr_to()
193     }
194
195     fn element_type(&self, ty: &'ll Type) -> &'ll Type {
196         unsafe {
197             llvm::LLVMGetElementType(ty)
198         }
199     }
200
201     fn vector_length(&self, ty: &'ll Type) -> usize {
202         unsafe {
203             llvm::LLVMGetVectorSize(ty) as usize
204         }
205     }
206
207     fn func_params_types(&self, ty: &'ll Type) -> Vec<&'ll Type> {
208         unsafe {
209             let n_args = llvm::LLVMCountParamTypes(ty) as usize;
210             let mut args = Vec::with_capacity(n_args);
211             llvm::LLVMGetParamTypes(ty, args.as_mut_ptr());
212             args.set_len(n_args);
213             args
214         }
215     }
216
217     fn float_width(&self, ty: &'ll Type) -> usize {
218         match self.type_kind(ty) {
219             TypeKind::Float => 32,
220             TypeKind::Double => 64,
221             TypeKind::X86_FP80 => 80,
222             TypeKind::FP128 | TypeKind::PPC_FP128 => 128,
223             _ => bug!("llvm_float_width called on a non-float type")
224         }
225     }
226
227     fn int_width(&self, ty: &'ll Type) -> u64 {
228         unsafe {
229             llvm::LLVMGetIntTypeWidth(ty) as u64
230         }
231     }
232
233     fn val_ty(&self, v: &'ll Value) -> &'ll Type {
234         common::val_ty(v)
235     }
236
237     fn scalar_lltypes(&self) -> &RefCell<FxHashMap<Ty<'tcx>, Self::Type>> {
238         &self.scalar_lltypes
239     }
240 }
241
242 impl Type {
243     pub fn i8_llcx(llcx: &llvm::Context) -> &Type {
244         unsafe {
245             llvm::LLVMInt8TypeInContext(llcx)
246         }
247     }
248
249     // Creates an integer type with the given number of bits, e.g., i24
250     pub fn ix_llcx(
251         llcx: &llvm::Context,
252         num_bits: u64
253     ) -> &Type {
254         unsafe {
255             llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint)
256         }
257     }
258
259     pub fn i8p_llcx(llcx: &'ll llvm::Context) -> &'ll Type {
260         Type::i8_llcx(llcx).ptr_to()
261     }
262
263     fn ptr_to(&self) -> &Type {
264         unsafe {
265             llvm::LLVMPointerType(&self, 0)
266         }
267     }
268 }
269
270
271 impl LayoutTypeMethods<'tcx> for CodegenCx<'ll, 'tcx> {
272     fn backend_type(&self, layout: TyLayout<'tcx>) -> &'ll Type {
273         layout.llvm_type(self)
274     }
275     fn immediate_backend_type(&self, layout: TyLayout<'tcx>) -> &'ll Type {
276         layout.immediate_llvm_type(self)
277     }
278     fn is_backend_immediate(&self, layout: TyLayout<'tcx>) -> bool {
279         layout.is_llvm_immediate()
280     }
281     fn is_backend_scalar_pair(&self, layout: TyLayout<'tcx>) -> bool {
282         layout.is_llvm_scalar_pair()
283     }
284     fn backend_field_index(&self, layout: TyLayout<'tcx>, index: usize) -> u64 {
285         layout.llvm_field_index(index)
286     }
287     fn scalar_pair_element_backend_type<'a>(
288         &self,
289         layout: TyLayout<'tcx>,
290         index: usize,
291         immediate: bool
292     ) -> &'ll Type {
293         layout.scalar_pair_element_llvm_type(self, index, immediate)
294     }
295     fn cast_backend_type(&self, ty: &CastTarget) -> &'ll Type {
296         ty.llvm_type(self)
297     }
298     fn fn_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> &'ll Type {
299         ty.llvm_type(self)
300     }
301     fn fn_ptr_backend_type(&self, ty: &FnType<'tcx, Ty<'tcx>>) -> &'ll Type {
302         ty.ptr_to_llvm_type(self)
303     }
304     fn reg_backend_type(&self, ty: &Reg) -> &'ll Type {
305         ty.llvm_type(self)
306     }
307 }