Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for calling conventions #1999

Merged
merged 7 commits into from Sep 2, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/build.yml
Expand Up @@ -140,6 +140,7 @@ jobs:
cargo clippy -p test_arch_feature &&
cargo clippy -p test_bcrypt &&
cargo clippy -p test_bstr &&
cargo clippy -p test_calling_convention &&
cargo clippy -p test_cfg_generic &&
cargo clippy -p test_class_factory &&
cargo clippy -p test_component &&
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/test.yml
Expand Up @@ -123,6 +123,7 @@ jobs:
cargo test --target ${{ matrix.target }} -p test_arch_feature &&
cargo test --target ${{ matrix.target }} -p test_bcrypt &&
cargo test --target ${{ matrix.target }} -p test_bstr &&
cargo test --target ${{ matrix.target }} -p test_calling_convention &&
cargo test --target ${{ matrix.target }} -p test_cfg_generic &&
cargo test --target ${{ matrix.target }} -p test_class_factory &&
cargo test --target ${{ matrix.target }} -p test_component &&
Expand Down
39 changes: 29 additions & 10 deletions crates/libs/bindgen/src/functions.rs
Expand Up @@ -26,10 +26,15 @@ fn gen_sys_function(gen: &Gen, def: MethodDef) -> TokenStream {
quote! { #name: #tokens }
});

let calling_convention = calling_convention(gen, def);

quote! {
#doc
#features
pub fn #name(#(#params),*) #return_type;
#[cfg_attr(windows, link(name = "windows"))]
extern #calling_convention {
#doc
#features
pub fn #name(#(#params),*) #return_type;
}
}
}

Expand Down Expand Up @@ -64,6 +69,7 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
let cfg = gen.reader.signature_cfg(&signature);
let doc = gen.cfg_doc(&cfg);
let features = gen.cfg_features(&cfg);
let calling_convention = calling_convention(gen, def);

let kind = gen.reader.signature_kind(&signature);
match kind {
Expand All @@ -79,7 +85,7 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
#[inline]
pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<T> #where_clause {
#link_attr
extern "system" {
extern #calling_convention {
fn #name(#(#abi_params),*) #abi_return_type;
}
let mut result__ = ::core::option::Option::None;
Expand All @@ -99,7 +105,7 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
#[inline]
pub unsafe fn #name<#generics>(#params result__: *mut ::core::option::Option<T>) -> ::windows::core::Result<()> #where_clause {
#link_attr
extern "system" {
extern #calling_convention {
fn #name(#(#abi_params),*) #abi_return_type;
}
#name(#args).ok()
Expand All @@ -119,7 +125,7 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
#[inline]
pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<#return_type_tokens> #where_clause {
#link_attr
extern "system" {
extern #calling_convention {
fn #name(#(#abi_params),*) #abi_return_type;
}
let mut result__ = ::core::mem::MaybeUninit::zeroed();
Expand All @@ -137,7 +143,7 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
#[inline]
pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<()> #where_clause {
#link_attr
extern "system" {
extern #calling_convention {
fn #name(#(#abi_params),*) #abi_return_type;
}
#name(#args).ok()
Expand All @@ -156,7 +162,7 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
#[inline]
pub unsafe fn #name<#generics>(#params) -> ::windows::core::Result<#return_type> #where_clause {
#link_attr
extern "system" {
extern #calling_convention {
fn #name(#(#abi_params),*) -> #return_type;
}
let result__ = #name(#args);
Expand All @@ -173,7 +179,7 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
#[inline]
pub unsafe fn #name<#generics>(#params) #abi_return_type #where_clause {
#link_attr
extern "system" {
extern #calling_convention {
fn #name(#(#abi_params),*) #abi_return_type;
}
#name(#args)
Expand All @@ -192,7 +198,7 @@ fn gen_win_function(gen: &Gen, def: MethodDef) -> TokenStream {
#[inline]
pub unsafe fn #name<#generics>(#params) #does_not_return #where_clause {
#link_attr
extern "system" {
extern #calling_convention {
fn #name(#(#abi_params),*) #does_not_return;
}
#name(#args)
Expand Down Expand Up @@ -227,3 +233,16 @@ fn handle_last_error(gen: &Gen, def: MethodDef, signature: &Signature) -> bool {
}
false
}

fn calling_convention(gen: &Gen, def: MethodDef) -> &'static str {
let impl_map = gen.reader.method_def_impl_map(def).expect("ImplMap not found");
let flags = gen.reader.impl_map_flags(impl_map);

if flags.conv_platform() {
"system"
} else if flags.conv_cdecl() {
"cdecl"
} else {
unimplemented!()
}
}
5 changes: 1 addition & 4 deletions crates/libs/bindgen/src/lib.rs
Expand Up @@ -80,10 +80,7 @@ pub fn namespace(gen: &Gen, tree: &Tree) -> String {
if !methods.is_empty() {
let methods = methods.values();
functions = vec![quote! {
#[cfg_attr(windows, link(name = "windows"))]
extern "system" {
#(#methods)*
}
#(#methods)*
}];
}
}
Expand Down
15 changes: 15 additions & 0 deletions crates/libs/metadata/src/flags.rs
Expand Up @@ -52,6 +52,21 @@ impl PInvokeAttributes {
pub fn last_error(&self) -> bool {
self.0 & 0x40 != 0
}
pub fn conv_platform(&self) -> bool {
self.0 & 0x100 != 0
}
pub fn conv_cdecl(&self) -> bool {
self.0 & 0x200 != 0
}
pub fn conv_stdcall(&self) -> bool {
self.0 & 0x300 != 0
}
pub fn conv_thiscall(&self) -> bool {
self.0 & 0x400 != 0
}
pub fn conv_fastcall(&self) -> bool {
self.0 & 0x500 != 0
}
}

