Skip to content

Commit b3c9532

Browse files
committed
Generate extern wrappers for inlined functions
If bindgen finds an inlined function and the `--generate-inline-functions` options is enabled, then: - It will generate two new source and header files with external functions that wrap the inlined functions. - Rerun `Bindings::generate` using the new header file to include these wrappers in the generated bindings. The following options were added: - `--extern-function-suffix=<suffix>`: Adds <suffix> to the name of each external wrapper function (`__extern` is used by default). - `--extern-functions-file-name=<name>`: Uses <name> as the file name for the header and source files (`extern` is used by default). - `--extern-function-directory=<dir>`: Creates the source and header files inside <dir> (`/tmp/bindgen` is used by default). The C code serialization is experimental and only supports a very limited set of C functions. Fixes rust-lang#1090.
1 parent 7c26cd2 commit b3c9532

File tree

7 files changed

+378
-10
lines changed

7 files changed

+378
-10
lines changed

bindgen-cli/options.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,18 @@ where
574574
.value_name("override")
575575
.multiple_occurrences(true)
576576
.number_of_values(1),
577+
Arg::new("extern-functions-file-name")
578+
.long("extern-functions-file-name")
579+
.help("Sets the name of the header and source code files that would be created if any extern wrapper functions must be generated due to the presence of inlined functions.")
580+
.takes_value(true),
581+
Arg::new("extern-functions-directory")
582+
.long("extern-functions-directory")
583+
.help("Sets the directory path where any extra files must be created due to the presence of inlined functions.")
584+
.takes_value(true),
585+
Arg::new("extern-function-suffix")
586+
.long("extern-function-suffix")
587+
.help("Sets the suffix added to the extern wrapper functions generated for inlined functions.")
588+
.takes_value(true),
577589
Arg::new("V")
578590
.long("version")
579591
.help("Prints the version, and exits"),
@@ -1106,5 +1118,17 @@ where
11061118
}
11071119
}
11081120

1121+
if let Some(file_name) = matches.value_of("extern-functions-file-name") {
1122+
builder = builder.extern_functions_file_name(file_name);
1123+
}
1124+
1125+
if let Some(directory) = matches.value_of("extern-functions-directory") {
1126+
builder = builder.extern_functions_directory(directory);
1127+
}
1128+
1129+
if let Some(suffix) = matches.value_of("extern-function-suffix") {
1130+
builder = builder.extern_function_suffix(suffix);
1131+
}
1132+
11091133
Ok((builder, output, verbose))
11101134
}

bindgen/codegen/mod.rs

