diff --git a/bindgen-cli/options.rs b/bindgen-cli/options.rs index 3d87fc1bc6..a0af03e7ff 100644 --- a/bindgen-cli/options.rs +++ b/bindgen-cli/options.rs @@ -336,7 +336,7 @@ struct BindgenCommand { /// Deduplicates extern blocks. #[arg(long)] merge_extern_blocks: bool, - /// Overrides the ABI of functions matching . The value must be of the shape = where can be one of C, stdcall, fastcall, thiscall, aapcs, win64 or C-unwind. + /// Overrides the ABI of functions matching . The value must be of the shape = where can be one of C, stdcall, efiapi, fastcall, thiscall, aapcs, win64 or C-unwind. #[arg(long, value_name = "OVERRIDE")] override_abi: Vec, /// Wrap unsafe operations in unsafe blocks. diff --git a/bindgen-tests/tests/expectations/tests/abi-override.rs b/bindgen-tests/tests/expectations/tests/abi-override.rs index 49693692e4..8f370cd7b2 100644 --- a/bindgen-tests/tests/expectations/tests/abi-override.rs +++ b/bindgen-tests/tests/expectations/tests/abi-override.rs @@ -14,3 +14,5 @@ extern "stdcall" { extern "C" { pub fn baz(); } +pub type boo = ::std::option::Option; +pub type foobar = ::std::option::Option; diff --git a/bindgen-tests/tests/headers/abi-override.h b/bindgen-tests/tests/headers/abi-override.h index cee72caeef..bbfe82c2f9 100644 --- a/bindgen-tests/tests/headers/abi-override.h +++ b/bindgen-tests/tests/headers/abi-override.h @@ -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); diff --git a/bindgen/codegen/mod.rs b/bindgen/codegen/mod.rs index 1c54eb8ff0..11e49b8d75 100644 --- a/bindgen/codegen/mod.rs +++ b/bindgen/codegen/mod.rs @@ -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, }; @@ -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 => { @@ -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 }), } @@ -4243,6 +4251,17 @@ impl CodeGenerator for Function { ); return None; } + ClangAbi::Known(Abi::EfiApi) + if !ctx.options().rust_features().abi_efiapi => + { + unsupported_abi_diagnostic::( + name, + item.location(), + "efiapi", + ctx, + ); + return None; + } ClangAbi::Known(Abi::Win64) if signature.is_variadic() => { unsupported_abi_diagnostic::( name, diff --git a/bindgen/features.rs b/bindgen/features.rs index ef44571a39..fe6f415887 100644 --- a/bindgen/features.rs +++ b/bindgen/features.rs @@ -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) @@ -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 { @@ -241,6 +244,9 @@ rust_feature_def!( Stable_1_64 { => core_ffi_c; } + Stable_1_68 { + => abi_efiapi; + } Nightly { => thiscall_abi; => vectorcall_abi; diff --git a/bindgen/ir/function.rs b/bindgen/ir/function.rs index bb2303fad6..bfcc1694fb 100644 --- a/bindgen/ir/function.rs +++ b/bindgen/ir/function.rs @@ -176,6 +176,8 @@ pub enum Abi { C, /// The "stdcall" ABI. Stdcall, + /// The "efiapi" ABI. + EfiApi, /// The "fastcall" ABI. Fastcall, /// The "thiscall" ABI. @@ -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), @@ -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", @@ -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, @@ -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(), @@ -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 }