Skip to content

Commit efbbca6

Browse files
authored
[llvm][DebugInfo] Allow DIDerivedType as a bound in DISubrangeType (#165880)
Consider this Ada type: ``` type Array_Type is array (Natural range <>) of Integer; type Record_Type (L1, L2 : Natural) is record I1 : Integer; A1 : Array_Type (1 .. L1); I2 : Integer; A2 : Array_Type (1 .. L2); I3 : Integer; end record; ``` Here, the array fields have lengths that depend on the discriminants of the record type. However, in this case the array lengths cannot be expressed as DWARF location expressions, with the issue being that "A2" has a non-constant offset, but an expression involving DW_OP_push_object_address will push the address of the field -- with no way to find the location of "L2". In a case like this, I believe the correct DWARF is to emit the array ranges using a direct reference to the discriminant, like: ``` <3><1156>: Abbrev Number: 1 (DW_TAG_member) <1157> DW_AT_name : l1 ... <3><1177>: Abbrev Number: 6 (DW_TAG_array_type) <1178> DW_AT_name : (indirect string, offset: 0x1a0b): vla__record_type__T4b <117c> DW_AT_type : <0x1287> <1180> DW_AT_sibling : <0x118e> <4><1184>: Abbrev Number: 7 (DW_TAG_subrange_type) <1185> DW_AT_type : <0x1280> <1189> DW_AT_upper_bound : <0x1156> ``` (FWIW this is what GCC has done for years.) This patch makes this possible in LLVM, by letting a DISubrangeType refer to a DIDerivedType. gnat-llvm can then arrange for the DIE reference to be correct by setting the array type's scope to be the record.
1 parent 1a09ac5 commit efbbca6

File tree

5 files changed

+106
-6
lines changed

5 files changed

+106
-6
lines changed

llvm/include/llvm/IR/DebugInfoMetadata.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1520,7 +1520,9 @@ inline bool operator!=(DIDerivedType::PtrAuthData Lhs,
15201520
/// is also a DIType.
15211521
class DISubrangeType : public DIType {
15221522
public:
1523-
typedef PointerUnion<ConstantInt *, DIVariable *, DIExpression *> BoundType;
1523+
typedef PointerUnion<ConstantInt *, DIVariable *, DIExpression *,
1524+
DIDerivedType *>
1525+
BoundType;
15241526

15251527
private:
15261528
friend class LLVMContextImpl;

llvm/lib/CodeGen/AsmPrinter/DwarfUnit.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1598,6 +1598,9 @@ void DwarfUnit::constructSubrangeDIE(DIE &DW_Subrange, const DISubrangeType *SR,
15981598
if (auto *BV = dyn_cast_if_present<DIVariable *>(Bound)) {
15991599
if (auto *VarDIE = getDIE(BV))
16001600
addDIEEntry(DW_Subrange, Attr, *VarDIE);
1601+
} else if (auto *DT = dyn_cast_if_present<DIDerivedType *>(Bound)) {
1602+
if (auto *DTDIE = getDIE(DT))
1603+
addDIEEntry(DW_Subrange, Attr, *DTDIE);
16011604
} else if (auto *BE = dyn_cast_if_present<DIExpression *>(Bound)) {
16021605
addBlock(DW_Subrange, Attr, BE);
16031606
} else if (auto *BI = dyn_cast_if_present<ConstantInt *>(Bound)) {

llvm/lib/IR/DebugInfoMetadata.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -839,7 +839,7 @@ DISubrangeType::convertRawToBound(Metadata *IN) const {
839839
return BoundType();
840840

841841
assert(isa<ConstantAsMetadata>(IN) || isa<DIVariable>(IN) ||
842-
isa<DIExpression>(IN));
842+
isa<DIExpression>(IN) || isa<DIDerivedType>(IN));
843843

844844
if (auto *MD = dyn_cast<ConstantAsMetadata>(IN))
845845
return BoundType(cast<ConstantInt>(MD->getValue()));
@@ -850,6 +850,9 @@ DISubrangeType::convertRawToBound(Metadata *IN) const {
850850
if (auto *MD = dyn_cast<DIExpression>(IN))
851851
return BoundType(MD);
852852

853+
if (auto *DT = dyn_cast<DIDerivedType>(IN))
854+
return BoundType(DT);
855+
853856
return BoundType();
854857
}
855858

llvm/lib/IR/Verifier.cpp

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1187,13 +1187,17 @@ void Verifier::visitDISubrangeType(const DISubrangeType &N) {
11871187
CheckDI(!BaseType || isType(BaseType), "BaseType must be a type");
11881188
auto *LBound = N.getRawLowerBound();
11891189
CheckDI(!LBound || isa<ConstantAsMetadata>(LBound) ||
1190-
isa<DIVariable>(LBound) || isa<DIExpression>(LBound),
1191-
"LowerBound must be signed constant or DIVariable or DIExpression",
1190+
isa<DIVariable>(LBound) || isa<DIExpression>(LBound) ||
1191+
isa<DIDerivedType>(LBound),
1192+
"LowerBound must be signed constant or DIVariable or DIExpression or "
1193+
"DIDerivedType",
11921194
&N);
11931195
auto *UBound = N.getRawUpperBound();
11941196
CheckDI(!UBound || isa<ConstantAsMetadata>(UBound) ||
1195-
isa<DIVariable>(UBound) || isa<DIExpression>(UBound),
1196-
"UpperBound must be signed constant or DIVariable or DIExpression",
1197+
isa<DIVariable>(UBound) || isa<DIExpression>(UBound) ||
1198+
isa<DIDerivedType>(UBound),
1199+
"UpperBound must be signed constant or DIVariable or DIExpression or "
1200+
"DIDerivedType",
11971201
&N);
11981202
auto *Stride = N.getRawStride();
11991203
CheckDI(!Stride || isa<ConstantAsMetadata>(Stride) ||
Lines changed: 88 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,88 @@
1+
; RUN: llvm-as < %s | llvm-dis | llc -mtriple=x86_64 -O0 -filetype=obj -o - | llvm-dwarfdump -v -debug-info - | FileCheck %s
2+
3+
; A test to verify the use of a DIDerivedType as a bound of a
4+
; DISubrangeType.
5+
6+
; CHECK: DW_TAG_array_type
7+
; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] {{.*}}
8+
; CHECK: DW_TAG_subrange_type {{.*}}
9+
; CHECK-NEXT: DW_AT_type [DW_FORM_ref4] {{.*}}
10+
; CHECK-NEXT: DW_AT_upper_bound [DW_FORM_ref4] {{.*}}
11+
12+
; ModuleID = 'vla.ads'
13+
source_filename = "vla.ads"
14+
target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128"
15+
target triple = "x86_64-unknown-linux-gnu"
16+
17+
%vla__array_type_FP = type { ptr, ptr }
18+
%vla__record_type_I = type <{ i32 }>
19+
20+
@vla_E = dso_local global i16 0, align 2, !dbg !0
21+
22+
; Function Attrs: inlinehint
23+
define dso_local void @vla__array_typeIP(%vla__array_type_FP %_init) #0 !dbg !10 {
24+
entry:
25+
%0 = extractvalue %vla__array_type_FP %_init, 1, !dbg !15
26+
%1 = call ptr @llvm.invariant.start.p0(i64 8, ptr %0), !dbg !15
27+
ret void, !dbg !15
28+
}
29+
30+
; Function Attrs: nocallback nofree nosync nounwind willreturn memory(argmem: readwrite)
31+
declare ptr @llvm.invariant.start.p0(i64 immarg, ptr nocapture) #1
32+
33+
; Function Attrs: inlinehint
34+
define dso_local void @vla__record_typeIP(ptr noalias nocapture nonnull %_init, i32 %l1) #0 !dbg !16 {
35+
entry:
36+
#dbg_declare(ptr %_init, !31, !DIExpression(), !32)
37+
#dbg_value(i32 %l1, !33, !DIExpression(), !34)
38+
%0 = getelementptr inbounds %vla__record_type_I, ptr %_init, i32 0, i32 0, !dbg !32
39+
store i32 %l1, ptr %0, align 4, !dbg !32, !tbaa !35
40+
ret void, !dbg !32
41+
}
42+
43+
attributes #0 = { inlinehint }
44+
attributes #1 = { nocallback nofree nosync nounwind willreturn memory(argmem: readwrite) }
45+
46+
!llvm.module.flags = !{!6, !7, !8, !9}
47+
!llvm.dbg.cu = !{!2}
48+
49+
!0 = !DIGlobalVariableExpression(var: !1, expr: !DIExpression())
50+
!1 = distinct !DIGlobalVariable(name: "vla_E", scope: !2, file: !3, line: 16, type: !5, isLocal: false, isDefinition: true, align: 16)
51+
!2 = distinct !DICompileUnit(language: DW_LANG_Ada95, file: !3, producer: "GNAT/LLVM", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, globals: !4, splitDebugInlining: false)
52+
!3 = !DIFile(filename: "vla.ads", directory: "")
53+
!4 = !{!0}
54+
!5 = !DIBasicType(name: "short_integer", size: 16, encoding: DW_ATE_signed)
55+
!6 = !{i32 8, !"PIC Level", i32 2}
56+
!7 = !{i32 7, !"PIE Level", i32 2}
57+
!8 = !{i32 2, !"Debug Info Version", i32 3}
58+
!9 = !{i32 2, !"Dwarf Version", i32 4}
59+
!10 = distinct !DISubprogram(name: "vla__array_typeIP", scope: !3, file: !3, line: 17, type: !11, scopeLine: 17, spFlags: DISPFlagDefinition, unit: !2)
60+
!11 = !DISubroutineType(types: !12)
61+
!12 = !{null, !13}
62+
!13 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !14, size: 64, align: 64, dwarfAddressSpace: 0)
63+
!14 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "vla__array_type")
64+
!15 = !DILocation(line: 17, column: 9, scope: !10)
65+
!16 = distinct !DISubprogram(name: "vla__record_typeIP", scope: !3, file: !3, line: 18, type: !17, scopeLine: 18, spFlags: DISPFlagDefinition, unit: !2, retainedNodes: !30)
66+
!17 = !DISubroutineType(types: !18)
67+
!18 = !{null, !19, !23}
68+
!19 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !20, size: 64, align: 64, dwarfAddressSpace: 0)
69+
!20 = !DICompositeType(tag: DW_TAG_structure_type, name: "vla__record_type", file: !3, line: 18, size: !DIExpression(DW_OP_push_object_address, DW_OP_deref_size, 4, DW_OP_constu, 32, DW_OP_mul, DW_OP_constu, 32, DW_OP_plus), align: 32, elements: !21, identifier: "vla__record_type")
70+
!21 = !{!22, !26}
71+
!22 = !DIDerivedType(tag: DW_TAG_member, name: "l1", file: !3, line: 18, baseType: !23)
72+
!23 = !DISubrangeType(name: "natural", file: !24, line: 1, size: 32, align: 32, baseType: !25, lowerBound: i64 0, upperBound: i64 2147483647)
73+
!24 = !DIFile(filename: "system.ads", directory: "/home/tromey/AdaCore/gnat-llvm/llvm-interface//lib/gnat-llvm/x86_64-unknown-linux-gnu/rts-native/adainclude/")
74+
!25 = !DIBasicType(name: "integer", size: 32, encoding: DW_ATE_signed)
75+
!26 = !DIDerivedType(tag: DW_TAG_member, name: "a1", file: !3, line: 19, baseType: !27, offset: 32)
76+
!27 = !DICompositeType(tag: DW_TAG_array_type, scope: !20, file: !3, line: 19, baseType: !25, align: 32, elements: !28)
77+
!28 = !{!29}
78+
!29 = !DISubrangeType(baseType: !25, lowerBound: i64 1, upperBound: !22)
79+
!30 = !{}
80+
!31 = !DILocalVariable(name: "_init", arg: 1, scope: !16, file: !3, line: 18, type: !20, flags: DIFlagArtificial)
81+
!32 = !DILocation(line: 18, column: 9, scope: !16)
82+
!33 = !DILocalVariable(name: "l1", arg: 2, scope: !16, file: !3, line: 18, type: !23, flags: DIFlagArtificial)
83+
!34 = !DILocation(line: 18, column: 22, scope: !16)
84+
!35 = !{!36, !36, i64 0, i64 4}
85+
!36 = !{!37, i64 4, !"natural#T5"}
86+
!37 = !{!38, i64 4, !"natural#TN"}
87+
!38 = !{!39, i64 4, !"integerB#TN"}
88+
!39 = !{!"Ada Root"}

0 commit comments

Comments
 (0)