Lines changed: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@ use crate::ir::derive::{
3232
};
3333
use crate::ir::dot;
3434
use crate::ir::enum_ty::{Enum, EnumVariant, EnumVariantValue};
35-
use crate::ir::function::{
36-
Abi, ClangAbi, Function, FunctionKind, FunctionSig, Linkage,
37-
};
35+
use crate::ir::function::{Abi, ClangAbi, Function, FunctionKind, FunctionSig};
3836
use crate::ir::int::IntKind;
3937
use crate::ir::item::{IsOpaque, Item, ItemCanonicalName, ItemCanonicalPath};
4038
use crate::ir::item_kind::ItemKind;
@@ -4043,9 +4041,8 @@ impl CodeGenerator for Function {
40434041

40444042
// We can't currently do anything with Internal functions so just
40454043
// avoid generating anything for them.
4046-
match self.linkage() {
4047-
Linkage::Internal => return None,
4048-
Linkage::External => {}
4044+
if self.is_inlined() {
4045+
return None;
40494046
}
40504047

40514048
// Pure virtual methods have no actual symbol, so we can't generate
@@ -4148,13 +4145,14 @@ impl CodeGenerator for Function {
41484145
abi => abi,
41494146
};
41504147

4151-
// Handle overloaded functions by giving each overload its own unique
4148+
// Handle overloaded functions by giving each overload its own uniq_ue
41524149
// suffix.
41534150
let times_seen = result.overload_number(&canonical_name);
41544151
if times_seen > 0 {
41554152
write!(&mut canonical_name, "{}", times_seen).unwrap();
41564153
}
41574154

4155+
let mut has_link_name_attr = false;
41584156
let link_name = mangled_name.unwrap_or(name);
41594157
if !is_dynamic_function &&
41604158
!utils::names_will_be_identical_after_mangling(
@@ -4164,6 +4162,7 @@ impl CodeGenerator for Function {
41644162
)
41654163
{
41664164
attributes.push(attributes::link_name(link_name));
4165+
has_link_name_attr = true;
41674166
}
41684167

41694168
// Unfortunately this can't piggyback on the `attributes` list because
@@ -4174,6 +4173,18 @@ impl CodeGenerator for Function {
41744173
quote! { #[link(wasm_import_module = #name)] }
41754174
});
41764175

4176+
if let Some(name) = canonical_name.strip_suffix(
4177+
ctx.options()
4178+
.extern_function_suffix
4179+
.as_deref()
4180+
.unwrap_or(crate::DEFAULT_EXTERN_FUNCTION_SUFFIX),
4181+
) {
4182+
if !has_link_name_attr {
4183+
attributes.push(attributes::link_name(&canonical_name));
4184+
}
4185+
canonical_name = name.to_owned();
4186+
}
4187+
41774188
let ident = ctx.rust_ident(canonical_name);
41784189
let tokens = quote! {
41794190
#wasm_link_attribute

bindgen/ir/context.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ use super::int::IntKind;
1616
use super::item::{IsOpaque, Item, ItemAncestors, ItemSet};
1717
use super::item_kind::ItemKind;
1818
use super::module::{Module, ModuleKind};
19+
use super::serialize::CItem;
1920
use super::template::{TemplateInstantiation, TemplateParameters};
2021
use super::traversal::{self, Edge, ItemTraversal};
2122
use super::ty::{FloatKind, Type, TypeKind};
@@ -461,6 +462,9 @@ pub struct BindgenContext {
461462

462463
/// The set of warnings raised during binding generation.
463464
warnings: Vec<String>,
465+
466+
/// C items that need to be serialized to an extra header file.
467+
pub(crate) c_items: Vec<CItem>,
464468
}
465469

466470
/// A traversal of allowlisted items.
@@ -576,6 +580,7 @@ If you encounter an error missing from this list, please file an issue or a PR!"
576580
has_type_param_in_array: None,
577581
has_float: None,
578582
warnings: Vec::new(),
583+
c_items: Vec::new(),
579584
}
580585
}
581586

bindgen/ir/function.rs

Lines changed: 29 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use super::item::Item;
77
use super::traversal::{EdgeKind, Trace, Tracer};
88
use super::ty::TypeKind;
99
use crate::clang::{self, Attribute};
10+
use crate::ir::serialize::CItem;
1011
use crate::parse::{
1112
ClangItemParser, ClangSubItemParser, ParseError, ParseResult,
1213
};
@@ -95,6 +96,9 @@ pub struct Function {
9596

9697
/// The linkage of the function.
9798
linkage: Linkage,
99+
100+
/// Whether this function is inlined or not
101+
is_inlined: bool,
98102
}
99103

100104
impl Function {
@@ -106,6 +110,7 @@ impl Function {
106110
comment: Option<String>,
107111
kind: FunctionKind,
108112
linkage: Linkage,
113+
is_inlined: bool,
109114
) -> Self {
110115
Function {
111116
name,
@@ -114,6 +119,7 @@ impl Function {
114119
comment,
115120
kind,
116121
linkage,
122+
is_inlined,
117123
}
118124
}
119125

@@ -146,6 +152,10 @@ impl Function {
146152
pub fn linkage(&self) -> Linkage {
147153
self.linkage
148154
}
155+
156+
pub fn is_inlined(&self) -> bool {
157+
self.is_inlined
158+
}
149159
}
150160

151161
impl DotAttributes for Function {
@@ -675,7 +685,9 @@ impl ClangSubItemParser for Function {
675685
return Err(ParseError::Continue);
676686
}
677687

678-
if cursor.is_inlined_function() {
688+
let is_inlined = cursor.is_inlined_function();
689+
690+
if is_inlined {
679691
if !context.options().generate_inline_functions {
680692
return Err(ParseError::Continue);
681693
}
@@ -721,8 +733,22 @@ impl ClangSubItemParser for Function {
721733
let mangled_name = cursor_mangling(context, &cursor);
722734
let comment = cursor.raw_comment();
723735

724-
let function =
725-
Self::new(name, mangled_name, sig, comment, kind, linkage);
736+
let function = Self::new(
737+
name,
738+
mangled_name,
739+
sig,
740+
comment,
741+
kind,
742+
linkage,
743+
is_inlined,
744+
);
745+
746+
if is_inlined {
747+
context
748+
.c_items
749+
.push(CItem::from_function(&function, context));
750+
}
751+
726752
Ok(ParseResult::New(function, Some(cursor)))
727753
}
728754
}

bindgen/ir/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ pub mod item_kind;
1818
pub mod layout;
1919
pub mod module;
2020
pub mod objc;
21+
pub(crate) mod serialize;
2122
pub mod template;
2223
pub mod traversal;
2324
pub mod ty;

0 commit comments

Comments
 (0)