rustc: collapse Layout::CEnum into Layout::General.
This commit is contained in:
parent
658ebfc788
commit
33a205b56f
9 changed files with 86 additions and 135 deletions
|
@ -47,10 +47,11 @@
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(drain_filter)]
|
#![feature(drain_filter)]
|
||||||
#![feature(i128_type)]
|
#![feature(i128_type)]
|
||||||
#![feature(match_default_bindings)]
|
#![feature(inclusive_range)]
|
||||||
#![feature(inclusive_range_syntax)]
|
#![feature(inclusive_range_syntax)]
|
||||||
#![cfg_attr(windows, feature(libc))]
|
#![cfg_attr(windows, feature(libc))]
|
||||||
#![feature(macro_vis_matcher)]
|
#![feature(macro_vis_matcher)]
|
||||||
|
#![feature(match_default_bindings)]
|
||||||
#![feature(never_type)]
|
#![feature(never_type)]
|
||||||
#![feature(nonzero)]
|
#![feature(nonzero)]
|
||||||
#![feature(quote)]
|
#![feature(quote)]
|
||||||
|
|
|
@ -25,7 +25,7 @@ use std::fmt;
|
||||||
use std::i64;
|
use std::i64;
|
||||||
use std::iter;
|
use std::iter;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Deref, Add, Sub, Mul, AddAssign};
|
use std::ops::{Deref, Add, Sub, Mul, AddAssign, RangeInclusive};
|
||||||
|
|
||||||
use ich::StableHashingContext;
|
use ich::StableHashingContext;
|
||||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
|
use rustc_data_structures::stable_hasher::{HashStable, StableHasher,
|
||||||
|
@ -841,9 +841,9 @@ impl<'a, 'tcx> Struct {
|
||||||
(&Scalar(Pointer), _) if !layout.ty.is_unsafe_ptr() => {
|
(&Scalar(Pointer), _) if !layout.ty.is_unsafe_ptr() => {
|
||||||
Ok(Some((Size::from_bytes(0), Pointer)))
|
Ok(Some((Size::from_bytes(0), Pointer)))
|
||||||
}
|
}
|
||||||
(&CEnum { discr, .. }, &ty::TyAdt(def, _)) => {
|
(&General { discr, .. }, &ty::TyAdt(def, _)) => {
|
||||||
if def.discriminants(tcx).all(|d| d.to_u128_unchecked() != 0) {
|
if def.discriminants(tcx).all(|d| d.to_u128_unchecked() != 0) {
|
||||||
Ok(Some((Size::from_bytes(0), discr)))
|
Ok(Some((layout.fields.offset(0), discr)))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -1095,18 +1095,6 @@ pub enum Layout {
|
||||||
|
|
||||||
// Remaining variants are all ADTs such as structs, enums or tuples.
|
// Remaining variants are all ADTs such as structs, enums or tuples.
|
||||||
|
|
||||||
/// C-like enums; basically an integer.
|
|
||||||
CEnum {
|
|
||||||
discr: Primitive,
|
|
||||||
/// Inclusive discriminant range.
|
|
||||||
/// If min > max, it represents min...u64::MAX followed by 0...max.
|
|
||||||
// FIXME(eddyb) always use the shortest range, e.g. by finding
|
|
||||||
// the largest space between two consecutive discriminants and
|
|
||||||
// taking everything else as the (shortest) discriminant range.
|
|
||||||
min: u64,
|
|
||||||
max: u64
|
|
||||||
},
|
|
||||||
|
|
||||||
/// Single-case enums, and structs/tuples.
|
/// Single-case enums, and structs/tuples.
|
||||||
Univariant(Struct),
|
Univariant(Struct),
|
||||||
|
|
||||||
|
@ -1118,6 +1106,12 @@ pub enum Layout {
|
||||||
/// at a non-0 offset, after where the discriminant would go.
|
/// at a non-0 offset, after where the discriminant would go.
|
||||||
General {
|
General {
|
||||||
discr: Primitive,
|
discr: Primitive,
|
||||||
|
/// Inclusive wrap-around range of discriminant values, that is,
|
||||||
|
/// if min > max, it represents min..=u64::MAX followed by 0..=max.
|
||||||
|
// FIXME(eddyb) always use the shortest range, e.g. by finding
|
||||||
|
// the largest space between two consecutive discriminants and
|
||||||
|
// taking everything else as the (shortest) discriminant range.
|
||||||
|
discr_range: RangeInclusive<u64>,
|
||||||
variants: Vec<Struct>,
|
variants: Vec<Struct>,
|
||||||
size: Size,
|
size: Size,
|
||||||
align: Align,
|
align: Align,
|
||||||
|
@ -1240,7 +1234,6 @@ impl<'a, 'tcx> Layout {
|
||||||
FieldPlacement::union(def.struct_variant().fields.len())
|
FieldPlacement::union(def.struct_variant().fields.len())
|
||||||
}
|
}
|
||||||
|
|
||||||
CEnum { .. } |
|
|
||||||
General { .. } => FieldPlacement::union(1),
|
General { .. } => FieldPlacement::union(1),
|
||||||
|
|
||||||
NullablePointer { ref discr_offset, .. } => {
|
NullablePointer { ref discr_offset, .. } => {
|
||||||
|
@ -1250,19 +1243,17 @@ impl<'a, 'tcx> Layout {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
let abi = match *layout {
|
let abi = match *layout {
|
||||||
Scalar(value) |
|
Scalar(value) => Abi::Scalar(value),
|
||||||
CEnum { discr: value, .. } => Abi::Scalar(value),
|
|
||||||
|
|
||||||
Vector { .. } => Abi::Vector,
|
Vector { .. } => Abi::Vector,
|
||||||
|
|
||||||
Array { .. } |
|
Array { .. } |
|
||||||
FatPointer { .. } |
|
FatPointer { .. } |
|
||||||
Univariant(_) |
|
Univariant(_) |
|
||||||
UntaggedUnion(_) |
|
UntaggedUnion(_) => Abi::Aggregate,
|
||||||
General { .. } => Abi::Aggregate,
|
|
||||||
|
|
||||||
NullablePointer { discr, discr_offset, .. } => {
|
General { discr, .. } |
|
||||||
if discr_offset.bytes() == 0 && discr.size(cx) == layout.size(cx) {
|
NullablePointer { discr, .. } => {
|
||||||
|
if fields.offset(0).bytes() == 0 && discr.size(cx) == layout.size(cx) {
|
||||||
Abi::Scalar(discr)
|
Abi::Scalar(discr)
|
||||||
} else {
|
} else {
|
||||||
Abi::Aggregate
|
Abi::Aggregate
|
||||||
|
@ -1431,7 +1422,14 @@ impl<'a, 'tcx> Layout {
|
||||||
|
|
||||||
// ADTs.
|
// ADTs.
|
||||||
ty::TyAdt(def, substs) => {
|
ty::TyAdt(def, substs) => {
|
||||||
if def.variants.is_empty() {
|
// Cache the field layouts.
|
||||||
|
let variants = def.variants.iter().map(|v| {
|
||||||
|
v.fields.iter().map(|field| {
|
||||||
|
cx.layout_of(field.ty(tcx, substs))
|
||||||
|
}).collect::<Result<Vec<_>, _>>()
|
||||||
|
}).collect::<Result<Vec<_>, _>>()?;
|
||||||
|
|
||||||
|
if variants.is_empty() {
|
||||||
// Uninhabitable; represent as unit
|
// Uninhabitable; represent as unit
|
||||||
// (Typechecking will reject discriminant-sizing attrs.)
|
// (Typechecking will reject discriminant-sizing attrs.)
|
||||||
|
|
||||||
|
@ -1439,74 +1437,39 @@ impl<'a, 'tcx> Layout {
|
||||||
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?));
|
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?));
|
||||||
}
|
}
|
||||||
|
|
||||||
if def.is_enum() && def.variants.iter().all(|v| v.fields.is_empty()) {
|
if !def.is_enum() || (variants.len() == 1 &&
|
||||||
// All bodies empty -> intlike
|
!def.repr.inhibit_enum_layout_opt() &&
|
||||||
let (mut min, mut max) = (i64::max_value(), i64::min_value());
|
!variants[0].is_empty()) {
|
||||||
for discr in def.discriminants(tcx) {
|
|
||||||
let x = discr.to_u128_unchecked() as i64;
|
|
||||||
if x < min { min = x; }
|
|
||||||
if x > max { max = x; }
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: should handle i128? signed-value based impl is weird and hard to
|
|
||||||
// grok.
|
|
||||||
let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
|
|
||||||
return success(CEnum {
|
|
||||||
discr: Int(discr, signed),
|
|
||||||
// FIXME: should be u128?
|
|
||||||
min: min as u64,
|
|
||||||
max: max as u64
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if !def.is_enum() || (def.variants.len() == 1 &&
|
|
||||||
!def.repr.inhibit_enum_layout_opt()) {
|
|
||||||
// Struct, or union, or univariant enum equivalent to a struct.
|
// Struct, or union, or univariant enum equivalent to a struct.
|
||||||
// (Typechecking will reject discriminant-sizing attrs.)
|
// (Typechecking will reject discriminant-sizing attrs.)
|
||||||
|
|
||||||
let kind = if def.is_enum() || def.variants[0].fields.len() == 0{
|
let kind = if def.is_enum() || variants[0].len() == 0 {
|
||||||
StructKind::AlwaysSizedUnivariant
|
StructKind::AlwaysSizedUnivariant
|
||||||
} else {
|
} else {
|
||||||
let param_env = tcx.param_env(def.did);
|
let param_env = tcx.param_env(def.did);
|
||||||
let fields = &def.variants[0].fields;
|
let last_field = def.variants[0].fields.last().unwrap();
|
||||||
let last_field = &fields[fields.len()-1];
|
|
||||||
let always_sized = tcx.type_of(last_field.did)
|
let always_sized = tcx.type_of(last_field.did)
|
||||||
.is_sized(tcx, param_env, DUMMY_SP);
|
.is_sized(tcx, param_env, DUMMY_SP);
|
||||||
if !always_sized { StructKind::MaybeUnsizedUnivariant }
|
if !always_sized { StructKind::MaybeUnsizedUnivariant }
|
||||||
else { StructKind::AlwaysSizedUnivariant }
|
else { StructKind::AlwaysSizedUnivariant }
|
||||||
};
|
};
|
||||||
|
|
||||||
let fields = def.variants[0].fields.iter().map(|field| {
|
|
||||||
cx.layout_of(field.ty(tcx, substs))
|
|
||||||
}).collect::<Result<Vec<_>, _>>()?;
|
|
||||||
let layout = if def.is_union() {
|
let layout = if def.is_union() {
|
||||||
let mut un = Union::new(dl, &def.repr);
|
let mut un = Union::new(dl, &def.repr);
|
||||||
un.extend(dl, fields.iter().map(|&f| Ok(f.layout)), ty)?;
|
un.extend(dl, variants[0].iter().map(|&f| Ok(f.layout)), ty)?;
|
||||||
UntaggedUnion(un)
|
UntaggedUnion(un)
|
||||||
} else {
|
} else {
|
||||||
Univariant(Struct::new(dl, &fields, &def.repr, kind, ty)?)
|
Univariant(Struct::new(dl, &variants[0], &def.repr, kind, ty)?)
|
||||||
};
|
};
|
||||||
return success(layout);
|
return success(layout);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Since there's at least one
|
let no_explicit_discriminants = def.variants.iter().enumerate()
|
||||||
// non-empty body, explicit discriminants should have
|
.all(|(i, v)| v.discr == ty::VariantDiscr::Relative(i));
|
||||||
// been rejected by a checker before this point.
|
|
||||||
for (i, v) in def.variants.iter().enumerate() {
|
|
||||||
if v.discr != ty::VariantDiscr::Relative(i) {
|
|
||||||
bug!("non-C-like enum {} with specified discriminants",
|
|
||||||
tcx.item_path_str(def.did));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cache the substituted and normalized variant field types.
|
if variants.len() == 2 &&
|
||||||
let variants = def.variants.iter().map(|v| {
|
!def.repr.inhibit_enum_layout_opt() &&
|
||||||
v.fields.iter().map(|field| {
|
no_explicit_discriminants {
|
||||||
cx.layout_of(field.ty(tcx, substs))
|
|
||||||
}).collect::<Result<Vec<_>, _>>()
|
|
||||||
}).collect::<Result<Vec<_>, _>>()?;
|
|
||||||
|
|
||||||
if variants.len() == 2 && !def.repr.inhibit_enum_layout_opt() {
|
|
||||||
// Nullable pointer optimization
|
// Nullable pointer optimization
|
||||||
let st0 = Struct::new(dl, &variants[0],
|
let st0 = Struct::new(dl, &variants[0],
|
||||||
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
|
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
|
||||||
|
@ -1554,16 +1517,23 @@ impl<'a, 'tcx> Layout {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// The general case.
|
let (mut min, mut max) = (i64::max_value(), i64::min_value());
|
||||||
let discr_max = (variants.len() - 1) as i64;
|
for discr in def.discriminants(tcx) {
|
||||||
assert!(discr_max >= 0);
|
let x = discr.to_u128_unchecked() as i64;
|
||||||
let (min_ity, _) = Integer::repr_discr(tcx, ty, &def.repr, 0, discr_max);
|
if x < min { min = x; }
|
||||||
|
if x > max { max = x; }
|
||||||
|
}
|
||||||
|
// FIXME: should handle i128? signed-value based impl is weird and hard to
|
||||||
|
// grok.
|
||||||
|
let (min_ity, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
|
||||||
|
|
||||||
let mut align = dl.aggregate_align;
|
let mut align = dl.aggregate_align;
|
||||||
let mut primitive_align = dl.aggregate_align;
|
let mut primitive_align = dl.aggregate_align;
|
||||||
let mut size = Size::from_bytes(0);
|
let mut size = Size::from_bytes(0);
|
||||||
|
|
||||||
// We're interested in the smallest alignment, so start large.
|
// We're interested in the smallest alignment, so start large.
|
||||||
let mut start_align = Align::from_bytes(256, 256).unwrap();
|
let mut start_align = Align::from_bytes(256, 256).unwrap();
|
||||||
|
assert_eq!(Integer::for_abi_align(dl, start_align), None);
|
||||||
|
|
||||||
// Create the set of structs that represent each variant.
|
// Create the set of structs that represent each variant.
|
||||||
let mut variants = variants.into_iter().map(|fields| {
|
let mut variants = variants.into_iter().map(|fields| {
|
||||||
|
@ -1644,7 +1614,10 @@ impl<'a, 'tcx> Layout {
|
||||||
}
|
}
|
||||||
|
|
||||||
General {
|
General {
|
||||||
discr: Int(ity, false),
|
discr: Int(ity, signed),
|
||||||
|
|
||||||
|
// FIXME: should be u128?
|
||||||
|
discr_range: (min as u64)..=(max as u64),
|
||||||
variants,
|
variants,
|
||||||
size,
|
size,
|
||||||
align,
|
align,
|
||||||
|
@ -1680,7 +1653,7 @@ impl<'a, 'tcx> Layout {
|
||||||
pub fn is_unsized(&self) -> bool {
|
pub fn is_unsized(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
Scalar(_) | Vector {..} | FatPointer {..} |
|
Scalar(_) | Vector {..} | FatPointer {..} |
|
||||||
CEnum {..} | UntaggedUnion {..} | General {..} |
|
UntaggedUnion {..} | General {..} |
|
||||||
NullablePointer {..} => false,
|
NullablePointer {..} => false,
|
||||||
|
|
||||||
Array { sized, .. } |
|
Array { sized, .. } |
|
||||||
|
@ -1720,7 +1693,6 @@ impl<'a, 'tcx> Layout {
|
||||||
metadata.size(dl)).abi_align(self.align(dl))
|
metadata.size(dl)).abi_align(self.align(dl))
|
||||||
}
|
}
|
||||||
|
|
||||||
CEnum { discr, .. } => discr.size(dl),
|
|
||||||
General { size, .. } => size,
|
General { size, .. } => size,
|
||||||
UntaggedUnion(ref un) => un.stride(),
|
UntaggedUnion(ref un) => un.stride(),
|
||||||
|
|
||||||
|
@ -1754,7 +1726,6 @@ impl<'a, 'tcx> Layout {
|
||||||
Pointer.align(dl).max(metadata.align(dl))
|
Pointer.align(dl).max(metadata.align(dl))
|
||||||
}
|
}
|
||||||
|
|
||||||
CEnum { discr, .. } => discr.align(dl),
|
|
||||||
Array { align, .. } | General { align, .. } => align,
|
Array { align, .. } | General { align, .. } => align,
|
||||||
UntaggedUnion(ref un) => un.align,
|
UntaggedUnion(ref un) => un.align,
|
||||||
|
|
||||||
|
@ -1856,16 +1827,6 @@ impl<'a, 'tcx> Layout {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
let build_primitive_info = |name: ast::Name, value: Primitive| {
|
|
||||||
session::VariantInfo {
|
|
||||||
name: Some(name.to_string()),
|
|
||||||
kind: session::SizeKind::Exact,
|
|
||||||
align: value.align(tcx).abi(),
|
|
||||||
size: value.size(tcx).bytes(),
|
|
||||||
fields: vec![],
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
let build_variant_info = |n: Option<ast::Name>,
|
let build_variant_info = |n: Option<ast::Name>,
|
||||||
flds: &[(ast::Name, Ty<'tcx>)],
|
flds: &[(ast::Name, Ty<'tcx>)],
|
||||||
s: &Struct| {
|
s: &Struct| {
|
||||||
|
@ -1959,17 +1920,6 @@ impl<'a, 'tcx> Layout {
|
||||||
record(adt_kind.into(), None, Vec::new());
|
record(adt_kind.into(), None, Vec::new());
|
||||||
}
|
}
|
||||||
|
|
||||||
Layout::CEnum { discr, .. } => {
|
|
||||||
debug!("print-type-size t: `{:?}` adt c-like enum", ty);
|
|
||||||
let variant_infos: Vec<_> =
|
|
||||||
adt_def.variants.iter()
|
|
||||||
.map(|variant_def| {
|
|
||||||
build_primitive_info(variant_def.name, discr)
|
|
||||||
})
|
|
||||||
.collect();
|
|
||||||
record(adt_kind.into(), Some(discr.size(tcx)), variant_infos);
|
|
||||||
}
|
|
||||||
|
|
||||||
// other cases provide little interesting (i.e. adjustable
|
// other cases provide little interesting (i.e. adjustable
|
||||||
// via representation tweaks) size info beyond total size.
|
// via representation tweaks) size info beyond total size.
|
||||||
Layout::Scalar(_) |
|
Layout::Scalar(_) |
|
||||||
|
@ -2284,6 +2234,7 @@ impl<'a, 'tcx> FullLayout<'tcx> {
|
||||||
FullLayout {
|
FullLayout {
|
||||||
variant_index: Some(variant_index),
|
variant_index: Some(variant_index),
|
||||||
fields,
|
fields,
|
||||||
|
abi: Abi::Aggregate,
|
||||||
..*self
|
..*self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2356,7 +2307,6 @@ impl<'a, 'tcx> FullLayout<'tcx> {
|
||||||
match self.variant_index {
|
match self.variant_index {
|
||||||
None => match *self.layout {
|
None => match *self.layout {
|
||||||
// Discriminant field for enums (where applicable).
|
// Discriminant field for enums (where applicable).
|
||||||
CEnum { discr, .. } |
|
|
||||||
General { discr, .. } |
|
General { discr, .. } |
|
||||||
NullablePointer { discr, .. } => {
|
NullablePointer { discr, .. } => {
|
||||||
return [discr.to_ty(tcx)][i];
|
return [discr.to_ty(tcx)][i];
|
||||||
|
@ -2416,19 +2366,23 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
|
||||||
FatPointer(ref metadata) => {
|
FatPointer(ref metadata) => {
|
||||||
metadata.hash_stable(hcx, hasher);
|
metadata.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
CEnum { discr, min, max } => {
|
|
||||||
discr.hash_stable(hcx, hasher);
|
|
||||||
min.hash_stable(hcx, hasher);
|
|
||||||
max.hash_stable(hcx, hasher);
|
|
||||||
}
|
|
||||||
Univariant(ref variant) => {
|
Univariant(ref variant) => {
|
||||||
variant.hash_stable(hcx, hasher);
|
variant.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
UntaggedUnion(ref un) => {
|
UntaggedUnion(ref un) => {
|
||||||
un.hash_stable(hcx, hasher);
|
un.hash_stable(hcx, hasher);
|
||||||
}
|
}
|
||||||
General { discr, ref variants, size, align, primitive_align } => {
|
General {
|
||||||
|
discr,
|
||||||
|
discr_range: RangeInclusive { start, end },
|
||||||
|
ref variants,
|
||||||
|
size,
|
||||||
|
align,
|
||||||
|
primitive_align
|
||||||
|
} => {
|
||||||
discr.hash_stable(hcx, hasher);
|
discr.hash_stable(hcx, hasher);
|
||||||
|
start.hash_stable(hcx, hasher);
|
||||||
|
end.hash_stable(hcx, hasher);
|
||||||
variants.hash_stable(hcx, hasher);
|
variants.hash_stable(hcx, hasher);
|
||||||
size.hash_stable(hcx, hasher);
|
size.hash_stable(hcx, hasher);
|
||||||
align.hash_stable(hcx, hasher);
|
align.hash_stable(hcx, hasher);
|
||||||
|
|
|
@ -69,7 +69,7 @@ pub fn finish_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
let l = cx.layout_of(t);
|
let l = cx.layout_of(t);
|
||||||
debug!("finish_type_of: {} with layout {:#?}", t, l);
|
debug!("finish_type_of: {} with layout {:#?}", t, l);
|
||||||
match *l {
|
match *l {
|
||||||
layout::CEnum { .. } | layout::General { .. } | layout::UntaggedUnion { .. } => { }
|
layout::General { .. } | layout::UntaggedUnion { .. } => { }
|
||||||
layout::Univariant { ..} | layout::NullablePointer { .. } => {
|
layout::Univariant { ..} | layout::NullablePointer { .. } => {
|
||||||
if let layout::Abi::Scalar(_) = l.abi {
|
if let layout::Abi::Scalar(_) = l.abi {
|
||||||
return;
|
return;
|
||||||
|
@ -101,13 +101,12 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
t: Ty<'tcx>,
|
t: Ty<'tcx>,
|
||||||
name: Option<&str>) -> Type {
|
name: Option<&str>) -> Type {
|
||||||
let l = cx.layout_of(t);
|
let l = cx.layout_of(t);
|
||||||
debug!("adt::generic_type_of t: {:?} name: {:?}", t, name);
|
debug!("adt::generic_type_of {:#?} name: {:?}", l, name);
|
||||||
match *l {
|
if let layout::Abi::Scalar(value) = l.abi {
|
||||||
layout::CEnum { discr, .. } => cx.llvm_type_of(discr.to_ty(cx.tcx())),
|
return cx.llvm_type_of(value.to_ty(cx.tcx()));
|
||||||
layout::NullablePointer { nndiscr, ref nonnull, .. } => {
|
|
||||||
if let layout::Abi::Scalar(_) = l.abi {
|
|
||||||
return cx.llvm_type_of(l.field(cx, 0).ty);
|
|
||||||
}
|
}
|
||||||
|
match *l {
|
||||||
|
layout::NullablePointer { nndiscr, ref nonnull, .. } => {
|
||||||
match name {
|
match name {
|
||||||
None => {
|
None => {
|
||||||
Type::struct_(cx, &struct_llfields(cx, l.for_variant(nndiscr as usize),
|
Type::struct_(cx, &struct_llfields(cx, l.for_variant(nndiscr as usize),
|
||||||
|
|
|
@ -1282,7 +1282,6 @@ impl<'tcx> EnumMemberDescriptionFactory<'tcx> {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
layout::CEnum { .. } => span_bug!(self.span, "This should be unreachable."),
|
|
||||||
ref l @ _ => bug!("Not an enum layout: {:#?}", l)
|
ref l @ _ => bug!("Not an enum layout: {:#?}", l)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1491,14 +1490,16 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
|
||||||
let type_rep = cx.layout_of(enum_type);
|
let type_rep = cx.layout_of(enum_type);
|
||||||
|
|
||||||
let discriminant_type_metadata = match *type_rep {
|
let discriminant_type_metadata = match *type_rep {
|
||||||
layout::CEnum { discr, .. } => {
|
|
||||||
return FinalMetadata(discriminant_type_metadata(discr))
|
|
||||||
},
|
|
||||||
layout::NullablePointer { .. } | layout::Univariant { .. } => None,
|
layout::NullablePointer { .. } | layout::Univariant { .. } => None,
|
||||||
layout::General { discr, .. } => Some(discriminant_type_metadata(discr)),
|
layout::General { discr, .. } => Some(discriminant_type_metadata(discr)),
|
||||||
ref l @ _ => bug!("Not an enum layout: {:#?}", l)
|
ref l @ _ => bug!("Not an enum layout: {:#?}", l)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
match (type_rep.abi, discriminant_type_metadata) {
|
||||||
|
(layout::Abi::Scalar(_), Some(discr)) => return FinalMetadata(discr),
|
||||||
|
_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
let (enum_type_size, enum_type_align) = type_rep.size_and_align(cx);
|
let (enum_type_size, enum_type_align) = type_rep.size_and_align(cx);
|
||||||
|
|
||||||
let enum_name = CString::new(enum_name).unwrap();
|
let enum_name = CString::new(enum_name).unwrap();
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#![allow(unused_attributes)]
|
#![allow(unused_attributes)]
|
||||||
#![feature(i128_type)]
|
#![feature(i128_type)]
|
||||||
#![feature(i128)]
|
#![feature(i128)]
|
||||||
|
#![feature(inclusive_range)]
|
||||||
#![feature(libc)]
|
#![feature(libc)]
|
||||||
#![feature(quote)]
|
#![feature(quote)]
|
||||||
#![feature(rustc_diagnostic_macros)]
|
#![feature(rustc_diagnostic_macros)]
|
||||||
|
|
|
@ -1091,7 +1091,7 @@ fn trans_const_adt<'a, 'tcx>(
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
match *l {
|
match *l {
|
||||||
layout::CEnum { .. } => {
|
layout::General { ref variants, .. } => {
|
||||||
let discr = match *kind {
|
let discr = match *kind {
|
||||||
mir::AggregateKind::Adt(adt_def, _, _, _) => {
|
mir::AggregateKind::Adt(adt_def, _, _, _) => {
|
||||||
adt_def.discriminant_for_variant(ccx.tcx(), variant_index)
|
adt_def.discriminant_for_variant(ccx.tcx(), variant_index)
|
||||||
|
@ -1099,15 +1099,14 @@ fn trans_const_adt<'a, 'tcx>(
|
||||||
},
|
},
|
||||||
_ => 0,
|
_ => 0,
|
||||||
};
|
};
|
||||||
assert_eq!(vals.len(), 0);
|
|
||||||
Const::new(C_int(ccx.llvm_type_of(t), discr as i64), t)
|
|
||||||
}
|
|
||||||
layout::General { ref variants, .. } => {
|
|
||||||
let discr_ty = l.field(ccx, 0).ty;
|
let discr_ty = l.field(ccx, 0).ty;
|
||||||
let variant = &variants[variant_index];
|
let discr = Const::new(C_int(ccx.llvm_type_of(discr_ty), discr as i64),
|
||||||
let lldiscr = C_int(ccx.llvm_type_of(discr_ty), variant_index as i64);
|
discr_ty);
|
||||||
build_const_struct(ccx, l, &variant, vals,
|
if let layout::Abi::Scalar(_) = l.abi {
|
||||||
Some(Const::new(lldiscr, discr_ty)))
|
discr
|
||||||
|
} else {
|
||||||
|
build_const_struct(ccx, l, &variants[variant_index], vals, Some(discr))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
layout::UntaggedUnion(ref un) => {
|
layout::UntaggedUnion(ref un) => {
|
||||||
assert_eq!(variant_index, 0);
|
assert_eq!(variant_index, 0);
|
||||||
|
|
|
@ -367,8 +367,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
||||||
_ => bug!("discriminant not scalar: {:#?}", discr_layout)
|
_ => bug!("discriminant not scalar: {:#?}", discr_layout)
|
||||||
};
|
};
|
||||||
let (min, max) = match *l {
|
let (min, max) = match *l {
|
||||||
layout::CEnum { min, max, .. } => (min, max),
|
layout::General { ref discr_range, .. } => (discr_range.start, discr_range.end),
|
||||||
layout::General { ref variants, .. } => (0, variants.len() as u64 - 1),
|
|
||||||
_ => (0, u64::max_value()),
|
_ => (0, u64::max_value()),
|
||||||
};
|
};
|
||||||
let max_next = max.wrapping_add(1);
|
let max_next = max.wrapping_add(1);
|
||||||
|
@ -394,7 +393,6 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
match *l {
|
match *l {
|
||||||
layout::CEnum { .. } |
|
|
||||||
layout::General { .. } => {
|
layout::General { .. } => {
|
||||||
let signed = match discr_scalar {
|
let signed = match discr_scalar {
|
||||||
layout::Int(_, signed) => signed,
|
layout::Int(_, signed) => signed,
|
||||||
|
@ -419,7 +417,6 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
|
||||||
.discriminant_for_variant(bcx.tcx(), variant_index)
|
.discriminant_for_variant(bcx.tcx(), variant_index)
|
||||||
.to_u128_unchecked() as u64;
|
.to_u128_unchecked() as u64;
|
||||||
match *l {
|
match *l {
|
||||||
layout::CEnum { .. } |
|
|
||||||
layout::General { .. } => {
|
layout::General { .. } => {
|
||||||
let ptr = self.project_field(bcx, 0);
|
let ptr = self.project_field(bcx, 0);
|
||||||
bcx.store(C_int(bcx.ccx.llvm_type_of(ptr.ty.to_ty(bcx.tcx())), to as i64),
|
bcx.store(C_int(bcx.ccx.llvm_type_of(ptr.ty.to_ty(bcx.tcx())), to as i64),
|
||||||
|
|
|
@ -277,8 +277,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
let llval = operand.immediate();
|
let llval = operand.immediate();
|
||||||
let l = bcx.ccx.layout_of(operand.ty);
|
let l = bcx.ccx.layout_of(operand.ty);
|
||||||
|
|
||||||
if let Layout::CEnum { min, max, .. } = *l {
|
if let Layout::General { ref discr_range, .. } = *l {
|
||||||
if max > min {
|
if discr_range.end > discr_range.start {
|
||||||
// We want `table[e as usize]` to not
|
// We want `table[e as usize]` to not
|
||||||
// have bound checks, and this is the most
|
// have bound checks, and this is the most
|
||||||
// convenient place to put the `assume`.
|
// convenient place to put the `assume`.
|
||||||
|
@ -286,7 +286,7 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
|
||||||
base::call_assume(&bcx, bcx.icmp(
|
base::call_assume(&bcx, bcx.icmp(
|
||||||
llvm::IntULE,
|
llvm::IntULE,
|
||||||
llval,
|
llval,
|
||||||
C_uint(ll_t_in, max)
|
C_uint(ll_t_in, discr_range.end)
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -242,7 +242,6 @@ impl<'tcx> LayoutLlvmExt for FullLayout<'tcx> {
|
||||||
}
|
}
|
||||||
match **self {
|
match **self {
|
||||||
Layout::Scalar { .. } |
|
Layout::Scalar { .. } |
|
||||||
Layout::CEnum { .. } |
|
|
||||||
Layout::UntaggedUnion { .. } => {
|
Layout::UntaggedUnion { .. } => {
|
||||||
bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
|
bug!("FullLayout::llvm_field_index({:?}): not applicable", self)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue