1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-25 20:23:11 +01:00

[DebugInfo] Support for DWARF operator DW_OP_over

LLVM rejects DWARF operator DW_OP_over. This DWARF operator is needed
for Flang to support assumed rank array.

  Summary:
Currently LLVM rejects DWARF operator DW_OP_over. Below error is
produced when llvm finds this operator.
[..]
invalid expression
!DIExpression(151, 20, 16, 48, 30, 35, 80, 34, 6)
warning: ignoring invalid debug info in over.ll
[..]
There were some parts missing in support of this operator, which are
now completed.

  Testing
-added a unit testcase
-check-debuginfo
-check-llvm

Reviewed By: aprantl

Differential Revision: https://reviews.llvm.org/D89208
This commit is contained in:
Alok Kumar Sharma 2020-10-17 08:24:08 +05:30
parent cf43cfffa7
commit b846ffc438
5 changed files with 98 additions and 0 deletions

View File

@ -5210,6 +5210,10 @@ The current supported opcode vocabulary is limited:
- ``DW_OP_push_object_address`` pushes the address of the object which can then
serve as a descriptor in subsequent calculation. This opcode can be used to
calculate bounds of fortran allocatable array which has array descriptors.
- ``DW_OP_over`` duplicates the entry currently second in the stack at the top
of the stack. This opcode can be used to calculate bounds of fortran assumed
rank array which has rank known at run time and current dimension number is
implicitly first element of the stack.
DWARF specifies three kinds of simple location descriptions: Register, memory,
and implicit location descriptions. Note that a location description is

View File

@ -525,6 +525,7 @@ void DwarfExpression::addExpression(DIExpressionCursor &&ExprCursor,
case dwarf::DW_OP_not:
case dwarf::DW_OP_dup:
case dwarf::DW_OP_push_object_address:
case dwarf::DW_OP_over:
emitOp(OpNum);
break;
case dwarf::DW_OP_deref:

View File

@ -1060,6 +1060,7 @@ bool DIExpression::isValid() const {
case dwarf::DW_OP_regx:
case dwarf::DW_OP_bregx:
case dwarf::DW_OP_push_object_address:
case dwarf::DW_OP_over:
break;
}
}

View File

@ -0,0 +1,10 @@
;; This test checks processing of DWARF operator DW_OP_over.
; RUN: llvm-as < %s | llvm-dis | llvm-as | llvm-dis | FileCheck %s
; CHECK: !DIExpression(DW_OP_push_object_address, DW_OP_over, DW_OP_constu, 48, DW_OP_mul, DW_OP_plus_uconst, 88, DW_OP_plus, DW_OP_deref)
; ModuleID = 'DW_OP_over.f90'
source_filename = "/dir/DW_OP_over.ll"
!named = !{!DIExpression(DW_OP_push_object_address, DW_OP_over, DW_OP_constu, 48, DW_OP_mul, DW_OP_plus_uconst, 88, DW_OP_plus, DW_OP_deref)}

View File

@ -0,0 +1,82 @@
; RUN: llc %s -filetype=obj -o %t.o
; RUN: llvm-dwarfdump %t.o | FileCheck %s
; Test whether DW_OP_over is processed properly.
; CHECK-LABEL: DW_TAG_array_type
; CHECK-LABEL: DW_TAG_array_type
; CHECK-NOT: DW_TAG
; CHECK: DW_AT_data_location
; CHECK: DW_AT_allocated
; CHECK: DW_TAG_subrange_type
; CHECK: DW_AT_lower_bound (DW_OP_push_object_address, DW_OP_over, DW_OP_constu 0x30, DW_OP_mul, DW_OP_plus_uconst 0x50, DW_OP_plus, DW_OP_deref)
; CHECK: DW_AT_upper_bound (DW_OP_push_object_address, DW_OP_over, DW_OP_constu 0x30, DW_OP_mul, DW_OP_plus_uconst 0x78, DW_OP_plus, DW_OP_deref)
; CHECK: DW_AT_byte_stride (DW_OP_push_object_address, DW_OP_over, DW_OP_constu 0x30, DW_OP_mul, DW_OP_plus_uconst 0x70, DW_OP_plus, DW_OP_deref, DW_OP_lit4, DW_OP_mul)
; CHECK: DW_TAG_subrange_type
; CHECK DW_AT_lower_bound (DW_OP_push_object_address, DW_OP_plus_uconst 0x80, DW_OP_deref)
; CHECK DW_AT_upper_bound (DW_OP_push_object_address, DW_OP_plus_uconst 0xa8, DW_OP_deref)
; CHECK DW_AT_byte_stride (DW_OP_push_object_address, DW_OP_plus_uconst 0xa0, DW_OP_deref, DW_OP_lit4, DW_OP_mul)
; CHECK: DW_TAG_subrange_type
; CHECK DW_AT_lower_bound (DW_OP_push_object_address, DW_OP_plus_uconst 0xb0, DW_OP_deref)
; CHECK DW_AT_upper_bound (DW_OP_push_object_address, DW_OP_plus_uconst 0xd8, DW_OP_deref)
; CHECK DW_AT_byte_stride (DW_OP_push_object_address, DW_OP_plus_uconst 0xd0, DW_OP_deref, DW_OP_lit4, DW_OP_mul)
; Test case is hand written with the help of below Fortran source program.
; Generated IR is meaning less and goal of it is just to check the
; processing of DWARF operator DW_OP_over.
;------------------------------
;program main
;integer, allocatable :: arr(:,:,:)
;allocate(arr(2:20,3:30,4:40))
;arr(2,3,4)=99
;print *, arr
;end program main
;------------------------------
; ModuleID = 'over.ll'
source_filename = "allocated.ll"
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-unknown-linux-gnu"
define void @MAIN_() !dbg !5 {
L.entry:
%.Z0655_362 = alloca i32*, align 8
%"arr$sd1_379" = alloca [28 x i64], align 8
call void @llvm.dbg.declare(metadata i32** %.Z0655_362, metadata !8, metadata !DIExpression()), !dbg !11
call void @llvm.dbg.declare(metadata i32** %.Z0655_362, metadata !12, metadata !DIExpression()), !dbg !11
call void @llvm.dbg.declare(metadata [28 x i64]* %"arr$sd1_379", metadata !14, metadata !DIExpression()), !dbg !11
call void @llvm.dbg.declare(metadata [28 x i64]* %"arr$sd1_379", metadata !19, metadata !DIExpression()), !dbg !11
ret void, !dbg !25
}
; Function Attrs: nounwind readnone speculatable willreturn
declare void @llvm.dbg.declare(metadata, metadata, metadata)
!llvm.module.flags = !{!0, !1}
!llvm.dbg.cu = !{!2}
!0 = !{i32 2, !"Dwarf Version", i32 4}
!1 = !{i32 2, !"Debug Info Version", i32 3}
!2 = distinct !DICompileUnit(language: DW_LANG_Fortran90, file: !3, producer: " F90 Flang 1.5 2017-05-01", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !4, globals: !4, imports: !4)
!3 = !DIFile(filename: "over.f90", directory: "/dir")
!4 = !{}
!5 = distinct !DISubprogram(name: "main", scope: !2, file: !3, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagMainSubprogram, unit: !2)
!6 = !DISubroutineType(cc: DW_CC_program, types: !7)
!7 = !{null}
!8 = distinct !DILocalVariable(scope: !5, file: !3, type: !9, flags: DIFlagArtificial)
!9 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !10, size: 64, align: 64)
!10 = !DIBasicType(name: "integer", size: 32, align: 32, encoding: DW_ATE_signed)
!11 = !DILocation(line: 0, scope: !5)
!12 = distinct !DILocalVariable(scope: !5, file: !3, type: !13, flags: DIFlagArtificial)
!13 = !DIBasicType(name: "logical", size: 32, align: 32, encoding: DW_ATE_boolean)
!14 = distinct !DILocalVariable(name: "descriptor", scope: !5, file: !3, type: !15)
!15 = !DICompositeType(tag: DW_TAG_array_type, baseType: !16, size: 1792, align: 64, elements: !17)
!16 = !DIBasicType(name: "integer*8", size: 64, align: 64, encoding: DW_ATE_signed)
!17 = !{!18}
!18 = !DISubrange(lowerBound: 1, upperBound: 28)
!19 = !DILocalVariable(name: "arr", scope: !5, file: !3, type: !20)
!20 = !DICompositeType(tag: DW_TAG_array_type, baseType: !10, size: 32, align: 32, elements: !21, dataLocation: !8, allocated: !12)
!21 = !{!22, !23, !24}
!22 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_over, DW_OP_constu, 48, DW_OP_mul, DW_OP_plus_uconst, 80, DW_OP_plus, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_over, DW_OP_constu, 48, DW_OP_mul, DW_OP_plus_uconst, 120, DW_OP_plus, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_over, DW_OP_constu, 48, DW_OP_mul, DW_OP_plus_uconst, 112, DW_OP_plus, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!23 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 128, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 168, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 160, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!24 = !DISubrange(lowerBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 176, DW_OP_deref), upperBound: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 216, DW_OP_deref), stride: !DIExpression(DW_OP_push_object_address, DW_OP_plus_uconst, 208, DW_OP_deref, DW_OP_constu, 4, DW_OP_mul))
!25 = !DILocation(line: 6, column: 1, scope: !5)