/// Load the combined index from disk, then load every file referenced by /// the index and add them to the generator, then performs the promotion and /// cross module importing on the files mentioned on the command line /// (these must match the index content). void import() { if (InputFilenames.size() != 1 && !OutputFilename.empty()) report_fatal_error("Can't handle a single output filename and multiple " "input files, do not provide an output filename and " "the output files will be suffixed from the input " "ones."); auto Index = loadCombinedIndex(); auto InputBuffers = loadAllFilesForIndex(*Index); for (auto &MemBuffer : InputBuffers) ThinGenerator.addModule(MemBuffer->getBufferIdentifier(), MemBuffer->getBuffer()); for (auto &Filename : InputFilenames) { LLVMContext Ctx; auto TheModule = loadModule(Filename, Ctx); ThinGenerator.crossModuleImport(*TheModule, *Index); std::string OutputName = OutputFilename; if (OutputName.empty()) { OutputName = Filename + ".thinlto.imported.bc"; } writeModuleToFile(*TheModule, OutputName); } }
/// Full ThinLTO process void runAll() { if (!OutputFilename.empty()) report_fatal_error("Do not provide an output filename for ThinLTO " " processing, the output files will be suffixed from " "the input ones."); if (!ThinLTOIndex.empty()) errs() << "Warning: -thinlto-index ignored for full ThinLTO process"; LLVMContext Ctx; std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers; for (unsigned i = 0; i < InputFilenames.size(); ++i) { auto &Filename = InputFilenames[i]; StringRef CurrentActivity = "loading file '" + Filename + "'"; auto InputOrErr = MemoryBuffer::getFile(Filename); error(InputOrErr, "error " + CurrentActivity); InputBuffers.push_back(std::move(*InputOrErr)); ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer()); } ThinGenerator.run(); auto &Binaries = ThinGenerator.getProducedBinaries(); if (Binaries.size() != InputFilenames.size()) report_fatal_error("Number of output objects does not match the number " "of inputs"); for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) { auto OutputName = InputFilenames[BufID] + ".thinlto.o"; std::error_code EC; raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None); error(EC, "error opening the file '" + OutputName + "'"); OS << Binaries[BufID]->getBuffer(); } }
/// Load the input files, create the combined index, and write it out. void thinLink() { // Perform "ThinLink": just produce the index if (OutputFilename.empty()) report_fatal_error( "OutputFilename is necessary to store the combined index.\n"); LLVMContext Ctx; std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers; for (unsigned i = 0; i < InputFilenames.size(); ++i) { auto &Filename = InputFilenames[i]; StringRef CurrentActivity = "loading file '" + Filename + "'"; auto InputOrErr = MemoryBuffer::getFile(Filename); error(InputOrErr, "error " + CurrentActivity); InputBuffers.push_back(std::move(*InputOrErr)); ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer()); } auto CombinedIndex = ThinGenerator.linkCombinedIndex(); std::error_code EC; raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::F_None); error(EC, "error opening the file '" + OutputFilename + "'"); WriteFunctionSummaryToFile(*CombinedIndex, OS); return; }