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

[DebugInfo] Array debugging support with upgraded DISubrange #952

Merged
merged 10 commits into from
Feb 21, 2021

Conversation

alokkrsharma
Copy link
Collaborator

@alokkrsharma alokkrsharma commented Nov 18, 2020

This PR supports general array debugging (adjustable array, assumed shape array, assumed size array, allocatable and pointer array and assumed rank array).

It uses multiple upgrades to upstream LLVM which are backported to flang-LLVM as
LLVM11: flang-compiler/classic-flang-llvm-project#14
LLVM10: flang-compiler/classic-flang-llvm-project#8
LLVM9: flang-compiler/llvm#86

Please note that this PR should be able to replace existing flang-LLVM DIFortranSubrage .

@alokkrsharma
Copy link
Collaborator Author

Hi @kiranchandramohan, I have closed other subset PRs. This PR should be ready to review. Additional commit is made to make the array debugging work for current version 9 (which should be valid after backport PRs to 9 and 10 are merged).

Copy link
Contributor

@gklimowicz gklimowicz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have two internal tests that fail after applying this set of changes. We'll send you the short test cases and the errors we see when running them (related to generated debtg metadata). We see these with LLVM 9 and LLVM 10.

Other internal tests pass, so I am approving this pull request while perhaps we investigate this in the background.

@alokkrsharma
Copy link
Collaborator Author

We have two internal tests that fail after applying this set of changes. We'll send you the short test cases and the errors we see when running them (related to generated debtg metadata). We see these with LLVM 9 and LLVM 10.

Other internal tests pass, so I am approving this pull request while perhaps we investigate this in the background.

Thanks @gklimowicz , The fix is pushed, can you please check now ?

@kiranchandramohan
Copy link
Collaborator

If we do not use LLVM_FLANG_EXTENSIONS, then string will go back to using DIBasicType instead of DIString. I see that @SouraVX introduced DIStringType in https://reviews.llvm.org/D86305. Is there a corresponding Flang change?

@gklimowicz
Copy link
Contributor

Thanks @gklimowicz , The fix is pushed, can you please check now ?

@alokkrsharma I reran our tests and they do indeed pass now with your latest change.

@kiranchandramohan
Copy link
Collaborator

Debug for allocatable variables in modules seem to be missing. Can that be handled?

module mod_vars
  integer, allocatable, dimension(:)   :: patch_count
end module     

program main 
use mod_vars
end program

@SouraVX
Copy link
Collaborator

SouraVX commented Dec 17, 2020

Debug for allocatable variables in modules seem to be missing. Can that be handled?

module mod_vars
  integer, allocatable, dimension(:)   :: patch_count
end module     

program main 
use mod_vars
end program
0x0000002f:   DW_TAG_module
                DW_AT_name      ("mod_vars")

0x00000034:     DW_TAG_variable
                  DW_AT_name    ("patch_count")
                  DW_AT_type    (0x00000074 "integer[0]")
                  DW_AT_external        (0x01)
                  DW_AT_location        (DW_OP_addr 0x4040c0, DW_OP_deref)
....

It's present @kiranchandramohan. Debuggers like GDB skips parsing/reading if line and file info is not present in a FORTRAN module as a result when an end user issues command info modules no info is presented.
#898 fixes this and after applying that, GDB show correct info for info modules command.
Please note that #898 has dependency on LLVM11.

@alokkrsharma
Copy link
Collaborator Author

Debug for allocatable variables in modules seem to be missing. Can that be handled?

module mod_vars
  integer, allocatable, dimension(:)   :: patch_count
end module     

program main 
use mod_vars
end program

Can you please check the printing of variable now ?

@kiranchandramohan
Copy link
Collaborator

kiranchandramohan commented Dec 18, 2020

Thanks @alokkrsharma. I can see the debug emitted for the "patch_count" variable. But I do not see it working in gdb.

Consider the program and gdb session below. It can be seen that the value of patch_count cannot be printed.

module mod_vars 
  integer, allocatable, dimension(:)   :: patch_count
  integer :: val2
end module
 
program main 
use mod_vars
allocate(patch_count(10))
patch_count = 10 
print *, patch_count
end program
Breakpoint 1, main () at /home/kircha02/armflang/compiler_dev/build/build-flang/tmp2.f90:9
9       patch_count = 10

(gdb) info locals
No locals.
(gdb) p patch_count
Missing ELF symbol "__mod_vars_MOD_patch_count".
(gdb) p patch_count(1)
Missing ELF symbol "__mod_vars_MOD_patch_count".

The IR and debug generated is as follows. As can be seen, the debug for @mod_vars_0 is pointing to !13 (patch_count$sd) instead of !7 (patch_count). If I make this correction then I can print patch_count.

@_mod_vars_0_ = common global %struct_mod_vars_0_ zeroinitializer, align 128, !dbg !13, !dbg !19
....
!7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression(DW_OP_constu, 0, DW_OP_plus))
!8 = distinct !DIGlobalVariable(name: "patch_count", scope: !2, file: !3, type: !9, isLocal: false, isDefinition: true)
...
!13 = !DIGlobalVariableExpression(var: !14, expr: !DIExpression(DW_OP_constu, 16, DW_OP_plus))
!14 = distinct !DIGlobalVariable(name: "patch_count$sd", scope: !2, file: !3, type: !15, isLocal: false, isDefinition: true, flags: DIFlagArtificial)

@alokkrsharma
Copy link
Collaborator Author

Thanks @alokkrsharma. I can see the debug emitted for the "patch_count" variable. But I do not see it working in gdb.

Consider the program and gdb session below. It can be seen that the value of patch_count cannot be printed.

module mod_vars 
  integer, allocatable, dimension(:)   :: patch_count
  integer :: val2
end module
 
program main 
use mod_vars
allocate(patch_count(10))
patch_count = 10 
print *, patch_count
end program
Breakpoint 1, main () at /home/kircha02/armflang/compiler_dev/build/build-flang/tmp2.f90:9
9       patch_count = 10

(gdb) info locals
No locals.
(gdb) p patch_count
Missing ELF symbol "__mod_vars_MOD_patch_count".
(gdb) p patch_count(1)
Missing ELF symbol "__mod_vars_MOD_patch_count".

The IR and debug generated is as follows. As can be seen, the debug for @mod_vars_0 is pointing to !13 (patch_count$sd) instead of !7 (patch_count). If I make this correction then I can print patch_count.

@_mod_vars_0_ = common global %struct_mod_vars_0_ zeroinitializer, align 128, !dbg !13, !dbg !19
....
!7 = !DIGlobalVariableExpression(var: !8, expr: !DIExpression(DW_OP_constu, 0, DW_OP_plus))
!8 = distinct !DIGlobalVariable(name: "patch_count", scope: !2, file: !3, type: !9, isLocal: false, isDefinition: true)
...
!13 = !DIGlobalVariableExpression(var: !14, expr: !DIExpression(DW_OP_constu, 16, DW_OP_plus))
!14 = distinct !DIGlobalVariable(name: "patch_count$sd", scope: !2, file: !3, type: !15, isLocal: false, isDefinition: true, flags: DIFlagArtificial)

Thanks for pointing this out. It is fixed in latest patch. Please try.

