/// Create a combined index file from the input IR files and write it. /// /// This is meant to enable testing of ThinLTO combined index generation, /// currently available via the gold plugin via -thinlto. static int createCombinedFunctionIndex(StringRef Command) { LLVMContext Context; FunctionInfoIndex CombinedIndex; uint64_t NextModuleId = 0; for (auto &Filename : InputFilenames) { std::string Error; std::unique_ptr<FunctionInfoIndex> Index = getFunctionIndexForFile(Filename, Error, Context); if (!Index) { errs() << Command << ": error loading file '" << Filename << "': " << Error << "\n"; return 1; } CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId); } std::error_code EC; assert(!OutputFilename.empty()); raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC, sys::fs::OpenFlags::F_None); if (EC) { errs() << Command << ": error opening the file '" << OutputFilename << ".thinlto.bc': " << EC.message() << "\n"; return 1; } WriteFunctionSummaryToFile(CombinedIndex, OS); OS.close(); return 0; }
/// Create a combined index file from the input IR files and write it. /// /// This is meant to enable testing of ThinLTO combined index generation, /// currently available via the gold plugin via -thinlto. static int createCombinedFunctionIndex(StringRef Command) { FunctionInfoIndex CombinedIndex; uint64_t NextModuleId = 0; for (auto &Filename : InputFilenames) { ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr = getFunctionIndexForFile(Filename, diagnosticHandler); if (std::error_code EC = IndexOrErr.getError()) { std::string Error = EC.message(); errs() << Command << ": error loading file '" << Filename << "': " << Error << "\n"; return 1; } std::unique_ptr<FunctionInfoIndex> Index = std::move(IndexOrErr.get()); // Skip files without a function summary. if (!Index) continue; CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId); } std::error_code EC; assert(!OutputFilename.empty()); raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC, sys::fs::OpenFlags::F_None); if (EC) { errs() << Command << ": error opening the file '" << OutputFilename << ".thinlto.bc': " << EC.message() << "\n"; return 1; } WriteFunctionSummaryToFile(CombinedIndex, OS); OS.close(); return 0; }
/// Create a combined index file from the input IR files and write it. /// /// This is meant to enable testing of ThinLTO combined index generation, /// currently available via the gold plugin via -thinlto. static void createCombinedFunctionIndex() { FunctionInfoIndex CombinedIndex; uint64_t NextModuleId = 0; for (auto &Filename : InputFilenames) { CurrentActivity = "loading file '" + Filename + "'"; ErrorOr<std::unique_ptr<FunctionInfoIndex>> IndexOrErr = llvm::getFunctionIndexForFile(Filename, diagnosticHandler); std::unique_ptr<FunctionInfoIndex> Index = std::move(IndexOrErr.get()); CurrentActivity = ""; // Skip files without a function summary. if (!Index) continue; CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId); } std::error_code EC; assert(!OutputFilename.empty()); raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC, sys::fs::OpenFlags::F_None); error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'"); WriteFunctionSummaryToFile(CombinedIndex, OS); OS.close(); }
/// gold informs us that all symbols have been read. At this point, we use /// get_symbols to see if any of our definitions have been overridden by a /// native object file. Then, perform optimization and codegen. static ld_plugin_status allSymbolsReadHook(raw_fd_ostream *ApiFile) { if (Modules.empty()) return LDPS_OK; LLVMContext Context; Context.setDiagnosticHandler(diagnosticHandlerForContext, nullptr, true); // If we are doing ThinLTO compilation, simply build the combined // function index/summary and emit it. We don't need to parse the modules // and link them in this case. if (options::thinlto) { FunctionInfoIndex CombinedIndex; uint64_t NextModuleId = 0; for (claimed_file &F : Modules) { ld_plugin_input_file File; if (get_input_file(F.handle, &File) != LDPS_OK) message(LDPL_FATAL, "Failed to get file information"); std::unique_ptr<FunctionInfoIndex> Index = getFunctionIndexForFile(F, File); // Skip files without a function summary. if (!Index) continue; CombinedIndex.mergeFrom(std::move(Index), ++NextModuleId); } std::error_code EC; raw_fd_ostream OS(output_name + ".thinlto.bc", EC, sys::fs::OpenFlags::F_None); if (EC) message(LDPL_FATAL, "Unable to open %s.thinlto.bc for writing: %s", output_name.data(), EC.message().c_str()); WriteFunctionSummaryToFile(CombinedIndex, OS); OS.close(); cleanup_hook(); exit(0); } std::unique_ptr<Module> Combined(new Module("ld-temp.o", Context)); Linker L(Combined.get()); std::string DefaultTriple = sys::getDefaultTargetTriple(); StringSet<> Internalize; StringSet<> Maybe; for (claimed_file &F : Modules) { ld_plugin_input_file File; if (get_input_file(F.handle, &File) != LDPS_OK) message(LDPL_FATAL, "Failed to get file information"); std::unique_ptr<Module> M = getModuleForFile(Context, F, File, ApiFile, Internalize, Maybe); if (!options::triple.empty()) M->setTargetTriple(options::triple.c_str()); else if (M->getTargetTriple().empty()) { M->setTargetTriple(DefaultTriple); } if (L.linkInModule(M.get())) message(LDPL_FATAL, "Failed to link module"); if (release_input_file(F.handle) != LDPS_OK) message(LDPL_FATAL, "Failed to release file information"); } for (const auto &Name : Internalize) { GlobalValue *GV = Combined->getNamedValue(Name.first()); if (GV) internalize(*GV); } for (const auto &Name : Maybe) { GlobalValue *GV = Combined->getNamedValue(Name.first()); if (!GV) continue; GV->setLinkage(GlobalValue::LinkOnceODRLinkage); if (canBeOmittedFromSymbolTable(GV)) internalize(*GV); } if (options::TheOutputType == options::OT_DISABLE) return LDPS_OK; if (options::TheOutputType != options::OT_NORMAL) { std::string path; if (options::TheOutputType == options::OT_BC_ONLY) path = output_name; else path = output_name + ".bc"; saveBCFile(path, *L.getModule()); if (options::TheOutputType == options::OT_BC_ONLY) return LDPS_OK; } codegen(std::move(Combined)); if (!options::extra_library_path.empty() && set_extra_library_path(options::extra_library_path.c_str()) != LDPS_OK) message(LDPL_FATAL, "Unable to set the extra library path."); return LDPS_OK; }