Skip to content

Commit 7bbfb44

Browse files
author
bors-servo
authored
Auto merge of #1058 - pepyakin:bitfield-accessors, r=fitzgen
Generate bitfield accessor names eagerly @fitzgen r? I'm not sure about `deanonymize_fields`, as we now assign names to data members and also generate names for the bitfield accessors, but can't come up with a better name.
2 parents 8387c7f + 91796cf commit 7bbfb44

File tree

7 files changed

+337
-99
lines changed

7 files changed

+337
-99
lines changed

src/codegen/impl_debug.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@ pub fn gen_debug_impl(
2828
&Field::Bitfields(ref bu) => bu.impl_debug(ctx, ()),
2929
});
3030

31-
3231
for (i, (fstring, toks)) in processed_fields.enumerate() {
3332
if i > 0 {
3433
format_string.push_str(", ");
@@ -91,14 +90,15 @@ impl<'a> ImplDebug<'a> for BitfieldUnit {
9190
) -> Option<(String, Vec<quote::Tokens>)> {
9291
let mut format_string = String::new();
9392
let mut tokens = vec![];
94-
for (i, bu) in self.bitfields().iter().enumerate() {
93+
for (i, bitfield) in self.bitfields().iter().enumerate() {
9594
if i > 0 {
9695
format_string.push_str(", ");
9796
}
9897

99-
if let Some(name) = bu.name() {
100-
format_string.push_str(&format!("{} : {{:?}}", name));
101-
let name_ident = ctx.rust_ident_raw(name);
98+
if let Some(bitfield_name) = bitfield.name() {
99+
format_string.push_str(&format!("{} : {{:?}}", bitfield_name));
100+
let getter_name = bitfield.getter_name();
101+
let name_ident = ctx.rust_ident_raw(getter_name);
102102
tokens.push(quote! {
103103
self.#name_ident ()
104104
});

src/codegen/impl_partialeq.rs

+3-2
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,9 @@ pub fn gen_partialeq_impl(
5151
tokens.push(gen_field(ctx, ty_item, name));
5252
}
5353
Field::Bitfields(ref bu) => for bitfield in bu.bitfields() {
54-
if let Some(name) = bitfield.name() {
55-
let name_ident = ctx.rust_ident_raw(name);
54+
if let Some(_) = bitfield.name() {
55+
let getter_name = bitfield.getter_name();
56+
let name_ident = ctx.rust_ident_raw(getter_name);
5657
tokens.push(quote! {
5758
self.#name_ident () == other.#name_ident ()
5859
});

src/codegen/mod.rs

+10-50
Original file line numberDiff line numberDiff line change
@@ -1202,7 +1202,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
12021202
(&unit_field_name, unit_field_int_ty.clone()),
12031203
);
12041204

1205-
let param_name = bitfield_getter_name(ctx, parent, bf.name().unwrap());
1205+
let param_name = bitfield_getter_name(ctx, bf);
12061206
let bitfield_ty_item = ctx.resolve_item(bf.ty());
12071207
let bitfield_ty = bitfield_ty_item.expect_type();
12081208
let bitfield_ty =
@@ -1236,59 +1236,21 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
12361236
}
12371237
}
12381238

1239-
fn parent_has_method(
1240-
ctx: &BindgenContext,
1241-
parent: &CompInfo,
1242-
name: &str,
1243-
) -> bool {
1244-
parent.methods().iter().any(|method| {
1245-
let method_name = match *ctx.resolve_item(method.signature()).kind() {
1246-
ItemKind::Function(ref func) => func.name(),
1247-
ref otherwise => {
1248-
panic!(
1249-
"a method's signature should always be a \
1250-
item of kind ItemKind::Function, found: \
1251-
{:?}",
1252-
otherwise
1253-
)
1254-
}
1255-
};
1256-
1257-
method_name == name || ctx.rust_mangle(&method_name) == name
1258-
})
1259-
}
1260-
12611239
fn bitfield_getter_name(
12621240
ctx: &BindgenContext,
1263-
parent: &CompInfo,
1264-
bitfield_name: &str,
1241+
bitfield: &Bitfield,
12651242
) -> quote::Tokens {
1266-
let name = ctx.rust_mangle(bitfield_name);
1267-
1268-
if parent_has_method(ctx, parent, &name) {
1269-
let mut name = name.to_string();
1270-
name.push_str("_bindgen_bitfield");
1271-
let name = ctx.rust_ident(name);
1272-
return quote! { #name };
1273-
}
1274-
1275-
let name = ctx.rust_ident(name);
1243+
let name = bitfield.getter_name();
1244+
let name = ctx.rust_ident_raw(name);
12761245
quote! { #name }
12771246
}
12781247

12791248
fn bitfield_setter_name(
12801249
ctx: &BindgenContext,
1281-
parent: &CompInfo,
1282-
bitfield_name: &str,
1250+
bitfield: &Bitfield,
12831251
) -> quote::Tokens {
1284-
let setter = format!("set_{}", bitfield_name);
1285-
let mut setter = ctx.rust_mangle(&setter).to_string();
1286-
1287-
if parent_has_method(ctx, parent, &setter) {
1288-
setter.push_str("_bindgen_bitfield");
1289-
}
1290-
1291-
let setter = ctx.rust_ident(setter);
1252+
let setter = bitfield.setter_name();
1253+
let setter = ctx.rust_ident_raw(setter);
12921254
quote! { #setter }
12931255
}
12941256

@@ -1301,7 +1263,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
13011263
_fields_should_be_private: bool,
13021264
_codegen_depth: usize,
13031265
_accessor_kind: FieldAccessorKind,
1304-
parent: &CompInfo,
1266+
_parent: &CompInfo,
13051267
_result: &mut CodegenResult,
13061268
_struct_layout: &mut StructLayoutTracker,
13071269
_fields: &mut F,
@@ -1311,11 +1273,9 @@ impl<'a> FieldCodegen<'a> for Bitfield {
13111273
F: Extend<quote::Tokens>,
13121274
M: Extend<quote::Tokens>,
13131275
{
1314-
// Should never be called with name() as None, as codegen can't be done
1315-
// on an anonymous bitfield
13161276
let prefix = ctx.trait_prefix();
1317-
let getter_name = bitfield_getter_name(ctx, parent, self.name().unwrap());
1318-
let setter_name = bitfield_setter_name(ctx, parent, self.name().unwrap());
1277+
let getter_name = bitfield_getter_name(ctx, self);
1278+
let setter_name = bitfield_setter_name(ctx, self);
13191279
let unit_field_ident = quote::Ident::new(unit_field_name);
13201280

13211281
let bitfield_ty_item = ctx.resolve_item(self.ty());

src/ir/comp.rs

+103-17
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use peeking_take_while::PeekableExt;
1717
use std::cmp;
1818
use std::io;
1919
use std::mem;
20+
use std::collections::HashMap;
2021

2122
/// The kind of compound type.
2223
#[derive(Debug, Copy, Clone, PartialEq)]
@@ -292,6 +293,16 @@ pub struct Bitfield {
292293

293294
/// The field data for this bitfield.
294295
data: FieldData,
296+
297+
/// Name of the generated Rust getter for this bitfield.
298+
///
299+
/// Should be assigned before codegen.
300+
getter_name: Option<String>,
301+
302+
/// Name of the generated Rust setter for this bitfield.
303+
///
304+
/// Should be assigned before codegen.
305+
setter_name: Option<String>,
295306
}
296307

297308
impl Bitfield {
@@ -302,6 +313,8 @@ impl Bitfield {
302313
Bitfield {
303314
offset_into_unit: offset_into_unit,
304315
data: raw.0,
316+
getter_name: None,
317+
setter_name: None,
305318
}
306319
}
307320

@@ -331,6 +344,30 @@ impl Bitfield {
331344
pub fn width(&self) -> u32 {
332345
self.data.bitfield().unwrap()
333346
}
347+
348+
/// Name of the generated Rust getter for this bitfield.
349+
///
350+
/// Panics if called before assigning bitfield accessor names or if
351+
/// this bitfield have no name.
352+
pub fn getter_name(&self) -> &str {
353+
assert!(self.name().is_some(), "`Bitfield::getter_name` called on anonymous field");
354+
self.getter_name.as_ref().expect(
355+
"`Bitfield::getter_name` should only be called after\
356+
assigning bitfield accessor names",
357+
)
358+
}
359+
360+
/// Name of the generated Rust setter for this bitfield.
361+
///
362+
/// Panics if called before assigning bitfield accessor names or if
363+
/// this bitfield have no name.
364+
pub fn setter_name(&self) -> &str {
365+
assert!(self.name().is_some(), "`Bitfield::setter_name` called on anonymous field");
366+
self.setter_name.as_ref().expect(
367+
"`Bitfield::setter_name` should only be called\
368+
after assigning bitfield accessor names",
369+
)
370+
}
334371
}
335372

336373
impl FieldMethods for Bitfield {
@@ -661,30 +698,79 @@ impl CompFields {
661698
);
662699
}
663700

664-
fn deanonymize_fields(&mut self) {
701+
fn deanonymize_fields(&mut self, ctx: &BindgenContext, methods: &[Method]) {
665702
let fields = match *self {
666-
CompFields::AfterComputingBitfieldUnits(ref mut fields) => {
667-
fields
668-
}
703+
CompFields::AfterComputingBitfieldUnits(ref mut fields) => fields,
669704
CompFields::BeforeComputingBitfieldUnits(_) => {
670705
panic!("Not yet computed bitfield units.");
671706
}
672707
};
673708

709+
fn has_method(methods: &[Method], ctx: &BindgenContext, name: &str) -> bool {
710+
methods.iter().any(|method| {
711+
let method_name = ctx.resolve_func(method.signature()).name();
712+
method_name == name || ctx.rust_mangle(&method_name) == name
713+
})
714+
}
715+
716+
struct AccessorNamesPair {
717+
getter: String,
718+
setter: String,
719+
}
720+
721+
let mut accessor_names: HashMap<String, AccessorNamesPair> = fields
722+
.iter()
723+
.flat_map(|field| match *field {
724+
Field::Bitfields(ref bu) => &*bu.bitfields,
725+
Field::DataMember(_) => &[],
726+
})
727+
.filter_map(|bitfield| bitfield.name())
728+
.map(|bitfield_name| {
729+
let bitfield_name = bitfield_name.to_string();
730+
let getter = {
731+
let mut getter = ctx.rust_mangle(&bitfield_name).to_string();
732+
if has_method(methods, ctx, &getter) {
733+
getter.push_str("_bindgen_bitfield");
734+
}
735+
getter
736+
};
737+
let setter = {
738+
let setter = format!("set_{}", bitfield_name);
739+
let mut setter = ctx.rust_mangle(&setter).to_string();
740+
if has_method(methods, ctx, &setter) {
741+
setter.push_str("_bindgen_bitfield");
742+
}
743+
setter
744+
};
745+
(bitfield_name, AccessorNamesPair { getter, setter })
746+
})
747+
.collect();
748+
674749
let mut anon_field_counter = 0;
675750
for field in fields.iter_mut() {
676-
let field_data = match *field {
677-
Field::DataMember(ref mut fd) => fd,
678-
Field::Bitfields(_) => continue,
679-
};
751+
match *field {
752+
Field::DataMember(FieldData { ref mut name, .. }) => {
753+
if let Some(_) = *name {
754+
continue;
755+
}
680756

681-
if let Some(_) = field_data.name {
682-
continue;
683-
}
757+
anon_field_counter += 1;
758+
let generated_name = format!("__bindgen_anon_{}", anon_field_counter);
759+
*name = Some(generated_name);
760+
}
761+
Field::Bitfields(ref mut bu) => for bitfield in &mut bu.bitfields {
762+
if bitfield.name().is_none() {
763+
continue;
764+
}
684765

685-
anon_field_counter += 1;
686-
let name = format!("__bindgen_anon_{}", anon_field_counter);
687-
field_data.name = Some(name);
766+
if let Some(AccessorNamesPair { getter, setter }) =
767+
accessor_names.remove(bitfield.name().unwrap())
768+
{
769+
bitfield.getter_name = Some(getter);
770+
bitfield.setter_name = Some(setter);
771+
}
772+
},
773+
}
688774
}
689775
}
690776
}
@@ -1397,8 +1483,8 @@ impl CompInfo {
13971483
}
13981484

13991485
/// Assign for each anonymous field a generated name.
1400-
pub fn deanonymize_fields(&mut self) {
1401-
self.fields.deanonymize_fields();
1486+
pub fn deanonymize_fields(&mut self, ctx: &BindgenContext) {
1487+
self.fields.deanonymize_fields(ctx, &self.methods);
14021488
}
14031489

14041490
/// Returns whether the current union can be represented as a Rust `union`
@@ -1484,7 +1570,7 @@ impl IsOpaque for CompInfo {
14841570
false
14851571
},
14861572
Field::Bitfields(ref unit) => {
1487-
unit.bitfields().iter().any(|bf| {
1573+
unit.bitfields().iter().any(|bf| {
14881574
let bitfield_layout = ctx.resolve_type(bf.ty())
14891575
.layout(ctx)
14901576
.expect("Bitfield without layout? Gah!");

0 commit comments

Comments
 (0)