Skip to content

Commit 33a205b

Browse files
committed
rustc: collapse Layout::CEnum into Layout::General.
1 parent 658ebfc commit 33a205b

File tree

9 files changed

+86
-135
lines changed

9 files changed

+86
-135
lines changed

src/librustc/lib.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,11 @@
4747
#![feature(core_intrinsics)]
4848
#![feature(drain_filter)]
4949
#![feature(i128_type)]
50-
#![feature(match_default_bindings)]
50+
#![feature(inclusive_range)]
5151
#![feature(inclusive_range_syntax)]
5252
#![cfg_attr(windows, feature(libc))]
5353
#![feature(macro_vis_matcher)]
54+
#![feature(match_default_bindings)]
5455
#![feature(never_type)]
5556
#![feature(nonzero)]
5657
#![feature(quote)]

src/librustc/ty/layout.rs

Lines changed: 61 additions & 107 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ use std::fmt;
2525
use std::i64;
2626
use std::iter;
2727
use std::mem;
28-
use std::ops::{Deref, Add, Sub, Mul, AddAssign};
28+
use std::ops::{Deref, Add, Sub, Mul, AddAssign, RangeInclusive};
2929

3030
use ich::StableHashingContext;
3131
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
@@ -841,9 +841,9 @@ impl<'a, 'tcx> Struct {
841841
(&Scalar(Pointer), _) if !layout.ty.is_unsafe_ptr() => {
842842
Ok(Some((Size::from_bytes(0), Pointer)))
843843
}
844-
(&CEnum { discr, .. }, &ty::TyAdt(def, _)) => {
844+
(&General { discr, .. }, &ty::TyAdt(def, _)) => {
845845
if def.discriminants(tcx).all(|d| d.to_u128_unchecked() != 0) {
846-
Ok(Some((Size::from_bytes(0), discr)))
846+
Ok(Some((layout.fields.offset(0), discr)))
847847
} else {
848848
Ok(None)
849849
}
@@ -1095,18 +1095,6 @@ pub enum Layout {
10951095

10961096
// Remaining variants are all ADTs such as structs, enums or tuples.
10971097

1098-
/// C-like enums; basically an integer.
1099-
CEnum {
1100-
discr: Primitive,
1101-
/// Inclusive discriminant range.
1102-
/// If min > max, it represents min...u64::MAX followed by 0...max.
1103-
// FIXME(eddyb) always use the shortest range, e.g. by finding
1104-
// the largest space between two consecutive discriminants and
1105-
// taking everything else as the (shortest) discriminant range.
1106-
min: u64,
1107-
max: u64
1108-
},
1109-
11101098
/// Single-case enums, and structs/tuples.
11111099
Univariant(Struct),
11121100

@@ -1118,6 +1106,12 @@ pub enum Layout {
11181106
/// at a non-0 offset, after where the discriminant would go.
11191107
General {
11201108
discr: Primitive,
1109+
/// Inclusive wrap-around range of discriminant values, that is,
1110+
/// if min > max, it represents min..=u64::MAX followed by 0..=max.
1111+
// FIXME(eddyb) always use the shortest range, e.g. by finding
1112+
// the largest space between two consecutive discriminants and
1113+
// taking everything else as the (shortest) discriminant range.
1114+
discr_range: RangeInclusive<u64>,
11211115
variants: Vec<Struct>,
11221116
size: Size,
11231117
align: Align,
@@ -1240,7 +1234,6 @@ impl<'a, 'tcx> Layout {
12401234
FieldPlacement::union(def.struct_variant().fields.len())
12411235
}
12421236

1243-
CEnum { .. } |
12441237
General { .. } => FieldPlacement::union(1),
12451238

12461239
NullablePointer { ref discr_offset, .. } => {
@@ -1250,19 +1243,17 @@ impl<'a, 'tcx> Layout {
12501243
}
12511244
};
12521245
let abi = match *layout {
1253-
Scalar(value) |
1254-
CEnum { discr: value, .. } => Abi::Scalar(value),
1255-
1246+
Scalar(value) => Abi::Scalar(value),
12561247
Vector { .. } => Abi::Vector,
12571248

12581249
Array { .. } |
12591250
FatPointer { .. } |
12601251
Univariant(_) |
1261-
UntaggedUnion(_) |
1262-
General { .. } => Abi::Aggregate,
1252+
UntaggedUnion(_) => Abi::Aggregate,
12631253

1264-
NullablePointer { discr, discr_offset, .. } => {
1265-
if discr_offset.bytes() == 0 && discr.size(cx) == layout.size(cx) {
1254+
General { discr, .. } |
1255+
NullablePointer { discr, .. } => {
1256+
if fields.offset(0).bytes() == 0 && discr.size(cx) == layout.size(cx) {
12661257
Abi::Scalar(discr)
12671258
} else {
12681259
Abi::Aggregate
@@ -1431,82 +1422,54 @@ impl<'a, 'tcx> Layout {
14311422

14321423
// ADTs.
14331424
ty::TyAdt(def, substs) => {
1434-
if def.variants.is_empty() {
1425+
// Cache the field layouts.
1426+
let variants = def.variants.iter().map(|v| {
1427+
v.fields.iter().map(|field| {
1428+
cx.layout_of(field.ty(tcx, substs))
1429+
}).collect::<Result<Vec<_>, _>>()
1430+
}).collect::<Result<Vec<_>, _>>()?;
1431+
1432+
if variants.is_empty() {
14351433
// Uninhabitable; represent as unit
14361434
// (Typechecking will reject discriminant-sizing attrs.)
14371435

14381436
return success(Univariant(Struct::new(dl, &[],
14391437
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?));
14401438
}
14411439

1442-
if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) {
1443-
// All bodies empty -> intlike
1444-
let (mut min, mut max) = (i64::max_value(), i64::min_value());
1445-
for discr in def.discriminants(tcx) {
1446-
let x = discr.to_u128_unchecked() as i64;
1447-
if x < min { min = x; }
1448-
if x > max { max = x; }
1449-
}
1450-
1451-
// FIXME: should handle i128? signed-value based impl is weird and hard to
1452-
// grok.
1453-
let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
1454-
return success(CEnum {
1455-
discr: Int(discr, signed),
1456-
// FIXME: should be u128?
1457-
min: min as u64,
1458-
max: max as u64
1459-
});
1460-
}
1461-
1462-
if !def.is_enum() || (def.variants.len() == 1 &&
1463-
!def.repr.inhibit_enum_layout_opt()) {
1440+
if !def.is_enum() || (variants.len() == 1 &&
1441+
!def.repr.inhibit_enum_layout_opt() &&
1442+
!variants[0].is_empty()) {
14641443
// Struct, or union, or univariant enum equivalent to a struct.
14651444
// (Typechecking will reject discriminant-sizing attrs.)
14661445

1467-
let kind = if def.is_enum() || def.variants[0].fields.len() == 0{
1446+
let kind = if def.is_enum() || variants[0].len() == 0 {
14681447
StructKind::AlwaysSizedUnivariant
14691448
} else {
14701449
let param_env = tcx.param_env(def.did);
1471-
let fields = &def.variants[0].fields;
1472-
let last_field = &fields[fields.len()-1];
1450+
let last_field = def.variants[0].fields.last().unwrap();
14731451
let always_sized = tcx.type_of(last_field.did)
14741452
.is_sized(tcx, param_env, DUMMY_SP);
14751453
if !always_sized { StructKind::MaybeUnsizedUnivariant }
14761454
else { StructKind::AlwaysSizedUnivariant }
14771455
};
14781456

1479-
let fields = def.variants[0].fields.iter().map(|field| {
1480-
cx.layout_of(field.ty(tcx, substs))
1481-
}).collect::<Result<Vec<_>, _>>()?;
14821457
let layout = if def.is_union() {
14831458
let mut un = Union::new(dl, &def.repr);
1484-
un.extend(dl, fields.iter().map(|&f| Ok(f.layout)), ty)?;
1459+
un.extend(dl, variants[0].iter().map(|&f| Ok(f.layout)), ty)?;
14851460
UntaggedUnion(un)
14861461
} else {
1487-
Univariant(Struct::new(dl, &fields, &def.repr, kind, ty)?)
1462+
Univariant(Struct::new(dl, &variants[0], &def.repr, kind, ty)?)
14881463
};
14891464
return success(layout);
14901465
}
14911466

1492-
// Since there's at least one
1493-
// non-empty body, explicit discriminants should have
1494-
// been rejected by a checker before this point.
1495-
for (i, v) in def.variants.iter().enumerate() {
1496-
if v.discr != ty::VariantDiscr::Relative(i) {
1497-
bug!("non-C-like enum {} with specified discriminants",
1498-
tcx.item_path_str(def.did));
1499-
}
1500-
}
1467+
let no_explicit_discriminants = def.variants.iter().enumerate()
1468+
.all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i));
15011469

1502-
// Cache the substituted and normalized variant field types.
1503-
let variants = def.variants.iter().map(|v| {
1504-
v.fields.iter().map(|field| {
1505-
cx.layout_of(field.ty(tcx, substs))
1506-
}).collect::<Result<Vec<_>, _>>()
1507-
}).collect::<Result<Vec<_>, _>>()?;
1508-
1509-
if variants.len() == 2 && !def.repr.inhibit_enum_layout_opt() {
1470+
if variants.len() == 2 &&
1471+
!def.repr.inhibit_enum_layout_opt() &&
1472+
no_explicit_discriminants {
15101473
// Nullable pointer optimization
15111474
let st0 = Struct::new(dl, &variants[0],
15121475
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
@@ -1554,16 +1517,23 @@ impl<'a, 'tcx> Layout {
15541517
}
15551518
}
15561519

1557-
// The general case.
1558-
let discr_max = (variants.len() - 1) as i64;
1559-
assert!(discr_max >= 0);
1560-
let (min_ity, _) = Integer::repr_discr(tcx, ty, &def.repr, 0, discr_max);
1520+
let (mut min, mut max) = (i64::max_value(), i64::min_value());
1521+
for discr in def.discriminants(tcx) {
1522+
let x = discr.to_u128_unchecked() as i64;
1523+
if x < min { min = x; }
1524+
if x > max { max = x; }
1525+
}
1526+
// FIXME: should handle i128? signed-value based impl is weird and hard to
1527+
// grok.
1528+
let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
1529+
15611530
let mut align = dl.aggregate_align;
15621531
let mut primitive_align = dl.aggregate_align;
15631532
let mut size = Size::from_bytes(0);
15641533

15651534
// We're interested in the smallest alignment, so start large.
15661535
let mut start_align = Align::from_bytes(256, 256).unwrap();
1536+
assert_eq!(Integer::for_abi_align(dl, start_align), None);
15671537

15681538
// Create the set of structs that represent each variant.
15691539
let mut variants = variants.into_iter().map(|fields| {
@@ -1644,7 +1614,10 @@ impl<'a, 'tcx> Layout {
16441614
}
16451615

16461616
General {
1647-
discr: Int(ity, false),
1617+
discr: Int(ity, signed),
1618+
1619+
// FIXME: should be u128?
1620+
discr_range: (min as u64)..=(max as u64),
16481621
variants,
16491622
size,
16501623
align,
@@ -1680,7 +1653,7 @@ impl<'a, 'tcx> Layout {
16801653
pub fn is_unsized(&self) -> bool {
16811654
match *self {
16821655
Scalar(_) | Vector {..} | FatPointer {..} |
1683-
CEnum {..} | UntaggedUnion {..} | General {..} |
1656+
UntaggedUnion {..} | General {..} |
16841657
NullablePointer {..} => false,
16851658

16861659
Array { sized, .. } |
@@ -1720,7 +1693,6 @@ impl<'a, 'tcx> Layout {
17201693
metadata.size(dl)).abi_align(self.align(dl))
17211694
}
17221695

1723-
CEnum { discr, .. } => discr.size(dl),
17241696
General { size, .. } => size,
17251697
UntaggedUnion(ref un) => un.stride(),
17261698

@@ -1754,7 +1726,6 @@ impl<'a, 'tcx> Layout {
17541726
Pointer.align(dl).max(metadata.align(dl))
17551727
}
17561728

1757-
CEnum { discr, .. } => discr.align(dl),
17581729
Array { align, .. } | General { align, .. } => align,
17591730
UntaggedUnion(ref un) => un.align,
17601731

@@ -1856,16 +1827,6 @@ impl<'a, 'tcx> Layout {
18561827
}
18571828
};
18581829

1859-
let build_primitive_info = |name: ast::Name, value: Primitive| {
1860-
session::VariantInfo {
1861-
name: Some(name.to_string()),
1862-
kind: session::SizeKind::Exact,
1863-
align: value.align(tcx).abi(),
1864-
size: value.size(tcx).bytes(),
1865-
fields: vec![],
1866-
}
1867-
};
1868-
18691830
let build_variant_info = |n: Option<ast::Name>,
18701831
flds: &[(ast::Name, Ty<'tcx>)],
18711832
s: &Struct| {
@@ -1959,17 +1920,6 @@ impl<'a, 'tcx> Layout {
19591920
record(adt_kind.into(), None, Vec::new());
19601921
}
19611922

1962-
Layout::CEnum { discr, .. } => {
1963-
debug!("print-type-size t: `{:?}` adt c-like enum", ty);
1964-
let variant_infos: Vec<_> =
1965-
adt_def.variants.iter()
1966-
.map(|variant_def| {
1967-
build_primitive_info(variant_def.name, discr)
1968-
})
1969-
.collect();
1970-
record(adt_kind.into(), Some(discr.size(tcx)), variant_infos);
1971-
}
1972-
19731923
// other cases provide little interesting (i.e. adjustable
19741924
// via representation tweaks) size info beyond total size.
19751925
Layout::Scalar(_) |
@@ -2284,6 +2234,7 @@ impl<'a, 'tcx> FullLayout<'tcx> {
22842234
FullLayout {
22852235
variant_index: Some(variant_index),
22862236
fields,
2237+
abi: Abi::Aggregate,
22872238
..*self
22882239
}
22892240
}
@@ -2356,7 +2307,6 @@ impl<'a, 'tcx> FullLayout<'tcx> {
23562307
match self.variant_index {
23572308
None => match *self.layout {
23582309
// Discriminant field for enums (where applicable).
2359-
CEnum { discr, .. } |
23602310
General { discr, .. } |
23612311
NullablePointer { discr, .. } => {
23622312
return [discr.to_ty(tcx)][i];
@@ -2416,19 +2366,23 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
24162366
FatPointer(ref metadata) => {
24172367
metadata.hash_stable(hcx, hasher);
24182368
}
2419-
CEnum { discr, min, max } => {
2420-
discr.hash_stable(hcx, hasher);
2421-
min.hash_stable(hcx, hasher);
2422-
max.hash_stable(hcx, hasher);
2423-
}
24242369
Univariant(ref variant) => {
24252370
variant.hash_stable(hcx, hasher);
24262371
}
24272372
UntaggedUnion(ref un) => {
24282373
un.hash_stable(hcx, hasher);
24292374
}
2430-
General { discr, ref variants, size, align, primitive_align } => {
2375+
General {
2376+
discr,
2377+
discr_range: RangeInclusive { start, end },
2378+
ref variants,
2379+
size,
2380+
align,
2381+
primitive_align
2382+
} => {
24312383
discr.hash_stable(hcx, hasher);
2384+
start.hash_stable(hcx, hasher);
2385+
end.hash_stable(hcx, hasher);
24322386
variants.hash_stable(hcx, hasher);
24332387
size.hash_stable(hcx, hasher);
24342388
align.hash_stable(hcx, hasher);

src/librustc_trans/adt.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
6969
let l = cx.layout_of(t);
7070
debug!("finish_type_of: {} with layout {:#?}", t, l);
7171
match *l {
72-
layout::CEnum { .. } | layout::General { .. } | layout::UntaggedUnion { .. } => { }
72+
layout::General { .. } | layout::UntaggedUnion { .. } => { }
7373
layout::Univariant { ..} | layout::NullablePointer { .. } => {
7474
if let layout::Abi::Scalar(_) = l.abi {
7575
return;
@@ -101,13 +101,12 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
101101
t: Ty<'tcx>,
102102
name: Option<&str>) -> Type {
103103
let l = cx.layout_of(t);
104-
debug!("adt::generic_type_of t: {:?} name: {:?}", t, name);
104+
debug!("adt::generic_type_of {:#?} name: {:?}", l, name);
105+
if let layout::Abi::Scalar(value) = l.abi {
106+
return cx.llvm_type_of(value.to_ty(cx.tcx()));
107+
}
105108
match *l {
106-
layout::CEnum { discr, .. } => cx.llvm_type_of(discr.to_ty(cx.tcx())),
107109
layout::NullablePointer { nndiscr, ref nonnull, .. } => {
108-
if let layout::Abi::Scalar(_) = l.abi {
109-
return cx.llvm_type_of(l.field(cx, 0).ty);
110-
}
111110
match name {
112111
None => {
113112
Type::struct_(cx, &struct_llfields(cx, l.for_variant(nndiscr as usize),

0 commit comments

Comments
 (0)