1
Fork 0

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(); let wanted = align.abi();
for &candidate in &[I8, I16, I32, I64] { 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() { if wanted == ty.align(dl).abi() && wanted == ty.size(dl).bytes() {
return Some(candidate); return Some(candidate);
} }
@ -577,7 +577,14 @@ impl<'a, 'tcx> Integer {
/// Fundamental unit of memory access and layout. /// Fundamental unit of memory access and layout.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
pub enum Primitive { 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, F32,
F64, F64,
Pointer Pointer
@ -588,11 +595,9 @@ impl<'a, 'tcx> Primitive {
let dl = cx.data_layout(); let dl = cx.data_layout();
match self { match self {
Int(I1) | Int(I8) => Size::from_bits(8), Int(i, _) => i.size(),
Int(I16) => Size::from_bits(16), F32 => Size::from_bits(32),
Int(I32) | F32 => Size::from_bits(32), F64 => Size::from_bits(64),
Int(I64) | F64 => Size::from_bits(64),
Int(I128) => Size::from_bits(128),
Pointer => dl.pointer_size Pointer => dl.pointer_size
} }
} }
@ -601,12 +606,7 @@ impl<'a, 'tcx> Primitive {
let dl = cx.data_layout(); let dl = cx.data_layout();
match self { match self {
Int(I1) => dl.i1_align, Int(i, _) => i.align(dl),
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,
F32 => dl.f32_align, F32 => dl.f32_align,
F64 => dl.f64_align, F64 => dl.f64_align,
Pointer => dl.pointer_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> { pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
match *self { match *self {
Int(i) => i.to_ty(tcx, false), Int(i, signed) => i.to_ty(tcx, signed),
F32 => tcx.types.f32, F32 => tcx.types.f32,
F64 => tcx.types.f64, F64 => tcx.types.f64,
Pointer => tcx.mk_mut_ptr(tcx.mk_nil()), Pointer => tcx.mk_mut_ptr(tcx.mk_nil()),
@ -1098,7 +1098,6 @@ pub enum Layout {
/// C-like enums; basically an integer. /// C-like enums; basically an integer.
CEnum { CEnum {
discr: Primitive, discr: Primitive,
signed: bool,
/// Inclusive discriminant range. /// Inclusive discriminant range.
/// If min > max, it represents min...u64::MAX followed by 0...max. /// If min > max, it represents min...u64::MAX followed by 0...max.
// FIXME(eddyb) always use the shortest range, e.g. by finding // 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 { let metadata = match unsized_part.sty {
ty::TyForeign(..) => return Ok(Scalar(Pointer)), ty::TyForeign(..) => return Ok(Scalar(Pointer)),
ty::TySlice(_) | ty::TyStr => { ty::TySlice(_) | ty::TyStr => {
Int(dl.ptr_sized_integer()) Int(dl.ptr_sized_integer(), false)
} }
ty::TyDynamic(..) => Pointer, ty::TyDynamic(..) => Pointer,
_ => return Err(LayoutError::Unknown(unsized_part)) _ => return Err(LayoutError::Unknown(unsized_part))
@ -1298,13 +1297,13 @@ impl<'a, 'tcx> Layout {
let layout = match ty.sty { let layout = match ty.sty {
// Basic scalars. // Basic scalars.
ty::TyBool => Scalar(Int(I1)), ty::TyBool => Scalar(Int(I1, false)),
ty::TyChar => Scalar(Int(I32)), ty::TyChar => Scalar(Int(I32, false)),
ty::TyInt(ity) => { 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) => { 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::F32) => Scalar(F32),
ty::TyFloat(FloatTy::F64) => Scalar(F64), ty::TyFloat(FloatTy::F64) => Scalar(F64),
@ -1453,8 +1452,7 @@ impl<'a, 'tcx> Layout {
// grok. // grok.
let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max); let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr, min, max);
return success(CEnum { return success(CEnum {
discr: Int(discr), discr: Int(discr, signed),
signed,
// FIXME: should be u128? // FIXME: should be u128?
min: min as u64, min: min as u64,
max: max as u64 max: max as u64
@ -1629,8 +1627,8 @@ impl<'a, 'tcx> Layout {
ity = min_ity; ity = min_ity;
} else { } else {
// Patch up the variants' first few fields. // Patch up the variants' first few fields.
let old_ity_size = Int(min_ity).size(dl); let old_ity_size = min_ity.size();
let new_ity_size = Int(ity).size(dl); let new_ity_size = ity.size();
for variant in &mut variants { for variant in &mut variants {
for i in variant.offsets.iter_mut() { for i in variant.offsets.iter_mut() {
if *i <= old_ity_size { if *i <= old_ity_size {
@ -1646,7 +1644,7 @@ impl<'a, 'tcx> Layout {
} }
General { General {
discr: Int(ity), discr: Int(ity, false),
variants, variants,
size, size,
align, align,
@ -2417,9 +2415,8 @@ 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, signed, min, max } => { CEnum { discr, min, max } => {
discr.hash_stable(hcx, hasher); discr.hash_stable(hcx, hasher);
signed.hash_stable(hcx, hasher);
min.hash_stable(hcx, hasher); min.hash_stable(hcx, hasher);
max.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 { impl_stable_hash_for!(enum ::ty::layout::Primitive {
Int(integer), Int(integer, signed),
F32, F32,
F64, F64,
Pointer Pointer

View file

@ -288,7 +288,7 @@ impl<'tcx> LayoutExt<'tcx> for FullLayout<'tcx> {
// The primitive for this algorithm. // The primitive for this algorithm.
layout::Abi::Scalar(value) => { layout::Abi::Scalar(value) => {
let kind = match value { let kind = match value {
layout::Int(_) | layout::Int(..) |
layout::Pointer => RegKind::Integer, layout::Pointer => RegKind::Integer,
layout::F32 | layout::F32 |
layout::F64 => RegKind::Float layout::F64 => RegKind::Float
@ -467,24 +467,18 @@ impl<'a, 'tcx> ArgType<'tcx> {
pub fn extend_integer_width_to(&mut self, bits: u64) { pub fn extend_integer_width_to(&mut self, bits: u64) {
// Only integers have signedness // Only integers have signedness
let (i, signed) = match *self.layout { match self.layout.abi {
Layout::Scalar(layout::Int(i)) if self.layout.ty.is_integral() => { layout::Abi::Scalar(layout::Int(i, signed)) => {
(i, self.layout.ty.is_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 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 { match layout.abi {
layout::Abi::Scalar(value) => { layout::Abi::Scalar(value) => {
let reg = match value { let reg = match value {
layout::Int(_) | layout::Int(..) |
layout::Pointer => Class::Int, layout::Pointer => Class::Int,
layout::F32 | layout::F32 |
layout::F64 => Class::Sse layout::F64 => Class::Sse

View file

@ -1451,7 +1451,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
}) })
.collect(); .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 disr_type_key = (enum_def_id, discr);
let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types let cached_discriminant_type_metadata = debug_context(cx).created_enum_disr_types
.borrow() .borrow()
@ -1462,12 +1462,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
let (discriminant_size, discriminant_align) = let (discriminant_size, discriminant_align) =
(discr.size(cx), discr.align(cx)); (discr.size(cx), discr.align(cx));
let discriminant_base_type_metadata = let discriminant_base_type_metadata =
type_metadata(cx, type_metadata(cx, discr.to_ty(cx.tcx()), syntax_pos::DUMMY_SP);
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); let discriminant_name = get_enum_discriminant_name(cx, enum_def_id);
let name = CString::new(discriminant_name.as_bytes()).unwrap(); 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 type_rep = cx.layout_of(enum_type);
let discriminant_type_metadata = match *type_rep { let discriminant_type_metadata = match *type_rep {
layout::CEnum { discr, signed, .. } => { layout::CEnum { discr, .. } => {
return FinalMetadata(discriminant_type_metadata(discr, signed)) return FinalMetadata(discriminant_type_metadata(discr))
}, },
layout::NullablePointer { .. } | layout::Univariant { .. } => None, 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) 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::ty::subst::{Kind, Substs, Subst};
use rustc_apfloat::{ieee, Float, Status}; use rustc_apfloat::{ieee, Float, Status};
use rustc_data_structures::indexed_vec::{Idx, IndexVec}; use rustc_data_structures::indexed_vec::{Idx, IndexVec};
use {adt, base}; use base;
use abi::{self, Abi}; use abi::{self, Abi};
use callee; use callee;
use builder::Builder; 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 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 ll_t_out = self.ccx.immediate_llvm_type_of(cast_ty);
let llval = operand.llval; let llval = operand.llval;
let signed = if let CastTy::Int(IntTy::CEnum) = r_t_in { let signed = match self.ccx.layout_of(operand.ty).abi {
let l = self.ccx.layout_of(operand.ty); layout::Abi::Scalar(layout::Int(_, signed)) => signed,
adt::is_discr_signed(&l) _ => false
} else {
operand.ty.is_signed()
}; };
unsafe { unsafe {

View file

@ -352,7 +352,7 @@ impl<'a, 'tcx> LvalueRef<'tcx> {
/// Helper for cases where the discriminant is simply loaded. /// Helper for cases where the discriminant is simply loaded.
fn load_discr(self, bcx: &Builder, discr: layout::Primitive, min: u64, max: u64) -> ValueRef { 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(); let bits = ity.size().bits();
assert!(bits <= 64); assert!(bits <= 64);
let bits = bits as usize; 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 l = bcx.ccx.layout_of(self.ty.to_ty(bcx.tcx()));
let cast_to = bcx.ccx.immediate_llvm_type_of(cast_to); let cast_to = bcx.ccx.immediate_llvm_type_of(cast_to);
let val = match *l { let (val, discr) = match *l {
layout::Univariant { .. } | layout::Univariant { .. } |
layout::UntaggedUnion { .. } => return C_uint(cast_to, 0), layout::UntaggedUnion { .. } => return C_uint(cast_to, 0),
layout::CEnum { discr, min, max, .. } => { 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, .. } => { layout::General { discr, ref variants, .. } => {
let ptr = self.project_field(bcx, 0); 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, .. } => { layout::NullablePointer { nndiscr, .. } => {
let ptr = self.project_field(bcx, 0); let ptr = self.project_field(bcx, 0);
let lldiscr = bcx.load(ptr.llval, ptr.alignment.non_abi()); let lldiscr = bcx.load(ptr.llval, ptr.alignment.non_abi());
let cmp = if nndiscr == 0 { llvm::IntEQ } else { llvm::IntNE }; 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) _ => 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 /// 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 llvm::{self, ValueRef};
use rustc::ty::{self, Ty}; use rustc::ty::{self, Ty};
use rustc::ty::cast::{CastTy, IntTy}; use rustc::ty::cast::{CastTy, IntTy};
use rustc::ty::layout::{Layout, LayoutOf}; use rustc::ty::layout::{self, Layout, LayoutOf};
use rustc::mir; use rustc::mir;
use rustc::middle::lang_items::ExchangeMallocFnLangItem; use rustc::middle::lang_items::ExchangeMallocFnLangItem;
use rustc_apfloat::{ieee, Float, Status, Round}; 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 ll_t_out = bcx.ccx.immediate_llvm_type_of(cast_ty);
let llval = operand.immediate(); let llval = operand.immediate();
let l = bcx.ccx.layout_of(operand.ty); 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 { if max > min {
// 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
@ -285,13 +286,14 @@ 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(common::val_ty(llval), max) C_uint(ll_t_in, max)
)); ));
} }
}
signed let signed = match l.abi {
} else { layout::Abi::Scalar(layout::Int(_, signed)) => signed,
operand.ty.is_signed() _ => false
}; };
let newval = match (r_t_in, r_t_out) { let newval = match (r_t_in, r_t_out) {