INLINE static void
init_subrange_bound(LL_DebugInfo *db, ISZ_T *cb, LL_MDRef *bound_sptr,
SPTR sptr, ISZ_T defVal, int findex)
INLINE static void init_subrange_bound_pre11(LL_DebugInfo *db, ISZ_T *cb,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FWIW, the PGI coding standard was to keep the function names starting in column 0.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this. I have corrected this.
Now I realize it is due to tool "git-clang-format" which I use, is there any equivalent tool for PGI coding style ?

@kiranchandramohan
Copy link
Collaborator

  1. The program given below shows the following error when compiled with "-fopenmp -g".

error: '%p$sd1_317' defined with type '[16 x i64]*' but expected '[16 x i64]'
call void @llvm.dbg.declare (metadata [16 x i64]
%p$sd1_317, metadata !80, metadata !21), !dbg !72

program decl
  real, target :: x(2,1000)
  real, pointer :: p(:)
  integer :: i
  x = 5.0
  !$omp parallel do lastprivate(p)
  do i=1,1000
    p => x(:,i)
  end do
  print *, p
end program
  1. Similar error seen in the following program also
subroutine test()
  integer, pointer ::  tmp(:)
  !$omp parallel private(tmp)
  allocate(tmp(10))
  deallocate(tmp)
  !$omp end parallel
end subroutine
  1. Compilation seems to run into an infinite loop
module pdt
  type t
    procedure (func), pointer, nopass :: p
    integer, allocatable :: c(:)
  end type t
contains
  function func()
    class (t), allocatable :: func
  end function func
end module pdt

subroutine sub
  use pdt
  type (t) a(3)
end subroutine sub

@alokkrsharma
Copy link
Collaborator Author

1. The program given below shows the following error when compiled with "-fopenmp -g".

error: '%p$sd1_317' defined with type '[16 x i64]*' but expected '[16 x i64]' call void @llvm.dbg.declare (metadata [16 x i64] %p$sd1_317, metadata !80, metadata !21), !dbg !72

program decl
  real, target :: x(2,1000)
  real, pointer :: p(:)
  integer :: i
  x = 5.0
  !$omp parallel do lastprivate(p)
  do i=1,1000
    p => x(:,i)
  end do
  print *, p
end program
1. Similar error seen in the following program also
subroutine test()
  integer, pointer ::  tmp(:)
  !$omp parallel private(tmp)
  allocate(tmp(10))
  deallocate(tmp)
  !$omp end parallel
end subroutine
1. Compilation seems to run into an infinite loop
module pdt
  type t
    procedure (func), pointer, nopass :: p
    integer, allocatable :: c(:)
  end type t
contains
  function func()
    class (t), allocatable :: func
  end function func
end module pdt

subroutine sub
  use pdt
  type (t) a(3)
end subroutine sub

Thanks for pointing this out. Can you please check with updated sources ?

@bryanpkc
Copy link
Collaborator

bryanpkc commented Jan 5, 2021

I built this branch with flang-compiler/classic-flang-llvm-project#8 successfully, but the debug_info/module_allocatable_arr.f90 test would fail intermittently:

FAIL: Flang :: debug_info/module_pointer_arr.f90 (1 of 1347)
******************** TEST 'Flang :: debug_info/module_pointer_arr.f90' FAILED ********************
Script:
--
: 'RUN: at line 1';    /home/b00375952/src/cpu/llvm.orig/install/bin/flang  -gdwarf-4 -S -emit-llvm /home/b00375952/src/cpu/llvm.orig/flang/test/debug_info/module_pointer_arr.f90 -o - | /home/b00375952/src/cpu/llvm.orig/build/flang/bin/FileCheck /home/b00375952/src/cpu/llvm.orig/flang/test/debug_info/module_pointer_arr.f90
--
Exit Code: 2

Command Output (stderr):
--
F90-S-0072-Assignment operation illegal to ptr_arr - must be a POINTER variable (/home/b00375952/src/cpu/llvm.orig/flang/test/debug_info/module_pointer_arr.f90: 19)
  0 inform,   0 warnings,   1 severes, 0 fatal for main
FileCheck error: '-' is empty.
FileCheck command line:  /home/b00375952/src/cpu/llvm.orig/build/flang/bin/FileCheck /home/b00375952/src/cpu/llvm.orig/flang/test/debug_info/module_pointer_arr.f90

--

Running this test by itself seems okay, but running the whole debug_info directories would result in this test failing about 50% of the time.

@kiranchandramohan
Copy link
Collaborator

@alokkrsharma were you able to reproduce the issue?
BTW, I am having some issues with the allocated status of an array. For the program given below,
flang (clang-10) does not show the allocation status

Breakpoint 1, test () at fl.f90:4
4         allocate(vv_2(100))
(gdb) p vv_2
value requires 4294963300 bytes, which is more than max-value-size

while gfortran correctly gives the allocation status.

Breakpoint 1, test () at fl.f90:4
4         allocate(vv_2(100))
(gdb) p vv_2
$1 = <not allocated>

The debug metadata looks like the following. Should the expression for metadata !13 do a dereference or load or something?

  %.Z0631_316 = alloca float*, align 8
  ...
  call void @llvm.dbg.declare(metadata float** %.Z0631_316, metadata !9, metadata !DIExpression()), !dbg !12
  call void @llvm.dbg.declare(metadata float** %.Z0631_316, metadata !13, metadata !DIExpression()), !dbg !12
  ...
  !9 = distinct !DILocalVariable(scope: !5, file: !3, type: !10, flags: DIFlagArtificial)
...
!13 = distinct !DILocalVariable(scope: !5, file: !3, type: !14, flags: DIFlagArtificial)
...
!20 = !DILocalVariable(name: "vv_2", scope: !5, file: !3, type: !21)
!21 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 32, align: 32, elements: !22, dataLocation: !9, allocated: !13)
program test
  real, dimension(:), allocatable :: vv_2
  print *, 'vv_2 is declared but not initialized'
  allocate(vv_2(100))
