Skip to content

Commit 6a2d1b4

Browse files
committed
Auto merge of #54071 - eddyb:alignsssss, r=oli-obk
rustc_target: separate out an individual alignment quantity type from Align. Before this PR, `rustc_target::abi::Align` combined "power-of-two alignment quantity" semantics, with a distinction between ABI (required) and preferred alignment (by having two quantities). After this PR, `Align` is only *one* such quantity, and a new `AbiAndPrefAlign` type is introduced to hold the pair of ABI and preferred `Align` quantities. `Align` is used everywhere one quantity is necessary/sufficient, simplifying some of the code in codegen/miri, while `AbiAndPrefAlign` only in layout computation (to propagate preferred alignment). r? @oli-obk cc @nagisa @RalfJung @nikomatsakis
2 parents 00e03ee + 5b4747d commit 6a2d1b4

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+363
-374
lines changed

src/librustc/mir/interpret/allocation.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ impl<Tag, Extra: Default> Allocation<Tag, Extra> {
104104
}
105105

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

110110
pub fn undef(size: Size, align: Align) -> Self {

src/librustc/mir/interpret/error.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -527,7 +527,7 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
527527
write!(f, "tried to interpret an invalid 32-bit value as a char: {}", c),
528528
AlignmentCheckFailed { required, has } =>
529529
write!(f, "tried to access memory with alignment {}, but alignment {} is required",
530-
has.abi(), required.abi()),
530+
has.bytes(), required.bytes()),
531531
TypeNotPrimitive(ty) =>
532532
write!(f, "expected primitive type, got {}", ty),
533533
Layout(ref err) =>
@@ -537,8 +537,9 @@ impl<'tcx, O: fmt::Debug> fmt::Debug for EvalErrorKind<'tcx, O> {
537537
MachineError(ref inner) =>
538538
write!(f, "{}", inner),
539539
IncorrectAllocationInformation(size, size2, align, align2) =>
540-
write!(f, "incorrect alloc info: expected size {} and align {}, got size {} and \
541-
align {}", size.bytes(), align.abi(), size2.bytes(), align2.abi()),
540+
write!(f, "incorrect alloc info: expected size {} and align {}, \
541+
got size {} and align {}",
542+
size.bytes(), align.bytes(), size2.bytes(), align2.bytes()),
542543
Panic { ref msg, line, col, ref file } =>
543544
write!(f, "the evaluated program panicked at '{}', {}:{}:{}", msg, file, line, col),
544545
InvalidDiscriminant(val) =>

src/librustc/session/code_stats.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ impl CodeStats {
7171
let info = TypeSizeInfo {
7272
kind,
7373
type_description: type_desc.to_string(),
74-
align: align.abi(),
74+
align: align.bytes(),
7575
overall_size: overall_size.bytes(),
7676
packed: packed,
7777
opt_discr_size: opt_discr_size.map(|s| s.bytes()),

src/librustc/ty/layout.rs

+52-53
Original file line numberDiff line numberDiff line change
@@ -226,9 +226,10 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
226226
tcx.intern_layout(LayoutDetails::scalar(self, scalar_unit(value)))
227227
};
228228
let scalar_pair = |a: Scalar, b: Scalar| {
229-
let align = a.value.align(dl).max(b.value.align(dl)).max(dl.aggregate_align);
230-
let b_offset = a.value.size(dl).abi_align(b.value.align(dl));
231-
let size = (b_offset + b.value.size(dl)).abi_align(align);
229+
let b_align = b.value.align(dl);
230+
let align = a.value.align(dl).max(b_align).max(dl.aggregate_align);
231+
let b_offset = a.value.size(dl).align_to(b_align.abi);
232+
let size = (b_offset + b.value.size(dl)).align_to(align.abi);
232233
LayoutDetails {
233234
variants: Variants::Single { index: VariantIdx::new(0) },
234235
fields: FieldPlacement::Arbitrary {
@@ -257,10 +258,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
257258
bug!("struct cannot be packed and aligned");
258259
}
259260

260-
let pack = {
261-
let pack = repr.pack as u64;
262-
Align::from_bytes(pack, pack).unwrap()
263-
};
261+
let pack = Align::from_bytes(repr.pack as u64).unwrap();
264262

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

275273
let mut optimize = !repr.inhibit_struct_field_reordering_opt();
276274
if let StructKind::Prefixed(_, align) = kind {
277-
optimize &= align.abi() == 1;
275+
optimize &= align.bytes() == 1;
278276
}
279277

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

314312
if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
315-
if packed {
316-
let prefix_align = prefix_align.min(pack);
317-
align = align.max(prefix_align);
313+
let prefix_align = if packed {
314+
prefix_align.min(pack)
318315
} else {
319-
align = align.max(prefix_align);
320-
}
321-
offset = prefix_size.abi_align(prefix_align);
316+
prefix_align
317+
};
318+
align = align.max(AbiAndPrefAlign::new(prefix_align));
319+
offset = prefix_size.align_to(prefix_align);
322320
}
323321

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

335333
// Invariant: offset < dl.obj_size_bound() <= 1<<61
336-
if packed {
337-
let field_pack = field.align.min(pack);
338-
offset = offset.abi_align(field_pack);
339-
align = align.max(field_pack);
340-
}
341-
else {
342-
offset = offset.abi_align(field.align);
343-
align = align.max(field.align);
344-
}
334+
let field_align = if packed {
335+
field.align.min(AbiAndPrefAlign::new(pack))
336+
} else {
337+
field.align
338+
};
339+
offset = offset.align_to(field_align.abi);
340+
align = align.max(field_align);
345341

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

353349
if repr.align > 0 {
354350
let repr_align = repr.align as u64;
355-
align = align.max(Align::from_bytes(repr_align, repr_align).unwrap());
351+
align = align.max(AbiAndPrefAlign::new(Align::from_bytes(repr_align).unwrap()));
356352
debug!("univariant repr_align: {:?}", repr_align);
357353
}
358354

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

380-
let size = min_size.abi_align(align);
376+
let size = min_size.align_to(align.abi);
381377
let mut abi = Abi::Aggregate { sized };
382378

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

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

683-
let pack = {
684-
let pack = def.repr.pack as u64;
685-
Align::from_bytes(pack, pack).unwrap()
686-
};
679+
let pack = Align::from_bytes(def.repr.pack as u64).unwrap();
687680

688681
let mut align = if packed {
689682
dl.i8_align
@@ -694,7 +687,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
694687
if def.repr.align > 0 {
695688
let repr_align = def.repr.align as u64;
696689
align = align.max(
697-
Align::from_bytes(repr_align, repr_align).unwrap());
690+
AbiAndPrefAlign::new(Align::from_bytes(repr_align).unwrap()));
698691
}
699692

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

707-
if packed {
708-
let field_pack = field.align.min(pack);
709-
align = align.max(field_pack);
700+
let field_align = if packed {
701+
field.align.min(AbiAndPrefAlign::new(pack))
710702
} else {
711-
align = align.max(field.align);
712-
}
703+
field.align
704+
};
705+
align = align.max(field_align);
713706

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

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

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

970963
// repr(C) on an enum tells us to make a (tag, union) layout,
971964
// so we need to grow the prefix alignment to be at least
972965
// the alignment of the union. (This value is used both for
973966
// determining the alignment of the overall enum, and the
974967
// determining the alignment of the payload after the tag.)
975-
let mut prefix_align = min_ity.align(dl);
968+
let mut prefix_align = min_ity.align(dl).abi;
976969
if def.repr.c() {
977970
for fields in &variants {
978971
for field in fields {
979-
prefix_align = prefix_align.max(field.align);
972+
prefix_align = prefix_align.max(field.align.abi);
980973
}
981974
}
982975
}
@@ -989,8 +982,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
989982
// Find the first field we can't move later
990983
// to make room for a larger discriminant.
991984
for field in st.fields.index_by_increasing_offset().map(|j| field_layouts[j]) {
992-
if !field.is_zst() || field.align.abi() != 1 {
993-
start_align = start_align.min(field.align);
985+
if !field.is_zst() || field.align.abi.bytes() != 1 {
986+
start_align = start_align.min(field.align.abi);
994987
break;
995988
}
996989
}
@@ -1000,7 +993,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
1000993
}).collect::<Result<IndexVec<VariantIdx, _>, _>>()?;
1001994

1002995
// Align the maximum variant size to the largest alignment.
1003-
size = size.abi_align(align);
996+
size = size.align_to(align.abi);
1004997

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

10421035
// If the alignment is not larger than the chosen discriminant size,
@@ -1204,7 +1197,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
12041197
let type_desc = format!("{:?}", layout.ty);
12051198
self.tcx.sess.code_stats.borrow_mut().record_type_size(kind,
12061199
type_desc,
1207-
layout.align,
1200+
layout.align.abi,
12081201
layout.size,
12091202
packed,
12101203
opt_discr_size,
@@ -1251,7 +1244,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
12511244
name: name.to_string(),
12521245
offset: offset.bytes(),
12531246
size: field_layout.size.bytes(),
1254-
align: field_layout.align.abi(),
1247+
align: field_layout.align.abi.bytes(),
12551248
}
12561249
}
12571250
}
@@ -1264,7 +1257,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
12641257
} else {
12651258
session::SizeKind::Exact
12661259
},
1267-
align: layout.align.abi(),
1260+
align: layout.align.abi.bytes(),
12681261
size: if min_size.bytes() == 0 {
12691262
layout.size.bytes()
12701263
} else {
@@ -1823,7 +1816,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
18231816
Abi::ScalarPair(ref a, ref b) => {
18241817
// HACK(nox): We iter on `b` and then `a` because `max_by_key`
18251818
// returns the last maximum.
1826-
let niche = iter::once((b, a.value.size(self).abi_align(b.value.align(self))))
1819+
let niche = iter::once(
1820+
(b, a.value.size(self).align_to(b.value.align(self).abi))
1821+
)
18271822
.chain(iter::once((a, Size::ZERO)))
18281823
.filter_map(|(scalar, offset)| scalar_niche(scalar, offset))
18291824
.max_by_key(|niche| niche.available);
@@ -1994,12 +1989,16 @@ impl_stable_hash_for!(enum ::ty::layout::Primitive {
19941989
Pointer
19951990
});
19961991

1992+
impl_stable_hash_for!(struct ::ty::layout::AbiAndPrefAlign {
1993+
abi,
1994+
pref
1995+
});
1996+
19971997
impl<'gcx> HashStable<StableHashingContext<'gcx>> for Align {
19981998
fn hash_stable<W: StableHasherResult>(&self,
19991999
hcx: &mut StableHashingContext<'gcx>,
20002000
hasher: &mut StableHasher<W>) {
2001-
self.abi().hash_stable(hcx, hasher);
2002-
self.pref().hash_stable(hcx, hasher);
2001+
self.bytes().hash_stable(hcx, hasher);
20032002
}
20042003
}
20052004

src/librustc_codegen_llvm/abi.rs

+7-7
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ impl ArgAttributesExt for ArgAttributes {
7373
if let Some(align) = self.pointee_align {
7474
llvm::LLVMRustAddAlignmentAttr(llfn,
7575
idx.as_uint(),
76-
align.abi() as u32);
76+
align.bytes() as u32);
7777
}
7878
regular.for_each_kind(|attr| attr.apply_llfn(idx, llfn));
7979
}
@@ -98,7 +98,7 @@ impl ArgAttributesExt for ArgAttributes {
9898
if let Some(align) = self.pointee_align {
9999
llvm::LLVMRustAddAlignmentCallSiteAttr(callsite,
100100
idx.as_uint(),
101-
align.abi() as u32);
101+
align.bytes() as u32);
102102
}
103103
regular.for_each_kind(|attr| attr.apply_callsite(idx, callsite));
104104
}
@@ -204,7 +204,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
204204
return;
205205
}
206206
if self.is_sized_indirect() {
207-
OperandValue::Ref(val, None, self.layout.align).store(bx, dst)
207+
OperandValue::Ref(val, None, self.layout.align.abi).store(bx, dst)
208208
} else if self.is_unsized_indirect() {
209209
bug!("unsized ArgType must be handled through store_fn_arg");
210210
} else if let PassMode::Cast(cast) = self.mode {
@@ -214,7 +214,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
214214
if can_store_through_cast_ptr {
215215
let cast_ptr_llty = bx.cx().type_ptr_to(cast.llvm_type(bx.cx()));
216216
let cast_dst = bx.pointercast(dst.llval, cast_ptr_llty);
217-
bx.store(val, cast_dst, self.layout.align);
217+
bx.store(val, cast_dst, self.layout.align.abi);
218218
} else {
219219
// The actual return type is a struct, but the ABI
220220
// adaptation code has cast it into some scalar type. The
@@ -242,7 +242,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
242242
// ...and then memcpy it to the intended destination.
243243
bx.memcpy(
244244
dst.llval,
245-
self.layout.align,
245+
self.layout.align.abi,
246246
llscratch,
247247
scratch_align,
248248
bx.cx().const_usize(self.layout.size.bytes()),
@@ -273,7 +273,7 @@ impl ArgTypeExt<'ll, 'tcx> for ArgType<'tcx, Ty<'tcx>> {
273273
OperandValue::Pair(next(), next()).store(bx, dst);
274274
}
275275
PassMode::Indirect(_, Some(_)) => {
276-
OperandValue::Ref(next(), Some(next()), self.layout.align).store(bx, dst);
276+
OperandValue::Ref(next(), Some(next()), self.layout.align.abi).store(bx, dst);
277277
}
278278
PassMode::Direct(_) | PassMode::Indirect(_, None) | PassMode::Cast(_) => {
279279
self.store(bx, next(), dst);
@@ -545,7 +545,7 @@ impl<'tcx> FnTypeExt<'tcx> for FnType<'tcx, Ty<'tcx>> {
545545
adjust_for_rust_scalar(&mut b_attrs,
546546
b,
547547
arg.layout,
548-
a.value.size(cx).abi_align(b.value.align(cx)),
548+
a.value.size(cx).align_to(b.value.align(cx).abi),
549549
false);
550550
arg.mode = PassMode::Pair(a_attrs, b_attrs);
551551
return arg;

0 commit comments

Comments
 (0)