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)]
14 use llvm
::{TypeRef, Bool, False, True, TypeKind}
;
15 use llvm
::{Float, Double, X86_FP80, PPC_FP128, FP128}
;
17 use context
::CrateContext
;
18 use util
::nodemap
::FnvHashMap
;
22 use std
::ffi
::CString
;
26 use std
::cell
::RefCell
;
30 #[derive(Clone, Copy, PartialEq)]
36 impl fmt
::Debug
for Type
{
37 fn fmt(&self, f
: &mut fmt
::Formatter
) -> fmt
::Result
{
38 f
.write_str(&llvm
::build_string(|s
| unsafe {
39 llvm
::LLVMRustWriteTypeToString(self.to_ref(), s
);
40 }).expect("non-UTF8 type description from LLVM"))
45 ($e
:expr
) => ( Type
::from_ref(unsafe { $e }
))
48 /// Wrapper for LLVM TypeRef
51 pub fn from_ref(r
: TypeRef
) -> Type
{
57 #[inline(always)] // So it doesn't kill --opt-level=0 builds of the compiler
58 pub fn to_ref(&self) -> TypeRef
{
62 pub fn to_ref_slice(slice
: &[Type
]) -> &[TypeRef
] {
63 unsafe { mem::transmute(slice) }
66 pub fn void(ccx
: &CrateContext
) -> Type
{
67 ty
!(llvm
::LLVMVoidTypeInContext(ccx
.llcx()))
70 pub fn nil(ccx
: &CrateContext
) -> Type
{
71 Type
::empty_struct(ccx
)
74 pub fn metadata(ccx
: &CrateContext
) -> Type
{
75 ty
!(llvm
::LLVMRustMetadataTypeInContext(ccx
.llcx()))
78 pub fn i1(ccx
: &CrateContext
) -> Type
{
79 ty
!(llvm
::LLVMInt1TypeInContext(ccx
.llcx()))
82 pub fn i8(ccx
: &CrateContext
) -> Type
{
83 ty
!(llvm
::LLVMInt8TypeInContext(ccx
.llcx()))
86 pub fn i16(ccx
: &CrateContext
) -> Type
{
87 ty
!(llvm
::LLVMInt16TypeInContext(ccx
.llcx()))
90 pub fn i32(ccx
: &CrateContext
) -> Type
{
91 ty
!(llvm
::LLVMInt32TypeInContext(ccx
.llcx()))
94 pub fn i64(ccx
: &CrateContext
) -> Type
{
95 ty
!(llvm
::LLVMInt64TypeInContext(ccx
.llcx()))
98 // Creates an integer type with the given number of bits, e.g. i24
99 pub fn ix(ccx
: &CrateContext
, num_bits
: u64) -> Type
{
100 ty
!(llvm
::LLVMIntTypeInContext(ccx
.llcx(), num_bits
as c_uint
))
103 pub fn f32(ccx
: &CrateContext
) -> Type
{
104 ty
!(llvm
::LLVMFloatTypeInContext(ccx
.llcx()))
107 pub fn f64(ccx
: &CrateContext
) -> Type
{
108 ty
!(llvm
::LLVMDoubleTypeInContext(ccx
.llcx()))
111 pub fn bool(ccx
: &CrateContext
) -> Type
{
115 pub fn char(ccx
: &CrateContext
) -> Type
{
119 pub fn i8p(ccx
: &CrateContext
) -> Type
{
120 Type
::i8(ccx
).ptr_to()
123 pub fn int(ccx
: &CrateContext
) -> Type
{
124 match &ccx
.tcx().sess
.target
.target
.target_pointer_width
[..] {
125 "16" => Type
::i16(ccx
),
126 "32" => Type
::i32(ccx
),
127 "64" => Type
::i64(ccx
),
128 tws
=> bug
!("Unsupported target word size for int: {}", tws
),
132 pub fn int_from_ty(ccx
: &CrateContext
, t
: ast
::IntTy
) -> Type
{
134 ast
::IntTy
::Is
=> ccx
.int_type(),
135 ast
::IntTy
::I8
=> Type
::i8(ccx
),
136 ast
::IntTy
::I16
=> Type
::i16(ccx
),
137 ast
::IntTy
::I32
=> Type
::i32(ccx
),
138 ast
::IntTy
::I64
=> Type
::i64(ccx
)
142 pub fn uint_from_ty(ccx
: &CrateContext
, t
: ast
::UintTy
) -> Type
{
144 ast
::UintTy
::Us
=> ccx
.int_type(),
145 ast
::UintTy
::U8
=> Type
::i8(ccx
),
146 ast
::UintTy
::U16
=> Type
::i16(ccx
),
147 ast
::UintTy
::U32
=> Type
::i32(ccx
),
148 ast
::UintTy
::U64
=> Type
::i64(ccx
)
152 pub fn float_from_ty(ccx
: &CrateContext
, t
: ast
::FloatTy
) -> Type
{
154 ast
::FloatTy
::F32
=> Type
::f32(ccx
),
155 ast
::FloatTy
::F64
=> Type
::f64(ccx
),
159 pub fn func(args
: &[Type
], ret
: &Type
) -> Type
{
160 let slice
: &[TypeRef
] = Type
::to_ref_slice(args
);
161 ty
!(llvm
::LLVMFunctionType(ret
.to_ref(), slice
.as_ptr(),
162 args
.len() as c_uint
, False
))
165 pub fn variadic_func(args
: &[Type
], ret
: &Type
) -> Type
{
166 let slice
: &[TypeRef
] = Type
::to_ref_slice(args
);
167 ty
!(llvm
::LLVMFunctionType(ret
.to_ref(), slice
.as_ptr(),
168 args
.len() as c_uint
, True
))
171 pub fn struct_(ccx
: &CrateContext
, els
: &[Type
], packed
: bool
) -> Type
{
172 let els
: &[TypeRef
] = Type
::to_ref_slice(els
);
173 ty
!(llvm
::LLVMStructTypeInContext(ccx
.llcx(), els
.as_ptr(),
178 pub fn named_struct(ccx
: &CrateContext
, name
: &str) -> Type
{
179 let name
= CString
::new(name
).unwrap();
180 ty
!(llvm
::LLVMStructCreateNamed(ccx
.llcx(), name
.as_ptr()))
183 pub fn empty_struct(ccx
: &CrateContext
) -> Type
{
184 Type
::struct_(ccx
, &[], false)
187 pub fn array(ty
: &Type
, len
: u64) -> Type
{
188 ty
!(llvm
::LLVMRustArrayType(ty
.to_ref(), len
))
191 pub fn vector(ty
: &Type
, len
: u64) -> Type
{
192 ty
!(llvm
::LLVMVectorType(ty
.to_ref(), len
as c_uint
))
195 pub fn vec(ccx
: &CrateContext
, ty
: &Type
) -> Type
{
197 &[Type
::array(ty
, 0), Type
::int(ccx
)],
201 pub fn opaque_vec(ccx
: &CrateContext
) -> Type
{
202 Type
::vec(ccx
, &Type
::i8(ccx
))
205 pub fn vtable_ptr(ccx
: &CrateContext
) -> Type
{
206 Type
::func(&[Type
::i8p(ccx
)], &Type
::void(ccx
)).ptr_to().ptr_to()
209 pub fn kind(&self) -> TypeKind
{
211 llvm
::LLVMRustGetTypeKind(self.to_ref())
215 pub fn set_struct_body(&mut self, els
: &[Type
], packed
: bool
) {
216 let slice
: &[TypeRef
] = Type
::to_ref_slice(els
);
218 llvm
::LLVMStructSetBody(self.to_ref(), slice
.as_ptr(),
219 els
.len() as c_uint
, packed
as Bool
)
223 pub fn ptr_to(&self) -> Type
{
224 ty
!(llvm
::LLVMPointerType(self.to_ref(), 0))
227 pub fn is_aggregate(&self) -> bool
{
229 TypeKind
::Struct
| TypeKind
::Array
=> true,
234 pub fn is_packed(&self) -> bool
{
236 llvm
::LLVMIsPackedStruct(self.to_ref()) == True
240 pub fn element_type(&self) -> Type
{
242 Type
::from_ref(llvm
::LLVMGetElementType(self.to_ref()))
246 /// Return the number of elements in `self` if it is a LLVM vector type.
247 pub fn vector_length(&self) -> usize {
249 llvm
::LLVMGetVectorSize(self.to_ref()) as usize
253 pub fn array_length(&self) -> usize {
255 llvm
::LLVMGetArrayLength(self.to_ref()) as usize
259 pub fn field_types(&self) -> Vec
<Type
> {
261 let n_elts
= llvm
::LLVMCountStructElementTypes(self.to_ref()) as usize;
265 let mut elts
= vec
![Type { rf: ptr::null_mut() }
; n_elts
];
266 llvm
::LLVMGetStructElementTypes(self.to_ref(),
267 elts
.as_mut_ptr() as *mut TypeRef
);
272 pub fn return_type(&self) -> Type
{
273 ty
!(llvm
::LLVMGetReturnType(self.to_ref()))
276 pub fn func_params(&self) -> Vec
<Type
> {
278 let n_args
= llvm
::LLVMCountParamTypes(self.to_ref()) as usize;
279 let mut args
= vec
![Type { rf: ptr::null_mut() }
; n_args
];
280 llvm
::LLVMGetParamTypes(self.to_ref(),
281 args
.as_mut_ptr() as *mut TypeRef
);
286 pub fn float_width(&self) -> usize {
291 FP128
| PPC_FP128
=> 128,
292 _
=> bug
!("llvm_float_width called on a non-float type")
296 /// Retrieve the bit width of the integer type `self`.
297 pub fn int_width(&self) -> u64 {
299 llvm
::LLVMGetIntTypeWidth(self.to_ref()) as u64
304 /* Memory-managed object interface to type handles. */
306 pub struct TypeNames
{
307 named_types
: RefCell
<FnvHashMap
<String
, TypeRef
>>,
311 pub fn new() -> TypeNames
{
313 named_types
: RefCell
::new(FnvHashMap())
317 pub fn associate_type(&self, s
: &str, t
: &Type
) {
318 assert
!(self.named_types
.borrow_mut().insert(s
.to_string(),
319 t
.to_ref()).is_none());
322 pub fn find_type(&self, s
: &str) -> Option
<Type
> {
323 self.named_types
.borrow().get(s
).map(|x
| Type
::from_ref(*x
))