Segfault when passing arguments implicitly
The following code will currently segfault when compiling and running with cargo r -- target/demo.st tests/lit/util/printf.pli --linker=clang && ./demo.st.out due to passing the arr variable implicitly to mainProg.
FUNCTION main
VAR
arr : ARRAY[0..9] OF INT;
END_VAR
mainProg(arr); // `mainProg(arr := arr);` works
END_FUNCTION
PROGRAM mainProg
VAR
i : INT;
END_VAR
VAR_IN_OUT
arr : ARRAY[0..9] OF INT;
END_VAR
FOR i := 0 TO 9 DO
arr[i] := i;
END_FOR
END_PROGRAM
When trying to compile this to IR, llvm gives the following error:
error: invalid forward reference to function 'mainProg' with wrong type: expected 'void (%mainProg*)*' but was 'void (%mainProg*, [10 x i16])*'
call void @mainProg(%mainProg* @mainProg_instance, [10 x i16] %load_arr)
This does not happen if the VAR block is declared after the VAR_IN_OUT block. The most likely cause is in generate_nameless_parameter, since it looks for a struct member at a certain index in a stateful POU for non-formally passed parameters. In this case, it is trying to get the parameter at index 0, but since the first member of the POU-struct is not a parameter, self.index.get_declared_parameter(function_name, index) will return None.
/// generates the appropriate value for the given expression where the expression
/// is a call's implicit argument (hence: foo(3), not foo(in := 3))
fn generate_nameless_parameter(
&self,
param_context: &CallParameterAssignment,
) -> Result<Option<BasicValueEnum<'ink>>, Diagnostic> {
let builder = &self.llvm.builder;
let function_name = param_context.function_name;
let index = param_context.index;
let parameter_struct = param_context.parameter_struct;
let expression = param_context.assignment;
if let Some(parameter) = self.index.get_declared_parameter(function_name, index) {
// ...
This index comes from for (i, stmt) in passed_parameters.iter().enumerate() { ... in generate_stateful_pou_arguments => only one parameter is passed but the index of this parameter does not match the gep offset in the struct.