end

Thanks for sharing this.

In short, it does not look like an issue. Following is the explanation.

I could see the issue as follows.

(gdb) p vv_2
value requires 562949416519096 bytes, which is more than max-value-size
(gdb) n
3         print *, 'vv_2 is declared but not initialized'
(gdb) p vv_2
$1 = <not allocated>

As it can be seen allocated status is displayed correctly on line 2 and incorrectly on line 1 (before some needed initialization)

In addition to IR you pasted above. Please note below instruction.

%2 = bitcast float** %.Z0631_316 to i8**, !dbg !8
store i8* null, i8** %2, align 8, !dbg !8

This is the initialization line before its execution, absurd results are expected as at line 1. Incorrect results can also be displayed in case this line is moved / optimized out by compiler. (I tested with "-g" and default optimization options on x86)

This issue can be avoided if you cherry-pick prologue related commit.
Please do let me know if my understanding is correct.

I tried with gdb-10.1 and it worked. Is the patch present in 10.1?

@alokkrsharma
Copy link
Collaborator Author

@alokkrsharma were you able to reproduce the issue?
BTW, I am having some issues with the allocated status of an array. For the program given below,
flang (clang-10) does not show the allocation status

Breakpoint 1, test () at fl.f90:4
4         allocate(vv_2(100))
(gdb) p vv_2
value requires 4294963300 bytes, which is more than max-value-size

while gfortran correctly gives the allocation status.

Breakpoint 1, test () at fl.f90:4
4         allocate(vv_2(100))
(gdb) p vv_2
$1 = <not allocated>

The debug metadata looks like the following. Should the expression for metadata !13 do a dereference or load or something?

  %.Z0631_316 = alloca float*, align 8
  ...
  call void @llvm.dbg.declare(metadata float** %.Z0631_316, metadata !9, metadata !DIExpression()), !dbg !12
  call void @llvm.dbg.declare(metadata float** %.Z0631_316, metadata !13, metadata !DIExpression()), !dbg !12
  ...
  !9 = distinct !DILocalVariable(scope: !5, file: !3, type: !10, flags: DIFlagArtificial)
...
!13 = distinct !DILocalVariable(scope: !5, file: !3, type: !14, flags: DIFlagArtificial)
...
!20 = !DILocalVariable(name: "vv_2", scope: !5, file: !3, type: !21)
!21 = !DICompositeType(tag: DW_TAG_array_type, baseType: !11, size: 32, align: 32, elements: !22, dataLocation: !9, allocated: !13)
program test
  real, dimension(:), allocatable :: vv_2
  print *, 'vv_2 is declared but not initialized'
  allocate(vv_2(100))
end

Thanks for sharing this.
In short, it does not look like an issue. Following is the explanation.
I could see the issue as follows.

(gdb) p vv_2
value requires 562949416519096 bytes, which is more than max-value-size
(gdb) n
3         print *, 'vv_2 is declared but not initialized'
(gdb) p vv_2
$1 = <not allocated>

As it can be seen allocated status is displayed correctly on line 2 and incorrectly on line 1 (before some needed initialization)
In addition to IR you pasted above. Please note below instruction.

%2 = bitcast float** %.Z0631_316 to i8**, !dbg !8
store i8* null, i8** %2, align 8, !dbg !8

