Skip to content

Commit 00b3eca

Browse files
move has_repr to layout, handle repr(transparent) properly
1 parent 65d11b5 commit 00b3eca

File tree

6 files changed

+34
-25
lines changed

6 files changed

+34
-25
lines changed

compiler/rustc_abi/src/layout.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ pub trait LayoutCalculator {
4040
largest_niche,
4141
align,
4242
size,
43+
has_repr_align: false,
4344
}
4445
}
4546

@@ -122,6 +123,7 @@ pub trait LayoutCalculator {
122123
largest_niche: None,
123124
align: dl.i8_align,
124125
size: Size::ZERO,
126+
has_repr_align: false,
125127
}
126128
}
127129

@@ -422,6 +424,7 @@ pub trait LayoutCalculator {
422424
largest_niche,
423425
size,
424426
align,
427+
has_repr_align: repr.align.is_some(),
425428
};
426429

427430
Some(TmpLayout { layout, variants: variant_layouts })
@@ -691,6 +694,7 @@ pub trait LayoutCalculator {
691694
abi,
692695
align,
693696
size,
697+
has_repr_align: repr.align.is_some(),
694698
};
695699

696700
let tagged_layout = TmpLayout { layout: tagged_layout, variants: layout_variants };
@@ -809,6 +813,7 @@ pub trait LayoutCalculator {
809813
largest_niche: None,
810814
align,
811815
size: size.align_to(align.abi),
816+
has_repr_align: repr.align.is_some(),
812817
})
813818
}
814819
}
@@ -1036,6 +1041,7 @@ fn univariant(
10361041
inverse_memory_index.into_iter().map(FieldIdx::as_u32).collect()
10371042
};
10381043
let size = min_size.align_to(align.abi);
1044+
let mut layout_of_single_non_zst_field = None;
10391045
let mut abi = Abi::Aggregate { sized };
10401046
// Unpack newtype ABIs and find scalar pairs.
10411047
if sized && size.bytes() > 0 {
@@ -1045,6 +1051,8 @@ fn univariant(
10451051
match (non_zst_fields.next(), non_zst_fields.next(), non_zst_fields.next()) {
10461052
// We have exactly one non-ZST field.
10471053
(Some((i, field)), None, None) => {
1054+
layout_of_single_non_zst_field = Some(field);
1055+
10481056
// Field fills the struct and it has a scalar or scalar pair ABI.
10491057
if offsets[i].bytes() == 0 && align.abi == field.align().abi && size == field.size()
10501058
{
@@ -1102,13 +1110,19 @@ fn univariant(
11021110
if fields.iter().any(|f| f.abi().is_uninhabited()) {
11031111
abi = Abi::Uninhabited;
11041112
}
1113+
1114+
let has_repr_align = repr.align.is_some()
1115+
|| repr.transparent()
1116+
&& layout_of_single_non_zst_field.map_or(false, |l| l.has_repr_align());
1117+
11051118
Some(LayoutS {
11061119
variants: Variants::Single { index: FIRST_VARIANT },
11071120
fields: FieldsShape::Arbitrary { offsets, memory_index },
11081121
abi,
11091122
largest_niche,
11101123
align,
11111124
size,
1125+
has_repr_align,
11121126
})
11131127
}
11141128

compiler/rustc_abi/src/lib.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1531,6 +1531,11 @@ pub struct LayoutS {
15311531

15321532
pub align: AbiAndPrefAlign,
15331533
pub size: Size,
1534+
1535+
/// True if the alignment was explicitly requested with `repr(align)`.
1536+
/// Only used on i686-windows, where the argument passing ABI is different when alignment is
1537+
/// requested, even if the requested alignment is equal to or less than the natural alignment.
1538+
pub has_repr_align: bool,
15341539
}
15351540

15361541
impl LayoutS {
@@ -1545,6 +1550,7 @@ impl LayoutS {
15451550
largest_niche,
15461551
size,
15471552
align,
1553+
has_repr_align: false,
15481554
}
15491555
}
15501556
}
@@ -1554,14 +1560,15 @@ impl fmt::Debug for LayoutS {
15541560
// This is how `Layout` used to print before it become
15551561
// `Interned<LayoutS>`. We print it like this to avoid having to update
15561562
// expected output in a lot of tests.
1557-
let LayoutS { size, align, abi, fields, largest_niche, variants } = self;
1563+
let LayoutS { size, align, abi, fields, largest_niche, variants, has_repr_align } = self;
15581564
f.debug_struct("Layout")
15591565
.field("size", size)
15601566
.field("align", align)
15611567
.field("abi", abi)
15621568
.field("fields", fields)
15631569
.field("largest_niche", largest_niche)
15641570
.field("variants", variants)
1571+
.field("has_repr_align", has_repr_align)
15651572
.finish()
15661573
}
15671574
}
@@ -1602,6 +1609,10 @@ impl<'a> Layout<'a> {
16021609
self.0.0.size
16031610
}
16041611

1612+
pub fn has_repr_align(self) -> bool {
1613+
self.0.0.has_repr_align
1614+
}
1615+
16051616
/// Whether the layout is from a type that implements [`std::marker::PointerLike`].
16061617
///
16071618
/// Currently, that means that the type is pointer-sized, pointer-aligned,

compiler/rustc_middle/src/ty/layout.rs

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -755,6 +755,7 @@ where
755755
largest_niche: None,
756756
align: tcx.data_layout.i8_align,
757757
size: Size::ZERO,
758+
has_repr_align: false,
758759
})
759760
}
760761

