Skip to content

Commit cb65351

Browse files
committed
refactor: self-review
1 parent 6cba4ce commit cb65351

File tree

10 files changed

+281
-257
lines changed

10 files changed

+281
-257
lines changed

compiler/plc_ast/src/ast.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1485,7 +1485,8 @@ impl AstNode {
14851485
matches!(self.stmt, AstStatement::Literal(AstLiteral::Real(_), ..))
14861486
}
14871487

1488-
pub fn get_name_of_lhs_of_assignment(&self) -> Option<&str> {
1488+
/// Returns the identifier of the left-hand side if this is an assignment statement
1489+
pub fn get_assignment_identifier(&self) -> Option<&str> {
14891490
match &self.stmt {
14901491
AstStatement::Assignment(Assignment { left, .. })
14911492
| AstStatement::OutputAssignment(Assignment { left, .. })

src/builtins.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -672,7 +672,7 @@ fn annotate_comparison_function(
672672
.has_nature(TypeNature::Elementary, annotator.index)
673673
}) {
674674
// we are trying to call this function with a non-elementary type, so we redirect back to the resolver
675-
annotator.annotate_call_statement(operator, Some(parameters), &ctx);
675+
annotator.annotate_arguments(operator, parameters, &ctx);
676676
return;
677677
}
678678

@@ -741,7 +741,7 @@ fn annotate_arithmetic_function(
741741
.has_nature(TypeNature::Num, annotator.index)
742742
}) {
743743
// we are trying to call this function with a non-numerical type, so we redirect back to the resolver
744-
annotator.annotate_call_statement(operator, Some(parameters), &ctx);
744+
annotator.annotate_arguments(operator, parameters, &ctx);
745745
return;
746746
}
747747

src/codegen/generators/expression_generator.rs

Lines changed: 49 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -68,15 +68,25 @@ pub struct ExpressionCodeGenerator<'a, 'b> {
6868
/// context information to generate a parameter
6969
#[derive(Debug)]
7070
struct CallParameterAssignment<'a, 'b> {
71-
/// the assignmentstatement in the call-argument list (a:=3)
71+
/// The named argument node of the function call (e.g. `foo(in := 3)`)
7272
assignment: &'b AstNode,
73-
/// the name of the function we're calling
73+
74+
/// The name of the POU being called
7475
function_name: &'b str,
75-
/// the position of the argument in the POU's argument's list
76-
index: u32,
76+
77+
/// The position of the parameter in the POUs variable declaration list.
78+
/// See also [`StatementAnnotation::Argument::position`].
79+
position: u32,
80+
81+
/// The depth between where the parameter is declared versus where it is being called from.
82+
/// See also [`StatementAnnotation::Argument::depth`].
7783
depth: u32,
78-
arg_pou: &'b str,
79-
/// a pointer to the struct instance that carries the call's arguments
84+
85+
/// The name of the POU where the parameter is declared
86+
/// See also [`StatementAnnotation::Argument::pou`].
87+
pou_parameter: &'b str,
88+
89+
/// The pointer to the struct instance that carries the call's arguments
8090
parameter_struct: PointerValue<'a>,
8191
}
8292

@@ -713,9 +723,9 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
713723
self.assign_output_value(&CallParameterAssignment {
714724
assignment: assignment_statement,
715725
function_name,
716-
index: *position as u32,
726+
position: *position as u32,
717727
depth: *depth as u32,
718-
arg_pou: pou,
728+
pou_parameter: pou,
719729
parameter_struct,
720730
})?
721731
}
@@ -843,13 +853,28 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
843853
Ok(())
844854
}
845855

