]> git.lizzy.rs Git - rust.git/commitdiff
Refactor layout to use the new ReprOptions
authorAustin Hicks <camlorn@camlorn.net>
Tue, 7 Feb 2017 17:35:06 +0000 (12:35 -0500)
committerAustin Hicks <camlorn@camlorn.net>
Tue, 7 Feb 2017 17:35:06 +0000 (12:35 -0500)
src/librustc/ty/layout.rs

index ff3ac3586a78778b69a84b0bbd9b8ec9b2347f27..3a463e981a6272e152b598113b32bdd4154de9fd 100644 (file)
@@ -15,7 +15,7 @@
 use infer::InferCtxt;
 use session::Session;
 use traits;
-use ty::{self, Ty, TyCtxt, TypeFoldable};
+use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions};
 
 use syntax::ast::{FloatTy, IntTy, UintTy};
 use syntax::attr;
@@ -437,7 +437,7 @@ pub fn from_attr(dl: &TargetDataLayout, ity: attr::IntType) -> Integer {
     /// signed discriminant range and #[repr] attribute.
     /// N.B.: u64 values above i64::MAX will be treated as signed, but
     /// that shouldn't affect anything, other than maybe debuginfo.
-    fn repr_discr(tcx: TyCtxt, ty: Ty, hints: &[attr::ReprAttr], min: i64, max: i64)
+    fn repr_discr(tcx: TyCtxt, ty: Ty, repr: &ReprOptions, min: i64, max: i64)
                       -> (Integer, bool) {
         // Theoretically, negative values could be larger in unsigned representation
         // than the unsigned representation of the signed minimum. However, if there
@@ -449,34 +449,24 @@ fn repr_discr(tcx: TyCtxt, ty: Ty, hints: &[attr::ReprAttr], min: i64, max: i64)
         let mut min_from_extern = None;
         let min_default = I8;
 
-        for &r in hints.iter() {
-            match r {
-                attr::ReprInt(ity) => {
-                    let discr = Integer::from_attr(&tcx.data_layout, ity);
-                    let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
-                    if discr < fit {
-                        bug!("Integer::repr_discr: `#[repr]` hint too small for \
-                              discriminant range of enum `{}", ty)
-                    }
-                    return (discr, ity.is_signed());
-                }
-                attr::ReprExtern => {
-                    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,
-                        // but some systems may use the variant corresponding to no
-                        // lower bound.  However, we don't run on those yet...?
-                        "arm" => min_from_extern = Some(I32),
-                        _ => min_from_extern = Some(I32),
-                    }
-                }
-                attr::ReprAny => {},
-                attr::ReprPacked => {
-                    bug!("Integer::repr_discr: found #[repr(packed)] on enum `{}", ty);
-                }
-                attr::ReprSimd => {
-                    bug!("Integer::repr_discr: found #[repr(simd)] on enum `{}", ty);
-                }
+        if let Some(ity) = repr.int {
+            let discr = Integer::from_attr(&tcx.data_layout, ity);
+            let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
+            if discr < fit {
+                bug!("Integer::repr_discr: `#[repr]` hint too small for \
+                  discriminant range of enum `{}", ty)
+            }
+            return (discr, ity.is_signed());
+        }
+
+        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,
+                // but some systems may use the variant corresponding to no
+                // lower bound.  However, we don't run on those yet...?
+                "arm" => min_from_extern = Some(I32),
+                _ => min_from_extern = Some(I32),
             }
         }
 
@@ -568,9 +558,9 @@ enum StructKind {
 impl<'a, 'gcx, 'tcx> Struct {
     // FIXME(camlorn): reprs need a better representation to deal with multiple reprs on one type.
     fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
-                  reprs: &[attr::ReprAttr], kind: StructKind,
+                  repr: &ReprOptions, kind: StructKind,
                   scapegoat: Ty<'gcx>) -> Result<Struct, LayoutError<'gcx>> {
-        let packed = reprs.contains(&attr::ReprPacked);
+        let packed = repr.packed;
         let mut ret = Struct {
             align: if packed { dl.i8_align } else { dl.aggregate_align },
             packed: packed,
@@ -580,27 +570,16 @@ fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
             min_size: Size::from_bytes(0),
         };
 
-        // Anything with ReprExtern or ReprPacked doesn't optimize.
+        // Anything with repr(C) or repr(packed) doesn't optimize.
         // Neither do  1-member and 2-member structs.
         // In addition, code in trans assume that 2-element structs can become pairs.
         // It's easier to just short-circuit here.
-        let mut can_optimize = fields.len() > 2 || StructKind::EnumVariant == kind;
-        if can_optimize {
-            // This exhaustive match makes new reprs force the adder to modify this function.
-            // Otherwise, things can silently break.
-            // Note the inversion, return true to stop optimizing.
-            can_optimize = !reprs.iter().any(|r| {
-                match *r {
-                    attr::ReprAny | attr::ReprInt(_) => false,
-                    attr::ReprExtern | attr::ReprPacked => true,
-                    attr::ReprSimd => bug!("Simd  vectors should be represented as layout::Vector")
-                }
-            });
-        }
+        let mut can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind)
+            && ! (repr.c || repr.packed);
 
         // Disable field reordering until we can decide what to do.
         // The odd pattern here avoids a warning about the value never being read.
-        if can_optimize { can_optimize = false }
+        if can_optimize { can_optimize = false; }
 
         let (optimize, sort_ascending) = match kind {
             StructKind::AlwaysSizedUnivariant => (can_optimize, false),
@@ -1092,7 +1071,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
 
             // The never type.
             ty::TyNever => Univariant {
-                variant: Struct::new(dl, &vec![], &[],
+                variant: Struct::new(dl, &vec![], &ReprOptions::default(),
                   StructKind::AlwaysSizedUnivariant, ty)?,
                 non_zero: false
             },
@@ -1135,12 +1114,12 @@ pub fn compute_uncached(ty: Ty<'gcx>,
             ty::TyFnDef(..) => {
                 Univariant {
                     variant: Struct::new(dl, &vec![],
-                      &[], StructKind::AlwaysSizedUnivariant, ty)?,
+                      &ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?,
                     non_zero: false
                 }
             }
             ty::TyDynamic(..) => {
-                let mut unit = Struct::new(dl, &vec![], &[],
+                let mut unit = Struct::new(dl, &vec![], &ReprOptions::default(),
                   StructKind::AlwaysSizedUnivariant, ty)?;
                 unit.sized = false;
                 Univariant { variant: unit, non_zero: false }
@@ -1152,7 +1131,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                 let st = Struct::new(dl,
                     &tys.map(|ty| ty.layout(infcx))
                       .collect::<Result<Vec<_>, _>>()?,
-                    &[],
+                    &ReprOptions::default(),
                     StructKind::AlwaysSizedUnivariant, ty)?;
                 Univariant { variant: st, non_zero: false }
             }
@@ -1163,7 +1142,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                 let st = Struct::new(dl,
                     &tys.iter().map(|ty| ty.layout(infcx))
                       .collect::<Result<Vec<_>, _>>()?,
-                    &[], StructKind::AlwaysSizedUnivariant, ty)?;
+                    &ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?;
                 Univariant { variant: st, non_zero: false }
             }
 
@@ -1187,16 +1166,13 @@ pub fn compute_uncached(ty: Ty<'gcx>,
 
             // ADTs.
             ty::TyAdt(def, substs) => {
-                let hints = &tcx.lookup_repr_hints(def.did)[..];
-
                 if def.variants.is_empty() {
                     // Uninhabitable; represent as unit
                     // (Typechecking will reject discriminant-sizing attrs.)
-                    assert_eq!(hints.len(), 0);
 
                     return success(Univariant {
                         variant: Struct::new(dl, &vec![],
-                          &hints[..], StructKind::AlwaysSizedUnivariant, ty)?,
+                          &def.repr, StructKind::AlwaysSizedUnivariant, ty)?,
                         non_zero: false
                     });
                 }
@@ -1219,7 +1195,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
 
                     // FIXME: should handle i128? signed-value based impl is weird and hard to
                     // grok.
-                    let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..],
+                    let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr,
                                                               min,
                                                               max);
                     return success(CEnum {
@@ -1232,7 +1208,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     });
                 }
 
-                if !def.is_enum() || def.variants.len() == 1 && hints.is_empty() {
+                if !def.is_enum() || def.variants.len() == 1 {
                     // Struct, or union, or univariant enum equivalent to a struct.
                     // (Typechecking will reject discriminant-sizing attrs.)
 
@@ -1259,7 +1235,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                         un.extend(dl, fields.iter().map(|&f| Ok(f)), ty)?;
                         UntaggedUnion { variants: un }
                     } else {
-                        let st = Struct::new(dl, &fields, &hints[..],
+                        let st = Struct::new(dl, &fields, &def.repr,
                           kind, ty)?;
                         let non_zero = Some(def.did) == tcx.lang_items.non_zero();
                         Univariant { variant: st, non_zero: non_zero }
@@ -1282,7 +1258,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     v.fields.iter().map(|field| field.ty(tcx, substs)).collect::<Vec<_>>()
                 }).collect::<Vec<_>>();
 
-                if variants.len() == 2 && hints.is_empty() {
+                if variants.len() == 2 && !def.repr.c {
                     // Nullable pointer optimization
                     for discr in 0..2 {
                         let other_fields = variants[1 - discr].iter().map(|ty| {
@@ -1315,7 +1291,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                         let st = Struct::new(dl,
                             &variants[discr].iter().map(|ty| ty.layout(infcx))
                               .collect::<Result<Vec<_>, _>>()?,
-                            &hints[..], StructKind::AlwaysSizedUnivariant, ty)?;
+                            &def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
 
                         // We have to fix the last element of path here.
                         let mut i = *path.last().unwrap();
@@ -1338,7 +1314,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                 // The general case.
                 let discr_max = (variants.len() - 1) as i64;
                 assert!(discr_max >= 0);
-                let (min_ity, _) = Integer::repr_discr(tcx, ty, &hints[..], 0, discr_max);
+                let (min_ity, _) = Integer::repr_discr(tcx, ty, &def.repr, 0, discr_max);
 
                 let mut align = dl.aggregate_align;
                 let mut size = Size::from_bytes(0);
@@ -1356,7 +1332,7 @@ pub fn compute_uncached(ty: Ty<'gcx>,
                     fields.insert(0, &discr);
                     let st = Struct::new(dl,
                         &fields,
-                        &hints[..], StructKind::EnumVariant, ty)?;
+                        &def.repr, StructKind::EnumVariant, ty)?;
                     // Find the first field we can't move later
                     // to make room for a larger discriminant.
                     // It is important to skip the first field.