Skip to content

Commit f16f182

Browse files
committed
StructKind::Prefixed
1 parent 322bb5f commit f16f182

File tree

1 file changed

+31
-35
lines changed

1 file changed

+31
-35
lines changed

src/librustc/ty/layout.rs

Lines changed: 31 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -232,7 +232,7 @@ enum StructKind {
232232
/// A univariant, the last field of which may be coerced to unsized.
233233
MaybeUnsized,
234234
/// A univariant, but with a prefix of an arbitrary size & alignment (e.g., enum tag).
235-
Prefixed(Size, Align),
235+
Prefixed(MemoryPosition),
236236
}
237237

238238
// Invert a bijective mapping, i.e. `invert(map)[y] = x` if `map[x] = y`.
@@ -291,7 +291,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
291291
bug!("struct cannot be packed and aligned");
292292
}
293293

294-
let mut align = if pack.is_some() {
294+
let base_align = if pack.is_some() {
295295
dl.i8_align
296296
} else {
297297
dl.aggregate_align
@@ -302,8 +302,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
302302
let mut inverse_memory_index: Vec<u32> = (0..fields.len() as u32).collect();
303303

304304
let mut optimize = !repr.inhibit_struct_field_reordering_opt();
305-
if let StructKind::Prefixed(_, align) = kind {
306-
optimize &= align.bytes() == 1;
305+
if let StructKind::Prefixed(mem_pos) = kind {
306+
optimize &= mem_pos.align.bytes() == 1;
307307
}
308308

309309
if optimize {
@@ -344,18 +344,17 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
344344
// produce `memory_index` (see `invert_mapping`).
345345

346346

347-
let mut offset = Size::ZERO;
347+
let mut offset_pos = LayoutPositionPref::new(Size::ZERO, base_align);
348348
let mut largest_niche = None;
349349
let mut largest_niche_available = 0;
350350

351-
if let StructKind::Prefixed(prefix_size, prefix_align) = kind {
351+
if let StructKind::Prefixed(prefix_mem_pos) = kind {
352352
let prefix_align = if let Some(pack) = pack {
353-
prefix_align.min(pack)
353+
prefix_mem_pos.align.min(pack)
354354
} else {
355-
prefix_align
355+
prefix_mem_pos.align
356356
};
357-
align = align.max(AbiAndPrefAlign::new(prefix_align));
358-
offset = prefix_size.align_to(prefix_align);
357+
offset_pos = prefix_mem_pos.align_and_stride_to(prefix_align).pref_pos();
359358
}
360359

361360
for &i in &inverse_memory_index {
@@ -369,37 +368,35 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
369368
sized = false;
370369
}
371370

372-
// Invariant: offset < dl.obj_size_bound() <= 1<<61
373-
let field_align = if let Some(pack) = pack {
374-
field.pref_pos.align.min(AbiAndPrefAlign::new(pack))
371+
// Invariant: offset_pos.size < dl.obj_size_bound() <= 1<<61
372+
let field_pos = if let Some(pack) = pack {
373+
field.pref_pos.pack_to(AbiAndPrefAlign::new(pack))
375374
} else {
376-
field.pref_pos.align
375+
field.pref_pos
377376
};
378-
offset = offset.align_to(field_align.abi);
379-
align = align.max(field_align);
377+
offset_pos = offset_pos.align_and_stride_to(field_pos.align);
380378

381-
debug!("univariant offset: {:?} field: {:#?}", offset, field);
382-
offsets[i as usize] = offset;
379+
debug!("univariant offset: {:?} field: {:#?}", offset_pos.size, field);
380+
offsets[i as usize] = offset_pos.size;
383381

384382
if let Some(mut niche) = field.largest_niche.clone() {
385383
let available = niche.available(dl);
386384
if available > largest_niche_available {
387385
largest_niche_available = available;
388-
niche.offset += offset;
386+
niche.offset += offset_pos.size;
389387
largest_niche = Some(niche);
390388
}
391389
}
392390

393-
offset = offset.checked_add(field.pref_pos.size, dl)
391+
offset_pos = offset_pos.checked_add(field_pos, dl)
394392
.ok_or(LayoutError::SizeOverflow(ty))?;
395393
}
396394

397395
if let Some(repr_align) = repr.align {
398-
align = align.max(AbiAndPrefAlign::new(repr_align));
396+
offset_pos = offset_pos.align_to(AbiAndPrefAlign::new(repr_align));
399397
}
400398

401-
debug!("univariant min_size: {:?}", offset);
402-
let min_size = offset;
399+
debug!("univariant min_size: {:?}", offset_pos.size);
403400

404401
// As stated above, inverse_memory_index holds field indices by increasing offset.
405402
// This makes it an already-sorted view of the offsets vec.
@@ -415,11 +412,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
415412
memory_index = inverse_memory_index;
416413
}
417414

418-
let size = min_size.align_to(align.abi);
415+
// preserve stride == size
416+
let pref_pos = offset_pos.strided();
419417
let mut abi = Abi::Aggregate { sized };
420418

421419
// Unpack newtype ABIs and find scalar pairs.
422-
if sized && size.bytes() > 0 {
420+
if sized && pref_pos.size.bytes() > 0 {
423421
// All other fields must be ZSTs, and we need them to all start at 0.
424422
let mut zst_offsets =
425423
offsets.iter().enumerate().filter(|&(i, _)| fields[i].is_zst());
@@ -432,8 +430,8 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
432430
(Some((i, field)), None, None) => {
433431
// Field fills the struct and it has a scalar or scalar pair ABI.
434432
if offsets[i].bytes() == 0 &&
435-
align.abi == field.pref_pos.align.abi &&
436-
size == field.pref_pos.size {
433+
pref_pos.size == field.pref_pos.size &&
434+
pref_pos.align.abi == field.pref_pos.align.abi {
437435
match field.abi {
438436
// For plain scalars, or vectors of them, we can't unpack
439437
// newtypes for `#[repr(C)]`, as that affects C ABIs.
@@ -475,8 +473,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
475473
};
476474
if offsets[i] == pair_offsets[0] &&
477475
offsets[j] == pair_offsets[1] &&
478-
align == pair.pref_pos.align &&
479-
size == pair.pref_pos.size {
476+
pref_pos == pair.pref_pos {
480477
// We can use `ScalarPair` only when it matches our
481478
// already computed layout (including `#[repr(C)]`).
482479
abi = pair.abi;
@@ -492,8 +489,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
492489
abi = Abi::Uninhabited;
493490
}
494491

495-
let pref_pos = LayoutPositionPref::new(size, align);
496-
497492
Ok(LayoutDetails {
498493
variants: Variants::Single { index: VariantIdx::new(0) },
499494
fields: FieldPlacement::Arbitrary {
@@ -1080,10 +1075,12 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
10801075
}
10811076
}
10821077

1078+
let prefix_mem_pos = MemoryPosition::new(min_ity.size(), prefix_align);
1079+
10831080
// Create the set of structs that represent each variant.
10841081
let mut layout_variants = variants.iter_enumerated().map(|(i, field_layouts)| {
10851082
let mut st = self.univariant_uninterned(ty, &field_layouts,
1086-
&def.repr, StructKind::Prefixed(min_ity.size(), prefix_align))?;
1083+
&def.repr, StructKind::Prefixed(prefix_mem_pos))?;
10871084
st.variants = Variants::Single { index: i };
10881085
// Find the first field we can't move later
10891086
// to make room for a larger discriminant.
@@ -1451,8 +1448,6 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
14511448
StructKind::AlwaysSized,
14521449
)?;
14531450

1454-
let prefix_pref_pos = prefix.pref_pos;
1455-
14561451
// Split the prefix layout into the "outer" fields (upvars and
14571452
// discriminant) and the "promoted" fields. Promoted fields will
14581453
// get included in each variant that requested them in
@@ -1491,6 +1486,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
14911486
};
14921487

14931488
let mut pref_pos = prefix.pref_pos;
1489+
let prefix_mem_pos = pref_pos.mem_pos();
14941490
let variants = info.variant_fields.iter_enumerated().map(|(index, variant_fields)| {
14951491
// Only include overlap-eligible fields when we compute our variant layout.
14961492
let variant_only_tys = variant_fields
@@ -1511,7 +1507,7 @@ impl<'tcx> LayoutCx<'tcx, TyCtxt<'tcx>> {
15111507
.map(|ty| self.layout_of(ty))
15121508
.collect::<Result<Vec<_>, _>>()?,
15131509
&ReprOptions::default(),
1514-
StructKind::Prefixed(prefix_pref_pos.size, prefix_pref_pos.align.abi))?;
1510+
StructKind::Prefixed(prefix_mem_pos))?;
15151511
variant.variants = Variants::Single { index };
15161512

15171513
let (offsets, memory_index) = match variant.fields {

0 commit comments

Comments
 (0)