This is the initialization line before its execution, absurd results are expected as at line 1. Incorrect results can also be displayed in case this line is moved / optimized out by compiler. (I tested with "-g" and default optimization options on x86)
This issue can be avoided if you cherry-pick prologue related commit.
Please do let me know if my understanding is correct.

I tried with gdb-10.1 and it worked. Is the patch present in 10.1?

Yes, GDB fix should be present in 10.1 and to include Flang fix for prologue #940 I have re-based the current PR.

@kiranchandramohan
Copy link
Collaborator

@alokkrsharma Can you rebase the PR to run the CI? I think once it passes we can merge it.

@kiranchandramohan
Copy link
Collaborator

@alokkrsharma Assuming the test fails since some of the relevant patches are not in llvm-11.

Copy link
Collaborator

@kiranchandramohan kiranchandramohan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is great work. Thanks for your patience.

Unfortunately, I do not have sufficient time to review this properly. At the same time we have delayed this PR for too long. Since we have tested it fairly well we will go ahead with this now.

If you get time please add all the macros that you used for arrays to the documentation in some page.

What can we do about the release_11x branch? Would cherry-picking the relevant debug commits there be too much work? Apologies for this, a timely review would have avoided the need for this.

@alokkrsharma
Copy link
Collaborator Author

@alokkrsharma Assuming the test fails since some of the relevant patches are not in llvm-11.

Yes, release_11x test fail due to this. Errors like these suggest this.
"error: invalid field 'associated'"
But I am not sure why other checks show as 'cancelled' ?

@alokkrsharma
Copy link
Collaborator Author

This is great work. Thanks for your patience.

Unfortunately, I do not have sufficient time to review this properly. At the same time we have delayed this PR for too long. Since we have tested it fairly well we will go ahead with this now.

If you get time please add all the macros that you used for arrays to the documentation in some page.

What can we do about the release_11x branch? Would cherry-picking the relevant debug commits there be too much work? Apologies for this, a timely review would have avoided the need for this.

Thanks a lot for your quality time on this.
I have raised another pull request for release_11x branch as flang-compiler/classic-flang-llvm-project#14
Please review that as well.

@alokkrsharma
Copy link
Collaborator Author

There is one more issue, but it seems to only happen when not using fast-isel or global-isel at O0. I don't know whether that is a setting that you use. Anyway this need not be a blocker.
It will generate Machine IR with a dbg_value that does not have a register as the first argument. The variable corresponding to this value is the dataLocation of the DICompositeType with DW_TAG_array-type.

  DBG_VALUE $noreg, $noreg, !"arr_dat_loc", !DIExpression(), debug-location !52; min.f90:0 line no:0

In DWARF it will manifest as a DW_TAG_variable without a DW_AT_location.
I don't know whether there is an option to switch off fast-isel from the flang command line. You can generate the llvm IR with debug and then run the following command to reproduce the issue.

llc -O0 -fast-isel=false -global-isel=false debug.ll -filetype=obj -o output.o --print-machineinstrs

Reproducer

program test
interface
subroutine assumed_shape_2d(name, arr)
  character*(*) :: name
  integer :: arr(:,:)
end subroutine
end interface

integer, dimension(-2:2,-3:3), target :: storage1_2d

storage1_2d=-1
storage1_2d(-2,-3)=-2
storage1_2d(2,3)=-3

call assumed_shape_2d('storage1_2d', storage1_2d)

write(*,*) 'end of program'
end

subroutine assumed_shape_2d(name, arr)
implicit none
character*(*) :: name
integer :: arr(:,:)

print *,"assumed_shape_2d: ",name," = ",arr
print *, arr(1,1)
call break_in_assumed_shape_2d()
end

subroutine break_in_assumed_shape_2d()
end

Thanks for reporting this. I'll look into it.

This is fixed.

@alokkrsharma
Copy link
Collaborator Author

Hi @bryanpkc , do you have any more comment on this ?

@kiranchandramohan
Copy link
Collaborator

There is one more issue, but it seems to only happen when not using fast-isel or global-isel at O0. I don't know whether that is a setting that you use. Anyway this need not be a blocker.
It will generate Machine IR with a dbg_value that does not have a register as the first argument. The variable corresponding to this value is the dataLocation of the DICompositeType with DW_TAG_array-type.

  DBG_VALUE $noreg, $noreg, !"arr_dat_loc", !DIExpression(), debug-location !52; min.f90:0 line no:0

