diff --git a/src/comp/middle/trans.rs b/src/comp/middle/trans.rs index 4c2abd17f36f..fdd1a4a93f61 100644 --- a/src/comp/middle/trans.rs +++ b/src/comp/middle/trans.rs @@ -408,11 +408,20 @@ fn llalign_of(t: TypeRef) -> ValueRef { } fn size_of(cx: @block_ctxt, t: ty::t) -> result { + size_of_(cx, t, align_total) +} + +tag align_mode { + align_total; + align_next(ty::t); +} + +fn size_of_(cx: @block_ctxt, t: ty::t, mode: align_mode) -> result { let ccx = bcx_ccx(cx); if check type_has_static_size(ccx, t) { let sp = cx.sp; rslt(cx, llsize_of(type_of(ccx, sp, t))) - } else { dynamic_size_of(cx, t) } + } else { dynamic_size_of(cx, t, mode) } } 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) } } -fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result { - fn align_elements(cx: @block_ctxt, elts: [ty::t]) -> result { +fn dynamic_size_of(cx: @block_ctxt, t: ty::t, mode: align_mode) -> result { + fn align_elements(cx: @block_ctxt, elts: [ty::t], + mode: align_mode) -> result { // // C padding rules: // @@ -547,7 +557,15 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result { off = Add(bcx, aligned_off, elt_size.val); max_align = umax(bcx, max_align, elt_align.val); } - off = align_to(bcx, off, max_align); + off = alt mode { + align_total. { + align_to(bcx, off, max_align) + } + align_next(t) { + let {bcx, val: align} = align_of(bcx, t); + align_to(bcx, off, align) + } + }; ret rslt(bcx, off); } alt ty::struct(bcx_tcx(cx), t) { @@ -558,12 +576,12 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result { ty::ty_rec(flds) { let tys: [ty::t] = []; for f: ty::field in flds { tys += [f.mt.ty]; } - ret align_elements(cx, tys); + ret align_elements(cx, tys, mode); } ty::ty_tup(elts) { let tys = []; for tp in elts { tys += [tp]; } - ret align_elements(cx, tys); + ret align_elements(cx, tys, mode); } ty::ty_tag(tid, tps) { let bcx = cx; @@ -581,7 +599,7 @@ fn dynamic_size_of(cx: @block_ctxt, t: ty::t) -> result { let t = ty::substitute_type_params(bcx_tcx(cx), tps, raw_ty); tys += [t]; } - let rslt = align_elements(bcx, tys); + let rslt = align_elements(bcx, tys, mode); bcx = rslt.bcx; let this_size = rslt.val; 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]) let prefix_ty = ty::mk_tup(bcx_tcx(cx), args); let bcx = cx; - let sz = size_of(bcx, prefix_ty); + let sz = size_of_(bcx, prefix_ty, align_next(s.target)); ret rslt(sz.bcx, bump_ptr(sz.bcx, s.target, base, sz.val)); } diff --git a/src/test/run-pass/issue-1112.rs b/src/test/run-pass/issue-1112.rs new file mode 100644 index 000000000000..35d21e40be26 --- /dev/null +++ b/src/test/run-pass/issue-1112.rs @@ -0,0 +1,37 @@ +// Issue #1112 +// Alignment of interior pointers to dynamic-size types + +use std; +import std::ptr::addr_of; + +type x = { + a: T, + b: u8, + c: bool, + d: u8, + e: u16, + f: u8, + g: u8 +}; + +fn main() { + let x: x = { + a: 12345678, + b: 9u8, + c: true, + d: 10u8, + e: 11u16, + f: 12u8, + g: 13u8 + }; + bar(x); +} + +fn bar(x: x) { + assert x.b == 9u8; + assert x.c == true; + assert x.d == 10u8; + assert x.e == 11u16; + assert x.f == 12u8; + assert x.g == 13u8; +} \ No newline at end of file