Skip to content

Two fixes for DISubrangeType #130345

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

Merged
merged 1 commit into from
Mar 7, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 62 additions & 15 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
Expand Down Expand Up @@ -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);
Expand Down
39 changes: 39 additions & 0 deletions llvm/test/DebugInfo/Generic/subrange_type.ll
Original file line number Diff line number Diff line change
@@ -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}
Loading