In DWARF it will manifest as a DW_TAG_variable without a DW_AT_location.
I don't know whether there is an option to switch off fast-isel from the flang command line. You can generate the llvm IR with debug and then run the following command to reproduce the issue.

llc -O0 -fast-isel=false -global-isel=false debug.ll -filetype=obj -o output.o --print-machineinstrs

Reproducer

program test
interface
subroutine assumed_shape_2d(name, arr)
  character*(*) :: name
  integer :: arr(:,:)
end subroutine
end interface

integer, dimension(-2:2,-3:3), target :: storage1_2d

storage1_2d=-1
storage1_2d(-2,-3)=-2
storage1_2d(2,3)=-3

call assumed_shape_2d('storage1_2d', storage1_2d)

write(*,*) 'end of program'
end

subroutine assumed_shape_2d(name, arr)
implicit none
character*(*) :: name
integer :: arr(:,:)

print *,"assumed_shape_2d: ",name," = ",arr
print *, arr(1,1)
call break_in_assumed_shape_2d()
end

subroutine break_in_assumed_shape_2d()
end

Thanks for reporting this. I'll look into it.

This is fixed.

@alokkrsharma Thanks. Is this a big change? I could not make out from the last commit. Could you add a small description?

@alokkrsharma
Copy link
Collaborator Author

There is one more issue, but it seems to only happen when not using fast-isel or global-isel at O0. I don't know whether that is a setting that you use. Anyway this need not be a blocker.
It will generate Machine IR with a dbg_value that does not have a register as the first argument. The variable corresponding to this value is the dataLocation of the DICompositeType with DW_TAG_array-type.

  DBG_VALUE $noreg, $noreg, !"arr_dat_loc", !DIExpression(), debug-location !52; min.f90:0 line no:0

In DWARF it will manifest as a DW_TAG_variable without a DW_AT_location.
I don't know whether there is an option to switch off fast-isel from the flang command line. You can generate the llvm IR with debug and then run the following command to reproduce the issue.

llc -O0 -fast-isel=false -global-isel=false debug.ll -filetype=obj -o output.o --print-machineinstrs

Reproducer

program test
interface
subroutine assumed_shape_2d(name, arr)
  character*(*) :: name
  integer :: arr(:,:)
end subroutine
end interface

integer, dimension(-2:2,-3:3), target :: storage1_2d

storage1_2d=-1
storage1_2d(-2,-3)=-2
storage1_2d(2,3)=-3

call assumed_shape_2d('storage1_2d', storage1_2d)

write(*,*) 'end of program'
end

subroutine assumed_shape_2d(name, arr)
implicit none
character*(*) :: name
integer :: arr(:,:)

print *,"assumed_shape_2d: ",name," = ",arr
print *, arr(1,1)
call break_in_assumed_shape_2d()
end

subroutine break_in_assumed_shape_2d()
end

Thanks for reporting this. I'll look into it.

This is fixed.

@alokkrsharma Thanks. Is this a big change? I could not make out from the last commit. Could you add a small description?

Please consider the change in (debug) IR for newly added test assumed_shape_noopt.f90
Before fix:

define void @show_(i64* %array, i64* %"array$sd") #0 !dbg !25 {  <---------------(A)
   . . .
  call void @llvm.dbg.value(metadata i64* %array, metadata !38, metadata !DIExpression()), !dbg !39
  call void @llvm.dbg.declare(metadata i64* %"array$sd", metadata !40, metadata !DIExpression()), !dbg !39
  . . . 
!38 = distinct !DILocalVariable(scope: !25, file: !3, type: !32, flags: DIFlagArtificial) <----------------(B1)
!40 = !DILocalVariable(name: "array", arg: 1, scope: !25, file: !3, line: 16, type: !41)
!41 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, align: 32, elements: !42, dataLocation: !38) <--- (C)

After fix:

