Skip to content

Commit 2c0d563

Browse files
authored
Add debuginfo C support for a SetType, Subrangetype, dynamic array type and replace arrays (#135607)
This change adds some support to the C DebugInfo capability to create set types, subrange types, dynamic array types and the ability to replace arrays.
1 parent b152611 commit 2c0d563

File tree

4 files changed

+217
-28
lines changed

4 files changed

+217
-28
lines changed

llvm/include/llvm-c/DebugInfo.h

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,77 @@ LLVM_C_ABI LLVMMetadataRef LLVMDIBuilderCreateArrayType(
688688
LLVMDIBuilderRef Builder, uint64_t Size, uint32_t AlignInBits,
689689
LLVMMetadataRef Ty, LLVMMetadataRef *Subscripts, unsigned NumSubscripts);
690690

691+
/**
692+
* Create debugging information entry for a set.
693+
* \param Builder The DIBuilder.
694+
* \param Scope The scope in which the set is defined.
695+
* \param Name A name that uniquely identifies this set.
696+
* \param NameLen The length of the C string passed to \c Name.
697+
* \param File File where the set is located.
698+
* \param Line Line number of the declaration.
699+
* \param SizeInBits Set size.
700+
* \param AlignInBits Set alignment.
701+
* \param BaseTy The base type of the set.
702+
*/
703+
LLVMMetadataRef LLVMDIBuilderCreateSetType(
704+
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
705+
size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
706+
uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef BaseTy);
707+
708+
/**
709+
* Create a descriptor for a subrange with dynamic bounds.
710+
* \param Builder The DIBuilder.
711+
* \param Scope The scope in which the subrange is defined.
712+
* \param Name A name that uniquely identifies this subrange.
713+
* \param NameLen The length of the C string passed to \c Name.
714+
* \param LineNo Line number.
715+
* \param File File where the subrange is located.
716+
* \param SizeInBits Member size.
717+
* \param AlignInBits Member alignment.
718+
* \param Flags Flags.
719+
* \param BaseTy The base type of the subrange. eg integer or enumeration
720+
* \param LowerBound Lower bound of the subrange.
721+
* \param UpperBound Upper bound of the subrange.
722+
* \param Stride Stride of the subrange.
723+
* \param Bias Bias of the subrange.
724+
*/
725+
LLVMMetadataRef LLVMDIBuilderCreateSubrangeType(
726+
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
727+
size_t NameLen, unsigned LineNo, LLVMMetadataRef File, uint64_t SizeInBits,
728+
uint32_t AlignInBits, LLVMDIFlags Flags, LLVMMetadataRef BaseTy,
729+
LLVMMetadataRef LowerBound, LLVMMetadataRef UpperBound,
730+
LLVMMetadataRef Stride, LLVMMetadataRef Bias);
731+
732+
/**
733+
* Create debugging information entry for a dynamic array.
734+
* \param Builder The DIBuilder.
735+
* \param Size Array size.
736+
* \param AlignInBits Alignment.
737+
* \param Ty Element type.
738+
* \param Subscripts Subscripts.
739+
* \param NumSubscripts Number of subscripts.
740+
* \param DataLocation DataLocation. (DIVariable, DIExpression or NULL)
741+
* \param Associated Associated. (DIVariable, DIExpression or NULL)
742+
* \param Allocated Allocated. (DIVariable, DIExpression or NULL)
743+
* \param Rank Rank. (DIVariable, DIExpression or NULL)
744+
* \param BitStride BitStride.
745+
*/
746+
LLVMMetadataRef LLVMDIBuilderCreateDynamicArrayType(
747+
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
748+
size_t NameLen, unsigned LineNo, LLVMMetadataRef File, uint64_t Size,
749+
uint32_t AlignInBits, LLVMMetadataRef Ty, LLVMMetadataRef *Subscripts,
750+
unsigned NumSubscripts, LLVMMetadataRef DataLocation,
751+
LLVMMetadataRef Associated, LLVMMetadataRef Allocated, LLVMMetadataRef Rank,
752+
LLVMMetadataRef BitStride);
753+
754+
/**
755+
* Replace arrays.
756+
*
757+
* @see DIBuilder::replaceArrays()
758+
*/
759+
void LLVMReplaceArrays(LLVMDIBuilderRef Builder, LLVMMetadataRef *T,
760+
LLVMMetadataRef *Elements, unsigned NumElements);
761+
691762
/**
692763
* Create debugging information entry for a vector type.
693764
* \param Builder The DIBuilder.

llvm/lib/IR/DebugInfo.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1325,6 +1325,63 @@ return wrap(unwrap(Builder)->createEnumerationType(
13251325
LineNumber, SizeInBits, AlignInBits, Elts, unwrapDI<DIType>(ClassTy)));
13261326
}
13271327

1328+
LLVMMetadataRef LLVMDIBuilderCreateSetType(
1329+
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
1330+
size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
1331+
uint64_t SizeInBits, uint32_t AlignInBits, LLVMMetadataRef BaseTy) {
1332+
return wrap(unwrap(Builder)->createSetType(
1333+
unwrapDI<DIScope>(Scope), {Name, NameLen}, unwrapDI<DIFile>(File),
1334+
LineNumber, SizeInBits, AlignInBits, unwrapDI<DIType>(BaseTy)));
1335+
}
1336+
1337+
LLVMMetadataRef LLVMDIBuilderCreateSubrangeType(
1338+
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
1339+
size_t NameLen, unsigned LineNo, LLVMMetadataRef File, uint64_t SizeInBits,
1340+
uint32_t AlignInBits, LLVMDIFlags Flags, LLVMMetadataRef BaseTy,
1341+
LLVMMetadataRef LowerBound, LLVMMetadataRef UpperBound,
1342+
LLVMMetadataRef Stride, LLVMMetadataRef Bias) {
1343+
return wrap(unwrap(Builder)->createSubrangeType(
1344+
{Name, NameLen}, unwrapDI<DIFile>(File), LineNo, unwrapDI<DIScope>(Scope),
1345+
SizeInBits, AlignInBits, map_from_llvmDIFlags(Flags),
1346+
unwrapDI<DIType>(BaseTy), unwrap(LowerBound), unwrap(UpperBound),
1347+
unwrap(Stride), unwrap(Bias)));
1348+
}
1349+
1350+
/// MD may be nullptr, a DIExpression or DIVariable.
1351+
PointerUnion<DIExpression *, DIVariable *> unwrapExprVar(LLVMMetadataRef MD) {
1352+
if (!MD)
1353+
return nullptr;
1354+
MDNode *MDN = unwrapDI<MDNode>(MD);
1355+
if (auto *E = dyn_cast<DIExpression>(MDN))
1356+
return E;
1357+
assert(isa<DIVariable>(MDN) && "Expected DIExpression or DIVariable");
1358+
return cast<DIVariable>(MDN);
1359+
}
1360+
1361+
LLVMMetadataRef LLVMDIBuilderCreateDynamicArrayType(
1362+
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
1363+
size_t NameLen, unsigned LineNo, LLVMMetadataRef File, uint64_t Size,
1364+
uint32_t AlignInBits, LLVMMetadataRef Ty, LLVMMetadataRef *Subscripts,
1365+
unsigned NumSubscripts, LLVMMetadataRef DataLocation,
1366+
LLVMMetadataRef Associated, LLVMMetadataRef Allocated, LLVMMetadataRef Rank,
1367+
LLVMMetadataRef BitStride) {
1368+
auto Subs =
1369+
unwrap(Builder)->getOrCreateArray({unwrap(Subscripts), NumSubscripts});
1370+
return wrap(unwrap(Builder)->createArrayType(
1371+
unwrapDI<DIScope>(Scope), {Name, NameLen}, unwrapDI<DIFile>(File), LineNo,
1372+
Size, AlignInBits, unwrapDI<DIType>(Ty), Subs,
1373+
unwrapExprVar(DataLocation), unwrapExprVar(Associated),
1374+
unwrapExprVar(Allocated), unwrapExprVar(Rank), unwrap(BitStride)));
1375+
}
1376+
1377+
void LLVMReplaceArrays(LLVMDIBuilderRef Builder, LLVMMetadataRef *T,
1378+
LLVMMetadataRef *Elements, unsigned NumElements) {
1379+
auto CT = unwrap<DICompositeType>(*T);
1380+
auto Elts =
1381+
unwrap(Builder)->getOrCreateArray({unwrap(Elements), NumElements});
1382+
unwrap(Builder)->replaceArrays(CT, Elts);
1383+
}
1384+
13281385
LLVMMetadataRef LLVMDIBuilderCreateUnionType(
13291386
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
13301387
size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,

llvm/test/Bindings/llvm-c/debug_info_new_format.ll

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -3,30 +3,36 @@
33

44
; CHECK: ; ModuleID = 'debuginfo.c'
55
; CHECK-NEXT: source_filename = "debuginfo.c"
6-
7-
; CHECK: define i64 @foo(i64 %0, i64 %1, <10 x i64> %2) !dbg !36 {
6+
7+
; CHECK: define i64 @foo(i64 %0, i64 %1, <10 x i64> %2) !dbg !44 {
88
; CHECK-NEXT: entry:
9-
; CHECK-NEXT: #dbg_declare(i64 0, !43, !DIExpression(), !50)
10-
; CHECK-NEXT: #dbg_declare(i64 0, !44, !DIExpression(), !50)
11-
; CHECK-NEXT: #dbg_declare(i64 0, !45, !DIExpression(), !50)
12-
; CHECK-NEXT: #dbg_label(!51, !50)
9+
; CHECK-NEXT: #dbg_declare(i64 0, !49, !DIExpression(), !58)
10+
; CHECK-NEXT: #dbg_declare(i64 0, !50, !DIExpression(), !58)
11+
; CHECK-NEXT: #dbg_declare(i64 0, !51, !DIExpression(), !58)
12+
; CHECK-NEXT: #dbg_label(!59, !58)
1313
; CHECK-NEXT: br label %vars
14-
; CHECK-NEXT: #dbg_label(!52, !50)
14+
; CHECK-NEXT: #dbg_label(!60, !58)
1515
; CHECK-NEXT: br label %vars
16-
; CHECK: vars:
16+
17+
; CHECK: vars: ; preds = %entry, %entry
1718
; CHECK-NEXT: %p1 = phi i64 [ 0, %entry ]
1819
; CHECK-NEXT: %p2 = phi i64 [ 0, %entry ]
19-
; CHECK-NEXT: #dbg_value(i64 0, !46, !DIExpression(DW_OP_constu, 0, DW_OP_stack_value), !53)
20-
; CHECK-NEXT: #dbg_value(i64 1, !48, !DIExpression(DW_OP_constu, 1, DW_OP_stack_value), !53)
20+
; CHECK-NEXT: #dbg_value(i64 0, !42, !DIExpression(DW_OP_constu, 0, DW_OP_stack_value), !61)
21+
; CHECK-NEXT: #dbg_value(i64 1, !52, !DIExpression(DW_OP_constu, 1, DW_OP_stack_value), !61)
2122
; CHECK-NEXT: %a = add i64 %p1, %p2
2223
; CHECK-NEXT: ret i64 0
2324
; CHECK-NEXT: }
24-
25+
2526
; CHECK: !llvm.dbg.cu = !{!0}
2627
; CHECK-NEXT: !FooType = !{!33}
2728
; CHECK-NEXT: !EnumTest = !{!3}
2829
; CHECK-NEXT: !LargeEnumTest = !{!11}
29-
30+
; CHECK-NEXT: !SubrangeType = !{!36}
31+
; CHECK-NEXT: !SetType1 = !{!37}
32+
; CHECK-NEXT: !SetType2 = !{!38}
33+
; CHECK-NEXT: !DynType = !{!39}
34+
; CHECK-NEXT: !ClassType = !{!54}
35+
3036
; CHECK: !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "llvm-c-test", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !16, imports: !24, macros: !28, splitDebugInlining: false, sysroot: "/")
3137
; CHECK-NEXT: !1 = !DIFile(filename: "debuginfo.c", directory: ".")
3238
; CHECK-NEXT: !2 = !{!3, !11}
@@ -63,21 +69,29 @@
6369
; CHECK-NEXT: !33 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !34, size: 192, dwarfAddressSpace: 0)
6470
; CHECK-NEXT: !34 = !DICompositeType(tag: DW_TAG_structure_type, name: "MyStruct", scope: !4, file: !1, size: 192, elements: !35, runtimeLang: DW_LANG_C89, identifier: "MyStruct")
6571
; CHECK-NEXT: !35 = !{!6, !6, !6}
66-
; CHECK-NEXT: !36 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !1, file: !1, line: 42, type: !37, scopeLine: 42, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !42)
67-
; CHECK-NEXT: !37 = !DISubroutineType(types: !38)
68-
; CHECK-NEXT: !38 = !{!6, !6, !39}
69-
; CHECK-NEXT: !39 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 640, flags: DIFlagVector, elements: !40)
72+
; CHECK-NEXT: !36 = !DISubrangeType(name: "foo", scope: !1, file: !1, line: 42, size: 64, baseType: !6, lowerBound: i64 0, upperBound: i64 1, stride: i64 8, bias: i64 4)
73+
; CHECK-NEXT: !37 = !DIDerivedType(tag: DW_TAG_set_type, name: "enumset", scope: !1, file: !1, line: 42, baseType: !3, size: 64)
74+
; CHECK-NEXT: !38 = !DIDerivedType(tag: DW_TAG_set_type, name: "subrangeset", scope: !1, file: !1, line: 42, baseType: !36, size: 64)
75+
; CHECK-NEXT: !39 = !DICompositeType(tag: DW_TAG_array_type, name: "foo", scope: !1, file: !1, line: 42, baseType: !6, size: 640, elements: !40, dataLocation: !DIExpression(), associated: !42, rank: !DIExpression())
7076
; CHECK-NEXT: !40 = !{!41}
7177
; CHECK-NEXT: !41 = !DISubrange(count: 10, lowerBound: 0)
72-
; CHECK-NEXT: !42 = !{!43, !44, !45, !46, !48, !49}
73-
; CHECK-NEXT: !43 = !DILocalVariable(name: "a", arg: 1, scope: !36, file: !1, line: 42, type: !6)
74-
; CHECK-NEXT: !44 = !DILocalVariable(name: "b", arg: 2, scope: !36, file: !1, line: 42, type: !6)
75-
; CHECK-NEXT: !45 = !DILocalVariable(name: "c", arg: 3, scope: !36, file: !1, line: 42, type: !39)
76-
; CHECK-NEXT: !46 = !DILocalVariable(name: "d", scope: !47, file: !1, line: 43, type: !6)
77-
; CHECK-NEXT: !47 = distinct !DILexicalBlock(scope: !36, file: !1, line: 42)
78-
; CHECK-NEXT: !48 = !DILocalVariable(name: "e", scope: !47, file: !1, line: 44, type: !6)
79-
; CHECK-NEXT: !49 = !DILabel(scope: !36, name: "label3", file: !1, line: 42)
80-
; CHECK-NEXT: !50 = !DILocation(line: 42, scope: !36)
81-
; CHECK-NEXT: !51 = !DILabel(scope: !36, name: "label1", file: !1, line: 42)
82-
; CHECK-NEXT: !52 = !DILabel(scope: !36, name: "label2", file: !1, line: 42)
83-
; CHECK-NEXT: !53 = !DILocation(line: 43, scope: !36)
78+
; CHECK-NEXT: !42 = !DILocalVariable(name: "d", scope: !43, file: !1, line: 43, type: !6)
79+
; CHECK-NEXT: !43 = distinct !DILexicalBlock(scope: !44, file: !1, line: 42)
80+
; CHECK-NEXT: !44 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !1, file: !1, line: 42, type: !45, scopeLine: 42, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !48)
81+
; CHECK-NEXT: !45 = !DISubroutineType(types: !46)
82+
; CHECK-NEXT: !46 = !{!6, !6, !47}
83+
; CHECK-NEXT: !47 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 640, flags: DIFlagVector, elements: !40)
84+
; CHECK-NEXT: !48 = !{!49, !50, !51, !42, !52, !53}
85+
; CHECK-NEXT: !49 = !DILocalVariable(name: "a", arg: 1, scope: !44, file: !1, line: 42, type: !6)
86+
; CHECK-NEXT: !50 = !DILocalVariable(name: "b", arg: 2, scope: !44, file: !1, line: 42, type: !6)
87+
; CHECK-NEXT: !51 = !DILocalVariable(name: "c", arg: 3, scope: !44, file: !1, line: 42, type: !47)
88+
; CHECK-NEXT: !52 = !DILocalVariable(name: "e", scope: !43, file: !1, line: 44, type: !6)
89+
; CHECK-NEXT: !53 = !DILabel(scope: !44, name: "label3", file: !1, line: 42)
90+
; CHECK-NEXT: !54 = !DICompositeType(tag: DW_TAG_class_type, name: "Class", scope: !4, file: !1, size: 192, flags: DIFlagFwdDecl, elements: !55, identifier: "FooClass")
91+
; CHECK-NEXT: !55 = !{!56}
92+
; CHECK-NEXT: !56 = !{!6, !6, !57}
93+
; CHECK-NEXT: !57 = !DIBasicType(name: "Int32", size: 32)
94+
; CHECK-NEXT: !58 = !DILocation(line: 42, scope: !44)
95+
; CHECK-NEXT: !59 = !DILabel(scope: !44, name: "label1", file: !1, line: 42)
96+
; CHECK-NEXT: !60 = !DILabel(scope: !44, name: "label2", file: !1, line: 42)
97+
; CHECK-NEXT: !61 = !DILocation(line: 43, scope: !44)

llvm/tools/llvm-c-test/debuginfo.c

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,53 @@ int llvm_test_dibuilder(void) {
235235
M, "LargeEnumTest",
236236
LLVMMetadataAsValue(LLVMGetModuleContext(M), LargeEnumTest));
237237

238+
LLVMValueRef FooVal3 = LLVMConstInt(LLVMInt64Type(), 8, false);
239+
LLVMValueRef FooVal4 = LLVMConstInt(LLVMInt64Type(), 4, false);
240+
LLVMMetadataRef lo = LLVMValueAsMetadata(FooVal1);
241+
LLVMMetadataRef hi = LLVMValueAsMetadata(FooVal2);
242+
LLVMMetadataRef strd = LLVMValueAsMetadata(FooVal3);
243+
LLVMMetadataRef bias = LLVMValueAsMetadata(FooVal4);
244+
LLVMMetadataRef SubrangeMetadataTy = LLVMDIBuilderCreateSubrangeType(
245+
DIB, File, "foo", 3, 42, File, 64, 0, 0, Int64Ty, lo, hi, strd, bias);
246+
LLVMAddNamedMetadataOperand(
247+
M, "SubrangeType",
248+
LLVMMetadataAsValue(LLVMGetModuleContext(M), SubrangeMetadataTy));
249+
250+
LLVMMetadataRef SetMetadataTy1 = LLVMDIBuilderCreateSetType(
251+
DIB, File, "enumset", 7, File, 42, 64, 0, EnumTest);
252+
LLVMMetadataRef SetMetadataTy2 = LLVMDIBuilderCreateSetType(
253+
DIB, File, "subrangeset", 11, File, 42, 64, 0, SubrangeMetadataTy);
254+
LLVMAddNamedMetadataOperand(
255+
M, "SetType1",
256+
LLVMMetadataAsValue(LLVMGetModuleContext(M), SetMetadataTy1));
257+
LLVMAddNamedMetadataOperand(
258+
M, "SetType2",
259+
LLVMMetadataAsValue(LLVMGetModuleContext(M), SetMetadataTy2));
260+
261+
LLVMMetadataRef DynSubscripts[] = {
262+
LLVMDIBuilderGetOrCreateSubrange(DIB, 0, 10),
263+
};
264+
LLVMMetadataRef Loc = LLVMDIBuilderCreateExpression(DIB, NULL, 0);
265+
LLVMMetadataRef Rank = LLVMDIBuilderCreateExpression(DIB, NULL, 0);
266+
LLVMMetadataRef DynamicArrayMetadataTy = LLVMDIBuilderCreateDynamicArrayType(
267+
DIB, File, "foo", 3, 42, File, 64 * 10, 0, Int64Ty, DynSubscripts, 1, Loc,
268+
FooVar1, NULL, Rank, NULL);
269+
LLVMAddNamedMetadataOperand(
270+
M, "DynType",
271+
LLVMMetadataAsValue(LLVMGetModuleContext(M), DynamicArrayMetadataTy));
272+
273+
LLVMMetadataRef StructPTy = LLVMDIBuilderCreateForwardDecl(
274+
DIB, 2 /*DW_TAG_class_type*/, "Class1", 5, NameSpace, File, 0, 0, 192, 0,
275+
"FooClass", 8);
276+
277+
LLVMMetadataRef Int32Ty =
278+
LLVMDIBuilderCreateBasicType(DIB, "Int32", 5, 32, 0, LLVMDIFlagZero);
279+
LLVMMetadataRef StructElts[] = {Int64Ty, Int64Ty, Int32Ty};
280+
LLVMMetadataRef ClassArr = LLVMDIBuilderGetOrCreateArray(DIB, StructElts, 3);
281+
LLVMReplaceArrays(DIB, &StructPTy, &ClassArr, 1);
282+
LLVMAddNamedMetadataOperand(
283+
M, "ClassType", LLVMMetadataAsValue(LLVMGetModuleContext(M), StructPTy));
284+
238285
// Using the new debug format, debug records get attached to instructions.
239286
// Insert a `br` and `ret` now to absorb the debug records which are
240287
// currently "trailing", meaning that they're associated with a block

0 commit comments

Comments
 (0)