From 6eeae175e1c1bacd23a466cf4413442a42691644 Mon Sep 17 00:00:00 2001 From: Ewan Crawford Date: Thu, 3 Aug 2017 09:23:03 +0000 Subject: [PATCH] [Cloning] Move distinct GlobalVariable debug info metadata in CloneModule Duplicating the distinct Subprogram and CU metadata nodes seems like the incorrect thing to do in CloneModule for GlobalVariable debug info. As it results in the scope of the GlobalVariable DI no longer being consistent with the rest of the module, and the new CU is absent from llvm.dbg.cu. Fixed by adding RF_MoveDistinctMDs to MapMetadata flags for GlobalVariables. Current unit test IR after clone: ``` @gv = global i32 1, comdat($comdat), !dbg !0, !type !5 define private void @f() comdat($comdat) personality void ()* @persfn !dbg !14 { !llvm.dbg.cu = !{!10} !0 = !DIGlobalVariableExpression(var: !1) !1 = distinct !DIGlobalVariable(name: "gv", linkageName: "gv", scope: !2, file: !3, line: 1, type: !9, isLocal: false, isDefinition: true) !2 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !3, line: 4, type: !4, isLocal: true, isDefinition: true, scopeLine: 3, isOptimized: false, unit: !6, variables: !5) !3 = !DIFile(filename: "filename.c", directory: "/file/dir/") !4 = !DISubroutineType(types: !5) !5 = !{} !6 = distinct !DICompileUnit(language: DW_LANG_C99, file: !7, producer: "CloneModule", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, globals: !8) !7 = !DIFile(filename: "filename.c", directory: "/file/dir") !8 = !{!0} !9 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "decltype(nullptr)") !10 = distinct !DICompileUnit(language: DW_LANG_C99, file: !7, producer: "CloneModule", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, globals: !11) !11 = !{!12} !12 = !DIGlobalVariableExpression(var: !13) !13 = distinct !DIGlobalVariable(name: "gv", linkageName: "gv", scope: !14, file: !3, line: 1, type: !9, isLocal: false, isDefinition: true) !14 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !3, line: 4, type: !4, isLocal: true, isDefinition: true, scopeLine: 3, isOptimized: false, unit: !10, variables: !5) ``` Patched IR after clone: ``` @gv = global i32 1, comdat($comdat), !dbg !0, !type !5 define private void @f() comdat($comdat) personality void ()* @persfn !dbg !2 { !llvm.dbg.cu = !{!6} !0 = !DIGlobalVariableExpression(var: !1) !1 = distinct !DIGlobalVariable(name: "gv", linkageName: "gv", scope: !2, file: !3, line: 1, type: !9, isLocal: false, isDefinition: true) !2 = distinct !DISubprogram(name: "f", linkageName: "f", scope: null, file: !3, line: 4, type: !4, isLocal: true, isDefinition: true, scopeLine: 3, isOptimized: false, unit: !6, variables: !5) !3 = !DIFile(filename: "filename.c", directory: "/file/dir/") !4 = !DISubroutineType(types: !5) !5 = !{} !6 = distinct !DICompileUnit(language: DW_LANG_C99, file: !7, producer: "CloneModule", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !5, globals: !8) !7 = !DIFile(filename: "filename.c", directory: "/file/dir") !8 = !{!0} !9 = !DIBasicType(tag: DW_TAG_unspecified_type, name: "decltype(nullptr)") ``` Reviewers: aprantl, probinson, dblaikie, echristo, loladiro Reviewed By: aprantl Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D36082 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@309928 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/Transforms/Utils/CloneModule.cpp | 3 +- unittests/Transforms/Utils/Cloning.cpp | 59 ++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/lib/Transforms/Utils/CloneModule.cpp b/lib/Transforms/Utils/CloneModule.cpp index d27cb45c7d7..e5392b53050 100644 --- a/lib/Transforms/Utils/CloneModule.cpp +++ b/lib/Transforms/Utils/CloneModule.cpp @@ -132,7 +132,8 @@ std::unique_ptr llvm::CloneModule( SmallVector, 1> MDs; I->getAllMetadata(MDs); for (auto MD : MDs) - GV->addMetadata(MD.first, *MapMetadata(MD.second, VMap)); + GV->addMetadata(MD.first, + *MapMetadata(MD.second, VMap, RF_MoveDistinctMDs)); copyComdat(GV, &*I); } diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index 01ee9b841f8..fe4e2ba7e94 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -506,6 +506,19 @@ protected: DINode::FlagZero, false); F->setSubprogram(Subprogram); + // Create and assign DIGlobalVariableExpression to gv + auto GVExpression = DBuilder.createGlobalVariableExpression( + Subprogram, "gv", "gv", File, 1, DBuilder.createNullPtrType(), false); + GV->addDebugInfo(GVExpression); + + // DIGlobalVariableExpression not attached to any global variable + auto Expr = DBuilder.createExpression( + ArrayRef{dwarf::DW_OP_constu, 42U, dwarf::DW_OP_stack_value}); + + DBuilder.createGlobalVariableExpression( + Subprogram, "unattached", "unattached", File, 1, + DBuilder.createNullPtrType(), false, Expr); + auto *Entry = BasicBlock::Create(C, "", F); IBuilder.SetInsertPoint(Entry); IBuilder.CreateRetVoid(); @@ -545,6 +558,52 @@ TEST_F(CloneModule, GlobalMetadata) { EXPECT_NE(nullptr, NewGV->getMetadata(LLVMContext::MD_type)); } +TEST_F(CloneModule, GlobalDebugInfo) { + GlobalVariable *NewGV = NewM->getGlobalVariable("gv"); + EXPECT_TRUE(NewGV != nullptr); + + // Find debug info expression assigned to global + SmallVector GVs; + NewGV->getDebugInfo(GVs); + EXPECT_EQ(GVs.size(), 1U); + + DIGlobalVariableExpression *GVExpr = GVs[0]; + DIGlobalVariable *GV = GVExpr->getVariable(); + EXPECT_TRUE(GV != nullptr); + + EXPECT_EQ(GV->getName(), "gv"); + EXPECT_EQ(GV->getLine(), 1U); + + // Assert that the scope of the debug info attached to + // global variable matches the cloned function. + DISubprogram *SP = NewM->getFunction("f")->getSubprogram(); + EXPECT_TRUE(SP != nullptr); + EXPECT_EQ(GV->getScope(), SP); +} + +TEST_F(CloneModule, CompileUnit) { + // Find DICompileUnit listed in llvm.dbg.cu + auto *NMD = NewM->getNamedMetadata("llvm.dbg.cu"); + EXPECT_TRUE(NMD != nullptr); + EXPECT_EQ(NMD->getNumOperands(), 1U); + + DICompileUnit *CU = dyn_cast(NMD->getOperand(0)); + EXPECT_TRUE(CU != nullptr); + + // Assert this CU is consistent with the cloned function debug info + DISubprogram *SP = NewM->getFunction("f")->getSubprogram(); + EXPECT_TRUE(SP != nullptr); + EXPECT_EQ(SP->getUnit(), CU); + + // Check globals listed in CU have the correct scope + DIGlobalVariableExpressionArray GlobalArray = CU->getGlobalVariables(); + EXPECT_EQ(GlobalArray.size(), 2U); + for (DIGlobalVariableExpression *GVExpr : GlobalArray) { + DIGlobalVariable *GV = GVExpr->getVariable(); + EXPECT_EQ(GV->getScope(), SP); + } +} + TEST_F(CloneModule, Comdat) { GlobalVariable *NewGV = NewM->getGlobalVariable("gv"); auto *CD = NewGV->getComdat(); -- 2.40.0