Skip to content

Commit c3b64cf

Browse files
committed
Refactor layout to use the new ReprOptions
1 parent 541aa8a commit c3b64cf

File tree

1 file changed

+39
-63
lines changed

1 file changed

+39
-63
lines changed

src/librustc/ty/layout.rs

+39-63
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub use self::Primitive::*;
1515
use infer::InferCtxt;
1616
use session::Session;
1717
use traits;
18-
use ty::{self, Ty, TyCtxt, TypeFoldable};
18+
use ty::{self, Ty, TyCtxt, TypeFoldable, ReprOptions};
1919

2020
use syntax::ast::{FloatTy, IntTy, UintTy};
2121
use syntax::attr;
@@ -437,7 +437,7 @@ impl Integer {
437437
/// signed discriminant range and #[repr] attribute.
438438
/// N.B.: u64 values above i64::MAX will be treated as signed, but
439439
/// that shouldn't affect anything, other than maybe debuginfo.
440-
fn repr_discr(tcx: TyCtxt, ty: Ty, hints: &[attr::ReprAttr], min: i64, max: i64)
440+
fn repr_discr(tcx: TyCtxt, ty: Ty, repr: &ReprOptions, min: i64, max: i64)
441441
-> (Integer, bool) {
442442
// Theoretically, negative values could be larger in unsigned representation
443443
// than the unsigned representation of the signed minimum. However, if there
@@ -449,34 +449,24 @@ impl Integer {
449449
let mut min_from_extern = None;
450450
let min_default = I8;
451451

452-
for &r in hints.iter() {
453-
match r {
454-
attr::ReprInt(ity) => {
455-
let discr = Integer::from_attr(&tcx.data_layout, ity);
456-
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
457-
if discr < fit {
458-
bug!("Integer::repr_discr: `#[repr]` hint too small for \
459-
discriminant range of enum `{}", ty)
460-
}
461-
return (discr, ity.is_signed());
462-
}
463-
attr::ReprExtern => {
464-
match &tcx.sess.target.target.arch[..] {
465-
// WARNING: the ARM EABI has two variants; the one corresponding
466-
// to `at_least == I32` appears to be used on Linux and NetBSD,
467-
// but some systems may use the variant corresponding to no
468-
// lower bound. However, we don't run on those yet...?
469-
"arm" => min_from_extern = Some(I32),
470-
_ => min_from_extern = Some(I32),
471-
}
472-
}
473-
attr::ReprAny => {},
474-
attr::ReprPacked => {
475-
bug!("Integer::repr_discr: found #[repr(packed)] on enum `{}", ty);
476-
}
477-
attr::ReprSimd => {
478-
bug!("Integer::repr_discr: found #[repr(simd)] on enum `{}", ty);
479-
}
452+
if let Some(ity) = repr.int {
453+
let discr = Integer::from_attr(&tcx.data_layout, ity);
454+
let fit = if ity.is_signed() { signed_fit } else { unsigned_fit };
455+
if discr < fit {
456+
bug!("Integer::repr_discr: `#[repr]` hint too small for \
457+
discriminant range of enum `{}", ty)
458+
}
459+
return (discr, ity.is_signed());
460+
}
461+
462+
if repr.c {
463+
match &tcx.sess.target.target.arch[..] {
464+
// WARNING: the ARM EABI has two variants; the one corresponding
465+
// to `at_least == I32` appears to be used on Linux and NetBSD,
466+
// but some systems may use the variant corresponding to no
467+
// lower bound. However, we don't run on those yet...?
468+
"arm" => min_from_extern = Some(I32),
469+
_ => min_from_extern = Some(I32),
480470
}
481471
}
482472

@@ -568,9 +558,9 @@ enum StructKind {
568558
impl<'a, 'gcx, 'tcx> Struct {
569559
// FIXME(camlorn): reprs need a better representation to deal with multiple reprs on one type.
570560
fn new(dl: &TargetDataLayout, fields: &Vec<&'a Layout>,
571-
reprs: &[attr::ReprAttr], kind: StructKind,
561+
repr: &ReprOptions, kind: StructKind,
572562
scapegoat: Ty<'gcx>) -> Result<Struct, LayoutError<'gcx>> {
573-
let packed = reprs.contains(&attr::ReprPacked);
563+
let packed = repr.packed;
574564
let mut ret = Struct {
575565
align: if packed { dl.i8_align } else { dl.aggregate_align },
576566
packed: packed,
@@ -580,27 +570,16 @@ impl<'a, 'gcx, 'tcx> Struct {
580570
min_size: Size::from_bytes(0),
581571
};
582572

583-
// Anything with ReprExtern or ReprPacked doesn't optimize.
573+
// Anything with repr(C) or repr(packed) doesn't optimize.
584574
// Neither do 1-member and 2-member structs.
585575
// In addition, code in trans assume that 2-element structs can become pairs.
586576
// It's easier to just short-circuit here.
587-
let mut can_optimize = fields.len() > 2 || StructKind::EnumVariant == kind;
588-
if can_optimize {
589-
// This exhaustive match makes new reprs force the adder to modify this function.
590-
// Otherwise, things can silently break.
591-
// Note the inversion, return true to stop optimizing.
592-
can_optimize = !reprs.iter().any(|r| {
593-
match *r {
594-
attr::ReprAny | attr::ReprInt(_) => false,
595-
attr::ReprExtern | attr::ReprPacked => true,
596-
attr::ReprSimd => bug!("Simd vectors should be represented as layout::Vector")
597-
}
598-
});
599-
}
577+
let mut can_optimize = (fields.len() > 2 || StructKind::EnumVariant == kind)
578+
&& ! (repr.c || repr.packed);
600579

601580
// Disable field reordering until we can decide what to do.
602581
// The odd pattern here avoids a warning about the value never being read.
603-
if can_optimize { can_optimize = false }
582+
if can_optimize { can_optimize = false; }
604583

605584
let (optimize, sort_ascending) = match kind {
606585
StructKind::AlwaysSizedUnivariant => (can_optimize, false),
@@ -1092,7 +1071,7 @@ impl<'a, 'gcx, 'tcx> Layout {
10921071

10931072
// The never type.
10941073
ty::TyNever => Univariant {
1095-
variant: Struct::new(dl, &vec![], &[],
1074+
variant: Struct::new(dl, &vec![], &ReprOptions::default(),
10961075
StructKind::AlwaysSizedUnivariant, ty)?,
10971076
non_zero: false
10981077
},
@@ -1135,12 +1114,12 @@ impl<'a, 'gcx, 'tcx> Layout {
11351114
ty::TyFnDef(..) => {
11361115
Univariant {
11371116
variant: Struct::new(dl, &vec![],
1138-
&[], StructKind::AlwaysSizedUnivariant, ty)?,
1117+
&ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?,
11391118
non_zero: false
11401119
}
11411120
}
11421121
ty::TyDynamic(..) => {
1143-
let mut unit = Struct::new(dl, &vec![], &[],
1122+
let mut unit = Struct::new(dl, &vec![], &ReprOptions::default(),
11441123
StructKind::AlwaysSizedUnivariant, ty)?;
11451124
unit.sized = false;
11461125
Univariant { variant: unit, non_zero: false }
@@ -1152,7 +1131,7 @@ impl<'a, 'gcx, 'tcx> Layout {
11521131
let st = Struct::new(dl,
11531132
&tys.map(|ty| ty.layout(infcx))
11541133
.collect::<Result<Vec<_>, _>>()?,
1155-
&[],
1134+
&ReprOptions::default(),
11561135
StructKind::AlwaysSizedUnivariant, ty)?;
11571136
Univariant { variant: st, non_zero: false }
11581137
}
@@ -1163,7 +1142,7 @@ impl<'a, 'gcx, 'tcx> Layout {
11631142
let st = Struct::new(dl,
11641143
&tys.iter().map(|ty| ty.layout(infcx))
11651144
.collect::<Result<Vec<_>, _>>()?,
1166-
&[], StructKind::AlwaysSizedUnivariant, ty)?;
1145+
&ReprOptions::default(), StructKind::AlwaysSizedUnivariant, ty)?;
11671146
Univariant { variant: st, non_zero: false }
11681147
}
11691148

@@ -1187,16 +1166,13 @@ impl<'a, 'gcx, 'tcx> Layout {
11871166

11881167
// ADTs.
11891168
ty::TyAdt(def, substs) => {
1190-
let hints = &tcx.lookup_repr_hints(def.did)[..];
1191-
11921169
if def.variants.is_empty() {
11931170
// Uninhabitable; represent as unit
11941171
// (Typechecking will reject discriminant-sizing attrs.)
1195-
assert_eq!(hints.len(), 0);
11961172

11971173
return success(Univariant {
11981174
variant: Struct::new(dl, &vec![],
1199-
&hints[..], StructKind::AlwaysSizedUnivariant, ty)?,
1175+
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?,
12001176
non_zero: false
12011177
});
12021178
}
@@ -1219,7 +1195,7 @@ impl<'a, 'gcx, 'tcx> Layout {
12191195

12201196
// FIXME: should handle i128? signed-value based impl is weird and hard to
12211197
// grok.
1222-
let (discr, signed) = Integer::repr_discr(tcx, ty, &hints[..],
1198+
let (discr, signed) = Integer::repr_discr(tcx, ty, &def.repr,
12231199
min,
12241200
max);
12251201
return success(CEnum {
@@ -1232,7 +1208,7 @@ impl<'a, 'gcx, 'tcx> Layout {
12321208
});
12331209
}
12341210

1235-
if !def.is_enum() || def.variants.len() == 1 && hints.is_empty() {
1211+
if !def.is_enum() || def.variants.len() == 1 {
12361212
// Struct, or union, or univariant enum equivalent to a struct.
12371213
// (Typechecking will reject discriminant-sizing attrs.)
12381214

@@ -1259,7 +1235,7 @@ impl<'a, 'gcx, 'tcx> Layout {
12591235
un.extend(dl, fields.iter().map(|&f| Ok(f)), ty)?;
12601236
UntaggedUnion { variants: un }
12611237
} else {
1262-
let st = Struct::new(dl, &fields, &hints[..],
1238+
let st = Struct::new(dl, &fields, &def.repr,
12631239
kind, ty)?;
12641240
let non_zero = Some(def.did) == tcx.lang_items.non_zero();
12651241
Univariant { variant: st, non_zero: non_zero }
@@ -1282,7 +1258,7 @@ impl<'a, 'gcx, 'tcx> Layout {
12821258
v.fields.iter().map(|field| field.ty(tcx, substs)).collect::<Vec<_>>()
12831259
}).collect::<Vec<_>>();
12841260

1285-
if variants.len() == 2 && hints.is_empty() {
1261+
if variants.len() == 2 && !def.repr.c {
12861262
// Nullable pointer optimization
12871263
for discr in 0..2 {
12881264
let other_fields = variants[1 - discr].iter().map(|ty| {
@@ -1315,7 +1291,7 @@ impl<'a, 'gcx, 'tcx> Layout {
13151291
let st = Struct::new(dl,
13161292
&variants[discr].iter().map(|ty| ty.layout(infcx))
13171293
.collect::<Result<Vec<_>, _>>()?,
1318-
&hints[..], StructKind::AlwaysSizedUnivariant, ty)?;
1294+
&def.repr, StructKind::AlwaysSizedUnivariant, ty)?;
13191295

13201296
// We have to fix the last element of path here.
13211297
let mut i = *path.last().unwrap();
@@ -1338,7 +1314,7 @@ impl<'a, 'gcx, 'tcx> Layout {
13381314
// The general case.
13391315
let discr_max = (variants.len() - 1) as i64;
13401316
assert!(discr_max >= 0);
1341-
let (min_ity, _) = Integer::repr_discr(tcx, ty, &hints[..], 0, discr_max);
1317+
let (min_ity, _) = Integer::repr_discr(tcx, ty, &def.repr, 0, discr_max);
13421318

13431319
let mut align = dl.aggregate_align;
13441320
let mut size = Size::from_bytes(0);
@@ -1356,7 +1332,7 @@ impl<'a, 'gcx, 'tcx> Layout {
13561332
fields.insert(0, &discr);
13571333
let st = Struct::new(dl,
13581334
&fields,
1359-
&hints[..], StructKind::EnumVariant, ty)?;
1335+
&def.repr, StructKind::EnumVariant, ty)?;
13601336
// Find the first field we can't move later
13611337
// to make room for a larger discriminant.
13621338
// It is important to skip the first field.

0 commit comments

Comments
 (0)