@@ -1104,15 +1105,6 @@ where
11041105
fn is_unit(this: TyAndLayout<'tcx>) -> bool {
11051106
matches!(this.ty.kind(), ty::Tuple(list) if list.len() == 0)
11061107
}
1107-
1108-
fn repr_options(this: TyAndLayout<'tcx>) -> ReprOptions {
1109-
match *this.ty.kind() {
1110-
ty::Adt(def, ..) => def.repr(),
1111-
_ => {
1112-
bug!("TyAndLayout::repr_options({:?}): not applicable", this)
1113-
}
1114-
}
1115-
}
11161108
}
11171109

11181110
/// Calculates whether a function's ABI can unwind or not.

compiler/rustc_target/src/abi/call/x86.rs

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -63,20 +63,15 @@ where
6363

6464
if t.is_like_msvc
6565
&& arg.layout.is_adt()
66-
&& let Some(requested_align) = arg.layout.repr_options().align
67-
&& requested_align > align_4
66+
&& arg.layout.has_repr_align
67+
&& arg.layout.align.abi > align_4
6868
{
6969
// MSVC has special rules for overaligned arguments: https://reviews.llvm.org/D72114.
7070
// Summarized here:
7171
// - Arguments with _requested_ alignment > 4 are passed indirectly.
7272
// - For backwards compatibility, arguments with natural alignment > 4 are still passed
7373
// on stack (via `byval`). For example, this includes `double`, `int64_t`,
7474
// and structs containing them, provided they lack an explicit alignment attribute.
75-
assert!(arg.layout.align.abi >= requested_align,
76-
"abi alignment {:?} less than requested alignment {:?}",
77-
arg.layout.align.abi,
78-
requested_align
79-
);
8075
arg.make_indirect();
8176
} else if arg.layout.is_aggregate() {
8277
// We need to compute the alignment of the `byval` argument. The rules can be found in

compiler/rustc_target/src/abi/mod.rs

Lines changed: 0 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ pub trait TyAbiInterface<'a, C>: Sized {
5555
fn is_never(this: TyAndLayout<'a, Self>) -> bool;
5656
fn is_tuple(this: TyAndLayout<'a, Self>) -> bool;
5757
fn is_unit(this: TyAndLayout<'a, Self>) -> bool;
58-
fn repr_options(this: TyAndLayout<'a, Self>) -> ReprOptions;
5958
}
6059

6160
impl<'a, Ty> TyAndLayout<'a, Ty> {
@@ -126,13 +125,6 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
126125
Ty::is_unit(self)
127126
}
128127

129-
pub fn repr_options<C>(self) -> ReprOptions
130-
where
131-
Ty: TyAbiInterface<'a, C>,
132-
{
133-
Ty::repr_options(self)
134-
}
135-
136128
pub fn offset_of_subfield<C>(self, cx: &C, indices: impl Iterator<Item = usize>) -> Size
137129
where
138130
Ty: TyAbiInterface<'a, C>,

compiler/rustc_ty_utils/src/layout.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,7 @@ fn layout_of_uncached<'tcx>(
258258
largest_niche,
259259
align: element.align,
260260
size,
261+
has_repr_align: false,
261262
})
262263
}
263264
ty::Slice(element) => {
@@ -269,6 +270,7 @@ fn layout_of_uncached<'tcx>(
269270
largest_niche: None,
270271
align: element.align,
271272
size: Size::ZERO,
273+
has_repr_align: false,
272274
})
273275
}
274276
ty::Str => tcx.mk_layout(LayoutS {
@@ -278,6 +280,7 @@ fn layout_of_uncached<'tcx>(
278280
largest_niche: None,
279281
align: dl.i8_align,
280282
size: Size::ZERO,
283+
has_repr_align: false,
281284
}),
282285

283286
// Odd unit types.
@@ -431,6 +434,7 @@ fn layout_of_uncached<'tcx>(
431434
largest_niche: e_ly.largest_niche,
432435
size,
433436
align,
437+
has_repr_align: false,
434438
})
435439
}
436440

@@ -879,6 +883,7 @@ fn generator_layout<'tcx>(
879883
largest_niche: prefix.largest_niche,
880884
size,
881885
align,
886+
has_repr_align: false,
882887
});
883888
debug!("generator layout ({:?}): {:#?}", ty, layout);
884889
Ok(layout)

0 commit comments

Comments
 (0)