Two fixes for DISubrangeType (#130345)
My previous patch to add DISubrangeType (#126772) had a couple of minor errors. This patch corrects them. 1. When using a DISubrangeType as an array index type, the wrong tag was written into the DIE. 2. I'd intended for subranges to use bit strides, not byte strides -- but neglected to actually implement this. Ada needs bit strides. This patch adds a new test that checks both these things. Finally, this patch adds some documentation for DISubrangeType.
This commit is contained in:
@@ -6319,21 +6319,24 @@ The following ``tag:`` values are valid:
|
||||
DW_TAG_union_type = 23
|
||||
|
||||
For ``DW_TAG_array_type``, the ``elements:`` should be :ref:`subrange
|
||||
descriptors <DISubrange>`, each representing the range of subscripts at that
|
||||
level of indexing. The ``DIFlagVector`` flag to ``flags:`` indicates that an
|
||||
array type is a native packed vector. The optional ``dataLocation`` is a
|
||||
DIExpression that describes how to get from an object's address to the actual
|
||||
raw data, if they aren't equivalent. This is only supported for array types,
|
||||
particularly to describe Fortran arrays, which have an array descriptor in
|
||||
addition to the array data. Alternatively it can also be DIVariable which
|
||||
has the address of the actual raw data. The Fortran language supports pointer
|
||||
arrays which can be attached to actual arrays, this attachment between pointer
|
||||
and pointee is called association. The optional ``associated`` is a
|
||||
DIExpression that describes whether the pointer array is currently associated.
|
||||
The optional ``allocated`` is a DIExpression that describes whether the
|
||||
allocatable array is currently allocated. The optional ``rank`` is a
|
||||
DIExpression that describes the rank (number of dimensions) of fortran assumed
|
||||
rank array (rank is known at runtime).
|
||||
descriptors <DISubrange>` or :ref:`subrange descriptors
|
||||
<DISubrangeType>`, each representing the range of subscripts at that
|
||||
level of indexing. The ``DIFlagVector`` flag to ``flags:`` indicates
|
||||
that an array type is a native packed vector. The optional
|
||||
``dataLocation`` is a DIExpression that describes how to get from an
|
||||
object's address to the actual raw data, if they aren't
|
||||
equivalent. This is only supported for array types, particularly to
|
||||
describe Fortran arrays, which have an array descriptor in addition to
|
||||
the array data. Alternatively it can also be DIVariable which has the
|
||||
address of the actual raw data. The Fortran language supports pointer
|
||||
arrays which can be attached to actual arrays, this attachment between
|
||||
pointer and pointee is called association. The optional
|
||||
``associated`` is a DIExpression that describes whether the pointer
|
||||
array is currently associated. The optional ``allocated`` is a
|
||||
DIExpression that describes whether the allocatable array is currently
|
||||
allocated. The optional ``rank`` is a DIExpression that describes the
|
||||
rank (number of dimensions) of fortran assumed rank array (rank is
|
||||
known at runtime).
|
||||
|
||||
For ``DW_TAG_enumeration_type``, the ``elements:`` should be :ref:`enumerator
|
||||
descriptors <DIEnumerator>`, each representing the definition of an enumeration
|
||||
@@ -6378,6 +6381,50 @@ DISubrange
|
||||
!12 = !DIGlobalVariable(name: "count", scope: !8, file: !6, line: 22, type: !9)
|
||||
!13 = !DISubrange(count: !12, lowerBound: 0)
|
||||
|
||||
.. _DISubrangeType:
|
||||
|
||||
DISubrangeType
|
||||
""""""""""""""
|
||||
|
||||
``DISubrangeType`` is similar to ``DISubrange``, but it is also a
|
||||
``DIType``. It may be used as the type of an object, but could also
|
||||
be used as an array index.
|
||||
|
||||
Like ``DISubrange``, it can hold a lower bound and count, or a lower
|
||||
bound and upper bound. A ``DISubrangeType`` refers to the underlying
|
||||
type of which it is a subrange; this type can be an integer type or an
|
||||
enumeration type.
|
||||
|
||||
A ``DISubrangeType`` may also have a stride -- unlike ``DISubrange``,
|
||||
this stride is a bit stride. The stride is only useful when a
|
||||
``DISubrangeType`` is used as an array index type.
|
||||
|
||||
Finally, ``DISubrangeType`` may have a bias. In Ada, a program can
|
||||
request that a subrange value be stored in the minimum number of bits
|
||||
required. In this situation, the stored value is biased by the lower
|
||||
bound -- e.g., a range ``-7 .. 0`` may take 3 bits in memory, and the
|
||||
value -5 would be stored as 2 (a bias of -7).
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
; Scopes used in rest of example
|
||||
!0 = !DIFile(filename: "vla.c", directory: "/path/to/file")
|
||||
!1 = distinct !DICompileUnit(language: DW_LANG_C99, file: !0)
|
||||
!2 = distinct !DISubprogram(name: "foo", scope: !1, file: !0, line: 5)
|
||||
|
||||
; Base type used in example.
|
||||
!3 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed)
|
||||
|
||||
; A simple subrange with a name.
|
||||
!4 = !DISubrange(name: "subrange", file: !0, line: 17, size: 32,
|
||||
align: 32, baseType: !3, lowerBound: 18, count: 12)
|
||||
; A subrange with a bias.
|
||||
!5 = !DISubrange(name: "biased", lowerBound: -7, upperBound: 0,
|
||||
bias: -7, size: 3)
|
||||
; A subrange with a bit stride.
|
||||
!6 = !DISubrange(name: "biased", lowerBound: 0, upperBound: 7,
|
||||
stride: 3)
|
||||
|
||||
.. _DIEnumerator:
|
||||
|
||||
DIEnumerator
|
||||
|
||||
@@ -1478,7 +1478,7 @@ void DwarfUnit::constructSubrangeDIE(DIE &DW_Subrange, const DISubrangeType *SR,
|
||||
|
||||
AddBoundTypeEntry(dwarf::DW_AT_upper_bound, SR->getUpperBound());
|
||||
|
||||
AddBoundTypeEntry(dwarf::DW_AT_byte_stride, SR->getStride());
|
||||
AddBoundTypeEntry(dwarf::DW_AT_bit_stride, SR->getStride());
|
||||
|
||||
AddBoundTypeEntry(dwarf::DW_AT_GNU_bias, SR->getBias());
|
||||
}
|
||||
@@ -1670,7 +1670,7 @@ void DwarfUnit::constructArrayTypeDIE(DIE &Buffer, const DICompositeType *CTy) {
|
||||
DINodeArray Elements = CTy->getElements();
|
||||
for (DINode *E : Elements) {
|
||||
if (auto *Element = dyn_cast_or_null<DISubrangeType>(E)) {
|
||||
DIE &TyDIE = createAndAddDIE(CTy->getTag(), Buffer, CTy);
|
||||
DIE &TyDIE = createAndAddDIE(Element->getTag(), Buffer, CTy);
|
||||
constructSubrangeDIE(TyDIE, Element, true);
|
||||
} else if (auto *Element = dyn_cast_or_null<DISubrange>(E))
|
||||
constructSubrangeDIE(Buffer, Element);
|
||||
|
||||
39
llvm/test/DebugInfo/Generic/subrange_type.ll
Normal file
39
llvm/test/DebugInfo/Generic/subrange_type.ll
Normal file
@@ -0,0 +1,39 @@
|
||||
;; Check output of DISubrangeType.
|
||||
|
||||
; RUN: %llc_dwarf -filetype=obj -O0 < %s | llvm-dwarfdump -debug-info - | FileCheck %s
|
||||
|
||||
; CHECK: DW_TAG_array_type
|
||||
; CHECK-TYPE: DW_AT_type{{.*}}"unsigned int"
|
||||
; CHECK-NOT: NULL
|
||||
; CHECK: DW_TAG_subrange_type
|
||||
; CHECK-NOT: NULL
|
||||
; CHECK: DW_AT_lower_bound (-7)
|
||||
; CHECK-NEXT: DW_AT_upper_bound (0)
|
||||
; CHECK-NEXT: DW_AT_bit_stride (6)
|
||||
|
||||
; ModuleID = 'subrange_type.ll'
|
||||
source_filename = "/dir/subrange_type.adb"
|
||||
|
||||
!llvm.module.flags = !{!0, !1}
|
||||
!llvm.dbg.cu = !{!2}
|
||||
|
||||
!0 = !{i32 2, !"Debug Info Version", i32 3}
|
||||
!1 = !{i32 2, !"Dwarf Version", i32 4}
|
||||
!2 = distinct !DICompileUnit(language: DW_LANG_Ada95, file: !3, producer: "GNAT/LLVM", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !4, retainedTypes: !5, globals: !4, imports: !4)
|
||||
!3 = !DIFile(filename: "subrange_type.adb", directory: "/dir")
|
||||
!4 = !{}
|
||||
!5 = !{!29}
|
||||
!6 = distinct !DISubprogram(name: "sr", scope: !3, file: !3, line: 1, type: !7, scopeLine: 1, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !9)
|
||||
!7 = !DISubroutineType(types: !8)
|
||||
!8 = !{null}
|
||||
!9 = !{!10}
|
||||
!10 = !DILocalVariable(name: "x", scope: !6, file: !3, line: 3, type: !31, align: 32)
|
||||
!11 = !DISubrangeType(name: "sr__int_range", file: !3, line: 2, size: 32, align: 32, baseType: !12, lowerBound: i64 -7, upperBound: i64 0, stride: 6)
|
||||
!12 = !DIBasicType(name: "sr__Tint_rangeB", size: 32, encoding: DW_ATE_signed)
|
||||
!13 = !DILocation(line: 3, column: 4, scope: !6)
|
||||
!14 = !DILocation(line: 6, column: 5, scope: !6)
|
||||
|
||||
|
||||
!29 = !DICompositeType(tag: DW_TAG_array_type, size: 64, align: 32, file: !3, scope: !6, baseType: !31, elements: !32)
|
||||
!31 = !DIBasicType(tag: DW_TAG_base_type, name: "unsigned int", size: 32, align: 32, encoding: DW_ATE_unsigned)
|
||||
!32 = !{!11}
|
||||
Reference in New Issue
Block a user