Index: include/llvm-c/lto.h =================================================================== --- include/llvm-c/lto.h +++ include/llvm-c/lto.h @@ -374,8 +374,10 @@ lto_codegen_add_module(lto_code_gen_t cg, lto_module_t mod); /** - * Sets the object module for code generation. This will transfer the ownship of - * the module to code generator. + * Sets the object module for code generation. This will transfer the ownership + * of the module to the code generator. In a future version of the API this call + * will destroy the module, so clients should not attempt to use it after + * passing it to this function. * * \c cg and \c mod must both be in the same context. * Index: include/llvm/LTO/LTOCodeGenerator.h =================================================================== --- include/llvm/LTO/LTOCodeGenerator.h +++ include/llvm/LTO/LTOCodeGenerator.h @@ -69,7 +69,11 @@ bool addModule(struct LTOModule *); // Set the destination module. - void setModule(struct LTOModule *); + // + // The ReleaseModule parameter controls whether LTOCodeGenerator releases + // ownership of the LTOModule. This parameter is needed to preserve API + // compatibility in libLTO. Do not pass true here outside of libLTO. + void setModule(std::unique_ptr M, bool ReleaseModule = false); void setTargetOptions(TargetOptions options); void setDebugInfo(lto_debug_model); @@ -155,9 +159,9 @@ typedef StringMap StringSet; - void destroyMergedModule(); std::unique_ptr OwnedContext; LLVMContext &Context; + std::unique_ptr OwnedModule; Linker IRLinker; std::unique_ptr TargetMach; bool EmitDwarfDebugInfo = false; @@ -173,7 +177,6 @@ unsigned OptLevel = 2; lto_diagnostic_handler_t DiagHandler = nullptr; void *DiagContext = nullptr; - LTOModule *OwnedModule = nullptr; bool ShouldInternalize = true; bool ShouldEmbedUselists = false; }; Index: include/llvm/LTO/LTOModule.h =================================================================== --- include/llvm/LTO/LTOModule.h +++ include/llvm/LTO/LTOModule.h @@ -113,6 +113,8 @@ return IRFile->getModule(); } + std::unique_ptr takeModule() { return IRFile->takeModule(); } + /// Return the Module's target triple. const std::string &getTargetTriple() { return getModule().getTargetTriple(); Index: lib/LTO/LTOCodeGenerator.cpp =================================================================== --- lib/LTO/LTOCodeGenerator.cpp +++ lib/LTO/LTOCodeGenerator.cpp @@ -64,29 +64,20 @@ } LTOCodeGenerator::LTOCodeGenerator() - : Context(getGlobalContext()), IRLinker(new Module("ld-temp.o", Context)) { + : Context(getGlobalContext()), + OwnedModule(new Module("ld-temp.o", Context)), + IRLinker(OwnedModule.get()) { initializeLTOPasses(); } LTOCodeGenerator::LTOCodeGenerator(std::unique_ptr Context) : OwnedContext(std::move(Context)), Context(*OwnedContext), - IRLinker(new Module("ld-temp.o", *OwnedContext)) { + OwnedModule(new Module("ld-temp.o", *OwnedContext)), + IRLinker(OwnedModule.get()) { initializeLTOPasses(); } -void LTOCodeGenerator::destroyMergedModule() { - if (OwnedModule) { - assert(IRLinker.getModule() == &OwnedModule->getModule() && - "The linker's module should be the same as the owned module"); - delete OwnedModule; - OwnedModule = nullptr; - } else if (IRLinker.getModule()) - IRLinker.deleteModule(); -} - -LTOCodeGenerator::~LTOCodeGenerator() { - destroyMergedModule(); -} +LTOCodeGenerator::~LTOCodeGenerator() {} // Initialize LTO passes. Please keep this funciton in sync with // PassManagerBuilder::populateLTOPassManager(), and make sure all LTO @@ -131,20 +122,22 @@ return !ret; } -void LTOCodeGenerator::setModule(LTOModule *Mod) { +void LTOCodeGenerator::setModule(std::unique_ptr Mod, + bool ReleaseModule) { assert(&Mod->getModule().getContext() == &Context && "Expected module in same context"); - // Delete the old merged module. - destroyMergedModule(); AsmUndefinedRefs.clear(); - OwnedModule = Mod; - IRLinker.setModule(&Mod->getModule()); + OwnedModule = Mod->takeModule(); + IRLinker.setModule(OwnedModule.get()); const std::vector &Undefs = Mod->getAsmUndefinedRefs(); for (int I = 0, E = Undefs.size(); I != E; ++I) AsmUndefinedRefs[Undefs[I]] = 1; + + if (ReleaseModule) + Mod.release(); } void LTOCodeGenerator::setTargetOptions(TargetOptions options) { @@ -543,8 +536,6 @@ if (!this->determineTarget(errMsg)) return false; - Module *mergedModule = IRLinker.getModule(); - legacy::PassManager codeGenPasses; // If the bitcode files contain ARC code and were compiled with optimization, @@ -557,8 +548,8 @@ return false; } - // Run the code generator, and write assembly file - codeGenPasses.run(*mergedModule); + // Run the code generator, and write object file + codeGenPasses.run(*OwnedModule); return true; } Index: tools/llvm-lto/llvm-lto.cpp =================================================================== --- tools/llvm-lto/llvm-lto.cpp +++ tools/llvm-lto/llvm-lto.cpp @@ -222,7 +222,7 @@ // SetMergedModule is true. if (SetMergedModule && i == BaseArg) { // Transfer ownership to the code generator. - CodeGen.setModule(Module.release()); + CodeGen.setModule(std::move(Module)); } else if (!CodeGen.addModule(Module.get())) return 1; } Index: tools/lto/lto.cpp =================================================================== --- tools/lto/lto.cpp +++ tools/lto/lto.cpp @@ -75,15 +75,16 @@ namespace { -// This derived class owns the native object file. This helps implement the -// libLTO API semantics, which require that the code generator owns the object -// file. +// This derived class owns the native object file and the LTO module passed to +// lto_codegen_set_module. This helps implement the libLTO API semantics, which +// require that the code generator owns these objects. struct LibLTOCodeGenerator : LTOCodeGenerator { LibLTOCodeGenerator() {} LibLTOCodeGenerator(std::unique_ptr Context) : LTOCodeGenerator(std::move(Context)) {} std::unique_ptr NativeObjectFile; + std::unique_ptr LTOMod; }; } @@ -260,7 +261,11 @@ } void lto_codegen_set_module(lto_code_gen_t cg, lto_module_t mod) { - unwrap(cg)->setModule(unwrap(mod)); + LibLTOCodeGenerator *CG = unwrap(cg); + LTOModule *Mod = unwrap(mod); + CG->setModule(std::unique_ptr(unwrap(mod)), + /*ReleaseModule=*/true); + CG->LTOMod.reset(Mod); } bool lto_codegen_set_debug_model(lto_code_gen_t cg, lto_debug_model debug) {