let cx = bx.cx;
let field = self.layout.field(cx, ix);
let offset = self.layout.fields.offset(ix);
- let align = self.align.min(self.layout.align).min(field.align);
+ let effective_field_align = self.align
+ .min(self.layout.align)
+ .min(field.align)
+ .restrict_for_offset(offset);
let simple = || {
// Unions and newtypes only use an offset of 0.
None
},
layout: field,
- align,
+ align: effective_field_align,
}
};
llval: bx.pointercast(byte_ptr, ll_fty.ptr_to()),
llextra: self.llextra,
layout: field,
- align,
+ align: effective_field_align,
}
}
let mut packed = false;
let mut offset = Size::ZERO;
- let mut prev_align = layout.align;
+ let mut prev_effective_align = layout.align;
let mut result: Vec<_> = Vec::with_capacity(1 + field_count * 2);
for i in layout.fields.index_by_increasing_offset() {
- let field = layout.field(cx, 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);
+ let field = layout.field(cx, i);
+ let effective_field_align = layout.align
+ .min(field.align)
+ .restrict_for_offset(target_offset);
+ packed |= effective_field_align.abi() < field.align.abi();
+
+ debug!("struct_llfields: {}: {:?} offset: {:?} target_offset: {:?} \
+ effective_field_align: {}",
+ i, field, offset, target_offset, effective_field_align.abi());
assert!(target_offset >= offset);
let padding = target_offset - offset;
- let padding_align = layout.align.min(prev_align).min(field.align);
+ let padding_align = prev_effective_align.min(effective_field_align);
assert_eq!(offset.abi_align(padding_align) + padding, target_offset);
result.push(Type::padding_filler(cx, padding, padding_align));
debug!(" padding before: {:?}", padding);
result.push(field.llvm_type(cx));
offset = target_offset + field.size;
- prev_align = field.align;
+ prev_effective_align = effective_field_align;
}
if !layout.is_unsized() && field_count > 0 {
if offset > layout.size {
layout, layout.size, offset);
}
let padding = layout.size - offset;
- let padding_align = layout.align.min(prev_align);
+ let padding_align = prev_effective_align;
assert_eq!(offset.abi_align(padding_align) + padding, layout.size);
debug!("struct_llfields: pad_bytes: {:?} offset: {:?} stride: {:?}",
padding, offset, layout.size);
pref_pow2: cmp::max(self.pref_pow2, other.pref_pow2),
}
}
+
+ /// Compute the best alignment possible for the given offset
+ /// (the largest power of two that the offset is a multiple of).
+ ///
+ /// NB: for an offset of `0`, this happens to return `2^64`.
+ pub fn max_for_offset(offset: Size) -> Align {
+ let pow2 = offset.bytes().trailing_zeros() as u8;
+ Align {
+ abi_pow2: pow2,
+ pref_pow2: pow2,
+ }
+ }
+
+ /// Lower the alignment, if necessary, such that the given offset
+ /// is aligned to it (the offset is a multiple of the aligment).
+ pub fn restrict_for_offset(self, offset: Size) -> Align {
+ self.min(Align::max_for_offset(offset))
+ }
}
/// Integers, also used for enum discriminants.
--- /dev/null
+// Copyright 2018 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#[repr(u16)]
+enum DeviceKind {
+ Nil = 0,
+}
+
+#[repr(packed)]
+struct DeviceInfo {
+ endianness: u8,
+ device_kind: DeviceKind,
+}
+
+fn main() {
+ let _x = None::<(DeviceInfo, u8)>;
+ let _y = None::<(DeviceInfo, u16)>;
+ let _z = None::<(DeviceInfo, u64)>;
+}