856+
fn build_parameter_struct_gep(&self, context: &CallParameterAssignment<'ink, 'b>) -> PointerValue<'ink> {
857+
unsafe {
858+
let mut gep_index = vec![0; (context.depth + 1) as usize];
859+
gep_index.push(context.position);
860+
861+
let i32_type = self.llvm.context.i32_type();
862+
let gep_index = gep_index
863+
.into_iter()
864+
.map(|value| i32_type.const_int(value as u64, false))
865+
.collect::<Vec<_>>();
866+
867+
self.llvm.builder.build_gep(context.parameter_struct, &gep_index, "").unwrap()
868+
}
869+
}
870+
846871
fn generate_output_assignment(&self, context: &CallParameterAssignment) -> Result<(), CodegenError> {
847872
let &CallParameterAssignment {
848873
assignment: expr,
849874
function_name,
850-
index,
875+
position: index,
851876
depth: _,
852-
arg_pou,
877+
pou_parameter: arg_pou,
853878
parameter_struct,
854879
} = context;
855880

@@ -901,18 +926,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
901926
let assigned_output = self.generate_lvalue(expr)?;
902927
let assigned_output_type =
903928
self.annotations.get_type_or_void(expr, self.index).get_type_information();
904-
let output = unsafe {
905-
let mut gep_index = vec![0; (context.depth + 1) as usize];
906-
gep_index.push(context.index);
907-
908-
let i32_type = self.llvm.context.i32_type();
909-
let gep_index = gep_index
910-
.into_iter()
911-
.map(|value| i32_type.const_int(value as u64, false))
912-
.collect::<Vec<_>>();
913-
914-
builder.build_gep(parameter_struct, &gep_index, "").unwrap()
915-
};
929+
let output = self.build_parameter_struct_gep(context);
916930

917931
let output_value_type = self.index.get_type_information_or_void(parameter.get_type_name());
918932

@@ -948,10 +962,10 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
948962
self.generate_output_assignment(&CallParameterAssignment {
949963
assignment: right,
950964
function_name,
951-
index: param_context.index,
965+
position: param_context.position,
952966
depth: param_context.depth,
953967
parameter_struct,
954-
arg_pou: param_context.arg_pou,
968+
pou_parameter: param_context.pou_parameter,
955969
})?
956970
};
957971

@@ -1304,9 +1318,9 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
13041318
let parameter = self.generate_call_struct_argument_assignment(&CallParameterAssignment {
13051319
assignment: argument,
13061320
function_name: pou_name,
1307-
index: *position as u32,
1321+
position: *position as u32,
13081322
depth: *depth as u32,
1309-
arg_pou: pou,
1323+
pou_parameter: pou,
13101324
parameter_struct,
13111325
})?;
13121326
if let Some(parameter) = parameter {
@@ -1398,34 +1412,22 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
13981412
) -> Result<Option<BasicValueEnum<'ink>>, CodegenError> {
13991413
let builder = &self.llvm.builder;
14001414
// let function_name = param_context.function_name;
1401-
let index = param_context.index;
1402-
let parameter_struct = param_context.parameter_struct;
1415+
let index = param_context.position;
14031416
let expression = param_context.assignment;
14041417

1405-
if let Some(parameter) = self.index.get_declared_parameter(param_context.arg_pou, index) {
1418+
if let Some(parameter) = self.index.get_declared_parameter(param_context.pou_parameter, index) {
14061419
// this happens before the pou call
14071420
// before the call statement we may only consider inputs and inouts
14081421
// after the call we need to copy the output values to the correct assigned variables
14091422
if matches!(parameter.get_variable_type(), VariableType::Output) {
14101423
return Ok(None);
14111424
}
14121425

1413-
let pointer_to_param = unsafe {
1414-
let mut gep_index = vec![0; (param_context.depth + 1) as usize];
1415-
gep_index.push(param_context.index);
1416-
1417-
let i32_type = self.llvm.context.i32_type();
1418-
let gep_index = gep_index
1419-
.into_iter()
1420-
.map(|value| i32_type.const_int(value as u64, false))
1421-
.collect::<Vec<_>>();
1422-
1423-
builder.build_gep(parameter_struct, &gep_index, "").unwrap()
1424-
};
1426+
let pointer_to_param = self.build_parameter_struct_gep(param_context);
14251427

14261428
let parameter = self
14271429
.index
1428-
.find_parameter(param_context.arg_pou, index)
1430+
.find_parameter(param_context.pou_parameter, index)
14291431
.and_then(|var| self.index.find_effective_type_by_name(var.get_type_name()))
14301432
.map(|var| var.get_type_information())
14311433
.unwrap_or_else(|| self.index.get_void_type().get_type_information());
@@ -1484,9 +1486,9 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
14841486
self.generate_call_struct_argument_assignment(&CallParameterAssignment {
14851487
assignment: right,
14861488
function_name,
1487-
index: param_context.index,
1489+
position: param_context.position,
14881490
depth: param_context.depth,
1489-
arg_pou: param_context.arg_pou,
1491+
pou_parameter: param_context.pou_parameter,
14901492
parameter_struct,
14911493
})?;
14921494
};
@@ -1532,7 +1534,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
15321534
let member_location = self
15331535
.index
15341536
.find_fully_qualified_variable(qualified_name)
1535-
.map(VariableIndexEntry::get_location_in_parent)
1537+
.map(VariableIndexEntry::get_position)
15361538
.ok_or_else(|| Diagnostic::unresolved_reference(qualified_name, offset))?;
15371539
let gep: PointerValue<'_> =
15381540
self.llvm.get_member_pointer_from_struct(*qualifier, member_location, name)?;
@@ -2274,7 +2276,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
22742276
Diagnostic::unresolved_reference(qualified_name, data.left.as_ref())
22752277
})?;
22762278

