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 trans
::type_
::Type
;
25 // LLVM doesn't like objects that are too big. Issue #17913
26 fn ensure_array_fits_in_address_space
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
28 size
: machine
::llsize
,
29 scapegoat
: Ty
<'tcx
>) {
30 let esz
= machine
::llsize_of_alloc(ccx
, llet
);
31 match esz
.checked_mul(size
) {
32 Some(n
) if n
< ccx
.obj_size_bound() => {}
33 _
=> { ccx.report_overbig_object(scapegoat) }
37 pub fn arg_is_indirect
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
38 arg_ty
: Ty
<'tcx
>) -> bool
{
39 !type_is_immediate(ccx
, arg_ty
) && !type_is_fat_ptr(ccx
.tcx(), arg_ty
)
42 pub fn return_uses_outptr
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
43 ty
: Ty
<'tcx
>) -> bool
{
44 arg_is_indirect(ccx
, ty
)
47 pub fn type_of_explicit_arg
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
48 arg_ty
: Ty
<'tcx
>) -> Type
{
49 let llty
= arg_type_of(ccx
, arg_ty
);
50 if arg_is_indirect(ccx
, arg_ty
) {
57 /// Yields the types of the "real" arguments for this function. For most
58 /// functions, these are simply the types of the arguments. For functions with
59 /// the `RustCall` ABI, however, this untuples the arguments of the function.
60 pub fn untuple_arguments_if_necessary
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>,
64 if abi
!= abi
::RustCall
{
65 return inputs
.iter().cloned().collect()
68 if inputs
.is_empty() {
72 let mut result
= Vec
::new();
73 for (i
, &arg_prior_to_tuple
) in inputs
.iter().enumerate() {
74 if i
< inputs
.len() - 1 {
75 result
.push(arg_prior_to_tuple
);
79 match inputs
[inputs
.len() - 1].sty
{
80 ty
::TyTuple(ref tupled_arguments
) => {
81 debug
!("untuple_arguments_if_necessary(): untupling arguments");
82 for &tupled_argument
in tupled_arguments
{
83 result
.push(tupled_argument
);
87 ccx
.tcx().sess
.bug("argument to function with \"rust-call\" ABI \
88 is neither a tuple nor unit")
95 pub fn type_of_rust_fn
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
96 llenvironment_type
: Option
<Type
>,
97 sig
: &ty
::Binder
<ty
::FnSig
<'tcx
>>,
101 debug
!("type_of_rust_fn(sig={:?},abi={:?})",
105 let sig
= ty
::erase_late_bound_regions(cx
.tcx(), sig
);
106 assert
!(!sig
.variadic
); // rust fns are never variadic
108 let mut atys
: Vec
<Type
> = Vec
::new();
110 // First, munge the inputs, if this has the `rust-call` ABI.
111 let inputs
= untuple_arguments_if_necessary(cx
, &sig
.inputs
, abi
);
113 // Arg 0: Output pointer.
114 // (if the output type is non-immediate)
115 let lloutputtype
= match sig
.output
{
116 ty
::FnConverging(output
) => {
117 let use_out_pointer
= return_uses_outptr(cx
, output
);
118 let lloutputtype
= arg_type_of(cx
, output
);
119 // Use the output as the actual return value if it's immediate.
121 atys
.push(lloutputtype
.ptr_to());
123 } else if return_type_is_void(cx
, output
) {
129 ty
::FnDiverging
=> Type
::void(cx
)
132 // Arg 1: Environment
133 match llenvironment_type
{
135 Some(llenvironment_type
) => atys
.push(llenvironment_type
),
138 // ... then explicit args.
139 for input
in &inputs
{
140 let arg_ty
= type_of_explicit_arg(cx
, input
);
142 if type_is_fat_ptr(cx
.tcx(), input
) {
143 atys
.extend(arg_ty
.field_types());
149 Type
::func(&atys
[..], &lloutputtype
)
152 // Given a function type and a count of ty params, construct an llvm type
153 pub fn type_of_fn_from_ty
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>, fty
: Ty
<'tcx
>) -> Type
{
155 ty
::TyBareFn(_
, ref f
) => {
156 // FIXME(#19925) once fn item types are
157 // zero-sized, we'll need to do something here
158 if f
.abi
== abi
::Rust
|| f
.abi
== abi
::RustCall
{
159 type_of_rust_fn(cx
, None
, &f
.sig
, f
.abi
)
161 foreign
::lltype_for_foreign_fn(cx
, fty
)
165 cx
.sess().bug("type_of_fn_from_ty given non-closure, non-bare-fn")
170 // A "sizing type" is an LLVM type, the size and alignment of which are
171 // guaranteed to be equivalent to what you would get out of `type_of()`. It's
174 // (1) It may be cheaper to compute the sizing type than the full type if all
175 // you're interested in is the size and/or alignment;
177 // (2) It won't make any recursive calls to determine the structure of the
178 // type behind pointers. This can help prevent infinite loops for
179 // recursive types. For example, enum types rely on this behavior.
181 pub fn sizing_type_of
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>, t
: Ty
<'tcx
>) -> Type
{
182 match cx
.llsizingtypes().borrow().get(&t
).cloned() {
187 let llsizingty
= match t
.sty
{
188 _
if !type_is_sized(cx
.tcx(), t
) => {
189 Type
::struct_(cx
, &[Type
::i8p(cx
), Type
::i8p(cx
)], false)
192 ty
::TyBool
=> Type
::bool(cx
),
193 ty
::TyChar
=> Type
::char(cx
),
194 ty
::TyInt(t
) => Type
::int_from_ty(cx
, t
),
195 ty
::TyUint(t
) => Type
::uint_from_ty(cx
, t
),
196 ty
::TyFloat(t
) => Type
::float_from_ty(cx
, t
),
198 ty
::TyBox(ty
) | ty
::TyRef(_
, ty
::mt{ty, ..}
) | ty
::TyRawPtr(ty
::mt{ty, ..}
) => {
199 if type_is_sized(cx
.tcx(), ty
) {
202 Type
::struct_(cx
, &[Type
::i8p(cx
), Type
::i8p(cx
)], false)
206 ty
::TyBareFn(..) => Type
::i8p(cx
),
208 ty
::TyArray(ty
, size
) => {
209 let llty
= sizing_type_of(cx
, ty
);
210 let size
= size
as u64;
211 ensure_array_fits_in_address_space(cx
, llty
, size
, t
);
212 Type
::array(&llty
, size
)
215 ty
::TyTuple(ref tys
) if tys
.is_empty() => {
219 ty
::TyTuple(..) | ty
::TyEnum(..) | ty
::TyClosure(..) => {
220 let repr
= adt
::represent_type(cx
, t
);
221 adt
::sizing_type_of(cx
, &*repr
, false)
224 ty
::TyStruct(..) => {
225 if ty
::type_is_simd(cx
.tcx(), t
) {
226 let llet
= type_of(cx
, ty
::simd_type(cx
.tcx(), t
));
227 let n
= ty
::simd_size(cx
.tcx(), t
) as u64;
228 ensure_array_fits_in_address_space(cx
, llet
, n
, t
);
229 Type
::vector(&llet
, n
)
231 let repr
= adt
::represent_type(cx
, t
);
232 adt
::sizing_type_of(cx
, &*repr
, false)
236 ty
::TyProjection(..) | ty
::TyInfer(..) | ty
::TyParam(..) | ty
::TyError(..) => {
237 cx
.sess().bug(&format
!("fictitious type {:?} in sizing_type_of()",
240 ty
::TySlice(_
) | ty
::TyTrait(..) | ty
::TyStr
=> unreachable
!()
243 cx
.llsizingtypes().borrow_mut().insert(t
, llsizingty
);
247 pub fn foreign_arg_type_of
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>, t
: Ty
<'tcx
>) -> Type
{
248 if ty
::type_is_bool(t
) {
255 pub fn arg_type_of
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>, t
: Ty
<'tcx
>) -> Type
{
256 if ty
::type_is_bool(t
) {
258 } else if type_is_immediate(cx
, t
) && type_of(cx
, t
).is_aggregate() {
259 // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
260 // for this leads to bad optimizations, so its arg type is an appropriately sized integer
261 match machine
::llsize_of_alloc(cx
, sizing_type_of(cx
, t
)) {
263 n
=> Type
::ix(cx
, n
* 8),
270 /// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
271 /// This is the right LLVM type for an alloca containing a value of that type,
272 /// and the pointee of an Lvalue Datum (which is always a LLVM pointer).
273 /// For unsized types, the returned type is a fat pointer, thus the resulting
274 /// LLVM type for a `Trait` Lvalue is `{ i8*, void(i8*)** }*`, which is a double
275 /// indirection to the actual data, unlike a `i8` Lvalue, which is just `i8*`.
276 /// This is needed due to the treatment of immediate values, as a fat pointer
277 /// is too large for it to be placed in SSA value (by our rules).
278 /// For the raw type without far pointer indirection, see `in_memory_type_of`.
279 pub fn type_of
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>, ty
: Ty
<'tcx
>) -> Type
{
280 let ty
= if !type_is_sized(cx
.tcx(), ty
) {
281 ty
::mk_imm_ptr(cx
.tcx(), ty
)
285 in_memory_type_of(cx
, ty
)
288 /// Get the LLVM type corresponding to a Rust type, i.e. `middle::ty::Ty`.
289 /// This is the right LLVM type for a field/array element of that type,
290 /// and is the same as `type_of` for all Sized types.
291 /// Unsized types, however, are represented by a "minimal unit", e.g.
292 /// `[T]` becomes `T`, while `str` and `Trait` turn into `i8` - this
293 /// is useful for indexing slices, as `&[T]`'s data pointer is `T*`.
294 /// If the type is an unsized struct, the regular layout is generated,
295 /// with the inner-most trailing unsized field using the "minimal unit"
296 /// of that field's type - this is useful for taking the address of
297 /// that field and ensuring the struct has the right alignment.
298 /// For the LLVM type of a value as a whole, see `type_of`.
299 /// NB: If you update this, be sure to update `sizing_type_of()` as well.
300 pub fn in_memory_type_of
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>, t
: Ty
<'tcx
>) -> Type
{
302 match cx
.lltypes().borrow().get(&t
) {
303 Some(&llty
) => return llty
,
307 debug
!("type_of {:?}", t
);
309 assert
!(!t
.has_escaping_regions());
311 // Replace any typedef'd types with their equivalent non-typedef
312 // type. This ensures that all LLVM nominal types that contain
313 // Rust types are defined as the same LLVM types. If we don't do
314 // this then, e.g. `Option<{myfield: bool}>` would be a different
315 // type than `Option<myrec>`.
316 let t_norm
= erase_regions(cx
.tcx(), &t
);
319 let llty
= in_memory_type_of(cx
, t_norm
);
320 debug
!("--> normalized {:?} {:?} to {:?} {:?} llty={}",
325 cx
.tn().type_to_string(llty
));
326 cx
.lltypes().borrow_mut().insert(t
, llty
);
330 let mut llty
= match t
.sty
{
331 ty
::TyBool
=> Type
::bool(cx
),
332 ty
::TyChar
=> Type
::char(cx
),
333 ty
::TyInt(t
) => Type
::int_from_ty(cx
, t
),
334 ty
::TyUint(t
) => Type
::uint_from_ty(cx
, t
),
335 ty
::TyFloat(t
) => Type
::float_from_ty(cx
, t
),
336 ty
::TyEnum(did
, ref substs
) => {
337 // Only create the named struct, but don't fill it in. We
338 // fill it in *after* placing it into the type cache. This
339 // avoids creating more than one copy of the enum when one
340 // of the enum's variants refers to the enum itself.
341 let repr
= adt
::represent_type(cx
, t
);
342 let tps
= substs
.types
.get_slice(subst
::TypeSpace
);
343 let name
= llvm_type_name(cx
, did
, tps
);
344 adt
::incomplete_type_of(cx
, &*repr
, &name
[..])
346 ty
::TyClosure(..) => {
347 // Only create the named struct, but don't fill it in. We
348 // fill it in *after* placing it into the type cache.
349 let repr
= adt
::represent_type(cx
, t
);
350 // Unboxed closures can have substitutions in all spaces
351 // inherited from their environment, so we use entire
352 // contents of the VecPerParamSpace to to construct the llvm
354 adt
::incomplete_type_of(cx
, &*repr
, "closure")
357 ty
::TyBox(ty
) | ty
::TyRef(_
, ty
::mt{ty, ..}
) | ty
::TyRawPtr(ty
::mt{ty, ..}
) => {
358 if !type_is_sized(cx
.tcx(), ty
) {
359 if let ty
::TyStr
= ty
.sty
{
360 // This means we get a nicer name in the output (str is always
362 cx
.tn().find_type("str_slice").unwrap()
364 let ptr_ty
= in_memory_type_of(cx
, ty
).ptr_to();
365 let unsized_part
= ty
::struct_tail(cx
.tcx(), ty
);
366 let info_ty
= match unsized_part
.sty
{
367 ty
::TyStr
| ty
::TyArray(..) | ty
::TySlice(_
) => {
368 Type
::uint_from_ty(cx
, ast
::TyUs
)
370 ty
::TyTrait(_
) => Type
::vtable_ptr(cx
),
371 _
=> panic
!("Unexpected type returned from \
372 struct_tail: {:?} for ty={:?}",
375 Type
::struct_(cx
, &[ptr_ty
, info_ty
], false)
378 in_memory_type_of(cx
, ty
).ptr_to()
382 ty
::TyArray(ty
, size
) => {
383 let size
= size
as u64;
384 let llty
= in_memory_type_of(cx
, ty
);
385 ensure_array_fits_in_address_space(cx
, llty
, size
, t
);
386 Type
::array(&llty
, size
)
389 // Unsized slice types (and str) have the type of their element, and
390 // traits have the type of u8. This is so that the data pointer inside
391 // fat pointers is of the right type (e.g. for array accesses), even
392 // when taking the address of an unsized field in a struct.
393 ty
::TySlice(ty
) => in_memory_type_of(cx
, ty
),
394 ty
::TyStr
| ty
::TyTrait(..) => Type
::i8(cx
),
396 ty
::TyBareFn(..) => {
397 type_of_fn_from_ty(cx
, t
).ptr_to()
399 ty
::TyTuple(ref tys
) if tys
.is_empty() => Type
::nil(cx
),
401 let repr
= adt
::represent_type(cx
, t
);
402 adt
::type_of(cx
, &*repr
)
404 ty
::TyStruct(did
, ref substs
) => {
405 if ty
::type_is_simd(cx
.tcx(), t
) {
406 let llet
= in_memory_type_of(cx
, ty
::simd_type(cx
.tcx(), t
));
407 let n
= ty
::simd_size(cx
.tcx(), t
) as u64;
408 ensure_array_fits_in_address_space(cx
, llet
, n
, t
);
409 Type
::vector(&llet
, n
)
411 // Only create the named struct, but don't fill it in. We fill it
412 // in *after* placing it into the type cache. This prevents
413 // infinite recursion with recursive struct types.
414 let repr
= adt
::represent_type(cx
, t
);
415 let tps
= substs
.types
.get_slice(subst
::TypeSpace
);
416 let name
= llvm_type_name(cx
, did
, tps
);
417 adt
::incomplete_type_of(cx
, &*repr
, &name
[..])
421 ty
::TyInfer(..) => cx
.sess().bug("type_of with TyInfer"),
422 ty
::TyProjection(..) => cx
.sess().bug("type_of with TyProjection"),
423 ty
::TyParam(..) => cx
.sess().bug("type_of with ty_param"),
424 ty
::TyError(..) => cx
.sess().bug("type_of with TyError"),
427 debug
!("--> mapped t={:?} {:?} to llty={}",
430 cx
.tn().type_to_string(llty
));
432 cx
.lltypes().borrow_mut().insert(t
, llty
);
434 // If this was an enum or struct, fill in the type now.
436 ty
::TyEnum(..) | ty
::TyStruct(..) | ty
::TyClosure(..)
437 if !ty
::type_is_simd(cx
.tcx(), t
) => {
438 let repr
= adt
::represent_type(cx
, t
);
439 adt
::finish_type_of(cx
, &*repr
, &mut llty
);
447 pub fn align_of
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>, t
: Ty
<'tcx
>)
448 -> machine
::llalign
{
449 let llty
= sizing_type_of(cx
, t
);
450 machine
::llalign_of_min(cx
, llty
)
453 fn llvm_type_name
<'a
, 'tcx
>(cx
: &CrateContext
<'a
, 'tcx
>,
457 let base
= ty
::item_path_str(cx
.tcx(), did
);
458 let strings
: Vec
<String
> = tps
.iter().map(|t
| t
.to_string()).collect();
459 let tstr
= if strings
.is_empty() {
462 format
!("{}<{}>", base
, strings
.connect(", "))
468 format
!("{}.{}", did
.krate
, tstr
)
472 pub fn type_of_dtor
<'a
, 'tcx
>(ccx
: &CrateContext
<'a
, 'tcx
>, self_ty
: Ty
<'tcx
>) -> Type
{
473 let self_ty
= type_of(ccx
, self_ty
).ptr_to();
474 Type
::func(&[self_ty
], &Type
::void(ccx
))