Skip to content

Commit 54f6bf5

Browse files
committed
remove align_mode and rewrite GEP_tup_like to align correctly
Although the old version of GEP_tup_like was incorrect in some cases, I do not believe we ever used it in an incorrect fashion. In particular, it could go wrong with extended index sequences like [0, 1, 3], but as near as I can tell we only ever use it with short sequences like [0, i].
1 parent da82874 commit 54f6bf5

File tree

6 files changed

+82
-97
lines changed

6 files changed

+82
-97
lines changed

src/comp/middle/shape.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -505,9 +505,9 @@ fn gen_tag_shapes(ccx: @crate_ctxt) -> ValueRef {
505505
let info_sz = 0u16;
506506
for did_: ast::def_id in ccx.shape_cx.tag_order {
507507
let did = did_; // Satisfy alias checker.
508-
let variants = ty::tag_variants(ccx.tcx, did);
508+
let num_variants = vec::len(*ty::tag_variants(ccx.tcx, did)) as u16;
509509
add_u16(header, header_sz + info_sz);
510-
info_sz += 2u16 * ((vec::len(*variants) as u16) + 2u16) + 3u16;
510+
info_sz += 2u16 * (num_variants + 2u16) + 3u16;
511511
}
512512

513513
// Construct the info tables, which contain offsets to the shape of each

src/comp/middle/trans.rs

Lines changed: 57 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -412,20 +412,15 @@ fn llalign_of(cx: @crate_ctxt, t: TypeRef) -> ValueRef {
412412
}
413413

414414
fn size_of(cx: @block_ctxt, t: ty::t) -> result {
415-
size_of_(cx, t, align_total)
415+
size_of_(cx, t)
416416
}
417417

418-
tag align_mode {
419-
align_total;
420-
align_next(ty::t);
421-
}
422-
423-
fn size_of_(cx: @block_ctxt, t: ty::t, mode: align_mode) -> result {
418+
fn size_of_(cx: @block_ctxt, t: ty::t) -> result {
424419
let ccx = bcx_ccx(cx);
425420
if check type_has_static_size(ccx, t) {
426421
let sp = cx.sp;
427422
rslt(cx, llsize_of(bcx_ccx(cx), type_of(ccx, sp, t)))
428-
} else { dynamic_size_of(cx, t, mode) }
423+
} else { dynamic_size_of(cx, t) }
429424
}
430425

431426
fn align_of(cx: @block_ctxt, t: ty::t) -> result {
@@ -536,9 +531,8 @@ fn static_size_of_tag(cx: @crate_ctxt, sp: span, t: ty::t)
536531
}
537532
}
538533

