Skip to content

Commit 9350792

Browse files
committed
[DebugInfo] Update loop metadata in stripNonLineTableDebugInfo
Summary: Have stripNonLineTableDebugInfo() attach updated !llvm.loop metadata to an instruction (instead of updating and then discarding the metadata). This fixes "!dbg attachment points at wrong subprogram for function" errors seen while archiving an iOS app. It would be nice -- as a follow-up -- to catch this issue earlier, perhaps by modifying the verifier to constrain where DILocations are allowed. Any alternative suggestions appreciated. rdar://61982466 Reviewers: aprantl, dsanders Subscribers: hiraditya, llvm-commits Tags: #llvm Differential Revision: https://reviews.llvm.org/D79200
1 parent cd05707 commit 9350792

File tree

2 files changed

+70
-9
lines changed

2 files changed

+70
-9
lines changed

llvm/lib/IR/DebugInfo.cpp

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -658,15 +658,10 @@ bool llvm::stripNonLineTableDebugInfo(Module &M) {
658658
if (I.getDebugLoc() != DebugLoc())
659659
I.setDebugLoc(remapDebugLoc(I.getDebugLoc()));
660660

661-
// Remap DILocations in untyped MDNodes (e.g., llvm.loop).
662-
SmallVector<std::pair<unsigned, MDNode *>, 2> MDs;
663-
I.getAllMetadata(MDs);
664-
for (auto Attachment : MDs)
665-
if (auto *T = dyn_cast_or_null<MDTuple>(Attachment.second))
666-
for (unsigned N = 0; N < T->getNumOperands(); ++N)
667-
if (auto *Loc = dyn_cast_or_null<DILocation>(T->getOperand(N)))
668-
if (Loc != DebugLoc())
669-
T->replaceOperandWith(N, remapDebugLoc(Loc));
661+
// Remap DILocations in llvm.loop attachments.
662+
updateLoopMetadataDebugLocations(I, [&](const DILocation &Loc) {
663+
return remapDebugLoc(&Loc).get();
664+
});
670665
}
671666
}
672667
}

llvm/unittests/IR/DebugInfoTest.cpp

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,25 @@
66
//
77
//===----------------------------------------------------------------------===//
88

9+
#include "llvm/IR/DebugInfo.h"
10+
#include "llvm/AsmParser/Parser.h"
911
#include "llvm/IR/DebugInfoMetadata.h"
12+
#include "llvm/IR/LLVMContext.h"
13+
#include "llvm/IR/Module.h"
14+
#include "llvm/IR/Verifier.h"
15+
#include "llvm/Support/SourceMgr.h"
1016
#include "gtest/gtest.h"
1117

1218
using namespace llvm;
1319

20+
static std::unique_ptr<Module> parseIR(LLVMContext &C, const char *IR) {
21+
SMDiagnostic Err;
22+
std::unique_ptr<Module> Mod = parseAssemblyString(IR, Err, C);
23+
if (!Mod)
24+
Err.print("DebugInfoTest", errs());
25+
return Mod;
26+
}
27+
1428
namespace {
1529

1630
TEST(DINodeTest, getFlag) {
@@ -79,4 +93,56 @@ TEST(DINodeTest, splitFlags) {
7993
#undef CHECK_SPLIT
8094
}
8195

96+
TEST(StripTest, LoopMetadata) {
97+
LLVMContext C;
98+
std::unique_ptr<Module> M = parseIR(C, R"(
99+
define void @f() !dbg !5 {
100+
ret void, !dbg !10, !llvm.loop !11
101+
}
102+
103+
!llvm.dbg.cu = !{!0}
104+
!llvm.debugify = !{!3, !3}
105+
!llvm.module.flags = !{!4}
106+
107+
!0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
108+
!1 = !DIFile(filename: "loop.ll", directory: "/")
109+
!2 = !{}
110+
!3 = !{i32 1}
111+
!4 = !{i32 2, !"Debug Info Version", i32 3}
112+
!5 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !7)
113+
!6 = !DISubroutineType(types: !2)
114+
!7 = !{!8}
115+
!8 = !DILocalVariable(name: "1", scope: !5, file: !1, line: 1, type: !9)
116+
!9 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned)
117+
!10 = !DILocation(line: 1, column: 1, scope: !5)
118+
!11 = distinct !{!11, !10, !10}
119+
)");
120+
121+
// Look up the debug info emission kind for the CU via the loop metadata
122+
// attached to the terminator. If, when stripping non-line table debug info,
123+
// we update the terminator's metadata correctly, we should be able to
124+
// observe the change in emission kind for the CU.
125+
auto getEmissionKind = [&]() {
126+
Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI();
127+
MDNode *LoopMD = I.getMetadata(LLVMContext::MD_loop);
128+
return cast<DILocation>(LoopMD->getOperand(1))
129+
->getScope()
130+
->getSubprogram()
131+
->getUnit()
132+
->getEmissionKind();
133+
};
134+
135+
EXPECT_EQ(getEmissionKind(), DICompileUnit::FullDebug);
136+
137+
bool Changed = stripNonLineTableDebugInfo(*M);
138+
EXPECT_TRUE(Changed);
139+
140+
EXPECT_EQ(getEmissionKind(), DICompileUnit::LineTablesOnly);
141+
142+
bool BrokenDebugInfo = false;
143+
bool HardError = verifyModule(*M, &errs(), &BrokenDebugInfo);
144+
EXPECT_FALSE(HardError);
145+
EXPECT_FALSE(BrokenDebugInfo);
146+
}
147+
82148
} // end namespace

0 commit comments

Comments
 (0)