Skip to content

Commit bd86f37

Browse files
committed
rustc: make Layout::NullablePointer a lot more like Layout::General.
1 parent 33a205b commit bd86f37

File tree

7 files changed

+83
-115
lines changed

7 files changed

+83
-115
lines changed

src/librustc/ty/layout.rs

Lines changed: 45 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,9 +1128,12 @@ pub enum Layout {
11281128
/// identity function.
11291129
NullablePointer {
11301130
nndiscr: u64,
1131-
nonnull: Struct,
11321131
discr: Primitive,
11331132
discr_offset: Size,
1133+
variants: Vec<Struct>,
1134+
size: Size,
1135+
align: Align,
1136+
primitive_align: Align,
11341137
}
11351138
}
11361139

@@ -1471,23 +1474,20 @@ impl<'a, 'tcx> Layout {
14711474
!def.repr.inhibit_enum_layout_opt() &&
14721475
no_explicit_discriminants {
14731476
// Nullable pointer optimization
1474-
let st0 = Struct::new(dl, &variants[0],
1475-
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
1476-
let st1 = Struct::new(dl, &variants[1],
1477-
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
1477+
let mut st = vec![
1478+
Struct::new(dl, &variants[0],
1479+
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?,
1480+
Struct::new(dl, &variants[1],
1481+
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?
1482+
];
14781483

14791484
let mut choice = None;
14801485
for discr in 0..2 {
1481-
let (st, other) = if discr == 0 {
1482-
(&st0, &st1)
1483-
} else {
1484-
(&st1, &st0)
1485-
};
1486-
if other.stride().bytes() > 0 {
1486+
if st[1 - discr].stride().bytes() > 0 {
14871487
continue;
14881488
}
14891489

1490-
let field = st.non_zero_field(tcx, param_env,
1490+
let field = st[discr].non_zero_field(tcx, param_env,
14911491
variants[discr].iter().map(|&f| Ok(f)))?;
14921492
if let Some((offset, primitive)) = field {
14931493
choice = Some((discr, offset, primitive));
@@ -1496,23 +1496,22 @@ impl<'a, 'tcx> Layout {
14961496
}
14971497

14981498
if let Some((discr, offset, primitive)) = choice {
1499-
// HACK(eddyb) work around not being able to move
1500-
// out of arrays with just the indexing operator.
1501-
let mut st = if discr == 0 { st0 } else { st1 };
1502-
15031499
let mut discr_align = primitive.align(dl);
15041500
if offset.abi_align(discr_align) != offset {
1505-
st.packed = true;
1501+
st[discr].packed = true;
15061502
discr_align = dl.i8_align;
15071503
}
1508-
st.align = st.align.max(discr_align);
1509-
st.primitive_align = st.primitive_align.max(discr_align);
1504+
let align = st[discr].align.max(discr_align);
1505+
let primitive_align = st[discr].primitive_align.max(discr_align);
15101506

15111507
return success(NullablePointer {
15121508
nndiscr: discr as u64,
1513-
nonnull: st,
15141509
discr: primitive,
15151510
discr_offset: offset,
1511+
size: st[discr].stride(),
1512+
align,
1513+
primitive_align,
1514+
variants: st,
15161515
});
15171516
}
15181517
}
@@ -1693,13 +1692,10 @@ impl<'a, 'tcx> Layout {
16931692
metadata.size(dl)).abi_align(self.align(dl))
16941693
}
16951694

1695+
NullablePointer { size, .. } |
16961696
General { size, .. } => size,
16971697
UntaggedUnion(ref un) => un.stride(),
1698-
1699-
Univariant(ref variant) |
1700-
NullablePointer { nonnull: ref variant, .. } => {
1701-
variant.stride()
1702-
}
1698+
Univariant(ref variant) => variant.stride()
17031699
}
17041700
}
17051701

@@ -1726,13 +1722,11 @@ impl<'a, 'tcx> Layout {
17261722
Pointer.align(dl).max(metadata.align(dl))
17271723
}
17281724

1729-
Array { align, .. } | General { align, .. } => align,
1725+
Array { align, .. } |
1726+
NullablePointer { align, .. } |
1727+
General { align, .. } => align,
17301728
UntaggedUnion(ref un) => un.align,
1731-
1732-
Univariant(ref variant) |
1733-
NullablePointer { nonnull: ref variant, .. } => {
1734-
variant.align
1735-
}
1729+
Univariant(ref variant) => variant.align
17361730
}
17371731
}
17381732

@@ -1743,11 +1737,11 @@ impl<'a, 'tcx> Layout {
17431737
/// Returns alignment before repr alignment is applied
17441738
pub fn primitive_align<C: HasDataLayout>(&self, cx: C) -> Align {
17451739
match *self {
1746-
Array { primitive_align, .. } | General { primitive_align, .. } => primitive_align,
1747-
Univariant(ref variant) |
1748-
NullablePointer { nonnull: ref variant, .. } => {
1749-
variant.primitive_align
1750-
},
1740+
Array { primitive_align, .. } |
1741+
NullablePointer { primitive_align, .. } |
1742+
General { primitive_align, .. } => primitive_align,
1743+
1744+
Univariant(ref variant) => variant.primitive_align,
17511745

17521746
_ => self.align(cx.data_layout())
17531747
}
@@ -1850,23 +1844,6 @@ impl<'a, 'tcx> Layout {
18501844
};
18511845

18521846
match *layout {
1853-
Layout::NullablePointer { nonnull: ref variant_layout,
1854-
nndiscr,
1855-
discr: _,
1856-
discr_offset: _ } => {
1857-
debug!("print-type-size t: `{:?}` adt nullable nndiscr {} is {:?}",
1858-
ty, nndiscr, variant_layout);
1859-
let variant_def = &adt_def.variants[nndiscr as usize];
1860-
let fields: Vec<_> =
1861-
variant_def.fields.iter()
1862-
.map(|field_def| (field_def.name, field_def.ty(tcx, substs)))
1863-
.collect();
1864-
record(adt_kind.into(),
1865-
None,
1866-
vec![build_variant_info(Some(variant_def.name),
1867-
&fields,
1868-
variant_layout)]);
1869-
}
18701847
Layout::Univariant(ref variant_layout) => {
18711848
let variant_names = || {
18721849
adt_def.variants.iter().map(|v|format!("{}", v.name)).collect::<Vec<_>>()
@@ -1893,7 +1870,8 @@ impl<'a, 'tcx> Layout {
18931870
}
18941871
}
18951872

1896-
Layout::General { ref variants, discr, .. } => {
1873+
Layout::NullablePointer { ref variants, .. } |
1874+
Layout::General { ref variants, .. } => {
18971875
debug!("print-type-size t: `{:?}` adt general variants def {} layouts {} {:?}",
18981876
ty, adt_def.variants.len(), variants.len(), variants);
18991877
let variant_infos: Vec<_> =
@@ -1910,7 +1888,10 @@ impl<'a, 'tcx> Layout {
19101888
variant_layout)
19111889
})
19121890
.collect();
1913-
record(adt_kind.into(), Some(discr.size(tcx)), variant_infos);
1891+
record(adt_kind.into(), match *layout {
1892+
Layout::General { discr, .. } => Some(discr.size(tcx)),
1893+
_ => None
1894+
}, variant_infos);
19141895
}
19151896

19161897
Layout::UntaggedUnion(ref un) => {
@@ -2215,19 +2196,13 @@ impl<'a, 'tcx> FullLayout<'tcx> {
22152196
}
22162197
}
22172198

2199+
NullablePointer { ref variants, .. } |
22182200
General { ref variants, .. } => {
22192201
FieldPlacement::Arbitrary {
22202202
offsets: &variants[variant_index].offsets
22212203
}
22222204
}
22232205

2224-
NullablePointer { nndiscr, ref nonnull, .. }
2225-
if nndiscr as usize == variant_index => {
2226-
FieldPlacement::Arbitrary {
2227-
offsets: &nonnull.offsets
2228-
}
2229-
}
2230-
22312206
_ => FieldPlacement::union(count)
22322207
};
22332208

@@ -2390,14 +2365,20 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
23902365
}
23912366
NullablePointer {
23922367
nndiscr,
2393-
ref nonnull,
2368+
ref variants,
23942369
ref discr,
23952370
discr_offset,
2371+
size,
2372+
align,
2373+
primitive_align
23962374
} => {
23972375
nndiscr.hash_stable(hcx, hasher);
2398-
nonnull.hash_stable(hcx, hasher);
2376+
variants.hash_stable(hcx, hasher);
23992377
discr.hash_stable(hcx, hasher);
24002378
discr_offset.hash_stable(hcx, hasher);
2379+
size.hash_stable(hcx, hasher);
2380+
align.hash_stable(hcx, hasher);
2381+
primitive_align.hash_stable(hcx, hasher);
24012382
}
24022383
}
24032384
}

src/librustc_trans/adt.rs

Lines changed: 18 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -68,28 +68,24 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
6868
t: Ty<'tcx>, llty: &mut Type) {
6969
let l = cx.layout_of(t);
7070
debug!("finish_type_of: {} with layout {:#?}", t, l);
71+
if let layout::Abi::Scalar(_) = l.abi {
72+
return;
73+
}
7174
match *l {
72-
layout::General { .. } | layout::UntaggedUnion { .. } => { }
73-
layout::Univariant { ..} | layout::NullablePointer { .. } => {
74-
if let layout::Abi::Scalar(_) = l.abi {
75-
return;
76-
}
77-
let (variant_layout, variant) = match *l {
78-
layout::Univariant(ref variant) => {
79-
let is_enum = if let ty::TyAdt(def, _) = t.sty {
80-
def.is_enum()
81-
} else {
82-
false
83-
};
84-
if is_enum {
85-
(l.for_variant(0), variant)
86-
} else {
87-
(l, variant)
88-
}
89-
}
90-
layout::NullablePointer { nndiscr, ref nonnull, .. } =>
91-
(l.for_variant(nndiscr as usize), nonnull),
92-
_ => unreachable!()
75+
layout::NullablePointer { .. } |
76+
layout::General { .. } |
77+
layout::UntaggedUnion { .. } => { }
78+
79+
layout::Univariant(ref variant) => {
80+
let is_enum = if let ty::TyAdt(def, _) = t.sty {
81+
def.is_enum()
82+
} else {
83+
false
84+
};
85+
let variant_layout = if is_enum {
86+
l.for_variant(0)
87+
} else {
88+
l
9389
};
9490
llty.set_struct_body(&struct_llfields(cx, variant_layout, variant), variant.packed)
9591
},
@@ -106,18 +102,6 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
106102
return cx.llvm_type_of(value.to_ty(cx.tcx()));
107103
}
108104
match *l {
109-
layout::NullablePointer { nndiscr, ref nonnull, .. } => {
110-
match name {
111-
None => {
112-
Type::struct_(cx, &struct_llfields(cx, l.for_variant(nndiscr as usize),
113-
nonnull),
114-
nonnull.packed)
115-
}
116-
Some(name) => {
117-
Type::named_struct(cx, name)
118-
}
119-
}
120-
}
121105
layout::Univariant(ref variant) => {
122106
match name {
123107
None => {
@@ -143,6 +127,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
143127
}
144128
}
145129
}
130+
layout::NullablePointer { size, align, .. } |
146131
layout::General { size, align, .. } => {
147132
let fill = union_fill(cx, size, align);
148133
match name {

src/librustc_trans/debuginfo/metadata.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1218,11 +1218,13 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
12181218
}
12191219
}
12201220
layout::NullablePointer {
1221-
nonnull: ref struct_def,
12221221
nndiscr,
12231222
discr,
1224-
discr_offset
1223+
discr_offset,
1224+
ref variants,
1225+
..
12251226
} => {
1227+
let struct_def = &variants[nndiscr as usize];
12261228
// Create a description of the non-null variant
12271229
let (variant_type_metadata, member_description_factory) =
12281230
describe_enum_variant(cx,

src/librustc_trans/mir/constant.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1124,9 +1124,9 @@ fn trans_const_adt<'a, 'tcx>(
11241124
layout::Vector { .. } => {
11251125
Const::new(C_vector(&vals.iter().map(|x| x.llval).collect::<Vec<_>>()), t)
11261126
}
1127-
layout::NullablePointer { ref nonnull, nndiscr, .. } => {
1127+
layout::NullablePointer { ref variants, nndiscr, .. } => {
11281128
if variant_index as u64 == nndiscr {
1129-
build_const_struct(ccx, l, &nonnull, vals, None)
1129+
build_const_struct(ccx, l, &variants[variant_index], vals, None)
11301130
} else {
11311131
// Always use null even if it's not the `discrfield`th
11321132
// field; see #8506.

src/librustc_trans/mir/lvalue.rs

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -273,7 +273,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
273273
// Check whether the variant being used is packed, if applicable.
274274
let is_packed = match (&*l, l.variant_index) {
275275
(&layout::Univariant(ref variant), _) => variant.packed,
276-
(&layout::NullablePointer { ref nonnull, .. }, _) => nonnull.packed,
276+
(&layout::NullablePointer { ref variants, .. }, Some(v)) |
277277
(&layout::General { ref variants, .. }, Some(v)) => variants[v].packed,
278278
_ => return simple()
279279
};
@@ -471,11 +471,15 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
471471

472472
// If this is an enum, cast to the appropriate variant struct type.
473473
let layout = bcx.ccx.layout_of(ty).for_variant(variant_index);
474-
if let layout::General { ref variants, .. } = *layout {
475-
let st = &variants[variant_index];
476-
let variant_ty = Type::struct_(bcx.ccx,
477-
&adt::struct_llfields(bcx.ccx, layout, st), st.packed);
478-
downcast.llval = bcx.pointercast(downcast.llval, variant_ty.ptr_to());
474+
match *layout {
475+
layout::NullablePointer { ref variants, .. } |
476+
layout::General { ref variants, .. } => {
477+
let st = &variants[variant_index];
478+
let variant_ty = Type::struct_(bcx.ccx,
479+
&adt::struct_llfields(bcx.ccx, layout, st), st.packed);
480+
downcast.llval = bcx.pointercast(downcast.llval, variant_ty.ptr_to());
481+
}
482+
_ => {}
479483
}
480484

481485
downcast

src/librustc_trans/type_of.rs

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -259,21 +259,14 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
259259
adt::memory_index_to_gep(variant.memory_index[index] as u64)
260260
}
261261

262+
Layout::NullablePointer { ref variants, .. } |
262263
Layout::General { ref variants, .. } => {
263264
if let Some(v) = self.variant_index {
264265
adt::memory_index_to_gep(variants[v].memory_index[index] as u64)
265266
} else {
266267
bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
267268
}
268269
}
269-
270-
Layout::NullablePointer { nndiscr, ref nonnull, .. } => {
271-
if self.variant_index == Some(nndiscr as usize) {
272-
adt::memory_index_to_gep(nonnull.memory_index[index] as u64)
273-
} else {
274-
bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
275-
}
276-
}
277270
}
278271
}
279272
}

src/test/ui/print_type_sizes/nullable.stdout

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,11 @@ print-type-size field `.post`: 2 bytes
44
print-type-size field `.pre`: 1 bytes
55
print-type-size end padding: 1 bytes
66
print-type-size type: `MyOption<IndirectNonZero<u32>>`: 12 bytes, alignment: 4 bytes
7+
print-type-size variant `None`: 0 bytes
78
print-type-size variant `Some`: 12 bytes
89
print-type-size field `.0`: 12 bytes
910
print-type-size type: `EmbeddedDiscr`: 8 bytes, alignment: 4 bytes
11+
print-type-size variant `None`: 0 bytes
1012
print-type-size variant `Record`: 7 bytes
1113
print-type-size field `.val`: 4 bytes
1214
print-type-size field `.post`: 2 bytes
@@ -18,6 +20,7 @@ print-type-size field `.post`: 2 bytes
1820
print-type-size field `.pre`: 1 bytes
1921
print-type-size end padding: 1 bytes
2022
print-type-size type: `MyOption<core::nonzero::NonZero<u32>>`: 4 bytes, alignment: 4 bytes
23+
print-type-size variant `None`: 0 bytes
2124
print-type-size variant `Some`: 4 bytes
2225
print-type-size field `.0`: 4 bytes
2326
print-type-size type: `core::nonzero::NonZero<u32>`: 4 bytes, alignment: 4 bytes

0 commit comments

Comments
 (0)