Skip to content

Panic during codegen when dereferencing paren-expression #1443

@mhasel

Description

@mhasel

Describe the bug
This came up during the implementation of SUPER but an equivalent example is also reproducible on master.
When trying to dereference the parenthesized result of a REF call, we hit a panic in inkwell.

To Reproduce

        FUNCTION_BLOCK fb1
        VAR
            x : INT := 10;
            ref_x : REF_TO INT;
        END_VAR
            ref_x := REF(x);
            x := (REF(x))^; // this expression should be valid, but panics
        END_FUNCTION_BLOCK

panics with:

thread '<unnamed>' panicked at /home/michael/.cargo/registry/src/index.crates.io-6f17d22bba15001f/inkwell-0.2.0/src/values/enums.rs:302:13:
Found IntValue(IntValue { int_value: Value { name: "deref", address: 0x74e03c008d60, is_const: false, is_null: false, is_undef: false, llvm_value: "  %deref = load i16, i16* %x, align 2", llvm_type: "i16" } }) but expected PointerValue variant
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

Additional context

This does not happen when dereferencing a parenthesized pointer, so it might be due to the inlining of our builtins.
Edit: this might also be an RValue problem, since dereferencing a pointer should require an LValue.

Additional examples

        FUNCTION_BLOCK  foo
        VAR
            i : LINT;
            ref_i : REF_TO LINT;
        END_VAR
            i := (REF(i) + 1)^ + 5;        // panics
            i := (ref_i + 1)^ + 5;          // panics
         END_FUNCTION_BLOCK

panic:

thread '<unnamed>' panicked at /home/michael/.cargo/registry/src/index.crates.io-6f17d22bba15001f/inkwell-0.2.0/src/values/enums.rs:302:13:
Found IntValue(IntValue { int_value: Value { name: "deref", address: 0x747a6400be80, is_const: false, is_null: false, is_undef: false, llvm_value: "  %deref = load i64, i64* %access___foo_ref_i, align 4", llvm_type: "i64" } }) but expected PointerValue variant
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

If one of the operands happens to be a struct-type, we don't hit a panic but abort codegen with a diagnostic instead.

        FUNCTION_BLOCK bar
        VAR
            x : LINT := 10;
            y : LINT := 20;
        END_VAR
        END_FUNCTION_BLOCK

        FUNCTION_BLOCK  foo
        VAR
            i : LINT;
            b : bar;
            ref_b : REF_TO bar;
        END_VAR
            i := (REF(b) + 1)^ + 5;
            i := (ref_b + 1)^ + 5;
        END_FUNCTION_BLOCK

Resulting codegen error:

Invalid types, cannot generate binary expression for "bar" and "DINT" at: target/demo.st:126:17:{126:17-126:29}: .
Hint: You can use `plc explain <ErrorCode>` for more information

Expected behavior
For each of those cases, we should either be able to deref the resulting RValue and attempt to continue (this might be undefined behaviour and a security concern) or catch these cases during validation and abort gracefully.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingcodegen

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions