summaryrefslogtreecommitdiff
path: root/compiler/rustc_abi
diff options
context:
space:
mode:
authorThe 8472 <git@infinite-source.de>2023-03-05 16:15:16 +0100
committerThe 8472 <git@infinite-source.de>2023-04-27 22:29:03 +0200
commit4907dac54cc43d44bd6df87636e545756d110957 (patch)
treed6b8fcb18473ec627073db3466f181876eb3877e /compiler/rustc_abi
parentfaf2da3e2f04f525784fd4d41375e96a8356f4e3 (diff)
downloadrust-4907dac54cc43d44bd6df87636e545756d110957.tar.gz
don't promote large fields to higher alignments if that would affect niche placement
Diffstat (limited to 'compiler/rustc_abi')
-rw-r--r--compiler/rustc_abi/src/layout.rs37
1 files changed, 24 insertions, 13 deletions
diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs
index a833302d566..0b0fea4c500 100644
--- a/compiler/rustc_abi/src/layout.rs
+++ b/compiler/rustc_abi/src/layout.rs
@@ -772,19 +772,6 @@ fn univariant(
if optimize {
let end = if let StructKind::MaybeUnsized = kind { fields.len() - 1 } else { fields.len() };
let optimizing = &mut inverse_memory_index.raw[..end];
- let effective_field_align = |layout: Layout<'_>| {
- if let Some(pack) = pack {
- // return the packed alignment in bytes
- layout.align().abi.min(pack).bytes()
- } else {
- // returns log2(effective-align).
- // This is ok since `pack` applies to all fields equally.
- // The calculation assumes that size is an integer multiple of align, except for ZSTs.
- //
- // group [u8; 4] with align-4 or [u8; 6] with align-2 fields
- layout.align().abi.bytes().max(layout.size().bytes()).trailing_zeros() as u64
- }
- };
// If `-Z randomize-layout` was enabled for the type definition we can shuffle
// the field ordering to try and catch some code making assumptions about layouts
@@ -801,6 +788,30 @@ fn univariant(
}
// Otherwise we just leave things alone and actually optimize the type's fields
} else {
+ let max_field_align = fields.iter().map(|f| f.align().abi.bytes()).max().unwrap_or(1);
+ let any_niche = fields.iter().any(|f| f.largest_niche().is_some());
+ let effective_field_align = |layout: Layout<'_>| {
+ if let Some(pack) = pack {
+ // return the packed alignment in bytes
+ layout.align().abi.min(pack).bytes()
+ } else {
+ // returns log2(effective-align).
+ // This is ok since `pack` applies to all fields equally.
+ // The calculation assumes that size is an integer multiple of align, except for ZSTs.
+ //
+ // group [u8; 4] with align-4 or [u8; 6] with align-2 fields
+ let align = layout.align().abi.bytes();
+ let size = layout.size().bytes();
+ let size_as_align = align.max(size).trailing_zeros();
+ let size_as_align = if any_niche {
+ max_field_align.trailing_zeros().min(size_as_align)
+ } else {
+ size_as_align
+ };
+ size_as_align as u64
+ }
+ };
+
match kind {
StructKind::AlwaysSized | StructKind::MaybeUnsized => {
optimizing.sort_by_key(|&x| {