From 11adcc4de0797c83e61ae0240927f0bafcf041a9 Mon Sep 17 00:00:00 2001 From: Keno Fischer Date: Sat, 13 Feb 2016 02:04:29 +0000 Subject: [PATCH] [Cloning] Clone every Function's Debug Info Summary: Export the CloneDebugInfoMetadata utility, which clones all debug info associated with a function into the first module. Also use this function in CloneModule on each function we clone (the CloneFunction entrypoint already does this). Without this, cloning a module will lead to DI quality regressions, especially since r252219 reversed the Function <-> DISubprogram edge (before we could get lucky and have this edge preserved if the DISubprogram itself was, e.g. due to location metadata). This was verified to fix missing debug information in julia and a unittest to verify the new behavior is included. Patch by Yichao Yu! Thanks! Reviewers: loladiro, pcc Differential Revision: http://reviews.llvm.org/D17165 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@260791 91177308-0d34-0410-b5e6-96231b3b80d8 Alpine maintainer notes: - Corresponds to llvm-D17165-D18583.patch in Julia. --- include/llvm/Transforms/Utils/Cloning.h | 5 +++++ lib/Transforms/Utils/CloneFunction.cpp | 4 ++-- lib/Transforms/Utils/CloneModule.cpp | 1 + unittests/Transforms/Utils/Cloning.cpp | 25 +++++++++++++++++++++++++ 4 files changed, 33 insertions(+), 2 deletions(-) diff --git a/include/llvm/Transforms/Utils/Cloning.h b/include/llvm/Transforms/Utils/Cloning.h index 4f006f2..0bae2bd 100644 --- a/include/llvm/Transforms/Utils/Cloning.h +++ b/include/llvm/Transforms/Utils/Cloning.h @@ -130,6 +130,11 @@ Function *CloneFunction(const Function *F, ValueToValueMapTy &VMap, bool ModuleLevelChanges, ClonedCodeInfo *CodeInfo = nullptr); +/// Clone the module-level debug info associated with OldFunc. The cloned data +/// will point to NewFunc instead. +void CloneDebugInfoMetadata(Function *NewFunc, const Function *OldFunc, + ValueToValueMapTy &VMap); + /// Clone OldFunc into NewFunc, transforming the old arguments into references /// to VMap values. Note that if NewFunc already has basic blocks, the ones /// cloned into it will be added to the end of the function. This function diff --git a/lib/Transforms/Utils/CloneFunction.cpp b/lib/Transforms/Utils/CloneFunction.cpp index 6454afb..8b5692a 100644 --- a/lib/Transforms/Utils/CloneFunction.cpp +++ b/lib/Transforms/Utils/CloneFunction.cpp @@ -187,8 +187,8 @@ static void AddOperand(DICompileUnit *CU, DISubprogramArray SPs, // Clone the module-level debug info associated with OldFunc. The cloned data // will point to NewFunc instead. -static void CloneDebugInfoMetadata(Function *NewFunc, const Function *OldFunc, - ValueToValueMapTy &VMap) { +void llvm::CloneDebugInfoMetadata(Function *NewFunc, const Function *OldFunc, + ValueToValueMapTy &VMap) { DebugInfoFinder Finder; Finder.processModule(*OldFunc->getParent()); diff --git a/lib/Transforms/Utils/CloneModule.cpp b/lib/Transforms/Utils/CloneModule.cpp index 53de62a..b16a02a 100644 --- a/lib/Transforms/Utils/CloneModule.cpp +++ b/lib/Transforms/Utils/CloneModule.cpp @@ -136,6 +136,7 @@ std::unique_ptr llvm::CloneModule( VMap[&*J] = &*DestI++; } + CloneDebugInfoMetadata(F, &*I, VMap); SmallVector Returns; // Ignore returns cloned. CloneFunctionInto(F, &*I, VMap, /*ModuleLevelChanges=*/true, Returns); } diff --git a/unittests/Transforms/Utils/Cloning.cpp b/unittests/Transforms/Utils/Cloning.cpp index 25e322e..b761e4e 100644 --- a/unittests/Transforms/Utils/Cloning.cpp +++ b/unittests/Transforms/Utils/Cloning.cpp @@ -423,6 +423,7 @@ class CloneModule : public ::testing::Test { void SetupModule() { OldM = new Module("", C); } void CreateOldModule() { + DIBuilder DBuilder(*OldM); IRBuilder<> IBuilder(C); auto *FuncType = FunctionType::get(Type::getVoidTy(C), false); @@ -431,9 +432,25 @@ class CloneModule : public ::testing::Test { auto *F = Function::Create(FuncType, GlobalValue::PrivateLinkage, "f", OldM); F->setPersonalityFn(PersFn); + + // Create debug info + auto *File = DBuilder.createFile("filename.c", "/file/dir/"); + DITypeRefArray ParamTypes = DBuilder.getOrCreateTypeArray(None); + DISubroutineType *DFuncType = DBuilder.createSubroutineType(ParamTypes); + auto *CU = + DBuilder.createCompileUnit(dwarf::DW_LANG_C99, "filename.c", + "/file/dir", "CloneModule", false, "", 0); + // Function DI + auto *Subprogram = DBuilder.createFunction(CU, "f", "f", File, 4, DFuncType, + true, true, 3, 0, false); + F->setSubprogram(Subprogram); + auto *Entry = BasicBlock::Create(C, "", F); IBuilder.SetInsertPoint(Entry); IBuilder.CreateRetVoid(); + + // Finalize the debug info + DBuilder.finalize(); } void CreateNewModule() { NewM = llvm::CloneModule(OldM).release(); } @@ -447,4 +464,12 @@ TEST_F(CloneModule, Verify) { EXPECT_FALSE(verifyModule(*NewM)); } +TEST_F(CloneModule, Subprogram) { + Function *NewF = NewM->getFunction("f"); + DISubprogram *SP = NewF->getSubprogram(); + EXPECT_TRUE(SP != nullptr); + EXPECT_EQ(SP->getName(), "f"); + EXPECT_EQ(SP->getFile()->getFilename(), "filename.c"); + EXPECT_EQ(SP->getLine(), (unsigned)4); +} }