Skip to content

Commit 61b6045

Browse files
committed
Fix alignment of interior pointers of dynamic-size types. Closes #1112
GEP_tup_like finds interior pointers by creating a tuple of all the types preceding the element it wants a pointer to, then asks for the size of that tuple. This results in incorrect pointers when the alignment of that tuple is not the alignment of the interior type you're getting a pointer to.
1 parent 1199935 commit 61b6045

File tree

2 files changed

+63
-8
lines changed

2 files changed

+63
-8
lines changed

src/comp/middle/trans.rs

+26-8
Original file line numberDiff line numberDiff line change
@@ -408,11 +408,20 @@ fn llalign_of(t: TypeRef) -> ValueRef {
408408
}
409409

410410
fn size_of(cx: @block_ctxt, t: ty::t) -> result {
411+
size_of_(cx, t, align_total)
412+
}
413+
414+
tag align_mode {
415+
align_total;
416+
align_next(ty::t);
417+
}
418+
419+
fn size_of_(cx: @block_ctxt, t: ty::t, mode: align_mode) -> result {
411420
let ccx = bcx_ccx(cx);
412421
if check type_has_static_size(ccx, t) {
413422
let sp = cx.sp;
414423
rslt(cx, llsize_of(type_of(ccx, sp, t)))
415-
} else { dynamic_size_of(cx, t) }
424+
} else { dynamic_size_of(cx, t, mode) }
416425
}
417426

418427
fn align_of(cx: @block_ctxt, t: ty::t) -> result {
@@ -524,8 +533,9 @@ fn static_size_of_tag(cx: @crate_ctxt, sp: span, t: ty::t)
524533
}
525534
}
526535

527-
fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
528-
fn align_elements(cx: @block_ctxt, elts: [ty::t]) -> result {
536+
fn dynamic_size_of(cx: @block_ctxt, t: ty::t, mode: align_mode) -> result {
537+
fn align_elements(cx: @block_ctxt, elts: [ty::t],
538+
mode: align_mode) -> result {
529539
//
530540
// C padding rules:
531541
//
@@ -547,7 +557,15 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
547557
off = Add(bcx, aligned_off, elt_size.val);
548558
max_align = umax(bcx, max_align, elt_align.val);
549559
}
550-
off = align_to(bcx, off, max_align);
560+
off = alt mode {
561+
align_total. {
562+
align_to(bcx, off, max_align)
563+
}
564+
align_next(t) {
565+
let {bcx, val: align} = align_of(bcx, t);
566+
align_to(bcx, off, align)
567+
}
568+
};
551569
ret rslt(bcx, off);
552570
}
553571
alt ty::struct(bcx_tcx(cx), t) {
@@ -558,12 +576,12 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
558576
ty::ty_rec(flds) {
559577
let tys: [ty::t] = [];
560578
for f: ty::field in flds { tys += [f.mt.ty]; }
561-
ret align_elements(cx, tys);
579+
ret align_elements(cx, tys, mode);
562580
}
563581
ty::ty_tup(elts) {
564582
let tys = [];
565583
for tp in elts { tys += [tp]; }
566-
ret align_elements(cx, tys);
584+
ret align_elements(cx, tys, mode);
567585
}
568586
ty::ty_tag(tid, tps) {
569587
let bcx = cx;
@@ -581,7 +599,7 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result {
581599
let t = ty::substitute_type_params(bcx_tcx(cx), tps, raw_ty);
582600
tys += [t];
583601
}
584-
let rslt = align_elements(bcx, tys);
602+
let rslt = align_elements(bcx, tys, mode);
585603
bcx = rslt.bcx;
586604
let this_size = rslt.val;
587605
let old_max_size = Load(bcx, max_size);
@@ -738,7 +756,7 @@ fn GEP_tup_like(cx: @block_ctxt, t: ty::t, base: ValueRef, ixs: [int])
738756
let prefix_ty = ty::mk_tup(bcx_tcx(cx), args);
739757

740758
let bcx = cx;
741-
let sz = size_of(bcx, prefix_ty);
759+
let sz = size_of_(bcx, prefix_ty, align_next(s.target));
742760
ret rslt(sz.bcx, bump_ptr(sz.bcx, s.target, base, sz.val));
743761
}
744762

src/test/run-pass/issue-1112.rs

+37
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
// Issue #1112
2+
// Alignment of interior pointers to dynamic-size types
3+
4+
use std;
5+
import std::ptr::addr_of;
6+
7+
type x<T> = {
8+
a: T,
9+
b: u8,
10+
c: bool,
11+
d: u8,
12+
e: u16,
13+
f: u8,
14+
g: u8
15+
};
16+
17+
fn main() {
18+
let x: x<int> = {
19+
a: 12345678,
20+
b: 9u8,
21+
c: true,
22+
d: 10u8,
23+
e: 11u16,
24+
f: 12u8,
25+
g: 13u8
26+
};
27+
bar(x);
28+
}
29+
30+
fn bar<T>(x: x<T>) {
31+
assert x.b == 9u8;
32+
assert x.c == true;
33+
assert x.d == 10u8;
34+
assert x.e == 11u16;
35+
assert x.f == 12u8;
36+
assert x.g == 13u8;
37+
}

0 commit comments

Comments
 (0)