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, ValueRef}
;
15 use llvm
::{Float, Double, X86_FP80, PPC_FP128, FP128}
;
17 use trans
::context
::CrateContext
;
18 use util
::nodemap
::FnvHashMap
;
22 use std
::ffi
::CString
;
25 use std
::cell
::RefCell
;
26 use std
::iter
::repeat
;
30 #[derive(Clone, Copy, PartialEq, Debug)]
37 ($e
:expr
) => ( Type
::from_ref(unsafe { $e }
))
40 /// Wrapper for LLVM TypeRef
43 pub fn from_ref(r
: TypeRef
) -> Type
{
49 #[inline(always)] // So it doesn't kill --opt-level=0 builds of the compiler
50 pub fn to_ref(&self) -> TypeRef
{
54 pub fn void(ccx
: &CrateContext
) -> Type
{
55 ty
!(llvm
::LLVMVoidTypeInContext(ccx
.llcx()))
58 pub fn nil(ccx
: &CrateContext
) -> Type
{
59 Type
::empty_struct(ccx
)
62 pub fn metadata(ccx
: &CrateContext
) -> Type
{
63 ty
!(llvm
::LLVMMetadataTypeInContext(ccx
.llcx()))
66 pub fn i1(ccx
: &CrateContext
) -> Type
{
67 ty
!(llvm
::LLVMInt1TypeInContext(ccx
.llcx()))
70 pub fn i8(ccx
: &CrateContext
) -> Type
{
71 ty
!(llvm
::LLVMInt8TypeInContext(ccx
.llcx()))
74 pub fn i16(ccx
: &CrateContext
) -> Type
{
75 ty
!(llvm
::LLVMInt16TypeInContext(ccx
.llcx()))
78 pub fn i32(ccx
: &CrateContext
) -> Type
{
79 ty
!(llvm
::LLVMInt32TypeInContext(ccx
.llcx()))
82 pub fn i64(ccx
: &CrateContext
) -> Type
{
83 ty
!(llvm
::LLVMInt64TypeInContext(ccx
.llcx()))
86 // Creates an integer type with the given number of bits, e.g. i24
87 pub fn ix(ccx
: &CrateContext
, num_bits
: u64) -> Type
{
88 ty
!(llvm
::LLVMIntTypeInContext(ccx
.llcx(), num_bits
as c_uint
))
91 pub fn f32(ccx
: &CrateContext
) -> Type
{
92 ty
!(llvm
::LLVMFloatTypeInContext(ccx
.llcx()))
95 pub fn f64(ccx
: &CrateContext
) -> Type
{
96 ty
!(llvm
::LLVMDoubleTypeInContext(ccx
.llcx()))
99 pub fn bool(ccx
: &CrateContext
) -> Type
{
103 pub fn char(ccx
: &CrateContext
) -> Type
{
107 pub fn i8p(ccx
: &CrateContext
) -> Type
{
108 Type
::i8(ccx
).ptr_to()
111 pub fn int(ccx
: &CrateContext
) -> Type
{
112 match &ccx
.tcx().sess
.target
.target
.target_pointer_width
[..] {
113 "32" => Type
::i32(ccx
),
114 "64" => Type
::i64(ccx
),
115 tws
=> panic
!("Unsupported target word size for int: {}", tws
),
119 pub fn int_from_ty(ccx
: &CrateContext
, t
: ast
::IntTy
) -> Type
{
121 ast
::TyIs
=> ccx
.int_type(),
122 ast
::TyI8
=> Type
::i8(ccx
),
123 ast
::TyI16
=> Type
::i16(ccx
),
124 ast
::TyI32
=> Type
::i32(ccx
),
125 ast
::TyI64
=> Type
::i64(ccx
)
129 pub fn uint_from_ty(ccx
: &CrateContext
, t
: ast
::UintTy
) -> Type
{
131 ast
::TyUs
=> ccx
.int_type(),
132 ast
::TyU8
=> Type
::i8(ccx
),
133 ast
::TyU16
=> Type
::i16(ccx
),
134 ast
::TyU32
=> Type
::i32(ccx
),
135 ast
::TyU64
=> Type
::i64(ccx
)
139 pub fn float_from_ty(ccx
: &CrateContext
, t
: ast
::FloatTy
) -> Type
{
141 ast
::TyF32
=> Type
::f32(ccx
),
142 ast
::TyF64
=> Type
::f64(ccx
),
146 pub fn func(args
: &[Type
], ret
: &Type
) -> Type
{
147 let vec
: &[TypeRef
] = unsafe { mem::transmute(args) }
;
148 ty
!(llvm
::LLVMFunctionType(ret
.to_ref(), vec
.as_ptr(),
149 args
.len() as c_uint
, False
))
152 pub fn variadic_func(args
: &[Type
], ret
: &Type
) -> Type
{
153 let vec
: &[TypeRef
] = unsafe { mem::transmute(args) }
;
154 ty
!(llvm
::LLVMFunctionType(ret
.to_ref(), vec
.as_ptr(),
155 args
.len() as c_uint
, True
))
158 pub fn struct_(ccx
: &CrateContext
, els
: &[Type
], packed
: bool
) -> Type
{
159 let els
: &[TypeRef
] = unsafe { mem::transmute(els) }
;
160 ty
!(llvm
::LLVMStructTypeInContext(ccx
.llcx(), els
.as_ptr(),
165 pub fn named_struct(ccx
: &CrateContext
, name
: &str) -> Type
{
166 let name
= CString
::new(name
).unwrap();
167 ty
!(llvm
::LLVMStructCreateNamed(ccx
.llcx(), name
.as_ptr()))
170 pub fn empty_struct(ccx
: &CrateContext
) -> Type
{
171 Type
::struct_(ccx
, &[], false)
174 pub fn glue_fn(ccx
: &CrateContext
, t
: Type
) -> Type
{
175 Type
::func(&[t
], &Type
::void(ccx
))
178 pub fn array(ty
: &Type
, len
: u64) -> Type
{
179 ty
!(llvm
::LLVMRustArrayType(ty
.to_ref(), len
))
182 pub fn vector(ty
: &Type
, len
: u64) -> Type
{
183 ty
!(llvm
::LLVMVectorType(ty
.to_ref(), len
as c_uint
))
186 pub fn vec(ccx
: &CrateContext
, ty
: &Type
) -> Type
{
188 &[Type
::array(ty
, 0), Type
::int(ccx
)],
192 pub fn opaque_vec(ccx
: &CrateContext
) -> Type
{
193 Type
::vec(ccx
, &Type
::i8(ccx
))
196 pub fn vtable_ptr(ccx
: &CrateContext
) -> Type
{
197 Type
::glue_fn(ccx
, Type
::i8p(ccx
)).ptr_to().ptr_to()
200 pub fn kind(&self) -> TypeKind
{
202 llvm
::LLVMGetTypeKind(self.to_ref())
206 pub fn set_struct_body(&mut self, els
: &[Type
], packed
: bool
) {
208 let vec
: &[TypeRef
] = mem
::transmute(els
);
209 llvm
::LLVMStructSetBody(self.to_ref(), vec
.as_ptr(),
210 els
.len() as c_uint
, packed
as Bool
)
214 pub fn ptr_to(&self) -> Type
{
215 ty
!(llvm
::LLVMPointerType(self.to_ref(), 0))
218 pub fn is_aggregate(&self) -> bool
{
220 TypeKind
::Struct
| TypeKind
::Array
=> true,
225 pub fn is_packed(&self) -> bool
{
227 llvm
::LLVMIsPackedStruct(self.to_ref()) == True
231 pub fn element_type(&self) -> Type
{
233 Type
::from_ref(llvm
::LLVMGetElementType(self.to_ref()))
237 /// Return the number of elements in `self` if it is a LLVM vector type.
238 pub fn vector_length(&self) -> usize {
240 llvm
::LLVMGetVectorSize(self.to_ref()) as usize
244 pub fn array_length(&self) -> usize {
246 llvm
::LLVMGetArrayLength(self.to_ref()) as usize
250 pub fn field_types(&self) -> Vec
<Type
> {
252 let n_elts
= llvm
::LLVMCountStructElementTypes(self.to_ref()) as usize;
256 let mut elts
: Vec
<_
> = repeat(Type { rf: ptr::null_mut() }
).take(n_elts
).collect();
257 llvm
::LLVMGetStructElementTypes(self.to_ref(),
258 elts
.as_mut_ptr() as *mut TypeRef
);
263 pub fn return_type(&self) -> Type
{
264 ty
!(llvm
::LLVMGetReturnType(self.to_ref()))
267 pub fn func_params(&self) -> Vec
<Type
> {
269 let n_args
= llvm
::LLVMCountParamTypes(self.to_ref()) as usize;
270 let mut args
: Vec
<_
> = repeat(Type { rf: ptr::null_mut() }
).take(n_args
).collect();
271 llvm
::LLVMGetParamTypes(self.to_ref(),
272 args
.as_mut_ptr() as *mut TypeRef
);
277 pub fn float_width(&self) -> usize {
282 FP128
| PPC_FP128
=> 128,
283 _
=> panic
!("llvm_float_width called on a non-float type")
287 /// Retrieve the bit width of the integer type `self`.
288 pub fn int_width(&self) -> u64 {
290 llvm
::LLVMGetIntTypeWidth(self.to_ref()) as u64
296 /* Memory-managed object interface to type handles. */
298 pub struct TypeNames
{
299 named_types
: RefCell
<FnvHashMap
<String
, TypeRef
>>,
303 pub fn new() -> TypeNames
{
305 named_types
: RefCell
::new(FnvHashMap())
309 pub fn associate_type(&self, s
: &str, t
: &Type
) {
310 assert
!(self.named_types
.borrow_mut().insert(s
.to_string(),
311 t
.to_ref()).is_none());
314 pub fn find_type(&self, s
: &str) -> Option
<Type
> {
315 self.named_types
.borrow().get(s
).map(|x
| Type
::from_ref(*x
))
318 pub fn type_to_string(&self, ty
: Type
) -> String
{
319 llvm
::build_string(|s
| unsafe {
320 llvm
::LLVMWriteTypeToString(ty
.to_ref(), s
);
321 }).expect("non-UTF8 type description from LLVM")
324 pub fn types_to_str(&self, tys
: &[Type
]) -> String
{
325 let strs
: Vec
<String
> = tys
.iter().map(|t
| self.type_to_string(*t
)).collect();
326 format
!("[{}]", strs
.connect(","))
329 pub fn val_to_string(&self, val
: ValueRef
) -> String
{
330 llvm
::build_string(|s
| unsafe {
331 llvm
::LLVMWriteValueToString(val
, s
);
332 }).expect("nun-UTF8 value description from LLVM")