Skip to content

Commit ddb680b

Browse files
author
bors-servo
authored
Auto merge of rust-lang#1130 - fitzgen:issue-1076, r=pepyakin
Unnamed bit-fields and alignment r? @pepyakin or @emilio
2 parents 55cf63c + e17bd8d commit ddb680b

File tree

4 files changed

+56
-16
lines changed

4 files changed

+56
-16
lines changed

src/ir/comp.rs

+17-13
Original file line numberDiff line numberDiff line change
@@ -595,12 +595,8 @@ fn bitfields_to_allocation_units<E, I>(
595595

596596
// Now we're working on a fresh bitfield allocation unit, so reset
597597
// the current unit size and alignment.
598-
#[allow(unused_assignments)]
599-
{
600-
unit_size_in_bits = 0;
601-
offset = 0;
602-
unit_align = 0;
603-
}
598+
offset = 0;
599+
unit_align = 0;
604600
}
605601
} else {
606602
if offset != 0 &&
@@ -612,20 +608,28 @@ fn bitfields_to_allocation_units<E, I>(
612608
}
613609
}
614610

611+
// According to the x86[-64] ABI spec: "Unnamed bit-fields’ types do not
612+
// affect the alignment of a structure or union". This makes sense: such
613+
// bit-fields are only used for padding, and we can't perform an
614+
// un-aligned read of something we can't read because we can't even name
615+
// it.
616+
if bitfield.name().is_some() {
617+
max_align = cmp::max(max_align, bitfield_align);
618+
619+
// NB: The `bitfield_width` here is completely, absolutely
620+
// intentional. Alignment of the allocation unit is based on the
621+
// maximum bitfield width, not (directly) on the bitfields' types'
622+
// alignment.
623+
unit_align = cmp::max(unit_align, bitfield_width);
624+
}
625+
615626
// Always keep all bitfields around. While unnamed bitifields are used
616627
// for padding (and usually not needed hereafter), large unnamed
617628
// bitfields over their types size cause weird allocation size behavior from clang.
618629
// Therefore, all bitfields needed to be kept around in order to check for this
619630
// and make the struct opaque in this case
620631
bitfields_in_unit.push(Bitfield::new(offset, bitfield));
621632

622-
max_align = cmp::max(max_align, bitfield_align);
623-
624-
// NB: The `bitfield_width` here is completely, absolutely intentional.
625-
// Alignment of the allocation unit is based on the maximum bitfield
626-
// width, not (directly) on the bitfields' types' alignment.
627-
unit_align = cmp::max(unit_align, bitfield_width);
628-
629633
unit_size_in_bits = offset + bitfield_width;
630634

631635
// Compute what the physical unit's final size would be given what we

tests/expectations/tests/issue-1034.rs

+4-3
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,11 @@
44
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
55

66

7-
#[repr(C, packed)]
7+
#[repr(C)]
88
#[derive(Debug, Default, Copy, Clone)]
99
pub struct S2 {
10-
pub _bitfield_1: u16,
10+
pub _bitfield_1: u8,
11+
pub __bindgen_padding_0: u8,
1112
}
1213
#[test]
1314
fn bindgen_test_layout_S2() {
@@ -24,7 +25,7 @@ fn bindgen_test_layout_S2() {
2425
}
2526
impl S2 {
2627
#[inline]
27-
pub fn new_bitfield_1() -> u16 {
28+
pub fn new_bitfield_1() -> u8 {
2829
0
2930
}
3031
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
5+
6+
7+
#[repr(C)]
8+
#[derive(Debug, Default, Copy, Clone)]
9+
pub struct S1 {
10+
pub _bitfield_1: [u8; 2usize],
11+
pub __bindgen_padding_0: u8,
12+
}
13+
#[test]
14+
fn bindgen_test_layout_S1() {
15+
assert_eq!(
16+
::std::mem::size_of::<S1>(),
17+
3usize,
18+
concat!("Size of: ", stringify!(S1))
19+
);
20+
assert_eq!(
21+
::std::mem::align_of::<S1>(),
22+
1usize,
23+
concat!("Alignment of ", stringify!(S1))
24+
);
25+
}
26+
impl S1 {
27+
#[inline]
28+
pub fn new_bitfield_1() -> u16 {
29+
0
30+
}
31+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
struct S1 {
2+
signed : 15;
3+
unsigned : 6
4+
};

0 commit comments

Comments
 (0)