diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs index 8926ff5c1fbbb..342553593af33 100644 --- a/src/librustc/middle/dead.rs +++ b/src/librustc/middle/dead.rs @@ -162,7 +162,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> { hir::ItemStruct(..) | hir::ItemUnion(..) => { let def_id = self.tcx.hir.local_def_id(item.id); let def = self.tcx.lookup_adt_def(def_id); - self.struct_has_extern_repr = def.repr.c; + self.struct_has_extern_repr = def.repr.c(); intravisit::walk_item(self, &item); } diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs index 8dc298b9c2a17..942f8475ecedd 100644 --- a/src/librustc/middle/intrinsicck.rs +++ b/src/librustc/middle/intrinsicck.rs @@ -46,7 +46,7 @@ fn unpack_option_like<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, _ => return ty }; - if def.variants.len() == 2 && !def.repr.c && def.repr.int.is_none() { + if def.variants.len() == 2 && !def.repr.c() && def.repr.int.is_none() { let data_idx; if def.variants[0].fields.is_empty() { diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs index d7a4b3fda63bb..df60eee8c0243 100644 --- a/src/librustc/ty/layout.rs +++ b/src/librustc/ty/layout.rs @@ -15,7 +15,7 @@ pub use self::Primitive::*; use infer::InferCtxt; use session::Session; use traits; -use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions}; +use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions, ReprFlags}; use syntax::ast::{FloatTy, IntTy, UintTy}; use syntax::attr; @@ -479,7 +479,7 @@ impl Integer { return (discr, ity.is_signed()); } - if repr.c { + if repr.c() { match &tcx.sess.target.target.arch[..] { // WARNING: the ARM EABI has two variants; the one corresponding // to `at_least == I32` appears to be used on Linux and NetBSD, @@ -583,7 +583,7 @@ impl<'a, 'gcx, 'tcx> Struct { fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>, repr: &ReprOptions, kind: StructKind, scapegoat: Ty<'gcx>) -> Result> { - let packed = repr.packed; + let packed = repr.packed(); let mut ret = Struct { align: if packed { dl.i8_align } else { dl.aggregate_align }, packed: packed, @@ -598,7 +598,7 @@ impl<'a, 'gcx, 'tcx> Struct { // In addition, code in trans assume that 2-element structs can become pairs. // It's easier to just short-circuit here. let can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind) - && !(repr.c || repr.packed || repr.linear || repr.simd); + && (repr.flags & ReprFlags::IS_UNOPTIMISABLE).is_empty(); let (optimize, sort_ascending) = match kind { StructKind::AlwaysSizedUnivariant => (can_optimize, false), @@ -1177,7 +1177,7 @@ impl<'a, 'gcx, 'tcx> Layout { } // SIMD vector types. - ty::TyAdt(def, ..) if def.repr.simd => { + ty::TyAdt(def, ..) if def.repr.simd() => { let element = ty.simd_type(tcx); match *element.layout(infcx)? { Scalar { value, .. } => { @@ -1255,7 +1255,7 @@ impl<'a, 'gcx, 'tcx> Layout { field.ty(tcx, substs).layout(infcx) }).collect::, _>>()?; let layout = if def.is_union() { - let mut un = Union::new(dl, def.repr.packed); + let mut un = Union::new(dl, def.repr.packed()); un.extend(dl, fields.iter().map(|&f| Ok(f)), ty)?; UntaggedUnion { variants: un } } else { @@ -1925,7 +1925,7 @@ impl<'a, 'tcx> TyLayout<'tcx> { ty::TyTuple(tys, _) => tys[i], // SIMD vector types. - ty::TyAdt(def, ..) if def.repr.simd => { + ty::TyAdt(def, ..) if def.repr.simd() => { self.ty.simd_type(tcx) } diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index 09eacb40aef7e..b4f2deabd234e 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -1438,51 +1438,81 @@ impl<'a, 'tcx> HashStable> for AdtDef { #[derive(Copy, Clone, Debug, Eq, PartialEq)] pub enum AdtKind { Struct, Union, Enum } +bitflags! { + #[derive(RustcEncodable, RustcDecodable, Default)] + flags ReprFlags: u8 { + const IS_C = 1 << 0, + const IS_PACKED = 1 << 1, + const IS_SIMD = 1 << 2, + // Internal only for now. If true, don't reorder fields. + const IS_LINEAR = 1 << 3, + + // Any of these flags being set prevent field reordering optimisation. + const IS_UNOPTIMISABLE = ReprFlags::IS_C.bits | + ReprFlags::IS_PACKED.bits | + ReprFlags::IS_SIMD.bits | + ReprFlags::IS_LINEAR.bits, + } +} + +impl_stable_hash_for!(struct ReprFlags { + bits +}); + + + /// Represents the repr options provided by the user, #[derive(Copy, Clone, Eq, PartialEq, RustcEncodable, RustcDecodable, Default)] pub struct ReprOptions { - pub c: bool, - pub packed: bool, - pub simd: bool, pub int: Option, - // Internal only for now. If true, don't reorder fields. - pub linear: bool, + pub flags: ReprFlags, } impl_stable_hash_for!(struct ReprOptions { - c, - packed, - simd, int, - linear + flags }); impl ReprOptions { pub fn new(tcx: TyCtxt, did: DefId) -> ReprOptions { - let mut ret = ReprOptions::default(); + let mut flags = ReprFlags::empty(); + let mut size = None; for attr in tcx.get_attrs(did).iter() { for r in attr::find_repr_attrs(tcx.sess.diagnostic(), attr) { - match r { - attr::ReprExtern => ret.c = true, - attr::ReprPacked => ret.packed = true, - attr::ReprSimd => ret.simd = true, - attr::ReprInt(i) => ret.int = Some(i), - } + flags.insert(match r { + attr::ReprExtern => ReprFlags::IS_C, + attr::ReprPacked => ReprFlags::IS_PACKED, + attr::ReprSimd => ReprFlags::IS_SIMD, + attr::ReprInt(i) => { + size = Some(i); + ReprFlags::empty() + }, + }); } } // FIXME(eddyb) This is deprecated and should be removed. if tcx.has_attr(did, "simd") { - ret.simd = true; + flags.insert(ReprFlags::IS_SIMD); } // This is here instead of layout because the choice must make it into metadata. - ret.linear = !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", - tcx.item_path_str(did))); - ret + if !tcx.consider_optimizing(|| format!("Reorder fields of {:?}", tcx.item_path_str(did))) { + flags.insert(ReprFlags::IS_LINEAR); + } + ReprOptions { int: size, flags: flags } } + #[inline] + pub fn simd(&self) -> bool { self.flags.contains(ReprFlags::IS_SIMD) } + #[inline] + pub fn c(&self) -> bool { self.flags.contains(ReprFlags::IS_C) } + #[inline] + pub fn packed(&self) -> bool { self.flags.contains(ReprFlags::IS_PACKED) } + #[inline] + pub fn linear(&self) -> bool { self.flags.contains(ReprFlags::IS_LINEAR) } + pub fn discr_type(&self) -> attr::IntType { self.int.unwrap_or(attr::SignedInt(ast::IntTy::Is)) } @@ -1491,7 +1521,7 @@ impl ReprOptions { /// layout" optimizations, such as representing `Foo<&T>` as a /// single pointer. pub fn inhibit_enum_layout_opt(&self) -> bool { - self.c || self.int.is_some() + self.c() || self.int.is_some() } } diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs index 0e3005847bc2c..d59248170344e 100644 --- a/src/librustc/ty/sty.rs +++ b/src/librustc/ty/sty.rs @@ -1095,7 +1095,7 @@ impl<'a, 'gcx, 'tcx> TyS<'tcx> { #[inline] pub fn is_simd(&self) -> bool { match self.sty { - TyAdt(def, _) => def.repr.simd, + TyAdt(def, _) => def.repr.simd(), _ => false, } } diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs index 2318bb81affe6..3e60d8a5ada09 100644 --- a/src/librustc_lint/types.rs +++ b/src/librustc_lint/types.rs @@ -416,7 +416,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { } match def.adt_kind() { AdtKind::Struct => { - if !def.repr.c { + if !def.repr.c() { return FfiUnsafe("found struct without foreign-function-safe \ representation annotation in foreign module, \ consider adding a #[repr(C)] attribute to the type"); @@ -450,7 +450,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { if all_phantom { FfiPhantom } else { FfiSafe } } AdtKind::Union => { - if !def.repr.c { + if !def.repr.c() { return FfiUnsafe("found union without foreign-function-safe \ representation annotation in foreign module, \ consider adding a #[repr(C)] attribute to the type"); @@ -489,7 +489,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> { // Check for a repr() attribute to specify the size of the // discriminant. - if !def.repr.c && def.repr.int.is_none() { + if !def.repr.c() && def.repr.int.is_none() { // Special-case types like `Option`. if !is_repr_nullable_ptr(cx, def, substs) { return FfiUnsafe("found enum without foreign-function-safe \ diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index 5e7325275b819..daa18aaa556ab 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -918,7 +918,7 @@ fn check_struct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def.destructor(tcx); // force the destructor to be evaluated check_representable(tcx, span, def_id); - if def.repr.simd { + if def.repr.simd() { check_simd(tcx, span, def_id); } }