Skip to content

Commit 9482bce

Browse files
committed
Replace offset_after_field with offsets
1 parent 791fb77 commit 9482bce

File tree

5 files changed

+47
-76
lines changed

5 files changed

+47
-76
lines changed

src/librustc/ty/layout.rs

+26-33
Original file line numberDiff line numberDiff line change
@@ -511,11 +511,11 @@ pub struct Struct {
511511
/// If true, the size is exact, otherwise it's only a lower bound.
512512
pub sized: bool,
513513

514-
/// Offsets for the first byte after each field.
515-
/// That is, field_offset(i) = offset_after_field[i - 1] and the
516-
/// whole structure's size is the last offset, excluding padding.
517-
// FIXME(eddyb) use small vector optimization for the common case.
518-
pub offset_after_field: Vec<Size>
514+
/// Offsets for the first byte of each field.
515+
/// FIXME(eddyb) use small vector optimization for the common case.
516+
pub offsets: Vec<Size>,
517+
518+
pub min_size: Size,
519519
}
520520

521521
impl<'a, 'gcx, 'tcx> Struct {
@@ -524,7 +524,8 @@ impl<'a, 'gcx, 'tcx> Struct {
524524
align: if packed { dl.i8_align } else { dl.aggregate_align },
525525
packed: packed,
526526
sized: true,
527-
offset_after_field: vec![]
527+
offsets: vec![],
528+
min_size: Size::from_bytes(0),
528529
}
529530
}
530531

@@ -534,12 +535,14 @@ impl<'a, 'gcx, 'tcx> Struct {
534535
scapegoat: Ty<'gcx>)
535536
-> Result<(), LayoutError<'gcx>>
536537
where I: Iterator<Item=Result<&'a Layout, LayoutError<'gcx>>> {
537-
self.offset_after_field.reserve(fields.size_hint().0);
538+
self.offsets.reserve(fields.size_hint().0);
539+
540+
let mut offset = self.min_size;
538541

539542
for field in fields {
540543
if !self.sized {
541544
bug!("Struct::extend: field #{} of `{}` comes after unsized field",
542-
self.offset_after_field.len(), scapegoat);
545+
self.offsets.len(), scapegoat);
543546
}
544547

545548
let field = field?;
@@ -548,34 +551,29 @@ impl<'a, 'gcx, 'tcx> Struct {
548551
}
549552

550553
// Invariant: offset < dl.obj_size_bound() <= 1<<61
551-
let mut offset = if !self.packed {
554+
if !self.packed {
552555
let align = field.align(dl);
553556
self.align = self.align.max(align);
554-
self.offset_after_field.last_mut().map_or(Size::from_bytes(0), |last| {
555-
*last = last.abi_align(align);
556-
*last
557-
})
558-
} else {
559-
self.offset_after_field.last().map_or(Size::from_bytes(0), |&last| last)
560-
};
557+
offset = offset.abi_align(align);
558+
}
559+
560+
self.offsets.push(offset);
561+
561562

562563
offset = offset.checked_add(field.size(dl), dl)
563564
.map_or(Err(LayoutError::SizeOverflow(scapegoat)), Ok)?;
564-
565-
self.offset_after_field.push(offset);
566565
}
567566

567+
self.min_size = offset;
568+
568569
Ok(())
569570
}
570571

571572
/// Get the size without trailing alignment padding.
572-
pub fn min_size(&self) -> Size {
573-
self.offset_after_field.last().map_or(Size::from_bytes(0), |&last| last)
574-
}
575573
576574
/// Get the size with trailing aligment padding.
577575
pub fn stride(&self) -> Size {
578-
self.min_size().abi_align(self.align)
576+
self.min_size.abi_align(self.align)
579577
}
580578

581579
/// Determine whether a structure would be zero-sized, given its fields.
@@ -671,15 +669,6 @@ impl<'a, 'gcx, 'tcx> Struct {
671669
}
672670
Ok(None)
673671
}
674-
675-
pub fn offset_of_field(&self, index: usize) -> Size {
676-
assert!(index < self.offset_after_field.len());
677-
if index == 0 {
678-
Size::from_bytes(0)
679-
} else {
680-
self.offset_after_field[index-1]
681-
}
682-
}
683672
}
684673

