llvm / llvm-project

The LLVM Project is a collection of modular and reusable compiler and toolchain technologies.
http://llvm.org
Other
27.17k stars 11.12k forks source link

[flang][debuginfo] Inconsistent debugger behavior when processing executables emitted by flang-new #97476

Closed pawosm-arm closed 1 week ago

pawosm-arm commented 3 weeks ago

Consider simple program:

PROGRAM allocatable
  IMPLICIT NONE
  INTEGER, ALLOCATABLE, TARGET :: alloc2d(:, :)

  ALLOCATE(alloc2d(-1:1, -2:2))
  IF (ALLOCATED(alloc2d)) THEN
    alloc2d(:, :) = -1
    DEALLOCATE(alloc2d)
  END IF
END PROGRAM

I've tried to compile it with gfortran and the old classic flang (each time with the -O0 -g flags), and I've observed (more or less) the same effect in gdb (after setting breakpoint at the ALLOCATE statement):

(gdb) b allocatable.f90:5
Breakpoint 1 at 0x40092c: file allocatable.f90, line 5.
(gdb) r
Starting program: /home/pawosm01/test_linear/allocatable
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".

Breakpoint 1, allocatable () at allocatable.f90:5
5         ALLOCATE(alloc2d(-1:1, -2:2))
(gdb) info locals
alloc2d = <not allocated>
(gdb)

When compiled with flang-new, I can observe a different behavior:

(gdb) b allocatable.f90:5
Breakpoint 1 at 0x2110: file allocatable.f90, line 5.
(gdb) r
Starting program: /home/pawosm01/test_linear/allocatable
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".

Breakpoint 1, _QQmain () at allocatable.f90:5
5         ALLOCATE(alloc2d(-1:1, -2:2))
(gdb) info locals
alloc2d = ()
(gdb)

Apparently, gdb can't figure out that the array was not allocated yet. This has some nasty implications as I extended the program a bit:

PROGRAM minimal
  IMPLICIT NONE
  INTEGER :: int_arr1d(-1:1)
  INTEGER :: int_arr2d(-1:1, -2:2)
  LOGICAL :: logical_arr2d(-1:1, -2:2)
  REAL    :: real_arr1d(-1:1)
  REAL    :: real_arr2d(-1:1, -2:2)
  INTEGER, ALLOCATABLE, TARGET :: alloc2d(:, :)

  ALLOCATE(alloc2d(-1:1, -2:2))
  IF (ALLOCATED(alloc2d)) THEN
    alloc2d(:, :) = -1
    DEALLOCATE(alloc2d)
  END IF
END PROGRAM

When compiled with gfortran (and more or less the same when compiled with the old classic flang):

(gdb) b minimal.f90:10
Breakpoint 1 at 0x40092c: file minimal.f90, line 10.
(gdb) r
Starting program: /home/pawosm01/test_linear/minimal
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".

Breakpoint 1, minimal () at minimal.f90:10
10        ALLOCATE(alloc2d(-1:1, -2:2))
(gdb) info locals
alloc2d = <not allocated>
(gdb)

Notice, that uninitialized variables are not present. When compiled with flang-new:

(gdb) b minimal.f90:10
Breakpoint 1 at 0x2110: file minimal.f90, line 10.
(gdb) r
Starting program: /home/pawosm01/test_linear/minimal
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1".

Breakpoint 1, _QQmain () at minimal.f90:10
10        ALLOCATE(alloc2d(-1:1, -2:2))
(gdb) info locals
int_arr1d = (-134225856, 65535, -1431689840)
real_arr1d = (6.12227299e-41, -9.7203448e+33, 9.18340949e-41)
alloc2d = <error reading variable alloc2d (Cannot access memory at address 0x1000000000000)>
(gdb)

Now, some (but only some) of the uninitialized variables are shown, all of them with random values, and alloc2d has gone completely to the moon. Note that when doing experiments (adding more variables, some of them with user defined types) I've managed to make the information about alloc2d completely lost, which is the most unfortunate.

