diff --git a/llvm/include/llvm/Transforms/Utils/Cloning.h b/llvm/include/llvm/Transforms/Utils/Cloning.h --- a/llvm/include/llvm/Transforms/Utils/Cloning.h +++ b/llvm/include/llvm/Transforms/Utils/Cloning.h @@ -48,9 +48,13 @@ class ReturnInst; class DomTreeUpdater; +void CloneModuleInto(Module &M, Module &TargetMod); + /// Return an exact copy of the specified module -std::unique_ptr CloneModule(const Module &M); -std::unique_ptr CloneModule(const Module &M, ValueToValueMapTy &VMap); +std::unique_ptr CloneModule(const Module &M, + Module *TargetMod = nullptr); +std::unique_ptr CloneModule(const Module &M, ValueToValueMapTy &VMap, + Module *TargetMod = nullptr); /// Return a copy of the specified module. The ShouldCloneDefinition function /// controls whether a specific GlobalValue's definition is cloned. If the @@ -58,7 +62,8 @@ /// in place of the global definition. std::unique_ptr CloneModule(const Module &M, ValueToValueMapTy &VMap, - function_ref ShouldCloneDefinition); + function_ref ShouldCloneDefinition, + Module *TargetMod = nullptr); /// This struct can be used to capture information about code /// being cloned, while it is being cloned. diff --git a/llvm/lib/Transforms/Utils/CloneModule.cpp b/llvm/lib/Transforms/Utils/CloneModule.cpp --- a/llvm/lib/Transforms/Utils/CloneModule.cpp +++ b/llvm/lib/Transforms/Utils/CloneModule.cpp @@ -27,28 +27,44 @@ Dst->setComdat(DC); } +void llvm::CloneModuleInto(Module &M, Module &TargetMod) { + assert(&M.getContext() == &TargetMod.getContext() && "Context doesn't match."); + TargetMod.~Module(); + new (&TargetMod) Module(M.getModuleIdentifier(), M.getContext()); + std::unique_ptr T = CloneModule(M, &TargetMod); + T.release(); +} + /// This is not as easy as it might seem because we have to worry about making /// copies of global variables and functions, and making their (initializers and /// references, respectively) refer to the right globals. /// -std::unique_ptr llvm::CloneModule(const Module &M) { +std::unique_ptr llvm::CloneModule(const Module &M, + Module *TargetMod) { // Create the value map that maps things from the old module over to the new // module. ValueToValueMapTy VMap; - return CloneModule(M, VMap); + return CloneModule(M, VMap, TargetMod); } std::unique_ptr llvm::CloneModule(const Module &M, - ValueToValueMapTy &VMap) { - return CloneModule(M, VMap, [](const GlobalValue *GV) { return true; }); + ValueToValueMapTy &VMap, + Module *TargetMod) { + return CloneModule(M, VMap, [](const GlobalValue *GV) { return true; }, + TargetMod); } std::unique_ptr llvm::CloneModule( const Module &M, ValueToValueMapTy &VMap, - function_ref ShouldCloneDefinition) { + function_ref ShouldCloneDefinition, + Module *TargetMod) { // First off, we need to create the new module. - std::unique_ptr New = - llvm::make_unique(M.getModuleIdentifier(), M.getContext()); + std::unique_ptr New; + if(TargetMod) + New.reset(TargetMod); + else + New =llvm::make_unique(M.getModuleIdentifier(), M.getContext()); + New->setSourceFileName(M.getSourceFileName()); New->setDataLayout(M.getDataLayout()); New->setTargetTriple(M.getTargetTriple()); diff --git a/llvm/unittests/Transforms/Utils/CloningTest.cpp b/llvm/unittests/Transforms/Utils/CloningTest.cpp --- a/llvm/unittests/Transforms/Utils/CloningTest.cpp +++ b/llvm/unittests/Transforms/Utils/CloningTest.cpp @@ -638,6 +638,17 @@ Module *NewM; }; +TEST_F(CloneModule, CloneInto) { + Function *OldF = OldM->getFunction("f"); + OldF->replaceAllUsesWith(UndefValue::get(OldF->getType())); + OldF->eraseFromParent(); + Module *Tmp = NewM; + llvm::CloneModuleInto(*OldM, *NewM); + EXPECT_FALSE(NewM->getFunction("f")); + EXPECT_EQ(Tmp, NewM); + EXPECT_FALSE(verifyModule(*NewM)); +} + TEST_F(CloneModule, Verify) { EXPECT_FALSE(verifyModule(*NewM)); }