rustc: move CEnum's signedness into Primitive::Int.

This commit is contained in:
Eduard-Mihai Burtescu 2017-09-16 16:39:53 +03:00
parent 61c2bd9ca4
commit d318b9c27b
8 changed files with 65 additions and 80 deletions

View File

@ -498,7 +498,7 @@ impl<'a, 'tcx> Integer {
let wanted = align.abi();
for &candidate in &[I8, I16, I32, I64] {
let ty = Int(candidate);
let ty = Int(candidate, false);
if wanted == ty.align(dl).abi() && wanted == ty.size(dl).bytes() {
return Some(candidate);
}
@ -577,7 +577,14 @@ impl<'a, 'tcx> Integer {
/// Fundamental unit of memory access and layout.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum Primitive {
Int(Integer),
/// The `bool` is the signedness of the `Integer` type.
///
/// One would think we would not care about such details this low down,
/// but some ABIs are described in terms of C types and ISAs where the
/// integer arithmetic is done on {sign,zero}-extended registers, e.g.
/// a negative integer passed by zero-extension will appear positive in
/// the callee, and most operations on it will produce the wrong values.
Int(Integer, bool),
F32,
F64,
Pointer
@ -588,11 +595,9 @@ impl<'a, 'tcx> Primitive {
let dl = cx.data_layout();
match self {
Int(I1) | Int(I8) => Size::from_bits(8),
Int(I16) => Size::from_bits(16),
Int(I32) | F32 => Size::from_bits(32),
Int(I64) | F64 => Size::from_bits(64),
Int(I128) => Size::from_bits(128),
Int(i, _) => i.size(),
F32 => Size::from_bits(32),
F64 => Size::from_bits(64),
Pointer => dl.pointer_size
}
}
@ -601,12 +606,7 @@ impl<'a, 'tcx> Primitive {
let dl = cx.data_layout();
match self {
Int(I1) => dl.i1_align,
Int(I8) => dl.i8_align,
Int(I16) => dl.i16_align,
Int(I32) => dl.i32_align,
Int(I64) => dl.i64_align,
Int(I128) => dl.i128_align,
Int(i, _) => i.align(dl),
F32 => dl.f32_align,
F64 => dl.f64_align,
Pointer => dl.pointer_align
@ -615,7 +615,7 @@ impl<'a, 'tcx> Primitive {
pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
match *self {
Int(i) => i.to_ty(tcx, false),
Int(i, signed) => i.to_ty(tcx, signed),
F32 => tcx.types.f32,
F64 => tcx.types.f64,
Pointer => tcx.mk_mut_ptr(tcx.mk_nil()),
@ -1098,7 +1098,6 @@ pub enum Layout {
/// C-like enums; basically an integer.
CEnum {
discr: Primitive,
signed: bool,
/// 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
@ -1287,7 +1286,7 @@ impl<'a, 'tcx> Layout {
let metadata = match unsized_part.sty {
ty::TyForeign(..) => return Ok(Scalar(Pointer)),
ty::TySlice(_) | ty::TyStr => {
Int(dl.ptr_sized_integer())
Int(dl.ptr_sized_integer(), false)
}
ty::TyDynamic(..) => Pointer,
_ => return Err(LayoutError::Unknown(unsized_part))
@ -1298,13 +1297,13 @@ impl<'a, 'tcx> Layout {
let layout = match ty.sty {
// Basic scalars.
ty::TyBool => Scalar(Int(I1)),
ty::TyChar => Scalar(Int(I32)),
ty::TyBool => Scalar(Int(I1, false)),
ty::TyChar => Scalar(Int(I32, false)),
ty::TyInt(ity) => {
Scalar(Int(Integer::from_attr(dl, attr::SignedInt(ity))))
Scalar(Int(Integer::from_attr(dl, attr::SignedInt(ity)), true))
}
ty::TyUint(ity) => {
Scalar(Int(Integer::from_attr(dl, attr::UnsignedInt(ity))))
Scalar(Int(Integer::from_attr(dl, attr::UnsignedInt(ity)), false))
}
ty::TyFloat(FloatTy::F32) => Scalar(F32),
ty::TyFloat(FloatTy::F64) => Scalar(F64),
@ -1453,8 +1452,7 @@ impl<'a, 'tcx> Layout {
// grok.
let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
return success(CEnum {
discr: Int(discr),
signed,
discr: Int(discr, signed),
// FIXME: should be u128?
min: min as u64,
max: max as u64
@ -1629,8 +1627,8 @@ impl<'a, 'tcx> Layout {
ity = min_ity;
} else {
// Patch up the variants' first few fields.
let old_ity_size = Int(min_ity).size(dl);
let new_ity_size = Int(ity).size(dl);
let old_ity_size = min_ity.size();
let new_ity_size = ity.size();
for variant in &mut variants {
for i in variant.offsets.iter_mut() {
if *i <= old_ity_size {
@ -1646,7 +1644,7 @@ impl<'a, 'tcx> Layout {
}
General {
discr: Int(ity),
discr: Int(ity, false),
variants,
size,
align,
@ -2417,9 +2415,8 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Layout
FatPointer(ref metadata) => {
metadata.hash_stable(hcx, hasher);
}
CEnum { discr, signed, min, max } => {
CEnum { discr, min, max } => {
discr.hash_stable(hcx, hasher);
signed.hash_stable(hcx, hasher);
min.hash_stable(hcx, hasher);
max.hash_stable(hcx, hasher);
}
@ -2505,7 +2502,7 @@ impl_stable_hash_for!(enum ::ty::layout::Integer {
});
impl_stable_hash_for!(enum ::ty::layout::Primitive {
Int(integer),
Int(integer, signed),
F32,
F64,
Pointer

View File

@ -288,7 +288,7 @@ impl<'tcx> LayoutExt<'tcx> for FullLayout<'tcx> {
// The primitive for this algorithm.
layout::Abi::Scalar(value) => {
let kind = match value {
layout::Int(_) |
layout::Int(..) |
layout::Pointer => RegKind::Integer,
layout::F32 |
layout::F64 => RegKind::Float
@ -467,24 +467,18 @@ impl<'a, 'tcx> ArgType<'tcx> {
pub fn extend_integer_width_to(&mut self, bits: u64) {
// Only integers have signedness
let (i, signed) = match *self.layout {
Layout::Scalar(layout::Int(i)) if self.layout.ty.is_integral() => {
(i, self.layout.ty.is_signed())
match self.layout.abi {
layout::Abi::Scalar(layout::Int(i, signed)) => {
if i.size().bits() < bits {
self.attrs.set(if signed {
ArgAttribute::SExt
} else {
ArgAttribute::ZExt
});
}
}
// Rust enum types that map onto C enums also need to follow
// the target ABI zero-/sign-extension rules.
Layout::CEnum { discr: layout::Int(i), signed, .. } => (i, signed),
_ => return
};
if i.size().bits() < bits {
self.attrs.set(if signed {
ArgAttribute::SExt
} else {
ArgAttribute::ZExt
});
_ => {}
}
}

View File

@ -230,9 +230,3 @@ pub fn struct_llfields<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
result
}
pub fn is_discr_signed<'tcx>(l: &layout::Layout) -> bool {
match *l {
layout::CEnum { signed, .. }=> signed,
_ => false,
}
}

View File

@ -67,7 +67,7 @@ fn classify_arg<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, arg: &ArgType<'tcx>)
match layout.abi {
layout::Abi::Scalar(value) => {
let reg = match value {
layout::Int(_) |
layout::Int(..) |
layout::Pointer => Class::Int,
layout::F32 |
layout::F64 => Class::Sse

View File

@ -1451,7 +1451,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
})
.collect();
let discriminant_type_metadata = |discr: layout::Primitive, signed: bool| {
let discriminant_type_metadata = |discr: layout::Primitive| {
let disr_type_key = (enum_def_id, discr);
let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
.borrow()
@ -1462,12 +1462,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let (discriminant_size, discriminant_align) =
(discr.size(cx), discr.align(cx));
let discriminant_base_type_metadata =
type_metadata(cx,
match discr {
layout::Int(i) => i.to_ty(cx.tcx(), signed),
_ => discr.to_ty(cx.tcx())
},
syntax_pos::DUMMY_SP);
type_metadata(cx, discr.to_ty(cx.tcx()), syntax_pos::DUMMY_SP);
let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
let name = CString::new(discriminant_name.as_bytes()).unwrap();
@ -1496,11 +1491,11 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let type_rep = cx.layout_of(enum_type);
let discriminant_type_metadata = match *type_rep {
layout::CEnum { discr, signed, .. } => {
return FinalMetadata(discriminant_type_metadata(discr, signed))
layout::CEnum { discr, .. } => {
return FinalMetadata(discriminant_type_metadata(discr))
},
layout::NullablePointer { .. } | layout::Univariant { .. } => None,
layout::General { discr, .. } => Some(discriminant_type_metadata(discr, false)),
layout::General { discr, .. } => Some(discriminant_type_metadata(discr)),
ref l @ _ => bug!("Not an enum layout: {:#?}", l)
};

View File

@ -23,7 +23,7 @@ use rustc::ty::cast::{CastTy, IntTy};
use rustc::ty::subst::{Kind, Substs, Subst};
use rustc_apfloat::{ieee, Float, Status};
use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use {adt, base};
use base;
use abi::{self, Abi};
use callee;
use builder::Builder;
@ -683,11 +683,9 @@ impl<'a, 'tcx> MirConstContext<'a, 'tcx> {
let r_t_out = CastTy::from_ty(cast_ty).expect("bad output type for cast");
let ll_t_out = self.ccx.immediate_llvm_type_of(cast_ty);
let llval = operand.llval;
let signed = if let CastTy::Int(IntTy::CEnum) = r_t_in {
let l = self.ccx.layout_of(operand.ty);
adt::is_discr_signed(&l)
} else {
operand.ty.is_signed()
let signed = match self.ccx.layout_of(operand.ty).abi {
layout::Abi::Scalar(layout::Int(_, signed)) => signed,
_ => false
};
unsafe {

View File

@ -352,7 +352,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
/// Helper for cases where the discriminant is simply loaded.
fn load_discr(self, bcx: &Builder, discr: layout::Primitive, min: u64, max: u64) -> ValueRef {
if let layout::Int(ity) = discr {
if let layout::Int(ity, _) = discr {
let bits = ity.size().bits();
assert!(bits <= 64);
let bits = bits as usize;
@ -380,25 +380,30 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
let l = bcx.ccx.layout_of(self.ty.to_ty(bcx.tcx()));
let cast_to = bcx.ccx.immediate_llvm_type_of(cast_to);
let val = match *l {
let (val, discr) = match *l {
layout::Univariant { .. } |
layout::UntaggedUnion { .. } => return C_uint(cast_to, 0),
layout::CEnum { discr, min, max, .. } => {
self.load_discr(bcx, discr, min, max)
(self.load_discr(bcx, discr, min, max), discr)
}
layout::General { discr, ref variants, .. } => {
let ptr = self.project_field(bcx, 0);
ptr.load_discr(bcx, discr, 0, variants.len() as u64 - 1)
(ptr.load_discr(bcx, discr, 0, variants.len() as u64 - 1), discr)
}
layout::NullablePointer { nndiscr, .. } => {
let ptr = self.project_field(bcx, 0);
let lldiscr = bcx.load(ptr.llval, ptr.alignment.non_abi());
let cmp = if nndiscr == 0 { llvm::IntEQ } else { llvm::IntNE };
bcx.icmp(cmp, lldiscr, C_null(bcx.ccx.llvm_type_of(ptr.ty.to_ty(bcx.tcx()))))
(bcx.icmp(cmp, lldiscr, C_null(bcx.ccx.llvm_type_of(ptr.ty.to_ty(bcx.tcx())))),
layout::Int(layout::I1, false))
},
_ => bug!("{} is not an enum", l.ty)
};
bcx.intcast(val, cast_to, adt::is_discr_signed(&l))
let signed = match discr {
layout::Int(_, signed) => signed,
_ => false
};
bcx.intcast(val, cast_to, signed)
}
/// Set the discriminant for a new value of the given case of the given

View File

@ -11,7 +11,7 @@
use llvm::{self, ValueRef};
use rustc::ty::{self, Ty};
use rustc::ty::cast::{CastTy, IntTy};
use rustc::ty::layout::{Layout, LayoutOf};
use rustc::ty::layout::{self, Layout, LayoutOf};
use rustc::mir;
use rustc::middle::lang_items::ExchangeMallocFnLangItem;
use rustc_apfloat::{ieee, Float, Status, Round};
@ -276,7 +276,8 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
let ll_t_out = bcx.ccx.immediate_llvm_type_of(cast_ty);
let llval = operand.immediate();
let l = bcx.ccx.layout_of(operand.ty);
let signed = if let Layout::CEnum { signed, min, max, .. } = *l {
if let Layout::CEnum { min, max, .. } = *l {
if max > min {
// We want `table[e as usize]` to not
// have bound checks, and this is the most
@ -285,13 +286,14 @@ impl<'a, 'tcx> MirContext<'a, 'tcx> {
base::call_assume(&bcx, bcx.icmp(
llvm::IntULE,
llval,
C_uint(common::val_ty(llval), max)
C_uint(ll_t_in, max)
));
}
}
signed
} else {
operand.ty.is_signed()
let signed = match l.abi {
layout::Abi::Scalar(layout::Int(_, signed)) => signed,
_ => false
};
let newval = match (r_t_in, r_t_out) {