From 7a084b4e4db71377a538363e6a7d73fc1acbbc10 Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Thu, 29 Aug 2024 13:28:11 +0100 Subject: [PATCH 01/10] [DebugInfo][RemoveDIs] Find types hidden in DbgRecords MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When serialising to textual IR, there can be constant Values referred to by DbgRecords that don't appear anywhere else, and have types hidden even deeper in side them. Enumerate these when enumerating all types. Test by Mikael Holmén. --- llvm/lib/IR/TypeFinder.cpp | 11 +++++ .../DebugInfo/type-finder-w-dbg-records.ll | 43 +++++++++++++++++++ 2 files changed, 54 insertions(+) create mode 100644 llvm/test/DebugInfo/type-finder-w-dbg-records.ll diff --git a/llvm/lib/IR/TypeFinder.cpp b/llvm/lib/IR/TypeFinder.cpp index 003155a4af487..d2ffe1ba77b4e 100644 --- a/llvm/lib/IR/TypeFinder.cpp +++ b/llvm/lib/IR/TypeFinder.cpp @@ -88,6 +88,17 @@ void TypeFinder::run(const Module &M, bool onlyNamed) { for (const auto &MD : MDForInst) incorporateMDNode(MD.second); MDForInst.clear(); + + // Incorporate types hiding in variable-location information. + for (const auto &Dbg : I.getDbgRecordRange()) { + // Pick out records that have Values. + if (Dbg.getRecordKind() != DbgRecord::Kind::ValueKind) + continue; + const DbgVariableRecord &DVI = static_cast(Dbg); + for (Value *V : DVI.location_ops()) { + incorporateValue(V); + } + } } } diff --git a/llvm/test/DebugInfo/type-finder-w-dbg-records.ll b/llvm/test/DebugInfo/type-finder-w-dbg-records.ll new file mode 100644 index 0000000000000..d2daabc40a3ac --- /dev/null +++ b/llvm/test/DebugInfo/type-finder-w-dbg-records.ll @@ -0,0 +1,43 @@ +; RUN: opt --passes=verify %s -o - -S | FileCheck %s + +;; Test that the type definitions are discovered when serialising to LLVM-IR, +;; even if they're only present inside a DbgRecord, and thus not normally +;; visible. + +; CHECK: %union.anon = type { %struct.a } +; CHECK: %struct.a = type { i32 } + +; ModuleID = 'bbi-98372.ll' +source_filename = "bbi-98372.ll" + +%union.anon = type { %struct.a } +%struct.a = type { i32 } + +@d = global [1 x { i16, i16 }] [{ i16, i16 } { i16 0, i16 undef }], align 1 + +define void @e() { +entry: + #dbg_value(ptr getelementptr inbounds ([1 x %union.anon], ptr @d, i32 0, i32 3), !7, !DIExpression(), !14) + ret void, !dbg !15 +} + +!llvm.dbg.cu = !{!0} +!llvm.module.flags = !{!2, !3, !4, !5} +!llvm.ident = !{!6} + +!0 = distinct !DICompileUnit(language: DW_LANG_C11, file: !1, producer: "clang", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, splitDebugInlining: false, nameTableKind: None) +!1 = !DIFile(filename: "foo.c", directory: "/bar") +!2 = !{i32 7, !"Dwarf Version", i32 4} +!3 = !{i32 2, !"Debug Info Version", i32 3} +!4 = !{i32 1, !"wchar_size", i32 1} +!5 = !{i32 7, !"frame-pointer", i32 2} +!6 = !{!"clang"} +!7 = !DILocalVariable(name: "f", scope: !8, file: !1, line: 8, type: !12) +!8 = distinct !DISubprogram(name: "e", scope: !1, file: !1, line: 8, type: !9, scopeLine: 8, flags: DIFlagAllCallsDescribed, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !11) +!9 = !DISubroutineType(types: !10) +!10 = !{null} +!11 = !{!7} +!12 = !DIDerivedType(tag: DW_TAG_pointer_type, baseType: !13, size: 16) +!13 = !DIBasicType(name: "int", size: 16, encoding: DW_ATE_signed) +!14 = !DILocation(line: 0, scope: !8) +!15 = !DILocation(line: 8, column: 28, scope: !8) From 1e5a2cdc7e3b933df6bae0a72305e7472d342dc5 Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Thu, 29 Aug 2024 13:40:07 +0100 Subject: [PATCH 02/10] claaannngggg fooorrmmaatttt --- llvm/lib/IR/TypeFinder.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/llvm/lib/IR/TypeFinder.cpp b/llvm/lib/IR/TypeFinder.cpp index d2ffe1ba77b4e..eb5d61e959ef5 100644 --- a/llvm/lib/IR/TypeFinder.cpp +++ b/llvm/lib/IR/TypeFinder.cpp @@ -94,7 +94,8 @@ void TypeFinder::run(const Module &M, bool onlyNamed) { // Pick out records that have Values. if (Dbg.getRecordKind() != DbgRecord::Kind::ValueKind) continue; - const DbgVariableRecord &DVI = static_cast(Dbg); + const DbgVariableRecord &DVI = + static_cast(Dbg); for (Value *V : DVI.location_ops()) { incorporateValue(V); } From 515ab3a707c10b1ef6ac7704c9f5cf4d91d3fae2 Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Thu, 29 Aug 2024 14:05:44 +0100 Subject: [PATCH 03/10] Switch to dyn_cast, get Address too --- llvm/lib/IR/TypeFinder.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/llvm/lib/IR/TypeFinder.cpp b/llvm/lib/IR/TypeFinder.cpp index eb5d61e959ef5..ed7b2ab3617ec 100644 --- a/llvm/lib/IR/TypeFinder.cpp +++ b/llvm/lib/IR/TypeFinder.cpp @@ -92,12 +92,11 @@ void TypeFinder::run(const Module &M, bool onlyNamed) { // Incorporate types hiding in variable-location information. for (const auto &Dbg : I.getDbgRecordRange()) { // Pick out records that have Values. - if (Dbg.getRecordKind() != DbgRecord::Kind::ValueKind) - continue; - const DbgVariableRecord &DVI = - static_cast(Dbg); - for (Value *V : DVI.location_ops()) { - incorporateValue(V); + if (const DbgVariableRecord*DVI = dyn_cast(&Dbg)) { + for (Value *V : DVI->location_ops()) + incorporateValue(V); + if (Value *Addr = DVI->getAddress(); Addr && DVI->isDbgAssign()) + incorporateValue(Addr); } } } From 791ce77e91340b88f92d75ad842da452e0c62d39 Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Thu, 29 Aug 2024 14:35:49 +0100 Subject: [PATCH 04/10] Add a #dbg_assign to be enumerated --- llvm/test/DebugInfo/type-finder-w-dbg-records.ll | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/llvm/test/DebugInfo/type-finder-w-dbg-records.ll b/llvm/test/DebugInfo/type-finder-w-dbg-records.ll index d2daabc40a3ac..8259b4a9f1c3a 100644 --- a/llvm/test/DebugInfo/type-finder-w-dbg-records.ll +++ b/llvm/test/DebugInfo/type-finder-w-dbg-records.ll @@ -6,18 +6,24 @@ ; CHECK: %union.anon = type { %struct.a } ; CHECK: %struct.a = type { i32 } +; CHECK: %union.anon2 = type { %struct.a2 } +; CHECK: %struct.a2 = type { i32 } ; ModuleID = 'bbi-98372.ll' source_filename = "bbi-98372.ll" %union.anon = type { %struct.a } %struct.a = type { i32 } +%union.anon2 = type { %struct.a2 } +%struct.a2 = type { i32 } @d = global [1 x { i16, i16 }] [{ i16, i16 } { i16 0, i16 undef }], align 1 +@e = global [1 x { i16, i16 }] [{ i16, i16 } { i16 0, i16 undef }], align 1 -define void @e() { +define void @f() { entry: #dbg_value(ptr getelementptr inbounds ([1 x %union.anon], ptr @d, i32 0, i32 3), !7, !DIExpression(), !14) + #dbg_assign(ptr null, !7, !DIExpression(), !16, ptr getelementptr inbounds ([1 x %union.anon2], ptr @e, i32 0, i32 3), !17, !14) ret void, !dbg !15 } @@ -41,3 +47,5 @@ entry: !13 = !DIBasicType(name: "int", size: 16, encoding: DW_ATE_signed) !14 = !DILocation(line: 0, scope: !8) !15 = !DILocation(line: 8, column: 28, scope: !8) +!16 = distinct !DIAssignID() +!17 = !DIExpression() From 90055ba9fca14447cf62261a14e18b14ed08137a Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Thu, 29 Aug 2024 17:46:04 +0100 Subject: [PATCH 05/10] clang-format again --- llvm/lib/IR/TypeFinder.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/llvm/lib/IR/TypeFinder.cpp b/llvm/lib/IR/TypeFinder.cpp index ed7b2ab3617ec..d33b80d6d073c 100644 --- a/llvm/lib/IR/TypeFinder.cpp +++ b/llvm/lib/IR/TypeFinder.cpp @@ -92,11 +92,12 @@ void TypeFinder::run(const Module &M, bool onlyNamed) { // Incorporate types hiding in variable-location information. for (const auto &Dbg : I.getDbgRecordRange()) { // Pick out records that have Values. - if (const DbgVariableRecord*DVI = dyn_cast(&Dbg)) { + if (const DbgVariableRecord *DVI = + dyn_cast(&Dbg)) { for (Value *V : DVI->location_ops()) incorporateValue(V); - if (Value *Addr = DVI->getAddress(); Addr && DVI->isDbgAssign()) - incorporateValue(Addr); + if (Value *Addr = DVI->getAddress(); Addr && DVI->isDbgAssign()) + incorporateValue(Addr); } } } From 4eaf585ee8531352ed3c6f816be1bbc1a0e9c439 Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Fri, 30 Aug 2024 10:51:20 +0100 Subject: [PATCH 06/10] Allow for empty dbg_assign addresses being null --- llvm/lib/IR/DebugProgramInstruction.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index 7937e306e7a8c..f9f3264eab23d 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -473,11 +473,12 @@ DbgLabelRecord::createDebugIntrinsic(Module *M, Value *DbgVariableRecord::getAddress() const { auto *MD = getRawAddress(); - if (auto *V = dyn_cast(MD)) + if (auto *V = dyn_cast_or_null(MD)) return V->getValue(); // When the value goes to null, it gets replaced by an empty MDNode. - assert(!cast(MD)->getNumOperands() && "Expected an empty MDNode"); + assert(!MD || !cast(MD)->getNumOperands() && + "Expected an empty MDNode"); return nullptr; } From e2a3fe40ba8e41684f533e16273da45b921e9d34 Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Fri, 30 Aug 2024 10:57:13 +0100 Subject: [PATCH 07/10] clang-format --- llvm/lib/IR/DebugProgramInstruction.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index f9f3264eab23d..c47d1ee4856ba 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -477,8 +477,8 @@ Value *DbgVariableRecord::getAddress() const { return V->getValue(); // When the value goes to null, it gets replaced by an empty MDNode. - assert(!MD || !cast(MD)->getNumOperands() && - "Expected an empty MDNode"); + assert(!MD || + !cast(MD)->getNumOperands() && "Expected an empty MDNode"); return nullptr; } From a887cb7edb6ce750867a2b8403b01a34b04edbaa Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Fri, 30 Aug 2024 12:59:50 +0100 Subject: [PATCH 08/10] Allow for DIArgLists in the address field of #dbg_assigns --- llvm/lib/IR/DebugProgramInstruction.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index c47d1ee4856ba..a3a712b540428 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -477,7 +477,11 @@ Value *DbgVariableRecord::getAddress() const { return V->getValue(); // When the value goes to null, it gets replaced by an empty MDNode. + // We can also convert the address to a DIArgList if an address computation + // gets salvaged; this is a legal salvage that we can't recover any + // assignment-tracking information from. assert(!MD || + isa(MD) || !cast(MD)->getNumOperands() && "Expected an empty MDNode"); return nullptr; } From 0a358b1e0c57c27df0e30e964b5cb4904d260f9d Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Fri, 30 Aug 2024 13:00:14 +0100 Subject: [PATCH 09/10] The proverbial clang-format --- llvm/lib/IR/DebugProgramInstruction.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index a3a712b540428..a30bc5fec7462 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -480,8 +480,7 @@ Value *DbgVariableRecord::getAddress() const { // We can also convert the address to a DIArgList if an address computation // gets salvaged; this is a legal salvage that we can't recover any // assignment-tracking information from. - assert(!MD || - isa(MD) || + assert(!MD || isa(MD) || !cast(MD)->getNumOperands() && "Expected an empty MDNode"); return nullptr; } From 792f9b9c667a0192abc32346dc81ab0cbcb1bb36 Mon Sep 17 00:00:00 2001 From: Jeremy Morse Date: Mon, 2 Sep 2024 10:27:44 +0100 Subject: [PATCH 10/10] Don't access address field on non-dbg-assigns --- llvm/lib/IR/DebugProgramInstruction.cpp | 5 +---- llvm/lib/IR/TypeFinder.cpp | 6 ++++-- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/llvm/lib/IR/DebugProgramInstruction.cpp b/llvm/lib/IR/DebugProgramInstruction.cpp index a30bc5fec7462..c47d1ee4856ba 100644 --- a/llvm/lib/IR/DebugProgramInstruction.cpp +++ b/llvm/lib/IR/DebugProgramInstruction.cpp @@ -477,10 +477,7 @@ Value *DbgVariableRecord::getAddress() const { return V->getValue(); // When the value goes to null, it gets replaced by an empty MDNode. - // We can also convert the address to a DIArgList if an address computation - // gets salvaged; this is a legal salvage that we can't recover any - // assignment-tracking information from. - assert(!MD || isa(MD) || + assert(!MD || !cast(MD)->getNumOperands() && "Expected an empty MDNode"); return nullptr; } diff --git a/llvm/lib/IR/TypeFinder.cpp b/llvm/lib/IR/TypeFinder.cpp index d33b80d6d073c..963f4b4806e1f 100644 --- a/llvm/lib/IR/TypeFinder.cpp +++ b/llvm/lib/IR/TypeFinder.cpp @@ -96,8 +96,10 @@ void TypeFinder::run(const Module &M, bool onlyNamed) { dyn_cast(&Dbg)) { for (Value *V : DVI->location_ops()) incorporateValue(V); - if (Value *Addr = DVI->getAddress(); Addr && DVI->isDbgAssign()) - incorporateValue(Addr); + if (DVI->isDbgAssign()) { + if (Value *Addr = DVI->getAddress()) + incorporateValue(Addr); + } } } }