Skip to content

Commit 7db640e

Browse files
committed
collapse sizeof, alignof into metrics, pass along an instance if avail
1 parent 4f52e5a commit 7db640e

File tree

3 files changed

+78
-47
lines changed

3 files changed

+78
-47
lines changed

src/comp/middle/trans.rs

Lines changed: 65 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -414,14 +414,26 @@ fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
414414
False);
415415
}
416416

417-
fn size_of(cx: @block_ctxt, t: ty::t) -> result {
418-
let {bcx, sz, align} = metrics(cx, t, none);
419-
rslt(bcx, align)
417+
fn size_of(bcx: @block_ctxt, t: ty::t) -> result {
418+
assert !ty::type_has_opaque_size(bcx_tcx(bcx), t);
419+
let {bcx, sz, align: _} = metrics(bcx, t, none);
420+
rslt(bcx, sz)
420421
}
421422

422-
fn align_of(cx: @block_ctxt, t: ty::t) -> result {
423-
let {bcx, sz, align} = metrics(cx, t, none);
424-
rslt(bcx, align)
423+
fn align_of(bcx: @block_ctxt, t: ty::t) -> result {
424+
assert !ty::type_has_opaque_size(bcx_tcx(bcx), t);
425+
alt ty::struct(ccx.tcx, t) {
426+
ty::ty_opaque_closure. {
427+
// Hack: the alignment of an opaque closure is always defined as the
428+
// alignment of a pointer. This is not, however, strictly correct,
429+
// depending on your point of view.
430+
llalign_of(bcx, T_ptr(T_i8()));
431+
}
432+
_ {
433+
let {bcx, sz: _, align} = metrics(bcx, t, none);
434+
rslt(bcx, align)
435+
}
436+
}
425437
}
426438

427439
// 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 {
431443
// instance is required.
432444
fn metrics(bcx: @block_ctxt, t: ty::t, opt_v: option<ValueRef>)
433445
-> metrics_result {
434-
let ccx = bcx_ccx(cx);
446+
assert (option::is_some(opt_v) ||
447+
!ty::type_has_opaque_size(bcx_tcx(bcx), t));
448+
let ccx = bcx_ccx(bcx);
435449
if check type_has_static_size(ccx, t) {
436-
let sp = cx.sp;
437-
let sz = llsize_of(bcx_ccx(cx), type_of(ccx, sp, t));
438-
let align = llalign_of(bcx_ccx(cx), type_of(ccx, sp, t));
450+
let sp = bcx.sp;
451+
let sz = llsize_of(bcx_ccx(bcx), type_of(ccx, sp, t));
452+
let align = llalign_of(bcx_ccx(bcx), type_of(ccx, sp, t));
439453
ret {bcx: bcx, sz: sz, align: align};
440454
} else {
441455
ret dynamic_metrics(bcx, t, opt_v);
@@ -552,11 +566,11 @@ type metrics_result = {
552566
};
553567

554568
fn dynamic_metrics(bcx: @block_ctxt,
555-
elts: [ty::t],
556-
opts_v: option<ValueRef>) -> metrics_result {
557-
fn compute_elements_metrics(bcx: @block_ctxt,
558-
elts: [ty::t],
559-
opt_v: option<ValueRef>) -> metrics_result {
569+
t: ty::t,
570+
opt_v: option<ValueRef>) -> metrics_result {
571+
fn c_struct_metrics(bcx: @block_ctxt,
572+
elts: [ty::t],
573+
opt_v: option<ValueRef>) -> metrics_result {
560574
//
561575
// C padding rules:
562576
//
@@ -570,40 +584,40 @@ fn dynamic_metrics(bcx: @block_ctxt,
570584
let max_align = C_int(bcx_ccx(bcx), 1);
571585
for e: ty::t in elts {
572586
let opt_ev = option::map(opt_v) {|v| ptr_offs(bcx, v, off) };
573-
let elt_align = align_of(bcx, e, opt_ev);
574-
bcx = elt_align.bcx;
575-
let elt_size = size_of(bcx, e, opt_ev);
576-
bcx = elt_size.bcx;
577-
let aligned_off = align_to(bcx, off, elt_align.val);
578-
off = Add(bcx, aligned_off, elt_size.val);
579-
max_align = umax(bcx, max_align, elt_align.val);
587+
let elt_metrics = metrics(bcx, e, opt_ev);
588+
bcx = elt_metrics.bcx;
589+
let aligned_off = align_to(bcx, off, elt_metrics.align);
590+
off = Add(bcx, aligned_off, elt_metrics.sz);
591+
max_align = umax(bcx, max_align, elt_metrics.align);
580592
}
593+
off = align_to(bcx, off, max_align);
581594
ret { bcx: bcx, sz: off, align: max_align };
582595
}
583596

584597
alt ty::struct(bcx_tcx(bcx), t) {
585598
ty::ty_param(p, _) {
586-
let {bcx, value: szptr} =
587-
field_of_tydesc(bcx, t, false, abi::tydesc_field_size);
588-
let {bcx, value: aptr} =
589-
field_of_tydesc(bcx, t, false, abi::tydesc_field_align);
590-
ret { bcx: bcx, sz: Load(szptr), align: Load(align) };
599+
let ti = none::<@tydesc_info>;
600+
let {bcx, val: tydesc} =
601+
get_tydesc(bcx, t, false, tps_normal, ti).result;
602+
let sz = Load(bcx, GEPi(bcx, tydesc, [0, abi::tydesc_field_size]));
603+
let al = Load(bcx, GEPi(bcx, tydesc, [0, abi::tydesc_field_align]));
604+
ret { bcx: bcx, sz: sz, align: al };
591605
}
592606
ty::ty_rec(flds) {
593607
let tys: [ty::t] = [];
594608
for f: ty::field in flds { tys += [f.mt.ty]; }
595-
ret compute_elements_metrics(bcx, tys, opt_v);
609+
ret c_struct_metrics(bcx, tys, opt_v);
596610
}
597611
ty::ty_tup(elts) {
598612
let tys = [];
599613
for tp in elts { tys += [tp]; }
600-
ret compute_elements_metrics(bcx, tys, opt_v);
614+
ret c_struct_metrics(bcx, tys, opt_v);
601615
}
602616
ty::ty_tag(tid, tps) {
603617
let bcx = bcx;
604618
let ccx = bcx_ccx(bcx);
605-
// Compute max(variant sizes) and max(variant alignments).
606619

620+
// Compute max(variant sizes) and max(variant alignments).
607621
let max_size: ValueRef = alloca(bcx, ccx.int_type);
608622
Store(bcx, C_int(ccx, 0), max_size);
609623
let variants = ty::tag_variants(bcx_tcx(bcx), tid);
@@ -616,9 +630,16 @@ fn dynamic_metrics(bcx: @block_ctxt,
616630
let t = ty::substitute_type_params(bcx_tcx(bcx), tps, raw_ty);
617631
tys += [t];
618632
}
619-
let rslt = align_elements(bcx, tys, opt_v);
633+
634+
// Note: we do not pass in opt_v here for the value but rather
635+
// none. The reason is that what we would want to pass in is a
636+
// ptr to the blob data of the tag, but this is impossible until
637+
// we know the size/alignment of the blob data. Therefore, it is
638+
// not legal to have a tag type that contains an interior opaque
639+
// type. Fortunately this will never happen.
640+
let rslt = c_struct_metrics(bcx, tys, none);
620641
bcx = rslt.bcx;
621-
let this_size = rslt.val;
642+
let this_size = rslt.sz;
622643
let old_max_size = Load(bcx, max_size);
623644
Store(bcx, umax(bcx, this_size, old_max_size), max_size);
624645
}
@@ -651,7 +672,7 @@ fn dynamic_metrics(bcx: @block_ctxt,
651672
let tdptr = Load(bcx, tdptrptr);
652673
let sz = Load(bcx, GEPi(bcx, tdptr, [0, abi::tydesc_field_size]));
653674
let align = Load(bcx, GEPi(bcx, tdptr, [0, abi::tydesc_field_align]));
654-
ret { bcx: bcx, sz: sz, align: sz };
675+
ret { bcx: bcx, sz: sz, align: align };
655676
}
656677
}
657678
}
@@ -661,7 +682,7 @@ fn dynamic_metrics(bcx: @block_ctxt,
661682
// return type, use bump_ptr().
662683
fn ptr_offs(bcx: @block_ctxt, base: ValueRef, sz: ValueRef) -> ValueRef {
663684
let raw = PointerCast(bcx, base, T_ptr(T_i8()));
664-
GEP(bcx, raw, [sz]);
685+
GEP(bcx, raw, [sz])
665686
}
666687

667688
// 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])
760781
let args = [];
761782
for typ: ty::t in s.prefix { args += [typ]; }
762783
let prefix_ty = ty::mk_tup(bcx_tcx(bcx), args);
763-
let {bcx, val: prefix_sz} = size_of(bcx, prefix_ty);
784+
let {bcx, sz: prefix_sz, align: _} = metrics(bcx, prefix_ty, some(base));
764785
let {bcx, val: align} = align_of(bcx, s.target);
765786
let sz = align_to(bcx, prefix_sz, align);
766787
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) ->
898919
GEPi(tydesc.bcx, tydesc.val, [0, field]));
899920
}
900921

901-
902922
// Given a type containing ty params, build a vector containing a ValueRef for
903923
// each of the ty params it uses (from the current frame) and a vector of the
904924
// 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,
20032023
Call(cx, memset, [dst_ptr, C_u8(0u), size, align, volatile]));
20042024
}
20052025

2006-
fn memmove_ty(cx: @block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t) ->
2026+
fn memmove_ty(bcx: @block_ctxt, dst: ValueRef, src: ValueRef, t: ty::t) ->
20072027
@block_ctxt {
2008-
let ccx = bcx_ccx(cx);
2028+
let ccx = bcx_ccx(bcx);
20092029
if check type_has_static_size(ccx, t) {
2010-
if ty::type_is_structural(bcx_tcx(cx), t) {
2011-
let sp = cx.sp;
2030+
if ty::type_is_structural(bcx_tcx(bcx), t) {
2031+
let sp = bcx.sp;
20122032
let llsz = llsize_of(ccx, type_of(ccx, sp, t));
2013-
ret call_memmove(cx, dst, src, llsz).bcx;
2033+
ret call_memmove(bcx, dst, src, llsz).bcx;
20142034
}
2015-
Store(cx, Load(cx, src), dst);
2016-
ret cx;
2035+
Store(bcx, Load(bcx, src), dst);
2036+
ret bcx;
20172037
}
20182038

2019-
let llsz = size_of(cx, t);
2020-
ret call_memmove(llsz.bcx, dst, src, llsz.val).bcx;
2039+
let {bcx, sz: llsz, align: _} = metrics(bcx, t, some(src));
2040+
ret call_memmove(bcx, dst, src, llsz).bcx;
20212041
}
20222042

20232043
tag copy_action { INIT; DROP_EXISTING; }

src/comp/middle/trans_uniq.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import trans_build::*;
55
import trans::{
66
trans_shared_malloc,
77
type_of_inner,
8+
metrics,
89
size_of,
910
node_id_type,
1011
INIT,
@@ -39,7 +40,7 @@ fn alloc_uniq(cx: @block_ctxt, uniq_ty: ty::t)
3940
}
4041

4142
fn alloc_uniq_(bcx: @block_ctxt, uniq_ty: ty::t, opt_v: option<ValueRef>)
42-
: type_is_unique_box(cx, uniq_ty) -> result {
43+
: type_is_unique_box(bcx, uniq_ty) -> result {
4344
let contents_ty = content_ty(bcx, uniq_ty);
4445
let {bcx, sz: llsz, align: _} = metrics(bcx, contents_ty, opt_v);
4546
let ccx = bcx_ccx(bcx);
@@ -83,7 +84,7 @@ fn duplicate(bcx: @block_ctxt, v: ValueRef, t: ty::t)
8384
: type_is_unique_box(bcx, t) -> result {
8485

8586
let content_ty = content_ty(bcx, t);
86-
let {bcx, val: llptr} = alloc_uniq_(bcx, t, v);
87+
let {bcx, val: llptr} = alloc_uniq_(bcx, t, some(v));
8788

8889
let src = load_if_immediate(bcx, v, content_ty);
8990
let dst = llptr;

src/comp/middle/ty.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ export kind_can_be_copied, kind_can_be_sent, proto_kind, kind_lteq, type_kind;
149149
export type_err;
150150
export type_err_to_str;
151151
export type_has_dynamic_size;
152+
export type_has_opaque_size;
152153
export type_needs_drop;
153154
export type_is_bool;
154155
export type_is_bot;
@@ -1140,6 +1141,15 @@ fn type_structurally_contains(cx: ctxt, ty: t, test: fn(sty) -> bool) ->
11401141
}
11411142
}
11421143

1144+
pure fn type_has_opaque_size(cx: ctxt, ty: t) -> bool unchecked {
1145+
type_structurally_contains(cx, ty, fn (sty: sty) -> bool {
1146+
alt sty {
1147+
ty_opaque_closure. { true}
1148+
_ { false }
1149+
}
1150+
})
1151+
}
1152+
11431153
pure fn type_has_dynamic_size(cx: ctxt, ty: t) -> bool unchecked {
11441154

11451155
/* type_structurally_contains can't be declared pure

0 commit comments

Comments
 (0)