Skip to content

Commit 9b95ce6

Browse files
committed
Add support for the thiscall ABI
1 parent 745d606 commit 9b95ce6

File tree

7 files changed

+117
-3
lines changed

7 files changed

+117
-3
lines changed

src/codegen/mod.rs

+19-3
Original file line numberDiff line numberDiff line change
@@ -1945,6 +1945,10 @@ impl MethodCodegen for Method {
19451945
_ => panic!("How in the world?"),
19461946
};
19471947

1948+
if let (Abi::ThisCall, false) = (signature.abi(), ctx.options().rust_features().thiscall_abi()) {
1949+
return;
1950+
}
1951+
19481952
// Do not generate variadic methods, since rust does not allow
19491953
// implementing them, and we don't do a good job at it anyway.
19501954
if signature.is_variadic() {
@@ -3058,9 +3062,17 @@ impl TryToRustTy for FunctionSig {
30583062
let arguments = utils::fnsig_arguments(ctx, &self);
30593063
let abi = self.abi();
30603064

3061-
Ok(quote! {
3062-
unsafe extern #abi fn ( #( #arguments ),* ) #ret
3063-
})
3065+
match abi {
3066+
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi() => {
3067+
warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
3068+
Ok(quote::Tokens::new())
3069+
}
3070+
_ => {
3071+
Ok(quote! {
3072+
unsafe extern #abi fn ( #( #arguments ),* ) #ret
3073+
})
3074+
}
3075+
}
30643076
}
30653077
}
30663078

@@ -3132,6 +3144,10 @@ impl CodeGenerator for Function {
31323144
}
31333145

31343146
let abi = match signature.abi() {
3147+
Abi::ThisCall if !ctx.options().rust_features().thiscall_abi() => {
3148+
warn!("Skipping function with thiscall ABI that isn't supported by the configured Rust target");
3149+
return;
3150+
}
31353151
Abi::Unknown(unknown_abi) => {
31363152
panic!(
31373153
"Invalid or unknown abi {:?} for function {:?} ({:?})",

src/features.rs

+3
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,8 @@ rust_feature_def!(
140140
=> untagged_union;
141141
/// Constant function ([RFC 911](https://github.com/rust-lang/rfcs/blob/master/text/0911-const-fn.md))
142142
=> const_fn;
143+
/// `thiscall` calling convention ([Tracking issue](https://github.com/rust-lang/rust/issues/42202))
144+
=> thiscall_abi;
143145
);
144146

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

153155
if rust_target >= RustTarget::Nightly {
154156
features.const_fn = true;
157+
features.thiscall_abi = true;
155158
}
156159

157160
features

src/ir/function.rs

+4
Original file line numberDiff line numberDiff line change
@@ -142,6 +142,8 @@ pub enum Abi {
142142
Stdcall,
143143
/// The "fastcall" ABI.
144144
Fastcall,
145+
/// The "thiscall" ABI.
146+
ThisCall,
145147
/// The "aapcs" ABI.
146148
Aapcs,
147149
/// The "win64" ABI.
@@ -166,6 +168,7 @@ impl quote::ToTokens for Abi {
166168
Abi::C => quote! { "C" },
167169
Abi::Stdcall => quote! { "stdcall" },
168170
Abi::Fastcall => quote! { "fastcall" },
171+
Abi::ThisCall => quote! { "thiscall" },
169172
Abi::Aapcs => quote! { "aapcs" },
170173
Abi::Win64 => quote! { "win64" },
171174
Abi::Unknown(cc) => panic!(
@@ -200,6 +203,7 @@ fn get_abi(cc: CXCallingConv) -> Abi {
200203
CXCallingConv_C => Abi::C,
201204
CXCallingConv_X86StdCall => Abi::Stdcall,
202205
CXCallingConv_X86FastCall => Abi::Fastcall,
206+
CXCallingConv_X86ThisCall => Abi::ThisCall,
203207
CXCallingConv_AAPCS => Abi::Aapcs,
204208
CXCallingConv_X86_64Win64 => Abi::Win64,
205209
other => Abi::Unknown(other),
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
5+
6+
7+
#[repr(C)]
8+
#[derive(Debug, Default, Copy)]
9+
pub struct Foo {
10+
pub _address: u8,
11+
}
12+
#[test]
13+
fn bindgen_test_layout_Foo() {
14+
assert_eq!(
15+
::std::mem::size_of::<Foo>(),
16+
1usize,
17+
concat!("Size of: ", stringify!(Foo))
18+
);
19+
assert_eq!(
20+
::std::mem::align_of::<Foo>(),
21+
1usize,
22+
concat!("Alignment of ", stringify!(Foo))
23+
);
24+
}
25+
impl Clone for Foo {
26+
fn clone(&self) -> Self {
27+
*self
28+
}
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
/* automatically generated by rust-bindgen */
2+
3+
4+
#![allow(dead_code, non_snake_case, non_camel_case_types, non_upper_case_globals)]
5+
#![cfg(feature = "nightly")]
6+
#![feature(abi_thiscall)]
7+
8+
#[repr(C)]
9+
#[derive(Debug, Default, Copy)]
10+
pub struct Foo {
11+
pub _address: u8,
12+
}
13+
#[test]
14+
fn bindgen_test_layout_Foo() {
15+
assert_eq!(
16+
::std::mem::size_of::<Foo>(),
17+
1usize,
18+
concat!("Size of: ", stringify!(Foo))
19+
);
20+
assert_eq!(
21+
::std::mem::align_of::<Foo>(),
22+
1usize,
23+
concat!("Alignment of ", stringify!(Foo))
24+
);
25+
}
26+
extern "thiscall" {
27+
#[link_name = "\u{1}?test@Foo@@QAEXXZ"]
28+
pub fn Foo_test(this: *mut Foo);
29+
}
30+
extern "thiscall" {
31+
#[link_name = "\u{1}?test2@Foo@@QAEHH@Z"]
32+
pub fn Foo_test2(this: *mut Foo, var: ::std::os::raw::c_int) -> ::std::os::raw::c_int;
33+
}
34+
impl Clone for Foo {
35+
fn clone(&self) -> Self {
36+
*self
37+
}
38+
}
39+
impl Foo {
40+
#[inline]
41+
pub unsafe fn test(&mut self) {
42+
Foo_test(self)
43+
}
44+
#[inline]
45+
pub unsafe fn test2(&mut self, var: ::std::os::raw::c_int) -> ::std::os::raw::c_int {
46+
Foo_test2(self, var)
47+
}
48+
}

tests/headers/win32-thiscall_1_0.hpp

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// bindgen-flags: --rust-target 1.0 -- --target=i686-pc-windows-msvc
2+
3+
class Foo {
4+
public:
5+
void test();
6+
int test2(int var);
7+
};
+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// bindgen-flags: --rust-target nightly --raw-line '#![cfg(feature = "nightly")]' --raw-line '#![feature(abi_thiscall)]' -- --target=i686-pc-windows-msvc
2+
3+
class Foo {
4+
public:
5+
void test();
6+
int test2(int var);
7+
};

0 commit comments

Comments
 (0)