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
::{ContextRef, TypeRef, Bool, False, True, TypeKind}
;
15 use llvm
::{Float, Double, X86_FP80, PPC_FP128, FP128}
;
17 use context
::CrateContext
;
20 use rustc
::ty
::layout
;
22 use std
::ffi
::CString
;
29 #[derive(Clone, Copy, PartialEq)]
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.to_ref(), s
);
39 }).expect("non-UTF8 type description from LLVM"))
44 ($e
:expr
) => ( Type
::from_ref(unsafe { $e }
))
47 /// Wrapper for LLVM TypeRef
50 pub fn from_ref(r
: TypeRef
) -> Type
{
56 #[inline(always)] // So it doesn't kill --opt-level=0 builds of the compiler
57 pub fn to_ref(&self) -> TypeRef
{
61 pub fn to_ref_slice(slice
: &[Type
]) -> &[TypeRef
] {
62 unsafe { mem::transmute(slice) }
65 pub fn void(ccx
: &CrateContext
) -> Type
{
66 ty
!(llvm
::LLVMVoidTypeInContext(ccx
.llcx()))
69 pub fn nil(ccx
: &CrateContext
) -> Type
{
70 Type
::empty_struct(ccx
)
73 pub fn metadata(ccx
: &CrateContext
) -> Type
{
74 ty
!(llvm
::LLVMRustMetadataTypeInContext(ccx
.llcx()))
77 pub fn i1(ccx
: &CrateContext
) -> Type
{
78 ty
!(llvm
::LLVMInt1TypeInContext(ccx
.llcx()))
81 pub fn i8(ccx
: &CrateContext
) -> Type
{
82 ty
!(llvm
::LLVMInt8TypeInContext(ccx
.llcx()))
85 pub fn i8_llcx(llcx
: ContextRef
) -> Type
{
86 ty
!(llvm
::LLVMInt8TypeInContext(llcx
))
89 pub fn i16(ccx
: &CrateContext
) -> Type
{
90 ty
!(llvm
::LLVMInt16TypeInContext(ccx
.llcx()))
93 pub fn i32(ccx
: &CrateContext
) -> Type
{
94 ty
!(llvm
::LLVMInt32TypeInContext(ccx
.llcx()))
97 pub fn i64(ccx
: &CrateContext
) -> Type
{
98 ty
!(llvm
::LLVMInt64TypeInContext(ccx
.llcx()))
101 pub fn i128(ccx
: &CrateContext
) -> Type
{
102 ty
!(llvm
::LLVMIntTypeInContext(ccx
.llcx(), 128))
105 // Creates an integer type with the given number of bits, e.g. i24
106 pub fn ix(ccx
: &CrateContext
, num_bits
: u64) -> Type
{
107 ty
!(llvm
::LLVMIntTypeInContext(ccx
.llcx(), num_bits
as c_uint
))
110 pub fn f32(ccx
: &CrateContext
) -> Type
{
111 ty
!(llvm
::LLVMFloatTypeInContext(ccx
.llcx()))
114 pub fn f64(ccx
: &CrateContext
) -> Type
{
115 ty
!(llvm
::LLVMDoubleTypeInContext(ccx
.llcx()))
118 pub fn bool(ccx
: &CrateContext
) -> Type
{
122 pub fn char(ccx
: &CrateContext
) -> Type
{
126 pub fn i8p(ccx
: &CrateContext
) -> Type
{
127 Type
::i8(ccx
).ptr_to()
130 pub fn i8p_llcx(llcx
: ContextRef
) -> Type
{
131 Type
::i8_llcx(llcx
).ptr_to()
134 pub fn isize(ccx
: &CrateContext
) -> Type
{
135 match &ccx
.tcx().sess
.target
.target
.target_pointer_width
[..] {
136 "16" => Type
::i16(ccx
),
137 "32" => Type
::i32(ccx
),
138 "64" => Type
::i64(ccx
),
139 tws
=> bug
!("Unsupported target word size for int: {}", tws
),
143 pub fn c_int(ccx
: &CrateContext
) -> Type
{
144 match &ccx
.tcx().sess
.target
.target
.target_c_int_width
[..] {
145 "16" => Type
::i16(ccx
),
146 "32" => Type
::i32(ccx
),
147 "64" => Type
::i64(ccx
),
148 width
=> bug
!("Unsupported target_c_int_width: {}", width
),
152 pub fn int_from_ty(ccx
: &CrateContext
, t
: ast
::IntTy
) -> Type
{
154 ast
::IntTy
::Is
=> ccx
.isize_ty(),
155 ast
::IntTy
::I8
=> Type
::i8(ccx
),
156 ast
::IntTy
::I16
=> Type
::i16(ccx
),
157 ast
::IntTy
::I32
=> Type
::i32(ccx
),
158 ast
::IntTy
::I64
=> Type
::i64(ccx
),
159 ast
::IntTy
::I128
=> Type
::i128(ccx
),
163 pub fn uint_from_ty(ccx
: &CrateContext
, t
: ast
::UintTy
) -> Type
{
165 ast
::UintTy
::Us
=> ccx
.isize_ty(),
166 ast
::UintTy
::U8
=> Type
::i8(ccx
),
167 ast
::UintTy
::U16
=> Type
::i16(ccx
),
168 ast
::UintTy
::U32
=> Type
::i32(ccx
),
169 ast
::UintTy
::U64
=> Type
::i64(ccx
),
170 ast
::UintTy
::U128
=> Type
::i128(ccx
),
174 pub fn float_from_ty(ccx
: &CrateContext
, t
: ast
::FloatTy
) -> Type
{
176 ast
::FloatTy
::F32
=> Type
::f32(ccx
),
177 ast
::FloatTy
::F64
=> Type
::f64(ccx
),
181 pub fn func(args
: &[Type
], ret
: &Type
) -> Type
{
182 let slice
: &[TypeRef
] = Type
::to_ref_slice(args
);
183 ty
!(llvm
::LLVMFunctionType(ret
.to_ref(), slice
.as_ptr(),
184 args
.len() as c_uint
, False
))
187 pub fn variadic_func(args
: &[Type
], ret
: &Type
) -> Type
{
188 let slice
: &[TypeRef
] = Type
::to_ref_slice(args
);
189 ty
!(llvm
::LLVMFunctionType(ret
.to_ref(), slice
.as_ptr(),
190 args
.len() as c_uint
, True
))
193 pub fn struct_(ccx
: &CrateContext
, els
: &[Type
], packed
: bool
) -> Type
{
194 let els
: &[TypeRef
] = Type
::to_ref_slice(els
);
195 ty
!(llvm
::LLVMStructTypeInContext(ccx
.llcx(), els
.as_ptr(),
200 pub fn named_struct(ccx
: &CrateContext
, name
: &str) -> Type
{
201 let name
= CString
::new(name
).unwrap();
202 ty
!(llvm
::LLVMStructCreateNamed(ccx
.llcx(), name
.as_ptr()))
205 pub fn empty_struct(ccx
: &CrateContext
) -> Type
{
206 Type
::struct_(ccx
, &[], false)
209 pub fn array(ty
: &Type
, len
: u64) -> Type
{
210 ty
!(llvm
::LLVMRustArrayType(ty
.to_ref(), len
))
213 pub fn vector(ty
: &Type
, len
: u64) -> Type
{
214 ty
!(llvm
::LLVMVectorType(ty
.to_ref(), len
as c_uint
))
217 pub fn vec(ccx
: &CrateContext
, ty
: &Type
) -> Type
{
219 &[Type
::array(ty
, 0), Type
::isize(ccx
)],
223 pub fn opaque_vec(ccx
: &CrateContext
) -> Type
{
224 Type
::vec(ccx
, &Type
::i8(ccx
))
227 pub fn vtable_ptr(ccx
: &CrateContext
) -> Type
{
228 Type
::func(&[Type
::i8p(ccx
)], &Type
::void(ccx
)).ptr_to().ptr_to()
231 pub fn kind(&self) -> TypeKind
{
233 llvm
::LLVMRustGetTypeKind(self.to_ref())
237 pub fn set_struct_body(&mut self, els
: &[Type
], packed
: bool
) {
238 let slice
: &[TypeRef
] = Type
::to_ref_slice(els
);
240 llvm
::LLVMStructSetBody(self.to_ref(), slice
.as_ptr(),
241 els
.len() as c_uint
, packed
as Bool
)
245 pub fn ptr_to(&self) -> Type
{
246 ty
!(llvm
::LLVMPointerType(self.to_ref(), 0))
249 pub fn element_type(&self) -> Type
{
251 Type
::from_ref(llvm
::LLVMGetElementType(self.to_ref()))
255 /// Return the number of elements in `self` if it is a LLVM vector type.
256 pub fn vector_length(&self) -> usize {
258 llvm
::LLVMGetVectorSize(self.to_ref()) as usize
262 pub fn field_types(&self) -> Vec
<Type
> {
264 let n_elts
= llvm
::LLVMCountStructElementTypes(self.to_ref()) as usize;
268 let mut elts
= vec
![Type { rf: ptr::null_mut() }
; n_elts
];
269 llvm
::LLVMGetStructElementTypes(self.to_ref(),
270 elts
.as_mut_ptr() as *mut TypeRef
);
275 pub fn func_params(&self) -> Vec
<Type
> {
277 let n_args
= llvm
::LLVMCountParamTypes(self.to_ref()) as usize;
278 let mut args
= vec
![Type { rf: ptr::null_mut() }
; n_args
];
279 llvm
::LLVMGetParamTypes(self.to_ref(),
280 args
.as_mut_ptr() as *mut TypeRef
);
285 pub fn float_width(&self) -> usize {
290 FP128
| PPC_FP128
=> 128,
291 _
=> bug
!("llvm_float_width called on a non-float type")
295 /// Retrieve the bit width of the integer type `self`.
296 pub fn int_width(&self) -> u64 {
298 llvm
::LLVMGetIntTypeWidth(self.to_ref()) as u64
302 pub fn from_integer(cx
: &CrateContext
, i
: layout
::Integer
) -> Type
{
303 use rustc
::ty
::layout
::Integer
::*;
307 I16
=> Type
::i16(cx
),
308 I32
=> Type
::i32(cx
),
309 I64
=> Type
::i64(cx
),
310 I128
=> Type
::i128(cx
),