Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Segfault when passing arguments implicitly #1328

Open
volsa opened this issue Oct 7, 2024 · 1 comment
Open

Segfault when passing arguments implicitly #1328

volsa opened this issue Oct 7, 2024 · 1 comment
Labels
bug Something isn't working

Comments

@volsa
Copy link
Member

volsa commented Oct 7, 2024

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
@volsa volsa added the bug Something isn't working label Oct 7, 2024
@mhasel
Copy link
Member

mhasel commented Oct 7, 2024

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants