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