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.
11 #![allow(non_camel_case_types)]
13 use middle::def_id::DefId;
20 use middle::ty::{self, Ty, TypeFoldable};
22 use trans::type_::Type;
27 // LLVM doesn't like objects that are too big. Issue #17913
28 fn ensure_array_fits_in_address_space<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
30 size: machine::llsize,
31 scapegoat: Ty<'tcx>) {
32 let esz = machine::llsize_of_alloc(ccx, llet);
33 match esz.checked_mul(size) {
34 Some(n) if n < ccx.obj_size_bound() => {}
35 _ => { ccx.report_overbig_object(scapegoat) }
39 pub fn arg_is_indirect<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
40 arg_ty: Ty<'tcx>) -> bool {
41 !type_is_immediate(ccx, arg_ty) && !type_is_fat_ptr(ccx.tcx(), arg_ty)
44 pub fn return_uses_outptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
45 ty: Ty<'tcx>) -> bool {
46 arg_is_indirect(ccx, ty)
49 pub fn type_of_explicit_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
50 arg_ty: Ty<'tcx>) -> Type {
51 let llty = arg_type_of(ccx, arg_ty);
52 if arg_is_indirect(ccx, arg_ty) {
59 /// Yields the types of the "real" arguments for a function using the `RustCall`
60 /// ABI by untupling the arguments of the function.
61 pub fn untuple_arguments<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
64 if inputs.is_empty() {
68 let mut result = Vec::new();
69 for (i, &arg_prior_to_tuple) in inputs.iter().enumerate() {
70 if i < inputs.len() - 1 {
71 result.push(arg_prior_to_tuple);
75 match inputs[inputs.len() - 1].sty {
76 ty::TyTuple(ref tupled_arguments) => {
77 debug!("untuple_arguments(): untupling arguments");
78 for &tupled_argument in tupled_arguments {
79 result.push(tupled_argument);
83 ccx.tcx().sess.bug("argument to function with \"rust-call\" ABI \
84 is neither a tuple nor unit")
91 pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
92 llenvironment_type: Option<Type>,
93 sig: &ty::FnSig<'tcx>,
97 debug!("type_of_rust_fn(sig={:?},abi={:?})",
101 assert!(!sig.variadic); // rust fns are never variadic
103 let mut atys: Vec<Type> = Vec::new();
105 // First, munge the inputs, if this has the `rust-call` ABI.
107 let inputs = if abi == Abi::RustCall {
108 inputs_temp = untuple_arguments(cx, &sig.inputs);
114 // Arg 0: Output pointer.
115 // (if the output type is non-immediate)
116 let lloutputtype = match sig.output {
117 ty::FnConverging(output) => {
118 let use_out_pointer = return_uses_outptr(cx, output);
119 let lloutputtype = arg_type_of(cx, output);
120 // Use the output as the actual return value if it's immediate.
122 atys.push(lloutputtype.ptr_to());
124 } else if return_type_is_void(cx, output) {
130 ty::FnDiverging => Type::void(cx)
133 // Arg 1: Environment
134 match llenvironment_type {
136 Some(llenvironment_type) => atys.push(llenvironment_type),
139 // ... then explicit args.
140 for input in inputs {
141 let arg_ty = type_of_explicit_arg(cx, input);
143 if type_is_fat_ptr(cx.tcx(), input) {
144 atys.extend(arg_ty.field_types());
150 Type::func(&atys[..], &lloutputtype)
153 // Given a function type and a count of ty params, construct an llvm type
154 pub fn type_of_fn_from_ty<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fty: Ty<'tcx>) -> Type {
156 ty::TyBareFn(_, ref f) => {
157 // FIXME(#19925) once fn item types are
158 // zero-sized, we'll need to do something here
159 if f.abi == Abi::Rust || f.abi == Abi::RustCall {
160 let sig = cx.tcx().erase_late_bound_regions(&f.sig);
161 let sig = infer::normalize_associated_type(cx.tcx(), &sig);
162 type_of_rust_fn(cx, None, &sig, f.abi)
164 foreign::lltype_for_foreign_fn(cx, fty)
168 cx.sess().bug("type_of_fn_from_ty given non-closure, non-bare-fn")
173 // A "sizing type" is an LLVM type, the size and alignment of which are
174 // guaranteed to be equivalent to what you would get out of `type_of()`. It's
177 // (1) It may be cheaper to compute the sizing type than the full type if all
178 // you're interested in is the size and/or alignment;
180 // (2) It won't make any recursive calls to determine the structure of the
181 // type behind pointers. This can help prevent infinite loops for
182 // recursive types. For example, enum types rely on this behavior.
184 pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
185 match cx.llsizingtypes().borrow().get(&t).cloned() {
190 debug!("sizing_type_of {:?}", t);
191 let _recursion_lock = cx.enter_type_of(t);
193 let llsizingty = match t.sty {
194 _ if !type_is_sized(cx.tcx(), t) => {
195 Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
198 ty::TyBool => Type::bool(cx),
199 ty::TyChar => Type::char(cx),
200 ty::TyInt(t) => Type::int_from_ty(cx, t),
201 ty::TyUint(t) => Type::uint_from_ty(cx, t),
202 ty::TyFloat(t) => Type::float_from_ty(cx, t),
205 ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
206 ty::TyRawPtr(ty::TypeAndMut{ty, ..}) => {
207 if type_is_sized(cx.tcx(), ty) {
210 Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
214 ty::TyBareFn(..) => Type::i8p(cx),
216 ty::TyArray(ty, size) => {
217 let llty = sizing_type_of(cx, ty);
218 let size = size as u64;
219 ensure_array_fits_in_address_space(cx, llty, size, t);
220 Type::array(&llty, size)
223 ty::TyTuple(ref tys) if tys.is_empty() => {
227 ty::TyTuple(..) | ty::TyEnum(..) | ty::TyClosure(..) => {
228 let repr = adt::represent_type(cx, t);
229 adt::sizing_type_of(cx, &repr, false)
232 ty::TyStruct(..) => {
234 let e = t.simd_type(cx.tcx());
236 cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
237 a non-machine element type `{}`",
240 let llet = type_of(cx, e);
241 let n = t.simd_size(cx.tcx()) as u64;
242 ensure_array_fits_in_address_space(cx, llet, n, t);
243 Type::vector(&llet, n)
245 let repr = adt::represent_type(cx, t);
246 adt::sizing_type_of(cx, &repr, false)
250 ty::TyProjection(..) | ty::TyInfer(..) | ty::TyParam(..) | ty::TyError => {
251 cx.sess().bug(&format!("fictitious type {:?} in sizing_type_of()",
254 ty::TySlice(_) | ty::TyTrait(..) | ty::TyStr => unreachable!()
257 debug!("--> mapped t={:?} to llsizingty={}",
259 cx.tn().type_to_string(llsizingty));
261 cx.llsizingtypes().borrow_mut().insert(t, llsizingty);
265 pub fn foreign_arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
273 pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
276 } else if type_is_immediate(cx, t) && type_of(cx, t).is_aggregate() {
277 // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
278 // for this leads to bad optimizations, so its arg type is an appropriately sized integer
279 match machine::llsize_of_alloc(cx, sizing_type_of(cx, t)) {
281 n => Type::ix(cx, n * 8),
288 /// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
289 /// This is the right LLVM type for an alloca containing a value of that type,
290 /// and the pointee of an Lvalue Datum (which is always a LLVM pointer).
291 /// For unsized types, the returned type is a fat pointer, thus the resulting
292 /// LLVM type for a `Trait` Lvalue is `{ i8*, void(i8*)** }*`, which is a double
293 /// indirection to the actual data, unlike a `i8` Lvalue, which is just `i8*`.
294 /// This is needed due to the treatment of immediate values, as a fat pointer
295 /// is too large for it to be placed in SSA value (by our rules).
296 /// For the raw type without far pointer indirection, see `in_memory_type_of`.
297 pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
298 let ty = if !type_is_sized(cx.tcx(), ty) {
299 cx.tcx().mk_imm_ptr(ty)
303 in_memory_type_of(cx, ty)
306 /// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
307 /// This is the right LLVM type for a field/array element of that type,
308 /// and is the same as `type_of` for all Sized types.
309 /// Unsized types, however, are represented by a "minimal unit", e.g.
310 /// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this
311 /// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.
312 /// If the type is an unsized struct, the regular layout is generated,
313 /// with the inner-most trailing unsized field using the "minimal unit"
314 /// of that field's type - this is useful for taking the address of
315 /// that field and ensuring the struct has the right alignment.
316 /// For the LLVM type of a value as a whole, see `type_of`.
317 /// NB: If you update this, be sure to update `sizing_type_of()` as well.
318 pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
320 match cx.lltypes().borrow().get(&t) {
321 Some(&llty) => return llty,
325 debug!("type_of {:?}", t);
327 assert!(!t.has_escaping_regions());
329 // Replace any typedef'd types with their equivalent non-typedef
330 // type. This ensures that all LLVM nominal types that contain
331 // Rust types are defined as the same LLVM types. If we don't do
332 // this then, e.g. `Option<{myfield: bool}>` would be a different
333 // type than `Option<myrec>`.
334 let t_norm = cx.tcx().erase_regions(&t);
337 let llty = in_memory_type_of(cx, t_norm);
338 debug!("--> normalized {:?} {:?} to {:?} {:?} llty={}",
343 cx.tn().type_to_string(llty));
344 cx.lltypes().borrow_mut().insert(t, llty);
348 let mut llty = match t.sty {
349 ty::TyBool => Type::bool(cx),
350 ty::TyChar => Type::char(cx),
351 ty::TyInt(t) => Type::int_from_ty(cx, t),
352 ty::TyUint(t) => Type::uint_from_ty(cx, t),
353 ty::TyFloat(t) => Type::float_from_ty(cx, t),
354 ty::TyEnum(def, ref substs) => {
355 // Only create the named struct, but don't fill it in. We
356 // fill it in *after* placing it into the type cache. This
357 // avoids creating more than one copy of the enum when one
358 // of the enum's variants refers to the enum itself.
359 let repr = adt::represent_type(cx, t);
360 let tps = substs.types.get_slice(subst::TypeSpace);
361 let name = llvm_type_name(cx, def.did, tps);
362 adt::incomplete_type_of(cx, &repr, &name[..])
364 ty::TyClosure(..) => {
365 // Only create the named struct, but don't fill it in. We
366 // fill it in *after* placing it into the type cache.
367 let repr = adt::represent_type(cx, t);
368 // Unboxed closures can have substitutions in all spaces
369 // inherited from their environment, so we use entire
370 // contents of the VecPerParamSpace to construct the llvm
372 adt::incomplete_type_of(cx, &repr, "closure")
376 ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
377 ty::TyRawPtr(ty::TypeAndMut{ty, ..}) => {
378 if !type_is_sized(cx.tcx(), ty) {
379 if let ty::TyStr = ty.sty {
380 // This means we get a nicer name in the output (str is always
382 cx.tn().find_type("str_slice").unwrap()
384 let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
385 let unsized_part = cx.tcx().struct_tail(ty);
386 let info_ty = match unsized_part.sty {
387 ty::TyStr | ty::TyArray(..) | ty::TySlice(_) => {
388 Type::uint_from_ty(cx, ast::UintTy::Us)
390 ty::TyTrait(_) => Type::vtable_ptr(cx),
391 _ => panic!("Unexpected type returned from \
392 struct_tail: {:?} for ty={:?}",
395 Type::struct_(cx, &[ptr_ty, info_ty], false)
398 in_memory_type_of(cx, ty).ptr_to()
402 ty::TyArray(ty, size) => {
403 let size = size as u64;
404 // we must use `sizing_type_of` here as the type may
405 // not be fully initialized.
406 let szty = sizing_type_of(cx, ty);
407 ensure_array_fits_in_address_space(cx, szty, size, t);
409 let llty = in_memory_type_of(cx, ty);
410 Type::array(&llty, size)
413 // Unsized slice types (and str) have the type of their element, and
414 // traits have the type of u8. This is so that the data pointer inside
415 // fat pointers is of the right type (e.g. for array accesses), even
416 // when taking the address of an unsized field in a struct.
417 ty::TySlice(ty) => in_memory_type_of(cx, ty),
418 ty::TyStr | ty::TyTrait(..) => Type::i8(cx),
420 ty::TyBareFn(..) => {
421 type_of_fn_from_ty(cx, t).ptr_to()
423 ty::TyTuple(ref tys) if tys.is_empty() => Type::nil(cx),
425 let repr = adt::represent_type(cx, t);
426 adt::type_of(cx, &repr)
428 ty::TyStruct(def, ref substs) => {
430 let e = t.simd_type(cx.tcx());
432 cx.sess().fatal(&format!("monomorphising SIMD type `{}` with \
433 a non-machine element type `{}`",
436 let llet = in_memory_type_of(cx, e);
437 let n = t.simd_size(cx.tcx()) as u64;
438 ensure_array_fits_in_address_space(cx, llet, n, t);
439 Type::vector(&llet, n)
441 // Only create the named struct, but don't fill it in. We fill it
442 // in *after* placing it into the type cache. This prevents
443 // infinite recursion with recursive struct types.
444 let repr = adt::represent_type(cx, t);
445 let tps = substs.types.get_slice(subst::TypeSpace);
446 let name = llvm_type_name(cx, def.did, tps);
447 adt::incomplete_type_of(cx, &repr, &name[..])
451 ty::TyInfer(..) => cx.sess().bug("type_of with TyInfer"),
452 ty::TyProjection(..) => cx.sess().bug("type_of with TyProjection"),
453 ty::TyParam(..) => cx.sess().bug("type_of with ty_param"),
454 ty::TyError => cx.sess().bug("type_of with TyError"),
457 debug!("--> mapped t={:?} to llty={}",
459 cx.tn().type_to_string(llty));
461 cx.lltypes().borrow_mut().insert(t, llty);
463 // If this was an enum or struct, fill in the type now.
465 ty::TyEnum(..) | ty::TyStruct(..) | ty::TyClosure(..)
467 let repr = adt::represent_type(cx, t);
468 adt::finish_type_of(cx, &repr, &mut llty);
476 pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
477 -> machine::llalign {
478 let llty = sizing_type_of(cx, t);
479 machine::llalign_of_min(cx, llty)
482 fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
486 let base = cx.tcx().item_path_str(did);
487 let strings: Vec<String> = tps.iter().map(|t| t.to_string()).collect();
488 let tstr = if strings.is_empty() {
491 format!("{}<{}>", base, strings.join(", "))
497 format!("{}.{}", did.krate, tstr)