Skip to content

Commit 5a15619

Browse files
committed
Fix more bugs in the alignment calculation refs to DSTs.
1 parent cea0dc4 commit 5a15619

File tree

1 file changed

+30
-7
lines changed

1 file changed

+30
-7
lines changed

src/librustc_trans/trans/glue.rs

+30-7
Original file line numberDiff line numberDiff line change
@@ -437,34 +437,57 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
437437
let field_ty = last_field.mt.ty;
438438
let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info);
439439

440+
let dbloc = DebugLoc::None;
441+
440442
// #27023 FIXME: We should be adding any necessary padding
441443
// to `sized_size` (to accommodate the `unsized_align`
442444
// required of the unsized field that follows) before
443445
// summing it with `sized_size`.
444446

445447
// Return the sum of sizes and max of aligns.
446-
let mut size = Add(bcx, sized_size, unsized_size, DebugLoc::None);
448+
let mut size = Add(bcx, sized_size, unsized_size, dbloc);
447449

448450
// Issue #27023: If there is a drop flag, *now* we add 1
449451
// to the size. (We can do this without adding any
450452
// padding because drop flags do not have any alignment
451453
// constraints.)
452454
if sizing_type.needs_drop_flag() {
453-
size = Add(bcx, size, C_uint(bcx.ccx(), 1_u64), DebugLoc::None);
455+
size = Add(bcx, size, C_uint(bcx.ccx(), 1_u64), dbloc);
454456
}
455457

458+
// Choose max of two known alignments (combined value must
459+
// be aligned according to more restrictive of the two).
456460
let align = Select(bcx,
457461
ICmp(bcx,
458-
llvm::IntULT,
462+
llvm::IntUGT,
459463
sized_align,
460464
unsized_align,
461-
DebugLoc::None),
465+
dbloc),
462466
sized_align,
463467
unsized_align);
464468

465-
// #27023 FIXME: We should be adding any necessary padding
466-
// to `size` (to make it a multiple of `align`) before
467-
// returning it.
469+
// Issue #27023: must add any necessary padding to `size`
470+
// (to make it a multiple of `align`) before returning it.
471+
//
472+
// Namely, the returned size should be, in C notation:
473+
//
474+
// `size + ((size & (align-1)) ? align : 0)`
475+
//
476+
// Currently I am emulating the above via:
477+
//
478+
// `size + ((size & (align-1)) * align-(size & (align-1)))`
479+
//
480+
// because I am not sure which is cheaper between a branch
481+
// or a multiply.
482+
483+
let mask = Sub(bcx, align, C_uint(bcx.ccx(), 1_u64), dbloc);
484+
let lowbits = And(bcx, size, mask, DebugLoc::None);
485+
let nonzero = ICmp(bcx, llvm::IntNE, lowbits, C_uint(bcx.ccx(), 0_u64), dbloc);
486+
let add_size = Mul(bcx,
487+
ZExt(bcx, nonzero, Type::i64(bcx.ccx())),
488+
Sub(bcx, align, lowbits, dbloc),
489+
dbloc);
490+
let size = Add(bcx, size, add_size, dbloc);
468491

469492
(size, align)
470493
}

0 commit comments

Comments
 (0)