Skip to content

Commit 2c1d615

Browse files
committed
gen: Generate bitfield getters for structs
1 parent 8a10eb1 commit 2c1d615

8 files changed

+201
-69
lines changed

src/gen.rs

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1017,7 +1017,7 @@ fn cstruct_to_rs(ctx: &mut GenCtx, name: &str, ci: CompInfo) -> Vec<P<ast::Item>
10171017
let mut offset: u32 = 0;
10181018
if let Some(ref bitfields) = f.bitfields {
10191019
for &(ref bf_name, bf_size) in bitfields.iter() {
1020-
setters.push(gen_bitfield_method(ctx, &f_name, bf_name, &f_ty, offset as usize, bf_size));
1020+
setters.extend(gen_bitfield_methods(ctx, &f_name, bf_name, &f_ty, offset as usize, bf_size).into_iter());
10211021
offset += bf_size;
10221022
}
10231023
setters.push(gen_fullbitfield_method(ctx, &f_name, &f_ty, bitfields))
@@ -1623,13 +1623,13 @@ fn type_for_bitfield_width(ctx: &mut GenCtx, width: u32, is_arg: bool) -> ast::T
16231623
mk_ty(ctx, false, &[input_type.to_owned()])
16241624
}
16251625

1626-
fn gen_bitfield_method(ctx: &mut GenCtx, bindgen_name: &str,
1627-
field_name: &str, field_type: &Type,
1628-
offset: usize, width: u32) -> ast::ImplItem {
1626+
fn gen_bitfield_methods(ctx: &mut GenCtx, bindgen_name: &str,
1627+
field_name: &str, field_type: &Type,
1628+
offset: usize, width: u32) -> Vec<ast::ImplItem> {
16291629
let input_type = type_for_bitfield_width(ctx, width, true);
1630-
let width = width % (field_type.layout().unwrap().size as u32 * 8);
1630+
let width = width as usize;
16311631

1632-
let field_type = cty_to_rs(ctx, &field_type, false, true);
1632+
let field_type = cty_to_rs(ctx, field_type, false, true);
16331633

16341634
let real_field_name = if field_name.is_empty() {
16351635
format!("at_offset_{}", offset)
@@ -1638,20 +1638,28 @@ fn gen_bitfield_method(ctx: &mut GenCtx, bindgen_name: &str,
16381638
};
16391639

16401640

1641-
let setter_name = ctx.ext_cx.ident_of(&format!("set_{}", real_field_name));
16421641
let bindgen_ident = ctx.ext_cx.ident_of(bindgen_name);
1642+
let setter_name = ctx.ext_cx.ident_of(&format!("set_{}", real_field_name));
1643+
let getter_name = ctx.ext_cx.ident_of(&real_field_name);
16431644

1645+
let mask = ((1usize << width) - 1) << offset;
16441646
let item = quote_item!(&ctx.ext_cx,
16451647
impl X {
1648+
#[inline]
1649+
pub fn $getter_name(&self) -> $field_type {
1650+
(self.$bindgen_ident & ($mask as $field_type)) >> $offset
1651+
}
1652+
1653+
#[inline]
16461654
pub fn $setter_name(&mut self, val: $input_type) {
1647-
self.$bindgen_ident &= !(((1 << $width as $field_type) - 1) << $offset);
1648-
self.$bindgen_ident |= (val as $field_type) << $offset;
1655+
self.$bindgen_ident &= !($mask as $field_type);
1656+
self.$bindgen_ident |= (val as $field_type << $offset) & ($mask as $field_type);
16491657
}
16501658
}
16511659
).unwrap();
16521660

1653-
match &item.node {
1654-
&ast::ItemKind::Impl(_, _, _, _, _, ref items) => items[0].clone(),
1661+
match item.node {
1662+
ast::ItemKind::Impl(_, _, _, _, _, ref items) => items.clone(),
16551663
_ => unreachable!()
16561664
}
16571665
}

src/parser.rs

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -681,11 +681,12 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
681681
(Some(width), _) => {
682682
// Bitfields containing enums are not supported by the c standard
683683
// https://stackoverflow.com/questions/11983231/is-it-safe-to-use-an-enum-in-a-bit-field
684+
684685
match ty {
685-
il::TInt(_, _) => (),
686+
il::TInt(..) => {},
686687
_ => {
687-
// NOTE: We rely on the name of the type converted to rust types,
688-
// and on the alignment.
688+
// NOTE: We rely on the name of the type converted
689+
// to rust types, and on the alignment.
689690
let bits = cmp::max(width, ty.size() as u32 * 8);
690691
let layout_size = cmp::max(1, bits.next_power_of_two() / 8) as usize;
691692

@@ -710,7 +711,7 @@ fn visit_composite(cursor: &Cursor, parent: &Cursor,
710711
ty = TNamed(Rc::new(RefCell::new(ti)))
711712
}
712713
}
713-
("".to_owned(), Some(vec!((cursor.spelling(), width))))
714+
("".to_owned(), Some(vec![(cursor.spelling(), width)]))
714715
},
715716
// The field is not a bitfield
716717
(None, _) => (cursor.spelling(), None)

tests/expectations/jsval_layout_opaque.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,13 +147,25 @@ pub struct jsval_layout_jsval_layout_opaque_hpp_unnamed_1 {
147147
pub _bitfield_1: u64,
148148
}
149149
impl jsval_layout_jsval_layout_opaque_hpp_unnamed_1 {
150+
#[inline]
151+
pub fn payload47(&self) -> u64 {
152+
(self._bitfield_1 & (140737488355327usize as u64)) >> 0usize
153+
}
154+
#[inline]
150155
pub fn set_payload47(&mut self, val: u32) {
151-
self._bitfield_1 &= !(((1 << (47u32 as u64)) - 1) << 0usize);
152-
self._bitfield_1 |= (val as u64) << 0usize;
156+
self._bitfield_1 &= !(140737488355327usize as u64);
157+
self._bitfield_1 |=
158+
((val as u64) << 0usize) & (140737488355327usize as u64);
153159
}
160+
#[inline]
161+
pub fn tag(&self) -> u64 {
162+
(self._bitfield_1 & (18446603336221196288usize as u64)) >> 47usize
163+
}
164+
#[inline]
154165
pub fn set_tag(&mut self, val: u32) {
155-
self._bitfield_1 &= !(((1 << (17u32 as u64)) - 1) << 47usize);
156-
self._bitfield_1 |= (val as u64) << 47usize;
166+
self._bitfield_1 &= !(18446603336221196288usize as u64);
167+
self._bitfield_1 |=
168+
((val as u64) << 47usize) & (18446603336221196288usize as u64);
157169
}
158170
pub const fn new_bitfield_1(payload47: u32, tag: u32) -> u64 {
159171
0 | ((payload47 as u64) << 0u32) | ((tag as u64) << 47u32)

tests/expectations/only_bitfields.rs

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,19 @@ pub struct Struct_C {
1111
pub _bitfield_1: u8,
1212
}
1313
impl Struct_C {
14+
#[inline]
15+
pub fn a(&self) -> u8 { (self._bitfield_1 & (1usize as u8)) >> 0usize }
16+
#[inline]
1417
pub fn set_a(&mut self, val: bool) {
15-
self._bitfield_1 &= !(((1 << (1u32 as u8)) - 1) << 0usize);
16-
self._bitfield_1 |= (val as u8) << 0usize;
18+
self._bitfield_1 &= !(1usize as u8);
19+
self._bitfield_1 |= ((val as u8) << 0usize) & (1usize as u8);
1720
}
21+
#[inline]
22+
pub fn b(&self) -> u8 { (self._bitfield_1 & (254usize as u8)) >> 1usize }
23+
#[inline]
1824
pub fn set_b(&mut self, val: u8) {
19-
self._bitfield_1 &= !(((1 << (7u32 as u8)) - 1) << 1usize);
20-
self._bitfield_1 |= (val as u8) << 1usize;
25+
self._bitfield_1 &= !(254usize as u8);
26+
self._bitfield_1 |= ((val as u8) << 1usize) & (254usize as u8);
2127
}
2228
pub const fn new_bitfield_1(a: bool, b: u8) -> u8 {
2329
0 | ((a as u8) << 0u32) | ((b as u8) << 1u32)

tests/expectations/struct_with_bitfields.rs

Lines changed: 73 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -14,35 +14,71 @@ pub struct Struct_bitfield {
1414
pub _bitfield_3: ::std::os::raw::c_uint,
1515
}
1616
impl Struct_bitfield {
17+
#[inline]
18+
pub fn a(&self) -> ::std::os::raw::c_ushort {
19+
(self._bitfield_1 & (1usize as ::std::os::raw::c_ushort)) >> 0usize
20+
}
21+
#[inline]
1722
pub fn set_a(&mut self, val: bool) {
18-
self._bitfield_1 &=
19-
!(((1 << (1u32 as ::std::os::raw::c_ushort)) - 1) << 0usize);
20-
self._bitfield_1 |= (val as ::std::os::raw::c_ushort) << 0usize;
23+
self._bitfield_1 &= !(1usize as ::std::os::raw::c_ushort);
24+
self._bitfield_1 |=
25+
((val as ::std::os::raw::c_ushort) << 0usize) &
26+
(1usize as ::std::os::raw::c_ushort);
27+
}
28+
#[inline]
29+
pub fn b(&self) -> ::std::os::raw::c_ushort {
30+
(self._bitfield_1 & (2usize as ::std::os::raw::c_ushort)) >> 1usize
2131
}
32+
#[inline]
2233
pub fn set_b(&mut self, val: bool) {
23-
self._bitfield_1 &=
24-
!(((1 << (1u32 as ::std::os::raw::c_ushort)) - 1) << 1usize);
25-
self._bitfield_1 |= (val as ::std::os::raw::c_ushort) << 1usize;
34+
self._bitfield_1 &= !(2usize as ::std::os::raw::c_ushort);
35+
self._bitfield_1 |=
36+
((val as ::std::os::raw::c_ushort) << 1usize) &
37+
(2usize as ::std::os::raw::c_ushort);
2638
}
39+
#[inline]
40+
pub fn c(&self) -> ::std::os::raw::c_ushort {
41+
(self._bitfield_1 & (4usize as ::std::os::raw::c_ushort)) >> 2usize
42+
}
43+
#[inline]
2744
pub fn set_c(&mut self, val: bool) {
28-
self._bitfield_1 &=
29-
!(((1 << (1u32 as ::std::os::raw::c_ushort)) - 1) << 2usize);
30-
self._bitfield_1 |= (val as ::std::os::raw::c_ushort) << 2usize;
45+
self._bitfield_1 &= !(4usize as ::std::os::raw::c_ushort);
46+
self._bitfield_1 |=
47+
((val as ::std::os::raw::c_ushort) << 2usize) &
48+
(4usize as ::std::os::raw::c_ushort);
49+
}
50+
#[inline]
51+
pub fn at_offset_3(&self) -> ::std::os::raw::c_ushort {
52+
(self._bitfield_1 & (8usize as ::std::os::raw::c_ushort)) >> 3usize
3153
}
54+
#[inline]
3255
pub fn set_at_offset_3(&mut self, val: bool) {
33-
self._bitfield_1 &=
34-
!(((1 << (1u32 as ::std::os::raw::c_ushort)) - 1) << 3usize);
35-
self._bitfield_1 |= (val as ::std::os::raw::c_ushort) << 3usize;
56+
self._bitfield_1 &= !(8usize as ::std::os::raw::c_ushort);
57+
self._bitfield_1 |=
58+
((val as ::std::os::raw::c_ushort) << 3usize) &
59+
(8usize as ::std::os::raw::c_ushort);
3660
}
61+
#[inline]
62+
pub fn at_offset_4(&self) -> ::std::os::raw::c_ushort {
63+
(self._bitfield_1 & (48usize as ::std::os::raw::c_ushort)) >> 4usize
64+
}
65+
#[inline]
3766
pub fn set_at_offset_4(&mut self, val: u8) {
38-
self._bitfield_1 &=
39-
!(((1 << (2u32 as ::std::os::raw::c_ushort)) - 1) << 4usize);
40-
self._bitfield_1 |= (val as ::std::os::raw::c_ushort) << 4usize;
67+
self._bitfield_1 &= !(48usize as ::std::os::raw::c_ushort);
68+
self._bitfield_1 |=
69+
((val as ::std::os::raw::c_ushort) << 4usize) &
70+
(48usize as ::std::os::raw::c_ushort);
71+
}
72+
#[inline]
73+
pub fn d(&self) -> ::std::os::raw::c_ushort {
74+
(self._bitfield_1 & (192usize as ::std::os::raw::c_ushort)) >> 6usize
4175
}
76+
#[inline]
4277
pub fn set_d(&mut self, val: u8) {
43-
self._bitfield_1 &=
44-
!(((1 << (2u32 as ::std::os::raw::c_ushort)) - 1) << 6usize);
45-
self._bitfield_1 |= (val as ::std::os::raw::c_ushort) << 6usize;
78+
self._bitfield_1 &= !(192usize as ::std::os::raw::c_ushort);
79+
self._bitfield_1 |=
80+
((val as ::std::os::raw::c_ushort) << 6usize) &
81+
(192usize as ::std::os::raw::c_ushort);
4682
}
4783
pub const fn new_bitfield_1(a: bool, b: bool, c: bool,
4884
unnamed_bitfield1: bool,
@@ -55,18 +91,31 @@ impl Struct_bitfield {
5591
((unnamed_bitfield2 as ::std::os::raw::c_ushort) << 4u32) |
5692
((d as ::std::os::raw::c_ushort) << 6u32)
5793
}
94+
#[inline]
95+
pub fn f(&self) -> ::std::os::raw::c_uint {
96+
(self._bitfield_2 & (3usize as ::std::os::raw::c_uint)) >> 0usize
97+
}
98+
#[inline]
5899
pub fn set_f(&mut self, val: u8) {
59-
self._bitfield_2 &=
60-
!(((1 << (2u32 as ::std::os::raw::c_uint)) - 1) << 0usize);
61-
self._bitfield_2 |= (val as ::std::os::raw::c_uint) << 0usize;
100+
self._bitfield_2 &= !(3usize as ::std::os::raw::c_uint);
101+
self._bitfield_2 |=
102+
((val as ::std::os::raw::c_uint) << 0usize) &
103+
(3usize as ::std::os::raw::c_uint);
62104
}
63105
pub const fn new_bitfield_2(f: u8) -> ::std::os::raw::c_uint {
64106
0 | ((f as ::std::os::raw::c_uint) << 0u32)
65107
}
108+
#[inline]
109+
pub fn g(&self) -> ::std::os::raw::c_uint {
110+
(self._bitfield_3 & (4294967295usize as ::std::os::raw::c_uint)) >>
111+
0usize
112+
}
113+
#[inline]
66114
pub fn set_g(&mut self, val: u32) {
67-
self._bitfield_3 &=
68-
!(((1 << (0u32 as ::std::os::raw::c_uint)) - 1) << 0usize);
69-
self._bitfield_3 |= (val as ::std::os::raw::c_uint) << 0usize;
115+
self._bitfield_3 &= !(4294967295usize as ::std::os::raw::c_uint);
116+
self._bitfield_3 |=
117+
((val as ::std::os::raw::c_uint) << 0usize) &
118+
(4294967295usize as ::std::os::raw::c_uint);
70119
}
71120
pub const fn new_bitfield_3(g: u32) -> ::std::os::raw::c_uint {
72121
0 | ((g as ::std::os::raw::c_uint) << 0u32)

tests/expectations/template.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,11 @@ pub struct Struct_ShouldNotBeCopiable<T> {
144144
pub struct Struct_ShouldNotBeCopiableAsWell<U> {
145145
pub m_member: Struct_ReplacedWithoutDestructorFwd<U>,
146146
}
147+
#[repr(C)]
148+
#[derive(Debug, Copy, Clone)]
149+
pub struct Struct_TemplateWithVar<T> {
150+
pub _phantom0: ::std::marker::PhantomData<T>,
151+
}
147152
extern "C" {
148153
#[link_name = "_Z3bar3FooIiiE"]
149154
pub fn bar(foo: Struct_Foo<::std::os::raw::c_int, ::std::os::raw::c_int>);

tests/expectations/union_with_anon_struct_bitfield.rs

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,28 @@ pub struct Struct_foo_union_with_anon_struct_bitfield_h_unnamed_1 {
5656
pub _bitfield_1: ::std::os::raw::c_int,
5757
}
5858
impl Struct_foo_union_with_anon_struct_bitfield_h_unnamed_1 {
59+
#[inline]
60+
pub fn b(&self) -> ::std::os::raw::c_int {
61+
(self._bitfield_1 & (127usize as ::std::os::raw::c_int)) >> 0usize
62+
}
63+
#[inline]
5964
pub fn set_b(&mut self, val: u8) {
60-
self._bitfield_1 &=
61-
!(((1 << (7u32 as ::std::os::raw::c_int)) - 1) << 0usize);
62-
self._bitfield_1 |= (val as ::std::os::raw::c_int) << 0usize;
65+
self._bitfield_1 &= !(127usize as ::std::os::raw::c_int);
66+
self._bitfield_1 |=
67+
((val as ::std::os::raw::c_int) << 0usize) &
68+
(127usize as ::std::os::raw::c_int);
6369
}
70+
#[inline]
71+
pub fn c(&self) -> ::std::os::raw::c_int {
72+
(self._bitfield_1 & (4294967168usize as ::std::os::raw::c_int)) >>
73+
7usize
74+
}
75+
#[inline]
6476
pub fn set_c(&mut self, val: u32) {
65-
self._bitfield_1 &=
66-
!(((1 << (25u32 as ::std::os::raw::c_int)) - 1) << 7usize);
67-
self._bitfield_1 |= (val as ::std::os::raw::c_int) << 7usize;
77+
self._bitfield_1 &= !(4294967168usize as ::std::os::raw::c_int);
78+
self._bitfield_1 |=
79+
((val as ::std::os::raw::c_int) << 7usize) &
80+
(4294967168usize as ::std::os::raw::c_int);
6881
}
6982
pub const fn new_bitfield_1(b: u8, c: u32) -> ::std::os::raw::c_int {
7083
0 | ((b as ::std::os::raw::c_int) << 0u32) |

0 commit comments

Comments
 (0)