1 // Copyright 2013 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.
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.
11 #![allow(non_upper_case_globals)]
16 use llvm::{Bool, False, True, TypeKind};
18 use context::CodegenCx;
19 use value::{Value, ValueTrait};
22 use rustc::ty::layout::{self, Align, Size};
23 use rustc_data_structures::small_c_str::SmallCStr;
29 impl PartialEq for Type {
30 fn eq(&self, other: &Self) -> bool {
31 self as *const _ == other as *const _
35 impl fmt::Debug for Type {
36 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
37 f.write_str(&llvm::build_string(|s| unsafe {
38 llvm::LLVMRustWriteTypeToString(self, s);
39 }).expect("non-UTF8 type description from LLVM"))
44 pub fn void<Value : ?Sized>(
45 cx: &CodegenCx<'ll, '_, &'ll Value>
46 ) -> &'ll Type where Value : ValueTrait {
48 llvm::LLVMVoidTypeInContext(cx.llcx)
52 pub fn metadata<Value : ?Sized>(
53 cx: &CodegenCx<'ll, '_, &'ll Value>
54 ) -> &'ll Type where Value : ValueTrait {
56 llvm::LLVMRustMetadataTypeInContext(cx.llcx)
60 pub fn i1<Value : ?Sized>(
61 cx: &CodegenCx<'ll, '_, &'ll Value>
62 ) -> &'ll Type where Value : ValueTrait {
64 llvm::LLVMInt1TypeInContext(cx.llcx)
68 pub fn i8<Value : ?Sized>(
69 cx: &CodegenCx<'ll, '_, &'ll Value>
70 ) -> &'ll Type where Value : ValueTrait {
72 llvm::LLVMInt8TypeInContext(cx.llcx)
76 pub fn i8_llcx<Value : ?Sized>(llcx: &llvm::Context) -> &Type where Value : ValueTrait {
78 llvm::LLVMInt8TypeInContext(llcx)
82 pub fn i16<Value : ?Sized>(
83 cx: &CodegenCx<'ll, '_, &'ll Value>) -> &'ll Type where Value : ValueTrait {
86 llvm::LLVMInt16TypeInContext(cx.llcx)
90 pub fn i32<Value : ?Sized>(
91 cx: &CodegenCx<'ll, '_, &'ll Value>
92 ) -> &'ll Type where Value : ValueTrait {
94 llvm::LLVMInt32TypeInContext(cx.llcx)
98 pub fn i64<Value : ?Sized>(
99 cx: &CodegenCx<'ll, '_, &'ll Value>
100 ) -> &'ll Type where Value : ValueTrait {
102 llvm::LLVMInt64TypeInContext(cx.llcx)
106 pub fn i128<Value : ?Sized>(
107 cx: &CodegenCx<'ll, '_, &'ll Value>
108 ) -> &'ll Type where Value : ValueTrait {
110 llvm::LLVMIntTypeInContext(cx.llcx, 128)
114 // Creates an integer type with the given number of bits, e.g. i24
115 pub fn ix<Value : ?Sized>(
116 cx: &CodegenCx<'ll, '_, &'ll Value>,
118 ) -> &'ll Type where Value : ValueTrait {
120 llvm::LLVMIntTypeInContext(cx.llcx, num_bits as c_uint)
124 // Creates an integer type with the given number of bits, e.g. i24
125 pub fn ix_llcx<Value : ?Sized>(
126 llcx: &llvm::Context,
128 ) -> &Type where Value : ValueTrait {
130 llvm::LLVMIntTypeInContext(llcx, num_bits as c_uint)
134 pub fn f32<Value : ?Sized>(
135 cx: &CodegenCx<'ll, '_, &'ll Value>
136 ) -> &'ll Type where Value : ValueTrait {
138 llvm::LLVMFloatTypeInContext(cx.llcx)
142 pub fn f64<Value : ?Sized>(
143 cx: &CodegenCx<'ll, '_, &'ll Value>
144 ) -> &'ll Type where Value : ValueTrait {
146 llvm::LLVMDoubleTypeInContext(cx.llcx)
150 pub fn bool<Value : ?Sized>(
151 cx: &CodegenCx<'ll, '_, &'ll Value>
152 ) -> &'ll Type where Value : ValueTrait {
156 pub fn char<Value : ?Sized>(
157 cx: &CodegenCx<'ll, '_, &'ll Value>
158 ) -> &'ll Type where Value : ValueTrait {
162 pub fn i8p<Value : ?Sized>(
163 cx: &CodegenCx<'ll, '_, &'ll Value>
164 ) -> &'ll Type where Value : ValueTrait {
165 Type::i8(cx).ptr_to()
168 pub fn i8p_llcx<Value : ?Sized>(llcx: &llvm::Context) -> &Type where Value : ValueTrait {
169 Type::i8_llcx::<Value>(llcx).ptr_to()
172 pub fn isize<Value : ?Sized>(
173 cx: &CodegenCx<'ll, '_, &'ll Value>
174 ) -> &'ll Type where Value : ValueTrait {
178 pub fn c_int<Value : ?Sized>(
179 cx: &CodegenCx<'ll, '_, &'ll Value>
180 ) -> &'ll Type where Value : ValueTrait {
181 match &cx.tcx.sess.target.target.target_c_int_width[..] {
182 "16" => Type::i16(cx),
183 "32" => Type::i32(cx),
184 "64" => Type::i64(cx),
185 width => bug!("Unsupported target_c_int_width: {}", width),
189 pub fn int_from_ty<Value : ?Sized>(
190 cx: &CodegenCx<'ll, '_, &'ll Value>,
192 ) -> &'ll Type where Value : ValueTrait {
194 ast::IntTy::Isize => cx.isize_ty,
195 ast::IntTy::I8 => Type::i8(cx),
196 ast::IntTy::I16 => Type::i16(cx),
197 ast::IntTy::I32 => Type::i32(cx),
198 ast::IntTy::I64 => Type::i64(cx),
199 ast::IntTy::I128 => Type::i128(cx),
203 pub fn uint_from_ty<Value : ?Sized>(
204 cx: &CodegenCx<'ll, '_, &'ll Value>,
206 ) -> &'ll Type where Value : ValueTrait {
208 ast::UintTy::Usize => cx.isize_ty,
209 ast::UintTy::U8 => Type::i8(cx),
210 ast::UintTy::U16 => Type::i16(cx),
211 ast::UintTy::U32 => Type::i32(cx),
212 ast::UintTy::U64 => Type::i64(cx),
213 ast::UintTy::U128 => Type::i128(cx),
217 pub fn float_from_ty<Value : ?Sized>(
218 cx: &CodegenCx<'ll, '_, &'ll Value>,
220 ) -> &'ll Type where Value : ValueTrait {
222 ast::FloatTy::F32 => Type::f32(cx),
223 ast::FloatTy::F64 => Type::f64(cx),
227 pub fn func<Value : ?Sized>(
230 ) -> &'ll Type where Value : ValueTrait {
232 llvm::LLVMFunctionType(ret, args.as_ptr(),
233 args.len() as c_uint, False)
237 pub fn variadic_func<Value : ?Sized>(
240 ) -> &'ll Type where Value : ValueTrait {
242 llvm::LLVMFunctionType(ret, args.as_ptr(),
243 args.len() as c_uint, True)
247 pub fn struct_<Value : ?Sized>(
248 cx: &CodegenCx<'ll, '_, &'ll Value>,
251 ) -> &'ll Type where Value : ValueTrait {
253 llvm::LLVMStructTypeInContext(cx.llcx, els.as_ptr(),
259 pub fn named_struct(cx: &CodegenCx<'ll, '_>, name: &str) -> &'ll Type {
260 let name = SmallCStr::new(name);
262 llvm::LLVMStructCreateNamed(cx.llcx, name.as_ptr())
267 pub fn array<Value : ?Sized>(ty: &Type, len: u64) -> &Type where Value : ValueTrait {
269 llvm::LLVMRustArrayType(ty, len)
273 pub fn vector<Value : ?Sized>(ty: &Type, len: u64) -> &Type where Value : ValueTrait {
275 llvm::LLVMVectorType(ty, len as c_uint)
279 pub fn kind(&self) -> TypeKind {
281 llvm::LLVMRustGetTypeKind(self)
285 pub fn set_struct_body(&'ll self, els: &[&'ll Type], packed: bool) {
287 llvm::LLVMStructSetBody(self, els.as_ptr(),
288 els.len() as c_uint, packed as Bool)
292 pub fn ptr_to(&self) -> &Type {
293 assert_ne!(self.kind(), TypeKind::Function,
294 "don't call ptr_to on function types, use ptr_to_llvm_type on FnType instead");
296 llvm::LLVMPointerType(self, 0)
300 pub fn element_type(&self) -> &Type {
302 llvm::LLVMGetElementType(self)
306 /// Return the number of elements in `self` if it is a LLVM vector type.
307 pub fn vector_length(&self) -> usize {
309 llvm::LLVMGetVectorSize(self) as usize
313 pub fn func_params(&self) -> Vec<&Type> {
315 let n_args = llvm::LLVMCountParamTypes(self) as usize;
316 let mut args = Vec::with_capacity(n_args);
317 llvm::LLVMGetParamTypes(self, args.as_mut_ptr());
318 args.set_len(n_args);
323 pub fn float_width(&self) -> usize {
325 TypeKind::Float => 32,
326 TypeKind::Double => 64,
327 TypeKind::X86_FP80 => 80,
328 TypeKind::FP128 | TypeKind::PPC_FP128 => 128,
329 _ => bug!("llvm_float_width called on a non-float type")
333 /// Retrieve the bit width of the integer type `self`.
334 pub fn int_width(&self) -> u64 {
336 llvm::LLVMGetIntTypeWidth(self) as u64
340 pub fn from_integer(cx: &CodegenCx<'ll, '_>, i: layout::Integer) -> &'ll Type {
341 use rustc::ty::layout::Integer::*;
344 I16 => Type::i16(cx),
345 I32 => Type::i32(cx),
346 I64 => Type::i64(cx),
347 I128 => Type::i128(cx),
351 /// Return a LLVM type that has at most the required alignment,
352 /// as a conservative approximation for unknown pointee types.
353 pub fn pointee_for_abi_align(cx: &CodegenCx<'ll, '_>, align: Align) -> &'ll Type {
354 // FIXME(eddyb) We could find a better approximation if ity.align < align.
355 let ity = layout::Integer::approximate_abi_align(cx, align);
356 Type::from_integer(cx, ity)
359 /// Return a LLVM type that has at most the required alignment,
360 /// and exactly the required size, as a best-effort padding array.
361 pub fn padding_filler(cx: &CodegenCx<'ll, '_>, size: Size, align: Align) -> &'ll Type {
362 let unit = layout::Integer::approximate_abi_align(cx, align);
363 let size = size.bytes();
364 let unit_size = unit.size().bytes();
365 assert_eq!(size % unit_size, 0);
366 Type::array::<Value>(Type::from_integer(cx, unit), size / unit_size)
369 pub fn x86_mmx(cx: &CodegenCx<'ll, '_>) -> &'ll Type {
371 llvm::LLVMX86MMXTypeInContext(cx.llcx)