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)]
18 use middle::ty::{self, RegionEscape, Ty};
20 use util::ppaux::Repr;
22 use trans::type_::Type;
28 // LLVM doesn't like objects that are too big. Issue #17913
29 fn ensure_array_fits_in_address_space<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
31 size: machine::llsize,
32 scapegoat: Ty<'tcx>) {
33 let esz = machine::llsize_of_alloc(ccx, llet);
34 match esz.checked_mul(size) {
35 Some(n) if n < ccx.obj_size_bound() => {}
36 _ => { ccx.report_overbig_object(scapegoat) }
40 pub fn arg_is_indirect<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
41 arg_ty: Ty<'tcx>) -> bool {
42 !type_is_immediate(ccx, arg_ty)
45 pub fn return_uses_outptr<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
46 ty: Ty<'tcx>) -> bool {
47 !type_is_immediate(ccx, ty)
50 pub fn type_of_explicit_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
51 arg_ty: Ty<'tcx>) -> Type {
52 let llty = arg_type_of(ccx, arg_ty);
53 if arg_is_indirect(ccx, arg_ty) {
60 /// Yields the types of the "real" arguments for this function. For most
61 /// functions, these are simply the types of the arguments. For functions with
62 /// the `RustCall` ABI, however, this untuples the arguments of the function.
63 pub fn untuple_arguments_if_necessary<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
67 if abi != abi::RustCall {
68 return inputs.iter().cloned().collect()
71 if inputs.len() == 0 {
75 let mut result = Vec::new();
76 for (i, &arg_prior_to_tuple) in inputs.iter().enumerate() {
77 if i < inputs.len() - 1 {
78 result.push(arg_prior_to_tuple);
82 match inputs[inputs.len() - 1].sty {
83 ty::ty_tup(ref tupled_arguments) => {
84 debug!("untuple_arguments_if_necessary(): untupling arguments");
85 for &tupled_argument in tupled_arguments {
86 result.push(tupled_argument);
90 ccx.tcx().sess.bug("argument to function with \"rust-call\" ABI \
91 is neither a tuple nor unit")
98 pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
99 llenvironment_type: Option<Type>,
100 sig: &ty::Binder<ty::FnSig<'tcx>>,
104 debug!("type_of_rust_fn(sig={},abi={:?})",
108 let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
109 assert!(!sig.variadic); // rust fns are never variadic
111 let mut atys: Vec<Type> = Vec::new();
113 // First, munge the inputs, if this has the `rust-call` ABI.
114 let inputs = untuple_arguments_if_necessary(cx, &sig.inputs, abi);
116 // Arg 0: Output pointer.
117 // (if the output type is non-immediate)
118 let lloutputtype = match sig.output {
119 ty::FnConverging(output) => {
120 let use_out_pointer = return_uses_outptr(cx, output);
121 let lloutputtype = arg_type_of(cx, output);
122 // Use the output as the actual return value if it's immediate.
124 atys.push(lloutputtype.ptr_to());
126 } else if return_type_is_void(cx, output) {
132 ty::FnDiverging => Type::void(cx)
135 // Arg 1: Environment
136 match llenvironment_type {
138 Some(llenvironment_type) => atys.push(llenvironment_type),
141 // ... then explicit args.
142 let input_tys = inputs.iter().map(|&arg_ty| type_of_explicit_arg(cx, arg_ty));
143 atys.extend(input_tys);
145 Type::func(&atys[..], &lloutputtype)
148 // Given a function type and a count of ty params, construct an llvm type
149 pub fn type_of_fn_from_ty<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, fty: Ty<'tcx>) -> Type {
151 ty::ty_bare_fn(_, ref f) => {
152 // FIXME(#19925) once fn item types are
153 // zero-sized, we'll need to do something here
154 if f.abi == abi::Rust || f.abi == abi::RustCall {
155 type_of_rust_fn(cx, None, &f.sig, f.abi)
157 foreign::lltype_for_foreign_fn(cx, fty)
161 cx.sess().bug("type_of_fn_from_ty given non-closure, non-bare-fn")
166 // A "sizing type" is an LLVM type, the size and alignment of which are
167 // guaranteed to be equivalent to what you would get out of `type_of()`. It's
170 // (1) It may be cheaper to compute the sizing type than the full type if all
171 // you're interested in is the size and/or alignment;
173 // (2) It won't make any recursive calls to determine the structure of the
174 // type behind pointers. This can help prevent infinite loops for
175 // recursive types. For example, enum types rely on this behavior.
177 pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
178 match cx.llsizingtypes().borrow().get(&t).cloned() {
183 let llsizingty = match t.sty {
184 _ if !type_is_sized(cx.tcx(), t) => {
185 Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
188 ty::ty_bool => Type::bool(cx),
189 ty::ty_char => Type::char(cx),
190 ty::ty_int(t) => Type::int_from_ty(cx, t),
191 ty::ty_uint(t) => Type::uint_from_ty(cx, t),
192 ty::ty_float(t) => Type::float_from_ty(cx, t),
194 ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
195 if type_is_sized(cx.tcx(), ty) {
198 Type::struct_(cx, &[Type::i8p(cx), Type::i8p(cx)], false)
202 ty::ty_bare_fn(..) => Type::i8p(cx),
204 ty::ty_vec(ty, Some(size)) => {
205 let llty = sizing_type_of(cx, ty);
206 let size = size as u64;
207 ensure_array_fits_in_address_space(cx, llty, size, t);
208 Type::array(&llty, size)
211 ty::ty_tup(ref tys) if tys.is_empty() => {
215 ty::ty_tup(..) | ty::ty_enum(..) | ty::ty_closure(..) => {
216 let repr = adt::represent_type(cx, t);
217 adt::sizing_type_of(cx, &*repr, false)
220 ty::ty_struct(..) => {
221 if ty::type_is_simd(cx.tcx(), t) {
222 let llet = type_of(cx, ty::simd_type(cx.tcx(), t));
223 let n = ty::simd_size(cx.tcx(), t) as u64;
224 ensure_array_fits_in_address_space(cx, llet, n, t);
225 Type::vector(&llet, n)
227 let repr = adt::represent_type(cx, t);
228 adt::sizing_type_of(cx, &*repr, false)
232 ty::ty_projection(..) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
233 cx.sess().bug(&format!("fictitious type {} in sizing_type_of()",
234 ppaux::ty_to_string(cx.tcx(), t)))
236 ty::ty_vec(_, None) | ty::ty_trait(..) | ty::ty_str => unreachable!()
239 cx.llsizingtypes().borrow_mut().insert(t, llsizingty);
243 pub fn foreign_arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
244 if ty::type_is_bool(t) {
251 pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
252 if ty::type_is_bool(t) {
254 } else if type_is_immediate(cx, t) && type_of(cx, t).is_aggregate() {
255 // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
256 // for this leads to bad optimizations, so its arg type is an appropriately sized integer
257 match machine::llsize_of_alloc(cx, sizing_type_of(cx, t)) {
259 n => Type::ix(cx, n * 8),
266 /// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
267 /// This is the right LLVM type for an alloca containg a value of that type,
268 /// and the pointee of an Lvalue Datum (which is always a LLVM pointer).
269 /// For unsized types, the returned type is a fat pointer, thus the resulting
270 /// LLVM type for a `Trait` Lvalue is `{ i8*, void(i8*)** }*`, which is a double
271 /// indirection to the actual data, unlike a `i8` Lvalue, which is just `i8*`.
272 /// This is needed due to the treatment of immediate values, as a fat pointer
273 /// is too large for it to be placed in SSA value (by our rules).
274 /// For the raw type without far pointer indirection, see `in_memory_type_of`.
275 pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
276 let ty = if !type_is_sized(cx.tcx(), ty) {
277 ty::mk_imm_ptr(cx.tcx(), ty)
281 in_memory_type_of(cx, ty)
284 /// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
285 /// This is the right LLVM type for a field/array element of that type,
286 /// and is the same as `type_of` for all Sized types.
287 /// Unsized types, however, are represented by a "minimal unit", e.g.
288 /// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this
289 /// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.
290 /// If the type is an unsized struct, the regular layout is generated,
291 /// with the inner-most trailing unsized field using the "minimal unit"
292 /// of that field's type - this is useful for taking the address of
293 /// that field and ensuring the struct has the right alignment.
294 /// For the LLVM type of a value as a whole, see `type_of`.
295 /// NB: If you update this, be sure to update `sizing_type_of()` as well.
296 pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
298 match cx.lltypes().borrow().get(&t) {
299 Some(&llty) => return llty,
303 debug!("type_of {} {:?}", t.repr(cx.tcx()), t.sty);
305 assert!(!t.has_escaping_regions());
307 // Replace any typedef'd types with their equivalent non-typedef
308 // type. This ensures that all LLVM nominal types that contain
309 // Rust types are defined as the same LLVM types. If we don't do
310 // this then, e.g. `Option<{myfield: bool}>` would be a different
311 // type than `Option<myrec>`.
312 let t_norm = erase_regions(cx.tcx(), &t);
315 let llty = in_memory_type_of(cx, t_norm);
316 debug!("--> normalized {} {:?} to {} {:?} llty={}",
319 t_norm.repr(cx.tcx()),
321 cx.tn().type_to_string(llty));
322 cx.lltypes().borrow_mut().insert(t, llty);
326 let mut llty = match t.sty {
327 ty::ty_bool => Type::bool(cx),
328 ty::ty_char => Type::char(cx),
329 ty::ty_int(t) => Type::int_from_ty(cx, t),
330 ty::ty_uint(t) => Type::uint_from_ty(cx, t),
331 ty::ty_float(t) => Type::float_from_ty(cx, t),
332 ty::ty_enum(did, ref substs) => {
333 // Only create the named struct, but don't fill it in. We
334 // fill it in *after* placing it into the type cache. This
335 // avoids creating more than one copy of the enum when one
336 // of the enum's variants refers to the enum itself.
337 let repr = adt::represent_type(cx, t);
338 let tps = substs.types.get_slice(subst::TypeSpace);
339 let name = llvm_type_name(cx, did, tps);
340 adt::incomplete_type_of(cx, &*repr, &name[..])
342 ty::ty_closure(..) => {
343 // Only create the named struct, but don't fill it in. We
344 // fill it in *after* placing it into the type cache.
345 let repr = adt::represent_type(cx, t);
346 // Unboxed closures can have substitutions in all spaces
347 // inherited from their environment, so we use entire
348 // contents of the VecPerParamSpace to to construct the llvm
350 adt::incomplete_type_of(cx, &*repr, "closure")
353 ty::ty_uniq(ty) | ty::ty_rptr(_, ty::mt{ty, ..}) | ty::ty_ptr(ty::mt{ty, ..}) => {
354 if !type_is_sized(cx.tcx(), ty) {
355 if let ty::ty_str = ty.sty {
356 // This means we get a nicer name in the output (str is always
358 cx.tn().find_type("str_slice").unwrap()
360 let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
361 let unsized_part = unsized_part_of_type(cx.tcx(), ty);
362 let info_ty = match unsized_part.sty {
363 ty::ty_str | ty::ty_vec(..) => {
364 Type::uint_from_ty(cx, ast::TyUs(false))
366 ty::ty_trait(_) => Type::vtable_ptr(cx),
367 _ => panic!("Unexpected type returned from \
368 unsized_part_of_type: {} for ty={}",
369 unsized_part.repr(cx.tcx()), ty.repr(cx.tcx()))
371 Type::struct_(cx, &[ptr_ty, info_ty], false)
374 in_memory_type_of(cx, ty).ptr_to()
378 ty::ty_vec(ty, Some(size)) => {
379 let size = size as u64;
380 let llty = in_memory_type_of(cx, ty);
381 ensure_array_fits_in_address_space(cx, llty, size, t);
382 Type::array(&llty, size)
385 // Unsized slice types (and str) have the type of their element, and
386 // traits have the type of u8. This is so that the data pointer inside
387 // fat pointers is of the right type (e.g. for array accesses), even
388 // when taking the address of an unsized field in a struct.
389 ty::ty_vec(ty, None) => in_memory_type_of(cx, ty),
390 ty::ty_str | ty::ty_trait(..) => Type::i8(cx),
392 ty::ty_bare_fn(..) => {
393 type_of_fn_from_ty(cx, t).ptr_to()
395 ty::ty_tup(ref tys) if tys.is_empty() => Type::nil(cx),
397 let repr = adt::represent_type(cx, t);
398 adt::type_of(cx, &*repr)
400 ty::ty_struct(did, ref substs) => {
401 if ty::type_is_simd(cx.tcx(), t) {
402 let llet = in_memory_type_of(cx, ty::simd_type(cx.tcx(), t));
403 let n = ty::simd_size(cx.tcx(), t) as u64;
404 ensure_array_fits_in_address_space(cx, llet, n, t);
405 Type::vector(&llet, n)
407 // Only create the named struct, but don't fill it in. We fill it
408 // in *after* placing it into the type cache. This prevents
409 // infinite recursion with recursive struct types.
410 let repr = adt::represent_type(cx, t);
411 let tps = substs.types.get_slice(subst::TypeSpace);
412 let name = llvm_type_name(cx, did, tps);
413 adt::incomplete_type_of(cx, &*repr, &name[..])
417 ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
418 ty::ty_projection(..) => cx.sess().bug("type_of with ty_projection"),
419 ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
420 ty::ty_err(..) => cx.sess().bug("type_of with ty_err"),
423 debug!("--> mapped t={} {:?} to llty={}",
426 cx.tn().type_to_string(llty));
428 cx.lltypes().borrow_mut().insert(t, llty);
430 // If this was an enum or struct, fill in the type now.
432 ty::ty_enum(..) | ty::ty_struct(..) | ty::ty_closure(..)
433 if !ty::type_is_simd(cx.tcx(), t) => {
434 let repr = adt::represent_type(cx, t);
435 adt::finish_type_of(cx, &*repr, &mut llty);
443 pub fn align_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>)
444 -> machine::llalign {
445 let llty = sizing_type_of(cx, t);
446 machine::llalign_of_min(cx, llty)
449 fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
453 let base = ty::item_path_str(cx.tcx(), did);
454 let strings: Vec<String> = tps.iter().map(|t| t.repr(cx.tcx())).collect();
455 let tstr = if strings.is_empty() {
458 format!("{}<{}>", base, strings.connect(", "))
464 format!("{}.{}", did.krate, tstr)
468 pub fn type_of_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, self_ty: Ty<'tcx>) -> Type {
469 let self_ty = type_of(ccx, self_ty).ptr_to();
470 Type::func(&[self_ty], &Type::void(ccx))