Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rustc_target: separate out an individual alignment quantity type from Align. #54071

Merged
merged 3 commits into from
Nov 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/librustc/mir/interpret/allocation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,7 @@ impl<Tag, Extra: Default> Allocation<Tag, Extra> {
}

pub fn from_byte_aligned_bytes(slice: &[u8]) -> Self {
Allocation::from_bytes(slice, Align::from_bytes(1, 1).unwrap())
Allocation::from_bytes(slice, Align::from_bytes(1).unwrap())
}

pub fn undef(size: Size, align: Align) -> Self {
Expand Down
7 changes: 4 additions & 3 deletions src/librustc/mir/interpret/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -527,7 +527,7 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c),
AlignmentCheckFailed { required, has } =>
write!(f, "tried to access memory with alignment {}, but alignment {} is required",
has.abi(), required.abi()),
has.bytes(), required.bytes()),
TypeNotPrimitive(ty) =>
write!(f, "expected primitive type, got {}", ty),
Layout(ref err) =>
Expand All @@ -537,8 +537,9 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
MachineError(ref inner) =>
write!(f, "{}", inner),
IncorrectAllocationInformation(size, size2, align, align2) =>
write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and \
align {}", size.bytes(), align.abi(), size2.bytes(), align2.abi()),
write!(f, "incorrect alloc info: expected size {} and align {}, \
got size {} and align {}",
size.bytes(), align.bytes(), size2.bytes(), align2.bytes()),
Panic { ref msg, line, col, ref file } =>
write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
InvalidDiscriminant(val) =>
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/session/code_stats.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ impl CodeStats {
let info = TypeSizeInfo {
kind,
type_description: type_desc.to_string(),
align: align.abi(),
align: align.bytes(),
overall_size: overall_size.bytes(),
packed: packed,
opt_discr_size: opt_discr_size.map(|s| s.bytes()),
Expand Down
105 changes: 52 additions & 53 deletions src/librustc/ty/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -226,9 +226,10 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
tcx.intern_layout(LayoutDetails::scalar(self, scalar_unit(value)))
};
let scalar_pair = |a: Scalar, b: Scalar| {
let align = a.value.align(dl).max(b.value.align(dl)).max(dl.aggregate_align);
let b_offset = a.value.size(dl).abi_align(b.value.align(dl));
let size = (b_offset + b.value.size(dl)).abi_align(align);
let b_align = b.value.align(dl);
let align = a.value.align(dl).max(b_align).max(dl.aggregate_align);
let b_offset = a.value.size(dl).align_to(b_align.abi);
let size = (b_offset + b.value.size(dl)).align_to(align.abi);
LayoutDetails {
variants: Variants::Single { index: VariantIdx::new(0) },
fields: FieldPlacement::Arbitrary {
Expand Down Expand Up @@ -257,10 +258,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
bug!("struct cannot be packed and aligned");
}

let pack = {
let pack = repr.pack as u64;
Align::from_bytes(pack, pack).unwrap()
};
let pack = Align::from_bytes(repr.pack as u64).unwrap();

let mut align = if packed {
dl.i8_align
Expand All @@ -274,7 +272,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {

let mut optimize = !repr.inhibit_struct_field_reordering_opt();
if let StructKind::Prefixed(_, align) = kind {
optimize &= align.abi() == 1;
optimize &= align.bytes() == 1;
}

if optimize {
Expand All @@ -285,7 +283,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
};
let optimizing = &mut inverse_memory_index[..end];
let field_align = |f: &TyLayout<'_>| {
if packed { f.align.min(pack).abi() } else { f.align.abi() }
if packed { f.align.abi.min(pack) } else { f.align.abi }
};
match kind {
StructKind::AlwaysSized |
Expand All @@ -312,13 +310,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
let mut offset = Size::ZERO;

if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
if packed {
let prefix_align = prefix_align.min(pack);
align = align.max(prefix_align);
let prefix_align = if packed {
prefix_align.min(pack)
} else {
align = align.max(prefix_align);
}
offset = prefix_size.abi_align(prefix_align);
prefix_align
};
align = align.max(AbiAndPrefAlign::new(prefix_align));
offset = prefix_size.align_to(prefix_align);
}

for &i in &inverse_memory_index {
Expand All @@ -333,15 +331,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
}

// Invariant: offset < dl.obj_size_bound() <= 1<<61
if packed {
let field_pack = field.align.min(pack);
offset = offset.abi_align(field_pack);
align = align.max(field_pack);
}
else {
offset = offset.abi_align(field.align);
align = align.max(field.align);
}
let field_align = if packed {
field.align.min(AbiAndPrefAlign::new(pack))
} else {
field.align
};
offset = offset.align_to(field_align.abi);
align = align.max(field_align);

debug!("univariant offset: {:?} field: {:#?}", offset, field);
offsets[i as usize] = offset;
Expand All @@ -352,7 +348,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {

if repr.align > 0 {
let repr_align = repr.align as u64;
align = align.max(Align::from_bytes(repr_align, repr_align).unwrap());
align = align.max(AbiAndPrefAlign::new(Align::from_bytes(repr_align).unwrap()));
debug!("univariant repr_align: {:?}", repr_align);
}

Expand All @@ -377,7 +373,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
memory_index = inverse_memory_index;
}

let size = min_size.abi_align(align);
let size = min_size.align_to(align.abi);
let mut abi = Abi::Aggregate { sized };

// Unpack newtype ABIs and find scalar pairs.
Expand All @@ -394,7 +390,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
(Some((i, field)), None, None) => {
// Field fills the struct and it has a scalar or scalar pair ABI.
if offsets[i].bytes() == 0 &&
align.abi() == field.align.abi() &&
align.abi == field.align.abi &&
size == field.size {
match field.abi {
// For plain scalars, or vectors of them, we can't unpack
Expand Down Expand Up @@ -648,7 +644,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
let size = element.size.checked_mul(count, dl)
.ok_or(LayoutError::SizeOverflow(ty))?;
let align = dl.vector_align(size);
let size = size.abi_align(align);
let size = size.align_to(align.abi);

tcx.intern_layout(LayoutDetails {
variants: Variants::Single { index: VariantIdx::new(0) },
Expand Down Expand Up @@ -680,10 +676,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
bug!("Union cannot be packed and aligned");
}

let pack = {
let pack = def.repr.pack as u64;
Align::from_bytes(pack, pack).unwrap()
};
let pack = Align::from_bytes(def.repr.pack as u64).unwrap();

let mut align = if packed {
dl.i8_align
Expand All @@ -694,7 +687,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
if def.repr.align > 0 {
let repr_align = def.repr.align as u64;
align = align.max(
Align::from_bytes(repr_align, repr_align).unwrap());
AbiAndPrefAlign::new(Align::from_bytes(repr_align).unwrap()));
}

let optimize = !def.repr.inhibit_union_abi_opt();
Expand All @@ -704,12 +697,12 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
for field in &variants[index] {
assert!(!field.is_unsized());

if packed {
let field_pack = field.align.min(pack);
align = align.max(field_pack);
let field_align = if packed {
field.align.min(AbiAndPrefAlign::new(pack))
} else {
align = align.max(field.align);
}
field.align
};
align = align.max(field_align);

// If all non-ZST fields have the same ABI, forward this ABI
if optimize && !field.is_zst() {
Expand Down Expand Up @@ -749,7 +742,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
fields: FieldPlacement::Union(variants[index].len()),
abi,
align,
size: size.abi_align(align)
size: size.align_to(align.abi)
}));
}

Expand Down Expand Up @@ -964,19 +957,19 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
let mut size = Size::ZERO;

// We're interested in the smallest alignment, so start large.
let mut start_align = Align::from_bytes(256, 256).unwrap();
assert_eq!(Integer::for_abi_align(dl, start_align), None);
let mut start_align = Align::from_bytes(256).unwrap();
assert_eq!(Integer::for_align(dl, start_align), None);

// repr(C) on an enum tells us to make a (tag, union) layout,
// so we need to grow the prefix alignment to be at least
// the alignment of the union. (This value is used both for
// determining the alignment of the overall enum, and the
// determining the alignment of the payload after the tag.)
let mut prefix_align = min_ity.align(dl);
let mut prefix_align = min_ity.align(dl).abi;
if def.repr.c() {
for fields in &variants {
for field in fields {
prefix_align = prefix_align.max(field.align);
prefix_align = prefix_align.max(field.align.abi);
}
}
}
Expand All @@ -989,8 +982,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
// Find the first field we can't move later
// to make room for a larger discriminant.
for field in st.fields.index_by_increasing_offset().map(|j| field_layouts[j]) {
if !field.is_zst() || field.align.abi() != 1 {
start_align = start_align.min(field.align);
if !field.is_zst() || field.align.abi.bytes() != 1 {
start_align = start_align.min(field.align.abi);
break;
}
}
Expand All @@ -1000,7 +993,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
}).collect::<Result<IndexVec<VariantIdx, _>, _>>()?;

// Align the maximum variant size to the largest alignment.
size = size.abi_align(align);
size = size.align_to(align.abi);

if size.bytes() >= dl.obj_size_bound() {
return Err(LayoutError::SizeOverflow(ty));
Expand Down Expand Up @@ -1036,7 +1029,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
let mut ity = if def.repr.c() || def.repr.int.is_some() {
min_ity
} else {
Integer::for_abi_align(dl, start_align).unwrap_or(min_ity)
Integer::for_align(dl, start_align).unwrap_or(min_ity)
};

// If the alignment is not larger than the chosen discriminant size,
Expand Down Expand Up @@ -1204,7 +1197,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
let type_desc = format!("{:?}", layout.ty);
self.tcx.sess.code_stats.borrow_mut().record_type_size(kind,
type_desc,
layout.align,
layout.align.abi,
layout.size,
packed,
opt_discr_size,
Expand Down Expand Up @@ -1251,7 +1244,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
name: name.to_string(),
offset: offset.bytes(),
size: field_layout.size.bytes(),
align: field_layout.align.abi(),
align: field_layout.align.abi.bytes(),
}
}
}
Expand All @@ -1264,7 +1257,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
} else {
session::SizeKind::Exact
},
align: layout.align.abi(),
align: layout.align.abi.bytes(),
size: if min_size.bytes() == 0 {
layout.size.bytes()
} else {
Expand Down Expand Up @@ -1823,7 +1816,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
Abi::ScalarPair(ref a, ref b) => {
// HACK(nox): We iter on `b` and then `a` because `max_by_key`
// returns the last maximum.
let niche = iter::once((b, a.value.size(self).abi_align(b.value.align(self))))
let niche = iter::once(
(b, a.value.size(self).align_to(b.value.align(self).abi))
)
.chain(iter::once((a, Size::ZERO)))
.filter_map(|(scalar, offset)| scalar_niche(scalar, offset))
.max_by_key(|niche| niche.available);
Expand Down Expand Up @@ -1994,12 +1989,16 @@ impl_stable_hash_for!(enum ::ty::layout::Primitive {
Pointer
});

impl_stable_hash_for!(struct ::ty::layout::AbiAndPrefAlign {
abi,
pref
});

impl<'gcx> HashStable<StableHashingContext<'gcx>> for Align {
fn hash_stable<W: StableHasherResult>(&self,
hcx: &mut StableHashingContext<'gcx>,
hasher: &mut StableHasher<W>) {
self.abi().hash_stable(hcx, hasher);
self.pref().hash_stable(hcx, hasher);
self.bytes().hash_stable(hcx, hasher);
}
}

Expand Down
14 changes: 7 additions & 7 deletions src/librustc_codegen_llvm/abi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -73,7 +73,7 @@ impl ArgAttributesExt for ArgAttributes {
if let Some(align) = self.pointee_align {
llvm::LLVMRustAddAlignmentAttr(llfn,
idx.as_uint(),
align.abi() as u32);
align.bytes() as u32);
}
regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
}
Expand All @@ -98,7 +98,7 @@ impl ArgAttributesExt for ArgAttributes {
if let Some(align) = self.pointee_align {
llvm::LLVMRustAddAlignmentCallSiteAttr(callsite,
idx.as_uint(),
align.abi() as u32);
align.bytes() as u32);
}
regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
}
Expand Down Expand Up @@ -204,7 +204,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
return;
}
if self.is_sized_indirect() {
OperandValue::Ref(val, None, self.layout.align).store(bx, dst)
OperandValue::Ref(val, None, self.layout.align.abi).store(bx, dst)
} else if self.is_unsized_indirect() {
bug!("unsized ArgType must be handled through store_fn_arg");
} else if let PassMode::Cast(cast) = self.mode {
Expand All @@ -214,7 +214,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
if can_store_through_cast_ptr {
let cast_ptr_llty = bx.cx().type_ptr_to(cast.llvm_type(bx.cx()));
let cast_dst = bx.pointercast(dst.llval, cast_ptr_llty);
bx.store(val, cast_dst, self.layout.align);
bx.store(val, cast_dst, self.layout.align.abi);
} else {
// The actual return type is a struct, but the ABI
// adaptation code has cast it into some scalar type. The
Expand Down Expand Up @@ -242,7 +242,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
// ...and then memcpy it to the intended destination.
bx.memcpy(
dst.llval,
self.layout.align,
self.layout.align.abi,
llscratch,
scratch_align,
bx.cx().const_usize(self.layout.size.bytes()),
Expand Down Expand Up @@ -273,7 +273,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
OperandValue::Pair(next(), next()).store(bx, dst);
}
PassMode::Indirect(_, Some(_)) => {
OperandValue::Ref(next(), Some(next()), self.layout.align).store(bx, dst);
OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst);
}
PassMode::Direct(_) | PassMode::Indirect(_, None) | PassMode::Cast(_) => {
self.store(bx, next(), dst);
Expand Down Expand Up @@ -545,7 +545,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
adjust_for_rust_scalar(&mut b_attrs,
b,
arg.layout,
a.value.size(cx).abi_align(b.value.align(cx)),
a.value.size(cx).align_to(b.value.align(cx).abi),
false);
arg.mode = PassMode::Pair(a_attrs, b_attrs);
return arg;
Expand Down
Loading