Skip to content

Commit 294fe03

Browse files
committed
Extremely basic Vtable generation
1 parent bcbd72d commit 294fe03

File tree

3 files changed

+207
-8
lines changed

3 files changed

+207
-8
lines changed

src/codegen/mod.rs

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1049,15 +1049,65 @@ impl<'a> CodeGenerator for Vtable<'a> {
10491049
) {
10501050
assert_eq!(item.id(), self.item_id);
10511051
debug_assert!(item.is_enabled_for_codegen(ctx));
1052-
1053-
// For now, generate an empty struct, later we should generate function
1054-
// pointers and whatnot.
10551052
let name = ctx.rust_ident(&self.canonical_name(ctx));
1056-
let void = helpers::ast_ty::c_void(ctx);
1057-
result.push(quote! {
1058-
#[repr(C)]
1059-
pub struct #name ( #void );
1060-
});
1053+
1054+
// For now, we will only generate vtables for classes that do not inherit from others.
1055+
if self.base_classes.is_empty() {
1056+
let methods = self
1057+
.methods
1058+
.iter()
1059+
.filter_map(|m| {
1060+
if !m.is_virtual() {
1061+
return None;
1062+
}
1063+
1064+
let function_item = ctx.resolve_item(m.signature());
1065+
if !function_item.process_before_codegen(ctx, result) {
1066+
return None;
1067+
}
1068+
1069+
let function = function_item.expect_function();
1070+
let signature_item = ctx.resolve_item(function.signature());
1071+
let signature = match signature_item.expect_type().kind() {
1072+
TypeKind::Function(ref sig) => sig,
1073+
_ => panic!("Function signature type mismatch"),
1074+
};
1075+
1076+
// FIXME: Is there a canonical name without the class prepended?
1077+
let function_name = function_item.canonical_name(ctx);
1078+
1079+
// FIXME: Need to account for overloading with times_seen (separately from regular function path).
1080+
let function_name = ctx.rust_ident(function_name);
1081+
let mut args = utils::fnsig_arguments(ctx, signature);
1082+
let ret = utils::fnsig_return_ty(ctx, signature);
1083+
1084+
args[0] = if m.is_const() {
1085+
quote! { &self }
1086+
} else {
1087+
quote! { &mut self }
1088+
};
1089+
1090+
Some(quote! {
1091+
#function_name : fn( #( #args ),* ) #ret
1092+
})
1093+
})
1094+
.collect::<Vec<_>>();
1095+
1096+
result.push(quote! {
1097+
#[repr(C)]
1098+
pub struct #name {
1099+
#( #methods ),*
1100+
}
1101+
})
1102+
} else {
1103+
// For the cases we don't support, simply generate an empty struct.
1104+
let void = helpers::ast_ty::c_void(ctx);
1105+
1106+
result.push(quote! {
1107+
#[repr(C)]
1108+
pub struct #name ( #void );
1109+
});
1110+
}
10611111
}
10621112
}
10631113