define void @show_(i64* %array, i64* %"array$sd") #0 !dbg !25 {
    . . .
  call void @llvm.dbg.value(metadata i64* %array, metadata !38, metadata !DIExpression()), !dbg !39
  call void @llvm.dbg.declare(metadata i64* %"array$sd", metadata !40, metadata !DIExpression()), !dbg !39
    . . .
!38 = !DILocalVariable(arg: 1, scope: !25, file: !3, line: 16, type: !32)  <------- (B2)
!40 = !DILocalVariable(name: "array", arg: 2, scope: !25, file: !3, line: 16, type: !41)
!41 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, align: 32, elements: !42, dataLocation: !38)

There is a minor change in statement B1(before fix) and B2(after fix) as after fix, this artificial variable is marked as an "arg:". Looking at the statement A, this is correct and helps in not getting optimized out.

Copy link
Collaborator

@bryanpkc bryanpkc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @bryanpkc , do you have any more comment on this ?

I had some problems merging this patch into our internal repo, but the vanilla Flang build seemed okay to me. I agree with Kiran, with the amount of review and testing already done, we should go ahead with it.

@kiranchandramohan
Copy link
Collaborator

@alokkrsharma can you push to trigger a fresh run of the CI? If it is green I will merge.

Note: This modification makes use of recent upgrade to DISubrange
    https://reviews.llvm.org/rGd20bf5a7258d4b6a7f017a81b125275dac1aa166

Currently flang generates 0 sized DISubrange metadata for assumed sahpe arrays.

---------
test case
---------
subroutine sub(assume,n1,n2)
  dimension assume(n1,n2)
end subroutine sub
-------
LLVM IR
-------
!29 = !DILocalVariable(name: "assume", arg: 1, scope: !26, file: !3, type: !30)
!30 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, align: 32, elements: !31)
!31 = !{!32, !32}
!32 = !DISubrange(count: 0, lowerBound: 1)
-------
This is fixed by upgrading DISubrange as it is upgraded in LLVM to be able to
dump proper DISubrange for assumed shape array.
-------
!29 = !DILocalVariable(name: "assume", arg: 1, scope: !26, file: !3, type: !30)
!30 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, align: 32, elements: !31)
!31 = !{!32, !36}
!32 = !DISubrange(lowerBound: 1, upperBound: !33)
!33 = distinct !DILocalVariable(scope: !34, file: !3, type: !35, flags: DIFlagArtificial)
!36 = !DISubrange(lowerBound: 1, upperBound: !37)
!37 = distinct !DILocalVariable(scope: !34, file: !3, type: !35, flags: DIFlagArtificial)
-------
Note: This modification makes use of recent upgrade to DISubrange
https://reviews.llvm.org/rGd20bf5a7258d4b6a7f017a81b125275dac1aa166

Now, below testcase gives desired results with debugger.
--------------
program main
  integer, allocatable  :: arr(:)
  allocate (arr(2:10))
  arr(3) = 9
end program main
--------------
(gdb) pt arr
type = integer (2:10)
(gdb) p arr
$1 = (0, 9, 0, 0, 0, 0, 0, 0, 0)
--------------
And below case works as well
--------------
program main
type dt
  integer :: var1
  integer :: var2
  integer, allocatable :: arr1 (:,:)
  integer :: var3
