-
Notifications
You must be signed in to change notification settings - Fork 13.3k
[LLVM-C] Support debug info for enumerators of arbitrary sizes #76735
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
base: main
Are you sure you want to change the base?
Conversation
@llvm/pr-subscribers-llvm-ir @llvm/pr-subscribers-debuginfo Author: Quinton Miller (HertzDevil) ChangesSince Full diff: https://github.com/llvm/llvm-project/pull/76735.diff 5 Files Affected:
diff --git a/llvm/docs/ReleaseNotes.rst b/llvm/docs/ReleaseNotes.rst
index 52610e7de18751..9f58bc6addb0b2 100644
--- a/llvm/docs/ReleaseNotes.rst
+++ b/llvm/docs/ReleaseNotes.rst
@@ -246,6 +246,9 @@ Changes to the C API
the fast-math flags of an instruction, as well as ``LLVMCanValueUseFastMathFlags``
for checking if an instruction can use such flags
+* Added ``LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision`` for creating
+ debugging metadata of enumerators larger than 64 bits.
+
Changes to the CodeGen infrastructure
-------------------------------------
diff --git a/llvm/include/llvm-c/DebugInfo.h b/llvm/include/llvm-c/DebugInfo.h
index 5924294708cc35..489db659d66e03 100644
--- a/llvm/include/llvm-c/DebugInfo.h
+++ b/llvm/include/llvm-c/DebugInfo.h
@@ -611,6 +611,19 @@ LLVMMetadataRef LLVMDIBuilderCreateEnumerator(LLVMDIBuilderRef Builder,
int64_t Value,
LLVMBool IsUnsigned);
+/**
+ * Create debugging information entry for an enumerator of arbitrary precision.
+ * @param Builder The DIBuilder.
+ * @param Name Enumerator name.
+ * @param NameLen Length of enumerator name.
+ * @param SizeInBits Number of bits of the value.
+ * @param Words The words that make up the value.
+ * @param IsUnsigned True if the value is unsigned.
+ */
+LLVMMetadataRef LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision(
+ LLVMDIBuilderRef Builder, const char *Name, size_t NameLen,
+ uint64_t SizeInBits, const uint64_t Words[], LLVMBool IsUnsigned);
+
/**
* Create debugging information entry for an enumeration.
* \param Builder The DIBuilder.
diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp
index eab05eed428e47..4b3110ab9ffb25 100644
--- a/llvm/lib/IR/DebugInfo.cpp
+++ b/llvm/lib/IR/DebugInfo.cpp
@@ -13,6 +13,7 @@
#include "llvm-c/DebugInfo.h"
#include "LLVMContextImpl.h"
+#include "llvm/ADT/APSInt.h"
#include "llvm/ADT/DenseMap.h"
#include "llvm/ADT/DenseSet.h"
#include "llvm/ADT/STLExtras.h"
@@ -1226,6 +1227,15 @@ LLVMMetadataRef LLVMDIBuilderCreateEnumerator(LLVMDIBuilderRef Builder,
IsUnsigned != 0));
}
+LLVMMetadataRef LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision(
+ LLVMDIBuilderRef Builder, const char *Name, size_t NameLen,
+ uint64_t SizeInBits, const uint64_t Words[], LLVMBool IsUnsigned) {
+ uint64_t NumWords = (SizeInBits + 63) / 64;
+ return wrap(unwrap(Builder)->createEnumerator(
+ {Name, NameLen},
+ APSInt(APInt(SizeInBits, ArrayRef(Words, NumWords)), IsUnsigned != 0)));
+}
+
LLVMMetadataRef LLVMDIBuilderCreateEnumerationType(
LLVMDIBuilderRef Builder, LLVMMetadataRef Scope, const char *Name,
size_t NameLen, LLVMMetadataRef File, unsigned LineNumber,
diff --git a/llvm/test/Bindings/llvm-c/debug_info.ll b/llvm/test/Bindings/llvm-c/debug_info.ll
index a7fcd8a999ef15..31d5ee20bba586 100644
--- a/llvm/test/Bindings/llvm-c/debug_info.ll
+++ b/llvm/test/Bindings/llvm-c/debug_info.ll
@@ -3,13 +3,13 @@
; CHECK: ; ModuleID = 'debuginfo.c'
; CHECK-NEXT: source_filename = "debuginfo.c"
-; CHECK: define i64 @foo(i64 %0, i64 %1, <10 x i64> %2) !dbg !31 {
+; CHECK: define i64 @foo(i64 %0, i64 %1, <10 x i64> %2) !dbg !36 {
; CHECK-NEXT: entry:
-; CHECK-NEXT: call void @llvm.dbg.declare(metadata i64 0, metadata !38, metadata !DIExpression()), !dbg !43
-; CHECK-NEXT: call void @llvm.dbg.declare(metadata i64 0, metadata !39, metadata !DIExpression()), !dbg !43
-; CHECK-NEXT: call void @llvm.dbg.declare(metadata i64 0, metadata !40, metadata !DIExpression()), !dbg !43
+; CHECK-NEXT: call void @llvm.dbg.declare(metadata i64 0, metadata !43, metadata !DIExpression()), !dbg !48
+; CHECK-NEXT: call void @llvm.dbg.declare(metadata i64 0, metadata !44, metadata !DIExpression()), !dbg !48
+; CHECK-NEXT: call void @llvm.dbg.declare(metadata i64 0, metadata !45, metadata !DIExpression()), !dbg !48
; CHECK: vars: ; No predecessors!
-; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 0, metadata !41, metadata !DIExpression(DW_OP_constu, 0, DW_OP_stack_value)), !dbg !44
+; CHECK-NEXT: call void @llvm.dbg.value(metadata i64 0, metadata !46, metadata !DIExpression(DW_OP_constu, 0, DW_OP_stack_value)), !dbg !49
; CHECK-NEXT: }
; CHECK: ; Function Attrs: nocallback nofree nosync nounwind speculatable willreturn memory(none)
@@ -21,12 +21,13 @@
; CHECK: attributes #0 = { nocallback nofree nosync nounwind speculatable willreturn memory(none) }
; CHECK: !llvm.dbg.cu = !{!0}
-; CHECK-NEXT: !FooType = !{!28}
+; CHECK-NEXT: !FooType = !{!33}
; CHECK-NEXT: !EnumTest = !{!3}
+; CHECK-NEXT: !LargeEnumTest = !{!11}
-; CHECK: !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "llvm-c-test", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2, globals: !11, imports: !19, macros: !23, splitDebugInlining: false, sysroot: "/")
+; 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: "/")
; CHECK-NEXT: !1 = !DIFile(filename: "debuginfo.c", directory: ".")
-; CHECK-NEXT: !2 = !{!3}
+; CHECK-NEXT: !2 = !{!3, !11}
; CHECK-NEXT: !3 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "EnumTest", scope: !4, file: !1, baseType: !6, size: 64, elements: !7)
; CHECK-NEXT: !4 = !DINamespace(name: "NameSpace", scope: !5)
; CHECK-NEXT: !5 = !DIModule(scope: null, name: "llvm-c-test", includePath: "/test/include/llvm-c-test.h")
@@ -35,37 +36,42 @@
; CHECK-NEXT: !8 = !DIEnumerator(name: "Test_A", value: 0, isUnsigned: true)
; CHECK-NEXT: !9 = !DIEnumerator(name: "Test_B", value: 1, isUnsigned: true)
; CHECK-NEXT: !10 = !DIEnumerator(name: "Test_B", value: 2, isUnsigned: true)
-; CHECK-NEXT: !11 = !{!12, !16}
-; CHECK-NEXT: !12 = !DIGlobalVariableExpression(var: !13, expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value))
-; CHECK-NEXT: !13 = distinct !DIGlobalVariable(name: "globalClass", scope: !5, file: !1, line: 1, type: !14, isLocal: true, isDefinition: true)
-; CHECK-NEXT: !14 = !DICompositeType(tag: DW_TAG_structure_type, name: "TestClass", scope: !1, file: !1, line: 42, size: 64, flags: DIFlagObjcClassComplete, elements: !15)
-; CHECK-NEXT: !15 = !{}
-; CHECK-NEXT: !16 = !DIGlobalVariableExpression(var: !17, expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value))
-; CHECK-NEXT: !17 = distinct !DIGlobalVariable(name: "global", scope: !5, file: !1, line: 1, type: !18, isLocal: true, isDefinition: true)
-; CHECK-NEXT: !18 = !DIDerivedType(tag: DW_TAG_typedef, name: "int64_t", scope: !1, file: !1, line: 42, baseType: !6)
-; CHECK-NEXT: !19 = !{!20, !22}
-; CHECK-NEXT: !20 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !5, entity: !21, file: !1, line: 42)
-; CHECK-NEXT: !21 = !DIModule(scope: null, name: "llvm-c-test-import", includePath: "/test/include/llvm-c-test-import.h")
-; CHECK-NEXT: !22 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !5, entity: !20, file: !1, line: 42)
-; CHECK-NEXT: !23 = !{!24}
-; CHECK-NEXT: !24 = !DIMacroFile(file: !1, nodes: !25)
-; CHECK-NEXT: !25 = !{!26, !27}
-; CHECK-NEXT: !26 = !DIMacro(type: DW_MACINFO_define, name: "SIMPLE_DEFINE")
-; CHECK-NEXT: !27 = !DIMacro(type: DW_MACINFO_define, name: "VALUE_DEFINE", value: "1")
-; CHECK-NEXT: !28 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !29, size: 192, dwarfAddressSpace: 0)
-; CHECK-NEXT: !29 = !DICompositeType(tag: DW_TAG_structure_type, name: "MyStruct", scope: !4, file: !1, size: 192, elements: !30, runtimeLang: DW_LANG_C89, identifier: "MyStruct")
-; CHECK-NEXT: !30 = !{!6, !6, !6}
-; CHECK-NEXT: !31 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !1, file: !1, line: 42, type: !32, scopeLine: 42, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !37)
-; CHECK-NEXT: !32 = !DISubroutineType(types: !33)
-; CHECK-NEXT: !33 = !{!6, !6, !34}
-; CHECK-NEXT: !34 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 640, flags: DIFlagVector, elements: !35)
-; CHECK-NEXT: !35 = !{!36}
-; CHECK-NEXT: !36 = !DISubrange(count: 10, lowerBound: 0)
-; CHECK-NEXT: !37 = !{!38, !39, !40, !41}
-; CHECK-NEXT: !38 = !DILocalVariable(name: "a", arg: 1, scope: !31, file: !1, line: 42, type: !6)
-; CHECK-NEXT: !39 = !DILocalVariable(name: "b", arg: 2, scope: !31, file: !1, line: 42, type: !6)
-; CHECK-NEXT: !40 = !DILocalVariable(name: "c", arg: 3, scope: !31, file: !1, line: 42, type: !34)
-; CHECK-NEXT: !41 = !DILocalVariable(name: "d", scope: !42, file: !1, line: 43, type: !6)
-; CHECK-NEXT: !42 = distinct !DILexicalBlock(scope: !31, file: !1, line: 42)
-; CHECK-NEXT: !43 = !DILocation(line: 42, scope: !31)
-; CHECK-NEXT: !44 = !DILocation(line: 43, scope: !31)
+; CHECK-NEXT: !11 = !DICompositeType(tag: DW_TAG_enumeration_type, name: "LargeEnumTest", scope: !4, file: !1, baseType: !12, size: 128, elements: !13)
+; CHECK-NEXT: !12 = !DIBasicType(name: "UInt128", size: 128)
+; CHECK-NEXT: !13 = !{!14, !15}
+; CHECK-NEXT: !14 = !DIEnumerator(name: "Test_D", value: 100000000000000000000000000000000000000)
+; CHECK-NEXT: !15 = !DIEnumerator(name: "Test_E", value: -1)
+; CHECK-NEXT: !16 = !{!17, !21}
+; CHECK-NEXT: !17 = !DIGlobalVariableExpression(var: !18, expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value))
+; CHECK-NEXT: !18 = distinct !DIGlobalVariable(name: "globalClass", scope: !5, file: !1, line: 1, type: !19, isLocal: true, isDefinition: true)
+; CHECK-NEXT: !19 = !DICompositeType(tag: DW_TAG_structure_type, name: "TestClass", scope: !1, file: !1, line: 42, size: 64, flags: DIFlagObjcClassComplete, elements: !20)
+; CHECK-NEXT: !20 = !{}
+; CHECK-NEXT: !21 = !DIGlobalVariableExpression(var: !22, expr: !DIExpression(DW_OP_constu, 0, DW_OP_stack_value))
+; CHECK-NEXT: !22 = distinct !DIGlobalVariable(name: "global", scope: !5, file: !1, line: 1, type: !23, isLocal: true, isDefinition: true)
+; CHECK-NEXT: !23 = !DIDerivedType(tag: DW_TAG_typedef, name: "int64_t", scope: !1, file: !1, line: 42, baseType: !6)
+; CHECK-NEXT: !24 = !{!25, !27}
+; CHECK-NEXT: !25 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !5, entity: !26, file: !1, line: 42)
+; CHECK-NEXT: !26 = !DIModule(scope: null, name: "llvm-c-test-import", includePath: "/test/include/llvm-c-test-import.h")
+; CHECK-NEXT: !27 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !5, entity: !25, file: !1, line: 42)
+; CHECK-NEXT: !28 = !{!29}
+; CHECK-NEXT: !29 = !DIMacroFile(file: !1, nodes: !30)
+; CHECK-NEXT: !30 = !{!31, !32}
+; CHECK-NEXT: !31 = !DIMacro(type: DW_MACINFO_define, name: "SIMPLE_DEFINE")
+; CHECK-NEXT: !32 = !DIMacro(type: DW_MACINFO_define, name: "VALUE_DEFINE", value: "1")
+; CHECK-NEXT: !33 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !34, size: 192, dwarfAddressSpace: 0)
+; 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")
+; CHECK-NEXT: !35 = !{!6, !6, !6}
+; 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)
+; CHECK-NEXT: !37 = !DISubroutineType(types: !38)
+; CHECK-NEXT: !38 = !{!6, !6, !39}
+; CHECK-NEXT: !39 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 640, flags: DIFlagVector, elements: !40)
+; CHECK-NEXT: !40 = !{!41}
+; CHECK-NEXT: !41 = !DISubrange(count: 10, lowerBound: 0)
+; CHECK-NEXT: !42 = !{!43, !44, !45, !46}
+; CHECK-NEXT: !43 = !DILocalVariable(name: "a", arg: 1, scope: !36, file: !1, line: 42, type: !6)
+; CHECK-NEXT: !44 = !DILocalVariable(name: "b", arg: 2, scope: !36, file: !1, line: 42, type: !6)
+; CHECK-NEXT: !45 = !DILocalVariable(name: "c", arg: 3, scope: !36, file: !1, line: 42, type: !39)
+; CHECK-NEXT: !46 = !DILocalVariable(name: "d", scope: !47, file: !1, line: 43, type: !6)
+; CHECK-NEXT: !47 = distinct !DILexicalBlock(scope: !36, file: !1, line: 42)
+; CHECK-NEXT: !48 = !DILocation(line: 42, scope: !36)
+; CHECK-NEXT: !49 = !DILocation(line: 43, scope: !36)
diff --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c
index a3e41be12e95d4..bb86ad941ce6ef 100644
--- a/llvm/tools/llvm-c-test/debuginfo.c
+++ b/llvm/tools/llvm-c-test/debuginfo.c
@@ -191,6 +191,26 @@ int llvm_test_dibuilder(void) {
LLVMAddNamedMetadataOperand(
M, "EnumTest", LLVMMetadataAsValue(LLVMGetModuleContext(M), EnumTest));
+ LLVMMetadataRef UInt128Ty = LLVMDIBuilderCreateBasicType(
+ DIB, "UInt128", strlen("UInt128"), 128, 0, LLVMDIFlagZero);
+ const uint64_t WordsTestD[] = {0x098a224000000000ull, 0x4b3b4ca85a86c47aull};
+ const uint64_t WordsTestE[] = {0xFFFFFFFFFFFFFFFFull, 0xFFFFFFFFFFFFFFFFull};
+
+ LLVMMetadataRef LargeEnumeratorTestD =
+ LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision(
+ DIB, "Test_D", strlen("Test_D"), 128, WordsTestD, false);
+ LLVMMetadataRef LargeEnumeratorTestE =
+ LLVMDIBuilderCreateEnumeratorOfArbitraryPrecision(
+ DIB, "Test_E", strlen("Test_E"), 128, WordsTestE, false);
+ LLVMMetadataRef LargeEnumeratorsTest[] = {LargeEnumeratorTestD,
+ LargeEnumeratorTestE};
+ LLVMMetadataRef LargeEnumTest = LLVMDIBuilderCreateEnumerationType(
+ DIB, NameSpace, "LargeEnumTest", strlen("LargeEnumTest"), File, 0, 128, 0,
+ LargeEnumeratorsTest, 2, UInt128Ty);
+ LLVMAddNamedMetadataOperand(
+ M, "LargeEnumTest",
+ LLVMMetadataAsValue(LLVMGetModuleContext(M), LargeEnumTest));
+
LLVMDIBuilderFinalize(DIB);
char *MStr = LLVMPrintModuleToString(M);
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs a rebase, but otherwise looks reasonable to me.
8452767
to
c57193a
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
Since
LLVMDIBuilderCreateEnumerator
only supports up to 64 bits, this PR adds a newLLVMDIBuilderCreateEnumeratorOfArbitraryPrecision
function that takes an arbitrary number of words, based onLLVMConstIntOfArbitraryPrecision
. This allows even larger enumeration types to represent their values exactly. (It seems LLVM should already support i128 enums since 13.0.0.)cc @nikic @arsenm