From 2f5abce39f5e9afc1f9c9d633b56352abff47b3a Mon Sep 17 00:00:00 2001 From: peter mckinna Date: Mon, 29 Sep 2025 08:50:41 +1000 Subject: [PATCH 1/2] Add checksum option for create file --- llvm/include/llvm-c/DebugInfo.h | 24 ++++ llvm/lib/IR/DebugInfo.cpp | 33 ++++++ .../Bindings/llvm-c/debug_info_new_format.ll | 107 +++++++++--------- llvm/tools/llvm-c-test/debuginfo.c | 5 +- 4 files changed, 115 insertions(+), 54 deletions(-) diff --git a/llvm/include/llvm-c/DebugInfo.h b/llvm/include/llvm-c/DebugInfo.h index 2ecd69a187d4d..96ebec42fcdb4 100644 --- a/llvm/include/llvm-c/DebugInfo.h +++ b/llvm/include/llvm-c/DebugInfo.h @@ -203,6 +203,11 @@ enum { }; typedef unsigned LLVMMetadataKind; +/** + * The kind of checksum to emit. + */ +typedef enum { CSK_MD5, CSK_SHA1, CSK_SHA256 } LLVMChecksumKind; + /** * An LLVM DWARF type encoding. */ @@ -326,6 +331,25 @@ LLVM_C_ABI LLVMMetadataRef LLVMDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Directory, size_t DirectoryLen); +/** + * Create a file descriptor to hold debugging information for a file. + * \param Builder The \c DIBuilder. + * \param Filename File name. + * \param FilenameLen The length of the C string passed to \c Filename. + * \param Directory Directory. + * \param DirectoryLen The length of the C string passed to \c Directory. + * \param ChecksumKind The kind of checksum. eg MD5, SHA256 + * \param Checksum The checksum. + * \param ChecksumLen The length of the checksum. + * \param Souce The embedded source. + * \param SourceLen The length of the source. + */ +LLVM_C_ABI LLVMMetadataRef LLVMDIBuilderCreateFileWithCheckSum( + LLVMDIBuilderRef Builder, const char *Filename, size_t FilenameLen, + const char *Directory, size_t DirectoryLen, LLVMChecksumKind ChecksumKind, + const char *Checksum, size_t ChecksumLen, const char *Source, + size_t SourceLen); + /** * Creates a new descriptor for a module with the specified parent scope. * \param Builder The \c DIBuilder. diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index f9ded507f8328..2b767f19a3923 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -1095,6 +1095,39 @@ LLVMDIBuilderCreateFile(LLVMDIBuilderRef Builder, const char *Filename, StringRef(Directory, DirectoryLen))); } +static llvm::DIFile::ChecksumKind +map_from_llvmChecksumKind(LLVMChecksumKind CSKind) { + switch (CSKind) { + case LLVMChecksumKind::CSK_MD5: + return llvm::DIFile::CSK_MD5; + case LLVMChecksumKind::CSK_SHA1: + return llvm::DIFile::CSK_SHA1; + case LLVMChecksumKind::CSK_SHA256: + return llvm::DIFile::CSK_SHA256; + default: + llvm_unreachable("Unhandled Checksum Kind"); + } +} + +LLVMMetadataRef LLVMDIBuilderCreateFileWithCheckSum( + LLVMDIBuilderRef Builder, const char *Filename, size_t FilenameLen, + const char *Directory, size_t DirectoryLen, LLVMChecksumKind ChecksumKind, + const char *Checksum, size_t ChecksumLen, const char *Source, + size_t SourceLen) { + StringRef ChkSum = StringRef(Checksum, ChecksumLen); + std::optional> CSInfo; + auto CSK = map_from_llvmChecksumKind(ChecksumKind); + CSInfo.emplace(CSK, ChkSum); + std::optional Src; + if (SourceLen > 0) + Src = StringRef(Source, SourceLen); + else + Src = std::nullopt; + return wrap(unwrap(Builder)->createFile(StringRef(Filename, FilenameLen), + StringRef(Directory, DirectoryLen), + CSInfo, Src)); +} + LLVMMetadataRef LLVMDIBuilderCreateModule(LLVMDIBuilderRef Builder, LLVMMetadataRef ParentScope, const char *Name, size_t NameLen, diff --git a/llvm/test/Bindings/llvm-c/debug_info_new_format.ll b/llvm/test/Bindings/llvm-c/debug_info_new_format.ll index 83b37da759b5c..75e5fa01b14a0 100644 --- a/llvm/test/Bindings/llvm-c/debug_info_new_format.ll +++ b/llvm/test/Bindings/llvm-c/debug_info_new_format.ll @@ -3,37 +3,37 @@ ; CHECK: ; ModuleID = 'debuginfo.c' ; CHECK-NEXT: source_filename = "debuginfo.c" - -; CHECK: define i64 @foo(i64 %0, i64 %1, <10 x i64> %2) !dbg !44 { + +; CHECK: define i64 @foo(i64 %0, i64 %1, <10 x i64> %2) !dbg !45 { ; CHECK-NEXT: entry: -; CHECK-NEXT: #dbg_declare(i64 0, !49, !DIExpression(), !58) -; CHECK-NEXT: #dbg_declare(i64 0, !50, !DIExpression(), !58) -; CHECK-NEXT: #dbg_declare(i64 0, !51, !DIExpression(), !58) -; CHECK-NEXT: #dbg_label(!59, !58) +; CHECK-NEXT: #dbg_declare(i64 0, !50, !DIExpression(), !59) +; CHECK-NEXT: #dbg_declare(i64 0, !51, !DIExpression(), !59) +; CHECK-NEXT: #dbg_declare(i64 0, !52, !DIExpression(), !59) +; CHECK-NEXT: #dbg_label(!60, !59) ; CHECK-NEXT: br label %vars -; CHECK-NEXT: #dbg_label(!60, !58) +; CHECK-NEXT: #dbg_label(!61, !59) ; CHECK-NEXT: br label %vars ; CHECK: vars: ; preds = %entry, %entry ; CHECK-NEXT: %p1 = phi i64 [ 0, %entry ] ; CHECK-NEXT: %p2 = phi i64 [ 0, %entry ] -; CHECK-NEXT: #dbg_value(i64 0, !42, !DIExpression(DW_OP_constu, 0, DW_OP_stack_value), !61) -; CHECK-NEXT: #dbg_value(i64 1, !52, !DIExpression(DW_OP_constu, 1, DW_OP_stack_value), !61) +; CHECK-NEXT: #dbg_value(i64 0, !43, !DIExpression(DW_OP_constu, 0, DW_OP_stack_value), !62) +; CHECK-NEXT: #dbg_value(i64 1, !53, !DIExpression(DW_OP_constu, 1, DW_OP_stack_value), !62) ; CHECK-NEXT: %a = add i64 %p1, %p2 ; CHECK-NEXT: ret i64 0 ; CHECK-NEXT: } ; CHECK: !llvm.dbg.cu = !{!0} -; CHECK-NEXT: !FooType = !{!33} +; CHECK-NEXT: !FooType = !{!34} ; CHECK-NEXT: !EnumTest = !{!3} ; CHECK-NEXT: !LargeEnumTest = !{!11} -; CHECK-NEXT: !SubrangeType = !{!36} -; CHECK-NEXT: !SetType1 = !{!37} -; CHECK-NEXT: !SetType2 = !{!38} -; CHECK-NEXT: !DynType = !{!39} -; CHECK-NEXT: !ClassType = !{!54} +; CHECK-NEXT: !SubrangeType = !{!37} +; CHECK-NEXT: !SetType1 = !{!38} +; CHECK-NEXT: !SetType2 = !{!39} +; CHECK-NEXT: !DynType = !{!40} +; CHECK-NEXT: !ClassType = !{!55} -; 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: !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: !29, splitDebugInlining: false, sysroot: "/") ; CHECK-NEXT: !1 = !DIFile(filename: "debuginfo.c", directory: ".") ; 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) @@ -57,41 +57,42 @@ ; 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: !24 = !{!25, !28} +; CHECK-NEXT: !25 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !5, entity: !26, file: !27, 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 = !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) -; CHECK-NEXT: !37 = !DIDerivedType(tag: DW_TAG_set_type, name: "enumset", scope: !1, file: !1, line: 42, baseType: !3, size: 64) -; CHECK-NEXT: !38 = !DIDerivedType(tag: DW_TAG_set_type, name: "subrangeset", scope: !1, file: !1, line: 42, baseType: !36, size: 64) -; 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()) -; CHECK-NEXT: !40 = !{!41} -; CHECK-NEXT: !41 = !DISubrange(count: 10, lowerBound: 0) -; CHECK-NEXT: !42 = !DILocalVariable(name: "d", scope: !43, file: !1, line: 43, type: !6) -; CHECK-NEXT: !43 = distinct !DILexicalBlock(scope: !44, file: !1, line: 42) -; 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) -; CHECK-NEXT: !45 = !DISubroutineType(types: !46) -; CHECK-NEXT: !46 = !{!6, !6, !47} -; CHECK-NEXT: !47 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 640, flags: DIFlagVector, elements: !40) -; CHECK-NEXT: !48 = !{!49, !50, !51, !42, !52, !53} -; CHECK-NEXT: !49 = !DILocalVariable(name: "a", arg: 1, scope: !44, file: !1, line: 42, type: !6) -; CHECK-NEXT: !50 = !DILocalVariable(name: "b", arg: 2, scope: !44, file: !1, line: 42, type: !6) -; CHECK-NEXT: !51 = !DILocalVariable(name: "c", arg: 3, scope: !44, file: !1, line: 42, type: !47) -; CHECK-NEXT: !52 = !DILocalVariable(name: "e", scope: !43, file: !1, line: 44, type: !6) -; CHECK-NEXT: !53 = !DILabel(scope: !44, name: "label3", file: !1, line: 42) -; CHECK-NEXT: !54 = !DICompositeType(tag: DW_TAG_class_type, name: "Class", scope: !4, file: !1, size: 192, flags: DIFlagFwdDecl, elements: !55, identifier: "FooClass") -; CHECK-NEXT: !55 = !{!56} -; CHECK-NEXT: !56 = !{!6, !6, !57} -; CHECK-NEXT: !57 = !DIBasicType(name: "Int32", size: 32) -; CHECK-NEXT: !58 = !DILocation(line: 42, scope: !44) -; CHECK-NEXT: !59 = !DILabel(scope: !44, name: "label1", file: !1, line: 42) -; CHECK-NEXT: !60 = !DILabel(scope: !44, name: "label2", file: !1, line: 42) -; CHECK-NEXT: !61 = !DILocation(line: 43, scope: !44) +; CHECK-NEXT: !27 = !DIFile(filename: "debuginfo.c", directory: ".", checksumkind: CSK_MD5, checksum: "1234", source: "source") +; CHECK-NEXT: !28 = !DIImportedEntity(tag: DW_TAG_imported_module, scope: !5, entity: !25, file: !1, line: 42) +; CHECK-NEXT: !29 = !{!30} +; CHECK-NEXT: !30 = !DIMacroFile(file: !1, nodes: !31) +; CHECK-NEXT: !31 = !{!32, !33} +; CHECK-NEXT: !32 = !DIMacro(type: DW_MACINFO_define, name: "SIMPLE_DEFINE") +; CHECK-NEXT: !33 = !DIMacro(type: DW_MACINFO_define, name: "VALUE_DEFINE", value: "1") +; CHECK-NEXT: !34 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !35, size: 192, dwarfAddressSpace: 0) +; CHECK-NEXT: !35 = !DICompositeType(tag: DW_TAG_structure_type, name: "MyStruct", scope: !4, file: !1, size: 192, elements: !36, runtimeLang: DW_LANG_C89, identifier: "MyStruct") +; CHECK-NEXT: !36 = !{!6, !6, !6} +; CHECK-NEXT: !37 = !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) +; CHECK-NEXT: !38 = !DIDerivedType(tag: DW_TAG_set_type, name: "enumset", scope: !1, file: !1, line: 42, baseType: !3, size: 64) +; CHECK-NEXT: !39 = !DIDerivedType(tag: DW_TAG_set_type, name: "subrangeset", scope: !1, file: !1, line: 42, baseType: !37, size: 64) +; CHECK-NEXT: !40 = !DICompositeType(tag: DW_TAG_array_type, name: "foo", scope: !1, file: !1, line: 42, baseType: !6, size: 640, elements: !41, dataLocation: !DIExpression(), associated: !43, rank: !DIExpression()) +; CHECK-NEXT: !41 = !{!42} +; CHECK-NEXT: !42 = !DISubrange(count: 10, lowerBound: 0) +; CHECK-NEXT: !43 = !DILocalVariable(name: "d", scope: !44, file: !1, line: 43, type: !6) +; CHECK-NEXT: !44 = distinct !DILexicalBlock(scope: !45, file: !1, line: 42) +; CHECK-NEXT: !45 = distinct !DISubprogram(name: "foo", linkageName: "foo", scope: !1, file: !1, line: 42, type: !46, scopeLine: 42, spFlags: DISPFlagLocalToUnit | DISPFlagDefinition, unit: !0, retainedNodes: !49) +; CHECK-NEXT: !46 = !DISubroutineType(types: !47) +; CHECK-NEXT: !47 = !{!6, !6, !48} +; CHECK-NEXT: !48 = !DICompositeType(tag: DW_TAG_array_type, baseType: !6, size: 640, flags: DIFlagVector, elements: !41) +; CHECK-NEXT: !49 = !{!50, !51, !52, !43, !53, !54} +; CHECK-NEXT: !50 = !DILocalVariable(name: "a", arg: 1, scope: !45, file: !1, line: 42, type: !6) +; CHECK-NEXT: !51 = !DILocalVariable(name: "b", arg: 2, scope: !45, file: !1, line: 42, type: !6) +; CHECK-NEXT: !52 = !DILocalVariable(name: "c", arg: 3, scope: !45, file: !1, line: 42, type: !48) +; CHECK-NEXT: !53 = !DILocalVariable(name: "e", scope: !44, file: !1, line: 44, type: !6) +; CHECK-NEXT: !54 = !DILabel(scope: !45, name: "label3", file: !1, line: 42) +; CHECK-NEXT: !55 = !DICompositeType(tag: DW_TAG_class_type, name: "Class", scope: !4, file: !1, size: 192, flags: DIFlagFwdDecl, elements: !56, identifier: "FooClass") +; CHECK-NEXT: !56 = !{!57} +; CHECK-NEXT: !57 = !{!6, !6, !58} +; CHECK-NEXT: !58 = !DIBasicType(name: "Int32", size: 32) +; CHECK-NEXT: !59 = !DILocation(line: 42, scope: !45) +; CHECK-NEXT: !60 = !DILabel(scope: !45, name: "label1", file: !1, line: 42) +; CHECK-NEXT: !61 = !DILabel(scope: !45, name: "label2", file: !1, line: 42) +; CHECK-NEXT: !62 = !DILocation(line: 43, scope: !45) diff --git a/llvm/tools/llvm-c-test/debuginfo.c b/llvm/tools/llvm-c-test/debuginfo.c index 0f09c74a476bb..23fa38f4091d3 100644 --- a/llvm/tools/llvm-c-test/debuginfo.c +++ b/llvm/tools/llvm-c-test/debuginfo.c @@ -43,6 +43,9 @@ int llvm_test_dibuilder(void) { LLVMMetadataRef File = LLVMDIBuilderCreateFile(DIB, Filename, strlen(Filename), ".", 1); + LLVMMetadataRef FileCS = LLVMDIBuilderCreateFileWithCheckSum( + DIB, Filename, strlen(Filename), ".", 1, CSK_MD5, "1234", 4, "source", 6); + LLVMMetadataRef CompileUnit = LLVMDIBuilderCreateCompileUnit( DIB, LLVMDWARFSourceLanguageC, File, "llvm-c-test", 11, 0, NULL, 0, 0, NULL, 0, LLVMDWARFEmissionFull, 0, 0, 0, "/", 1, "", 0); @@ -61,7 +64,7 @@ int llvm_test_dibuilder(void) { "/test/include/llvm-c-test-import.h", 34, "", 0); LLVMMetadataRef ImportedModule = LLVMDIBuilderCreateImportedModuleFromModule( - DIB, Module, OtherModule, File, 42, NULL, 0); + DIB, Module, OtherModule, FileCS, 42, NULL, 0); LLVMDIBuilderCreateImportedModuleFromAlias(DIB, Module, ImportedModule, File, 42, NULL, 0); From 4b1ae36c0236cb925378c37c208b05429040204b Mon Sep 17 00:00:00 2001 From: peter mckinna Date: Thu, 9 Oct 2025 14:50:24 +1100 Subject: [PATCH 2/2] Fix switch default --- llvm/lib/IR/DebugInfo.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/IR/DebugInfo.cpp b/llvm/lib/IR/DebugInfo.cpp index 2b767f19a3923..8e44c5f1d5aab 100644 --- a/llvm/lib/IR/DebugInfo.cpp +++ b/llvm/lib/IR/DebugInfo.cpp @@ -1104,9 +1104,8 @@ map_from_llvmChecksumKind(LLVMChecksumKind CSKind) { return llvm::DIFile::CSK_SHA1; case LLVMChecksumKind::CSK_SHA256: return llvm::DIFile::CSK_SHA256; - default: - llvm_unreachable("Unhandled Checksum Kind"); } + llvm_unreachable("Unhandled Checksum Kind"); } LLVMMetadataRef LLVMDIBuilderCreateFileWithCheckSum(