rustc: don't track whether layouts are "packed".

This commit is contained in:
Eduard-Mihai Burtescu 2017-12-01 18:29:35 +02:00
parent 53a6d14e5b
commit 7c6f242ca8
10 changed files with 116 additions and 184 deletions

View File

@ -895,7 +895,7 @@ pub struct InterpretInterner<'tcx> {
/// Allows checking whether a constant already has an allocation
///
/// The pointers are to the beginning of an `alloc_by_id` allocation
alloc_cache: FxHashMap<interpret::GlobalId<'tcx>, interpret::PtrAndAlign>,
alloc_cache: FxHashMap<interpret::GlobalId<'tcx>, interpret::Pointer>,
/// A cache for basic byte allocations keyed by their contents. This is used to deduplicate
/// allocations for string and bytestring literals.
@ -931,14 +931,14 @@ impl<'tcx> InterpretInterner<'tcx> {
pub fn get_cached(
&self,
global_id: interpret::GlobalId<'tcx>,
) -> Option<interpret::PtrAndAlign> {
) -> Option<interpret::Pointer> {
self.alloc_cache.get(&global_id).cloned()
}
pub fn cache(
&mut self,
global_id: interpret::GlobalId<'tcx>,
ptr: interpret::PtrAndAlign,
ptr: interpret::Pointer,
) {
if let Some(old) = self.alloc_cache.insert(global_id, ptr) {
bug!("tried to cache {:?}, but was already existing as {:#?}", global_id, old);

View File

@ -778,7 +778,6 @@ pub enum Abi {
Aggregate {
/// If true, the size is exact, otherwise it's only a lower bound.
sized: bool,
packed: bool
}
}
@ -790,18 +789,7 @@ impl Abi {
Abi::Scalar(_) |
Abi::ScalarPair(..) |
Abi::Vector { .. } => false,
Abi::Aggregate { sized, .. } => !sized
}
}
/// Returns true if the fields of the layout are packed.
pub fn is_packed(&self) -> bool {
match *self {
Abi::Uninhabited |
Abi::Scalar(_) |
Abi::ScalarPair(..) |
Abi::Vector { .. } => false,
Abi::Aggregate { packed, .. } => packed
Abi::Aggregate { sized } => !sized
}
}
}
@ -1077,10 +1065,7 @@ impl<'a, 'tcx> LayoutDetails {
}
let size = min_size.abi_align(align);
let mut abi = Abi::Aggregate {
sized,
packed
};
let mut abi = Abi::Aggregate { sized };
// Unpack newtype ABIs and find scalar pairs.
if sized && size.bytes() > 0 {
@ -1254,10 +1239,7 @@ impl<'a, 'tcx> LayoutDetails {
stride: element.size,
count
},
abi: Abi::Aggregate {
sized: true,
packed: false
},
abi: Abi::Aggregate { sized: true },
align: element.align,
size
})
@ -1270,10 +1252,7 @@ impl<'a, 'tcx> LayoutDetails {
stride: element.size,
count: 0
},
abi: Abi::Aggregate {
sized: false,
packed: false
},
abi: Abi::Aggregate { sized: false },
align: element.align,
size: Size::from_bytes(0)
})
@ -1285,10 +1264,7 @@ impl<'a, 'tcx> LayoutDetails {
stride: Size::from_bytes(1),
count: 0
},
abi: Abi::Aggregate {
sized: false,
packed: false
},
abi: Abi::Aggregate { sized: false },
align: dl.i8_align,
size: Size::from_bytes(0)
})
@ -1302,7 +1278,7 @@ impl<'a, 'tcx> LayoutDetails {
let mut unit = univariant_uninterned(&[], &ReprOptions::default(),
StructKind::AlwaysSized)?;
match unit.abi {
Abi::Aggregate { ref mut sized, .. } => *sized = false,
Abi::Aggregate { ref mut sized } => *sized = false,
_ => bug!()
}
tcx.intern_layout(unit)
@ -1418,10 +1394,7 @@ impl<'a, 'tcx> LayoutDetails {
return Ok(tcx.intern_layout(LayoutDetails {
variants: Variants::Single { index: 0 },
fields: FieldPlacement::Union(variants[0].len()),
abi: Abi::Aggregate {
sized: true,
packed
},
abi: Abi::Aggregate { sized: true },
align,
size: size.abi_align(align)
}));
@ -1525,15 +1498,10 @@ impl<'a, 'tcx> LayoutDetails {
let abi = if offset.bytes() == 0 && niche.value.size(dl) == size {
Abi::Scalar(niche.clone())
} else {
let mut packed = st[i].abi.is_packed();
if offset.abi_align(niche_align) != offset {
packed = true;
niche_align = dl.i8_align;
}
Abi::Aggregate {
sized: true,
packed
}
Abi::Aggregate { sized: true }
};
align = align.max(niche_align);
@ -1681,10 +1649,7 @@ impl<'a, 'tcx> LayoutDetails {
let abi = if discr.value.size(dl) == size {
Abi::Scalar(discr.clone())
} else {
Abi::Aggregate {
sized: true,
packed: false
}
Abi::Aggregate { sized: true }
};
tcx.intern_layout(LayoutDetails {
variants: Variants::Tagged {
@ -2277,11 +2242,6 @@ impl<'a, 'tcx> TyLayout<'tcx> {
self.abi.is_unsized()
}
/// Returns true if the fields of the layout are packed.
pub fn is_packed(&self) -> bool {
self.abi.is_packed()
}
/// Returns true if the type is a ZST and not unsized.
pub fn is_zst(&self) -> bool {
match self.abi {
@ -2289,7 +2249,7 @@ impl<'a, 'tcx> TyLayout<'tcx> {
Abi::Scalar(_) |
Abi::ScalarPair(..) |
Abi::Vector { .. } => false,
Abi::Aggregate { sized, .. } => sized && self.size.bytes() == 0
Abi::Aggregate { sized } => sized && self.size.bytes() == 0
}
}
@ -2452,8 +2412,7 @@ impl<'gcx> HashStable<StableHashingContext<'gcx>> for Abi {
element.hash_stable(hcx, hasher);
count.hash_stable(hcx, hasher);
}
Aggregate { packed, sized } => {
packed.hash_stable(hcx, hasher);
Aggregate { sized } => {
sized.hash_stable(hcx, hasher);
}
}

View File

@ -12,7 +12,7 @@ use rustc_data_structures::indexed_vec::Idx;
use syntax::ast::Mutability;
use syntax::codemap::Span;
use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, PrimVal, PtrAndAlign};
use rustc::mir::interpret::{EvalResult, EvalError, EvalErrorKind, GlobalId, Value, Pointer, PrimVal, PtrAndAlign};
use super::{Place, PlaceExtra, EvalContext, StackPopCleanup, ValTy, HasMemory};
use rustc_const_math::ConstInt;
@ -45,7 +45,7 @@ pub fn eval_body<'a, 'tcx>(
tcx: TyCtxt<'a, 'tcx, 'tcx>,
instance: Instance<'tcx>,
param_env: ty::ParamEnv<'tcx>,
) -> EvalResult<'tcx, (PtrAndAlign, Ty<'tcx>)> {
) -> EvalResult<'tcx, (Pointer, Ty<'tcx>)> {
debug!("eval_body: {:?}, {:?}", instance, param_env);
let limits = super::ResourceLimits::default();
let mut ecx = EvalContext::new(tcx, param_env, limits, CompileTimeEvaluator, ());
@ -69,13 +69,7 @@ pub fn eval_body<'a, 'tcx>(
layout.align.abi(),
None,
)?;
tcx.interpret_interner.borrow_mut().cache(
cid,
PtrAndAlign {
ptr: ptr.into(),
aligned: !layout.is_packed(),
},
);
tcx.interpret_interner.borrow_mut().cache(cid, ptr.into());
let cleanup = StackPopCleanup::MarkStatic(Mutability::Immutable);
let name = ty::tls::with(|tcx| tcx.item_path_str(instance.def_id()));
trace!("const_eval: pushing stack frame for global: {}", name);
@ -101,7 +95,7 @@ pub fn eval_body_as_integer<'a, 'tcx>(
let ptr_ty = eval_body(tcx, instance, param_env);
let (ptr, ty) = ptr_ty?;
let ecx = mk_eval_cx(tcx, instance, param_env)?;
let prim = match ecx.read_maybe_aligned(ptr.aligned, |ectx| ectx.try_read_value(ptr.ptr, ty))? {
let prim = match ecx.try_read_value(ptr, ty)? {
Some(Value::ByVal(prim)) => prim.to_bytes()?,
_ => return err!(TypeNotPrimitive(ty)),
};
@ -363,7 +357,10 @@ pub fn const_eval_provider<'a, 'tcx>(
(_, Err(err)) => Err(err),
(Ok((miri_val, miri_ty)), Ok(ctfe)) => {
let mut ecx = mk_eval_cx(tcx, instance, key.param_env).unwrap();
check_ctfe_against_miri(&mut ecx, miri_val, miri_ty, ctfe.val);
check_ctfe_against_miri(&mut ecx, PtrAndAlign {
ptr: miri_val,
aligned: true
}, miri_ty, ctfe.val);
Ok(ctfe)
}
}

View File

@ -261,11 +261,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
Unevaluated(def_id, substs) => {
let instance = self.resolve(def_id, substs)?;
let cid = GlobalId {
return Ok(self.read_global_as_value(GlobalId {
instance,
promoted: None,
};
return Ok(Value::ByRef(self.tcx.interpret_interner.borrow().get_cached(cid).expect("static/const not cached")));
}));
}
Aggregate(..) |
@ -834,11 +833,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
Literal::Value { ref value } => self.const_to_value(&value.val)?,
Literal::Promoted { index } => {
let cid = GlobalId {
self.read_global_as_value(GlobalId {
instance: self.frame().instance,
promoted: Some(index),
};
Value::ByRef(self.tcx.interpret_interner.borrow().get_cached(cid).expect("promoted not cached"))
})
}
};
@ -951,7 +949,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
}
pub fn read_global_as_value(&self, gid: GlobalId) -> Value {
Value::ByRef(self.tcx.interpret_interner.borrow().get_cached(gid).expect("global not cached"))
Value::ByRef(PtrAndAlign {
ptr: self.tcx.interpret_interner.borrow().get_cached(gid).expect("global not cached"),
aligned: true
})
}
fn copy(&mut self, src: Pointer, dest: Pointer, ty: Ty<'tcx>) -> EvalResult<'tcx> {
@ -1149,51 +1150,29 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
}
Value::ByVal(primval) => {
let layout = self.layout_of(dest_ty)?;
if layout.is_zst() {
assert!(primval.is_undef());
Ok(())
} else {
// TODO: Do we need signedness?
self.memory.write_maybe_aligned_mut(!layout.is_packed(), |mem| {
mem.write_primval(dest.to_ptr()?, primval, layout.size.bytes(), false)
})
match layout.abi {
layout::Abi::Scalar(_) => {}
_ if primval.is_undef() => {}
_ => bug!("write_value_to_ptr: invalid ByVal layout: {:#?}", layout)
}
// TODO: Do we need signedness?
self.memory.write_primval(dest.to_ptr()?, primval, layout.size.bytes(), false)
}
Value::ByValPair(a, b) => {
Value::ByValPair(a_val, b_val) => {
let ptr = dest.to_ptr()?;
let mut layout = self.layout_of(dest_ty)?;
trace!("write_value_to_ptr valpair: {:#?}", layout);
let mut packed = layout.is_packed();
'outer: loop {
for i in 0..layout.fields.count() {
let field = layout.field(&self, i)?;
if layout.fields.offset(i).bytes() == 0 && layout.size == field.size {
layout = field;
packed |= layout.is_packed();
continue 'outer;
}
}
break;
}
trace!("write_value_to_ptr valpair: {:#?}", layout);
assert_eq!(layout.fields.count(), 2);
let field_0 = layout.field(&self, 0)?;
let field_1 = layout.field(&self, 1)?;
trace!("write_value_to_ptr field 0: {:#?}", field_0);
trace!("write_value_to_ptr field 1: {:#?}", field_1);
assert_eq!(
field_0.is_packed(),
field_1.is_packed(),
"the two fields must agree on being packed"
);
packed |= field_0.is_packed();
let field_0_ptr = ptr.offset(layout.fields.offset(0).bytes(), &self)?.into();
let field_1_ptr = ptr.offset(layout.fields.offset(1).bytes(), &self)?.into();
let (a, b) = match layout.abi {
layout::Abi::ScalarPair(ref a, ref b) => (&a.value, &b.value),
_ => bug!("write_value_to_ptr: invalid ByValPair layout: {:#?}", layout)
};
let (a_size, b_size) = (a.size(&self), b.size(&self));
let a_ptr = ptr;
let b_offset = a_size.abi_align(b.align(&self));
let b_ptr = ptr.offset(b_offset.bytes(), &self)?.into();
// TODO: What about signedess?
self.memory.write_maybe_aligned_mut(!packed, |mem| {
mem.write_primval(field_0_ptr, a, field_0.size.bytes(), false)?;
mem.write_primval(field_1_ptr, b, field_1.size.bytes(), false)
})?;
self.memory.write_primval(a_ptr, a_val, a_size.bytes(), false)?;
self.memory.write_primval(b_ptr, b_val, b_size.bytes(), false)?;
Ok(())
}
}

View File

@ -1,6 +1,6 @@
use rustc::mir;
use rustc::ty::{self, Ty};
use rustc::ty::layout::{LayoutOf, TyLayout};
use rustc::ty::layout::{self, LayoutOf, TyLayout};
use rustc_data_structures::indexed_vec::Idx;
use rustc::mir::interpret::{GlobalId, PtrAndAlign};
@ -106,9 +106,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
instance,
promoted: None,
};
Ok(Some(Value::ByRef(
self.tcx.interpret_interner.borrow().get_cached(cid).expect("global not cached"),
)))
Ok(Some(self.read_global_as_value(cid)))
}
Projection(ref proj) => self.try_read_place_projection(proj),
}
@ -193,7 +191,10 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
promoted: None,
};
Place::Ptr {
ptr: self.tcx.interpret_interner.borrow().get_cached(gid).expect("uncached global"),
ptr: PtrAndAlign {
ptr: self.tcx.interpret_interner.borrow().get_cached(gid).expect("uncached global"),
aligned: true
},
extra: PlaceExtra::None,
}
}
@ -232,15 +233,15 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
let (base_ptr, base_extra) = match base {
Place::Ptr { ptr, extra } => (ptr, extra),
Place::Local { frame, local } => {
match self.stack[frame].get_local(local)? {
match (&self.stack[frame].get_local(local)?, &base_layout.abi) {
// in case the field covers the entire type, just return the value
Value::ByVal(_) if offset.bytes() == 0 &&
field.size == base_layout.size => {
(&Value::ByVal(_), &layout::Abi::Scalar(_)) |
(&Value::ByValPair(..), &layout::Abi::ScalarPair(..))
if offset.bytes() == 0 && field.size == base_layout.size =>
{
return Ok((base, field));
}
Value::ByRef { .. } |
Value::ByValPair(..) |
Value::ByVal(_) => self.force_allocation(base)?.to_ptr_extra_aligned(),
_ => self.force_allocation(base)?.to_ptr_extra_aligned(),
}
}
};
@ -257,9 +258,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
};
let mut ptr = base_ptr.offset(offset, &self)?;
// if we were unaligned, stay unaligned
// no matter what we were, if we are packed, we must not be aligned anymore
ptr.aligned &= !base_layout.is_packed();
ptr.aligned &= base_layout.align.abi() >= field.align.abi();
let extra = if !field.is_unsized() {
PlaceExtra::None

View File

@ -8,7 +8,7 @@ use rustc::mir;
use rustc::ty::{self, Instance};
use rustc::ty::layout::LayoutOf;
use rustc::middle::const_val::ConstVal;
use rustc::mir::interpret::{PtrAndAlign, GlobalId};
use rustc::mir::interpret::GlobalId;
use rustc::mir::interpret::{EvalResult, EvalErrorKind};
use super::{EvalContext, StackPopCleanup, Place, Machine};
@ -182,13 +182,7 @@ impl<'a, 'tcx, M: Machine<'tcx>> EvalContext<'a, 'tcx, M> {
layout.align.abi(),
None,
)?;
self.tcx.interpret_interner.borrow_mut().cache(
cid,
PtrAndAlign {
ptr: ptr.into(),
aligned: !layout.is_packed(),
},
);
self.tcx.interpret_interner.borrow_mut().cache(cid, ptr.into());
let internally_mutable = !layout.ty.is_freeze(self.tcx, self.param_env, span);
let mutability = if mutability == Mutability::Mutable || internally_mutable {
Mutability::Mutable
@ -273,13 +267,7 @@ impl<'a, 'b, 'tcx, M: Machine<'tcx>> Visitor<'tcx> for ConstantExtractor<'a, 'b,
layout.align.abi(),
None,
)?;
this.ecx.tcx.interpret_interner.borrow_mut().cache(
cid,
PtrAndAlign {
ptr: ptr.into(),
aligned: !layout.is_packed(),
},
);
this.ecx.tcx.interpret_interner.borrow_mut().cache(cid, ptr.into());
trace!("pushing stack frame for {:?}", index);
this.ecx.push_stack_frame(
this.instance,

View File

@ -69,7 +69,7 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
// Recurse to get the size of the dynamically sized field (must be
// the last field).
let field_ty = layout.field(ccx, i).ty;
let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info);
let (unsized_size, mut unsized_align) = size_and_align_of_dst(bcx, field_ty, info);
// FIXME (#26403, #27023): We should be adding padding
// to `sized_size` (to accommodate the `unsized_align`
@ -81,6 +81,13 @@ pub fn size_and_align_of_dst<'a, 'tcx>(bcx: &Builder<'a, 'tcx>, t: Ty<'tcx>, inf
// Return the sum of sizes and max of aligns.
let size = bcx.add(sized_size, unsized_size);
// Packed types ignore the alignment of their fields.
if let ty::TyAdt(def, _) = t.sty {
if def.repr.packed() {
unsized_align = sized_align;
}
}
// Choose max of two known alignments (combined value must
// be aligned according to more restrictive of the two).
let align = match (const_to_opt_u128(sized_align, false),

View File

@ -1134,12 +1134,14 @@ fn trans_const_adt<'a, 'tcx>(
if let layout::FieldPlacement::Union(_) = l.fields {
assert_eq!(variant_index, 0);
assert_eq!(vals.len(), 1);
let (field_size, field_align) = ccx.size_and_align_of(vals[0].ty);
let contents = [
vals[0].llval,
padding(ccx, l.size - ccx.size_of(vals[0].ty))
padding(ccx, l.size - field_size)
];
Const::new(C_struct(ccx, &contents, l.is_packed()), t)
let packed = l.align.abi() < field_align.abi();
Const::new(C_struct(ccx, &contents, packed), t)
} else {
if let layout::Abi::Vector { .. } = l.abi {
if let layout::FieldPlacement::Array { .. } = l.fields {
@ -1232,28 +1234,33 @@ fn build_const_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
}
// offset of current value
let mut packed = false;
let mut offset = Size::from_bytes(0);
let mut cfields = Vec::new();
cfields.reserve(discr.is_some() as usize + 1 + layout.fields.count() * 2);
if let Some(discr) = discr {
let (field_size, field_align) = ccx.size_and_align_of(discr.ty);
packed |= layout.align.abi() < field_align.abi();
cfields.push(discr.llval);
offset = ccx.size_of(discr.ty);
offset = field_size;
}
let parts = layout.fields.index_by_increasing_offset().map(|i| {
(vals[i], layout.fields.offset(i))
});
for (val, target_offset) in parts {
let (field_size, field_align) = ccx.size_and_align_of(val.ty);
packed |= layout.align.abi() < field_align.abi();
cfields.push(padding(ccx, target_offset - offset));
cfields.push(val.llval);
offset = target_offset + ccx.size_of(val.ty);
offset = target_offset + field_size;
}
// Pad to the size of the whole type, not e.g. the variant.
cfields.push(padding(ccx, ccx.size_of(layout.ty) - offset));
Const::new(C_struct(ccx, &cfields, layout.is_packed()), layout.ty)
Const::new(C_struct(ccx, &cfields, packed), layout.ty)
}
fn padding(ccx: &CrateContext, size: Size) -> ValueRef {

View File

@ -55,11 +55,7 @@ impl ops::BitOr for Alignment {
impl<'a> From<TyLayout<'a>> for Alignment {
fn from(layout: TyLayout) -> Self {
if layout.is_packed() {
Alignment::Packed(layout.align)
} else {
Alignment::AbiAligned
}
Alignment::Packed(layout.align)
}
}
@ -232,25 +228,27 @@ impl<'a, 'tcx> PlaceRef<'tcx> {
}
};
// Simple case - we can just GEP the field
// * Packed struct - There is no alignment padding
// * Field is sized - pointer is properly aligned already
if self.layout.is_packed() || !field.is_unsized() {
return simple();
}
// If the type of the last field is [T], str or a foreign type, then we don't need to do
// any adjusments
// Simple cases, which don't need DST adjustment:
// * no metadata available - just log the case
// * known alignment - sized types, [T], str or a foreign type
// * packed struct - there is no alignment padding
match field.ty.sty {
_ if !self.has_extra() => {
debug!("Unsized field `{}`, of `{:?}` has no metadata for adjustment",
ix, Value(self.llval));
return simple();
}
_ if !field.is_unsized() => return simple(),
ty::TySlice(..) | ty::TyStr | ty::TyForeign(..) => return simple(),
_ => ()
}
// There's no metadata available, log the case and just do the GEP.
if !self.has_extra() {
debug!("Unsized field `{}`, of `{:?}` has no metadata for adjustment",
ix, Value(self.llval));
return simple();
ty::TyAdt(def, _) => {
if def.repr.packed() {
// FIXME(eddyb) generalize the adjustment when we
// start supporting packing to larger alignments.
assert_eq!(self.layout.align.abi(), 1);
return simple();
}
}
_ => {}
}
// We need to get the pointer manually now.

View File

@ -79,13 +79,14 @@ fn uncached_llvm_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
match layout.fields {
layout::FieldPlacement::Union(_) => {
let fill = Type::padding_filler(ccx, layout.size, layout.align);
let packed = false;
match name {
None => {
Type::struct_(ccx, &[fill], layout.is_packed())
Type::struct_(ccx, &[fill], packed)
}
Some(ref name) => {
let mut llty = Type::named_struct(ccx, name);
llty.set_struct_body(&[fill], layout.is_packed());
llty.set_struct_body(&[fill], packed);
llty
}
}
@ -96,7 +97,8 @@ fn uncached_llvm_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
layout::FieldPlacement::Arbitrary { .. } => {
match name {
None => {
Type::struct_(ccx, &struct_llfields(ccx, layout), layout.is_packed())
let (llfields, packed) = struct_llfields(ccx, layout);
Type::struct_(ccx, &llfields, packed)
}
Some(ref name) => {
let llty = Type::named_struct(ccx, name);
@ -109,15 +111,19 @@ fn uncached_llvm_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
}
fn struct_llfields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
layout: TyLayout<'tcx>) -> Vec<Type> {
layout: TyLayout<'tcx>)
-> (Vec<Type>, bool) {
debug!("struct_llfields: {:#?}", layout);
let field_count = layout.fields.count();
let mut packed = false;
let mut offset = Size::from_bytes(0);
let mut prev_align = layout.align;
let mut result: Vec<Type> = Vec::with_capacity(1 + field_count * 2);
for i in layout.fields.index_by_increasing_offset() {
let field = layout.field(ccx, i);
packed |= layout.align.abi() < field.align.abi();
let target_offset = layout.fields.offset(i as usize);
debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?}",
i, field, offset, target_offset);
@ -129,15 +135,6 @@ fn struct_llfields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
debug!(" padding before: {:?}", padding);
result.push(field.llvm_type(ccx));
if layout.is_packed() {
assert_eq!(padding.bytes(), 0);
} else {
assert!(field.align.abi() <= layout.align.abi(),
"non-packed type has field with larger align ({}): {:#?}",
field.align.abi(), layout);
}
offset = target_offset + field.size;
prev_align = field.align;
}
@ -158,7 +155,7 @@ fn struct_llfields<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
offset, layout.size);
}
result
(result, packed)
}
impl<'a, 'tcx> CrateContext<'a, 'tcx> {
@ -301,7 +298,8 @@ impl<'tcx> LayoutLlvmExt<'tcx> for TyLayout<'tcx> {
ccx.lltypes().borrow_mut().insert((self.ty, variant_index), llty);
if let Some((mut llty, layout)) = defer {
llty.set_struct_body(&struct_llfields(ccx, layout), layout.is_packed())
let (llfields, packed) = struct_llfields(ccx, layout);
llty.set_struct_body(&llfields, packed)
}
llty