llvmbot commented 3 weeks ago

@llvm/issue-subscribers-flang-ir

Author: Paul Osmialowski (pawosm-arm)

Consider simple program: ``` PROGRAM allocatable IMPLICIT NONE INTEGER, ALLOCATABLE, TARGET :: alloc2d(:, :) ALLOCATE(alloc2d(-1:1, -2:2)) IF (ALLOCATED(alloc2d)) THEN alloc2d(:, :) = -1 DEALLOCATE(alloc2d) END IF END PROGRAM ``` I've tried to compile it with gfortran and the old classic flang (each time with the `-O0 -g` flags), and I've observed (more or less) the same effect in gdb (after setting breakpoint at the ALLOCATE statement): ``` (gdb) b allocatable.f90:5 Breakpoint 1 at 0x40092c: file allocatable.f90, line 5. (gdb) r Starting program: /home/pawosm01/test_linear/allocatable [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1". Breakpoint 1, allocatable () at allocatable.f90:5 5 ALLOCATE(alloc2d(-1:1, -2:2)) (gdb) info locals alloc2d = <not allocated> (gdb) ``` When compiled with flang-new, I can observe a different behavior: ``` (gdb) b allocatable.f90:5 Breakpoint 1 at 0x2110: file allocatable.f90, line 5. (gdb) r Starting program: /home/pawosm01/test_linear/allocatable [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1". Breakpoint 1, _QQmain () at allocatable.f90:5 5 ALLOCATE(alloc2d(-1:1, -2:2)) (gdb) info locals alloc2d = () (gdb) ``` Apparently, gdb can't figure out that the array was not allocated yet. This has some nasty implications as I extended the program a bit: ``` PROGRAM minimal IMPLICIT NONE INTEGER :: int_arr1d(-1:1) INTEGER :: int_arr2d(-1:1, -2:2) LOGICAL :: logical_arr2d(-1:1, -2:2) REAL :: real_arr1d(-1:1) REAL :: real_arr2d(-1:1, -2:2) INTEGER, ALLOCATABLE, TARGET :: alloc2d(:, :) ALLOCATE(alloc2d(-1:1, -2:2)) IF (ALLOCATED(alloc2d)) THEN alloc2d(:, :) = -1 DEALLOCATE(alloc2d) END IF END PROGRAM ``` When compiled with gfortran (and more or less the same when compiled with the old classic flang): ``` (gdb) b minimal.f90:10 Breakpoint 1 at 0x40092c: file minimal.f90, line 10. (gdb) r Starting program: /home/pawosm01/test_linear/minimal [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1". Breakpoint 1, minimal () at minimal.f90:10 10 ALLOCATE(alloc2d(-1:1, -2:2)) (gdb) info locals alloc2d = <not allocated> (gdb) ``` Notice, that uninitialized variables are not present. When compiled with flang-new: ``` (gdb) b minimal.f90:10 Breakpoint 1 at 0x2110: file minimal.f90, line 10. (gdb) r Starting program: /home/pawosm01/test_linear/minimal [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1". Breakpoint 1, _QQmain () at minimal.f90:10 10 ALLOCATE(alloc2d(-1:1, -2:2)) (gdb) info locals int_arr1d = (-134225856, 65535, -1431689840) real_arr1d = (6.12227299e-41, -9.7203448e+33, 9.18340949e-41) alloc2d = <error reading variable alloc2d (Cannot access memory at address 0x1000000000000)> (gdb) ``` Now, some (but only some) of the uninitialized variables are shown, all of them with random values, and `alloc2d` has gone completely to the moon. Note that when doing experiments (adding more variables, some of them with user defined types) I've managed to make the information about `alloc2d` completely lost, which is the most unfortunate.
llvmbot commented 3 weeks ago

@llvm/issue-subscribers-debuginfo

Author: Paul Osmialowski (pawosm-arm)

