rusty icon indicating copy to clipboard operation
rusty copied to clipboard

Panic during codegen when dereferencing paren-expression

Open mhasel opened this issue 9 months ago • 0 comments

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.

mhasel avatar Mar 26 '25 14:03 mhasel