rustc: move CEnum's signedness into Primitive::Int.
This commit is contained in:
parent
61c2bd9ca4
commit
d318b9c27b
@ -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
|
||||
|
@ -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
|
||||
});
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
};
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -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
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user