Skip to content

Commit 0171fe5

Browse files
authored
Rollup merge of rust-lang#59519 - eddyb:layout-variants-refactor, r=oli-obk
rustc_target: factor out common fields of non-Single Variants. @tmandry and I were discussing ways to generalize the current variants/discriminant layout to allow more fields in the "`enum`" (or another multi-variant types, such as potentially generator state, in the future), shared by all variants, than just the tag/niche discriminant. This refactor should make it easier to extend multi-variant layouts, as nothing is duplicating anymore between "tagged enums" and "niche-filling enums". r? @oli-obk
2 parents 245a0af + 5b7f4e9 commit 0171fe5

File tree

12 files changed

+193
-134
lines changed

12 files changed

+193
-134
lines changed

src/librustc/ty/layout.rs

+34-23
Original file line numberDiff line numberDiff line change
@@ -913,11 +913,13 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
913913
}
914914

915915
return Ok(tcx.intern_layout(LayoutDetails {
916-
variants: Variants::NicheFilling {
917-
dataful_variant: i,
918-
niche_variants,
919-
niche: niche_scalar,
920-
niche_start,
916+
variants: Variants::Multiple {
917+
discr: niche_scalar,
918+
discr_kind: DiscriminantKind::Niche {
919+
dataful_variant: i,
920+
niche_variants,
921+
niche_start,
922+
},
921923
variants: st,
922924
},
923925
fields: FieldPlacement::Arbitrary {
@@ -1137,8 +1139,9 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
11371139
}
11381140

11391141
tcx.intern_layout(LayoutDetails {
1140-
variants: Variants::Tagged {
1141-
tag,
1142+
variants: Variants::Multiple {
1143+
discr: tag,
1144+
discr_kind: DiscriminantKind::Tag,
11421145
variants: layout_variants,
11431146
},
11441147
fields: FieldPlacement::Arbitrary {
@@ -1293,8 +1296,7 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
12931296
}
12941297
}
12951298

1296-
Variants::NicheFilling { .. } |
1297-
Variants::Tagged { .. } => {
1299+
Variants::Multiple { ref discr, ref discr_kind, .. } => {
12981300
debug!("print-type-size `{:#?}` adt general variants def {}",
12991301
layout.ty, adt_def.variants.len());
13001302
let variant_infos: Vec<_> =
@@ -1306,8 +1308,8 @@ impl<'a, 'tcx> LayoutCx<'tcx, TyCtxt<'a, 'tcx, 'tcx>> {
13061308
layout.for_variant(self, i))
13071309
})
13081310
.collect();
1309-
record(adt_kind.into(), adt_packed, match layout.variants {
1310-
Variants::Tagged { ref tag, .. } => Some(tag.value.size(self)),
1311+
record(adt_kind.into(), adt_packed, match discr_kind {
1312+
DiscriminantKind::Tag => Some(discr.value.size(self)),
13111313
_ => None
13121314
}, variant_infos);
13131315
}
@@ -1627,8 +1629,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
16271629
})
16281630
}
16291631

1630-
Variants::NicheFilling { ref variants, .. } |
1631-
Variants::Tagged { ref variants, .. } => {
1632+
Variants::Multiple { ref variants, .. } => {
16321633
&variants[variant_index]
16331634
}
16341635
};
@@ -1735,8 +1736,7 @@ impl<'a, 'tcx, C> TyLayoutMethods<'tcx, C> for Ty<'tcx>
17351736
}
17361737

17371738
// Discriminant field for enums (where applicable).
1738-
Variants::Tagged { tag: ref discr, .. } |
1739-
Variants::NicheFilling { niche: ref discr, .. } => {
1739+
Variants::Multiple { ref discr, .. } => {
17401740
assert_eq!(i, 0);
17411741
let layout = LayoutDetails::scalar(cx, discr.clone());
17421742
return MaybeResult::from_ok(TyLayout {
@@ -1881,26 +1881,37 @@ impl<'a> HashStable<StableHashingContext<'a>> for Variants {
18811881
Single { index } => {
18821882
index.hash_stable(hcx, hasher);
18831883
}
1884-
Tagged {
1885-
ref tag,
1884+
Multiple {
1885+
ref discr,
1886+
ref discr_kind,
18861887
ref variants,
18871888
} => {
1888-
tag.hash_stable(hcx, hasher);
1889+
discr.hash_stable(hcx, hasher);
1890+
discr_kind.hash_stable(hcx, hasher);
18891891
variants.hash_stable(hcx, hasher);
18901892
}
1891-
NicheFilling {
1893+
}
1894+
}
1895+
}
1896+
1897+
impl<'a> HashStable<StableHashingContext<'a>> for DiscriminantKind {
1898+
fn hash_stable<W: StableHasherResult>(&self,
1899+
hcx: &mut StableHashingContext<'a>,
1900+
hasher: &mut StableHasher<W>) {
1901+
use crate::ty::layout::DiscriminantKind::*;
1902+
mem::discriminant(self).hash_stable(hcx, hasher);
1903+
1904+
match *self {
1905+
Tag => {}
1906+
Niche {
18921907
dataful_variant,
18931908
ref niche_variants,
1894-
ref niche,
18951909
niche_start,
1896-
ref variants,
18971910
} => {
18981911
dataful_variant.hash_stable(hcx, hasher);
18991912
niche_variants.start().hash_stable(hcx, hasher);
19001913
niche_variants.end().hash_stable(hcx, hasher);
1901-
niche.hash_stable(hcx, hasher);
19021914
niche_start.hash_stable(hcx, hasher);
1903-
variants.hash_stable(hcx, hasher);
19041915
}
19051916
}
19061917
}

src/librustc_codegen_llvm/debuginfo/metadata.rs

+48-20
Original file line numberDiff line numberDiff line change
@@ -1246,7 +1246,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
12461246
}
12471247
]
12481248
}
1249-
layout::Variants::Tagged { ref variants, .. } => {
1249+
layout::Variants::Multiple {
1250+
discr_kind: layout::DiscriminantKind::Tag,
1251+
ref variants,
1252+
..
1253+
} => {
12501254
let discriminant_info = if fallback {
12511255
RegularDiscriminant(self.discriminant_type_metadata
12521256
.expect(""))
@@ -1288,12 +1292,14 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
12881292
}
12891293
}).collect()
12901294
}
1291-
layout::Variants::NicheFilling {
1292-
ref niche_variants,
1293-
niche_start,
1295+
layout::Variants::Multiple {
1296+
discr_kind: layout::DiscriminantKind::Niche {
1297+
ref niche_variants,
1298+
niche_start,
1299+
dataful_variant,
1300+
},
1301+
ref discr,
12941302
ref variants,
1295-
dataful_variant,
1296-
ref niche,
12971303
} => {
12981304
if fallback {
12991305
let variant = self.layout.for_variant(cx, dataful_variant);
@@ -1380,7 +1386,11 @@ impl EnumMemberDescriptionFactory<'ll, 'tcx> {
13801386
let value = (i.as_u32() as u128)
13811387
.wrapping_sub(niche_variants.start().as_u32() as u128)
13821388
.wrapping_add(niche_start);
1383-
let value = truncate(value, niche.value.size(cx));
1389+
let value = truncate(value, discr.value.size(cx));
1390+
// NOTE(eddyb) do *NOT* remove this assert, until
1391+
// we pass the full 128-bit value to LLVM, otherwise
1392+
// truncation will be silent and remain undetected.
1393+
assert_eq!(value as u64 as u128, value);
13841394
Some(value as u64)
13851395
};
13861396

@@ -1597,8 +1607,11 @@ fn prepare_enum_metadata(
15971607
let layout = cx.layout_of(enum_type);
15981608

15991609
match (&layout.abi, &layout.variants) {
1600-
(&layout::Abi::Scalar(_), &layout::Variants::Tagged {ref tag, .. }) =>
1601-
return FinalMetadata(discriminant_type_metadata(tag.value)),
1610+
(&layout::Abi::Scalar(_), &layout::Variants::Multiple {
1611+
discr_kind: layout::DiscriminantKind::Tag,
1612+
ref discr,
1613+
..
1614+
}) => return FinalMetadata(discriminant_type_metadata(discr.value)),
16021615
_ => {}
16031616
}
16041617

@@ -1610,9 +1623,16 @@ fn prepare_enum_metadata(
16101623
if use_enum_fallback(cx) {
16111624
let discriminant_type_metadata = match layout.variants {
16121625
layout::Variants::Single { .. } |
1613-
layout::Variants::NicheFilling { .. } => None,
1614-
layout::Variants::Tagged { ref tag, .. } => {
1615-
Some(discriminant_type_metadata(tag.value))
1626+
layout::Variants::Multiple {
1627+
discr_kind: layout::DiscriminantKind::Niche { .. },
1628+
..
1629+
} => None,
1630+
layout::Variants::Multiple {
1631+
discr_kind: layout::DiscriminantKind::Tag,
1632+
ref discr,
1633+
..
1634+
} => {
1635+
Some(discriminant_type_metadata(discr.value))
16161636
}
16171637
};
16181638

@@ -1647,16 +1667,20 @@ fn prepare_enum_metadata(
16471667
);
16481668
}
16491669

1650-
let discriminator_metadata = match &layout.variants {
1670+
let discriminator_metadata = match layout.variants {
16511671
// A single-variant enum has no discriminant.
1652-
&layout::Variants::Single { .. } => None,
1672+
layout::Variants::Single { .. } => None,
16531673

1654-
&layout::Variants::NicheFilling { ref niche, .. } => {
1674+
layout::Variants::Multiple {
1675+
discr_kind: layout::DiscriminantKind::Niche { .. },
1676+
ref discr,
1677+
..
1678+
} => {
16551679
// Find the integer type of the correct size.
1656-
let size = niche.value.size(cx);
1657-
let align = niche.value.align(cx);
1680+
let size = discr.value.size(cx);
1681+
let align = discr.value.align(cx);
16581682

1659-
let discr_type = match niche.value {
1683+
let discr_type = match discr.value {
16601684
layout::Int(t, _) => t,
16611685
layout::Float(layout::FloatTy::F32) => Integer::I32,
16621686
layout::Float(layout::FloatTy::F64) => Integer::I64,
@@ -1679,8 +1703,12 @@ fn prepare_enum_metadata(
16791703
}
16801704
},
16811705

1682-
&layout::Variants::Tagged { ref tag, .. } => {
1683-
let discr_type = tag.value.to_ty(cx.tcx);
1706+
layout::Variants::Multiple {
1707+
discr_kind: layout::DiscriminantKind::Tag,
1708+
ref discr,
1709+
..
1710+
} => {
1711+
let discr_type = discr.value.to_ty(cx.tcx);
16841712
let (size, align) = cx.size_and_align_of(discr_type);
16851713

16861714
let discr_metadata = basic_type_metadata(cx, discr_type);

src/librustc_codegen_llvm/type_of.rs

+7-1
Original file line numberDiff line numberDiff line change
@@ -452,7 +452,13 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
452452

453453
_ => {
454454
let mut data_variant = match self.variants {
455-
layout::Variants::NicheFilling { dataful_variant, .. } => {
455+
layout::Variants::Multiple {
456+
discr_kind: layout::DiscriminantKind::Niche {
457+
dataful_variant,
458+
..
459+
},
460+
..
461+
} => {
456462
// Only the niche itself is always initialized,
457463
// so only check for a pointer at its offset.
458464
//

src/librustc_codegen_ssa/mir/place.rs

+20-16
Original file line numberDiff line numberDiff line change
@@ -216,37 +216,36 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
216216
if self.layout.abi.is_uninhabited() {
217217
return bx.cx().const_undef(cast_to);
218218
}
219-
match self.layout.variants {
219+
let (discr_scalar, discr_kind) = match self.layout.variants {
220220
layout::Variants::Single { index } => {
221221
let discr_val = self.layout.ty.ty_adt_def().map_or(
222222
index.as_u32() as u128,
223223
|def| def.discriminant_for_variant(bx.cx().tcx(), index).val);
224224
return bx.cx().const_uint_big(cast_to, discr_val);
225225
}
226-
layout::Variants::Tagged { .. } |
227-
layout::Variants::NicheFilling { .. } => {},
228-
}
226+
layout::Variants::Multiple { ref discr, ref discr_kind, .. } => {
227+
(discr, discr_kind)
228+
}
229+
};
229230

230231
let discr = self.project_field(bx, 0);
231232
let lldiscr = bx.load_operand(discr).immediate();
232-
match self.layout.variants {
233-
layout::Variants::Single { .. } => bug!(),
234-
layout::Variants::Tagged { ref tag, .. } => {
235-
let signed = match tag.value {
233+
match *discr_kind {
234+
layout::DiscriminantKind::Tag => {
235+
let signed = match discr_scalar.value {
236236
// We use `i1` for bytes that are always `0` or `1`,
237237
// e.g., `#[repr(i8)] enum E { A, B }`, but we can't
238238
// let LLVM interpret the `i1` as signed, because
239239
// then `i1 1` (i.e., E::B) is effectively `i8 -1`.
240-
layout::Int(_, signed) => !tag.is_bool() && signed,
240+
layout::Int(_, signed) => !discr_scalar.is_bool() && signed,
241241
_ => false
242242
};
243243
bx.intcast(lldiscr, cast_to, signed)
244244
}
245-
layout::Variants::NicheFilling {
245+
layout::DiscriminantKind::Niche {
246246
dataful_variant,
247247
ref niche_variants,
248248
niche_start,
249-
..
250249
} => {
251250
let niche_llty = bx.cx().immediate_backend_type(discr.layout);
252251
if niche_variants.start() == niche_variants.end() {
@@ -291,7 +290,10 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
291290
layout::Variants::Single { index } => {
292291
assert_eq!(index, variant_index);
293292
}
294-
layout::Variants::Tagged { .. } => {
293+
layout::Variants::Multiple {
294+
discr_kind: layout::DiscriminantKind::Tag,
295+
..
296+
} => {
295297
let ptr = self.project_field(bx, 0);
296298
let to = self.layout.ty.ty_adt_def().unwrap()
297299
.discriminant_for_variant(bx.tcx(), variant_index)
@@ -301,10 +303,12 @@ impl<'a, 'tcx: 'a, V: CodegenObject> PlaceRef<'tcx, V> {
301303
ptr.llval,
302304
ptr.align);
303305
}
304-
layout::Variants::NicheFilling {
305-
dataful_variant,
306-
ref niche_variants,
307-
niche_start,
306+
layout::Variants::Multiple {
307+
discr_kind: layout::DiscriminantKind::Niche {
308+
dataful_variant,
309+
ref niche_variants,
310+
niche_start,
311+
},
308312
..
309313
} => {
310314
if variant_index != dataful_variant {

src/librustc_codegen_ssa/mir/rvalue.rs

+1-2
Original file line numberDiff line numberDiff line change
@@ -282,8 +282,7 @@ impl<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
282282
});
283283
}
284284
}
285-
layout::Variants::Tagged { .. } |
286-
layout::Variants::NicheFilling { .. } => {},
285+
layout::Variants::Multiple { .. } => {},
287286
}
288287
let llval = operand.immediate();
289288

0 commit comments

Comments
 (0)