impl TypeAttributes {
Expand Down
30 changes: 28 additions & 2 deletions crates/libs/metadata/src/reader/mod.rs
Expand Up @@ -595,20 +595,46 @@ impl<'a> Reader<'a> {
if self.type_def_flags(def).explicit_layout() {
self.type_def_fields(def).map(|field| self.type_size(&self.field_type(field, Some(def)))).max().unwrap_or(1)
} else {
self.type_def_fields(def).fold(0, |sum, field| sum + self.type_size(&self.field_type(field, Some(def))))
let mut sum = 0;
for field in self.type_def_fields(def) {
let size = self.type_size(&self.field_type(field, Some(def)));
let align = self.type_align(&self.field_type(field, Some(def)));
sum = (sum + (align - 1)) & !(align - 1);
sum += size;
}
sum
}
}
TypeKind::Enum => self.type_size(&self.type_def_underlying_type(def)),
_ => 4,
}
}
pub fn type_size(&self, ty: &Type) -> usize {
fn type_size(&self, ty: &Type) -> usize {
match ty {
Type::I8 | Type::U8 => 1,
Type::I16 | Type::U16 => 2,
Type::I64 | Type::U64 | Type::F64 => 8,
Type::GUID => 16,
Type::TypeDef((def, _)) => self.type_def_size(*def),
Type::Win32Array((ty, len)) => self.type_size(ty) * len,
_ => 4,
}
}
fn type_def_align(&self, def: TypeDef) -> usize {
match self.type_def_kind(def) {
TypeKind::Struct => self.type_def_fields(def).map(|field| self.type_align(&self.field_type(field, Some(def)))).max().unwrap_or(1),
TypeKind::Enum => self.type_align(&self.type_def_underlying_type(def)),
_ => 4,
}
}
fn type_align(&self, ty: &Type) -> usize {
match ty {
Type::I8 | Type::U8 => 1,
Type::I16 | Type::U16 => 2,
Type::I64 | Type::U64 | Type::F64 => 8,
Type::GUID => 4,
Type::TypeDef((def, _)) => self.type_def_align(*def),
Type::Win32Array((ty, len)) => self.type_align(ty) * len,
_ => 4,
}
}
Expand Down
Expand Up @@ -3,6 +3,9 @@ extern "system" {
#[doc = "*Required features: `\"Win32_AI_MachineLearning_DirectML\"`, `\"Win32_Graphics_Direct3D12\"`*"]
#[cfg(feature = "Win32_Graphics_Direct3D12")]
pub fn DMLCreateDevice(d3d12device: super::super::super::Graphics::Direct3D12::ID3D12Device, flags: DML_CREATE_DEVICE_FLAGS, riid: *const ::windows_sys::core::GUID, ppv: *mut *mut ::core::ffi::c_void) -> ::windows_sys::core::HRESULT;
}
#[cfg_attr(windows, link(name = "windows"))]
extern "system" {
#[doc = "*Required features: `\"Win32_AI_MachineLearning_DirectML\"`, `\"Win32_Graphics_Direct3D12\"`*"]
#[cfg(feature = "Win32_Graphics_Direct3D12")]
pub fn DMLCreateDevice1(d3d12device: super::super::super::Graphics::Direct3D12::ID3D12Device, flags: DML_CREATE_DEVICE_FLAGS, minimumfeaturelevel: DML_FEATURE_LEVEL, riid: *const ::windows_sys::core::GUID, ppv: *mut *mut ::core::ffi::c_void) -> ::windows_sys::core::HRESULT;
Expand Down
Expand Up @@ -2,6 +2,9 @@
extern "system" {
#[doc = "*Required features: `\"Win32_AI_MachineLearning_WinML\"`*"]
pub fn MLCreateOperatorRegistry(registry: *mut IMLOperatorRegistry) -> ::windows_sys::core::HRESULT;
}
#[cfg_attr(windows, link(name = "windows"))]
extern "system" {
#[doc = "*Required features: `\"Win32_AI_MachineLearning_WinML\"`*"]
pub fn WinMLCreateRuntime(runtime: *mut IWinMLRuntime) -> ::windows_sys::core::HRESULT;
}
Expand Down