2277-
let index_in_parent = member.get_location_in_parent();
2279+
let index_in_parent = member.get_position();
22782280
let value = self.generate_expression(data.right.as_ref())?;
22792281

22802282
uninitialized_members.remove(member);
@@ -2306,7 +2308,7 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
23062308
Diagnostic::cannot_generate_initializer(member.get_qualified_name(), assignments)
23072309
})?;
23082310

2309-
member_values.push((member.get_location_in_parent(), initial_value));
2311+
member_values.push((member.get_position(), initial_value));
23102312
}
23112313
let struct_type = self.llvm_index.get_associated_type(struct_name)?.into_struct_type();
23122314
if member_values.len() == struct_type.count_fields() as usize {

src/index.rs

Lines changed: 38 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ impl VariableIndexEntry {
199199
self.data_type_name.as_str()
200200
}
201201

202-
pub fn get_location_in_parent(&self) -> u32 {
202+
pub fn get_position(&self) -> u32 {
203203
self.location_in_parent
204204
}
205205

@@ -1551,30 +1551,31 @@ impl Index {
15511551
})
15521552
}
15531553

1554-
fn truly_find_local_member(&self, pou: &str, name: &str) -> Option<&VariableIndexEntry> {
1555-
self.type_index.find_type(pou).and_then(|it| it.find_member(name))
1556-
}
1554+
// XXX: This is super specific and currently only being used in the context of argument annotations. Do we
1555+
// want to move this to the resolver?
1556+
/// Finds a member in the specified POU, traversing the inheritance chain if necessary. Returns the
1557+
/// [`VariableIndexEntry`] along with the inheritance depth from the given POU to where the member
1558+
/// was declared.
1559+
pub fn find_pou_member_and_depth(&self, pou: &str, name: &str) -> Option<(&VariableIndexEntry, usize)> {
1560+
fn find<'a>(index: &'a Index, pou: &str, name: &str) -> Option<&'a VariableIndexEntry> {
1561+
index.type_index.find_type(pou).and_then(|pou| pou.find_member(name))
1562+
}
15571563