539-
fn dynamic_size_of(cx: @block_ctxt, t: ty::t, mode: align_mode) -> result {
540-
fn align_elements(cx: @block_ctxt, elts: [ty::t],
541-
mode: align_mode) -> result {
534+
fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
535+
fn align_elements(cx: @block_ctxt, elts: [ty::t]) -> result {
542536
//
543537
// C padding rules:
544538
//
@@ -560,15 +554,16 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t, mode: align_mode) -> result {
560554
off = Add(bcx, aligned_off, elt_size.val);
561555
max_align = umax(bcx, max_align, elt_align.val);
562556
}
563-
off = alt mode {
564-
align_total. {
565-
align_to(bcx, off, max_align)
566-
}
567-
align_next(t) {
568-
let {bcx, val: align} = align_of(bcx, t);
569-
align_to(bcx, off, align)
570-
}
571-
};
557+
off = align_to(bcx, off, max_align);
558+
//off = alt mode {
559+
// align_total. {
560+
// align_to(bcx, off, max_align)
561+
// }
562+
// align_next(t) {
563+
// let {bcx, val: align} = align_of(bcx, t);
564+
// align_to(bcx, off, align)
565+
// }
566+
//};
572567
ret rslt(bcx, off);
573568
}
574569
alt ty::struct(bcx_tcx(cx), t) {
@@ -579,12 +574,12 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t, mode: align_mode) -> result {
579574
ty::ty_rec(flds) {
580575
let tys: [ty::t] = [];
581576
for f: ty::field in flds { tys += [f.mt.ty]; }
582-
ret align_elements(cx, tys, mode);
577+
ret align_elements(cx, tys);
583578
}
584579
ty::ty_tup(elts) {
585580
let tys = [];
586581
for tp in elts { tys += [tp]; }
587-
ret align_elements(cx, tys, mode);
582+
ret align_elements(cx, tys);
588583
}
589584
ty::ty_tag(tid, tps) {
590585
let bcx = cx;
@@ -603,7 +598,7 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t, mode: align_mode) -> result {
603598
let t = ty::substitute_type_params(bcx_tcx(cx), tps, raw_ty);
604599
tys += [t];
605600
}
606-
let rslt = align_elements(bcx, tys, mode);
601+
let rslt = align_elements(bcx, tys);
607602
bcx = rslt.bcx;
608603
let this_size = rslt.val;
609604
let old_max_size = Load(bcx, max_size);
@@ -689,84 +684,55 @@ fn GEP_tup_like_1(cx: @block_ctxt, t: ty::t, base: ValueRef, ixs: [int])
689684
// above.
690685
fn GEP_tup_like(bcx: @block_ctxt, t: ty::t, base: ValueRef, ixs: [int])
691686
: type_is_tup_like(bcx, t) -> result {
692-
// It might be a static-known type. Handle this.
693-
if !ty::type_has_dynamic_size(bcx_tcx(bcx), t) {
694-
#debug["GEP_tup_like t=%? ixs=%? -> static",
695-
ty_to_str(bcx_tcx(bcx), t), ixs];
696687

697-
ret rslt(bcx, GEPi(bcx, base, ixs));
698-
}
699-
// It is a dynamic-containing type that, if we convert directly to an LLVM
700-
// TypeRef, will be all wrong; there's no proper LLVM type to represent
701-
// it, and the lowering function will stick in i8* values for each
702-
// ty_param, which is not right; the ty_params are all of some dynamic
703-
// size.
704-
//
705-
// What we must do instead is sadder. We must look through the indices
706-
// manually and split the input type into a prefix and a target. We then
707-
// measure the prefix size, bump the input pointer by that amount, and
708-
// cast to a pointer-to-target type.
709-
710-
// Given a type, an index vector and an element number N in that vector,
711-
// calculate index X and the type that results by taking the first X-1
712-
// elements of the type and splitting the Xth off. Return the prefix as
713-
// well as the innermost Xth type.
714-
715-
fn split_type(ccx: @crate_ctxt, t: ty::t, ixs: [int], n: uint) ->
716-
{prefix: [ty::t], target: ty::t} {
717-
let len: uint = vec::len::<int>(ixs);
718-
// We don't support 0-index or 1-index GEPs: The former is nonsense
719-
// and the latter would only be meaningful if we supported non-0
720-
// values for the 0th index (we don't).
721-
722-
assert (len > 1u);
723-
if n == 0u {
724-
// Since we're starting from a value that's a pointer to a
725-
// *single* structure, the first index (in GEP-ese) should just be
726-
// 0, to yield the pointee.
727-
728-
assert (ixs[n] == 0);
729-
ret split_type(ccx, t, ixs, n + 1u);
688+
fn compute_off(bcx: @block_ctxt,
689+
off: ValueRef,
690+
t: ty::t,
691+
ixs: [int],
692+
n: uint) -> (@block_ctxt, ValueRef, ty::t) {
693+
if n == vec::len(ixs) {
694+
ret (bcx, off, t);
730695
}
731-
assert (n < len);
732-
let ix: int = ixs[n];
733-
let prefix: [ty::t] = [];
734-
let i: int = 0;
735-
while i < ix {
736-
prefix += [ty::get_element_type(ccx.tcx, t, i as uint)];
737-
i += 1;
696+
697+
let tcx = bcx_tcx(bcx);
698+
let ix = ixs[n];
699+
let bcx = bcx, off = off;
700+
int::range(0, ix) {|i|
701+
let comp_t = ty::get_element_type(tcx, t, i as uint);
702+
let align = align_of(bcx, comp_t);
703+
bcx = align.bcx;
704+
off = align_to(bcx, off, align.val);
705+
let sz = size_of(bcx, comp_t);
706+
bcx = sz.bcx;
707+
off = Add(bcx, off, sz.val);
738708
}
739-
let selected = ty::get_element_type(ccx.tcx, t, i as uint);
740-
if n == len - 1u {
741-
// We are at the innermost index.
742709

743-
ret {prefix: prefix, target: selected};
744-
} else {
745-
// Not the innermost index; call self recursively to dig deeper.
746-
// Once we get an inner result, append it current prefix and
747-
// return to caller.
710+
let comp_t = ty::get_element_type(tcx, t, ix as uint);
711+
let align = align_of(bcx, comp_t);
712+
bcx = align.bcx;
713+
off = align_to(bcx, off, align.val);
748714

749-
let inner = split_type(ccx, selected, ixs, n + 1u);
750-
prefix += inner.prefix;
751-
ret {prefix: prefix with inner};
752-
}
715+
be compute_off(bcx, off, comp_t, ixs, n+1u);
753716
}
754-
// We make a fake prefix tuple-type here; luckily for measuring sizes
755-
// the tuple parens are associative so it doesn't matter that we've
756-
// flattened the incoming structure.
757717

758-
let s = split_type(bcx_ccx(bcx), t, ixs, 0u);
718+
if !ty::type_has_dynamic_size(bcx_tcx(bcx), t) {
719+
ret rslt(bcx, GEPi(bcx, base, ixs));
720+
}
759721

760-
let args = [];
761-
for typ: ty::t in s.prefix { args += [typ]; }
762-
let prefix_ty = ty::mk_tup(bcx_tcx(bcx), args);
722+
#debug["GEP_tup_like(t=%s,base=%s,ixs=%?)",
723+
ty_to_str(bcx_tcx(bcx), t),
724+
val_str(bcx_ccx(bcx).tn, base),
725+
ixs];
763726

764-
#debug["GEP_tup_like t=%? ixs=%? prefix_ty=%?",
765-
ty_to_str(bcx_tcx(bcx), t), ixs,
766-
ty_to_str(bcx_tcx(bcx), prefix_ty)];
727+
// We require that ixs start with 0 and we expect the input to be a
728+
// pointer to an instance of type t, so we can safely ignore ixs[0],
729+
// basically.
730+
assert ixs[0] == 0;
767731

768-
let sz = size_of_(bcx, prefix_ty, align_next(s.target));
769-
ret rslt(sz.bcx, bump_ptr(sz.bcx, s.target, base, sz.val));
732+
let (bcx, off, tar_t) = {
733+
compute_off(bcx, C_int(bcx_ccx(bcx), 0), t, ixs, 1u)
734+
};
735+
ret rslt(bcx, bump_ptr(bcx, tar_t, base, off));
770736
}
771737

772738

src/comp/middle/trans_closure.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -361,7 +361,8 @@ fn store_environment(
361361
}
362362

363363
let bound_data = GEP_tup_like_1(bcx, cbox_ty, llbox,
364-
[0, abi::cbox_elt_bindings, i as int]);
364+
[0, abi::cbox_elt_bindings,
365+
i as int]);
365366
bcx = bound_data.bcx;
366367
let bound_data = bound_data.val;
367368
alt bv {

src/comp/middle/ty.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -869,8 +869,9 @@ fn get_element_type(cx: ctxt, ty: t, i: uint) -> t {
869869
ty_rec(flds) { ret flds[i].mt.ty; }
870870
ty_tup(ts) { ret ts[i]; }
871871
_ {
872-
cx.sess.bug("get_element_type called on type " + ty_to_str(cx, ty) +
873-
" - expected a tuple or record");
872+
cx.sess.bug(
873+
#fmt["get_element_type called on invalid type %s with index %u",
874+
ty_to_str(cx, ty), i]);
874875
}
875876
}
876877
}

src/comp/rustc.rc

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,5 +142,4 @@ mod lib {
142142
// indent-tabs-mode: nil
143143
// c-basic-offset: 4
144144
// buffer-file-coding-system: utf-8-unix
145-
// compile-command: "make -k -C $RBUILD 2>&1 | sed -e 's/\\/x\\//x:\\//g'";
146145
// End:
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// If we use GEPi rathern than GEP_tup_like when
2+
// storing closure data (as we used to do), the u64 would
3+
// overwrite the u16.
4+
5+
type pair<A,B> = {
6+
a: A, b: B
7+
};
8+
9+
fn f<A:copy>(a: A, b: u16) -> fn@() -> (A, u16) {
10+
fn@() -> (A, u16) { (a, b) }
11+
}
12+
13+
fn main() {
14+
let (a, b) = f(22_u64, 44u16)();
15+
#debug["a=%? b=%?", a, b];
16+
assert a == 22u64;
17+
assert b == 44u16;
18+
}

0 commit comments

Comments
 (0)