PLC-lang / rusty

Structured Text Parser and LLVM Frontend
GNU Lesser General Public License v3.0
183 stars 48 forks source link

GLOBAL VARIABLES array problem #361

Closed rarris closed 2 years ago

rarris commented 2 years ago

the following test is not compiled

    VAR_GLOBAL
        gX : ARRAY[0..2] OF INT;
        gZ : INT;
    END_VAR
    FUNCTION main : REAL
    VAR
        x,y : INT;
        z : INT;
    END_VAR
    gX[0] := 10;
    gX[1] := 21;
    gZ := 5;
    x := gX[0];
    y := gX[1];
    z := gZ;
    main := (x + y) / z;
    END_FUNCTION

(exit code: 0xc0000005, STATUS_ACCESS_VIOLATION)

ghaith commented 2 years ago

It compiles, but does not run, on linux it's an invalid memory reference, on windows an access violation. It seems to be related to the global array If I compile the code with -c and then pass it to clang, clang complains about a missing symbol gX

riederm commented 2 years ago

It compiles, but does not run, on linux it's an invalid memory reference, on windows an access violation. It seems to be related to the global array If I compile the code with -c and then pass it to clang, clang complains about a missing symbol gX

can you post the resulting ir?

ghaith commented 2 years ago

Did not investigate much yet, here's the IR

; ModuleID = 'main'
source_filename = "main"

%main_interface = type { i16, i16, i16 }

@gX = external global [3 x i16]
@gZ = global i16 0

define float @main(%main_interface* %0) {
entry:
  %x = getelementptr inbounds %main_interface, %main_interface* %0, i32 0, i32 0
  %y = getelementptr inbounds %main_interface, %main_interface* %0, i32 0, i32 1
  %z = getelementptr inbounds %main_interface, %main_interface* %0, i32 0, i32 2
  %main = alloca float, align 4
  store i16 10, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @gX, i32 0, i32 0), align 2
  store i16 21, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @gX, i32 0, i32 1), align 2
  store i16 5, i16* @gZ, align 2
  %load_tmpVar = load i16, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @gX, i32 0, i32 0), align 2
  store i16 %load_tmpVar, i16* %x, align 2
  %load_tmpVar1 = load i16, i16* getelementptr inbounds ([3 x i16], [3 x i16]* @gX, i32 0, i32 1), align 2
  store i16 %load_tmpVar1, i16* %y, align 2
  %load_gZ = load i16, i16* @gZ, align 2
  store i16 %load_gZ, i16* %z, align 2
  %load_x = load i16, i16* %x, align 2
  %1 = sext i16 %load_x to i32
  %load_y = load i16, i16* %y, align 2
  %2 = sext i16 %load_y to i32
  %tmpVar = add i32 %1, %2
  %load_z = load i16, i16* %z, align 2
  %3 = sext i16 %load_z to i32
  %tmpVar2 = sdiv i32 %tmpVar, %3
  %4 = sitofp i32 %tmpVar2 to float
  store float %4, float* %main, align 4
  %main_ret = load float, float* %main, align 4
  ret float %main_ret
}
riederm commented 2 years ago
@gX = external global [3 x i16]

external means that it is defined somewhere else ... why would this be external? maybe we have an initialization problem? like we don't provide a default value for arrays?

riederm commented 2 years ago

Turns out that we can't handle uninitialized arrays. I guess inside POUs this problem doesn't happen, because the whole POU's memory gets zero-initialized. With a global, llvm turns it into an extern (forward-declaration) if no initializer is provided.

If you initialize the array the code compiles.

VAR_GLOBAL
    gX : ARRAY[0..2] OF INT := [0, 0, 0];
    gZ : INT;
END_VAR

FUNCTION main : REAL
    VAR
        x,y : INT;
        z : INT;
    END_VAR
    gX[0] := 10;
    gX[1] := 21;
    gZ := 5;
    x := gX[0];
    y := gX[1];
    z := gZ;
    main := (x + y) / z;
END_FUNCTION
create-issue-branch[bot] commented 2 years ago

Branch issue-361-GLOBAL_VARIABLES_array_problem created!