Skip to content

Commit

Permalink
Compress ReprOptions a little bit
Browse files Browse the repository at this point in the history
  • Loading branch information
nagisa committed Apr 16, 2017
1 parent 13fd5e9 commit fcbd898
Show file tree
Hide file tree
Showing 7 changed files with 65 additions and 35 deletions.
2 changes: 1 addition & 1 deletion src/librustc/middle/dead.rs
Expand Up @@ -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);
}
Expand Down
2 changes: 1 addition & 1 deletion src/librustc/middle/intrinsicck.rs
Expand Up @@ -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() {
Expand Down
14 changes: 7 additions & 7 deletions src/librustc/ty/layout.rs
Expand Up @@ -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;
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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<Struct, LayoutError<'gcx>> {
let packed = repr.packed;
let packed = repr.packed();
let mut ret = Struct {
align: if packed { dl.i8_align } else { dl.aggregate_align },
packed: packed,
Expand All @@ -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),
Expand Down Expand Up @@ -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, .. } => {
Expand Down Expand Up @@ -1255,7 +1255,7 @@ impl<'a, 'gcx, 'tcx> Layout {
field.ty(tcx, substs).layout(infcx)
}).collect::<Result<Vec<_>, _>>()?;
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 {
Expand Down Expand Up @@ -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)
}

Expand Down
72 changes: 51 additions & 21 deletions src/librustc/ty/mod.rs
Expand Up @@ -1438,51 +1438,81 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a, 'tcx>> 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<attr::IntType>,
// 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))
}
Expand All @@ -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()
}
}

Expand Down
2 changes: 1 addition & 1 deletion src/librustc/ty/sty.rs
Expand Up @@ -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,
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/librustc_lint/types.rs
Expand Up @@ -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");
Expand Down Expand Up @@ -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");
Expand Down Expand Up @@ -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<extern fn()>`.
if !is_repr_nullable_ptr(cx, def, substs) {
return FfiUnsafe("found enum without foreign-function-safe \
Expand Down
2 changes: 1 addition & 1 deletion src/librustc_typeck/check/mod.rs
Expand Up @@ -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);
}
}
Expand Down

0 comments on commit fcbd898

Please sign in to comment.