Consider simple program: ``` PROGRAM allocatable IMPLICIT NONE INTEGER, ALLOCATABLE, TARGET :: alloc2d(:, :) ALLOCATE(alloc2d(-1:1, -2:2)) IF (ALLOCATED(alloc2d)) THEN alloc2d(:, :) = -1 DEALLOCATE(alloc2d) END IF END PROGRAM ``` I've tried to compile it with gfortran and the old classic flang (each time with the `-O0 -g` flags), and I've observed (more or less) the same effect in gdb (after setting breakpoint at the ALLOCATE statement): ``` (gdb) b allocatable.f90:5 Breakpoint 1 at 0x40092c: file allocatable.f90, line 5. (gdb) r Starting program: /home/pawosm01/test_linear/allocatable [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1". Breakpoint 1, allocatable () at allocatable.f90:5 5 ALLOCATE(alloc2d(-1:1, -2:2)) (gdb) info locals alloc2d = <not allocated> (gdb) ``` When compiled with flang-new, I can observe a different behavior: ``` (gdb) b allocatable.f90:5 Breakpoint 1 at 0x2110: file allocatable.f90, line 5. (gdb) r Starting program: /home/pawosm01/test_linear/allocatable [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1". Breakpoint 1, _QQmain () at allocatable.f90:5 5 ALLOCATE(alloc2d(-1:1, -2:2)) (gdb) info locals alloc2d = () (gdb) ``` Apparently, gdb can't figure out that the array was not allocated yet. This has some nasty implications as I extended the program a bit: ``` PROGRAM minimal IMPLICIT NONE INTEGER :: int_arr1d(-1:1) INTEGER :: int_arr2d(-1:1, -2:2) LOGICAL :: logical_arr2d(-1:1, -2:2) REAL :: real_arr1d(-1:1) REAL :: real_arr2d(-1:1, -2:2) INTEGER, ALLOCATABLE, TARGET :: alloc2d(:, :) ALLOCATE(alloc2d(-1:1, -2:2)) IF (ALLOCATED(alloc2d)) THEN alloc2d(:, :) = -1 DEALLOCATE(alloc2d) END IF END PROGRAM ``` When compiled with gfortran (and more or less the same when compiled with the old classic flang): ``` (gdb) b minimal.f90:10 Breakpoint 1 at 0x40092c: file minimal.f90, line 10. (gdb) r Starting program: /home/pawosm01/test_linear/minimal [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1". Breakpoint 1, minimal () at minimal.f90:10 10 ALLOCATE(alloc2d(-1:1, -2:2)) (gdb) info locals alloc2d = <not allocated> (gdb) ``` Notice, that uninitialized variables are not present. When compiled with flang-new: ``` (gdb) b minimal.f90:10 Breakpoint 1 at 0x2110: file minimal.f90, line 10. (gdb) r Starting program: /home/pawosm01/test_linear/minimal [Thread debugging using libthread_db enabled] Using host libthread_db library "/lib/aarch64-linux-gnu/libthread_db.so.1". Breakpoint 1, _QQmain () at minimal.f90:10 10 ALLOCATE(alloc2d(-1:1, -2:2)) (gdb) info locals int_arr1d = (-134225856, 65535, -1431689840) real_arr1d = (6.12227299e-41, -9.7203448e+33, 9.18340949e-41) alloc2d = <error reading variable alloc2d (Cannot access memory at address 0x1000000000000)> (gdb) ``` Now, some (but only some) of the uninitialized variables are shown, all of them with random values, and `alloc2d` has gone completely to the moon. Note that when doing experiments (adding more variables, some of them with user defined types) I've managed to make the information about `alloc2d` completely lost, which is the most unfortunate.
abidh commented 3 weeks ago

Thanks for reporting this @pawosm-arm. We have an issue that when a local variable is pointing to a global storage, LLVM's drops such local variables. This was the reason debugger did not show you logical_arr2d etc. I am aware of this issue and I intend to fix it soon. It also caused a lot of failures in GDB's testsuite when I tried it.

If you move these variables to a module, then you should be able to evaluate them correctly. For example, here is how my debug session looked when I moved them to a module (see example program below). Although if you look at the output of ptype command, you noticed that flang confused upper bound with count in case of allocatable arrays. I will fix that.

Breakpoint 1, _QQmain () at test.f90:13
13        ALLOCATE(alloc2d(-1:1, -2:2))
(gdb) p min::real_arr2d
$3 = ((0, 0, 0) (0, 0, 0) (0, 0, 0) (0, 0, 0) (0, 0, 0))
(gdb) p min::real_arr1d
$4 = (0, 0, 0)
(gdb) p min::alloc2d
$5 = <not allocated>
(gdb) n
14        IF (ALLOCATED(alloc2d)) THEN
(gdb) ptype min::alloc2d
type = integer, allocatable (-1:3,-2:5)
(gdb) 
module min
  INTEGER :: int_arr1d(-1:1)
  INTEGER :: int_arr2d(-1:1, -2:2)
  LOGICAL :: logical_arr2d(-1:1, -2:2)
  REAL    :: real_arr1d(-1:1)
  REAL    :: real_arr2d(-1:1, -2:2)
  INTEGER, ALLOCATABLE, TARGET :: alloc2d(:, :)
end module min

PROGRAM minimal
  use min

  ALLOCATE(alloc2d(-1:1, -2:2))
  IF (ALLOCATED(alloc2d)) THEN
    alloc2d(:, :) = -1
    DEALLOCATE(alloc2d)
  END IF
END PROGRAM
pawosm-arm commented 3 weeks ago

Thanks @abidh for looking into it. The minimalist reproducer that I've prepared wasn't based on my code, I have no power to shift things around into modules.

abidh commented 3 weeks ago

Thanks @abidh for looking into it. The minimalist reproducer that I've prepared wasn't based on my code, I have no power to shift things around into modules.

I understand. My example was just to make clear what exactly is not working.

abidh commented 2 weeks ago

One more comment. You should see all the local variables with info locals. You don't see most of them with gfortran or classic flang because they are not being used and probably get optimized away. If you use the variable then they will show up in debugger.

abidh commented 2 weeks ago

@pawosm-arm I posted a fix for it in #98661. If you could kindly test that it works for you then it would be great.

pawosm-arm commented 1 week ago

It is better and the tests I've quoted above are now passing. Yet still I have a test case that is failing, see:

module use_mod
  INTEGER, DIMENSION(:,:), ALLOCATABLE :: alloc2d
end module

program using_mod
  use use_mod
  ALLOCATE (alloc2d(-1:1,-2:2))
  alloc2d(:,:) = -1
end program

If you set breakpoint at the line 7 (ALLOCATE...), gdb should be able to print alloc2d not being allocated:

(gdb) p alloc2d
$1 = <not allocated>

That is the case when you build the code with gfortran or the old classic flang. Sadly, not with the new flang:

(gdb) p alloc2d
No symbol "alloc2d" in current context.
abidh commented 1 week ago

It is better and the tests I've quoted above are now passing. Yet still I have a test case that is failing, see:

module use_mod
  INTEGER, DIMENSION(:,:), ALLOCATABLE :: alloc2d
end module

program using_mod
  use use_mod
  ALLOCATE (alloc2d(-1:1,-2:2))
  alloc2d(:,:) = -1
end program

If you set breakpoint at the line 7 (ALLOCATE...), gdb should be able to print alloc2d not being allocated:

(gdb) p alloc2d
$1 = <not allocated>

That is the case when you build the code with gfortran or the old classic flang. Sadly, not with the new flang:

(gdb) p alloc2d
No symbol "alloc2d" in current context.

Thanks for checking. The problem you described is known. At the moment, we have to qualify the module member with its name. So if you try p use_mod::alloc2d then it should work. Please let me know if it still gives error.

pawosm-arm commented 1 week ago

Thanks for checking. The problem you described is known.

Do you know if there was a bug report opened for that?

abidh commented 1 week ago

Thanks for checking. The problem you described is known.

Do you know if there was a bug report opened for that?

https://github.com/llvm/llvm-project/issues/98883