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::c_str::ToCStr;
24 use std::cell::RefCell;
25 use std::iter::repeat;
29 #[deriving(Clone, Copy, PartialEq, Show)]
36 ($e:expr) => ( Type::from_ref(unsafe { $e }))
39 /// Wrapper for LLVM TypeRef
42 pub fn from_ref(r: TypeRef) -> Type {
48 #[inline(always)] // So it doesn't kill --opt-level=0 builds of the compiler
49 pub fn to_ref(&self) -> TypeRef {
53 pub fn void(ccx: &CrateContext) -> Type {
54 ty!(llvm::LLVMVoidTypeInContext(ccx.llcx()))
57 pub fn nil(ccx: &CrateContext) -> Type {
58 Type::empty_struct(ccx)
61 pub fn metadata(ccx: &CrateContext) -> Type {
62 ty!(llvm::LLVMMetadataTypeInContext(ccx.llcx()))
65 pub fn i1(ccx: &CrateContext) -> Type {
66 ty!(llvm::LLVMInt1TypeInContext(ccx.llcx()))
69 pub fn i8(ccx: &CrateContext) -> Type {
70 ty!(llvm::LLVMInt8TypeInContext(ccx.llcx()))
73 pub fn i16(ccx: &CrateContext) -> Type {
74 ty!(llvm::LLVMInt16TypeInContext(ccx.llcx()))
77 pub fn i32(ccx: &CrateContext) -> Type {
78 ty!(llvm::LLVMInt32TypeInContext(ccx.llcx()))
81 pub fn i64(ccx: &CrateContext) -> Type {
82 ty!(llvm::LLVMInt64TypeInContext(ccx.llcx()))
85 pub fn f32(ccx: &CrateContext) -> Type {
86 ty!(llvm::LLVMFloatTypeInContext(ccx.llcx()))
89 pub fn f64(ccx: &CrateContext) -> Type {
90 ty!(llvm::LLVMDoubleTypeInContext(ccx.llcx()))
93 pub fn bool(ccx: &CrateContext) -> Type {
97 pub fn char(ccx: &CrateContext) -> Type {
101 pub fn i8p(ccx: &CrateContext) -> Type {
102 Type::i8(ccx).ptr_to()
105 pub fn int(ccx: &CrateContext) -> Type {
106 match ccx.tcx().sess.target.target.target_word_size[] {
107 "32" => Type::i32(ccx),
108 "64" => Type::i64(ccx),
109 tws => panic!("Unsupported target word size for int: {}", tws),
113 pub fn int_from_ty(ccx: &CrateContext, t: ast::IntTy) -> Type {
115 ast::TyI => ccx.int_type(),
116 ast::TyI8 => Type::i8(ccx),
117 ast::TyI16 => Type::i16(ccx),
118 ast::TyI32 => Type::i32(ccx),
119 ast::TyI64 => Type::i64(ccx)
123 pub fn uint_from_ty(ccx: &CrateContext, t: ast::UintTy) -> Type {
125 ast::TyU => ccx.int_type(),
126 ast::TyU8 => Type::i8(ccx),
127 ast::TyU16 => Type::i16(ccx),
128 ast::TyU32 => Type::i32(ccx),
129 ast::TyU64 => Type::i64(ccx)
133 pub fn float_from_ty(ccx: &CrateContext, t: ast::FloatTy) -> Type {
135 ast::TyF32 => Type::f32(ccx),
136 ast::TyF64 => Type::f64(ccx),
140 pub fn func(args: &[Type], ret: &Type) -> Type {
141 let vec : &[TypeRef] = unsafe { mem::transmute(args) };
142 ty!(llvm::LLVMFunctionType(ret.to_ref(), vec.as_ptr(),
143 args.len() as c_uint, False))
146 pub fn variadic_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, True))
152 pub fn struct_(ccx: &CrateContext, els: &[Type], packed: bool) -> Type {
153 let els : &[TypeRef] = unsafe { mem::transmute(els) };
154 ty!(llvm::LLVMStructTypeInContext(ccx.llcx(), els.as_ptr(),
159 pub fn named_struct(ccx: &CrateContext, name: &str) -> Type {
160 ty!(name.with_c_str(|s| llvm::LLVMStructCreateNamed(ccx.llcx(), s)))
163 pub fn empty_struct(ccx: &CrateContext) -> Type {
164 Type::struct_(ccx, &[], false)
167 pub fn vtable(ccx: &CrateContext) -> Type {
168 Type::array(&Type::i8p(ccx).ptr_to(), 1)
171 pub fn generic_glue_fn(cx: &CrateContext) -> Type {
172 match cx.tn().find_type("glue_fn") {
173 Some(ty) => return ty,
177 let ty = Type::glue_fn(cx, Type::i8p(cx));
178 cx.tn().associate_type("glue_fn", &ty);
183 pub fn glue_fn(ccx: &CrateContext, t: Type) -> Type {
184 Type::func(&[t], &Type::void(ccx))
187 pub fn tydesc(ccx: &CrateContext, str_slice_ty: Type) -> Type {
188 let mut tydesc = Type::named_struct(ccx, "tydesc");
189 let glue_fn_ty = Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to();
191 let int_ty = Type::int(ccx);
195 // std::unstable::intrinsics::TyDesc
197 let elems = [int_ty, // size
200 str_slice_ty]; // name
201 tydesc.set_struct_body(&elems, false);
206 pub fn array(ty: &Type, len: u64) -> Type {
207 ty!(llvm::LLVMRustArrayType(ty.to_ref(), len))
210 pub fn vector(ty: &Type, len: u64) -> Type {
211 ty!(llvm::LLVMVectorType(ty.to_ref(), len as c_uint))
214 pub fn vec(ccx: &CrateContext, ty: &Type) -> Type {
216 &[Type::array(ty, 0), Type::int(ccx)],
220 pub fn opaque_vec(ccx: &CrateContext) -> Type {
221 Type::vec(ccx, &Type::i8(ccx))
224 // The box pointed to by @T.
225 pub fn at_box(ccx: &CrateContext, ty: Type) -> Type {
226 Type::struct_(ccx, &[
227 ccx.int_type(), Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to(),
228 Type::i8p(ccx), Type::i8p(ccx), ty
232 pub fn vtable_ptr(ccx: &CrateContext) -> Type {
233 Type::glue_fn(ccx, Type::i8p(ccx)).ptr_to().ptr_to()
236 pub fn opaque_trait(ccx: &CrateContext) -> Type {
237 Type::struct_(ccx, &[Type::opaque_trait_data(ccx).ptr_to(), Type::vtable_ptr(ccx)], false)
240 pub fn opaque_trait_data(ccx: &CrateContext) -> Type {
244 pub fn kind(&self) -> TypeKind {
246 llvm::LLVMGetTypeKind(self.to_ref())
250 pub fn set_struct_body(&mut self, els: &[Type], packed: bool) {
252 let vec : &[TypeRef] = mem::transmute(els);
253 llvm::LLVMStructSetBody(self.to_ref(), vec.as_ptr(),
254 els.len() as c_uint, packed as Bool)
258 pub fn ptr_to(&self) -> Type {
259 ty!(llvm::LLVMPointerType(self.to_ref(), 0))
262 pub fn is_packed(&self) -> bool {
264 llvm::LLVMIsPackedStruct(self.to_ref()) == True
268 pub fn element_type(&self) -> Type {
270 Type::from_ref(llvm::LLVMGetElementType(self.to_ref()))
274 pub fn array_length(&self) -> uint {
276 llvm::LLVMGetArrayLength(self.to_ref()) as uint
280 pub fn field_types(&self) -> Vec<Type> {
282 let n_elts = llvm::LLVMCountStructElementTypes(self.to_ref()) as uint;
286 let mut elts: Vec<_> = repeat(Type { rf: 0 as TypeRef }).take(n_elts).collect();
287 llvm::LLVMGetStructElementTypes(self.to_ref(),
288 elts.as_mut_ptr() as *mut TypeRef);
293 pub fn return_type(&self) -> Type {
294 ty!(llvm::LLVMGetReturnType(self.to_ref()))
297 pub fn func_params(&self) -> Vec<Type> {
299 let n_args = llvm::LLVMCountParamTypes(self.to_ref()) as uint;
300 let mut args: Vec<_> = repeat(Type { rf: 0 as TypeRef }).take(n_args).collect();
301 llvm::LLVMGetParamTypes(self.to_ref(),
302 args.as_mut_ptr() as *mut TypeRef);
307 pub fn float_width(&self) -> uint {
312 FP128 | PPC_FP128 => 128,
313 _ => panic!("llvm_float_width called on a non-float type")
319 /* Memory-managed object interface to type handles. */
321 pub struct TypeNames {
322 named_types: RefCell<FnvHashMap<String, TypeRef>>,
326 pub fn new() -> TypeNames {
328 named_types: RefCell::new(FnvHashMap::new())
332 pub fn associate_type(&self, s: &str, t: &Type) {
333 assert!(self.named_types.borrow_mut().insert(s.to_string(),
334 t.to_ref()).is_none());
337 pub fn find_type(&self, s: &str) -> Option<Type> {
338 self.named_types.borrow().get(s).map(|x| Type::from_ref(*x))
341 pub fn type_to_string(&self, ty: Type) -> String {
342 llvm::build_string(|s| unsafe {
343 llvm::LLVMWriteTypeToString(ty.to_ref(), s);
344 }).expect("non-UTF8 type description from LLVM")
347 pub fn types_to_str(&self, tys: &[Type]) -> String {
348 let strs: Vec<String> = tys.iter().map(|t| self.type_to_string(*t)).collect();
349 format!("[{}]", strs.connect(","))
352 pub fn val_to_string(&self, val: ValueRef) -> String {
353 llvm::build_string(|s| unsafe {
354 llvm::LLVMWriteValueToString(val, s);
355 }).expect("nun-UTF8 value description from LLVM")