Skip to content

Commit 9ea498d

Browse files
volsaghaith
authored andcommitted
refactor: Adjust VTable structure
1 parent e1fbef7 commit 9ea498d

File tree

3 files changed

+114
-37
lines changed

3 files changed

+114
-37
lines changed

compiler/plc_ast/src/ast.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ impl DataTypeDeclaration {
652652
}
653653
}
654654

655-
#[derive(PartialEq)]
655+
#[derive(PartialEq, Clone)]
656656
pub struct UserTypeDeclaration {
657657
pub data_type: DataType,
658658
pub initializer: Option<AstNode>,

compiler/plc_driver/src/pipelines/participant.rs

Lines changed: 104 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55
//!
66
77
use std::{
8-
collections::HashMap,
8+
collections::{HashMap, HashSet},
99
env, fs,
1010
path::{Path, PathBuf},
1111
sync::{Arc, Mutex, RwLock},
1212
};
1313

14-
use ast::ast::{DataType, DataTypeDeclaration, UserTypeDeclaration};
14+
use ast::ast::{DataType, DataTypeDeclaration, Identifier, UserTypeDeclaration};
1515
use ast::{ast::Variable, provider::IdProvider};
1616
use plc::{
1717
codegen::GeneratedModule,
18-
index::PouIndexEntry,
18+
index::{Index, PouIndexEntry},
1919
lowering::calls::AggregateTypeLowerer,
2020
output::FormatOption,
2121
typesystem::{VOID_INTERNAL_NAME, VOID_POINTER_TYPE},
@@ -300,48 +300,116 @@ impl VTableIndexer {
300300
format!("__vtable_{name}")
301301
}
302302

303-
fn create_vtable(
304-
name: &str,
305-
methods: Vec<&PouIndexEntry>,
306-
location: SourceLocation,
307-
) -> UserTypeDeclaration {
308-
let mut variables = Vec::new();
309-
for method in methods.iter() {
310-
let variable = Variable {
311-
name: method.get_name().to_string(),
312-
data_type_declaration: DataTypeDeclaration::Reference {
313-
referenced_type: VOID_POINTER_TYPE.into(),
314-
location: method.get_location().clone(),
315-
},
316-
initializer: None,
317-
address: None,
318-
location: method.get_location().clone(),
319-
};
320-
variables.push(variable);
303+
fn create_vtables_for_pous(index: &Index) -> HashMap<String, UserTypeDeclaration> {
304+
let mut vtables = HashMap::new();
305+
for pou in index.get_pous().values().filter(|pou| pou.is_function_block() || pou.is_class()) {
306+
let mut variables = Vec::new();
307+
308+
if let Some(parent) = pou.get_super_class() {
309+
variables.push(Variable {
310+
name: VTableIndexer::get_vtable_name(parent),
311+
data_type_declaration: DataTypeDeclaration::Reference {
312+
referenced_type: VTableIndexer::get_vtable_name(parent),
313+
location: SourceLocation::internal(),
314+
},
315+
initializer: None,
316+
address: None,
317+
location: SourceLocation::internal(),
318+
});
319+
}
320+
321+
for interface in pou.get_interfaces() {
322+
variables.push(Variable {
323+
name: VTableIndexer::get_vtable_name(interface),
324+
data_type_declaration: DataTypeDeclaration::Reference {
325+
referenced_type: VTableIndexer::get_vtable_name(interface),
326+
location: SourceLocation::internal(),
327+
},
328+
initializer: None,
329+
address: None,
330+
location: SourceLocation::internal(),
331+
});
332+
}
333+
334+
for method in index.get_methods_local(pou.get_name()) {
335+
variables.push(VTableIndexer::create_void_pointer(method.get_name()));
336+
}
337+
338+
vtables
339+
.insert(pou.get_name().to_string(), VTableIndexer::create_vtable(pou.get_name(), variables));
340+
}
341+
342+
vtables
343+
}
344+
345+
fn create_vtables_for_interfaces(index: &Index) -> HashMap<String, UserTypeDeclaration> {
346+
let mut vtables = HashMap::new();
347+
for interface in index.get_interfaces().values() {
348+
let mut variables = Vec::new();
349+
for Identifier { name, location } in &interface.extensions {
350+
variables.push(Variable {
351+
name: VTableIndexer::get_vtable_name(name),
352+
data_type_declaration: DataTypeDeclaration::Reference {
353+
referenced_type: VTableIndexer::get_vtable_name(name),
354+
location: location.clone(),
355+
},
356+
initializer: None,
357+
address: None,
358+
location: SourceLocation::internal(),
359+
});
360+
}
361+
362+
for method in interface.get_declared_methods(index) {
363+
variables.push(VTableIndexer::create_void_pointer(method.get_name()));
364+
}
365+
366+
vtables.insert(
367+
interface.get_name().to_string(),
368+
VTableIndexer::create_vtable(interface.get_name(), variables),
369+
);
370+
}
371+
372+
vtables
373+
}
374+
375+
/// Creates a void pointer variable with the given name and location
376+
fn create_void_pointer(name: &str) -> Variable {
377+
Variable {
378+
name: name.to_string(),
379+
data_type_declaration: DataTypeDeclaration::Reference {
380+
referenced_type: VOID_POINTER_TYPE.into(),
381+
location: SourceLocation::internal(),
382+
},
383+
initializer: None,
384+
address: None,
385+
location: SourceLocation::internal(),
386+
}
387+
}
388+
389+
/// Creates a vtable with the given member variables and a mangled name of the form `__vtable_<name>`
390+
fn create_vtable(name: &str, variables: Vec<Variable>) -> UserTypeDeclaration {
391+
UserTypeDeclaration {
392+
data_type: DataType::StructType { name: Some(Self::get_vtable_name(name)), variables },
393+
initializer: None,
394+
location: SourceLocation::internal(),
395+
scope: Some(name.to_string()),
321396
}
322-
let data_type = DataType::StructType { name: Some(Self::get_vtable_name(name)), variables };
323-
UserTypeDeclaration { data_type, initializer: None, location, scope: Some(name.to_string()) }
324397
}
325398
}
326399

327400
impl PipelineParticipantMut for VTableIndexer {
401+
// TODO: Don't track overridden methods in vtable, as they're part of the parent instance (same for interfaces)
328402
fn post_index(&mut self, indexed_project: IndexedProject) -> IndexedProject {
329-
//For each class or interface, create a vtable type
330-
//and add it to the index
331403
let IndexedProject { mut project, index, .. } = indexed_project;
332-
let mut vtables = Vec::new();
333-
for interface in index.get_interfaces().values() {
334-
let methods = interface.get_methods(&index);
335-
let vtable = Self::create_vtable(interface.get_name(), methods, interface.get_location().clone());
336-
vtables.push(vtable);
337-
}
338404

339-
for pou in index.get_pous().values().filter(|it| it.is_function_block() || it.is_class()) {
340-
let methods = index.get_methods(pou.get_name());
341-
let vtable = Self::create_vtable(pou.get_name(), methods, pou.get_location().clone());
342-
vtables.push(vtable);
405+
let vtables_pou = VTableIndexer::create_vtables_for_pous(&index);
406+
let vtables_intf = VTableIndexer::create_vtables_for_interfaces(&index);
407+
408+
if let Some(unit) = project.units.first_mut() {
409+
unit.user_types.extend(vtables_pou.into_iter().map(|(_, vtable)| vtable));
410+
unit.user_types.extend(vtables_intf.into_iter().map(|(_, vtable)| vtable));
343411
}
344-
project.units.first_mut().unwrap().user_types.extend(vtables);
412+
345413
project.index(self.id_provider.clone())
346414
}
347415
}

src/index.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2161,6 +2161,15 @@ impl Index {
21612161
self.get_methods_recursive(container, vec![], &mut FxHashSet::default())
21622162
}
21632163

2164+
/// Returns all methods directly declared on a container, not including inherited methods.
2165+
pub fn get_methods_local(&self, container: &str) -> Vec<&PouIndexEntry> {
2166+
self.get_pous()
2167+
.values()
2168+
.filter(|pou| pou.is_method())
2169+
.filter(|pou| pou.get_parent_pou_name().is_some_and(|opt| opt == container))
2170+
.collect()
2171+
}
2172+
21642173
fn get_methods_recursive<'b>(
21652174
&'b self,
21662175
container: &str,

0 commit comments

Comments
 (0)