From d318b9c27b46b8d59a21c9015a6847ce1964394c Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Sat, 16 Sep 2017 16:39:53 +0300 Subject: [PATCH] rustc: move CEnum's signedness into Primitive::Int. --- src/librustc/ty/layout.rs | 53 +++++++++++------------- src/librustc_trans/abi.rs | 28 +++++-------- src/librustc_trans/adt.rs | 6 --- src/librustc_trans/cabi_x86_64.rs | 2 +- src/librustc_trans/debuginfo/metadata.rs | 15 +++---- src/librustc_trans/mir/constant.rs | 10 ++--- src/librustc_trans/mir/lvalue.rs | 17 +++++--- src/librustc_trans/mir/rvalue.rs | 14 ++++--- 8 files changed, 65 insertions(+), 80 deletions(-) diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index 65efc3b5186..c7a49b7ae0a 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -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> 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 diff --git a/src/librustc_trans/abi.rs b/src/librustc_trans/abi.rs index 45367508c94..93cfd967643 100644 --- a/src/librustc_trans/abi.rs +++ b/src/librustc_trans/abi.rs @@ -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 - }); + _ => {} } } diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs index e718c7f6f48..de42676a90d 100644 --- a/src/librustc_trans/adt.rs +++ b/src/librustc_trans/adt.rs @@ -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, - } -} diff --git a/src/librustc_trans/cabi_x86_64.rs b/src/librustc_trans/cabi_x86_64.rs index 6e5bc576be5..f2208e4909e 100644 --- a/src/librustc_trans/cabi_x86_64.rs +++ b/src/librustc_trans/cabi_x86_64.rs @@ -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 diff --git a/src/librustc_trans/debuginfo/metadata.rs b/src/librustc_trans/debuginfo/metadata.rs index 9ae1ded7805..aad6f3446ee 100644 --- a/src/librustc_trans/debuginfo/metadata.rs +++ b/src/librustc_trans/debuginfo/metadata.rs @@ -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) }; diff --git a/src/librustc_trans/mir/constant.rs b/src/librustc_trans/mir/constant.rs index dd06f369470..c677352c278 100644 --- a/src/librustc_trans/mir/constant.rs +++ b/src/librustc_trans/mir/constant.rs @@ -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 { diff --git a/src/librustc_trans/mir/lvalue.rs b/src/librustc_trans/mir/lvalue.rs index dd134138f78..4ad6e985e7a 100644 --- a/src/librustc_trans/mir/lvalue.rs +++ b/src/librustc_trans/mir/lvalue.rs @@ -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 diff --git a/src/librustc_trans/mir/rvalue.rs b/src/librustc_trans/mir/rvalue.rs index e83d4c586e7..b931d9a2549 100644 --- a/src/librustc_trans/mir/rvalue.rs +++ b/src/librustc_trans/mir/rvalue.rs @@ -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) {