Skip to content

Commit 78b8ce8

Browse files
committed
refactor: self review
1 parent d4157a3 commit 78b8ce8

10 files changed

+254
-81
lines changed

.vscode/launch.json

Lines changed: 24 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,31 +4,29 @@
44
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
55
"version": "0.2.0",
66
"configurations": [
7-
{
8-
"type": "codelldb",
9-
"request": "launch",
10-
"name": "Debug codelldb standard_lib",
11-
"cargo": {
12-
"args": [
13-
"build",
14-
"--bin=plc",
15-
"--package=plc_driver"
16-
],
17-
"filter": {
18-
"name": "plc",
19-
"kind": "bin"
20-
}
21-
},
22-
"program": "target/debug/plc",
7+
{
8+
"type": "codelldb",
9+
"request": "launch",
10+
"name": "Debug codelldb standard_lib",
11+
"cargo": {
2312
"args": [
24-
"libs/stdlib/iec61131-st/*.st"
13+
"build",
14+
"--bin=plc",
15+
"--package=plc_driver"
2516
],
26-
"cwd": "${workspaceFolder}",
27-
"env": {
28-
"RUST_LOG": "rusty"
29-
},
30-
"terminal": "integrated"
17+
"filter": {
18+
"name": "plc",
19+
"kind": "bin"
20+
}
21+
},
22+
"program": "target/debug/plc",
23+
"args": ["libs/stdlib/iec61131-st/*.st"],
24+
"cwd": "${workspaceFolder}",
25+
"env": {
26+
"RUST_LOG": "rusty"
3127
},
28+
"terminal": "integrated"
29+
},
3230
{
3331
"type": "codelldb",
3432
"request": "launch",
@@ -45,11 +43,7 @@
4543
}
4644
},
4745
"program": "target/debug/plc",
48-
"args": [
49-
"target/demo.st",
50-
"-g",
51-
"-c"
52-
],
46+
"args": ["target/demo.st", "-g", "-c"],
5347
"cwd": "${workspaceFolder}",
5448
"env": {
5549
"RUST_LOG": "rusty"
@@ -73,8 +67,7 @@
7367
},
7468
"args": [
7569
"target/demo.st",
76-
"tests/lit/util/printf.pli",
77-
"-j=1",
70+
"tests/lit/util/printf.pli"
7871
],
7972
"cwd": "${workspaceFolder}",
8073
"env": {
@@ -114,6 +107,7 @@
114107
"cwd": "${workspaceFolder}",
115108
"program": "target/demo",
116109
"terminal": "integrated"
110+
117111
}
118112
]
119-
}
113+
}

Makefile

Lines changed: 0 additions & 7 deletions
This file was deleted.

src/codegen/generators/data_type_generator.rs

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -286,30 +286,29 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
286286
}
287287
}
288288

289-
// TODO(vosa): Is this neccessary? Are the function types indexed and later on used in the expression
290-
// generator? If not this whole commit could be reverted, double-check before merging
291-
fn create_function_type(&mut self, pou_name: &str) -> Result<FunctionType<'ink>, Diagnostic> {
289+
fn create_function_type(&mut self, method_name: &str) -> Result<FunctionType<'ink>, Diagnostic> {
292290
let return_type = self
293291
.types_index
294-
.find_associated_type(self.index.get_return_type_or_void(pou_name).get_name())
292+
.find_associated_type(self.index.get_return_type_or_void(method_name).get_name())
295293
.map(|opt| opt.as_any_type_enum())
296294
.unwrap_or(self.llvm.context.void_type().as_any_type_enum());
297295

298296
let mut parameter_types = Vec::new();
299297

