Skip to content

Commit

Permalink
Add support for the "efiapi" ABI. (#2481)
Browse files Browse the repository at this point in the history
This allows for use of `extern "efiapi" ...`
which is now stable since the following commit:
`https://github.com/rust-lang/rust/commit/46f9e878f68e6ece9e8dad54c67e97e5dd5838e1`
  • Loading branch information
JohnBobbo96 authored Apr 10, 2023
1 parent dcc21c1 commit 594eb7b
Show file tree
Hide file tree
Showing 6 changed files with 52 additions and 7 deletions.
2 changes: 1 addition & 1 deletion bindgen-cli/options.rs
Original file line number Diff line number Diff line change
Expand Up @@ -336,7 +336,7 @@ struct BindgenCommand {
/// Deduplicates extern blocks.
#[arg(long)]
merge_extern_blocks: bool,
/// Overrides the ABI of functions matching <regex>. The <OVERRIDE> value must be of the shape <REGEX>=<ABI> where <ABI> can be one of C, stdcall, fastcall, thiscall, aapcs, win64 or C-unwind.
/// Overrides the ABI of functions matching <regex>. The <OVERRIDE> value must be of the shape <REGEX>=<ABI> where <ABI> can be one of C, stdcall, efiapi, fastcall, thiscall, aapcs, win64 or C-unwind.
#[arg(long, value_name = "OVERRIDE")]
override_abi: Vec<String>,
/// Wrap unsafe operations in unsafe blocks.
Expand Down
2 changes: 2 additions & 0 deletions bindgen-tests/tests/expectations/tests/abi-override.rs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion bindgen-tests/tests/headers/abi-override.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
// bindgen-flags: --override-abi=foo=fastcall --override-abi=bar=stdcall
// bindgen-flags: --override-abi=foo=fastcall --override-abi=bar=stdcall --override-abi=boo=efiapi --override-abi=foobar=efiapi

void foo();
void bar();
void baz();

typedef void (*boo)();
typedef void (*foobar)(boo boo);
25 changes: 22 additions & 3 deletions bindgen/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2566,6 +2566,9 @@ impl Method {
ClangAbi::Known(Abi::CUnwind) => {
ctx.options().rust_features().c_unwind_abi
}
ClangAbi::Known(Abi::EfiApi) => {
ctx.options().rust_features().abi_efiapi
}
_ => true,
};

Expand Down Expand Up @@ -4089,9 +4092,8 @@ impl TryToRustTy for FunctionSig {
// TODO: we might want to consider ignoring the reference return value.
let ret = utils::fnsig_return_ty(ctx, self);
let arguments = utils::fnsig_arguments(ctx, self);
let abi = self.abi(ctx, None);

match abi {
match self.abi(ctx, None) {
ClangAbi::Known(Abi::ThisCall)
if !ctx.options().rust_features().thiscall_abi =>
{
Expand All @@ -4110,7 +4112,13 @@ impl TryToRustTy for FunctionSig {
warn!("Skipping function with C-unwind ABI that isn't supported by the configured Rust target");
Ok(proc_macro2::TokenStream::new())
}
_ => Ok(quote! {
ClangAbi::Known(Abi::EfiApi)
if !ctx.options().rust_features().abi_efiapi =>
{
warn!("Skipping function with efiapi ABI that isn't supported by the configured Rust target");
Ok(proc_macro2::TokenStream::new())
}
abi => Ok(quote! {
unsafe extern #abi fn ( #( #arguments ),* ) #ret
}),
}
Expand Down Expand Up @@ -4243,6 +4251,17 @@ impl CodeGenerator for Function {
);
return None;
}
ClangAbi::Known(Abi::EfiApi)
if !ctx.options().rust_features().abi_efiapi =>
{
unsupported_abi_diagnostic::<true>(
name,
item.location(),
"efiapi",
ctx,
);
return None;
}
ClangAbi::Known(Abi::Win64) if signature.is_variadic() => {
unsupported_abi_diagnostic::<true>(
name,
Expand Down
8 changes: 7 additions & 1 deletion bindgen/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,9 @@ macro_rules! rust_target_base {
/// Rust stable 1.64
/// * `core_ffi_c` ([Tracking issue](https://github.com/rust-lang/rust/issues/94501))
=> Stable_1_64 => 1.64;
/// Rust stable 1.68
/// * `abi_efiapi` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/65815))
=> Stable_1_68 => 1.68;
/// Nightly rust
/// * `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
/// * `vectorcall` calling convention (no tracking issue)
Expand All @@ -144,7 +147,7 @@ rust_target_base!(rust_target_def);
rust_target_base!(rust_target_values_def);

/// Latest stable release of Rust
pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_64;
pub const LATEST_STABLE_RUST: RustTarget = RustTarget::Stable_1_68;

/// Create RustFeatures struct definition, new(), and a getter for each field
macro_rules! rust_feature_def {
Expand Down Expand Up @@ -241,6 +244,9 @@ rust_feature_def!(
Stable_1_64 {
=> core_ffi_c;
}
Stable_1_68 {
=> abi_efiapi;
}
Nightly {
=> thiscall_abi;
=> vectorcall_abi;
Expand Down
17 changes: 16 additions & 1 deletion bindgen/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,8 @@ pub enum Abi {
C,
/// The "stdcall" ABI.
Stdcall,
/// The "efiapi" ABI.
EfiApi,
/// The "fastcall" ABI.
Fastcall,
/// The "thiscall" ABI.
Expand All @@ -197,6 +199,7 @@ impl FromStr for Abi {
match s {
"C" => Ok(Self::C),
"stdcall" => Ok(Self::Stdcall),
"efiapi" => Ok(Self::EfiApi),
"fastcall" => Ok(Self::Fastcall),
"thiscall" => Ok(Self::ThisCall),
"vectorcall" => Ok(Self::Vectorcall),
Expand All @@ -213,6 +216,7 @@ impl std::fmt::Display for Abi {
let s = match *self {
Self::C => "C",
Self::Stdcall => "stdcall",
Self::EfiApi => "efiapi",
Self::Fastcall => "fastcall",
Self::ThisCall => "thiscall",
Self::Vectorcall => "vectorcall",
Expand Down Expand Up @@ -263,6 +267,9 @@ impl quote::ToTokens for ClangAbi {
/// A function signature.
#[derive(Debug)]
pub(crate) struct FunctionSig {
/// The name of this function signature.
name: String,

/// The return type of the function.
return_type: TypeId,

Expand Down Expand Up @@ -572,7 +579,8 @@ impl FunctionSig {
warn!("Unknown calling convention: {:?}", call_conv);
}

Ok(FunctionSig {
Ok(Self {
name: spelling,
return_type: ret,
argument_types: args,
is_variadic: ty.is_variadic(),
Expand Down Expand Up @@ -611,6 +619,13 @@ impl FunctionSig {
} else {
self.abi
}
} else if let Some((abi, _)) = ctx
.options()
.abi_overrides
.iter()
.find(|(_, regex_set)| regex_set.matches(&self.name))
{
ClangAbi::Known(*abi)
} else {
self.abi
}
Expand Down

0 comments on commit 594eb7b

Please sign in to comment.