collapse sizeof, alignof into metrics, pass along an instance if avail

This commit is contained in:
Niko Matsakis 2012-01-05 12:05:22 -08:00
parent 4f52e5a5ec
commit 7db640e63d
3 changed files with 78 additions and 47 deletions

View File

@ -414,14 +414,26 @@ fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
False);
}
fn size_of(cx: @block_ctxt, t: ty::t) -> result {
let {bcx, sz, align} = metrics(cx, t, none);
rslt(bcx, align)
fn size_of(bcx: @block_ctxt, t: ty::t) -> result {
assert !ty::type_has_opaque_size(bcx_tcx(bcx), t);
let {bcx, sz, align: _} = metrics(bcx, t, none);
rslt(bcx, sz)
}
fn align_of(cx: @block_ctxt, t: ty::t) -> result {
let {bcx, sz, align} = metrics(cx, t, none);
rslt(bcx, align)
fn align_of(bcx: @block_ctxt, t: ty::t) -> result {
assert !ty::type_has_opaque_size(bcx_tcx(bcx), t);
alt ty::struct(ccx.tcx, t) {
ty::ty_opaque_closure. {
// Hack: the alignment of an opaque closure is always defined as the
// alignment of a pointer. This is not, however, strictly correct,
// depending on your point of view.
llalign_of(bcx, T_ptr(T_i8()));
}
_ {
let {bcx, sz: _, align} = metrics(bcx, t, none);
rslt(bcx, align)
}
}
}
// Computes the size/alignment of the type `t`. `opt_v`, if provided, should
@ -431,11 +443,13 @@ fn align_of(cx: @block_ctxt, t: ty::t) -> result {
// instance is required.
fn metrics(bcx: @block_ctxt, t: ty::t, opt_v: option<ValueRef>)
-> metrics_result {
let ccx = bcx_ccx(cx);
assert (option::is_some(opt_v) ||
!ty::type_has_opaque_size(bcx_tcx(bcx), t));
let ccx = bcx_ccx(bcx);
if check type_has_static_size(ccx, t) {
let sp = cx.sp;
let sz = llsize_of(bcx_ccx(cx), type_of(ccx, sp, t));
let align = llalign_of(bcx_ccx(cx), type_of(ccx, sp, t));
let sp = bcx.sp;
let sz = llsize_of(bcx_ccx(bcx), type_of(ccx, sp, t));
let align = llalign_of(bcx_ccx(bcx), type_of(ccx, sp, t));
ret {bcx: bcx, sz: sz, align: align};
} else {
ret dynamic_metrics(bcx, t, opt_v);
@ -552,11 +566,11 @@ type metrics_result = {
};
fn dynamic_metrics(bcx: @block_ctxt,
elts: [ty::t],
opts_v: option<ValueRef>) -> metrics_result {
fn compute_elements_metrics(bcx: @block_ctxt,
elts: [ty::t],
opt_v: option<ValueRef>) -> metrics_result {
t: ty::t,
opt_v: option<ValueRef>) -> metrics_result {
fn c_struct_metrics(bcx: @block_ctxt,
elts: [ty::t],
opt_v: option<ValueRef>) -> metrics_result {
//
// C padding rules:
//
@ -570,40 +584,40 @@ fn dynamic_metrics(bcx: @block_ctxt,
let max_align = C_int(bcx_ccx(bcx), 1);
for e: ty::t in elts {
let opt_ev = option::map(opt_v) {|v| ptr_offs(bcx, v, off) };
let elt_align = align_of(bcx, e, opt_ev);
bcx = elt_align.bcx;
let elt_size = size_of(bcx, e, opt_ev);
bcx = elt_size.bcx;
let aligned_off = align_to(bcx, off, elt_align.val);
off = Add(bcx, aligned_off, elt_size.val);
max_align = umax(bcx, max_align, elt_align.val);
let elt_metrics = metrics(bcx, e, opt_ev);
bcx = elt_metrics.bcx;
let aligned_off = align_to(bcx, off, elt_metrics.align);
off = Add(bcx, aligned_off, elt_metrics.sz);
max_align = umax(bcx, max_align, elt_metrics.align);
}
off = align_to(bcx, off, max_align);
ret { bcx: bcx, sz: off, align: max_align };
}
alt ty::struct(bcx_tcx(bcx), t) {
ty::ty_param(p, _) {
let {bcx, value: szptr} =
field_of_tydesc(bcx, t, false, abi::tydesc_field_size);
let {bcx, value: aptr} =
field_of_tydesc(bcx, t, false, abi::tydesc_field_align);
ret { bcx: bcx, sz: Load(szptr), align: Load(align) };
let ti = none::<@tydesc_info>;
let {bcx, val: tydesc} =
get_tydesc(bcx, t, false, tps_normal, ti).result;
let sz = Load(bcx, GEPi(bcx, tydesc, [0, abi::tydesc_field_size]));
let al = Load(bcx, GEPi(bcx, tydesc, [0, abi::tydesc_field_align]));
ret { bcx: bcx, sz: sz, align: al };
}
ty::ty_rec(flds) {
let tys: [ty::t] = [];
for f: ty::field in flds { tys += [f.mt.ty]; }
ret compute_elements_metrics(bcx, tys, opt_v);
ret c_struct_metrics(bcx, tys, opt_v);
}
ty::ty_tup(elts) {
let tys = [];
for tp in elts { tys += [tp]; }
ret compute_elements_metrics(bcx, tys, opt_v);
ret c_struct_metrics(bcx, tys, opt_v);
}
ty::ty_tag(tid, tps) {
let bcx = bcx;
let ccx = bcx_ccx(bcx);
// Compute max(variant sizes) and max(variant alignments).
// Compute max(variant sizes) and max(variant alignments).
let max_size: ValueRef = alloca(bcx, ccx.int_type);
Store(bcx, C_int(ccx, 0), max_size);
let variants = ty::tag_variants(bcx_tcx(bcx), tid);
@ -616,9 +630,16 @@ fn dynamic_metrics(bcx: @block_ctxt,
let t = ty::substitute_type_params(bcx_tcx(bcx), tps, raw_ty);
tys += [t];
}
let rslt = align_elements(bcx, tys, opt_v);
// Note: we do not pass in opt_v here for the value but rather
// none. The reason is that what we would want to pass in is a
// ptr to the blob data of the tag, but this is impossible until
// we know the size/alignment of the blob data. Therefore, it is
// not legal to have a tag type that contains an interior opaque
// type. Fortunately this will never happen.
let rslt = c_struct_metrics(bcx, tys, none);
bcx = rslt.bcx;
let this_size = rslt.val;
let this_size = rslt.sz;
let old_max_size = Load(bcx, max_size);
Store(bcx, umax(bcx, this_size, old_max_size), max_size);
}
@ -651,7 +672,7 @@ fn dynamic_metrics(bcx: @block_ctxt,
let tdptr = Load(bcx, tdptrptr);
let sz = Load(bcx, GEPi(bcx, tdptr, [0, abi::tydesc_field_size]));
let align = Load(bcx, GEPi(bcx, tdptr, [0, abi::tydesc_field_align]));
ret { bcx: bcx, sz: sz, align: sz };
ret { bcx: bcx, sz: sz, align: align };
}
}
}
@ -661,7 +682,7 @@ fn dynamic_metrics(bcx: @block_ctxt,
// return type, use bump_ptr().
fn ptr_offs(bcx: @block_ctxt, base: ValueRef, sz: ValueRef) -> ValueRef {
let raw = PointerCast(bcx, base, T_ptr(T_i8()));
GEP(bcx, raw, [sz]);
GEP(bcx, raw, [sz])
}
// Increment a pointer by a given amount and then cast it to be a pointer
@ -760,7 +781,7 @@ fn GEP_tup_like(bcx: @block_ctxt, t: ty::t, base: ValueRef, ixs: [int])
let args = [];
for typ: ty::t in s.prefix { args += [typ]; }
let prefix_ty = ty::mk_tup(bcx_tcx(bcx), args);
let {bcx, val: prefix_sz} = size_of(bcx, prefix_ty);
let {bcx, sz: prefix_sz, align: _} = metrics(bcx, prefix_ty, some(base));
let {bcx, val: align} = align_of(bcx, s.target);
let sz = align_to(bcx, prefix_sz, align);
ret rslt(bcx, bump_ptr(bcx, s.target, base, sz));
@ -898,7 +919,6 @@ fn field_of_tydesc(cx: @block_ctxt, t: ty::t, escapes: bool, field: int) ->
GEPi(tydesc.bcx, tydesc.val, [0, field]));
}
// Given a type containing ty params, build a vector containing a ValueRef for
// each of the ty params it uses (from the current frame) and a vector of the
// indices of the ty params present in the type. This is used solely for
@ -2003,21 +2023,21 @@ fn call_bzero(cx: @block_ctxt, dst: ValueRef, n_bytes: ValueRef,
Call(cx, memset, [dst_ptr, C_u8(0u), size, align, volatile]));
}
fn memmove_ty(cx: @block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t) ->
fn memmove_ty(bcx: @block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t) ->
@block_ctxt {
let ccx = bcx_ccx(cx);
let ccx = bcx_ccx(bcx);
if check type_has_static_size(ccx, t) {
if ty::type_is_structural(bcx_tcx(cx), t) {
let sp = cx.sp;
if ty::type_is_structural(bcx_tcx(bcx), t) {
let sp = bcx.sp;
let llsz = llsize_of(ccx, type_of(ccx, sp, t));
ret call_memmove(cx, dst, src, llsz).bcx;
ret call_memmove(bcx, dst, src, llsz).bcx;
}
Store(cx, Load(cx, src), dst);
ret cx;
Store(bcx, Load(bcx, src), dst);
ret bcx;
}
let llsz = size_of(cx, t);
ret call_memmove(llsz.bcx, dst, src, llsz.val).bcx;
let {bcx, sz: llsz, align: _} = metrics(bcx, t, some(src));
ret call_memmove(bcx, dst, src, llsz).bcx;
}
tag copy_action { INIT; DROP_EXISTING; }

View File

@ -5,6 +5,7 @@ import trans_build::*;
import trans::{
trans_shared_malloc,
type_of_inner,
metrics,
size_of,
node_id_type,
INIT,
@ -39,7 +40,7 @@ fn alloc_uniq(cx: @block_ctxt, uniq_ty: ty::t)
}
fn alloc_uniq_(bcx: @block_ctxt, uniq_ty: ty::t, opt_v: option<ValueRef>)
: type_is_unique_box(cx, uniq_ty) -> result {
: type_is_unique_box(bcx, uniq_ty) -> result {
let contents_ty = content_ty(bcx, uniq_ty);
let {bcx, sz: llsz, align: _} = metrics(bcx, contents_ty, opt_v);
let ccx = bcx_ccx(bcx);
@ -83,7 +84,7 @@ fn duplicate(bcx: @block_ctxt, v: ValueRef, t: ty::t)
: type_is_unique_box(bcx, t) -> result {
let content_ty = content_ty(bcx, t);
let {bcx, val: llptr} = alloc_uniq_(bcx, t, v);
let {bcx, val: llptr} = alloc_uniq_(bcx, t, some(v));
let src = load_if_immediate(bcx, v, content_ty);
let dst = llptr;

View File

@ -149,6 +149,7 @@ export kind_can_be_copied, kind_can_be_sent, proto_kind, kind_lteq, type_kind;
export type_err;
export type_err_to_str;
export type_has_dynamic_size;
export type_has_opaque_size;
export type_needs_drop;
export type_is_bool;
export type_is_bot;
@ -1140,6 +1141,15 @@ fn type_structurally_contains(cx: ctxt, ty: t, test: fn(sty) -> bool) ->
}
}
pure fn type_has_opaque_size(cx: ctxt, ty: t) -> bool unchecked {
type_structurally_contains(cx, ty, fn (sty: sty) -> bool {
alt sty {
ty_opaque_closure. { true}
_ { false }
}
})
}
pure fn type_has_dynamic_size(cx: ctxt, ty: t) -> bool unchecked {
/* type_structurally_contains can't be declared pure