rustc: use Primitive instead of Integer for CEnum and General discriminants.

This commit is contained in:
Eduard-Mihai Burtescu 2017-09-16 12:23:22 +03:00
parent 335bd8ea1b
commit 61c2bd9ca4
8 changed files with 57 additions and 63 deletions

View file

@ -843,7 +843,7 @@ impl<'a, 'tcx> Struct {
}
(&CEnum { discr, .. }, &ty::TyAdt(def, _)) => {
if def.discriminants(tcx).all(|d| d.to_u128_unchecked() != 0) {
Ok(Some((Size::from_bytes(0), Int(discr))))
Ok(Some((Size::from_bytes(0), discr)))
} else {
Ok(None)
}
@ -1097,7 +1097,7 @@ pub enum Layout {
/// C-like enums; basically an integer.
CEnum {
discr: Integer,
discr: Primitive,
signed: bool,
/// Inclusive discriminant range.
/// If min > max, it represents min...u64::MAX followed by 0...max.
@ -1118,7 +1118,7 @@ pub enum Layout {
/// all space reserved for the discriminant, and their first field starts
/// at a non-0 offset, after where the discriminant would go.
General {
discr: Integer,
discr: Primitive,
variants: Vec<Struct>,
size: Size,
align: Align,
@ -1251,8 +1251,8 @@ impl<'a, 'tcx> Layout {
}
};
let abi = match *layout {
Scalar(value) => Abi::Scalar(value),
CEnum { discr, .. } => Abi::Scalar(Int(discr)),
Scalar(value) |
CEnum { discr: value, .. } => Abi::Scalar(value),
Vector { .. } => Abi::Vector,
@ -1453,7 +1453,7 @@ impl<'a, 'tcx> Layout {
// grok.
let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
return success(CEnum {
discr,
discr: Int(discr),
signed,
// FIXME: should be u128?
min: min as u64,
@ -1646,7 +1646,7 @@ impl<'a, 'tcx> Layout {
}
General {
discr: ity,
discr: Int(ity),
variants,
size,
align,
@ -1722,7 +1722,7 @@ impl<'a, 'tcx> Layout {
metadata.size(dl)).abi_align(self.align(dl))
}
CEnum { discr, .. } => Int(discr).size(dl),
CEnum { discr, .. } => discr.size(dl),
General { size, .. } => size,
UntaggedUnion(ref un) => un.stride(),
@ -1756,7 +1756,7 @@ impl<'a, 'tcx> Layout {
Pointer.align(dl).max(metadata.align(dl))
}
CEnum { discr, .. } => Int(discr).align(dl),
CEnum { discr, .. } => discr.align(dl),
Array { align, .. } | General { align, .. } => align,
UntaggedUnion(ref un) => un.align,
@ -1858,7 +1858,7 @@ impl<'a, 'tcx> Layout {
}
};
let build_primitive_info = |name: ast::Name, value: &Primitive| {
let build_primitive_info = |name: ast::Name, value: Primitive| {
session::VariantInfo {
name: Some(name.to_string()),
kind: session::SizeKind::Exact,
@ -1951,7 +1951,7 @@ impl<'a, 'tcx> Layout {
variant_layout)
})
.collect();
record(adt_kind.into(), Some(discr.size()), variant_infos);
record(adt_kind.into(), Some(discr.size(tcx)), variant_infos);
}
Layout::UntaggedUnion(ref un) => {
@ -1966,11 +1966,10 @@ impl<'a, 'tcx> Layout {
let variant_infos: Vec<_> =
adt_def.variants.iter()
.map(|variant_def| {
build_primitive_info(variant_def.name,
&Primitive::Int(discr))
build_primitive_info(variant_def.name, discr)
})
.collect();
record(adt_kind.into(), Some(discr.size()), variant_infos);
record(adt_kind.into(), Some(discr.size(tcx)), variant_infos);
}
// other cases provide little interesting (i.e. adjustable
@ -2359,9 +2358,7 @@ impl<'a, 'tcx> FullLayout<'tcx> {
match self.variant_index {
None => match *self.layout {
// Discriminant field for enums (where applicable).
General { discr, .. } => {
return [discr.to_ty(tcx, false)][i];
}
General { discr, .. } |
NullablePointer { discr, .. } => {
return [discr.to_ty(tcx)][i];
}

View file

@ -13,7 +13,7 @@
use rustc::hir::def_id::DefId;
use rustc::ty::subst::Substs;
use rustc::ty::{self, AdtKind, Ty, TyCtxt};
use rustc::ty::layout::{Layout, LayoutOf, Primitive};
use rustc::ty::layout::{Layout, LayoutOf};
use middle::const_val::ConstVal;
use rustc_const_eval::ConstContext;
use util::nodemap::FxHashSet;
@ -754,7 +754,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
});
if let Layout::General { ref variants, ref size, discr, .. } = *layout {
let discr_size = Primitive::Int(discr).size(cx.tcx).bytes();
let discr_size = discr.size(cx.tcx).bytes();
debug!("enum `{}` is {} bytes large with layout:\n{:#?}",
t, size.bytes(), layout);

View file

@ -474,7 +474,7 @@ impl<'a, 'tcx> ArgType<'tcx> {
// Rust enum types that map onto C enums also need to follow
// the target ABI zero-/sign-extension rules.
Layout::CEnum { discr, signed, .. } => (discr, signed),
Layout::CEnum { discr: layout::Int(i), signed, .. } => (i, signed),
_ => return
};

View file

@ -103,7 +103,7 @@ fn generic_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let l = cx.layout_of(t);
debug!("adt::generic_type_of t: {:?} name: {:?}", t, name);
match *l {
layout::CEnum { discr, .. } => Type::from_integer(cx, discr),
layout::CEnum { discr, .. } => cx.llvm_type_of(discr.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);
@ -236,11 +236,3 @@ pub fn is_discr_signed<'tcx>(l: &layout::Layout) -> bool {
_ => false,
}
}
pub fn assert_discr_in_range<D: PartialOrd>(min: D, max: D, discr: D) {
if min <= max {
assert!(min <= discr && discr <= max)
} else {
assert!(min <= discr || discr <= max)
}
}

View file

@ -1451,8 +1451,8 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
})
.collect();
let discriminant_type_metadata = |inttype: layout::Integer, signed: bool| {
let disr_type_key = (enum_def_id, inttype);
let discriminant_type_metadata = |discr: layout::Primitive, signed: bool| {
let disr_type_key = (enum_def_id, discr);
let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
.borrow()
.get(&disr_type_key).cloned();
@ -1460,10 +1460,13 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
Some(discriminant_type_metadata) => discriminant_type_metadata,
None => {
let (discriminant_size, discriminant_align) =
(inttype.size(), inttype.align(cx));
(discr.size(cx), discr.align(cx));
let discriminant_base_type_metadata =
type_metadata(cx,
inttype.to_ty(cx.tcx(), signed),
match discr {
layout::Int(i) => i.to_ty(cx.tcx(), signed),
_ => discr.to_ty(cx.tcx())
},
syntax_pos::DUMMY_SP);
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);

View file

@ -71,7 +71,7 @@ pub struct CrateDebugContext<'tcx> {
llmod: ModuleRef,
builder: DIBuilderRef,
created_files: RefCell<FxHashMap<(Symbol, Symbol), DIFile>>,
created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Integer), DIType>>,
created_enum_disr_types: RefCell<FxHashMap<(DefId, layout::Primitive), DIType>>,
type_map: RefCell<TypeMap<'tcx>>,
namespace_map: RefCell<DefIdMap<DIScope>>,

View file

@ -1093,7 +1093,7 @@ fn trans_const_adt<'a, 'tcx>(
_ => 0,
};
match *l {
layout::CEnum { discr: d, min, max, .. } => {
layout::CEnum { .. } => {
let discr = match *kind {
mir::AggregateKind::Adt(adt_def, _, _, _) => {
adt_def.discriminant_for_variant(ccx.tcx(), variant_index)
@ -1102,14 +1102,14 @@ fn trans_const_adt<'a, 'tcx>(
_ => 0,
};
assert_eq!(vals.len(), 0);
adt::assert_discr_in_range(min, max, discr);
Const::new(C_int(Type::from_integer(ccx, d), discr as i64), t)
Const::new(C_int(ccx.llvm_type_of(t), discr as i64), t)
}
layout::General { discr: d, ref variants, .. } => {
layout::General { ref variants, .. } => {
let discr_ty = l.field(ccx, 0).ty;
let variant = &variants[variant_index];
let lldiscr = C_int(Type::from_integer(ccx, d), variant_index as i64);
let lldiscr = C_int(ccx.llvm_type_of(discr_ty), variant_index as i64);
build_const_struct(ccx, l, &variant, vals,
Some(Const::new(lldiscr, d.to_ty(ccx.tcx(), false))))
Some(Const::new(lldiscr, discr_ty)))
}
layout::UntaggedUnion(ref un) => {
assert_eq!(variant_index, 0);

View file

@ -351,25 +351,28 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
}
/// Helper for cases where the discriminant is simply loaded.
fn load_discr(self, bcx: &Builder, ity: layout::Integer, min: u64, max: u64) -> ValueRef {
let bits = ity.size().bits();
assert!(bits <= 64);
let bits = bits as usize;
let mask = !0u64 >> (64 - bits);
// For a (max) discr of -1, max will be `-1 as usize`, which overflows.
// However, that is fine here (it would still represent the full range),
if max.wrapping_add(1) & mask == min & mask {
// i.e., if the range is everything. The lo==hi case would be
// rejected by the LLVM verifier (it would mean either an
// empty set, which is impossible, or the entire range of the
// type, which is pointless).
bcx.load(self.llval, self.alignment.non_abi())
} else {
// llvm::ConstantRange can deal with ranges that wrap around,
// so an overflow on (max + 1) is fine.
bcx.load_range_assert(self.llval, min, max.wrapping_add(1), /* signed: */ llvm::True,
self.alignment.non_abi())
fn load_discr(self, bcx: &Builder, discr: layout::Primitive, min: u64, max: u64) -> ValueRef {
if let layout::Int(ity) = discr {
let bits = ity.size().bits();
assert!(bits <= 64);
let bits = bits as usize;
let mask = !0u64 >> (64 - bits);
// For a (max) discr of -1, max will be `-1 as usize`, which overflows.
// However, that is fine here (it would still represent the full range),
if max.wrapping_add(1) & mask == min & mask {
// i.e., if the range is everything. The lo==hi case would be
// rejected by the LLVM verifier (it would mean either an
// empty set, which is impossible, or the entire range of the
// type, which is pointless).
} else {
// llvm::ConstantRange can deal with ranges that wrap around,
// so an overflow on (max + 1) is fine.
return bcx.load_range_assert(self.llval, min, max.wrapping_add(1),
/* signed: */ llvm::True,
self.alignment.non_abi());
}
}
bcx.load(self.llval, self.alignment.non_abi())
}
/// Obtain the actual discriminant of a value.
@ -406,14 +409,13 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
.discriminant_for_variant(bcx.tcx(), variant_index)
.to_u128_unchecked() as u64;
match *l {
layout::CEnum { discr, min, max, .. } => {
adt::assert_discr_in_range(min, max, to);
bcx.store(C_int(Type::from_integer(bcx.ccx, discr), to as i64),
layout::CEnum { .. } => {
bcx.store(C_int(bcx.ccx.llvm_type_of(self.ty.to_ty(bcx.tcx())), to as i64),
self.llval, self.alignment.non_abi());
}
layout::General { discr, .. } => {
layout::General { .. } => {
let ptr = self.project_field(bcx, 0);
bcx.store(C_int(Type::from_integer(bcx.ccx, discr), to as i64),
bcx.store(C_int(bcx.ccx.llvm_type_of(ptr.ty.to_ty(bcx.tcx())), to as i64),
ptr.llval, ptr.alignment.non_abi());
}
layout::Univariant { .. }