1558-
// TODO: Own type?
1559-
/// Given some POU name and one of its members' name, returns the member and the position including its
1560-
/// inheritance level. For example If we have `A { localVarA }, B extends A { localVarB }`, then
1561-
/// `find_member_with_path("B", "localVarA")` will return `(localVarA, 0, 1)`
1562-
pub fn find_member_with_path(&self, pou: &str, name: &str) -> Option<(String, &VariableIndexEntry, u32)> {
15631564
// Check if the POU has the member locally
1564-
if let Some(entry) = self.truly_find_local_member(pou, name) {
1565-
return Some((pou.to_string(), entry, 0));
1565+
if let Some(entry) = find(self, pou, name) {
1566+
return Some((entry, 0));
15661567
}
15671568

15681569
// ..and if not walk the inheritance chain and re-try
1569-
let mut level = 1;
1570+
let mut depth = 1;
15701571
let mut current_pou = pou;
15711572

1572-
while let Some(parent) = self.find_pou(current_pou).and_then(|it| it.get_super_class()) {
1573-
if let Some(entry) = self.truly_find_local_member(parent, name) {
1574-
return Some((parent.to_string(), entry, level));
1573+
while let Some(parent) = self.find_pou(current_pou).and_then(PouIndexEntry::get_super_class) {
1574+
if let Some(entry) = find(self, parent, name) {
1575+
return Some((entry, depth));
15751576
}
15761577

1577-
level += 1;
1578+
depth += 1;
15781579
current_pou = parent;
15791580
}
15801581

@@ -1731,21 +1732,30 @@ impl Index {
17311732
self.get_pou_types().get(&pou_name.to_lowercase())
17321733
}
17331734

1734-
pub fn get_declared_parameters(&self, pou_name: &str) -> Vec<&VariableIndexEntry> {
1735-
self.get_pou_members(pou_name)
1736-
.iter()
1737-
.filter(|it| it.is_parameter() && !it.is_variadic())
1738-
.collect::<Vec<_>>()
1735+
/// Returns the parameter (INPUT, OUTPUT or IN_OUT) for the given POU by its location, if it exists.
1736+
pub fn get_declared_parameter(&self, pou_name: &str, index: u32) -> Option<&VariableIndexEntry> {
1737+
self.type_index.find_pou_type(pou_name).and_then(|it| it.find_declared_parameter_by_location(index))
17391738
}
17401739

1741-
/// Returns all declared parameters of a POU, including those defined in super-classes
1742-
pub fn get_declared_parameters_2nd(&self, pou: &str) -> Vec<&VariableIndexEntry> {
1743-
let mut pou = pou;
1744-
let mut parameters = self.get_declared_parameters(pou);
1740+
/// Returns all declared parameters (INPUT, OUTPUT or IN_OUT) of a POU, including those defined in parent
1741+
/// POUs. The returned list is ordered by the inheritance chain, from base to derived.
1742+
pub fn get_declared_parameters(&self, pou: &str) -> Vec<&VariableIndexEntry> {
1743+
// Collect all POU names in the inheritance chain from base to derived
1744+
let mut chain = Vec::new();
1745+
let mut current = Some(pou);
1746+
let mut parameters = Vec::new();
17451747

1746-
while let Some(parent) = self.find_pou(pou).and_then(PouIndexEntry::get_super_class) {
1747-
parameters.extend(self.get_declared_parameters(parent));
1748-
pou = parent;
1748+
// Walk the inheritance chain and collect its POU names; only has an effect on function block calls
1749+
while let Some(pou_name) = current {
1750+
chain.push(pou_name);
1751+
current = self.find_pou(pou_name).and_then(PouIndexEntry::get_super_class);
1752+
}
1753+
1754+
// Then, reverse the chain to start at the root and collect its parameters
1755+
for &name in chain.iter().rev() {
1756+
parameters.extend(
1757+
self.get_pou_members(name).iter().filter(|var| var.is_parameter() && !var.is_variadic()),
1758+
);
17491759
}
17501760

17511761
parameters
@@ -1755,13 +1765,6 @@ impl Index {
17551765
self.get_pou_members(pou_name).iter().any(|member| member.is_parameter() && member.is_variadic())
17561766
}
17571767

1758-
/// returns some if the current index is a VAR_INPUT, VAR_IN_OUT or VAR_OUTPUT that is not a variadic argument
1759-
/// In other words it returns some if the member variable at `index` of the given container is a possible parameter in
1760-
/// the call to it
1761-
pub fn get_declared_parameter(&self, pou_name: &str, index: u32) -> Option<&VariableIndexEntry> {
1762-
self.type_index.find_pou_type(pou_name).and_then(|it| it.find_declared_parameter_by_location(index))
1763-
}
1764-
17651768
pub fn get_variadic_member(&self, pou_name: &str) -> Option<&VariableIndexEntry> {
17661769
self.type_index.find_pou_type(pou_name).and_then(|it| it.find_variadic_member())
17671770
}

0 commit comments

Comments
 (0)