Index: include/llvm/Transforms/Utils/Cloning.h =================================================================== --- include/llvm/Transforms/Utils/Cloning.h +++ include/llvm/Transforms/Utils/Cloning.h @@ -130,6 +130,11 @@ 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 Index: lib/Transforms/Utils/CloneFunction.cpp =================================================================== --- lib/Transforms/Utils/CloneFunction.cpp +++ lib/Transforms/Utils/CloneFunction.cpp @@ -187,8 +187,8 @@ // 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()); Index: lib/Transforms/Utils/CloneModule.cpp =================================================================== --- lib/Transforms/Utils/CloneModule.cpp +++ lib/Transforms/Utils/CloneModule.cpp @@ -136,6 +136,7 @@ VMap[&*J] = &*DestI++; } + CloneDebugInfoMetadata(F, &*I, VMap); SmallVector Returns; // Ignore returns cloned. CloneFunctionInto(F, &*I, VMap, /*ModuleLevelChanges=*/true, Returns); } Index: unittests/Transforms/Utils/Cloning.cpp =================================================================== --- unittests/Transforms/Utils/Cloning.cpp +++ unittests/Transforms/Utils/Cloning.cpp @@ -423,6 +423,7 @@ 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,26 @@ 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 +465,9 @@ EXPECT_FALSE(verifyModule(*NewM)); } +TEST_F(CloneModule, Subprogram) { + Function *NewF = NewM->getFunction("f"); + EXPECT_TRUE(NewF->getSubprogram() != nullptr); +} + }