Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lld/ELF/LTO.cpp
34878 views
1
//===- LTO.cpp ------------------------------------------------------------===//
2
//
3
// 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
6
//
7
//===----------------------------------------------------------------------===//
8
9
#include "LTO.h"
10
#include "Config.h"
11
#include "InputFiles.h"
12
#include "SymbolTable.h"
13
#include "Symbols.h"
14
#include "lld/Common/Args.h"
15
#include "lld/Common/CommonLinkerContext.h"
16
#include "lld/Common/ErrorHandler.h"
17
#include "lld/Common/Filesystem.h"
18
#include "lld/Common/Strings.h"
19
#include "lld/Common/TargetOptionsCommandFlags.h"
20
#include "llvm/ADT/SmallString.h"
21
#include "llvm/ADT/StringRef.h"
22
#include "llvm/ADT/Twine.h"
23
#include "llvm/BinaryFormat/ELF.h"
24
#include "llvm/Bitcode/BitcodeWriter.h"
25
#include "llvm/LTO/Config.h"
26
#include "llvm/LTO/LTO.h"
27
#include "llvm/Support/Caching.h"
28
#include "llvm/Support/CodeGen.h"
29
#include "llvm/Support/Error.h"
30
#include "llvm/Support/FileSystem.h"
31
#include "llvm/Support/MemoryBuffer.h"
32
#include "llvm/Support/Path.h"
33
#include <algorithm>
34
#include <cstddef>
35
#include <memory>
36
#include <string>
37
#include <system_error>
38
#include <vector>
39
40
using namespace llvm;
41
using namespace llvm::object;
42
using namespace llvm::ELF;
43
using namespace lld;
44
using namespace lld::elf;
45
46
static std::string getThinLTOOutputFile(StringRef modulePath) {
47
return lto::getThinLTOOutputFile(modulePath, config->thinLTOPrefixReplaceOld,
48
config->thinLTOPrefixReplaceNew);
49
}
50
51
static lto::Config createConfig() {
52
lto::Config c;
53
54
// LLD supports the new relocations and address-significance tables.
55
c.Options = initTargetOptionsFromCodeGenFlags();
56
c.Options.EmitAddrsig = true;
57
for (StringRef C : config->mllvmOpts)
58
c.MllvmArgs.emplace_back(C.str());
59
60
// Always emit a section per function/datum with LTO.
61
c.Options.FunctionSections = true;
62
c.Options.DataSections = true;
63
64
c.Options.BBAddrMap = config->ltoBBAddrMap;
65
66
// Check if basic block sections must be used.
67
// Allowed values for --lto-basic-block-sections are "all", "labels",
68
// "<file name specifying basic block ids>", or none. This is the equivalent
69
// of -fbasic-block-sections= flag in clang.
70
if (!config->ltoBasicBlockSections.empty()) {
71
if (config->ltoBasicBlockSections == "all") {
72
c.Options.BBSections = BasicBlockSection::All;
73
} else if (config->ltoBasicBlockSections == "labels") {
74
c.Options.BBSections = BasicBlockSection::Labels;
75
} else if (config->ltoBasicBlockSections == "none") {
76
c.Options.BBSections = BasicBlockSection::None;
77
} else {
78
ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr =
79
MemoryBuffer::getFile(config->ltoBasicBlockSections.str());
80
if (!MBOrErr) {
81
error("cannot open " + config->ltoBasicBlockSections + ":" +
82
MBOrErr.getError().message());
83
} else {
84
c.Options.BBSectionsFuncListBuf = std::move(*MBOrErr);
85
}
86
c.Options.BBSections = BasicBlockSection::List;
87
}
88
}
89
90
c.Options.UniqueBasicBlockSectionNames =
91
config->ltoUniqueBasicBlockSectionNames;
92
93
if (auto relocModel = getRelocModelFromCMModel())
94
c.RelocModel = *relocModel;
95
else if (config->relocatable)
96
c.RelocModel = std::nullopt;
97
else if (config->isPic)
98
c.RelocModel = Reloc::PIC_;
99
else
100
c.RelocModel = Reloc::Static;
101
102
c.CodeModel = getCodeModelFromCMModel();
103
c.DisableVerify = config->disableVerify;
104
c.DiagHandler = diagnosticHandler;
105
c.OptLevel = config->ltoo;
106
c.CPU = getCPUStr();
107
c.MAttrs = getMAttrs();
108
c.CGOptLevel = config->ltoCgo;
109
110
c.PTO.LoopVectorization = c.OptLevel > 1;
111
c.PTO.SLPVectorization = c.OptLevel > 1;
112
113
// Set up a custom pipeline if we've been asked to.
114
c.OptPipeline = std::string(config->ltoNewPmPasses);
115
c.AAPipeline = std::string(config->ltoAAPipeline);
116
117
// Set up optimization remarks if we've been asked to.
118
c.RemarksFilename = std::string(config->optRemarksFilename);
119
c.RemarksPasses = std::string(config->optRemarksPasses);
120
c.RemarksWithHotness = config->optRemarksWithHotness;
121
c.RemarksHotnessThreshold = config->optRemarksHotnessThreshold;
122
c.RemarksFormat = std::string(config->optRemarksFormat);
123
124
// Set up output file to emit statistics.
125
c.StatsFile = std::string(config->optStatsFilename);
126
127
c.SampleProfile = std::string(config->ltoSampleProfile);
128
for (StringRef pluginFn : config->passPlugins)
129
c.PassPlugins.push_back(std::string(pluginFn));
130
c.DebugPassManager = config->ltoDebugPassManager;
131
c.DwoDir = std::string(config->dwoDir);
132
133
c.HasWholeProgramVisibility = config->ltoWholeProgramVisibility;
134
c.ValidateAllVtablesHaveTypeInfos =
135
config->ltoValidateAllVtablesHaveTypeInfos;
136
c.AllVtablesHaveTypeInfos = ctx.ltoAllVtablesHaveTypeInfos;
137
c.AlwaysEmitRegularLTOObj = !config->ltoObjPath.empty();
138
139
for (const llvm::StringRef &name : config->thinLTOModulesToCompile)
140
c.ThinLTOModulesToCompile.emplace_back(name);
141
142
c.TimeTraceEnabled = config->timeTraceEnabled;
143
c.TimeTraceGranularity = config->timeTraceGranularity;
144
145
c.CSIRProfile = std::string(config->ltoCSProfileFile);
146
c.RunCSIRInstr = config->ltoCSProfileGenerate;
147
c.PGOWarnMismatch = config->ltoPGOWarnMismatch;
148
149
if (config->emitLLVM) {
150
c.PreCodeGenModuleHook = [](size_t task, const Module &m) {
151
if (std::unique_ptr<raw_fd_ostream> os =
152
openLTOOutputFile(config->outputFile))
153
WriteBitcodeToFile(m, *os, false);
154
return false;
155
};
156
}
157
158
if (config->ltoEmitAsm) {
159
c.CGFileType = CodeGenFileType::AssemblyFile;
160
c.Options.MCOptions.AsmVerbose = true;
161
}
162
163
if (!config->saveTempsArgs.empty())
164
checkError(c.addSaveTemps(config->outputFile.str() + ".",
165
/*UseInputModulePath*/ true,
166
config->saveTempsArgs));
167
return c;
168
}
169
170
BitcodeCompiler::BitcodeCompiler() {
171
// Initialize indexFile.
172
if (!config->thinLTOIndexOnlyArg.empty())
173
indexFile = openFile(config->thinLTOIndexOnlyArg);
174
175
// Initialize ltoObj.
176
lto::ThinBackend backend;
177
auto onIndexWrite = [&](StringRef s) { thinIndices.erase(s); };
178
if (config->thinLTOIndexOnly) {
179
backend = lto::createWriteIndexesThinBackend(
180
std::string(config->thinLTOPrefixReplaceOld),
181
std::string(config->thinLTOPrefixReplaceNew),
182
std::string(config->thinLTOPrefixReplaceNativeObject),
183
config->thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite);
184
} else {
185
backend = lto::createInProcessThinBackend(
186
llvm::heavyweight_hardware_concurrency(config->thinLTOJobs),
187
onIndexWrite, config->thinLTOEmitIndexFiles,
188
config->thinLTOEmitImportsFiles);
189
}
190
191
constexpr llvm::lto::LTO::LTOKind ltoModes[3] =
192
{llvm::lto::LTO::LTOKind::LTOK_UnifiedThin,
193
llvm::lto::LTO::LTOKind::LTOK_UnifiedRegular,
194
llvm::lto::LTO::LTOKind::LTOK_Default};
195
ltoObj = std::make_unique<lto::LTO>(
196
createConfig(), backend, config->ltoPartitions,
197
ltoModes[config->ltoKind]);
198
199
// Initialize usedStartStop.
200
if (ctx.bitcodeFiles.empty())
201
return;
202
for (Symbol *sym : symtab.getSymbols()) {
203
if (sym->isPlaceholder())
204
continue;
205
StringRef s = sym->getName();
206
for (StringRef prefix : {"__start_", "__stop_"})
207
if (s.starts_with(prefix))
208
usedStartStop.insert(s.substr(prefix.size()));
209
}
210
}
211
212
BitcodeCompiler::~BitcodeCompiler() = default;
213
214
void BitcodeCompiler::add(BitcodeFile &f) {
215
lto::InputFile &obj = *f.obj;
216
bool isExec = !config->shared && !config->relocatable;
217
218
if (config->thinLTOEmitIndexFiles)
219
thinIndices.insert(obj.getName());
220
221
ArrayRef<Symbol *> syms = f.getSymbols();
222
ArrayRef<lto::InputFile::Symbol> objSyms = obj.symbols();
223
std::vector<lto::SymbolResolution> resols(syms.size());
224
225
// Provide a resolution to the LTO API for each symbol.
226
for (size_t i = 0, e = syms.size(); i != e; ++i) {
227
Symbol *sym = syms[i];
228
const lto::InputFile::Symbol &objSym = objSyms[i];
229
lto::SymbolResolution &r = resols[i];
230
231
// Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
232
// reports two symbols for module ASM defined. Without this check, lld
233
// flags an undefined in IR with a definition in ASM as prevailing.
234
// Once IRObjectFile is fixed to report only one symbol this hack can
235
// be removed.
236
r.Prevailing = !objSym.isUndefined() && sym->file == &f;
237
238
// We ask LTO to preserve following global symbols:
239
// 1) All symbols when doing relocatable link, so that them can be used
240
// for doing final link.
241
// 2) Symbols that are used in regular objects.
242
// 3) C named sections if we have corresponding __start_/__stop_ symbol.
243
// 4) Symbols that are defined in bitcode files and used for dynamic
244
// linking.
245
// 5) Symbols that will be referenced after linker wrapping is performed.
246
r.VisibleToRegularObj = config->relocatable || sym->isUsedInRegularObj ||
247
sym->referencedAfterWrap ||
248
(r.Prevailing && sym->includeInDynsym()) ||
249
usedStartStop.count(objSym.getSectionName());
250
// Identify symbols exported dynamically, and that therefore could be
251
// referenced by a shared library not visible to the linker.
252
r.ExportDynamic =
253
sym->computeBinding() != STB_LOCAL &&
254
(config->exportDynamic || sym->exportDynamic || sym->inDynamicList);
255
const auto *dr = dyn_cast<Defined>(sym);
256
r.FinalDefinitionInLinkageUnit =
257
(isExec || sym->visibility() != STV_DEFAULT) && dr &&
258
// Skip absolute symbols from ELF objects, otherwise PC-rel relocations
259
// will be generated by for them, triggering linker errors.
260
// Symbol section is always null for bitcode symbols, hence the check
261
// for isElf(). Skip linker script defined symbols as well: they have
262
// no File defined.
263
!(dr->section == nullptr &&
264
(sym->file->isInternal() || sym->file->isElf()));
265
266
if (r.Prevailing)
267
Undefined(ctx.internalFile, StringRef(), STB_GLOBAL, STV_DEFAULT,
268
sym->type)
269
.overwrite(*sym);
270
271
// We tell LTO to not apply interprocedural optimization for wrapped
272
// (with --wrap) symbols because otherwise LTO would inline them while
273
// their values are still not final.
274
r.LinkerRedefined = sym->scriptDefined;
275
}
276
checkError(ltoObj->add(std::move(f.obj), resols));
277
}
278
279
// If LazyObjFile has not been added to link, emit empty index files.
280
// This is needed because this is what GNU gold plugin does and we have a
281
// distributed build system that depends on that behavior.
282
static void thinLTOCreateEmptyIndexFiles() {
283
DenseSet<StringRef> linkedBitCodeFiles;
284
for (BitcodeFile *f : ctx.bitcodeFiles)
285
linkedBitCodeFiles.insert(f->getName());
286
287
for (BitcodeFile *f : ctx.lazyBitcodeFiles) {
288
if (!f->lazy)
289
continue;
290
if (linkedBitCodeFiles.contains(f->getName()))
291
continue;
292
std::string path =
293
replaceThinLTOSuffix(getThinLTOOutputFile(f->obj->getName()));
294
std::unique_ptr<raw_fd_ostream> os = openFile(path + ".thinlto.bc");
295
if (!os)
296
continue;
297
298
ModuleSummaryIndex m(/*HaveGVs*/ false);
299
m.setSkipModuleByDistributedBackend();
300
writeIndexToFile(m, *os);
301
if (config->thinLTOEmitImportsFiles)
302
openFile(path + ".imports");
303
}
304
}
305
306
// Merge all the bitcode files we have seen, codegen the result
307
// and return the resulting ObjectFile(s).
308
std::vector<InputFile *> BitcodeCompiler::compile() {
309
unsigned maxTasks = ltoObj->getMaxTasks();
310
buf.resize(maxTasks);
311
files.resize(maxTasks);
312
filenames.resize(maxTasks);
313
314
// The --thinlto-cache-dir option specifies the path to a directory in which
315
// to cache native object files for ThinLTO incremental builds. If a path was
316
// specified, configure LTO to use it as the cache directory.
317
FileCache cache;
318
if (!config->thinLTOCacheDir.empty())
319
cache = check(localCache("ThinLTO", "Thin", config->thinLTOCacheDir,
320
[&](size_t task, const Twine &moduleName,
321
std::unique_ptr<MemoryBuffer> mb) {
322
files[task] = std::move(mb);
323
filenames[task] = moduleName.str();
324
}));
325
326
if (!ctx.bitcodeFiles.empty())
327
checkError(ltoObj->run(
328
[&](size_t task, const Twine &moduleName) {
329
buf[task].first = moduleName.str();
330
return std::make_unique<CachedFileStream>(
331
std::make_unique<raw_svector_ostream>(buf[task].second));
332
},
333
cache));
334
335
// Emit empty index files for non-indexed files but not in single-module mode.
336
if (config->thinLTOModulesToCompile.empty()) {
337
for (StringRef s : thinIndices) {
338
std::string path = getThinLTOOutputFile(s);
339
openFile(path + ".thinlto.bc");
340
if (config->thinLTOEmitImportsFiles)
341
openFile(path + ".imports");
342
}
343
}
344
345
if (config->thinLTOEmitIndexFiles)
346
thinLTOCreateEmptyIndexFiles();
347
348
if (config->thinLTOIndexOnly) {
349
if (!config->ltoObjPath.empty())
350
saveBuffer(buf[0].second, config->ltoObjPath);
351
352
// ThinLTO with index only option is required to generate only the index
353
// files. After that, we exit from linker and ThinLTO backend runs in a
354
// distributed environment.
355
if (indexFile)
356
indexFile->close();
357
return {};
358
}
359
360
if (!config->thinLTOCacheDir.empty())
361
pruneCache(config->thinLTOCacheDir, config->thinLTOCachePolicy, files);
362
363
if (!config->ltoObjPath.empty()) {
364
saveBuffer(buf[0].second, config->ltoObjPath);
365
for (unsigned i = 1; i != maxTasks; ++i)
366
saveBuffer(buf[i].second, config->ltoObjPath + Twine(i));
367
}
368
369
bool savePrelink = config->saveTempsArgs.contains("prelink");
370
std::vector<InputFile *> ret;
371
const char *ext = config->ltoEmitAsm ? ".s" : ".o";
372
for (unsigned i = 0; i != maxTasks; ++i) {
373
StringRef bitcodeFilePath;
374
StringRef objBuf;
375
if (files[i]) {
376
// When files[i] is not null, we get the native relocatable file from the
377
// cache. filenames[i] contains the original BitcodeFile's identifier.
378
objBuf = files[i]->getBuffer();
379
bitcodeFilePath = filenames[i];
380
} else {
381
// Get the native relocatable file after in-process LTO compilation.
382
objBuf = buf[i].second;
383
bitcodeFilePath = buf[i].first;
384
}
385
if (objBuf.empty())
386
continue;
387
388
// If the input bitcode file is path/to/x.o and -o specifies a.out, the
389
// corresponding native relocatable file path will look like:
390
// path/to/a.out.lto.x.o.
391
StringRef ltoObjName;
392
if (bitcodeFilePath == "ld-temp.o") {
393
ltoObjName =
394
saver().save(Twine(config->outputFile) + ".lto" +
395
(i == 0 ? Twine("") : Twine('.') + Twine(i)) + ext);
396
} else {
397
StringRef directory = sys::path::parent_path(bitcodeFilePath);
398
// For an archive member, which has an identifier like "d/a.a(coll.o at
399
// 8)" (see BitcodeFile::BitcodeFile), use the filename; otherwise, use
400
// the stem (d/a.o => a).
401
StringRef baseName = bitcodeFilePath.ends_with(")")
402
? sys::path::filename(bitcodeFilePath)
403
: sys::path::stem(bitcodeFilePath);
404
StringRef outputFileBaseName = sys::path::filename(config->outputFile);
405
SmallString<256> path;
406
sys::path::append(path, directory,
407
outputFileBaseName + ".lto." + baseName + ext);
408
sys::path::remove_dots(path, true);
409
ltoObjName = saver().save(path.str());
410
}
411
if (savePrelink || config->ltoEmitAsm)
412
saveBuffer(buf[i].second, ltoObjName);
413
if (!config->ltoEmitAsm)
414
ret.push_back(createObjFile(MemoryBufferRef(objBuf, ltoObjName)));
415
}
416
return ret;
417
}
418
419