300-
// Methods are defined as functions in the LLVM IR, but carry the underlying POU type as their first
301-
// parameter to operate on them, hence push the POU type to the very first position.
302-
match self.index.find_pou(pou_name) {
298+
match self.index.find_pou(method_name) {
303299
Some(PouIndexEntry::Method { parent_name, .. }) => {
304300
let ty = self.types_index.get_associated_type(parent_name).expect("must exist");
305301
let ty_ptr = ty.ptr_type(AddressSpace::from(ADDRESS_SPACE_GENERIC)).into();
306302

303+
// Methods are defined as functions in the LLVM IR, but carry the underlying POU type as their
304+
// first parameter to operate on them, hence push the POU type to the very first position.
307305
parameter_types.push(ty_ptr);
308-
for parameter in self.index.get_declared_parameters(pou_name) {
309-
// Instead of relying on the LLVM index, we create data-types directly in here because some of
310-
// them may not have been registered yet. For example, at the time of writing this comment the
311-
// `__auto_pointer_to_DINT` type was not present in the index for a VAR_IN_OUT parameter which
312-
// resulted in an error
306+
307+
for parameter in self.index.get_declared_parameters(method_name) {
308+
// Instead of relying on the LLVM index, we create data-types on the fly here because some
309+
// types have not yet been visited and as a result may not be in the index. For example at
310+
// the time of writing this the index was not able to find a input parameter of type
311+
// `__auto_pointer_to_DINT`, consequently panicking
313312
let ty = self.create_type(
314313
parameter.get_name(),
315314
self.index.get_type(&parameter.data_type_name).expect("must exist"),
@@ -319,13 +318,13 @@ impl<'ink> DataTypeGenerator<'ink, '_> {
319318
}
320319
}
321320

322-
// Function blocks are a bit "weird" in that they only expect an instance argument even if they
323-
// define input, output and/or inout parameters. Effectively, while being methods per-se, their
324-
// calling convention differs from regular methods.
325321
Some(PouIndexEntry::FunctionBlock { name, .. }) => {
326322
let ty = self.types_index.get_associated_type(name).expect("must exist");
327323
let ty_ptr = ty.ptr_type(AddressSpace::from(ADDRESS_SPACE_GENERIC)).into();
328324

325+
// Function blocks are a bit "weird" in that they only expect an instance argument even if
326+
// they define input, output and/or inout parameters. Effectively, while being methods per-se,
327+
// their calling convention differs from regular methods.
329328
parameter_types.push(ty_ptr);
330329
}
331330

src/codegen/generators/expression_generator.rs

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -490,7 +490,6 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
490490
operator: &AstNode,
491491
parameters: Option<&AstNode>,
492492
) -> Result<ExpressionValue<'ink>, Diagnostic> {
493-
// Check if we are dealing with something alike `foo^(...)`
494493
if self.annotations.get(operator).is_some_and(StatementAnnotation::is_fnptr) {
495494
return self.generate_fnptr_call(operator, parameters);
496495
}
@@ -595,6 +594,8 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
595594
arguments: Option<&AstNode>,
596595
) -> Result<ExpressionValue<'ink>, Diagnostic> {
597596
let Some(ReferenceExpr { base: Some(ref base), .. }) = operator.get_deref_expr() else {
597+
// XXX: This would fail for auto-deref pointers, but given (for now) function pointers are never
598+
// auto-derefed this should be fine.
598599
unreachable!("internal error, invalid method call")
599600
};
600601

@@ -652,13 +653,10 @@ impl<'ink, 'b> ExpressionCodeGenerator<'ink, 'b> {
652653

653654
let value = match call.try_as_basic_value() {
654655
Either::Left(value) => value,
655-
Either::Right(_) => {
656-
// TODO: When is this neccessary?
657-
get_llvm_int_type(self.llvm.context, INT_SIZE, INT_TYPE)
658-
.ptr_type(AddressSpace::from(ADDRESS_SPACE_CONST))
659-
.const_null()
660-
.as_basic_value_enum()
661-
}
656+
Either::Right(_) => get_llvm_int_type(self.llvm.context, INT_SIZE, INT_TYPE)
657+
.ptr_type(AddressSpace::from(ADDRESS_SPACE_CONST))
658+
.const_null()
659+
.as_basic_value_enum(),
662660
};
663661

664662
// Output variables are assigned after the function block call, effectively gep'ing the instance

src/codegen/llvm_index.rs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ pub struct LlvmTypedIndex<'ink> {
2727
pub trait TypeHelper<'ink> {
2828
#[allow(clippy::wrong_self_convention)]
2929
fn as_basic_type(self) -> Option<BasicTypeEnum<'ink>>;
30-
3130
fn create_ptr_type(&self, address_space: AddressSpace) -> PointerType<'ink>;
3231
}
3332

@@ -113,7 +112,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
113112
) -> Result<(), Diagnostic> {
114113
let name = type_name.to_lowercase();
115114

116-
log::debug!("registered `{name}` as type `{}`", target_type.print_to_string());
115+
log::trace!("registered `{name}` as type `{}`", target_type.print_to_string());
117116
self.type_associations.insert(name, target_type);
118117
Ok(())
119118
}
@@ -125,7 +124,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
125124
) -> Result<(), Diagnostic> {
126125
let name = type_name.to_lowercase();
127126

128-
log::debug!("registered `{name}` as POU type `{}`", target_type.print_to_string());
127+
log::trace!("registered `{name}` as POU type `{}`", target_type.print_to_string());
129128
self.pou_type_associations.insert(name, target_type);
130129
Ok(())
131130
}
@@ -137,7 +136,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
137136
) -> Result<(), Diagnostic> {
138137
let name = type_name.to_lowercase();
139138

140-
log::debug!("registered `{name}` as initial value type `{}`", initial_value.print_to_string());
139+
log::trace!("registered `{name}` as initial value type `{}`", initial_value.print_to_string());
141140
self.initial_value_associations.insert(name, initial_value);
142141
Ok(())
143142
}
@@ -150,7 +149,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
150149
) -> Result<(), Diagnostic> {
151150
let name = qualified_name(container_name, variable_name).to_lowercase();
152151

153-
log::debug!("registered `{name}` as loaded local type `{}`", target_value.print_to_string());
152+
log::trace!("registered `{name}` as loaded local type `{}`", target_value.print_to_string());
154153
self.loaded_variable_associations.insert(name, target_value);
155154
Ok(())
156155
}
@@ -162,7 +161,7 @@ impl<'ink> LlvmTypedIndex<'ink> {
162161
) -> Result<(), Diagnostic> {
163162
let name = variable_name.to_lowercase();
164163

165-
log::debug!("registered `{name}` as global variable type `{}`", global_variable.print_to_string());
164+
log::trace!("registered `{name}` as global variable type `{}`", global_variable.print_to_string());
166165
self.global_values.insert(name.clone(), global_variable);
167166
self.initial_value_associations.insert(name, global_variable.as_pointer_value().into());
168167

@@ -177,19 +176,19 @@ impl<'ink> LlvmTypedIndex<'ink> {
177176
) -> Result<(), Diagnostic> {
178177
let name = callable_name.to_lowercase();
179178

180-
log::debug!("registered `{name}` as implementation type `{}`", function_value.print_to_string());
179+
log::trace!("registered `{name}` as implementation type `{}`", function_value.print_to_string());
181180
self.implementations.insert(name, function_value);
182181

183182
Ok(())
184183
}
185184

186185
pub fn associate_utf08_literal(&mut self, literal: &str, literal_variable: GlobalValue<'ink>) {
187-
log::debug!("registered literal {literal}");
186+
log::trace!("registered literal {literal}");
188187
self.utf08_literals.insert(literal.to_string(), literal_variable);
189188
}
190189

191190
pub fn associate_utf16_literal(&mut self, literal: &str, literal_variable: GlobalValue<'ink>) {
192-
log::debug!("registered literal {literal}");
191+
log::trace!("registered literal {literal}");
193192
self.utf16_literals.insert(literal.to_string(), literal_variable);
194193
}
195194

src/lowering/calls.rs

Lines changed: 46 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,8 @@ impl AstVisitorMut for AggregateTypeLowerer {
346346
let mut parameters =
347347
stmt.parameters.as_mut().map(|it| steal_expression_list(it.borrow_mut())).unwrap_or_default();
348348

349-
// When dealing with function pointers (which for now support only methods), then the alloca
350-
// variable must be placed at index 1 rather than 0 because the instance variable must always be
351-
// the first argument
349+
// Place the alloca aggregate variable at index 1 when dealing with function pointers because 0
350+
// is reserved for the instance variable.
352351
if self.annotation.as_ref().unwrap().get(&stmt.operator).is_some_and(|opt| opt.is_fnptr()) {
353352
parameters.insert(1, reference);
354353
} else {
@@ -1211,7 +1210,50 @@ mod tests {
12111210
}
12121211

12131212
#[test]
1214-
fn fnptr_no_argument() {
1213+
fn fnptr_with_arguments() {
1214+
let id_provider = IdProvider::default();
1215+
let (mut unit, index) = index_with_ids(
1216+
r#"
1217+
FUNCTION_BLOCK FbA
1218+
METHOD foo: STRING
1219+
VAR_INPUT
1220+
x: DINT;
1221+
y: STRING;
1222+
END_VAR
1223+
END_METHOD
1224+
END_FUNCTION_BLOCK
1225+
1226+
FUNCTION main
1227+
VAR
1228+
instanceFbA: FbA;
1229+
fooPtr: FNPTR FbA.foo;
1230+
localX: DINT;
1231+
localY: STRING;
1232+
result: STRING;
1233+
END_VAR
1234+
1235+
result := fooPtr^(instanceFbA, localX, localY);
1236+
END_FUNCTION
1237+
"#,
1238+
id_provider.clone(),
1239+
);
1240+
1241+
let mut lowerer = AggregateTypeLowerer {
1242+
index: Some(index),
1243+
annotation: None,
1244+
id_provider: id_provider.clone(),
1245+
..Default::default()
1246+
};
1247+
lowerer.visit_compilation_unit(&mut unit);
1248+
lowerer.index.replace(index_unit_with_id(&unit, id_provider.clone()));
1249+
let annotations = annotate_with_ids(&unit, lowerer.index.as_mut().unwrap(), id_provider.clone());
1250+
lowerer.annotation.replace(Box::new(annotations));
1251+
lowerer.visit_compilation_unit(&mut unit);
1252+
assert_debug_snapshot!(unit.implementations[2].statements[0]);
1253+
}
1254+
1255+
#[test]
1256+
fn fnptr_without_arguments() {
12151257
let id_provider = IdProvider::default();
12161258
let (mut unit, index) = index_with_ids(
12171259
r#"

0 commit comments

Comments
 (0)