diff --git a/lib/IR/DebugInfo.cpp b/lib/IR/DebugInfo.cpp index 1c63476785f..254b6fe563e 100644 --- a/lib/IR/DebugInfo.cpp +++ b/lib/IR/DebugInfo.cpp @@ -658,15 +658,10 @@ bool llvm::stripNonLineTableDebugInfo(Module &M) { if (I.getDebugLoc() != DebugLoc()) I.setDebugLoc(remapDebugLoc(I.getDebugLoc())); - // Remap DILocations in untyped MDNodes (e.g., llvm.loop). - SmallVector, 2> MDs; - I.getAllMetadata(MDs); - for (auto Attachment : MDs) - if (auto *T = dyn_cast_or_null(Attachment.second)) - for (unsigned N = 0; N < T->getNumOperands(); ++N) - if (auto *Loc = dyn_cast_or_null(T->getOperand(N))) - if (Loc != DebugLoc()) - T->replaceOperandWith(N, remapDebugLoc(Loc)); + // Remap DILocations in llvm.loop attachments. + updateLoopMetadataDebugLocations(I, [&](const DILocation &Loc) { + return remapDebugLoc(&Loc).get(); + }); } } } diff --git a/unittests/IR/DebugInfoTest.cpp b/unittests/IR/DebugInfoTest.cpp index 93247908d8a..c7ec3a93330 100644 --- a/unittests/IR/DebugInfoTest.cpp +++ b/unittests/IR/DebugInfoTest.cpp @@ -6,11 +6,25 @@ // //===----------------------------------------------------------------------===// +#include "llvm/IR/DebugInfo.h" +#include "llvm/AsmParser/Parser.h" #include "llvm/IR/DebugInfoMetadata.h" +#include "llvm/IR/LLVMContext.h" +#include "llvm/IR/Module.h" +#include "llvm/IR/Verifier.h" +#include "llvm/Support/SourceMgr.h" #include "gtest/gtest.h" using namespace llvm; +static std::unique_ptr parseIR(LLVMContext &C, const char *IR) { + SMDiagnostic Err; + std::unique_ptr Mod = parseAssemblyString(IR, Err, C); + if (!Mod) + Err.print("DebugInfoTest", errs()); + return Mod; +} + namespace { TEST(DINodeTest, getFlag) { @@ -79,4 +93,56 @@ TEST(DINodeTest, splitFlags) { #undef CHECK_SPLIT } +TEST(StripTest, LoopMetadata) { + LLVMContext C; + std::unique_ptr M = parseIR(C, R"( + define void @f() !dbg !5 { + ret void, !dbg !10, !llvm.loop !11 + } + + !llvm.dbg.cu = !{!0} + !llvm.debugify = !{!3, !3} + !llvm.module.flags = !{!4} + + !0 = distinct !DICompileUnit(language: DW_LANG_C, file: !1, producer: "debugify", isOptimized: true, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) + !1 = !DIFile(filename: "loop.ll", directory: "/") + !2 = !{} + !3 = !{i32 1} + !4 = !{i32 2, !"Debug Info Version", i32 3} + !5 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !1, line: 1, type: !6, scopeLine: 1, spFlags: DISPFlagDefinition | DISPFlagOptimized, unit: !0, retainedNodes: !7) + !6 = !DISubroutineType(types: !2) + !7 = !{!8} + !8 = !DILocalVariable(name: "1", scope: !5, file: !1, line: 1, type: !9) + !9 = !DIBasicType(name: "ty32", size: 32, encoding: DW_ATE_unsigned) + !10 = !DILocation(line: 1, column: 1, scope: !5) + !11 = distinct !{!11, !10, !10} +)"); + + // Look up the debug info emission kind for the CU via the loop metadata + // attached to the terminator. If, when stripping non-line table debug info, + // we update the terminator's metadata correctly, we should be able to + // observe the change in emission kind for the CU. + auto getEmissionKind = [&]() { + Instruction &I = *M->getFunction("f")->getEntryBlock().getFirstNonPHI(); + MDNode *LoopMD = I.getMetadata(LLVMContext::MD_loop); + return cast(LoopMD->getOperand(1)) + ->getScope() + ->getSubprogram() + ->getUnit() + ->getEmissionKind(); + }; + + EXPECT_EQ(getEmissionKind(), DICompileUnit::FullDebug); + + bool Changed = stripNonLineTableDebugInfo(*M); + EXPECT_TRUE(Changed); + + EXPECT_EQ(getEmissionKind(), DICompileUnit::LineTablesOnly); + + bool BrokenDebugInfo = false; + bool HardError = verifyModule(*M, &errs(), &BrokenDebugInfo); + EXPECT_FALSE(HardError); + EXPECT_FALSE(BrokenDebugInfo); +} + } // end namespace