Skip to content

Commit

Permalink
Add support for the thiscall ABI
Browse files Browse the repository at this point in the history
  • Loading branch information
liranringel committed Oct 9, 2017
1 parent 745d606 commit 9b95ce6
Show file tree
Hide file tree
Showing 7 changed files with 117 additions and 3 deletions.
22 changes: 19 additions & 3 deletions src/codegen/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1945,6 +1945,10 @@ impl MethodCodegen for Method {
_ => panic!("How in the world?"),
};

if let (Abi::ThisCall, false) = (signature.abi(), ctx.options().rust_features().thiscall_abi()) {
return;
}

// Do not generate variadic methods, since rust does not allow
// implementing them, and we don't do a good job at it anyway.
if signature.is_variadic() {
Expand Down Expand Up @@ -3058,9 +3062,17 @@ impl TryToRustTy for FunctionSig {
let arguments = utils::fnsig_arguments(ctx, &self);
let abi = self.abi();

Ok(quote! {
unsafe extern #abi fn ( #( #arguments ),* ) #ret
})
match abi {
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi() => {
warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
Ok(quote::Tokens::new())
}
_ => {
Ok(quote! {
unsafe extern #abi fn ( #( #arguments ),* ) #ret
})
}
}
}
}

Expand Down Expand Up @@ -3132,6 +3144,10 @@ impl CodeGenerator for Function {
}

let abi = match signature.abi() {
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi() => {
warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
return;
}
Abi::Unknown(unknown_abi) => {
panic!(
"Invalid or unknown abi {:?} for function {:?} ({:?})",
Expand Down
3 changes: 3 additions & 0 deletions src/features.rs
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,8 @@ rust_feature_def!(
=> untagged_union;
/// Constant function ([RFC 911](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md))
=> const_fn;
/// `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
=> thiscall_abi;
);

impl From<RustTarget> for RustFeatures {
Expand All @@ -152,6 +154,7 @@ impl From<RustTarget> for RustFeatures {

if rust_target >= RustTarget::Nightly {
features.const_fn = true;
features.thiscall_abi = true;
}

features
Expand Down
4 changes: 4 additions & 0 deletions src/ir/function.rs
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,8 @@ pub enum Abi {
Stdcall,
/// The "fastcall" ABI.
Fastcall,
/// The "thiscall" ABI.
ThisCall,
/// The "aapcs" ABI.
Aapcs,
/// The "win64" ABI.
Expand All @@ -166,6 +168,7 @@ impl quote::ToTokens for Abi {
Abi::C => quote! { "C" },
Abi::Stdcall => quote! { "stdcall" },
Abi::Fastcall => quote! { "fastcall" },
Abi::ThisCall => quote! { "thiscall" },
Abi::Aapcs => quote! { "aapcs" },
Abi::Win64 => quote! { "win64" },
Abi::Unknown(cc) => panic!(
Expand Down Expand Up @@ -200,6 +203,7 @@ fn get_abi(cc: CXCallingConv) -> Abi {
CXCallingConv_C => Abi::C,
CXCallingConv_X86StdCall => Abi::Stdcall,
CXCallingConv_X86FastCall => Abi::Fastcall,
CXCallingConv_X86ThisCall => Abi::ThisCall,
CXCallingConv_AAPCS => Abi::Aapcs,
CXCallingConv_X86_64Win64 => Abi::Win64,
other => Abi::Unknown(other),
Expand Down
29 changes: 29 additions & 0 deletions tests/expectations/tests/win32-thiscall_1_0.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/* automatically generated by rust-bindgen */


#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]


#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct Foo {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_Foo() {
assert_eq!(
::std::mem::size_of::<Foo>(),
1usize,
concat!("Size of: ", stringify!(Foo))
);
assert_eq!(
::std::mem::align_of::<Foo>(),
1usize,
concat!("Alignment of ", stringify!(Foo))
);
}
impl Clone for Foo {
fn clone(&self) -> Self {
*self
}
}
48 changes: 48 additions & 0 deletions tests/expectations/tests/win32-thiscall_nightly.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
/* automatically generated by rust-bindgen */


#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
#![cfg(feature = "nightly")]
#![feature(abi_thiscall)]

#[repr(C)]
#[derive(Debug, Default, Copy)]
pub struct Foo {
pub _address: u8,
}
#[test]
fn bindgen_test_layout_Foo() {
assert_eq!(
::std::mem::size_of::<Foo>(),
1usize,
concat!("Size of: ", stringify!(Foo))
);
assert_eq!(
::std::mem::align_of::<Foo>(),
1usize,
concat!("Alignment of ", stringify!(Foo))
);
}
extern "thiscall" {
#[link_name = "\u{1}?test@Foo@@QAEXXZ"]
pub fn Foo_test(this: *mut Foo);
}
extern "thiscall" {
#[link_name = "\u{1}?test2@Foo@@QAEHH@Z"]
pub fn Foo_test2(this: *mut Foo, var: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
}
impl Clone for Foo {
fn clone(&self) -> Self {
*self
}
}
impl Foo {
#[inline]
pub unsafe fn test(&mut self) {
Foo_test(self)
}
#[inline]
pub unsafe fn test2(&mut self, var: ::std::os::raw::c_int) -> ::std::os::raw::c_int {
Foo_test2(self, var)
}
}
7 changes: 7 additions & 0 deletions tests/headers/win32-thiscall_1_0.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// bindgen-flags: --rust-target 1.0 -- --target=i686-pc-windows-msvc

class Foo {
public:
void test();
int test2(int var);
};
7 changes: 7 additions & 0 deletions tests/headers/win32-thiscall_nightly.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
// bindgen-flags: --rust-target nightly --raw-line '#![cfg(feature = "nightly")]' --raw-line '#![feature(abi_thiscall)]' -- --target=i686-pc-windows-msvc

class Foo {
public:
void test();
int test2(int var);
};

0 comments on commit 9b95ce6

Please sign in to comment.