summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorArtur Pilipenko <apilipenko@azulsystems.com>2019-08-28 21:27:50 +0000
committerArtur Pilipenko <apilipenko@azulsystems.com>2019-08-28 21:27:50 +0000
commit925afc1ce70ab4117073d52bf519ea7cf05ed03f (patch)
tree5348ad743af4bfb73cf552a001eb3c13dcdabcd1
parent5970076466cf9722b7b5bd08f50e6479c352baf3 (diff)
downloadbcm5719-llvm-925afc1ce70ab4117073d52bf519ea7cf05ed03f.tar.gz
bcm5719-llvm-925afc1ce70ab4117073d52bf519ea7cf05ed03f.zip
Fix for "DICompileUnit not listed in llvm.dbg.cu" verification error after ...
...cloning a function from a different module Currently when a function with debug info is cloned from a different module, the cloned function may have hanging DICompileUnits, so that the module with the cloned function fails debug info verification. The proposed fix inserts all DICompileUnits reachable from the cloned function to "llvm.dbg.cu" metadata operands of the cloned function module. Reviewed By: aprantl, efriedma Differential Revision: https://reviews.llvm.org/D66510 Patch by Oleg Pliss (Oleg.Pliss@azul.com) llvm-svn: 370265
-rw-r--r--llvm/lib/Transforms/Utils/CloneFunction.cpp15
-rw-r--r--llvm/lib/Transforms/Utils/CloneModule.cpp16
-rw-r--r--llvm/unittests/Transforms/Utils/CloningTest.cpp56
3 files changed, 85 insertions, 2 deletions
diff --git a/llvm/lib/Transforms/Utils/CloneFunction.cpp b/llvm/lib/Transforms/Utils/CloneFunction.cpp
index 1026c9d3703..75e8963303c 100644
--- a/llvm/lib/Transforms/Utils/CloneFunction.cpp
+++ b/llvm/lib/Transforms/Utils/CloneFunction.cpp
@@ -210,6 +210,21 @@ void llvm::CloneFunctionInto(Function *NewFunc, const Function *OldFunc,
RemapInstruction(&II, VMap,
ModuleLevelChanges ? RF_None : RF_NoModuleLevelChanges,
TypeMapper, Materializer);
+
+ // Register all DICompileUnits of the old parent module in the new parent module
+ auto* OldModule = OldFunc->getParent();
+ auto* NewModule = NewFunc->getParent();
+ if (OldModule && NewModule && OldModule != NewModule && DIFinder.compile_unit_count()) {
+ auto* NMD = NewModule->getOrInsertNamedMetadata("llvm.dbg.cu");
+ // Avoid multiple insertions of the same DICompileUnit to NMD.
+ SmallPtrSet<const void*, 8> Visited;
+ for (auto* Operand : NMD->operands())
+ Visited.insert(Operand);
+ for (auto* Unit : DIFinder.compile_units())
+ // VMap.MD()[Unit] == Unit
+ if (Visited.insert(Unit).second)
+ NMD->addOperand(Unit);
+ }
}
/// Return a copy of the specified function and add it to that function's
diff --git a/llvm/lib/Transforms/Utils/CloneModule.cpp b/llvm/lib/Transforms/Utils/CloneModule.cpp
index 71e39e9f56f..2c8c3abb292 100644
--- a/llvm/lib/Transforms/Utils/CloneModule.cpp
+++ b/llvm/lib/Transforms/Utils/CloneModule.cpp
@@ -181,13 +181,25 @@ std::unique_ptr<Module> llvm::CloneModule(
}
// And named metadata....
+ const auto* LLVM_DBG_CU = M.getNamedMetadata("llvm.dbg.cu");
for (Module::const_named_metadata_iterator I = M.named_metadata_begin(),
E = M.named_metadata_end();
I != E; ++I) {
const NamedMDNode &NMD = *I;
NamedMDNode *NewNMD = New->getOrInsertNamedMetadata(NMD.getName());
- for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i)
- NewNMD->addOperand(MapMetadata(NMD.getOperand(i), VMap));
+ if (&NMD == LLVM_DBG_CU) {
+ // Do not insert duplicate operands.
+ SmallPtrSet<const void*, 8> Visited;
+ for (const auto* Operand : NewNMD->operands())
+ Visited.insert(Operand);
+ for (const auto* Operand : NMD.operands()) {
+ auto* MappedOperand = MapMetadata(Operand, VMap);
+ if (Visited.insert(MappedOperand).second)
+ NewNMD->addOperand(MappedOperand);
+ }
+ } else
+ for (unsigned i = 0, e = NMD.getNumOperands(); i != e; ++i)
+ NewNMD->addOperand(MapMetadata(NMD.getOperand(i), VMap));
}
return New;
diff --git a/llvm/unittests/Transforms/Utils/CloningTest.cpp b/llvm/unittests/Transforms/Utils/CloningTest.cpp
index 514a7708f9f..3d0bd10e87a 100644
--- a/llvm/unittests/Transforms/Utils/CloningTest.cpp
+++ b/llvm/unittests/Transforms/Utils/CloningTest.cpp
@@ -652,6 +652,62 @@ TEST_F(CloneFunc, DebugIntrinsics) {
}
}
+static int GetDICompileUnitCount(const Module& M) {
+ if (const auto* LLVM_DBG_CU = M.getNamedMetadata("llvm.dbg.cu")) {
+ return LLVM_DBG_CU->getNumOperands();
+ }
+ return 0;
+}
+
+TEST(CloneFunction, CloneFunctionToDifferentModule) {
+ StringRef ImplAssembly = R"(
+ define void @foo() {
+ ret void, !dbg !5
+ }
+
+ !llvm.module.flags = !{!0}
+ !llvm.dbg.cu = !{!2, !6}
+ !0 = !{i32 1, !"Debug Info Version", i32 3}
+ !1 = distinct !DISubprogram(unit: !2)
+ !2 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3)
+ !3 = !DIFile(filename: "foo.c", directory: "/tmp")
+ !4 = distinct !DISubprogram(unit: !2)
+ !5 = !DILocation(line: 4, scope: !1)
+ !6 = distinct !DICompileUnit(language: DW_LANG_C99, file: !3)
+ )";
+ StringRef DeclAssembly = R"(
+ declare void @foo()
+ )";
+
+ LLVMContext Context;
+ SMDiagnostic Error;
+
+ auto ImplModule = parseAssemblyString(ImplAssembly, Error, Context);
+ EXPECT_TRUE(ImplModule != nullptr);
+ // DICompileUnits: !2, !6. Only !2 is reachable from @foo().
+ EXPECT_TRUE(GetDICompileUnitCount(*ImplModule) == 2);
+ auto* ImplFunction = ImplModule->getFunction("foo");
+ EXPECT_TRUE(ImplFunction != nullptr);
+
+ auto DeclModule = parseAssemblyString(DeclAssembly, Error, Context);
+ EXPECT_TRUE(DeclModule != nullptr);
+ // No DICompileUnits defined here.
+ EXPECT_TRUE(GetDICompileUnitCount(*DeclModule) == 0);
+ auto* DeclFunction = DeclModule->getFunction("foo");
+ EXPECT_TRUE(DeclFunction != nullptr);
+
+ ValueToValueMapTy VMap;
+ VMap[ImplFunction] = DeclFunction;
+ // No args to map
+ SmallVector<ReturnInst*, 8> Returns;
+ CloneFunctionInto(DeclFunction, ImplFunction, VMap, true, Returns);
+
+ EXPECT_FALSE(verifyModule(*ImplModule, &errs()));
+ EXPECT_FALSE(verifyModule(*DeclModule, &errs()));
+ // DICompileUnit !2 shall be inserted into DeclModule.
+ EXPECT_TRUE(GetDICompileUnitCount(*DeclModule) == 1);
+}
+
class CloneModule : public ::testing::Test {
protected:
void SetUp() override {
OpenPOWER on IntegriCloud