1 // Copyright 2012-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.
15 use rustc::ty::{self, Ty, TypeFoldable};
16 use rustc::ty::layout::LayoutTyper;
17 use trans_item::DefPathBasedNames;
22 pub fn fat_ptr_base_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
24 ty::TyRef(_, ty::TypeAndMut { ty: t, .. }) |
25 ty::TyRawPtr(ty::TypeAndMut { ty: t, .. }) if !ccx.shared().type_is_sized(t) => {
26 in_memory_type_of(ccx, t).ptr_to()
28 ty::TyAdt(def, _) if def.is_box() => {
29 in_memory_type_of(ccx, ty.boxed_ty()).ptr_to()
31 _ => bug!("expected fat ptr ty but got {:?}", ty)
35 pub fn unsized_info_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
36 let unsized_part = ccx.tcx().struct_tail(ty);
37 match unsized_part.sty {
38 ty::TyStr | ty::TyArray(..) | ty::TySlice(_) => {
39 Type::uint_from_ty(ccx, ast::UintTy::Us)
41 ty::TyDynamic(..) => Type::vtable_ptr(ccx),
42 _ => bug!("Unexpected tail in unsized_info_ty: {:?} for ty={:?}",
47 pub fn immediate_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
55 /// Get the LLVM type corresponding to a Rust type, i.e. `rustc::ty::Ty`.
56 /// This is the right LLVM type for an alloca containing a value of that type,
57 /// and the pointee of an Lvalue Datum (which is always a LLVM pointer).
58 /// For unsized types, the returned type is a fat pointer, thus the resulting
59 /// LLVM type for a `Trait` Lvalue is `{ i8*, void(i8*)** }*`, which is a double
60 /// indirection to the actual data, unlike a `i8` Lvalue, which is just `i8*`.
61 /// This is needed due to the treatment of immediate values, as a fat pointer
62 /// is too large for it to be placed in SSA value (by our rules).
63 /// For the raw type without far pointer indirection, see `in_memory_type_of`.
64 pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
65 let ty = if !cx.shared().type_is_sized(ty) {
66 cx.tcx().mk_imm_ptr(ty)
70 in_memory_type_of(cx, ty)
73 /// Get the LLVM type corresponding to a Rust type, i.e. `rustc::ty::Ty`.
74 /// This is the right LLVM type for a field/array element of that type,
75 /// and is the same as `type_of` for all Sized types.
76 /// Unsized types, however, are represented by a "minimal unit", e.g.
77 /// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this
78 /// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.
79 /// If the type is an unsized struct, the regular layout is generated,
80 /// with the inner-most trailing unsized field using the "minimal unit"
81 /// of that field's type - this is useful for taking the address of
82 /// that field and ensuring the struct has the right alignment.
83 /// For the LLVM type of a value as a whole, see `type_of`.
84 pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
86 if let Some(&llty) = cx.lltypes().borrow().get(&t) {
90 debug!("type_of {:?}", t);
92 assert!(!t.has_escaping_regions(), "{:?} has escaping regions", t);
94 // Replace any typedef'd types with their equivalent non-typedef
95 // type. This ensures that all LLVM nominal types that contain
96 // Rust types are defined as the same LLVM types. If we don't do
97 // this then, e.g. `Option<{myfield: bool}>` would be a different
98 // type than `Option<myrec>`.
99 let t_norm = cx.tcx().erase_regions(&t);
102 let llty = in_memory_type_of(cx, t_norm);
103 debug!("--> normalized {:?} to {:?} llty={:?}", t, t_norm, llty);
104 cx.lltypes().borrow_mut().insert(t, llty);
108 let ptr_ty = |ty: Ty<'tcx>| {
109 if !cx.shared().type_is_sized(ty) {
110 if let ty::TyStr = ty.sty {
111 // This means we get a nicer name in the output (str is always
115 let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
116 let info_ty = unsized_info_ty(cx, ty);
117 Type::struct_(cx, &[ptr_ty, info_ty], false)
120 in_memory_type_of(cx, ty).ptr_to()
124 let mut llty = match t.sty {
125 ty::TyBool => Type::bool(cx),
126 ty::TyChar => Type::char(cx),
127 ty::TyInt(t) => Type::int_from_ty(cx, t),
128 ty::TyUint(t) => Type::uint_from_ty(cx, t),
129 ty::TyFloat(t) => Type::float_from_ty(cx, t),
130 ty::TyNever => Type::nil(cx),
131 ty::TyClosure(..) => {
132 // Only create the named struct, but don't fill it in. We
133 // fill it in *after* placing it into the type cache.
134 adt::incomplete_type_of(cx, t, "closure")
137 ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
138 ty::TyRawPtr(ty::TypeAndMut{ty, ..}) => {
141 ty::TyAdt(def, _) if def.is_box() => {
145 ty::TyArray(ty, size) => {
146 let size = size as u64;
147 let llty = in_memory_type_of(cx, ty);
148 Type::array(&llty, size)
151 // Unsized slice types (and str) have the type of their element, and
152 // traits have the type of u8. This is so that the data pointer inside
153 // fat pointers is of the right type (e.g. for array accesses), even
154 // when taking the address of an unsized field in a struct.
155 ty::TySlice(ty) => in_memory_type_of(cx, ty),
156 ty::TyStr | ty::TyDynamic(..) => Type::i8(cx),
158 ty::TyFnDef(..) => Type::nil(cx),
159 ty::TyFnPtr(sig) => {
160 let sig = cx.tcx().erase_late_bound_regions_and_normalize(&sig);
161 FnType::new(cx, sig, &[]).llvm_type(cx).ptr_to()
163 ty::TyTuple(ref tys, _) if tys.is_empty() => Type::nil(cx),
167 ty::TyAdt(..) if t.is_simd() => {
168 let e = t.simd_type(cx.tcx());
170 cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
171 a non-machine element type `{}`",
174 let llet = in_memory_type_of(cx, e);
175 let n = t.simd_size(cx.tcx()) as u64;
176 Type::vector(&llet, n)
179 // Only create the named struct, but don't fill it in. We
180 // fill it in *after* placing it into the type cache. This
181 // avoids creating more than one copy of the enum when one
182 // of the enum's variants refers to the enum itself.
183 let name = llvm_type_name(cx, t);
184 adt::incomplete_type_of(cx, t, &name[..])
188 ty::TyProjection(..) |
191 ty::TyError => bug!("type_of with {:?}", t),
194 debug!("--> mapped t={:?} to llty={:?}", t, llty);
196 cx.lltypes().borrow_mut().insert(t, llty);
198 // If this was an enum or struct, fill in the type now.
200 ty::TyAdt(..) | ty::TyClosure(..) if !t.is_simd() && !t.is_box() => {
201 adt::finish_type_of(cx, t, &mut llty);
209 impl<'a, 'tcx> CrateContext<'a, 'tcx> {
210 pub fn align_of(&self, ty: Ty<'tcx>) -> machine::llalign {
211 self.layout_of(ty).align(self).abi() as machine::llalign
214 pub fn size_of(&self, ty: Ty<'tcx>) -> machine::llsize {
215 self.layout_of(ty).size(self).bytes() as machine::llsize
218 pub fn over_align_of(&self, t: Ty<'tcx>)
219 -> Option<machine::llalign> {
220 let layout = self.layout_of(t);
221 if let Some(align) = layout.over_align(&self.tcx().data_layout) {
222 Some(align as machine::llalign)
229 fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> String {
230 let mut name = String::with_capacity(32);
231 let printer = DefPathBasedNames::new(cx.tcx(), true, true);
232 printer.push_type_name(ty, &mut name);