Skip to content

Commit d9db740

Browse files
committed
ir: Fix wrong condition in bitfield alignment.
We should also align the allocation unit even if it's the first bitfield in the allocation unit. Fixes #1314
1 parent caa020b commit d9db740

File tree

3 files changed

+195
-3
lines changed

3 files changed

+195
-3
lines changed

src/ir/comp.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -604,6 +604,7 @@ where
604604
let bitfield_size = bitfield_layout.size;
605605
let bitfield_align = bitfield_layout.align;
606606

607+
debug!("{:?}, {:?}", bitfield, bitfield_layout);
607608
let mut offset = unit_size_in_bits;
608609
if is_ms_struct {
609610
if unit_size_in_bits != 0 &&
@@ -627,10 +628,9 @@ where
627628
unit_align = 0;
628629
}
629630
} else {
630-
if offset != 0 &&
631-
(bitfield_width == 0 ||
631+
if bitfield_width == 0 ||
632632
(offset & (bitfield_align * 8 - 1)) + bitfield_width >
633-
bitfield_size * 8)
633+
bitfield_size * 8
634634
{
635635
offset = align_to(offset, bitfield_align * 8);
636636
}
Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
4+
5+
#[repr(C)]
6+
#[derive(Copy, Clone, Debug, Default, Eq, Hash, Ord, PartialEq, PartialOrd)]
7+
pub struct __BindgenBitfieldUnit<Storage, Align>
8+
where
9+
Storage: AsRef<[u8]> + AsMut<[u8]>,
10+
{
11+
storage: Storage,
12+
align: [Align; 0],
13+
}
14+
15+
impl<Storage, Align> __BindgenBitfieldUnit<Storage, Align>
16+
where
17+
Storage: AsRef<[u8]> + AsMut<[u8]>,
18+
{
19+
#[inline]
20+
pub fn new(storage: Storage) -> Self {
21+
Self { storage, align: [] }
22+
}
23+
24+
#[inline]
25+
pub fn get_bit(&self, index: usize) -> bool {
26+
debug_assert!(index / 8 < self.storage.as_ref().len());
27+
28+
let byte_index = index / 8;
29+
let byte = self.storage.as_ref()[byte_index];
30+
31+
let bit_index = index % 8;
32+
let mask = 1 << bit_index;
33+
34+
byte & mask == mask
35+
}
36+
37+
#[inline]
38+
pub fn set_bit(&mut self, index: usize, val: bool) {
39+
debug_assert!(index / 8 < self.storage.as_ref().len());
40+
41+
let byte_index = index / 8;
42+
let byte = &mut self.storage.as_mut()[byte_index];
43+
44+
let bit_index = index % 8;
45+
let mask = 1 << bit_index;
46+
47+
if val {
48+
*byte |= mask;
49+
} else {
50+
*byte &= !mask;
51+
}
52+
}
53+
54+
#[inline]
55+
pub fn get(&self, bit_offset: usize, bit_width: u8) -> u64 {
56+
debug_assert!(bit_width <= 64);
57+
debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
58+
debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());
59+
60+
let mut val = 0;
61+
62+
for i in 0..(bit_width as usize) {
63+
if self.get_bit(i + bit_offset) {
64+
val |= 1 << i;
65+
}
66+
}
67+
68+
val
69+
}
70+
71+
#[inline]
72+
pub fn set(&mut self, bit_offset: usize, bit_width: u8, val: u64) {
73+
debug_assert!(bit_width <= 64);
74+
debug_assert!(bit_offset / 8 < self.storage.as_ref().len());
75+
debug_assert!((bit_offset + (bit_width as usize)) / 8 <= self.storage.as_ref().len());
76+
77+
for i in 0..(bit_width as usize) {
78+
let mask = 1 << i;
79+
let val_bit_is_set = val & mask == mask;
80+
self.set_bit(i + bit_offset, val_bit_is_set);
81+
}
82+
}
83+
}
84+
#[repr(C)]
85+
#[derive(Debug, Default, Copy, Clone)]
86+
pub struct S {
87+
pub a: u8,
88+
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize], u16>,
89+
pub __bindgen_align: [u32; 0usize],
90+
}
91+
#[test]
92+
fn bindgen_test_layout_S() {
93+
assert_eq!(
94+
::std::mem::size_of::<S>(),
95+
4usize,
96+
concat!("Size of: ", stringify!(S))
97+
);
98+
assert_eq!(
99+
::std::mem::align_of::<S>(),
100+
4usize,
101+
concat!("Alignment of ", stringify!(S))
102+
);
103+
assert_eq!(
104+
unsafe { &(*(::std::ptr::null::<S>())).a as *const _ as usize },
105+
0usize,
106+
concat!("Offset of field: ", stringify!(S), "::", stringify!(a))
107+
);
108+
}
109+
impl S {
110+
#[inline]
111+
pub fn b(&self) -> u32 {
112+
unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 15u8) as u32) }
113+
}
114+
#[inline]
115+
pub fn set_b(&mut self, val: u32) {
116+
unsafe {
117+
let val: u32 = ::std::mem::transmute(val);
118+
self._bitfield_1.set(0usize, 15u8, val as u64)
119+
}
120+
}
121+
#[inline]
122+
pub fn new_bitfield_1(b: u32) -> __BindgenBitfieldUnit<[u8; 2usize], u16> {
123+
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize], u16> =
124+
Default::default();
125+
__bindgen_bitfield_unit.set(0usize, 15u8, {
126+
let b: u32 = unsafe { ::std::mem::transmute(b) };
127+
b as u64
128+
});
129+
__bindgen_bitfield_unit
130+
}
131+
}
132+
#[repr(C)]
133+
#[derive(Debug, Default, Copy, Clone)]
134+
pub struct S2 {
135+
pub a: u8,
136+
pub _bitfield_1: __BindgenBitfieldUnit<[u8; 2usize], u16>,
137+
pub __bindgen_align: [u16; 0usize],
138+
}
139+
#[test]
140+
fn bindgen_test_layout_S2() {
141+
assert_eq!(
142+
::std::mem::size_of::<S2>(),
143+
4usize,
144+
concat!("Size of: ", stringify!(S2))
145+
);
146+
assert_eq!(
147+
::std::mem::align_of::<S2>(),
148+
2usize,
149+
concat!("Alignment of ", stringify!(S2))
150+
);
151+
assert_eq!(
152+
unsafe { &(*(::std::ptr::null::<S2>())).a as *const _ as usize },
153+
0usize,
154+
concat!("Offset of field: ", stringify!(S2), "::", stringify!(a))
155+
);
156+
}
157+
impl S2 {
158+
#[inline]
159+
pub fn b(&self) -> u16 {
160+
unsafe { ::std::mem::transmute(self._bitfield_1.get(0usize, 15u8) as u16) }
161+
}
162+
#[inline]
163+
pub fn set_b(&mut self, val: u16) {
164+
unsafe {
165+
let val: u16 = ::std::mem::transmute(val);
166+
self._bitfield_1.set(0usize, 15u8, val as u64)
167+
}
168+
}
169+
#[inline]
170+
pub fn new_bitfield_1(b: u16) -> __BindgenBitfieldUnit<[u8; 2usize], u16> {
171+
let mut __bindgen_bitfield_unit: __BindgenBitfieldUnit<[u8; 2usize], u16> =
172+
Default::default();
173+
__bindgen_bitfield_unit.set(0usize, 15u8, {
174+
let b: u16 = unsafe { ::std::mem::transmute(b) };
175+
b as u64
176+
});
177+
__bindgen_bitfield_unit
178+
}
179+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
typedef unsigned char uint8_t;
2+
typedef unsigned short uint16_t;
3+
typedef unsigned uint32_t;
4+
5+
typedef struct {
6+
uint8_t a;
7+
uint32_t b : 15;
8+
} S;
9+
10+
typedef struct {
11+
uint8_t a;
12+
uint16_t b : 15;
13+
} S2;

0 commit comments

Comments
 (0)