xref: /freebsd/contrib/llvm-project/lld/ELF/LTO.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
10b57cec5SDimitry Andric //===- LTO.cpp ------------------------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "LTO.h"
100b57cec5SDimitry Andric #include "Config.h"
110b57cec5SDimitry Andric #include "InputFiles.h"
120b57cec5SDimitry Andric #include "SymbolTable.h"
130b57cec5SDimitry Andric #include "Symbols.h"
140b57cec5SDimitry Andric #include "lld/Common/Args.h"
15*7a6dacacSDimitry Andric #include "lld/Common/CommonLinkerContext.h"
160b57cec5SDimitry Andric #include "lld/Common/ErrorHandler.h"
175f757f3fSDimitry Andric #include "lld/Common/Filesystem.h"
1881ad6265SDimitry Andric #include "lld/Common/Strings.h"
190b57cec5SDimitry Andric #include "lld/Common/TargetOptionsCommandFlags.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
210b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
220b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
230b57cec5SDimitry Andric #include "llvm/BinaryFormat/ELF.h"
240b57cec5SDimitry Andric #include "llvm/Bitcode/BitcodeWriter.h"
250b57cec5SDimitry Andric #include "llvm/LTO/Config.h"
260b57cec5SDimitry Andric #include "llvm/LTO/LTO.h"
27349cc55cSDimitry Andric #include "llvm/Support/Caching.h"
280b57cec5SDimitry Andric #include "llvm/Support/CodeGen.h"
290b57cec5SDimitry Andric #include "llvm/Support/Error.h"
300b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
310b57cec5SDimitry Andric #include "llvm/Support/MemoryBuffer.h"
32*7a6dacacSDimitry Andric #include "llvm/Support/Path.h"
330b57cec5SDimitry Andric #include <algorithm>
340b57cec5SDimitry Andric #include <cstddef>
350b57cec5SDimitry Andric #include <memory>
360b57cec5SDimitry Andric #include <string>
370b57cec5SDimitry Andric #include <system_error>
380b57cec5SDimitry Andric #include <vector>
390b57cec5SDimitry Andric 
400b57cec5SDimitry Andric using namespace llvm;
410b57cec5SDimitry Andric using namespace llvm::object;
420b57cec5SDimitry Andric using namespace llvm::ELF;
435ffd83dbSDimitry Andric using namespace lld;
445ffd83dbSDimitry Andric using namespace lld::elf;
450b57cec5SDimitry Andric 
460b57cec5SDimitry Andric static std::string getThinLTOOutputFile(StringRef modulePath) {
4706c3fb27SDimitry Andric   return lto::getThinLTOOutputFile(modulePath, config->thinLTOPrefixReplaceOld,
4806c3fb27SDimitry Andric                                    config->thinLTOPrefixReplaceNew);
490b57cec5SDimitry Andric }
500b57cec5SDimitry Andric 
510b57cec5SDimitry Andric static lto::Config createConfig() {
520b57cec5SDimitry Andric   lto::Config c;
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric   // LLD supports the new relocations and address-significance tables.
550b57cec5SDimitry Andric   c.Options = initTargetOptionsFromCodeGenFlags();
560b57cec5SDimitry Andric   c.Options.EmitAddrsig = true;
57bdd1243dSDimitry Andric   for (StringRef C : config->mllvmOpts)
58bdd1243dSDimitry Andric     c.MllvmArgs.emplace_back(C.str());
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric   // Always emit a section per function/datum with LTO.
610b57cec5SDimitry Andric   c.Options.FunctionSections = true;
620b57cec5SDimitry Andric   c.Options.DataSections = true;
630b57cec5SDimitry Andric 
645ffd83dbSDimitry Andric   // Check if basic block sections must be used.
65e8d8bef9SDimitry Andric   // Allowed values for --lto-basic-block-sections are "all", "labels",
665ffd83dbSDimitry Andric   // "<file name specifying basic block ids>", or none.  This is the equivalent
675ffd83dbSDimitry Andric   // of -fbasic-block-sections= flag in clang.
685ffd83dbSDimitry Andric   if (!config->ltoBasicBlockSections.empty()) {
695ffd83dbSDimitry Andric     if (config->ltoBasicBlockSections == "all") {
705ffd83dbSDimitry Andric       c.Options.BBSections = BasicBlockSection::All;
715ffd83dbSDimitry Andric     } else if (config->ltoBasicBlockSections == "labels") {
725ffd83dbSDimitry Andric       c.Options.BBSections = BasicBlockSection::Labels;
735ffd83dbSDimitry Andric     } else if (config->ltoBasicBlockSections == "none") {
745ffd83dbSDimitry Andric       c.Options.BBSections = BasicBlockSection::None;
755ffd83dbSDimitry Andric     } else {
765ffd83dbSDimitry Andric       ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
775ffd83dbSDimitry Andric           MemoryBuffer::getFile(config->ltoBasicBlockSections.str());
785ffd83dbSDimitry Andric       if (!MBOrErr) {
795ffd83dbSDimitry Andric         error("cannot open " + config->ltoBasicBlockSections + ":" +
805ffd83dbSDimitry Andric               MBOrErr.getError().message());
815ffd83dbSDimitry Andric       } else {
825ffd83dbSDimitry Andric         c.Options.BBSectionsFuncListBuf = std::move(*MBOrErr);
835ffd83dbSDimitry Andric       }
845ffd83dbSDimitry Andric       c.Options.BBSections = BasicBlockSection::List;
855ffd83dbSDimitry Andric     }
865ffd83dbSDimitry Andric   }
875ffd83dbSDimitry Andric 
885ffd83dbSDimitry Andric   c.Options.UniqueBasicBlockSectionNames =
895ffd83dbSDimitry Andric       config->ltoUniqueBasicBlockSectionNames;
905ffd83dbSDimitry Andric 
9185868e8aSDimitry Andric   if (auto relocModel = getRelocModelFromCMModel())
9285868e8aSDimitry Andric     c.RelocModel = *relocModel;
9385868e8aSDimitry Andric   else if (config->relocatable)
94bdd1243dSDimitry Andric     c.RelocModel = std::nullopt;
950b57cec5SDimitry Andric   else if (config->isPic)
960b57cec5SDimitry Andric     c.RelocModel = Reloc::PIC_;
970b57cec5SDimitry Andric   else
980b57cec5SDimitry Andric     c.RelocModel = Reloc::Static;
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   c.CodeModel = getCodeModelFromCMModel();
1010b57cec5SDimitry Andric   c.DisableVerify = config->disableVerify;
1020b57cec5SDimitry Andric   c.DiagHandler = diagnosticHandler;
1030b57cec5SDimitry Andric   c.OptLevel = config->ltoo;
1040b57cec5SDimitry Andric   c.CPU = getCPUStr();
1050b57cec5SDimitry Andric   c.MAttrs = getMAttrs();
10606c3fb27SDimitry Andric   c.CGOptLevel = config->ltoCgo;
1070b57cec5SDimitry Andric 
108480093f4SDimitry Andric   c.PTO.LoopVectorization = c.OptLevel > 1;
109480093f4SDimitry Andric   c.PTO.SLPVectorization = c.OptLevel > 1;
110480093f4SDimitry Andric 
1110b57cec5SDimitry Andric   // Set up a custom pipeline if we've been asked to.
1125ffd83dbSDimitry Andric   c.OptPipeline = std::string(config->ltoNewPmPasses);
1135ffd83dbSDimitry Andric   c.AAPipeline = std::string(config->ltoAAPipeline);
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   // Set up optimization remarks if we've been asked to.
1165ffd83dbSDimitry Andric   c.RemarksFilename = std::string(config->optRemarksFilename);
1175ffd83dbSDimitry Andric   c.RemarksPasses = std::string(config->optRemarksPasses);
1180b57cec5SDimitry Andric   c.RemarksWithHotness = config->optRemarksWithHotness;
119e8d8bef9SDimitry Andric   c.RemarksHotnessThreshold = config->optRemarksHotnessThreshold;
1205ffd83dbSDimitry Andric   c.RemarksFormat = std::string(config->optRemarksFormat);
1210b57cec5SDimitry Andric 
12281ad6265SDimitry Andric   // Set up output file to emit statistics.
12381ad6265SDimitry Andric   c.StatsFile = std::string(config->optStatsFilename);
12481ad6265SDimitry Andric 
1255ffd83dbSDimitry Andric   c.SampleProfile = std::string(config->ltoSampleProfile);
12681ad6265SDimitry Andric   for (StringRef pluginFn : config->passPlugins)
12781ad6265SDimitry Andric     c.PassPlugins.push_back(std::string(pluginFn));
1280b57cec5SDimitry Andric   c.DebugPassManager = config->ltoDebugPassManager;
1295ffd83dbSDimitry Andric   c.DwoDir = std::string(config->dwoDir);
1300b57cec5SDimitry Andric 
1315ffd83dbSDimitry Andric   c.HasWholeProgramVisibility = config->ltoWholeProgramVisibility;
1325f757f3fSDimitry Andric   c.ValidateAllVtablesHaveTypeInfos =
1335f757f3fSDimitry Andric       config->ltoValidateAllVtablesHaveTypeInfos;
1345f757f3fSDimitry Andric   c.AllVtablesHaveTypeInfos = ctx.ltoAllVtablesHaveTypeInfos;
1355ffd83dbSDimitry Andric   c.AlwaysEmitRegularLTOObj = !config->ltoObjPath.empty();
1365ffd83dbSDimitry Andric 
1375ffd83dbSDimitry Andric   for (const llvm::StringRef &name : config->thinLTOModulesToCompile)
1385ffd83dbSDimitry Andric     c.ThinLTOModulesToCompile.emplace_back(name);
1395ffd83dbSDimitry Andric 
1405ffd83dbSDimitry Andric   c.TimeTraceEnabled = config->timeTraceEnabled;
1415ffd83dbSDimitry Andric   c.TimeTraceGranularity = config->timeTraceGranularity;
1425ffd83dbSDimitry Andric 
1435ffd83dbSDimitry Andric   c.CSIRProfile = std::string(config->ltoCSProfileFile);
1440b57cec5SDimitry Andric   c.RunCSIRInstr = config->ltoCSProfileGenerate;
145349cc55cSDimitry Andric   c.PGOWarnMismatch = config->ltoPGOWarnMismatch;
1460b57cec5SDimitry Andric 
1470b57cec5SDimitry Andric   if (config->emitLLVM) {
1480b57cec5SDimitry Andric     c.PostInternalizeModuleHook = [](size_t task, const Module &m) {
149e8d8bef9SDimitry Andric       if (std::unique_ptr<raw_fd_ostream> os =
150e8d8bef9SDimitry Andric               openLTOOutputFile(config->outputFile))
1510b57cec5SDimitry Andric         WriteBitcodeToFile(m, *os, false);
1520b57cec5SDimitry Andric       return false;
1530b57cec5SDimitry Andric     };
1540b57cec5SDimitry Andric   }
1550b57cec5SDimitry Andric 
156bdd1243dSDimitry Andric   if (config->ltoEmitAsm) {
1575f757f3fSDimitry Andric     c.CGFileType = CodeGenFileType::AssemblyFile;
158bdd1243dSDimitry Andric     c.Options.MCOptions.AsmVerbose = true;
159bdd1243dSDimitry Andric   }
1605ffd83dbSDimitry Andric 
161753f127fSDimitry Andric   if (!config->saveTempsArgs.empty())
1620b57cec5SDimitry Andric     checkError(c.addSaveTemps(config->outputFile.str() + ".",
163753f127fSDimitry Andric                               /*UseInputModulePath*/ true,
164753f127fSDimitry Andric                               config->saveTempsArgs));
1650b57cec5SDimitry Andric   return c;
1660b57cec5SDimitry Andric }
1670b57cec5SDimitry Andric 
1680b57cec5SDimitry Andric BitcodeCompiler::BitcodeCompiler() {
1690b57cec5SDimitry Andric   // Initialize indexFile.
1700b57cec5SDimitry Andric   if (!config->thinLTOIndexOnlyArg.empty())
1710b57cec5SDimitry Andric     indexFile = openFile(config->thinLTOIndexOnlyArg);
1720b57cec5SDimitry Andric 
1730b57cec5SDimitry Andric   // Initialize ltoObj.
1740b57cec5SDimitry Andric   lto::ThinBackend backend;
1750b57cec5SDimitry Andric   auto onIndexWrite = [&](StringRef s) { thinIndices.erase(s); };
17681ad6265SDimitry Andric   if (config->thinLTOIndexOnly) {
1770b57cec5SDimitry Andric     backend = lto::createWriteIndexesThinBackend(
17806c3fb27SDimitry Andric         std::string(config->thinLTOPrefixReplaceOld),
17906c3fb27SDimitry Andric         std::string(config->thinLTOPrefixReplaceNew),
18006c3fb27SDimitry Andric         std::string(config->thinLTOPrefixReplaceNativeObject),
1810b57cec5SDimitry Andric         config->thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite);
1825ffd83dbSDimitry Andric   } else {
1835ffd83dbSDimitry Andric     backend = lto::createInProcessThinBackend(
18481ad6265SDimitry Andric         llvm::heavyweight_hardware_concurrency(config->thinLTOJobs),
18581ad6265SDimitry Andric         onIndexWrite, config->thinLTOEmitIndexFiles,
18681ad6265SDimitry Andric         config->thinLTOEmitImportsFiles);
1870b57cec5SDimitry Andric   }
1880b57cec5SDimitry Andric 
18906c3fb27SDimitry Andric   constexpr llvm::lto::LTO::LTOKind ltoModes[3] =
19006c3fb27SDimitry Andric     {llvm::lto::LTO::LTOKind::LTOK_UnifiedThin,
19106c3fb27SDimitry Andric      llvm::lto::LTO::LTOKind::LTOK_UnifiedRegular,
19206c3fb27SDimitry Andric      llvm::lto::LTO::LTOKind::LTOK_Default};
19306c3fb27SDimitry Andric   ltoObj = std::make_unique<lto::LTO>(
19406c3fb27SDimitry Andric       createConfig(), backend, config->ltoPartitions,
19506c3fb27SDimitry Andric       ltoModes[config->ltoKind]);
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   // Initialize usedStartStop.
198bdd1243dSDimitry Andric   if (ctx.bitcodeFiles.empty())
1990eae32dcSDimitry Andric     return;
200bdd1243dSDimitry Andric   for (Symbol *sym : symtab.getSymbols()) {
20104eeddc0SDimitry Andric     if (sym->isPlaceholder())
20204eeddc0SDimitry Andric       continue;
2030b57cec5SDimitry Andric     StringRef s = sym->getName();
2040b57cec5SDimitry Andric     for (StringRef prefix : {"__start_", "__stop_"})
20506c3fb27SDimitry Andric       if (s.starts_with(prefix))
2060b57cec5SDimitry Andric         usedStartStop.insert(s.substr(prefix.size()));
207480093f4SDimitry Andric   }
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
2100b57cec5SDimitry Andric BitcodeCompiler::~BitcodeCompiler() = default;
2110b57cec5SDimitry Andric 
2120b57cec5SDimitry Andric void BitcodeCompiler::add(BitcodeFile &f) {
2130b57cec5SDimitry Andric   lto::InputFile &obj = *f.obj;
2140b57cec5SDimitry Andric   bool isExec = !config->shared && !config->relocatable;
2150b57cec5SDimitry Andric 
21681ad6265SDimitry Andric   if (config->thinLTOEmitIndexFiles)
2170b57cec5SDimitry Andric     thinIndices.insert(obj.getName());
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric   ArrayRef<Symbol *> syms = f.getSymbols();
2200b57cec5SDimitry Andric   ArrayRef<lto::InputFile::Symbol> objSyms = obj.symbols();
2210b57cec5SDimitry Andric   std::vector<lto::SymbolResolution> resols(syms.size());
2220b57cec5SDimitry Andric 
2230b57cec5SDimitry Andric   // Provide a resolution to the LTO API for each symbol.
2240b57cec5SDimitry Andric   for (size_t i = 0, e = syms.size(); i != e; ++i) {
2250b57cec5SDimitry Andric     Symbol *sym = syms[i];
2260b57cec5SDimitry Andric     const lto::InputFile::Symbol &objSym = objSyms[i];
2270b57cec5SDimitry Andric     lto::SymbolResolution &r = resols[i];
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric     // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
2300b57cec5SDimitry Andric     // reports two symbols for module ASM defined. Without this check, lld
2310b57cec5SDimitry Andric     // flags an undefined in IR with a definition in ASM as prevailing.
2320b57cec5SDimitry Andric     // Once IRObjectFile is fixed to report only one symbol this hack can
2330b57cec5SDimitry Andric     // be removed.
2340b57cec5SDimitry Andric     r.Prevailing = !objSym.isUndefined() && sym->file == &f;
2350b57cec5SDimitry Andric 
2360b57cec5SDimitry Andric     // We ask LTO to preserve following global symbols:
2370b57cec5SDimitry Andric     // 1) All symbols when doing relocatable link, so that them can be used
2380b57cec5SDimitry Andric     //    for doing final link.
2390b57cec5SDimitry Andric     // 2) Symbols that are used in regular objects.
2400b57cec5SDimitry Andric     // 3) C named sections if we have corresponding __start_/__stop_ symbol.
24181ad6265SDimitry Andric     // 4) Symbols that are defined in bitcode files and used for dynamic
24281ad6265SDimitry Andric     //    linking.
24381ad6265SDimitry Andric     // 5) Symbols that will be referenced after linker wrapping is performed.
2440b57cec5SDimitry Andric     r.VisibleToRegularObj = config->relocatable || sym->isUsedInRegularObj ||
24581ad6265SDimitry Andric                             sym->referencedAfterWrap ||
2460b57cec5SDimitry Andric                             (r.Prevailing && sym->includeInDynsym()) ||
2470b57cec5SDimitry Andric                             usedStartStop.count(objSym.getSectionName());
248fe6060f1SDimitry Andric     // Identify symbols exported dynamically, and that therefore could be
249fe6060f1SDimitry Andric     // referenced by a shared library not visible to the linker.
25081ad6265SDimitry Andric     r.ExportDynamic =
25181ad6265SDimitry Andric         sym->computeBinding() != STB_LOCAL &&
25281ad6265SDimitry Andric         (config->exportDynamic || sym->exportDynamic || sym->inDynamicList);
2530b57cec5SDimitry Andric     const auto *dr = dyn_cast<Defined>(sym);
2540b57cec5SDimitry Andric     r.FinalDefinitionInLinkageUnit =
255bdd1243dSDimitry Andric         (isExec || sym->visibility() != STV_DEFAULT) && dr &&
2560b57cec5SDimitry Andric         // Skip absolute symbols from ELF objects, otherwise PC-rel relocations
2570b57cec5SDimitry Andric         // will be generated by for them, triggering linker errors.
2580b57cec5SDimitry Andric         // Symbol section is always null for bitcode symbols, hence the check
2590b57cec5SDimitry Andric         // for isElf(). Skip linker script defined symbols as well: they have
2600b57cec5SDimitry Andric         // no File defined.
261*7a6dacacSDimitry Andric         !(dr->section == nullptr &&
262*7a6dacacSDimitry Andric           (sym->file->isInternal() || sym->file->isElf()));
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric     if (r.Prevailing)
265*7a6dacacSDimitry Andric       Undefined(ctx.internalFile, StringRef(), STB_GLOBAL, STV_DEFAULT,
266*7a6dacacSDimitry Andric                 sym->type)
267bdd1243dSDimitry Andric           .overwrite(*sym);
2680b57cec5SDimitry Andric 
2690b57cec5SDimitry Andric     // We tell LTO to not apply interprocedural optimization for wrapped
2700b57cec5SDimitry Andric     // (with --wrap) symbols because otherwise LTO would inline them while
2710b57cec5SDimitry Andric     // their values are still not final.
27281ad6265SDimitry Andric     r.LinkerRedefined = sym->scriptDefined;
2730b57cec5SDimitry Andric   }
2740b57cec5SDimitry Andric   checkError(ltoObj->add(std::move(f.obj), resols));
2750b57cec5SDimitry Andric }
2760b57cec5SDimitry Andric 
2770b57cec5SDimitry Andric // If LazyObjFile has not been added to link, emit empty index files.
2780b57cec5SDimitry Andric // This is needed because this is what GNU gold plugin does and we have a
2790b57cec5SDimitry Andric // distributed build system that depends on that behavior.
2800b57cec5SDimitry Andric static void thinLTOCreateEmptyIndexFiles() {
281bdd1243dSDimitry Andric   DenseSet<StringRef> linkedBitCodeFiles;
282bdd1243dSDimitry Andric   for (BitcodeFile *f : ctx.bitcodeFiles)
283bdd1243dSDimitry Andric     linkedBitCodeFiles.insert(f->getName());
284bdd1243dSDimitry Andric 
285bdd1243dSDimitry Andric   for (BitcodeFile *f : ctx.lazyBitcodeFiles) {
2860eae32dcSDimitry Andric     if (!f->lazy)
2870b57cec5SDimitry Andric       continue;
288bdd1243dSDimitry Andric     if (linkedBitCodeFiles.contains(f->getName()))
289bdd1243dSDimitry Andric       continue;
290bdd1243dSDimitry Andric     std::string path =
291bdd1243dSDimitry Andric         replaceThinLTOSuffix(getThinLTOOutputFile(f->obj->getName()));
2920b57cec5SDimitry Andric     std::unique_ptr<raw_fd_ostream> os = openFile(path + ".thinlto.bc");
2930b57cec5SDimitry Andric     if (!os)
2940b57cec5SDimitry Andric       continue;
2950b57cec5SDimitry Andric 
2960b57cec5SDimitry Andric     ModuleSummaryIndex m(/*HaveGVs*/ false);
2970b57cec5SDimitry Andric     m.setSkipModuleByDistributedBackend();
2981fd87a68SDimitry Andric     writeIndexToFile(m, *os);
2990b57cec5SDimitry Andric     if (config->thinLTOEmitImportsFiles)
3000b57cec5SDimitry Andric       openFile(path + ".imports");
3010b57cec5SDimitry Andric   }
3020b57cec5SDimitry Andric }
3030b57cec5SDimitry Andric 
3040b57cec5SDimitry Andric // Merge all the bitcode files we have seen, codegen the result
3050b57cec5SDimitry Andric // and return the resulting ObjectFile(s).
3060b57cec5SDimitry Andric std::vector<InputFile *> BitcodeCompiler::compile() {
3070b57cec5SDimitry Andric   unsigned maxTasks = ltoObj->getMaxTasks();
3080b57cec5SDimitry Andric   buf.resize(maxTasks);
3090b57cec5SDimitry Andric   files.resize(maxTasks);
310*7a6dacacSDimitry Andric   filenames.resize(maxTasks);
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   // The --thinlto-cache-dir option specifies the path to a directory in which
3130b57cec5SDimitry Andric   // to cache native object files for ThinLTO incremental builds. If a path was
3140b57cec5SDimitry Andric   // specified, configure LTO to use it as the cache directory.
315349cc55cSDimitry Andric   FileCache cache;
3160b57cec5SDimitry Andric   if (!config->thinLTOCacheDir.empty())
317bdd1243dSDimitry Andric     cache = check(localCache("ThinLTO", "Thin", config->thinLTOCacheDir,
318bdd1243dSDimitry Andric                              [&](size_t task, const Twine &moduleName,
319bdd1243dSDimitry Andric                                  std::unique_ptr<MemoryBuffer> mb) {
3200b57cec5SDimitry Andric                                files[task] = std::move(mb);
321*7a6dacacSDimitry Andric                                filenames[task] = moduleName.str();
3220b57cec5SDimitry Andric                              }));
3230b57cec5SDimitry Andric 
324bdd1243dSDimitry Andric   if (!ctx.bitcodeFiles.empty())
3250b57cec5SDimitry Andric     checkError(ltoObj->run(
326bdd1243dSDimitry Andric         [&](size_t task, const Twine &moduleName) {
327*7a6dacacSDimitry Andric           buf[task].first = moduleName.str();
328349cc55cSDimitry Andric           return std::make_unique<CachedFileStream>(
329*7a6dacacSDimitry Andric               std::make_unique<raw_svector_ostream>(buf[task].second));
3300b57cec5SDimitry Andric         },
3310b57cec5SDimitry Andric         cache));
3320b57cec5SDimitry Andric 
3335ffd83dbSDimitry Andric   // Emit empty index files for non-indexed files but not in single-module mode.
3345ffd83dbSDimitry Andric   if (config->thinLTOModulesToCompile.empty()) {
3350b57cec5SDimitry Andric     for (StringRef s : thinIndices) {
3360b57cec5SDimitry Andric       std::string path = getThinLTOOutputFile(s);
3370b57cec5SDimitry Andric       openFile(path + ".thinlto.bc");
3380b57cec5SDimitry Andric       if (config->thinLTOEmitImportsFiles)
3390b57cec5SDimitry Andric         openFile(path + ".imports");
3400b57cec5SDimitry Andric     }
3415ffd83dbSDimitry Andric   }
3420b57cec5SDimitry Andric 
34381ad6265SDimitry Andric   if (config->thinLTOEmitIndexFiles)
3440b57cec5SDimitry Andric     thinLTOCreateEmptyIndexFiles();
3450b57cec5SDimitry Andric 
34681ad6265SDimitry Andric   if (config->thinLTOIndexOnly) {
3470b57cec5SDimitry Andric     if (!config->ltoObjPath.empty())
348*7a6dacacSDimitry Andric       saveBuffer(buf[0].second, config->ltoObjPath);
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric     // ThinLTO with index only option is required to generate only the index
3510b57cec5SDimitry Andric     // files. After that, we exit from linker and ThinLTO backend runs in a
3520b57cec5SDimitry Andric     // distributed environment.
3530b57cec5SDimitry Andric     if (indexFile)
3540b57cec5SDimitry Andric       indexFile->close();
3550b57cec5SDimitry Andric     return {};
3560b57cec5SDimitry Andric   }
3570b57cec5SDimitry Andric 
3580b57cec5SDimitry Andric   if (!config->thinLTOCacheDir.empty())
359bdd1243dSDimitry Andric     pruneCache(config->thinLTOCacheDir, config->thinLTOCachePolicy, files);
3600b57cec5SDimitry Andric 
3610b57cec5SDimitry Andric   if (!config->ltoObjPath.empty()) {
362*7a6dacacSDimitry Andric     saveBuffer(buf[0].second, config->ltoObjPath);
3630b57cec5SDimitry Andric     for (unsigned i = 1; i != maxTasks; ++i)
364*7a6dacacSDimitry Andric       saveBuffer(buf[i].second, config->ltoObjPath + Twine(i));
3650b57cec5SDimitry Andric   }
3660b57cec5SDimitry Andric 
367*7a6dacacSDimitry Andric   bool savePrelink = config->saveTempsArgs.contains("prelink");
3680b57cec5SDimitry Andric   std::vector<InputFile *> ret;
369*7a6dacacSDimitry Andric   const char *ext = config->ltoEmitAsm ? ".s" : ".o";
370*7a6dacacSDimitry Andric   for (unsigned i = 0; i != maxTasks; ++i) {
371*7a6dacacSDimitry Andric     StringRef bitcodeFilePath;
372*7a6dacacSDimitry Andric     StringRef objBuf;
373*7a6dacacSDimitry Andric     if (files[i]) {
374*7a6dacacSDimitry Andric       // When files[i] is not null, we get the native relocatable file from the
375*7a6dacacSDimitry Andric       // cache. filenames[i] contains the original BitcodeFile's identifier.
376*7a6dacacSDimitry Andric       objBuf = files[i]->getBuffer();
377*7a6dacacSDimitry Andric       bitcodeFilePath = filenames[i];
378*7a6dacacSDimitry Andric     } else {
379*7a6dacacSDimitry Andric       // Get the native relocatable file after in-process LTO compilation.
380*7a6dacacSDimitry Andric       objBuf = buf[i].second;
381*7a6dacacSDimitry Andric       bitcodeFilePath = buf[i].first;
382*7a6dacacSDimitry Andric     }
383*7a6dacacSDimitry Andric     if (objBuf.empty())
384*7a6dacacSDimitry Andric       continue;
3850b57cec5SDimitry Andric 
386*7a6dacacSDimitry Andric     // If the input bitcode file is path/to/x.o and -o specifies a.out, the
387*7a6dacacSDimitry Andric     // corresponding native relocatable file path will look like:
388*7a6dacacSDimitry Andric     // path/to/a.out.lto.x.o.
389*7a6dacacSDimitry Andric     StringRef ltoObjName;
390*7a6dacacSDimitry Andric     if (bitcodeFilePath == "ld-temp.o") {
391*7a6dacacSDimitry Andric       ltoObjName =
392*7a6dacacSDimitry Andric           saver().save(Twine(config->outputFile) + ".lto" +
393*7a6dacacSDimitry Andric                        (i == 0 ? Twine("") : Twine('.') + Twine(i)) + ext);
394*7a6dacacSDimitry Andric     } else {
395*7a6dacacSDimitry Andric       StringRef directory = sys::path::parent_path(bitcodeFilePath);
396*7a6dacacSDimitry Andric       // For an archive member, which has an identifier like "d/a.a(coll.o at
397*7a6dacacSDimitry Andric       // 8)" (see BitcodeFile::BitcodeFile), use the filename; otherwise, use
398*7a6dacacSDimitry Andric       // the stem (d/a.o => a).
399*7a6dacacSDimitry Andric       StringRef baseName = bitcodeFilePath.ends_with(")")
400*7a6dacacSDimitry Andric                                ? sys::path::filename(bitcodeFilePath)
401*7a6dacacSDimitry Andric                                : sys::path::stem(bitcodeFilePath);
402*7a6dacacSDimitry Andric       StringRef outputFileBaseName = sys::path::filename(config->outputFile);
403*7a6dacacSDimitry Andric       SmallString<256> path;
404*7a6dacacSDimitry Andric       sys::path::append(path, directory,
405*7a6dacacSDimitry Andric                         outputFileBaseName + ".lto." + baseName + ext);
406*7a6dacacSDimitry Andric       sys::path::remove_dots(path, true);
407*7a6dacacSDimitry Andric       ltoObjName = saver().save(path.str());
408*7a6dacacSDimitry Andric     }
409*7a6dacacSDimitry Andric     if (savePrelink || config->ltoEmitAsm)
410*7a6dacacSDimitry Andric       saveBuffer(buf[i].second, ltoObjName);
411*7a6dacacSDimitry Andric     if (!config->ltoEmitAsm)
412*7a6dacacSDimitry Andric       ret.push_back(createObjFile(MemoryBufferRef(objBuf, ltoObjName)));
413*7a6dacacSDimitry Andric   }
4140b57cec5SDimitry Andric   return ret;
4150b57cec5SDimitry Andric }
416