Skip to content

Commit 5427e58

Browse files
committed
---
yaml --- r: 44541 b: refs/heads/master c: 8d8c25b h: refs/heads/master i: 44539: 8033c2f v: v3
1 parent cfeaca0 commit 5427e58

File tree

5 files changed

+140
-88
lines changed

5 files changed

+140
-88
lines changed

[refs]

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
refs/heads/master: 65aa2594c00ed319ae0f3ba5dfbf4613a0274872
2+
refs/heads/master: 8d8c25b825f109c9ae33ff0e52a061b62ae9f434
33
refs/heads/snap-stage1: e33de59e47c5076a89eadeb38f4934f58a3618a6
44
refs/heads/snap-stage3: a6d9689399d091c3265f00434a69c551a61c28dc
55
refs/heads/try: ef355f6332f83371e4acf04fc4eb940ab41d78d3

trunk/src/librustc/middle/trans/base.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3030,6 +3030,7 @@ pub fn trans_crate(sess: session::Session,
30303030
const_values: HashMap(),
30313031
module_data: HashMap(),
30323032
lltypes: ty::new_ty_hash(),
3033+
llsizingtypes: ty::new_ty_hash(),
30333034
names: new_namegen(sess.parse_sess.interner),
30343035
next_addrspace: new_addrspace_gen(),
30353036
symbol_hasher: symbol_hasher,

trunk/src/librustc/middle/trans/common.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -202,6 +202,7 @@ pub struct crate_ctxt {
202202
const_values: HashMap<ast::node_id, ValueRef>,
203203
module_data: HashMap<~str, ValueRef>,
204204
lltypes: HashMap<ty::t, TypeRef>,
205+
llsizingtypes: HashMap<ty::t, TypeRef>,
205206
names: namegen,
206207
next_addrspace: addrspace_gen,
207208
symbol_hasher: @hash::State,

trunk/src/librustc/middle/trans/machine.rs

Lines changed: 33 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -13,60 +13,8 @@
1313

1414
use middle::trans::common::*;
1515
use middle::trans::type_of;
16-
use middle::ty::field;
1716
use middle::ty;
18-
19-
use syntax::parse::token::special_idents;
20-
21-
// Creates a simpler, size-equivalent type. The resulting type is guaranteed
22-
// to have (a) the same size as the type that was passed in; (b) to be non-
23-
// recursive. This is done by replacing all boxes in a type with boxed unit
24-
// types.
25-
// This should reduce all pointers to some simple pointer type, to
26-
// ensure that we don't recurse endlessly when computing the size of a
27-
// nominal type that has pointers to itself in it.
28-
pub fn simplify_type(tcx: ty::ctxt, typ: ty::t) -> ty::t {
29-
fn nilptr(tcx: ty::ctxt) -> ty::t {
30-
ty::mk_ptr(tcx, ty::mt {ty: ty::mk_nil(tcx), mutbl: ast::m_imm})
31-
}
32-
fn simplifier(tcx: ty::ctxt, typ: ty::t) -> ty::t {
33-
match ty::get(typ).sty {
34-
ty::ty_box(_) | ty::ty_opaque_box | ty::ty_uniq(_) |
35-
ty::ty_evec(_, ty::vstore_uniq) | ty::ty_evec(_, ty::vstore_box) |
36-
ty::ty_estr(ty::vstore_uniq) | ty::ty_estr(ty::vstore_box) |
37-
ty::ty_ptr(_) | ty::ty_rptr(*) => nilptr(tcx),
38-
39-
ty::ty_bare_fn(*) | // FIXME(#4804) Bare fn repr
40-
ty::ty_closure(*) => ty::mk_tup(tcx, ~[nilptr(tcx), nilptr(tcx)]),
41-
42-
ty::ty_evec(_, ty::vstore_slice(_)) |
43-
ty::ty_estr(ty::vstore_slice(_)) => {
44-
ty::mk_tup(tcx, ~[nilptr(tcx), ty::mk_int(tcx)])
45-
}
46-
// Reduce a class type to a record type in which all the fields are
47-
// simplified
48-
ty::ty_struct(did, ref substs) => {
49-
let simpl_fields = (if ty::ty_dtor(tcx, did).is_present() {
50-
// remember the drop flag
51-
~[field {
52-
ident: special_idents::dtor,
53-
mt: ty::mt {ty: ty::mk_u8(tcx), mutbl: ast::m_mutbl}
54-
}] }
55-
else { ~[] }) +
56-
do ty::lookup_struct_fields(tcx, did).map |f| {
57-
let t = ty::lookup_field_type(tcx, did, f.id, substs);
58-
field {
59-
ident: f.ident,
60-
mt: ty::mt {ty: simplify_type(tcx, t), mutbl: ast::m_const
61-
}}
62-
};
63-
ty::mk_rec(tcx, simpl_fields)
64-
}
65-
_ => typ
66-
}
67-
}
68-
ty::fold_ty(tcx, typ, |t| simplifier(tcx, t))
69-
}
17+
use util::ppaux::ty_to_str;
7018

7119
// ______________________________________________________________________
7220
// compute sizeof / alignof
@@ -180,27 +128,40 @@ pub fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
180128

181129
// Computes the size of the data part of an enum.
182130
pub fn static_size_of_enum(cx: @crate_ctxt, t: ty::t) -> uint {
183-
if cx.enum_sizes.contains_key(&t) { return cx.enum_sizes.get(&t); }
131+
if cx.enum_sizes.contains_key(&t) {
132+
return cx.enum_sizes.get(&t);
133+
}
134+
135+
debug!("static_size_of_enum %s", ty_to_str(cx.tcx, t));
136+
184137
match ty::get(t).sty {
185-
ty::ty_enum(tid, ref substs) => {
186-
// Compute max(variant sizes).
187-
let mut max_size = 0u;
188-
let variants = ty::enum_variants(cx.tcx, tid);
189-
for vec::each(*variants) |variant| {
190-
let tup_ty = simplify_type(
191-
cx.tcx,
192-
ty::mk_tup(cx.tcx, /*bad*/copy variant.args));
193-
// Perform any type parameter substitutions.
194-
let tup_ty = ty::subst(cx.tcx, substs, tup_ty);
195-
// Here we possibly do a recursive call.
196-
let this_size =
197-
llsize_of_real(cx, type_of::type_of(cx, tup_ty));
198-
if max_size < this_size { max_size = this_size; }
138+
ty::ty_enum(tid, ref substs) => {
139+
// Compute max(variant sizes).
140+
let mut max_size = 0;
141+
let variants = ty::enum_variants(cx.tcx, tid);
142+
for variants.each |variant| {
143+
if variant.args.len() == 0 {
144+
loop;
145+
}
146+
147+
let lltypes = variant.args.map(|&variant_arg| {
148+
let substituted = ty::subst(cx.tcx, substs, variant_arg);
149+
type_of::sizing_type_of(cx, substituted)
150+
});
151+
152+
debug!("static_size_of_enum: variant %s type %s",
153+
cx.tcx.sess.str_of(variant.name),
154+
ty_str(cx.tn, T_struct(lltypes)));
155+
156+
let this_size = llsize_of_real(cx, T_struct(lltypes));
157+
if max_size < this_size {
158+
max_size = this_size;
159+
}
160+
}
161+
cx.enum_sizes.insert(t, max_size);
162+
return max_size;
199163
}
200-
cx.enum_sizes.insert(t, max_size);
201-
return max_size;
202-
}
203-
_ => cx.sess.bug(~"static_size_of_enum called on non-enum")
164+
_ => cx.sess.bug(~"static_size_of_enum called on non-enum")
204165
}
205166
}
206167

trunk/src/librustc/middle/trans/type_of.rs

Lines changed: 104 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,95 @@ pub fn type_of_non_gc_box(cx: @crate_ctxt, t: ty::t) -> TypeRef {
8989
}
9090
}
9191

92+
// A "sizing type" is an LLVM type, the size and alignment of which are
93+
// guaranteed to be equivalent to what you would get out of `type_of()`. It's
94+
// useful because:
95+
//
96+
// (1) It may be cheaper to compute the sizing type than the full type if all
97+
// you're interested in is the size and/or alignment;
98+
//
99+
// (2) It won't make any recursive calls to determine the structure of the
100+
// type behind pointers. This can help prevent infinite loops for
101+
// recursive types. For example, `static_size_of_enum()` relies on this
102+
// behavior.
103+
104+
pub fn sizing_type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
105+
if cx.llsizingtypes.contains_key(&t) {
106+
return cx.llsizingtypes.get(&t);
107+
}
108+
109+
let llsizingty = match ty::get(t).sty {
110+
ty::ty_nil | ty::ty_bot => T_nil(),
111+
ty::ty_bool => T_bool(),
112+
ty::ty_int(t) => T_int_ty(cx, t),
113+
ty::ty_uint(t) => T_uint_ty(cx, t),
114+
ty::ty_float(t) => T_float_ty(cx, t),
115+
116+
ty::ty_estr(ty::vstore_uniq) |
117+
ty::ty_estr(ty::vstore_box) |
118+
ty::ty_evec(_, ty::vstore_uniq) |
119+
ty::ty_evec(_, ty::vstore_box) |
120+
ty::ty_box(*) |
121+
ty::ty_opaque_box |
122+
ty::ty_uniq(*) |
123+
ty::ty_ptr(*) |
124+
ty::ty_rptr(*) |
125+
ty::ty_type |
126+
ty::ty_opaque_closure_ptr(*) => T_ptr(T_i8()),
127+
128+
ty::ty_estr(ty::vstore_slice(*)) |
129+
ty::ty_evec(_, ty::vstore_slice(*)) => {
130+
T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())])
131+
}
132+
133+
// FIXME(#4804) Bare fn repr
134+
ty::ty_bare_fn(*) => T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())]),
135+
ty::ty_closure(*) => T_struct(~[T_ptr(T_i8()), T_ptr(T_i8())]),
136+
ty::ty_trait(_, _, vstore) => T_opaque_trait(cx, vstore),
137+
138+
ty::ty_estr(ty::vstore_fixed(size)) => T_array(T_i8(), size),
139+
ty::ty_evec(mt, ty::vstore_fixed(size)) => {
140+
T_array(sizing_type_of(cx, mt.ty), size)
141+
}
142+
143+
ty::ty_unboxed_vec(mt) => T_vec(cx, sizing_type_of(cx, mt.ty)),
144+
145+
ty::ty_tup(ref elems) => {
146+
T_struct(elems.map(|&t| sizing_type_of(cx, t)))
147+
}
148+
149+
ty::ty_rec(ref fields) => {
150+
T_struct(fields.map(|f| sizing_type_of(cx, f.mt.ty)))
151+
}
152+
153+
ty::ty_struct(def_id, ref substs) => {
154+
let fields = ty::lookup_struct_fields(cx.tcx, def_id);
155+
let lltype = T_struct(fields.map(|field| {
156+
let field_type = ty::lookup_field_type(cx.tcx,
157+
def_id,
158+
field.id,
159+
substs);
160+
sizing_type_of(cx, field_type)
161+
}));
162+
if ty::ty_dtor(cx.tcx, def_id).is_present() {
163+
T_struct(~[lltype, T_i8()])
164+
} else {
165+
lltype
166+
}
167+
}
168+
169+
ty::ty_enum(def_id, _) => T_struct(enum_body_types(cx, def_id, t)),
170+
171+
ty::ty_self | ty::ty_infer(*) | ty::ty_param(*) | ty::ty_err(*) => {
172+
cx.tcx.sess.bug(~"fictitious type in sizing_type_of()")
173+
}
174+
};
175+
176+
cx.llsizingtypes.insert(t, llsizingty);
177+
llsizingty
178+
}
179+
180+
// NB: If you update this, be sure to update `sizing_type_of()` as well.
92181
pub fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
93182
debug!("type_of %?: %?", t, ty::get(t));
94183

