diff options
author | Dr. Chat <arkolbed@gmail.com> | 2021-12-24 14:12:13 -0600 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2022-01-29 11:29:00 +0100 |
commit | e755ea4a6d9aee386223a027f2d251b836275515 (patch) | |
tree | 5f952f0b6e4b4595c5d6d715823adc1d523c8663 /src/codegen/mod.rs | |
parent | e24afad6a16b0940baadebc937be9461fdccdc0f (diff) |
Extremely basic Vtable generation
Diffstat (limited to 'src/codegen/mod.rs')
-rw-r--r-- | src/codegen/mod.rs | 66 |
1 files changed, 58 insertions, 8 deletions
diff --git a/src/codegen/mod.rs b/src/codegen/mod.rs index bee299ed..7b72722a 100644 --- a/src/codegen/mod.rs +++ b/src/codegen/mod.rs @@ -1049,15 +1049,65 @@ impl<'a> CodeGenerator for Vtable<'a> { ) { assert_eq!(item.id(), self.item_id); debug_assert!(item.is_enabled_for_codegen(ctx)); - - // For now, generate an empty struct, later we should generate function - // pointers and whatnot. let name = ctx.rust_ident(&self.canonical_name(ctx)); - let void = helpers::ast_ty::c_void(ctx); - result.push(quote! { - #[repr(C)] - pub struct #name ( #void ); - }); + + // For now, we will only generate vtables for classes that do not inherit from others. + if self.base_classes.is_empty() { + let methods = self + .methods + .iter() + .filter_map(|m| { + if !m.is_virtual() { + return None; + } + + let function_item = ctx.resolve_item(m.signature()); + if !function_item.process_before_codegen(ctx, result) { + return None; + } + + let function = function_item.expect_function(); + let signature_item = ctx.resolve_item(function.signature()); + let signature = match signature_item.expect_type().kind() { + TypeKind::Function(ref sig) => sig, + _ => panic!("Function signature type mismatch"), + }; + + // FIXME: Is there a canonical name without the class prepended? + let function_name = function_item.canonical_name(ctx); + + // FIXME: Need to account for overloading with times_seen (separately from regular function path). + let function_name = ctx.rust_ident(function_name); + let mut args = utils::fnsig_arguments(ctx, signature); + let ret = utils::fnsig_return_ty(ctx, signature); + + args[0] = if m.is_const() { + quote! { &self } + } else { + quote! { &mut self } + }; + + Some(quote! { + #function_name : fn( #( #args ),* ) #ret + }) + }) + .collect::<Vec<_>>(); + + result.push(quote! { + #[repr(C)] + pub struct #name { + #( #methods ),* + } + }) + } else { + // For the cases we don't support, simply generate an empty struct. + let void = helpers::ast_ty::c_void(ctx); + + result.push(quote! { + #[repr(C)] + pub struct #name ( #void ); + }); + } } } |