Lines changed: 125 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,125 @@
1+
#![allow(
2+
dead_code,
3+
non_snake_case,
4+
non_camel_case_types,
5+
non_upper_case_globals
6+
)]
7+
8+
#[repr(C)]
9+
pub struct PureVirtualIFace__bindgen_vtable {
10+
PureVirtualIFace_Foo: fn(&mut self),
11+
PureVirtualIFace_Bar: fn(&mut self, arg1: ::std::os::raw::c_uint),
12+
}
13+
#[repr(C)]
14+
#[derive(Debug, Copy, Clone)]
15+
pub struct PureVirtualIFace {
16+
pub vtable_: *const PureVirtualIFace__bindgen_vtable,
17+
}
18+
#[test]
19+
fn bindgen_test_layout_PureVirtualIFace() {
20+
assert_eq!(
21+
::std::mem::size_of::<PureVirtualIFace>(),
22+
8usize,
23+
concat!("Size of: ", stringify!(PureVirtualIFace))
24+
);
25+
assert_eq!(
26+
::std::mem::align_of::<PureVirtualIFace>(),
27+
8usize,
28+
concat!("Alignment of ", stringify!(PureVirtualIFace))
29+
);
30+
}
31+
impl Default for PureVirtualIFace {
32+
fn default() -> Self {
33+
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
34+
unsafe {
35+
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
36+
s.assume_init()
37+
}
38+
}
39+
}
40+
#[repr(C)]
41+
pub struct AnotherInterface__bindgen_vtable {
42+
AnotherInterface_Baz: fn(&mut self),
43+
}
44+
#[repr(C)]
45+
#[derive(Debug, Copy, Clone)]
46+
pub struct AnotherInterface {
47+
pub vtable_: *const AnotherInterface__bindgen_vtable,
48+
}
49+
#[test]
50+
fn bindgen_test_layout_AnotherInterface() {
51+
assert_eq!(
52+
::std::mem::size_of::<AnotherInterface>(),
53+
8usize,
54+
concat!("Size of: ", stringify!(AnotherInterface))
55+
);
56+
assert_eq!(
57+
::std::mem::align_of::<AnotherInterface>(),
58+
8usize,
59+
concat!("Alignment of ", stringify!(AnotherInterface))
60+
);
61+
}
62+
impl Default for AnotherInterface {
63+
fn default() -> Self {
64+
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
65+
unsafe {
66+
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
67+
s.assume_init()
68+
}
69+
}
70+
}
71+
#[repr(C)]
72+
#[derive(Debug, Copy, Clone)]
73+
pub struct Implementation {
74+
pub _base: PureVirtualIFace,
75+
}
76+
#[test]
77+
fn bindgen_test_layout_Implementation() {
78+
assert_eq!(
79+
::std::mem::size_of::<Implementation>(),
80+
8usize,
81+
concat!("Size of: ", stringify!(Implementation))
82+
);
83+
assert_eq!(
84+
::std::mem::align_of::<Implementation>(),
85+
8usize,
86+
concat!("Alignment of ", stringify!(Implementation))
87+
);
88+
}
89+
impl Default for Implementation {
90+
fn default() -> Self {
91+
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
92+
unsafe {
93+
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
94+
s.assume_init()
95+
}
96+
}
97+
}
98+
#[repr(C)]
99+
#[derive(Debug, Copy, Clone)]
100+
pub struct DoubleImpl {
101+
pub _base: PureVirtualIFace,
102+
pub _base_1: AnotherInterface,
103+
}
104+
#[test]
105+
fn bindgen_test_layout_DoubleImpl() {
106+
assert_eq!(
107+
::std::mem::size_of::<DoubleImpl>(),
108+
16usize,
109+
concat!("Size of: ", stringify!(DoubleImpl))
110+
);
111+
assert_eq!(
112+
::std::mem::align_of::<DoubleImpl>(),
113+
8usize,
114+
concat!("Alignment of ", stringify!(DoubleImpl))
115+
);
116+
}
117+
impl Default for DoubleImpl {
118+
fn default() -> Self {
119+
let mut s = ::std::mem::MaybeUninit::<Self>::uninit();
120+
unsafe {
121+
::std::ptr::write_bytes(s.as_mut_ptr(), 0, 1);
122+
s.assume_init()
123+
}
124+
}
125+
}

tests/headers/virtual_interface.hpp

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
class PureVirtualIFace {
2+
public:
3+
virtual void Foo() = 0;
4+
virtual void Bar(unsigned int) = 0;
5+
};
6+
7+
class AnotherInterface {
8+
public:
9+
virtual void Baz() = 0;
10+
};
11+
12+
class Implementation : public PureVirtualIFace {
13+
public:
14+
void Foo() override {}
15+
void Bar(unsigned int) override {}
16+
};
17+
18+
class DoubleImpl : public PureVirtualIFace, public AnotherInterface {
19+
public:
20+
void Foo() override {}
21+
void Bar(unsigned int) override {}
22+
23+
void Baz() override {}
24+
};

0 commit comments

Comments
 (0)