blob: 195526bf390d2c8a662de3898eea6384f3db5ddf [file] [log] [blame]
Rui Ueyama25992482016-03-22 20:52:101//===- LTO.cpp ------------------------------------------------------------===//
2//
Chandler Carruth2946cd72019-01-19 08:50:563// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
Rui Ueyama25992482016-03-22 20:52:106//
7//===----------------------------------------------------------------------===//
8
9#include "LTO.h"
10#include "Config.h"
Rui Ueyama25992482016-03-22 20:52:1011#include "InputFiles.h"
Rafael Espindola4b075bb2017-07-26 23:39:1012#include "SymbolTable.h"
Rui Ueyama25992482016-03-22 20:52:1013#include "Symbols.h"
Sam Clegg5cdc91d2019-01-30 20:46:1814#include "lld/Common/Args.h"
Fangrui Songf7669ba2024-01-23 19:38:1515#include "lld/Common/CommonLinkerContext.h"
Bob Haarmanb8a59c82017-10-25 22:28:3816#include "lld/Common/ErrorHandler.h"
Matheus Izvekov8ff77a82023-09-27 22:06:4817#include "lld/Common/Filesystem.h"
Fangrui Song27bb7992022-02-08 05:53:3418#include "lld/Common/Strings.h"
Rui Ueyama3f851702017-10-02 21:00:4119#include "lld/Common/TargetOptionsCommandFlags.h"
Rui Ueyama8c6a5aa2016-11-05 22:37:5920#include "llvm/ADT/SmallString.h"
Eugene Zelenko22886a22016-11-05 01:00:5621#include "llvm/ADT/StringRef.h"
22#include "llvm/ADT/Twine.h"
Zachary Turner264b5d92017-06-07 03:48:5623#include "llvm/BinaryFormat/ELF.h"
Rumeet Dhindsad366e362018-05-02 21:40:0724#include "llvm/Bitcode/BitcodeWriter.h"
Eugene Zelenko22886a22016-11-05 01:00:5625#include "llvm/LTO/Config.h"
Davide Italiano786d8e32016-09-29 00:40:0826#include "llvm/LTO/LTO.h"
Noah Shuttye678c512021-10-19 01:40:5727#include "llvm/Support/Caching.h"
Eugene Zelenko22886a22016-11-05 01:00:5628#include "llvm/Support/CodeGen.h"
Eugene Zelenko22886a22016-11-05 01:00:5629#include "llvm/Support/Error.h"
30#include "llvm/Support/FileSystem.h"
31#include "llvm/Support/MemoryBuffer.h"
Fangrui Songf7669ba2024-01-23 19:38:1532#include "llvm/Support/Path.h"
Eugene Zelenko22886a22016-11-05 01:00:5633#include <algorithm>
34#include <cstddef>
35#include <memory>
36#include <string>
37#include <system_error>
38#include <vector>
Rui Ueyama25992482016-03-22 20:52:1039
40using namespace llvm;
41using namespace llvm::object;
42using namespace llvm::ELF;
Fangrui Song07837b82020-05-15 05:18:5843using namespace lld;
44using namespace lld::elf;
Rui Ueyama25992482016-03-22 20:52:1045
Fangrui Song6b56a272024-09-21 17:11:3746static std::string getThinLTOOutputFile(Ctx &ctx, StringRef modulePath) {
47 return lto::getThinLTOOutputFile(modulePath, ctx.arg.thinLTOPrefixReplaceOld,
48 ctx.arg.thinLTOPrefixReplaceNew);
Rui Ueyamad54f1c22018-05-07 22:11:2449}
50
Fangrui Song6b56a272024-09-21 17:11:3751static lto::Config createConfig(Ctx &ctx) {
Rui Ueyama3837f422019-07-10 05:00:3752 lto::Config c;
Davide Italianod26c4a12016-05-15 19:29:3853
Peter Collingbourne82a7f142018-08-06 20:12:1254 // LLD supports the new relocations and address-significance tables.
Rui Ueyama3837f422019-07-10 05:00:3755 c.Options = initTargetOptionsFromCodeGenFlags();
Rui Ueyama3837f422019-07-10 05:00:3756 c.Options.EmitAddrsig = true;
Fangrui Song6b56a272024-09-21 17:11:3757 for (StringRef C : ctx.arg.mllvmOpts)
Mircea Trofinc625c172022-09-16 04:01:5658 c.MllvmArgs.emplace_back(C.str());
Davide Italianodf24d5b2016-06-02 22:58:1159
Davide Italiano957f1202017-07-24 20:15:0760 // Always emit a section per function/datum with LTO.
Rui Ueyama3837f422019-07-10 05:00:3761 c.Options.FunctionSections = true;
62 c.Options.DataSections = true;
Davide Italiano1f4e29c2017-07-24 19:38:1363
Sriraman Tallam94317872020-04-07 13:48:1864 // Check if basic block sections must be used.
Rahman Lavaee1f17c2d2024-10-07 16:22:3665 // Allowed values for --lto-basic-block-sections are "all",
Sriraman Tallam94317872020-04-07 13:48:1866 // "<file name specifying basic block ids>", or none. This is the equivalent
Sriraman Tallame0bca462020-06-02 06:17:2967 // of -fbasic-block-sections= flag in clang.
Fangrui Song6b56a272024-09-21 17:11:3768 if (!ctx.arg.ltoBasicBlockSections.empty()) {
69 if (ctx.arg.ltoBasicBlockSections == "all") {
Sriraman Tallam94317872020-04-07 13:48:1870 c.Options.BBSections = BasicBlockSection::All;
Fangrui Song6b56a272024-09-21 17:11:3771 } else if (ctx.arg.ltoBasicBlockSections == "labels") {
Rahman Lavaee7b7747d2024-09-26 05:03:1072 c.Options.BBAddrMap = true;
Fangrui Songf8bae3a2024-11-07 06:19:3173 Warn(ctx)
74 << "'--lto-basic-block-sections=labels' is deprecated; Please use "
75 "'--lto-basic-block-address-map' instead";
Fangrui Song6b56a272024-09-21 17:11:3776 } else if (ctx.arg.ltoBasicBlockSections == "none") {
Sriraman Tallam94317872020-04-07 13:48:1877 c.Options.BBSections = BasicBlockSection::None;
78 } else {
79 ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
Fangrui Song6b56a272024-09-21 17:11:3780 MemoryBuffer::getFile(ctx.arg.ltoBasicBlockSections.str());
Sriraman Tallam94317872020-04-07 13:48:1881 if (!MBOrErr) {
Fangrui Song09c2c5e2024-11-07 06:04:5282 ErrAlways(ctx) << "cannot open " << ctx.arg.ltoBasicBlockSections << ":"
83 << MBOrErr.getError().message();
Sriraman Tallam94317872020-04-07 13:48:1884 } else {
85 c.Options.BBSectionsFuncListBuf = std::move(*MBOrErr);
86 }
87 c.Options.BBSections = BasicBlockSection::List;
88 }
89 }
90
Rahman Lavaee7b7747d2024-09-26 05:03:1091 c.Options.BBAddrMap = ctx.arg.ltoBBAddrMap;
92
Sriraman Tallame0bca462020-06-02 06:17:2993 c.Options.UniqueBasicBlockSectionNames =
Fangrui Song6b56a272024-09-21 17:11:3794 ctx.arg.ltoUniqueBasicBlockSectionNames;
Sriraman Tallam94317872020-04-07 13:48:1895
Petr Hosekae4c30a2019-07-20 21:59:4796 if (auto relocModel = getRelocModelFromCMModel())
97 c.RelocModel = *relocModel;
Fangrui Song6b56a272024-09-21 17:11:3798 else if (ctx.arg.relocatable)
Kazu Hiratac68af422022-12-03 07:12:3699 c.RelocModel = std::nullopt;
Fangrui Song6b56a272024-09-21 17:11:37100 else if (ctx.arg.isPic)
Rui Ueyama3837f422019-07-10 05:00:37101 c.RelocModel = Reloc::PIC_;
Evgeniy Stepanovf12ac5b2017-05-22 21:11:44102 else
Rui Ueyama3837f422019-07-10 05:00:37103 c.RelocModel = Reloc::Static;
Rui Ueyama397dffd2018-05-07 23:24:07104
Rui Ueyama3837f422019-07-10 05:00:37105 c.CodeModel = getCodeModelFromCMModel();
Fangrui Song6b56a272024-09-21 17:11:37106 c.DisableVerify = ctx.arg.disableVerify;
Rui Ueyama3837f422019-07-10 05:00:37107 c.DiagHandler = diagnosticHandler;
Fangrui Song6b56a272024-09-21 17:11:37108 c.OptLevel = ctx.arg.ltoo;
Rui Ueyama3837f422019-07-10 05:00:37109 c.CPU = getCPUStr();
110 c.MAttrs = getMAttrs();
Fangrui Song6b56a272024-09-21 17:11:37111 c.CGOptLevel = ctx.arg.ltoCgo;
Davide Italianodf24d5b2016-06-02 22:58:11112
Wei Mi21a47102020-01-10 04:58:31113 c.PTO.LoopVectorization = c.OptLevel > 1;
114 c.PTO.SLPVectorization = c.OptLevel > 1;
115
Davide Italiano786d8e32016-09-29 00:40:08116 // Set up a custom pipeline if we've been asked to.
Fangrui Song6b56a272024-09-21 17:11:37117 c.OptPipeline = std::string(ctx.arg.ltoNewPmPasses);
118 c.AAPipeline = std::string(ctx.arg.ltoAAPipeline);
Rui Ueyama25992482016-03-22 20:52:10119
Davide Italianodb4b0a72017-02-13 17:49:18120 // Set up optimization remarks if we've been asked to.
Fangrui Song6b56a272024-09-21 17:11:37121 c.RemarksFilename = std::string(ctx.arg.optRemarksFilename);
122 c.RemarksPasses = std::string(ctx.arg.optRemarksPasses);
123 c.RemarksWithHotness = ctx.arg.optRemarksWithHotness;
124 c.RemarksHotnessThreshold = ctx.arg.optRemarksHotnessThreshold;
125 c.RemarksFormat = std::string(ctx.arg.optRemarksFormat);
Rui Ueyama397dffd2018-05-07 23:24:07126
wangliushuai1c04b522022-03-17 03:53:44127 // Set up output file to emit statistics.
Fangrui Song6b56a272024-09-21 17:11:37128 c.StatsFile = std::string(ctx.arg.optStatsFilename);
wangliushuai1c04b522022-03-17 03:53:44129
Fangrui Song6b56a272024-09-21 17:11:37130 c.SampleProfile = std::string(ctx.arg.ltoSampleProfile);
131 for (StringRef pluginFn : ctx.arg.passPlugins)
Jakob Koschel0c861982022-03-24 06:52:16132 c.PassPlugins.push_back(std::string(pluginFn));
Fangrui Song6b56a272024-09-21 17:11:37133 c.DebugPassManager = ctx.arg.ltoDebugPassManager;
134 c.DwoDir = std::string(ctx.arg.dwoDir);
Davide Italianodb4b0a72017-02-13 17:49:18135
Fangrui Song6b56a272024-09-21 17:11:37136 c.HasWholeProgramVisibility = ctx.arg.ltoWholeProgramVisibility;
modimo272bd6f2023-07-14 02:02:52137 c.ValidateAllVtablesHaveTypeInfos =
Fangrui Song6b56a272024-09-21 17:11:37138 ctx.arg.ltoValidateAllVtablesHaveTypeInfos;
modimo272bd6f2023-07-14 02:02:52139 c.AllVtablesHaveTypeInfos = ctx.ltoAllVtablesHaveTypeInfos;
Fangrui Song6b56a272024-09-21 17:11:37140 c.AlwaysEmitRegularLTOObj = !ctx.arg.ltoObjPath.empty();
Mingming Liu09b231c2024-09-09 18:16:58141 c.KeepSymbolNameCopies = false;
Teresa Johnson2f63d542020-01-24 20:24:18142
Fangrui Song6b56a272024-09-21 17:11:37143 for (const llvm::StringRef &name : ctx.arg.thinLTOModulesToCompile)
Hongtao Yu2638aaf2020-05-21 20:19:44144 c.ThinLTOModulesToCompile.emplace_back(name);
145
Fangrui Song6b56a272024-09-21 17:11:37146 c.TimeTraceEnabled = ctx.arg.timeTraceEnabled;
147 c.TimeTraceGranularity = ctx.arg.timeTraceGranularity;
Russell Gallope7cb3742020-01-28 16:05:13148
Fangrui Song6b56a272024-09-21 17:11:37149 c.CSIRProfile = std::string(ctx.arg.ltoCSProfileFile);
150 c.RunCSIRInstr = ctx.arg.ltoCSProfileGenerate;
151 c.PGOWarnMismatch = ctx.arg.ltoPGOWarnMismatch;
Rong Xuf92e59c2019-03-11 22:51:38152
Fangrui Song6b56a272024-09-21 17:11:37153 if (ctx.arg.emitLLVM) {
154 c.PreCodeGenModuleHook = [&ctx](size_t task, const Module &m) {
Jianzhou Zhao11201312020-09-12 19:35:17155 if (std::unique_ptr<raw_fd_ostream> os =
Fangrui Song6b56a272024-09-21 17:11:37156 openLTOOutputFile(ctx.arg.outputFile))
Rui Ueyama3837f422019-07-10 05:00:37157 WriteBitcodeToFile(m, *os, false);
Rui Ueyama9f499902018-12-14 21:58:49158 return false;
159 };
160 }
161
Fangrui Song6b56a272024-09-21 17:11:37162 if (ctx.arg.ltoEmitAsm) {
Arthur Eubanks0a1aa6c2023-09-14 21:10:14163 c.CGFileType = CodeGenFileType::AssemblyFile;
Pierre van Houtryve6aff41e2023-01-09 10:33:38164 c.Options.MCOptions.AsmVerbose = true;
165 }
Hongtao Yu964ef8e2020-04-01 17:01:23166
Fangrui Song6b56a272024-09-21 17:11:37167 if (!ctx.arg.saveTempsArgs.empty())
Fangrui Song8f238f62024-11-17 06:28:54168 checkError(ctx.e, c.addSaveTemps(ctx.arg.outputFile.str() + ".",
169 /*UseInputModulePath*/ true,
170 ctx.arg.saveTempsArgs));
Rui Ueyama3837f422019-07-10 05:00:37171 return c;
Rui Ueyama397dffd2018-05-07 23:24:07172}
Davide Italiano786d8e32016-09-29 00:40:08173
Fangrui Song6b56a272024-09-21 17:11:37174BitcodeCompiler::BitcodeCompiler(Ctx &ctx) : ctx(ctx) {
Fangrui Song47cfe8f2019-07-16 05:50:45175 // Initialize indexFile.
Fangrui Song6b56a272024-09-21 17:11:37176 if (!ctx.arg.thinLTOIndexOnlyArg.empty())
177 indexFile = openFile(ctx.arg.thinLTOIndexOnlyArg);
Rui Ueyama98e4a5c2018-09-11 14:37:27178
Fangrui Song47cfe8f2019-07-16 05:50:45179 // Initialize ltoObj.
Rui Ueyama3837f422019-07-10 05:00:37180 lto::ThinBackend backend;
Jin Xin Ng22f12732022-06-01 17:49:36181 auto onIndexWrite = [&](StringRef s) { thinIndices.erase(s); };
Fangrui Song6b56a272024-09-21 17:11:37182 if (ctx.arg.thinLTOIndexOnly) {
Rui Ueyama3837f422019-07-10 05:00:37183 backend = lto::createWriteIndexesThinBackend(
Nuri Amari2edd8972024-10-07 15:16:46184 llvm::hardware_concurrency(ctx.arg.thinLTOJobs),
Fangrui Song6b56a272024-09-21 17:11:37185 std::string(ctx.arg.thinLTOPrefixReplaceOld),
186 std::string(ctx.arg.thinLTOPrefixReplaceNew),
187 std::string(ctx.arg.thinLTOPrefixReplaceNativeObject),
188 ctx.arg.thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite);
Alexandre Ganea09158252020-03-27 14:20:39189 } else {
190 backend = lto::createInProcessThinBackend(
Fangrui Song6b56a272024-09-21 17:11:37191 llvm::heavyweight_hardware_concurrency(ctx.arg.thinLTOJobs),
192 onIndexWrite, ctx.arg.thinLTOEmitIndexFiles,
193 ctx.arg.thinLTOEmitImportsFiles);
Rumeet Dhindsad366e362018-05-02 21:40:07194 }
195
Matthew Vossab9b3c82023-07-18 23:13:58196 constexpr llvm::lto::LTO::LTOKind ltoModes[3] =
197 {llvm::lto::LTO::LTOKind::LTOK_UnifiedThin,
198 llvm::lto::LTO::LTOKind::LTOK_UnifiedRegular,
199 llvm::lto::LTO::LTOKind::LTOK_Default};
Fangrui Song6b56a272024-09-21 17:11:37200 ltoObj = std::make_unique<lto::LTO>(createConfig(ctx), backend,
201 ctx.arg.ltoPartitions,
202 ltoModes[ctx.arg.ltoKind]);
Rui Ueyama25992482016-03-22 20:52:10203
Fangrui Song47cfe8f2019-07-16 05:50:45204 // Initialize usedStartStop.
Fangrui Song34fa8602022-10-01 19:06:33205 if (ctx.bitcodeFiles.empty())
Fangrui Song33319dd2021-12-23 09:52:54206 return;
Fangrui Songdf0864e2024-09-23 17:33:43207 for (Symbol *sym : ctx.symtab->getSymbols()) {
Fangrui Songe9262ed2021-12-27 02:11:45208 if (sym->isPlaceholder())
209 continue;
Rui Ueyama3837f422019-07-10 05:00:37210 StringRef s = sym->getName();
211 for (StringRef prefix : {"__start_", "__stop_"})
Fangrui Song8d85c962023-06-05 21:36:19212 if (s.starts_with(prefix))
Rui Ueyama3837f422019-07-10 05:00:37213 usedStartStop.insert(s.substr(prefix.size()));
Fangrui Songa2fc9642019-11-20 19:16:15214 }
Rafael Espindola4b075bb2017-07-26 23:39:10215}
Rafael Espindolaae605c12016-04-21 20:35:25216
Eugene Zelenko22886a22016-11-05 01:00:56217BitcodeCompiler::~BitcodeCompiler() = default;
Rui Ueyama412c802b2016-04-22 21:16:18218
Rui Ueyama3837f422019-07-10 05:00:37219void BitcodeCompiler::add(BitcodeFile &f) {
220 lto::InputFile &obj = *f.obj;
Fangrui Songa7e14e22024-09-22 05:54:37221 bool isExec = !ctx.arg.shared && !ctx.arg.relocatable;
Rumeet Dhindsad366e362018-05-02 21:40:07222
Fangrui Songa7e14e22024-09-22 05:54:37223 if (ctx.arg.thinLTOEmitIndexFiles)
Rui Ueyama3837f422019-07-10 05:00:37224 thinIndices.insert(obj.getName());
Rumeet Dhindsad366e362018-05-02 21:40:07225
Rui Ueyama3837f422019-07-10 05:00:37226 ArrayRef<Symbol *> syms = f.getSymbols();
227 ArrayRef<lto::InputFile::Symbol> objSyms = obj.symbols();
228 std::vector<lto::SymbolResolution> resols(syms.size());
Davide Italiano334fce92016-05-11 01:07:22229
Davide Italiano786d8e32016-09-29 00:40:08230 // Provide a resolution to the LTO API for each symbol.
Rui Ueyama3837f422019-07-10 05:00:37231 for (size_t i = 0, e = syms.size(); i != e; ++i) {
232 Symbol *sym = syms[i];
233 const lto::InputFile::Symbol &objSym = objSyms[i];
234 lto::SymbolResolution &r = resols[i];
Davide Italiano86f2bd52016-03-29 21:46:35235
Davide Italiano786d8e32016-09-29 00:40:08236 // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
237 // reports two symbols for module ASM defined. Without this check, lld
238 // flags an undefined in IR with a definition in ASM as prevailing.
239 // Once IRObjectFile is fixed to report only one symbol this hack can
240 // be removed.
Rui Ueyama3837f422019-07-10 05:00:37241 r.Prevailing = !objSym.isUndefined() && sym->file == &f;
Peter Collingbourne3ad1c1e2016-05-05 17:13:49242
George Rimar3a1af222017-08-22 08:36:54243 // We ask LTO to preserve following global symbols:
244 // 1) All symbols when doing relocatable link, so that them can be used
245 // for doing final link.
246 // 2) Symbols that are used in regular objects.
247 // 3) C named sections if we have corresponding __start_/__stop_ symbol.
Shoaib Meenai1af25a92022-04-20 01:04:17248 // 4) Symbols that are defined in bitcode files and used for dynamic
249 // linking.
250 // 5) Symbols that will be referenced after linker wrapping is performed.
Fangrui Songa7e14e22024-09-22 05:54:37251 r.VisibleToRegularObj = ctx.arg.relocatable || sym->isUsedInRegularObj ||
Shoaib Meenai1af25a92022-04-20 01:04:17252 sym->referencedAfterWrap ||
Fangrui Song3733ed62024-12-09 06:40:14253 (r.Prevailing && sym->isExported) ||
Rui Ueyama3837f422019-07-10 05:00:37254 usedStartStop.count(objSym.getSectionName());
Teresa Johnson14877472020-12-30 23:56:53255 // Identify symbols exported dynamically, and that therefore could be
256 // referenced by a shared library not visible to the linker.
Fangrui Songaedc81b2024-12-08 17:17:38257 r.ExportDynamic = sym->computeBinding(ctx) != STB_LOCAL &&
Fangrui Song3733ed62024-12-09 06:40:14258 (ctx.arg.exportDynamic || sym->isExported);
Rui Ueyama3837f422019-07-10 05:00:37259 const auto *dr = dyn_cast<Defined>(sym);
260 r.FinalDefinitionInLinkageUnit =
Fangrui Song82ed93ea2022-09-05 00:27:35261 (isExec || sym->visibility() != STV_DEFAULT) && dr &&
Dmitry Mikulinc84e0ee2018-02-07 00:49:51262 // Skip absolute symbols from ELF objects, otherwise PC-rel relocations
263 // will be generated by for them, triggering linker errors.
264 // Symbol section is always null for bitcode symbols, hence the check
Dmitry Mikulin8ddd9222018-02-08 04:25:52265 // for isElf(). Skip linker script defined symbols as well: they have
266 // no File defined.
Fangrui Song43b13342024-01-22 17:09:46267 !(dr->section == nullptr &&
268 (sym->file->isInternal() || sym->file->isElf()));
Rafael Espindolac6df38c2018-01-16 16:49:05269
Rui Ueyama3837f422019-07-10 05:00:37270 if (r.Prevailing)
Fangrui Song43b13342024-01-22 17:09:46271 Undefined(ctx.internalFile, StringRef(), STB_GLOBAL, STV_DEFAULT,
272 sym->type)
Fangrui Song7a58dd12022-09-28 20:11:31273 .overwrite(*sym);
George Rimard28c26b2017-09-25 09:31:43274
George Rimarc4ccfb52018-01-30 09:04:27275 // We tell LTO to not apply interprocedural optimization for wrapped
276 // (with --wrap) symbols because otherwise LTO would inline them while
277 // their values are still not final.
Fangrui Song7c675922022-02-05 20:00:34278 r.LinkerRedefined = sym->scriptDefined;
Rui Ueyama25992482016-03-22 20:52:10279 }
Fangrui Song8f238f62024-11-17 06:28:54280 checkError(ctx.e, ltoObj->add(std::move(f.obj), resols));
Davide Italianobc176632016-04-15 22:38:10281}
282
Fangrui Song0178cff2019-05-02 14:05:20283// If LazyObjFile has not been added to link, emit empty index files.
284// This is needed because this is what GNU gold plugin does and we have a
285// distributed build system that depends on that behavior.
Fangrui Songbab5d5b2024-09-29 21:45:00286static void thinLTOCreateEmptyIndexFiles(Ctx &ctx) {
Wei Wang5529a752022-09-13 00:35:51287 DenseSet<StringRef> linkedBitCodeFiles;
Fangrui Song34fa8602022-10-01 19:06:33288 for (BitcodeFile *f : ctx.bitcodeFiles)
Wei Wang5529a752022-09-13 00:35:51289 linkedBitCodeFiles.insert(f->getName());
290
Fangrui Song34fa8602022-10-01 19:06:33291 for (BitcodeFile *f : ctx.lazyBitcodeFiles) {
Fangrui Song3a5fb572021-12-23 01:41:50292 if (!f->lazy)
Fangrui Song0178cff2019-05-02 14:05:20293 continue;
Wei Wang5529a752022-09-13 00:35:51294 if (linkedBitCodeFiles.contains(f->getName()))
295 continue;
Aiden Grossmanf7418152022-10-01 06:24:32296 std::string path =
Fangrui Songc4c34f02024-10-04 06:06:18297 replaceThinLTOSuffix(ctx, getThinLTOOutputFile(ctx, f->obj->getName()));
Rui Ueyama3837f422019-07-10 05:00:37298 std::unique_ptr<raw_fd_ostream> os = openFile(path + ".thinlto.bc");
299 if (!os)
Fangrui Song0178cff2019-05-02 14:05:20300 continue;
Rui Ueyamaf06d4942018-05-17 18:27:12301
Rui Ueyama3837f422019-07-10 05:00:37302 ModuleSummaryIndex m(/*HaveGVs*/ false);
303 m.setSkipModuleByDistributedBackend();
Fangrui Song7aaf0242022-02-01 00:46:11304 writeIndexToFile(m, *os);
Fangrui Songa7e14e22024-09-22 05:54:37305 if (ctx.arg.thinLTOEmitImportsFiles)
Rui Ueyama3837f422019-07-10 05:00:37306 openFile(path + ".imports");
Fangrui Song0178cff2019-05-02 14:05:20307 }
Rui Ueyamaf06d4942018-05-17 18:27:12308}
309
Rui Ueyama25992482016-03-22 20:52:10310// Merge all the bitcode files we have seen, codegen the result
Davide Italiano786d8e32016-09-29 00:40:08311// and return the resulting ObjectFile(s).
Fangrui Songdbf37e92024-11-17 07:50:34312SmallVector<std::unique_ptr<InputFile>, 0> BitcodeCompiler::compile() {
Rui Ueyama3837f422019-07-10 05:00:37313 unsigned maxTasks = ltoObj->getMaxTasks();
314 buf.resize(maxTasks);
315 files.resize(maxTasks);
Fangrui Songf7669ba2024-01-23 19:38:15316 filenames.resize(maxTasks);
Davide Italiano828ac5412016-03-28 15:44:21317
Peter Collingbournee02775f2017-03-01 23:00:10318 // The --thinlto-cache-dir option specifies the path to a directory in which
319 // to cache native object files for ThinLTO incremental builds. If a path was
320 // specified, configure LTO to use it as the cache directory.
Noah Shuttyd788c442021-11-04 19:59:59321 FileCache cache;
Fangrui Song6b56a272024-09-21 17:11:37322 if (!ctx.arg.thinLTOCacheDir.empty())
323 cache = check(localCache("ThinLTO", "Thin", ctx.arg.thinLTOCacheDir,
Zequan Wu84be92d2022-11-22 21:46:42324 [&](size_t task, const Twine &moduleName,
325 std::unique_ptr<MemoryBuffer> mb) {
326 files[task] = std::move(mb);
Fangrui Songf7669ba2024-01-23 19:38:15327 filenames[task] = moduleName.str();
Zequan Wu84be92d2022-11-22 21:46:42328 }));
Peter Collingbournee02775f2017-03-01 23:00:10329
Fangrui Song34fa8602022-10-01 19:06:33330 if (!ctx.bitcodeFiles.empty())
Fangrui Song8f238f62024-11-17 06:28:54331 checkError(ctx.e, ltoObj->run(
332 [&](size_t task, const Twine &moduleName) {
333 buf[task].first = moduleName.str();
334 return std::make_unique<CachedFileStream>(
335 std::make_unique<raw_svector_ostream>(
336 buf[task].second));
337 },
338 cache));
Rafael Espindolaabf6c652016-04-17 23:20:08339
Hongtao Yu2638aaf2020-05-21 20:19:44340 // Emit empty index files for non-indexed files but not in single-module mode.
Fangrui Song6b56a272024-09-21 17:11:37341 if (ctx.arg.thinLTOModulesToCompile.empty()) {
Hongtao Yu2638aaf2020-05-21 20:19:44342 for (StringRef s : thinIndices) {
Fangrui Song6b56a272024-09-21 17:11:37343 std::string path = getThinLTOOutputFile(ctx, s);
Hongtao Yu2638aaf2020-05-21 20:19:44344 openFile(path + ".thinlto.bc");
Fangrui Song6b56a272024-09-21 17:11:37345 if (ctx.arg.thinLTOEmitImportsFiles)
Hongtao Yu2638aaf2020-05-21 20:19:44346 openFile(path + ".imports");
347 }
Davide Italiano786d8e32016-09-29 00:40:08348 }
Peter Collingbournee02775f2017-03-01 23:00:10349
Fangrui Song6b56a272024-09-21 17:11:37350 if (ctx.arg.thinLTOEmitIndexFiles)
Fangrui Songbab5d5b2024-09-29 21:45:00351 thinLTOCreateEmptyIndexFiles(ctx);
Rui Ueyamad54f1c22018-05-07 22:11:24352
Fangrui Song6b56a272024-09-21 17:11:37353 if (ctx.arg.thinLTOIndexOnly) {
354 if (!ctx.arg.ltoObjPath.empty())
355 saveBuffer(buf[0].second, ctx.arg.ltoObjPath);
Rumeet Dhindsa18883262018-05-08 20:12:07356
Rui Ueyamad54f1c22018-05-07 22:11:24357 // ThinLTO with index only option is required to generate only the index
358 // files. After that, we exit from linker and ThinLTO backend runs in a
359 // distributed environment.
Rui Ueyama3837f422019-07-10 05:00:37360 if (indexFile)
361 indexFile->close();
Rui Ueyama554adb22018-05-07 22:11:34362 return {};
Rui Ueyamad54f1c22018-05-07 22:11:24363 }
Rui Ueyamaf06d4942018-05-17 18:27:12364
Fangrui Song6b56a272024-09-21 17:11:37365 if (!ctx.arg.thinLTOCacheDir.empty())
366 pruneCache(ctx.arg.thinLTOCacheDir, ctx.arg.thinLTOCachePolicy, files);
Rumeet Dhindsa18883262018-05-08 20:12:07367
Fangrui Song6b56a272024-09-21 17:11:37368 if (!ctx.arg.ltoObjPath.empty()) {
369 saveBuffer(buf[0].second, ctx.arg.ltoObjPath);
Rui Ueyama3837f422019-07-10 05:00:37370 for (unsigned i = 1; i != maxTasks; ++i)
Fangrui Song6b56a272024-09-21 17:11:37371 saveBuffer(buf[i].second, ctx.arg.ltoObjPath + Twine(i));
Rumeet Dhindsa18883262018-05-08 20:12:07372 }
Rumeet Dhindsad366e362018-05-02 21:40:07373
Fangrui Song6b56a272024-09-21 17:11:37374 bool savePrelink = ctx.arg.saveTempsArgs.contains("prelink");
Fangrui Songdbf37e92024-11-17 07:50:34375 SmallVector<std::unique_ptr<InputFile>, 0> ret;
Fangrui Song6b56a272024-09-21 17:11:37376 const char *ext = ctx.arg.ltoEmitAsm ? ".s" : ".o";
Fangrui Songf7669ba2024-01-23 19:38:15377 for (unsigned i = 0; i != maxTasks; ++i) {
378 StringRef bitcodeFilePath;
379 StringRef objBuf;
380 if (files[i]) {
381 // When files[i] is not null, we get the native relocatable file from the
382 // cache. filenames[i] contains the original BitcodeFile's identifier.
383 objBuf = files[i]->getBuffer();
384 bitcodeFilePath = filenames[i];
385 } else {
386 // Get the native relocatable file after in-process LTO compilation.
387 objBuf = buf[i].second;
388 bitcodeFilePath = buf[i].first;
389 }
390 if (objBuf.empty())
391 continue;
Bill Wendling01706bd2019-02-26 19:29:14392
Fangrui Songf7669ba2024-01-23 19:38:15393 // If the input bitcode file is path/to/x.o and -o specifies a.out, the
394 // corresponding native relocatable file path will look like:
395 // path/to/a.out.lto.x.o.
396 StringRef ltoObjName;
397 if (bitcodeFilePath == "ld-temp.o") {
398 ltoObjName =
Fangrui Song2991a4e2024-11-17 06:34:12399 ctx.saver.save(Twine(ctx.arg.outputFile) + ".lto" +
400 (i == 0 ? Twine("") : Twine('.') + Twine(i)) + ext);
Fangrui Songf7669ba2024-01-23 19:38:15401 } else {
402 StringRef directory = sys::path::parent_path(bitcodeFilePath);
403 // For an archive member, which has an identifier like "d/a.a(coll.o at
404 // 8)" (see BitcodeFile::BitcodeFile), use the filename; otherwise, use
405 // the stem (d/a.o => a).
406 StringRef baseName = bitcodeFilePath.ends_with(")")
407 ? sys::path::filename(bitcodeFilePath)
408 : sys::path::stem(bitcodeFilePath);
Fangrui Song6b56a272024-09-21 17:11:37409 StringRef outputFileBaseName = sys::path::filename(ctx.arg.outputFile);
Fangrui Songf7669ba2024-01-23 19:38:15410 SmallString<256> path;
411 sys::path::append(path, directory,
412 outputFileBaseName + ".lto." + baseName + ext);
413 sys::path::remove_dots(path, true);
Fangrui Song2991a4e2024-11-17 06:34:12414 ltoObjName = ctx.saver.save(path.str());
Fangrui Songf7669ba2024-01-23 19:38:15415 }
Fangrui Song6b56a272024-09-21 17:11:37416 if (savePrelink || ctx.arg.ltoEmitAsm)
Fangrui Songf7669ba2024-01-23 19:38:15417 saveBuffer(buf[i].second, ltoObjName);
Fangrui Song6b56a272024-09-21 17:11:37418 if (!ctx.arg.ltoEmitAsm)
Fangrui Songb6720712024-10-07 01:09:52419 ret.push_back(createObjFile(ctx, MemoryBufferRef(objBuf, ltoObjName)));
Fangrui Songf7669ba2024-01-23 19:38:15420 }
Rui Ueyama3837f422019-07-10 05:00:37421 return ret;
Rui Ueyama961f2ff2016-03-23 21:19:27422}