end type dt
type(dt) :: dvar1
dvar1%var1 = 21
dvar1%var2 = 22
dvar1%var3 = 23
allocate (dvar1%arr1(2:9, 3:11))
dvar1%arr1(5,4) = 11
end program main
--------------
(gdb) pt dvar1
type = Type dt
integer :: var1
integer :: var2
integer :: arr1(2:9,3:11)
integer :: var3
End Type dt
(gdb) p dvar1%arr1
$2 = (( 0, 0, 0, 0, 0, 0, 0, 0) ( 0, 0, 0, 11, 0, 0, 0, 0) ( 0, 0, 0, 0, 0, 0, 0, 0) ( 0, 0, 0, 0, 0, 0, 0, 0) ( 0, 0, 0, 0, 0, 0, 0, 0) ( 0, 0, 0, 0, 0, 0, 0, 0) ( 0, 0, 0, 0, 0, 0, 0, 0) ( 0, 0, 0, 0, 0, 0, 0, 0) ( 0, 0, 0, 0, 0, 0, 0, 0) )
---------------
    This patch makes use of commited llvm patch
      [DebugInfo] Support for DW_AT_associated and DW_AT_allocated.
      https://reviews.llvm.org/rG2d10258a31a6d05368dfd4442c4aaa7b54614f1e

    This fix is needed for allocatable/pointer arrays.

    for pointer array (before allocation/association)
    Before fix
    ------
    (gdb) pt ptr
    type = integer (140737345375288:140737354129776)
    (gdb) p ptr
    value requires 35017956 bytes, which is more than max-value-size
    ------
    After fix
    ------
    (gdb) pt ptr
    type = integer (:)
    (gdb) p ptr
    $1 = <not associated>
    ------
    for allocatable array (before allocation)
    Before fix
    ------
    (gdb) pt arr
    type = integer (140737345375288:140737354129776)
    (gdb) p arr
    value requires 35017956 bytes, which is more than max-value-size
    ------
    After fix
    ------
    (gdb) pt arr
    type = integer, allocatable (:)
    (gdb) p arr
    $1 = <not allocated>
    ------

Testing:
    - check-flang
…d away

Base address of assumed shape array is marked as 'dataLocation' field of
array type, this is an artifical variable earlier mentioned as DW_TAG_variable.
With below options this artificial variable is optimized out.
%flang -g -S -emit-llvm test/debug_info/assumed_shape_noopt.f90
%llc -O0 -fast-isel=false -global-isel=false -filetype=obj assumed_shape_noopt.ll
Marking this variable as DW_TAG_formal_parameter is a right thing to do and also
avoids optimization.
@alokkrsharma
Copy link
Collaborator Author

@alokkrsharma can you push to trigger a fresh run of the CI? If it is green I will merge.

All checks have passed. Thanks in advance.

@alokkrsharma
Copy link
Collaborator Author

alokkrsharma commented Feb 20, 2021

Hi @bryanpkc , do you have any more comment on this ?

I had some problems merging this patch into our internal repo, but the vanilla Flang build seemed okay to me. I agree with Kiran, with the amount of review and testing already done, we should go ahead with it.

Thanks @bryanpkc for your quality time review. It helped a lot.

@bryanpkc bryanpkc merged commit 73be625 into flang-compiler:master Feb 21, 2021
@kiranchandramohan
Copy link
Collaborator

kiranchandramohan commented Feb 22, 2021

@alokkrsharma is the following gdb patch required for allocation status to work correctly?

commit 9cdf98207c5bab668e3734d11d5a24d6b5375b54
Author: Alok Kumar Sharma [email protected]
Date: Wed Jul 1 11:53:09 2020 +0530

Allow reference form for DW_AT_associated and DW_AT_allocated attributes

Currently, GDB rejects the (die) reference form while it accepts exprloc
form. It is allowed in DWARF standard. "Table 7.5: Attribute encodings"
in DWARF5 standard. Flang compiler assigns (die) reference to
DW_AT_associated and DW_AT_allocated for some cases.

gdb/ChangeLog

        * dwarf2/read.c (set_die_type): Removed conditions to restrict
        forms for DW_AT_associated and DW_AT_allocated attributes,
        which is already checked in function attr_to_dynamic_prop.

@alokkrsharma
Copy link
Collaborator Author

@alokkrsharma is the following gdb patch required for allocation status to work correctly?

commit 9cdf98207c5bab668e3734d11d5a24d6b5375b54
Author: Alok Kumar Sharma [email protected]
Date: Wed Jul 1 11:53:09 2020 +0530

Allow reference form for DW_AT_associated and DW_AT_allocated attributes

Currently, GDB rejects the (die) reference form while it accepts exprloc
form. It is allowed in DWARF standard. "Table 7.5: Attribute encodings"
in DWARF5 standard. Flang compiler assigns (die) reference to
DW_AT_associated and DW_AT_allocated for some cases.

gdb/ChangeLog

        * dwarf2/read.c (set_die_type): Removed conditions to restrict
        forms for DW_AT_associated and DW_AT_allocated attributes,
        which is already checked in function attr_to_dynamic_prop.

Yes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants