Page MenuHomePhabricator

Adding debug info to support Fortran (part 3)
Needs ReviewPublic

Authored by schweitz on Nov 9 2018, 9:17 AM.

Details

Summary
  1. Fortran COMMON Block

COMMON blocks are a feature of Fortran that has no direct analog in C languages, but they are similar to data sections in assembly language programming. A COMMON block is a named area of memory that holds a collection of variables. Fortran subprograms may map the COMMON block memory area to their own, possibly distinct, non-empty list of variables. A Fortran COMMON block might look like the following example.

COMMON /ALPHA/ I, J

For this construct, the compiler generates a new scope-like DI construct (!DICommonBlock) into which variables (see I, J above) can be placed. As the common block implies a range of storage with global lifetime, the !DICommonBlock refers to a !DIGlobalVariable. The Fortran variable that comprise the COMMON block are also linked via metadata to offsets within the global variable that stands for the entire common block.

@alpha_ = common global %alphabytes_ zeroinitializer, align 64, !dbg !27, !dbg !30, !dbg !33
!14 = distinct !DISubprogram(…)
!20 = distinct !DICommonBlock(scope: !14, declaration: !25, name: "alpha")
!25 = distinct !DIGlobalVariable(scope: !20, name: "common alpha", type: !24)
!27 = !DIGlobalVariableExpression(var: !25, expr: !DIExpression())
!29 = distinct !DIGlobalVariable(scope: !20, name: "i", file: !3, type: !28)
!30 = !DIGlobalVariableExpression(var: !29, expr: !DIExpression())
!31 = distinct !DIGlobalVariable(scope: !20, name: "j", file: !3, type: !28)
!32 = !DIExpression(DW_OP_plus_uconst, 4)
!33 = !DIGlobalVariableExpression(var: !31, expr: !32)

The DWARF generated for this is as follows.

DW_TAG_common_block:
DW_AT_name: alpha
DW_AT_location: @alpha_+0
DW_TAG_variable:
DW_AT_name: common alpha
DW_AT_type: array of 8 bytes
DW_AT_location: @alpha_+0
DW_TAG_variable:
DW_AT_name: i
DW_AT_type: integer*4
DW_AT_location: @Alpha+0
DW_TAG_variable:
DW_AT_name: j
DW_AT_type: integer*4
DW_AT_location: @Alpha+4

Diff Detail

Repository
rL LLVM

Event Timeline

schweitz created this revision.Nov 9 2018, 9:17 AM

I don't understand the need for the "common alpha" global variable. For VMS Fortran on Itanium (not LLVM), we generate the following DWARF for

COMMON /ALPHA/ I,J

0x0000008f:     DW_TAG_common_block [5] *
                  DW_AT_name [DW_FORM_string]	("ALPHA")
                  DW_AT_location [DW_FORM_block1]	(<0x09> 03 00 00 00 00 00 00 00 00 )

0x000000a0:       DW_TAG_base_type [6]  
                    DW_AT_name [DW_FORM_string]	("integer*4")
                    DW_AT_encoding [DW_FORM_data1]	(0x05)
                    DW_AT_byte_size [DW_FORM_udata]	(4)

0x000000ad:       DW_TAG_variable [4]  
                    DW_AT_name [DW_FORM_string]	("I")
                    DW_AT_type [DW_FORM_ref4]	(cu + 0x00a0 => {0x000000a0})
                    DW_AT_location [DW_FORM_block1]	(<0x09> 03 00 00 00 00 00 00 00 00 )

0x000000be:       DW_TAG_variable [4]  
                    DW_AT_name [DW_FORM_string]	("J")
                    DW_AT_type [DW_FORM_ref4]	(cu + 0x00a0 => {0x000000a0})
                    DW_AT_location [DW_FORM_block1]	(<0x09> 03 00 00 00 00 00 00 00 00 )

0x000000cf:       NULL

