rustc: Remove most of the code that generates shapes
This commit is contained in:
parent
a66e23d236
commit
42b6037297
|
@ -215,379 +215,3 @@ fn add_substr(&dest: ~[u8], src: ~[u8]) {
|
|||
dest += src;
|
||||
}
|
||||
|
||||
fn shape_of(ccx: @crate_ctxt, t: ty::t) -> ~[u8] {
|
||||
match ty::get(t).sty {
|
||||
ty::ty_nil | ty::ty_bool | ty::ty_uint(ast::ty_u8) |
|
||||
ty::ty_bot => ~[shape_u8],
|
||||
ty::ty_int(ast::ty_i) => ~[s_int(ccx.tcx)],
|
||||
ty::ty_float(ast::ty_f) => ~[s_float(ccx.tcx)],
|
||||
ty::ty_uint(ast::ty_u) | ty::ty_ptr(_) => ~[s_uint(ccx.tcx)],
|
||||
ty::ty_type => ~[s_tydesc(ccx.tcx)],
|
||||
ty::ty_int(ast::ty_i8) => ~[shape_i8],
|
||||
ty::ty_uint(ast::ty_u16) => ~[shape_u16],
|
||||
ty::ty_int(ast::ty_i16) => ~[shape_i16],
|
||||
ty::ty_uint(ast::ty_u32) => ~[shape_u32],
|
||||
ty::ty_int(ast::ty_i32) | ty::ty_int(ast::ty_char) => ~[shape_i32],
|
||||
ty::ty_uint(ast::ty_u64) => ~[shape_u64],
|
||||
ty::ty_int(ast::ty_i64) => ~[shape_i64],
|
||||
ty::ty_float(ast::ty_f32) => ~[shape_f32],
|
||||
ty::ty_float(ast::ty_f64) => ~[shape_f64],
|
||||
ty::ty_estr(ty::vstore_uniq) => {
|
||||
shape_of(ccx, tvec::expand_boxed_vec_ty(ccx.tcx, t))
|
||||
}
|
||||
ty::ty_enum(did, substs) => {
|
||||
match enum_kind(ccx, did) {
|
||||
tk_unit => ~[s_variant_enum_t(ccx.tcx)],
|
||||
tk_enum => ~[s_variant_enum_t(ccx.tcx)],
|
||||
tk_newtype | tk_complex => {
|
||||
let mut s = ~[shape_enum], id;
|
||||
let nom_id = mk_nominal_id(ccx.tcx, did,
|
||||
None, substs.tps);
|
||||
match ccx.shape_cx.tag_id_to_index.find(nom_id) {
|
||||
None => {
|
||||
id = ccx.shape_cx.next_tag_id;
|
||||
ccx.shape_cx.tag_id_to_index.insert(nom_id, id);
|
||||
ccx.shape_cx.tag_order.push({did: did,
|
||||
substs: substs});
|
||||
ccx.shape_cx.next_tag_id += 1u16;
|
||||
}
|
||||
Some(existing_id) => id = existing_id,
|
||||
}
|
||||
add_u16(s, id as u16);
|
||||
|
||||
s
|
||||
}
|
||||
}
|
||||
}
|
||||
ty::ty_estr(ty::vstore_box) |
|
||||
ty::ty_evec(_, ty::vstore_box) |
|
||||
ty::ty_box(_) | ty::ty_opaque_box => ~[shape_box],
|
||||
ty::ty_uniq(mt) => {
|
||||
let mut s = ~[shape_uniq];
|
||||
add_substr(s, shape_of(ccx, mt.ty));
|
||||
s
|
||||
}
|
||||
ty::ty_unboxed_vec(mt) => {
|
||||
let mut s = ~[shape_unboxed_vec];
|
||||
add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty));
|
||||
add_substr(s, shape_of(ccx, mt.ty));
|
||||
s
|
||||
}
|
||||
ty::ty_evec(_, ty::vstore_uniq) => {
|
||||
shape_of(ccx, tvec::expand_boxed_vec_ty(ccx.tcx, t))
|
||||
}
|
||||
|
||||
ty::ty_estr(ty::vstore_fixed(n)) => {
|
||||
let mut s = ~[shape_fixedvec];
|
||||
let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8);
|
||||
assert (n + 1u) <= 0xffffu;
|
||||
add_u16(s, (n + 1u) as u16);
|
||||
add_bool(s, true);
|
||||
add_substr(s, shape_of(ccx, u8_t));
|
||||
s
|
||||
}
|
||||
|
||||
ty::ty_evec(mt, ty::vstore_fixed(n)) => {
|
||||
let mut s = ~[shape_fixedvec];
|
||||
assert n <= 0xffffu;
|
||||
add_u16(s, n as u16);
|
||||
add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty));
|
||||
add_substr(s, shape_of(ccx, mt.ty));
|
||||
s
|
||||
}
|
||||
|
||||
ty::ty_estr(ty::vstore_slice(_)) => {
|
||||
let mut s = ~[shape_slice];
|
||||
let u8_t = ty::mk_mach_uint(ccx.tcx, ast::ty_u8);
|
||||
add_bool(s, true); // is_pod
|
||||
add_bool(s, true); // is_str
|
||||
add_substr(s, shape_of(ccx, u8_t));
|
||||
s
|
||||
}
|
||||
|
||||
ty::ty_evec(mt, ty::vstore_slice(_)) => {
|
||||
let mut s = ~[shape_slice];
|
||||
add_bool(s, ty::type_is_pod(ccx.tcx, mt.ty));
|
||||
add_bool(s, false); // is_str
|
||||
add_substr(s, shape_of(ccx, mt.ty));
|
||||
s
|
||||
}
|
||||
|
||||
ty::ty_rec(fields) => {
|
||||
let mut s = ~[shape_struct], sub = ~[];
|
||||
for vec::each(fields) |f| {
|
||||
sub += shape_of(ccx, f.mt.ty);
|
||||
}
|
||||
add_substr(s, sub);
|
||||
s
|
||||
}
|
||||
ty::ty_tup(elts) => {
|
||||
let mut s = ~[shape_struct], sub = ~[];
|
||||
for vec::each(elts) |elt| {
|
||||
sub += shape_of(ccx, *elt);
|
||||
}
|
||||
add_substr(s, sub);
|
||||
s
|
||||
}
|
||||
ty::ty_trait(_, _, _) => ~[shape_box_fn],
|
||||
ty::ty_class(did, ref substs) => {
|
||||
// same as records, unless there's a dtor
|
||||
let tps = substs.tps;
|
||||
let m_dtor_did = ty::ty_dtor(ccx.tcx, did);
|
||||
let mut s = if m_dtor_did.is_some() {
|
||||
~[shape_res]
|
||||
}
|
||||
else { ~[shape_struct] }, sub = ~[];
|
||||
do m_dtor_did.iter |dtor_did| {
|
||||
let ri = @{did: dtor_did, parent_id: Some(did), tps: tps};
|
||||
let id = ccx.shape_cx.resources.intern(ri);
|
||||
add_u16(s, id as u16);
|
||||
};
|
||||
for ty::class_items_as_mutable_fields(ccx.tcx, did,
|
||||
substs).each |f| {
|
||||
sub += shape_of(ccx, f.mt.ty);
|
||||
}
|
||||
add_substr(s, sub);
|
||||
s
|
||||
}
|
||||
ty::ty_rptr(_, mt) => {
|
||||
let mut s = ~[shape_rptr];
|
||||
add_substr(s, shape_of(ccx, mt.ty));
|
||||
s
|
||||
}
|
||||
ty::ty_param(*) => {
|
||||
ccx.tcx.sess.bug(~"non-monomorphized type parameter");
|
||||
}
|
||||
ty::ty_fn(ref fn_ty) => {
|
||||
match fn_ty.meta.proto {
|
||||
ty::proto_vstore(ty::vstore_box) => ~[shape_box_fn],
|
||||
ty::proto_vstore(ty::vstore_uniq) => ~[shape_uniq_fn],
|
||||
ty::proto_vstore(ty::vstore_slice(_)) => ~[shape_stack_fn],
|
||||
ty::proto_bare => ~[shape_bare_fn],
|
||||
ty::proto_vstore(ty::vstore_fixed(_)) =>
|
||||
fail ~"fixed vstore is impossible",
|
||||
}
|
||||
}
|
||||
ty::ty_opaque_closure_ptr(_) => ~[shape_opaque_closure_ptr],
|
||||
ty::ty_infer(_) | ty::ty_self => {
|
||||
ccx.sess.bug(~"shape_of: unexpected type struct found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn shape_of_variant(ccx: @crate_ctxt, v: ty::variant_info) -> ~[u8] {
|
||||
let mut s = ~[];
|
||||
for vec::each(v.args) |t| { s += shape_of(ccx, *t); }
|
||||
return s;
|
||||
}
|
||||
|
||||
fn gen_enum_shapes(ccx: @crate_ctxt) -> ValueRef {
|
||||
// Loop over all the enum variants and write their shapes into a
|
||||
// data buffer. As we do this, it's possible for us to discover
|
||||
// new enums, so we must do this first.
|
||||
let mut data = ~[];
|
||||
let mut offsets = ~[];
|
||||
let mut i = 0u;
|
||||
let mut enum_variants = ~[];
|
||||
while i < ccx.shape_cx.tag_order.len() {
|
||||
let {did, substs} = ccx.shape_cx.tag_order[i];
|
||||
let variants = @ty::substd_enum_variants(ccx.tcx, did, &substs);
|
||||
for vec::each(*variants) |v| {
|
||||
offsets += ~[vec::len(data) as u16];
|
||||
|
||||
let variant_shape = shape_of_variant(ccx, *v);
|
||||
add_substr(data, variant_shape);
|
||||
|
||||
let zname = str::to_bytes(ccx.sess.str_of(v.name)) + ~[0u8];
|
||||
add_substr(data, zname);
|
||||
}
|
||||
enum_variants += ~[variants];
|
||||
i += 1u;
|
||||
}
|
||||
|
||||
// Now calculate the sizes of the header space (which contains offsets to
|
||||
// info records for each enum) and the info space (which contains offsets
|
||||
// to each variant shape). As we do so, build up the header.
|
||||
|
||||
let mut header = ~[];
|
||||
let mut inf = ~[];
|
||||
let header_sz = 2u16 * ccx.shape_cx.next_tag_id;
|
||||
let data_sz = vec::len(data) as u16;
|
||||
|
||||
let mut inf_sz = 0u16;
|
||||
for enum_variants.each |variants| {
|
||||
let num_variants = vec::len(**variants) as u16;
|
||||
add_u16(header, header_sz + inf_sz);
|
||||
inf_sz += 2u16 * (num_variants + 2u16) + 3u16;
|
||||
}
|
||||
|
||||
// Construct the info tables, which contain offsets to the shape of each
|
||||
// variant. Also construct the largest-variant table for each enum, which
|
||||
// contains the variants that the size-of operation needs to look at.
|
||||
|
||||
let mut lv_table = ~[];
|
||||
let mut i = 0u;
|
||||
for enum_variants.each |variants| {
|
||||
add_u16(inf, vec::len(**variants) as u16);
|
||||
|
||||
// Construct the largest-variants table.
|
||||
add_u16(inf,
|
||||
header_sz + inf_sz + data_sz + (vec::len(lv_table) as u16));
|
||||
|
||||
let lv = largest_variants(ccx, *variants);
|
||||
add_u16(lv_table, vec::len(lv) as u16);
|
||||
for vec::each(lv) |v| { add_u16(lv_table, *v as u16); }
|
||||
|
||||
// Determine whether the enum has dynamic size.
|
||||
assert !variants.any(|v| v.args.any(|t| ty::type_has_params(t)));
|
||||
|
||||
// If we can, write in the static size and alignment of the enum.
|
||||
// Otherwise, write a placeholder.
|
||||
let size_align = compute_static_enum_size(ccx, lv, *variants);
|
||||
|
||||
// Write in the static size and alignment of the enum.
|
||||
add_u16(inf, size_align.size);
|
||||
inf += ~[size_align.align];
|
||||
|
||||
// Now write in the offset of each variant.
|
||||
for variants.each |_v| {
|
||||
add_u16(inf, header_sz + inf_sz + offsets[i]);
|
||||
i += 1u;
|
||||
}
|
||||
}
|
||||
|
||||
assert (i == vec::len(offsets));
|
||||
assert (header_sz == vec::len(header) as u16);
|
||||
assert (inf_sz == vec::len(inf) as u16);
|
||||
assert (data_sz == vec::len(data) as u16);
|
||||
|
||||
header += inf;
|
||||
header += data;
|
||||
header += lv_table;
|
||||
|
||||
return mk_global(ccx, ~"tag_shapes", C_bytes(header), true);
|
||||
|
||||
/* tjc: Not annotating FIXMEs in this module because of #1498 */
|
||||
fn largest_variants(ccx: @crate_ctxt,
|
||||
variants: @~[ty::variant_info]) -> ~[uint] {
|
||||
// Compute the minimum and maximum size and alignment for each
|
||||
// variant.
|
||||
//
|
||||
// NB: We could do better here; e.g. we know that any
|
||||
// variant that contains (T,T) must be as least as large as
|
||||
// any variant that contains just T.
|
||||
let mut ranges = ~[];
|
||||
for vec::each(*variants) |variant| {
|
||||
let mut bounded = true;
|
||||
let mut min_size = 0u, min_align = 0u;
|
||||
for vec::each(variant.args) |elem_t| {
|
||||
if ty::type_has_params(*elem_t) {
|
||||
// NB: We could do better here; this causes us to
|
||||
// conservatively assume that (int, T) has minimum size 0,
|
||||
// when in fact it has minimum size sizeof(int).
|
||||
bounded = false;
|
||||
} else {
|
||||
let llty = type_of::type_of(ccx, *elem_t);
|
||||
min_size += llsize_of_real(ccx, llty);
|
||||
min_align += llalign_of_pref(ccx, llty);
|
||||
}
|
||||
}
|
||||
|
||||
ranges +=
|
||||
~[{size: {min: min_size, bounded: bounded},
|
||||
align: {min: min_align, bounded: bounded}}];
|
||||
}
|
||||
|
||||
// Initialize the candidate set to contain all variants.
|
||||
let mut candidates = ~[mut];
|
||||
for vec::each(*variants) |_v| { candidates += ~[mut true]; }
|
||||
|
||||
// Do a pairwise comparison among all variants still in the
|
||||
// candidate set. Throw out any variant that we know has size
|
||||
// and alignment at least as small as some other variant.
|
||||
let mut i = 0u;
|
||||
while i < vec::len(ranges) - 1u {
|
||||
if candidates[i] {
|
||||
let mut j = i + 1u;
|
||||
while j < vec::len(ranges) {
|
||||
if candidates[j] {
|
||||
if ranges[i].size.bounded &&
|
||||
ranges[i].align.bounded &&
|
||||
ranges[j].size.bounded &&
|
||||
ranges[j].align.bounded {
|
||||
if ranges[i].size.min >= ranges[j].size.min &&
|
||||
ranges[i].align.min >= ranges[j].align.min {
|
||||
// Throw out j.
|
||||
candidates[j] = false;
|
||||
} else if ranges[j].size.min >=
|
||||
ranges[i].size.min &&
|
||||
ranges[j].align.min >=
|
||||
ranges[j].align.min {
|
||||
// Throw out i.
|
||||
candidates[i] = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
j += 1u;
|
||||
}
|
||||
}
|
||||
i += 1u;
|
||||
}
|
||||
|
||||
// Return the resulting set.
|
||||
let mut result = ~[];
|
||||
let mut i = 0u;
|
||||
while i < vec::len(candidates) {
|
||||
if candidates[i] { vec::push(result, i); }
|
||||
i += 1u;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
fn compute_static_enum_size(ccx: @crate_ctxt, largest_variants: ~[uint],
|
||||
variants: @~[ty::variant_info])
|
||||
-> size_align {
|
||||
let mut max_size = 0u16;
|
||||
let mut max_align = 1u8;
|
||||
for vec::each(largest_variants) |vid| {
|
||||
// We increment a "virtual data pointer" to compute the size.
|
||||
let mut lltys = ~[];
|
||||
for vec::each(variants[*vid].args) |typ| {
|
||||
lltys += ~[type_of::type_of(ccx, *typ)];
|
||||
}
|
||||
|
||||
let llty = trans::common::T_struct(lltys);
|
||||
let dp = llsize_of_real(ccx, llty) as u16;
|
||||
let variant_align = llalign_of_pref(ccx, llty) as u8;
|
||||
|
||||
if max_size < dp { max_size = dp; }
|
||||
if max_align < variant_align { max_align = variant_align; }
|
||||
}
|
||||
|
||||
// Add space for the enum if applicable.
|
||||
// FIXME (issue #792): This is wrong. If the enum starts with an
|
||||
// 8 byte aligned quantity, we don't align it.
|
||||
if vec::len(*variants) > 1u {
|
||||
let variant_t = T_enum_discrim(ccx);
|
||||
max_size += llsize_of_real(ccx, variant_t) as u16;
|
||||
let align = llalign_of_pref(ccx, variant_t) as u8;
|
||||
if max_align < align { max_align = align; }
|
||||
}
|
||||
|
||||
return {size: max_size, align: max_align};
|
||||
}
|
||||
}
|
||||
|
||||
fn gen_resource_shapes(ccx: @crate_ctxt) -> ValueRef {
|
||||
let mut dtors = ~[];
|
||||
let len = ccx.shape_cx.resources.len();
|
||||
for uint::range(0u, len) |i| {
|
||||
let ri = ccx.shape_cx.resources.get(i);
|
||||
for ri.tps.each() |s| { assert !ty::type_has_params(*s); }
|
||||
do ri.parent_id.iter |id| {
|
||||
dtors += ~[trans::base::get_res_dtor(ccx, ri.did, id, ri.tps)];
|
||||
}
|
||||
}
|
||||
return mk_global(ccx, ~"resource_shapes", C_struct(dtors), true);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue