| From 11adcc4de0797c83e61ae0240927f0bafcf041a9 Mon Sep 17 00:00:00 2001 |
| From: Keno Fischer <kfischer@college.harvard.edu> |
| 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 |
| |
| |
| @@ -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 |
| |
| |
| @@ -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 |
| |
| |
| @@ -136,6 +136,7 @@ std::unique_ptr<Module> llvm::CloneModule( |
| VMap[&*J] = &*DestI++; |
| } |
| |
| + CloneDebugInfoMetadata(F, &*I, VMap); |
| SmallVector<ReturnInst*, 8> 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 |
| |
| |
| @@ -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); |
| +} |
| } |