685674
/// An untagged union.
@@ -1138,7 +1127,7 @@ impl<'a, 'gcx, 'tcx> Layout {
11381127
});
11391128
let mut st = Struct::new(dl, false);
11401129
st.extend(dl, discr.iter().map(Ok).chain(fields), ty)?;
1141-
size = cmp::max(size, st.min_size());
1130+
size = cmp::max(size, st.min_size);
11421131
align = align.max(st.align);
11431132
Ok(st)
11441133
}).collect::<Result<Vec<_>, _>>()?;
@@ -1171,12 +1160,16 @@ impl<'a, 'gcx, 'tcx> Layout {
11711160
let old_ity_size = Int(min_ity).size(dl);
11721161
let new_ity_size = Int(ity).size(dl);
11731162
for variant in &mut variants {
1174-
for offset in &mut variant.offset_after_field {
1163+
for offset in &mut variant.offsets[1..] {
11751164
if *offset > old_ity_size {
11761165
break;
11771166
}
11781167
*offset = new_ity_size;
11791168
}
1169+
// We might be making the struct larger.
1170+
if variant.min_size <= old_ity_size {
1171+
variant.min_size = new_ity_size;
1172+
}
11801173
}
11811174
}
11821175

src/librustc_lint/types.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,7 @@ impl LateLintPass for VariantSizeDifferences {
738738
.zip(variants)
739739
.map(|(variant, variant_layout)| {
740740
// Subtract the size of the enum discriminant
741-
let bytes = variant_layout.min_size().bytes()
741+
let bytes = variant_layout.min_size.bytes()
742742
.saturating_sub(discr_size);
743743

744744
debug!("- variant `{}` is {} bytes large", variant.node.name, bytes);

src/librustc_trans/adt.rs

+18-29
Original file line numberDiff line numberDiff line change
@@ -632,7 +632,7 @@ fn struct_field_ptr<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
632632
let meta = val.meta;
633633

634634

635-
let offset = st.offset_of_field(ix).bytes();
635+
let offset = st.offsets[ix].bytes();
636636
let unaligned_offset = C_uint(bcx.ccx(), offset);
637637

638638
// Get the alignment of the field
@@ -695,9 +695,9 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, discr: D
695695
let lldiscr = C_integral(Type::from_integer(ccx, d), discr.0 as u64, true);
696696
let mut vals_with_discr = vec![lldiscr];
697697
vals_with_discr.extend_from_slice(vals);
698-
let mut contents = build_const_struct(ccx, &variant.offset_after_field[..],
699-
&vals_with_discr[..], variant.packed);
700-
let needed_padding = l.size(dl).bytes() - variant.min_size().bytes();
698+
let mut contents = build_const_struct(ccx, &variant,
699+
&vals_with_discr[..]);
700+
let needed_padding = l.size(dl).bytes() - variant.min_size.bytes();
701701
if needed_padding > 0 {
702702
contents.push(padding(ccx, needed_padding));
703703
}
@@ -711,7 +711,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, discr: D
711711
layout::Univariant { ref variant, .. } => {
712712
assert_eq!(discr, Disr(0));
713713
let contents = build_const_struct(ccx,
714-
&variant.offset_after_field[..], vals, variant.packed);
714+
&variant, vals);
715715
C_struct(ccx, &contents[..], variant.packed)
716716
}
717717
layout::Vector { .. } => {
@@ -728,9 +728,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, discr: D
728728
}
729729
layout::StructWrappedNullablePointer { ref nonnull, nndiscr, .. } => {
730730
if discr.0 == nndiscr {
731-
C_struct(ccx, &build_const_struct(ccx,
732-
&nonnull.offset_after_field[..],
733-
vals, nonnull.packed),
731+
C_struct(ccx, &build_const_struct(ccx, &nonnull, vals),
734732
false)
735733
} else {
736734
let fields = compute_fields(ccx, t, nndiscr as usize, false);
@@ -739,10 +737,7 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, discr: D
739737
// field; see #8506.
740738
C_null(type_of::sizing_type_of(ccx, ty))
741739
}).collect::<Vec<ValueRef>>();
742-
C_struct(ccx, &build_const_struct(ccx,
743-
&nonnull.offset_after_field[..],
744-
&vals[..],
745-
false),
740+
C_struct(ccx, &build_const_struct(ccx, &nonnull, &vals[..]),
746741
false)
747742
}
748743
}
@@ -759,11 +754,10 @@ pub fn trans_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>, discr: D
759754
/// a two-element struct will locate it at offset 4, and accesses to it
760755
/// will read the wrong memory.
761756
fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
762-
offset_after_field: &[layout::Size],
763-
vals: &[ValueRef],
764-
packed: bool)
757+
st: &layout::Struct,
758+
vals: &[ValueRef])
765759
-> Vec<ValueRef> {
766-
assert_eq!(vals.len(), offset_after_field.len());
760+
assert_eq!(vals.len(), st.offsets.len());
767761

768762
if vals.len() == 0 {
769763
return Vec::new();
@@ -772,24 +766,19 @@ fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
772766
// offset of current value
773767
let mut offset = 0;
774768
let mut cfields = Vec::new();
775-
let target_offsets = offset_after_field.iter().map(|i| i.bytes());
776-
for (&val, target_offset) in vals.iter().zip(target_offsets) {
777-
assert!(!is_undef(val));
778-
cfields.push(val);
779-
offset += machine::llsize_of_alloc(ccx, val_ty(val));
780-
if !packed {
781-
let val_align = machine::llalign_of_min(ccx, val_ty(val));
782-
offset = roundup(offset, val_align);
783-
}
784-
if offset != target_offset {
769+
let offsets = st.offsets.iter().map(|i| i.bytes());
770+
for (&val, target_offset) in vals.iter().zip(offsets) {
771+
if offset < target_offset {
785772
cfields.push(padding(ccx, target_offset - offset));
786773
offset = target_offset;
787774
}
775+
assert!(!is_undef(val));
776+
cfields.push(val);
777+
offset += machine::llsize_of_alloc(ccx, val_ty(val));
788778
}
789779

790-
let size = offset_after_field.last().unwrap();
791-
if offset < size.bytes() {
792-
cfields.push(padding(ccx, size.bytes() - offset));
780+
if offset < st.min_size.bytes() {
781+
cfields.push(padding(ccx, st.min_size.bytes() - offset));
793782
}
794783

795784
cfields

src/librustc_trans/common.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ pub fn type_is_imm_pair<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>)
127127
Layout::FatPointer { .. } => true,
128128
Layout::Univariant { ref variant, .. } => {
129129
// There must be only 2 fields.
130-
if variant.offset_after_field.len() != 2 {
130+
if variant.offsets.len() != 2 {
131131
return false;
132132
}
133133

src/librustc_trans/glue.rs

+1-12
Original file line numberDiff line numberDiff line change
@@ -335,20 +335,9 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: &BlockAndBuilder<'blk, 'tcx>,
335335
let layout = ccx.layout_of(t);
336336
debug!("DST {} layout: {:?}", t, layout);
337337

338-
// Returns size in bytes of all fields except the last one
339-
// (we will be recursing on the last one).
340-
fn local_prefix_bytes(variant: &ty::layout::Struct) -> u64 {
341-
let fields = variant.offset_after_field.len();
342-
if fields > 1 {
343-
variant.offset_after_field[fields - 2].bytes()
344-
} else {
345-
0
346-
}
347-
}
348-
349338
let (sized_size, sized_align) = match *layout {
350339
ty::layout::Layout::Univariant { ref variant, .. } => {
351-
(local_prefix_bytes(variant), variant.align.abi())
340+
(variant.offsets.last().map_or(0, |o| o.bytes()), variant.align.abi())
352341
}
353342
_ => {
354343
bug!("size_and_align_of_dst: expcted Univariant for `{}`, found {:#?}",

0 commit comments

Comments
 (0)