0x000000d0:     DW_TAG_common_inclusion [7]  
                  DW_AT_common_reference [DW_FORM_ref4]	(cu + 0x008f => {0x0000008f})

with 3 DIRLSB64s relocations for the DW_AT_locations

[I don't have an Itanium obdump so forgive our platform-specific format]

                   Relocation Entry 3.
00000AE8 00000048    Sec. 21. offset affected:   0000000000000098                                       rela$pq_r_offset
                     Relocation Entry Info:      0000000700000027                                       rela$q_r_info
00000AF0 00000050      Relocation Type:                  00000027          DIR64LSB                     rela$l_r_type
00000AF4 00000054      Sec 12. Sym Index:                00000007       7.                              rela$l_r_sym
                       Symbol Bound to Section:          00000008       8. "ALPHA"
00000AF8 00000058    Relocation addend:          0000000000000000                                       rela$q_r_addend
                   Relocation Entry 4.
00000B00 00000060    Sec. 21. offset affected:   00000000000000B6                                       rela$pq_r_offset
                     Relocation Entry Info:      0000000700000027                                       rela$q_r_info
00000B08 00000068      Relocation Type:                  00000027          DIR64LSB                     rela$l_r_type
00000B0C 0000006C      Sec 12. Sym Index:                00000007       7.                              rela$l_r_sym
                       Symbol Bound to Section:          00000008       8. "ALPHA"
00000B10 00000070    Relocation addend:          0000000000000000                                       rela$q_r_addend
                   Relocation Entry 5.
00000B18 00000078    Sec. 21. offset affected:   00000000000000C7                                       rela$pq_r_offset
                     Relocation Entry Info:      0000000700000027                                       rela$q_r_info
00000B20 00000080      Relocation Type:                  00000027          DIR64LSB                     rela$l_r_type
00000B24 00000084      Sec 12. Sym Index:                00000007       7.                              rela$l_r_sym
                       Symbol Bound to Section:          00000008       8. "ALPHA"
00000B28 00000088    Relocation addend:          0000000000000004                                       rela$q_r_addend

This will also need assembler roundtrip tests in tests/Assembler.

lib/IR/LLVMContextImpl.h
805

Why does a common block have an alignment?

I don't understand the need for the "common alpha" global variable.

It's not strictly required to have it explicitly named. Our implementation allocates a COMMON block as an "untyped" block of memory and each subprogram can, of course, remap the storage units to its own list of variable names. The DW_TAG_common_block does require a DW_AT_location, and the !DIGlobalVariable fulfills that requirement.

schweitz added inline comments.Nov 9 2018, 1:20 PM
lib/IR/LLVMContextImpl.h
805

Good point. It seems like the alignment of the global storage would suffice.

dblaikie added inline comments.
include/llvm/IR/DebugInfoMetadata.h
2619

Probably skip this as it's the implicit default?

(I see this seems to have been defaulted all over the Metadata hierarchy - so far as I can tell, still unnecessary in all those places & no need to propagate this around further?)

I don't understand the need for the "common alpha" global variable.

It's not strictly required to have it explicitly named. Our implementation allocates a COMMON block as an "untyped" block of memory and each subprogram can, of course, remap the storage units to its own list of variable names. The DW_TAG_common_block does require a DW_AT_location, and the !DIGlobalVariable fulfills that requirement.

Ah, yes I see. I forgot that for us, we have a platform-specific ELF section flag for "overlay" sections which are common blocks. We don't need the extra hidden weak variable to be the intermediate allocator.

schweitz updated this revision to Diff 174456.Nov 16 2018, 2:42 PM

Remove alignment (not needed for DW_TAG_common_block).
Remove default dtor. (not needed)
Add both an llc test and a llvm-as | llvm-dis loop test.

I believe all the comments have been addressed. Is there anything else required on our end with this one?

I am curious how debug info for common blocks plays with LTO. I think we would not want different common-block descriptions to be de-duplicated just because the global name was the same.