mirror of
https://github.com/rust-lang/rust.git
synced 2025-02-19 18:34:08 +00:00
Fix more bugs in the alignment calculation refs to DSTs.
This commit is contained in:
parent
cea0dc4f6d
commit
5a156190cb
@ -437,34 +437,57 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
|
||||
let field_ty = last_field.mt.ty;
|
||||
let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info);
|
||||
|
||||
let dbloc = DebugLoc::None;
|
||||
|
||||
// #27023 FIXME: We should be adding any necessary padding
|
||||
// to `sized_size` (to accommodate the `unsized_align`
|
||||
// required of the unsized field that follows) before
|
||||
// summing it with `sized_size`.
|
||||
|
||||
// Return the sum of sizes and max of aligns.
|
||||
let mut size = Add(bcx, sized_size, unsized_size, DebugLoc::None);
|
||||
let mut size = Add(bcx, sized_size, unsized_size, dbloc);
|
||||
|
||||
// Issue #27023: If there is a drop flag, *now* we add 1
|
||||
// to the size. (We can do this without adding any
|
||||
// padding because drop flags do not have any alignment
|
||||
// constraints.)
|
||||
if sizing_type.needs_drop_flag() {
|
||||
size = Add(bcx, size, C_uint(bcx.ccx(), 1_u64), DebugLoc::None);
|
||||
size = Add(bcx, size, C_uint(bcx.ccx(), 1_u64), dbloc);
|
||||
}
|
||||
|
||||
// Choose max of two known alignments (combined value must
|
||||
// be aligned according to more restrictive of the two).
|
||||
let align = Select(bcx,
|
||||
ICmp(bcx,
|
||||
llvm::IntULT,
|
||||
llvm::IntUGT,
|
||||
sized_align,
|
||||
unsized_align,
|
||||
DebugLoc::None),
|
||||
dbloc),
|
||||
sized_align,
|
||||
unsized_align);
|
||||
|
||||
// #27023 FIXME: We should be adding any necessary padding
|
||||
// to `size` (to make it a multiple of `align`) before
|
||||
// returning it.
|
||||
// Issue #27023: must add any necessary padding to `size`
|
||||
// (to make it a multiple of `align`) before returning it.
|
||||
//
|
||||
// Namely, the returned size should be, in C notation:
|
||||
//
|
||||
// `size + ((size & (align-1)) ? align : 0)`
|
||||
//
|
||||
// Currently I am emulating the above via:
|
||||
//
|
||||
// `size + ((size & (align-1)) * align-(size & (align-1)))`
|
||||
//
|
||||
// because I am not sure which is cheaper between a branch
|
||||
// or a multiply.
|
||||
|
||||
let mask = Sub(bcx, align, C_uint(bcx.ccx(), 1_u64), dbloc);
|
||||
let lowbits = And(bcx, size, mask, DebugLoc::None);
|
||||
let nonzero = ICmp(bcx, llvm::IntNE, lowbits, C_uint(bcx.ccx(), 0_u64), dbloc);
|
||||
let add_size = Mul(bcx,
|
||||
ZExt(bcx, nonzero, Type::i64(bcx.ccx())),
|
||||
Sub(bcx, align, lowbits, dbloc),
|
||||
dbloc);
|
||||
let size = Add(bcx, size, add_size, dbloc);
|
||||
|
||||
(size, align)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user