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

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

Closed
pawosm-arm opened this issue Jul 2, 2024 · 11 comments · Fixed by #98661
Assignees

Comments

@pawosm-arm
Copy link
Contributor

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.

@github-actions github-actions bot added the flang Flang issues not falling into any other category label Jul 2, 2024
@EugeneZelenko EugeneZelenko added debuginfo flang:ir and removed flang Flang issues not falling into any other category labels Jul 2, 2024
@llvmbot
Copy link
Member

llvmbot commented Jul 2, 2024

@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.

</details>

@llvmbot
Copy link
Member

llvmbot commented Jul 2, 2024

@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.

</details>

@abidh
Copy link
Contributor

abidh commented Jul 3, 2024

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
Copy link
Contributor Author

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
Copy link
Contributor

abidh commented Jul 3, 2024

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 added a commit to abidh/llvm-project that referenced this issue Jul 12, 2024
This PR fixes 2 similar issues.
1. As reported in llvm#97476, flang generated executable has inconsistent
behavior regarding values of the local array variables.
2. Variable with save attribute would not show up in debugger.

The reason behind is same for both cases. If a local variable has
storage which extends beyond function lifetime, the way to represent
it in the debug info is through a global variable whose scope is limited
to the function. This is what is used for static local variable in C.
Previously local array worked in cases they were on stack. But will not
show up if they had a global storage.

To fix this, if we can get a corresponding GlobalOp for a variable while
processing DeclareOp, we treat it as a global variable.
@abidh
Copy link
Contributor

abidh commented Jul 12, 2024

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
Copy link
Contributor

abidh commented Jul 12, 2024

@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
Copy link
Contributor Author

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
Copy link
Contributor

abidh commented Jul 15, 2024

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
Copy link
Contributor Author

pawosm-arm commented Jul 16, 2024

Thanks for checking. The problem you described is known.

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

@abidh
Copy link
Contributor

abidh commented Jul 16, 2024

Thanks for checking. The problem you described is known.

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

#98883

@abidh abidh closed this as completed in 20c6b9f Jul 17, 2024
sgundapa pushed a commit to sgundapa/upstream_effort that referenced this issue Jul 23, 2024
This PR fixes 2 similar issues.
1. As reported in llvm#97476, flang generated executable has inconsistent
behavior regarding values of the local array variables.
2. Variable with save attribute would not show up in debugger.

The reason behind is same for both cases. If a local variable has
storage which extends beyond function lifetime, the way to represent it
in the debug info is through a global variable whose scope is limited to
the function. This is what is used for static local variable in C.
Previously local array worked in cases they were on stack. But will not
show up if they had a global storage.

To fix this, if we can get a corresponding `GlobalOp` for a variable
while processing `DeclareOp`, we treat it the variable as global with
scope set appropriately. A new FIR test is added. A previous Integration
test has been adjusted as to not expect local variables for local
arrays.

With this fix in place, all the issues described in llvm#97476 go away. It
also fixes a lot of fails in GDB's fortran testsuite.

Fixes llvm#97476.
yuxuanchen1997 pushed a commit that referenced this issue Jul 25, 2024
Summary:
This PR fixes 2 similar issues.
1. As reported in #97476, flang generated executable has inconsistent
behavior regarding values of the local array variables.
2. Variable with save attribute would not show up in debugger.

The reason behind is same for both cases. If a local variable has
storage which extends beyond function lifetime, the way to represent it
in the debug info is through a global variable whose scope is limited to
the function. This is what is used for static local variable in C.
Previously local array worked in cases they were on stack. But will not
show up if they had a global storage.

To fix this, if we can get a corresponding `GlobalOp` for a variable
while processing `DeclareOp`, we treat it the variable as global with
scope set appropriately. A new FIR test is added. A previous Integration
test has been adjusted as to not expect local variables for local
arrays.

With this fix in place, all the issues described in #97476 go away. It
also fixes a lot of fails in GDB's fortran testsuite.

Fixes #97476.

Test Plan: 

Reviewers: 

Subscribers: 

Tasks: 

Tags: 


Differential Revision: https://phabricator.intern.facebook.com/D60250985
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants