summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/codegen/mod.rs22
-rw-r--r--src/features.rs3
-rw-r--r--src/ir/function.rs4
-rw-r--r--tests/expectations/tests/win32-thiscall_1_0.rs29
-rw-r--r--tests/expectations/tests/win32-thiscall_nightly.rs48
-rw-r--r--tests/headers/win32-thiscall_1_0.hpp7
-rw-r--r--tests/headers/win32-thiscall_nightly.hpp7
7 files changed, 117 insertions, 3 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs
index 94a62b97..6d8e8a9d 100644
--- a/src/codegen/mod.rs
+++ b/src/codegen/mod.rs
@@ -1959,6 +1959,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() {
@@ -3072,9 +3076,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
+ })
+ }
+ }
}
}
@@ -3146,6 +3158,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 {:?} ({:?})",
diff --git a/src/features.rs b/src/features.rs
index 29e60ab7..b89185fd 100644
--- a/src/features.rs
+++ b/src/features.rs
@@ -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 {
@@ -152,6 +154,7 @@ impl From<RustTarget> for RustFeatures {
if rust_target >= RustTarget::Nightly {
features.const_fn = true;
+ features.thiscall_abi = true;
}
features
diff --git a/src/ir/function.rs b/src/ir/function.rs
index b637f9f1..2eab6638 100644
--- a/src/ir/function.rs
+++ b/src/ir/function.rs
@@ -142,6 +142,8 @@ pub enum Abi {
Stdcall,
/// The "fastcall" ABI.
Fastcall,
+ /// The "thiscall" ABI.
+ ThisCall,
/// The "aapcs" ABI.
Aapcs,
/// The "win64" ABI.
@@ -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!(
@@ -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),
diff --git a/tests/expectations/tests/win32-thiscall_1_0.rs b/tests/expectations/tests/win32-thiscall_1_0.rs
new file mode 100644
index 00000000..f84a7005
--- /dev/null
+++ b/tests/expectations/tests/win32-thiscall_1_0.rs
@@ -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
+ }
+}
diff --git a/tests/expectations/tests/win32-thiscall_nightly.rs b/tests/expectations/tests/win32-thiscall_nightly.rs
new file mode 100644
index 00000000..0fd1c00d
--- /dev/null
+++ b/tests/expectations/tests/win32-thiscall_nightly.rs
@@ -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)
+ }
+}
diff --git a/tests/headers/win32-thiscall_1_0.hpp b/tests/headers/win32-thiscall_1_0.hpp
new file mode 100644
index 00000000..5907c76e
--- /dev/null
+++ b/tests/headers/win32-thiscall_1_0.hpp
@@ -0,0 +1,7 @@
+// bindgen-flags: --rust-target 1.0 -- --target=i686-pc-windows-msvc
+
+class Foo {
+ public:
+ void test();
+ int test2(int var);
+};
diff --git a/tests/headers/win32-thiscall_nightly.hpp b/tests/headers/win32-thiscall_nightly.hpp
new file mode 100644
index 00000000..2c9f2f17
--- /dev/null
+++ b/tests/headers/win32-thiscall_nightly.hpp
@@ -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);
+};