Skip to content

Commit a26bf0b

Browse files
committed
Eagerly generate bitfield accessor names
Also clean a bit.
1 parent 4e74c39 commit a26bf0b

File tree

3 files changed

+147
-73
lines changed

3 files changed

+147
-73
lines changed

src/codegen/mod.rs

Lines changed: 10 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1198,7 +1198,7 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
11981198
(&unit_field_name, unit_field_int_ty.clone()),
11991199
);
12001200

1201-
let param_name = bitfield_getter_name(ctx, parent, bf.name());
1201+
let param_name = bitfield_getter_name(ctx, bf);
12021202
let bitfield_ty_item = ctx.resolve_item(bf.ty());
12031203
let bitfield_ty = bitfield_ty_item.expect_type();
12041204
let bitfield_ty =
@@ -1232,59 +1232,21 @@ impl<'a> FieldCodegen<'a> for BitfieldUnit {
12321232
}
12331233
}
12341234

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

12751244
fn bitfield_setter_name(
12761245
ctx: &BindgenContext,
1277-
parent: &CompInfo,
1278-
bitfield_name: &str,
1246+
bitfield: &Bitfield,
12791247
) -> quote::Tokens {
1280-
let setter = format!("set_{}", bitfield_name);
1281-
let mut setter = ctx.rust_mangle(&setter).to_string();
1282-
1283-
if parent_has_method(ctx, parent, &setter) {
1284-
setter.push_str("_bindgen_bitfield");
1285-
}
1286-
1287-
let setter = ctx.rust_ident(setter);
1248+
let setter = bitfield.setter_name();
1249+
let setter = ctx.rust_ident_raw(setter);
12881250
quote! { #setter }
12891251
}
12901252

@@ -1297,7 +1259,7 @@ impl<'a> FieldCodegen<'a> for Bitfield {
12971259
_fields_should_be_private: bool,
12981260
_codegen_depth: usize,
12991261
_accessor_kind: FieldAccessorKind,
1300-
parent: &CompInfo,
1262+
_parent: &CompInfo,
13011263
_result: &mut CodegenResult,
13021264
_struct_layout: &mut StructLayoutTracker,
13031265
_fields: &mut F,
@@ -1308,8 +1270,8 @@ impl<'a> FieldCodegen<'a> for Bitfield {
13081270
M: Extend<quote::Tokens>,
13091271
{
13101272
let prefix = ctx.trait_prefix();
1311-
let getter_name = bitfield_getter_name(ctx, parent, self.name());
1312-
let setter_name = bitfield_setter_name(ctx, parent, self.name());
1273+
let getter_name = bitfield_getter_name(ctx, self);
1274+
let setter_name = bitfield_setter_name(ctx, self);
13131275
let unit_field_ident = quote::Ident::new(unit_field_name);
13141276

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

src/ir/comp.rs

Lines changed: 100 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,16 @@ pub struct Bitfield {
292292

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

297307
impl Bitfield {
@@ -303,6 +313,8 @@ impl Bitfield {
303313
Bitfield {
304314
offset_into_unit: offset_into_unit,
305315
data: raw.0,
316+
getter_name: None,
317+
setter_name: None,
306318
}
307319
}
308320

@@ -337,6 +349,16 @@ impl Bitfield {
337349
pub fn name(&self) -> &str {
338350
self.data.name().unwrap()
339351
}
352+
353+
/// Name of the generated Rust getter for this bitfield.
354+
pub fn getter_name(&self) -> &str {
355+
self.getter_name.as_ref().unwrap()
356+
}
357+
358+
/// Name of the generated Rust setter for this bitfield.
359+
pub fn setter_name(&self) -> &str {
360+
self.setter_name.as_ref().unwrap()
361+
}
340362
}
341363

342364
impl FieldMethods for Bitfield {
@@ -668,30 +690,92 @@ impl CompFields {
668690
);
669691
}
670692

671-
fn deanonymize_fields(&mut self) {
693+
fn deanonymize_fields(&mut self, ctx: &BindgenContext, methods: &[Method]) {
694+
use std::collections::HashMap;
695+
672696
let fields = match *self {
673-
CompFields::AfterComputingBitfieldUnits(ref mut fields) => {
674-
fields
675-
}
697+
CompFields::AfterComputingBitfieldUnits(ref mut fields) => fields,
676698
CompFields::BeforeComputingBitfieldUnits(_) => {
677699
panic!("Not yet computed bitfield units.");
678700
}
679701
};
680702

703+
fn has_method(
704+
methods: &[Method],
705+
ctx: &BindgenContext,
706+
name: &str,
707+
) -> bool {
708+
methods.iter().any(|method| {
709+
let method_name = ctx.resolve_func(method.signature()).name();
710+
method_name == name || ctx.rust_mangle(&method_name) == name
711+
})
712+
}
713+
714+
struct AccessorNamesPair {
715+
getter: String,
716+
setter: String,
717+
}
718+
719+
let mut accessor_names: HashMap<String, AccessorNamesPair> = fields
720+
.iter()
721+
.flat_map(|field| match *field {
722+
Field::Bitfields(ref bu) => &*bu.bitfields,
723+
Field::DataMember(_) => &[],
724+
})
725+
.map(|bitfield| {
726+
let bitfield_name = bitfield.name().to_string();
727+
let getter = {
728+
let mut getter =
729+
ctx.rust_mangle(&bitfield_name).to_string();
730+
if has_method(methods, ctx, &getter) {
731+
getter.push_str("_bindgen_bitfield");
732+
}
733+
getter
734+
};
735+
let setter = {
736+
let setter = format!("set_{}", bitfield_name);
737+
let mut setter = ctx.rust_mangle(&setter).to_string();
738+
if has_method(methods, ctx, &setter) {
739+
setter.push_str("_bindgen_bitfield");
740+
}
741+
setter
742+
};
743+
(
744+
bitfield_name,
745+
AccessorNamesPair {
746+
getter,
747+
setter,
748+
},
749+
)
750+
})
751+
.collect();
752+
681753
let mut anon_field_counter = 0;
682754
for field in fields.iter_mut() {
683-
let field_data = match *field {
684-
Field::DataMember(ref mut fd) => fd,
685-
Field::Bitfields(_) => continue,
686-
};
755+
match *field {
756+
Field::DataMember(FieldData {
757+
ref mut name, ..
758+
}) => {
759+
if let Some(_) = *name {
760+
continue;
761+
}
687762

688-
if let Some(_) = field_data.name {
689-
continue;
763+
anon_field_counter += 1;
764+
let generated_name =
765+
format!("__bindgen_anon_{}", anon_field_counter);
766+
*name = Some(generated_name);
767+
}
768+
Field::Bitfields(ref mut bu) => {
769+
for bitfield in &mut bu.bitfields {
770+
let AccessorNamesPair {
771+
getter,
772+
setter,
773+
} = accessor_names.remove(bitfield.name()).unwrap();
774+
bitfield.getter_name = Some(getter);
775+
bitfield.setter_name = Some(setter);
776+
}
777+
}
690778
}
691-
692-
anon_field_counter += 1;
693-
let name = format!("__bindgen_anon_{}", anon_field_counter);
694-
field_data.name = Some(name);
695779
}
696780
}
697781
}
@@ -1404,8 +1488,8 @@ impl CompInfo {
14041488
}
14051489

14061490
/// Assign for each anonymous field a generated name.
1407-
pub fn deanonymize_fields(&mut self) {
1408-
self.fields.deanonymize_fields();
1491+
pub fn deanonymize_fields(&mut self, ctx: &BindgenContext) {
1492+
self.fields.deanonymize_fields(ctx, &self.methods);
14091493
}
14101494

14111495
/// Returns whether the current union can be represented as a Rust `union`

src/ir/context.rs

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ use super::module::{Module, ModuleKind};
1515
use super::template::{TemplateInstantiation, TemplateParameters};
1616
use super::traversal::{self, Edge, ItemTraversal};
1717
use super::ty::{FloatKind, Type, TypeKind};
18+
use super::function::Function;
1819
use super::super::time::Timer;
1920
use BindgenOptions;
2021
use callbacks::ParseCallbacks;
@@ -994,12 +995,31 @@ impl BindgenContext {
994995
/// Assign a new generated name for each anonymous field.
995996
fn deanonymize_fields(&mut self) {
996997
let _t = self.timer("deanonymize_fields");
997-
let comp_types = self.items
998-
.values_mut()
999-
.filter_map(|item| item.kind_mut().as_type_mut())
1000-
.filter_map(Type::as_comp_mut);
1001-
for comp_info in comp_types {
1002-
comp_info.deanonymize_fields();
998+
999+
let comp_item_ids: Vec<ItemId> = self.items
1000+
.iter()
1001+
.filter_map(|(id, item)| {
1002+
if let Some(ty) = item.kind().as_type() {
1003+
if let Some(_comp) = ty.as_comp() {
1004+
return Some(id);
1005+
}
1006+
}
1007+
None
1008+
})
1009+
.cloned()
1010+
.collect();
1011+
1012+
for id in comp_item_ids {
1013+
let mut item = self.items.remove(&id).unwrap();
1014+
1015+
item.kind_mut()
1016+
.as_type_mut()
1017+
.unwrap()
1018+
.as_comp_mut()
1019+
.unwrap()
1020+
.deanonymize_fields(self);
1021+
1022+
self.items.insert(id, item);
10031023
}
10041024
}
10051025

@@ -1395,12 +1415,20 @@ impl BindgenContext {
13951415
self.root_module
13961416
}
13971417

1398-
/// Resolve the given `ItemId` as a type.
1418+
/// Resolve a type with the given id.
13991419
///
1400-
/// Panics if there is no item for the given `ItemId` or if the resolved
1420+
/// Panics if there is no item for the given `TypeId` or if the resolved
14011421
/// item is not a `Type`.
14021422
pub fn resolve_type(&self, type_id: TypeId) -> &Type {
1403-
self.items.get(&type_id.into()).unwrap().kind().expect_type()
1423+
self.resolve_item(type_id).kind().expect_type()
1424+
}
1425+
1426+
/// Resolve a function with the given id.
1427+
///
1428+
/// Panics if there is no item for the given `FunctionId` or if the resolved
1429+
/// item is not a `Function`.
1430+
pub fn resolve_func(&self, func_id: FunctionId) -> &Function {
1431+
self.resolve_item(func_id).kind().expect_function()
14041432
}
14051433

14061434
/// Resolve the given `ItemId` as a type, or `None` if there is no item with

0 commit comments

Comments
 (0)