@@ -236,23 +325,23 @@ pub fn type_of(cx: @crate_ctxt, t: ty::t) -> TypeRef {
236325
return llty;
237326
}
238327

239-
pub fn fill_type_of_enum(cx: @crate_ctxt, did: ast::def_id, t: ty::t,
240-
llty: TypeRef) {
328+
pub fn enum_body_types(cx: @crate_ctxt, did: ast::def_id, t: ty::t)
329+
-> ~[TypeRef] {
330+
let univar = ty::enum_is_univariant(cx.tcx, did);
331+
let size = machine::static_size_of_enum(cx, t);
332+
if !univar {
333+
~[T_enum_discrim(cx), T_array(T_i8(), size)]
334+
} else {
335+
~[T_array(T_i8(), size)]
336+
}
337+
}
241338

339+
pub fn fill_type_of_enum(cx: @crate_ctxt,
340+
did: ast::def_id,
341+
t: ty::t,
342+
llty: TypeRef) {
242343
debug!("type_of_enum %?: %?", t, ty::get(t));
243-
244-
let lltys = {
245-
let univar = ty::enum_is_univariant(cx.tcx, did);
246-
let size = machine::static_size_of_enum(cx, t);
247-
if !univar {
248-
~[T_enum_discrim(cx), T_array(T_i8(), size)]
249-
}
250-
else {
251-
~[T_array(T_i8(), size)]
252-
}
253-
};
254-
255-
common::set_struct_body(llty, lltys);
344+
common::set_struct_body(llty, enum_body_types(cx, did, t));
256345
}
257346

258347
// Want refinements! (Or case classes, I guess

0 commit comments

Comments
 (0)