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::trans::adt;
14 use middle::trans::common::*;
15 use middle::trans::foreign;
18 use util::ppaux::Repr;
20 use middle::trans::type_::Type;
23 use syntax::owned_slice::OwnedSlice;
25 pub fn arg_is_indirect(ccx: &CrateContext, arg_ty: ty::t) -> bool {
26 !type_is_immediate(ccx, arg_ty)
29 pub fn return_uses_outptr(ccx: &CrateContext, ty: ty::t) -> bool {
30 !type_is_immediate(ccx, ty)
33 pub fn type_of_explicit_arg(ccx: &CrateContext, arg_ty: ty::t) -> Type {
34 let llty = type_of(ccx, arg_ty);
35 if arg_is_indirect(ccx, arg_ty) {
42 pub fn type_of_rust_fn(cx: &CrateContext, has_env: bool,
43 inputs: &[ty::t], output: ty::t) -> Type {
44 let mut atys: Vec<Type> = Vec::new();
46 // Arg 0: Output pointer.
47 // (if the output type is non-immediate)
48 let use_out_pointer = return_uses_outptr(cx, output);
49 let lloutputtype = type_of(cx, output);
51 atys.push(lloutputtype.ptr_to());
56 atys.push(Type::i8p(cx));
59 // ... then explicit args.
60 let mut input_tys = inputs.iter().map(|&arg_ty| type_of_explicit_arg(cx, arg_ty));
61 atys.extend(&mut input_tys);
63 // Use the output as the actual return value if it's immediate.
64 if use_out_pointer || return_type_is_void(cx, output) {
65 Type::func(atys.as_slice(), &Type::void(cx))
67 Type::func(atys.as_slice(), &lloutputtype)
71 // Given a function type and a count of ty params, construct an llvm type
72 pub fn type_of_fn_from_ty(cx: &CrateContext, fty: ty::t) -> Type {
73 match ty::get(fty).sty {
74 ty::ty_closure(ref f) => {
75 type_of_rust_fn(cx, true, f.sig.inputs.as_slice(), f.sig.output)
77 ty::ty_bare_fn(ref f) => {
78 if f.abis.is_rust() || f.abis.is_intrinsic() {
81 f.sig.inputs.as_slice(),
84 foreign::lltype_for_foreign_fn(cx, fty)
88 cx.sess().bug("type_of_fn_from_ty given non-closure, non-bare-fn")
93 // A "sizing type" is an LLVM type, the size and alignment of which are
94 // guaranteed to be equivalent to what you would get out of `type_of()`. It's
97 // (1) It may be cheaper to compute the sizing type than the full type if all
98 // you're interested in is the size and/or alignment;
100 // (2) It won't make any recursive calls to determine the structure of the
101 // type behind pointers. This can help prevent infinite loops for
102 // recursive types. For example, enum types rely on this behavior.
104 pub fn sizing_type_of(cx: &CrateContext, t: ty::t) -> Type {
106 let llsizingtypes = cx.llsizingtypes.borrow();
107 match llsizingtypes.get().find_copy(&t) {
113 let llsizingty = match ty::get(t).sty {
114 ty::ty_nil | ty::ty_bot => Type::nil(cx),
115 ty::ty_bool => Type::bool(cx),
116 ty::ty_char => Type::char(cx),
117 ty::ty_int(t) => Type::int_from_ty(cx, t),
118 ty::ty_uint(t) => Type::uint_from_ty(cx, t),
119 ty::ty_float(t) => Type::float_from_ty(cx, t),
121 ty::ty_str(ty::vstore_uniq) |
122 ty::ty_vec(_, ty::vstore_uniq) |
126 ty::ty_rptr(..) => Type::i8p(cx),
128 ty::ty_str(ty::vstore_slice(..)) |
129 ty::ty_vec(_, ty::vstore_slice(..)) => {
130 Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false)
133 ty::ty_bare_fn(..) => Type::i8p(cx),
134 ty::ty_closure(..) => Type::struct_(cx, [Type::i8p(cx), Type::i8p(cx)], false),
135 ty::ty_trait(..) => Type::opaque_trait(cx),
137 ty::ty_str(ty::vstore_fixed(size)) => Type::array(&Type::i8(cx), size as u64),
138 ty::ty_vec(mt, ty::vstore_fixed(size)) => {
139 Type::array(&sizing_type_of(cx, mt.ty), size as u64)
142 ty::ty_unboxed_vec(mt) => {
143 Type::vec(cx, &sizing_type_of(cx, mt.ty))
146 ty::ty_tup(..) | ty::ty_enum(..) => {
147 let repr = adt::represent_type(cx, t);
148 adt::sizing_type_of(cx, repr)
151 ty::ty_struct(..) => {
152 if ty::type_is_simd(cx.tcx(), t) {
153 let et = ty::simd_type(cx.tcx(), t);
154 let n = ty::simd_size(cx.tcx(), t);
155 Type::vector(&type_of(cx, et), n as u64)
157 let repr = adt::represent_type(cx, t);
158 adt::sizing_type_of(cx, repr)
162 ty::ty_self(_) | ty::ty_infer(..) | ty::ty_param(..) | ty::ty_err(..) => {
163 cx.sess().bug(format!("fictitious type {:?} in sizing_type_of()",
168 let mut llsizingtypes = cx.llsizingtypes.borrow_mut();
169 llsizingtypes.get().insert(t, llsizingty);
173 // NB: If you update this, be sure to update `sizing_type_of()` as well.
174 pub fn type_of(cx: &CrateContext, t: ty::t) -> Type {
177 let lltypes = cx.lltypes.borrow();
178 match lltypes.get().find(&t) {
179 Some(&llty) => return llty,
184 debug!("type_of {} {:?}", t.repr(cx.tcx()), t);
186 // Replace any typedef'd types with their equivalent non-typedef
187 // type. This ensures that all LLVM nominal types that contain
188 // Rust types are defined as the same LLVM types. If we don't do
189 // this then, e.g. `Option<{myfield: bool}>` would be a different
190 // type than `Option<myrec>`.
191 let t_norm = ty::normalize_ty(cx.tcx(), t);
194 let llty = type_of(cx, t_norm);
195 debug!("--> normalized {} {:?} to {} {:?} llty={}",
198 t_norm.repr(cx.tcx()),
200 cx.tn.type_to_str(llty));
201 let mut lltypes = cx.lltypes.borrow_mut();
202 lltypes.get().insert(t, llty);
206 let mut llty = match ty::get(t).sty {
207 ty::ty_nil | ty::ty_bot => Type::nil(cx),
208 ty::ty_bool => Type::bool(cx),
209 ty::ty_char => Type::char(cx),
210 ty::ty_int(t) => Type::int_from_ty(cx, t),
211 ty::ty_uint(t) => Type::uint_from_ty(cx, t),
212 ty::ty_float(t) => Type::float_from_ty(cx, t),
213 ty::ty_str(ty::vstore_uniq) => {
214 Type::vec(cx, &Type::i8(cx)).ptr_to()
216 ty::ty_enum(did, ref substs) => {
217 // Only create the named struct, but don't fill it in. We
218 // fill it in *after* placing it into the type cache. This
219 // avoids creating more than one copy of the enum when one
220 // of the enum's variants refers to the enum itself.
221 let repr = adt::represent_type(cx, t);
222 let name = llvm_type_name(cx, an_enum, did, substs.tps.as_slice());
223 adt::incomplete_type_of(cx, repr, name)
226 Type::at_box(cx, type_of(cx, typ)).ptr_to()
228 ty::ty_uniq(typ) => {
229 type_of(cx, typ).ptr_to()
231 ty::ty_vec(ref mt, ty::vstore_uniq) => {
232 Type::vec(cx, &type_of(cx, mt.ty)).ptr_to()
234 ty::ty_unboxed_vec(ref mt) => {
235 Type::vec(cx, &type_of(cx, mt.ty))
237 ty::ty_ptr(ref mt) => type_of(cx, mt.ty).ptr_to(),
238 ty::ty_rptr(_, ref mt) => type_of(cx, mt.ty).ptr_to(),
240 ty::ty_vec(ref mt, ty::vstore_slice(_)) => {
241 let p_ty = type_of(cx, mt.ty).ptr_to();
242 let u_ty = Type::uint_from_ty(cx, ast::TyU);
243 Type::struct_(cx, [p_ty, u_ty], false)
246 ty::ty_str(ty::vstore_slice(_)) => {
247 // This means we get a nicer name in the output
248 cx.tn.find_type("str_slice").unwrap()
251 ty::ty_str(ty::vstore_fixed(n)) => {
252 Type::array(&Type::i8(cx), (n + 1u) as u64)
255 ty::ty_vec(ref mt, ty::vstore_fixed(n)) => {
256 Type::array(&type_of(cx, mt.ty), n as u64)
259 ty::ty_bare_fn(_) => {
260 type_of_fn_from_ty(cx, t).ptr_to()
262 ty::ty_closure(_) => {
263 let fn_ty = type_of_fn_from_ty(cx, t).ptr_to();
264 Type::struct_(cx, [fn_ty, Type::i8p(cx)], false)
266 ty::ty_trait(..) => Type::opaque_trait(cx),
268 let repr = adt::represent_type(cx, t);
269 adt::type_of(cx, repr)
271 ty::ty_struct(did, ref substs) => {
272 if ty::type_is_simd(cx.tcx(), t) {
273 let et = ty::simd_type(cx.tcx(), t);
274 let n = ty::simd_size(cx.tcx(), t);
275 Type::vector(&type_of(cx, et), n as u64)
277 // Only create the named struct, but don't fill it in. We fill it
278 // in *after* placing it into the type cache. This prevents
279 // infinite recursion with recursive struct types.
280 let repr = adt::represent_type(cx, t);
281 let name = llvm_type_name(cx,
284 substs.tps.as_slice());
285 adt::incomplete_type_of(cx, repr, name)
288 ty::ty_self(..) => cx.sess().unimpl("type_of: ty_self"),
289 ty::ty_infer(..) => cx.sess().bug("type_of with ty_infer"),
290 ty::ty_param(..) => cx.sess().bug("type_of with ty_param"),
291 ty::ty_err(..) => cx.sess().bug("type_of with ty_err")
294 debug!("--> mapped t={} {:?} to llty={}",
297 cx.tn.type_to_str(llty));
299 let mut lltypes = cx.lltypes.borrow_mut();
300 lltypes.get().insert(t, llty);
303 // If this was an enum or struct, fill in the type now.
304 match ty::get(t).sty {
305 ty::ty_enum(..) | ty::ty_struct(..) if !ty::type_is_simd(cx.tcx(), t) => {
306 let repr = adt::represent_type(cx, t);
307 adt::finish_type_of(cx, repr, &mut llty);
315 // Want refinements! (Or case classes, I guess
316 pub enum named_ty { a_struct, an_enum }
318 pub fn llvm_type_name(cx: &CrateContext,
321 tps: &[ty::t]) -> ~str {
322 let name = match what {
323 a_struct => { "struct" }
324 an_enum => { "enum" }
326 let tstr = ppaux::parameterized(cx.tcx(), ty::item_path_str(cx.tcx(), did),
327 &ty::NonerasedRegions(OwnedSlice::empty()),
330 format!("{}.{}", name, tstr)
332 format!("{}.{}[\\#{}]", name, tstr, did.krate)
336 pub fn type_of_dtor(ccx: &CrateContext, self_ty: ty::t) -> Type {
337 let self_ty = type_of(ccx, self_ty).ptr_to();
338 Type::func([self_ty], &Type::void(ccx))