Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lld/COFF/LTO.cpp
34870 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 "COFFLinkerContext.h"
11
#include "Config.h"
12
#include "InputFiles.h"
13
#include "Symbols.h"
14
#include "lld/Common/Args.h"
15
#include "lld/Common/CommonLinkerContext.h"
16
#include "lld/Common/Filesystem.h"
17
#include "lld/Common/Strings.h"
18
#include "lld/Common/TargetOptionsCommandFlags.h"
19
#include "llvm/ADT/STLExtras.h"
20
#include "llvm/ADT/SmallString.h"
21
#include "llvm/ADT/StringRef.h"
22
#include "llvm/ADT/Twine.h"
23
#include "llvm/Bitcode/BitcodeWriter.h"
24
#include "llvm/IR/DiagnosticPrinter.h"
25
#include "llvm/LTO/Config.h"
26
#include "llvm/LTO/LTO.h"
27
#include "llvm/Object/SymbolicFile.h"
28
#include "llvm/Support/Caching.h"
29
#include "llvm/Support/CodeGen.h"
30
#include "llvm/Support/Error.h"
31
#include "llvm/Support/FileSystem.h"
32
#include "llvm/Support/MemoryBuffer.h"
33
#include "llvm/Support/raw_ostream.h"
34
#include <algorithm>
35
#include <cstddef>
36
#include <memory>
37
#include <string>
38
#include <system_error>
39
#include <vector>
40
41
using namespace llvm;
42
using namespace llvm::object;
43
using namespace lld;
44
using namespace lld::coff;
45
46
std::string BitcodeCompiler::getThinLTOOutputFile(StringRef path) {
47
return lto::getThinLTOOutputFile(path, ctx.config.thinLTOPrefixReplaceOld,
48
ctx.config.thinLTOPrefixReplaceNew);
49
}
50
51
lto::Config BitcodeCompiler::createConfig() {
52
lto::Config c;
53
c.Options = initTargetOptionsFromCodeGenFlags();
54
c.Options.EmitAddrsig = true;
55
for (StringRef C : ctx.config.mllvmOpts)
56
c.MllvmArgs.emplace_back(C.str());
57
58
// Always emit a section per function/datum with LTO. LLVM LTO should get most
59
// of the benefit of linker GC, but there are still opportunities for ICF.
60
c.Options.FunctionSections = true;
61
c.Options.DataSections = true;
62
63
// Use static reloc model on 32-bit x86 because it usually results in more
64
// compact code, and because there are also known code generation bugs when
65
// using the PIC model (see PR34306).
66
if (ctx.config.machine == COFF::IMAGE_FILE_MACHINE_I386)
67
c.RelocModel = Reloc::Static;
68
else
69
c.RelocModel = Reloc::PIC_;
70
#ifndef NDEBUG
71
c.DisableVerify = false;
72
#else
73
c.DisableVerify = true;
74
#endif
75
c.DiagHandler = diagnosticHandler;
76
c.DwoDir = ctx.config.dwoDir.str();
77
c.OptLevel = ctx.config.ltoo;
78
c.CPU = getCPUStr();
79
c.MAttrs = getMAttrs();
80
std::optional<CodeGenOptLevel> optLevelOrNone = CodeGenOpt::getLevel(
81
ctx.config.ltoCgo.value_or(args::getCGOptLevel(ctx.config.ltoo)));
82
assert(optLevelOrNone && "Invalid optimization level!");
83
c.CGOptLevel = *optLevelOrNone;
84
c.AlwaysEmitRegularLTOObj = !ctx.config.ltoObjPath.empty();
85
c.DebugPassManager = ctx.config.ltoDebugPassManager;
86
c.CSIRProfile = std::string(ctx.config.ltoCSProfileFile);
87
c.RunCSIRInstr = ctx.config.ltoCSProfileGenerate;
88
c.PGOWarnMismatch = ctx.config.ltoPGOWarnMismatch;
89
c.SampleProfile = ctx.config.ltoSampleProfileName;
90
c.TimeTraceEnabled = ctx.config.timeTraceEnabled;
91
c.TimeTraceGranularity = ctx.config.timeTraceGranularity;
92
93
if (ctx.config.emit == EmitKind::LLVM) {
94
c.PreCodeGenModuleHook = [this](size_t task, const Module &m) {
95
if (std::unique_ptr<raw_fd_ostream> os =
96
openLTOOutputFile(ctx.config.outputFile))
97
WriteBitcodeToFile(m, *os, false);
98
return false;
99
};
100
} else if (ctx.config.emit == EmitKind::ASM) {
101
c.CGFileType = CodeGenFileType::AssemblyFile;
102
c.Options.MCOptions.AsmVerbose = true;
103
}
104
105
if (ctx.config.saveTemps)
106
checkError(c.addSaveTemps(std::string(ctx.config.outputFile) + ".",
107
/*UseInputModulePath*/ true));
108
return c;
109
}
110
111
BitcodeCompiler::BitcodeCompiler(COFFLinkerContext &c) : ctx(c) {
112
// Initialize indexFile.
113
if (!ctx.config.thinLTOIndexOnlyArg.empty())
114
indexFile = openFile(ctx.config.thinLTOIndexOnlyArg);
115
116
// Initialize ltoObj.
117
lto::ThinBackend backend;
118
if (ctx.config.thinLTOIndexOnly) {
119
auto OnIndexWrite = [&](StringRef S) { thinIndices.erase(S); };
120
backend = lto::createWriteIndexesThinBackend(
121
std::string(ctx.config.thinLTOPrefixReplaceOld),
122
std::string(ctx.config.thinLTOPrefixReplaceNew),
123
std::string(ctx.config.thinLTOPrefixReplaceNativeObject),
124
ctx.config.thinLTOEmitImportsFiles, indexFile.get(), OnIndexWrite);
125
} else {
126
backend = lto::createInProcessThinBackend(
127
llvm::heavyweight_hardware_concurrency(ctx.config.thinLTOJobs));
128
}
129
130
ltoObj = std::make_unique<lto::LTO>(createConfig(), backend,
131
ctx.config.ltoPartitions);
132
}
133
134
BitcodeCompiler::~BitcodeCompiler() = default;
135
136
static void undefine(Symbol *s) { replaceSymbol<Undefined>(s, s->getName()); }
137
138
void BitcodeCompiler::add(BitcodeFile &f) {
139
lto::InputFile &obj = *f.obj;
140
unsigned symNum = 0;
141
std::vector<Symbol *> symBodies = f.getSymbols();
142
std::vector<lto::SymbolResolution> resols(symBodies.size());
143
144
if (ctx.config.thinLTOIndexOnly)
145
thinIndices.insert(obj.getName());
146
147
// Provide a resolution to the LTO API for each symbol.
148
for (const lto::InputFile::Symbol &objSym : obj.symbols()) {
149
Symbol *sym = symBodies[symNum];
150
lto::SymbolResolution &r = resols[symNum];
151
++symNum;
152
153
// Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
154
// reports two symbols for module ASM defined. Without this check, lld
155
// flags an undefined in IR with a definition in ASM as prevailing.
156
// Once IRObjectFile is fixed to report only one symbol this hack can
157
// be removed.
158
r.Prevailing = !objSym.isUndefined() && sym->getFile() == &f;
159
r.VisibleToRegularObj = sym->isUsedInRegularObj;
160
if (r.Prevailing)
161
undefine(sym);
162
163
// We tell LTO to not apply interprocedural optimization for wrapped
164
// (with -wrap) symbols because otherwise LTO would inline them while
165
// their values are still not final.
166
r.LinkerRedefined = !sym->canInline;
167
}
168
checkError(ltoObj->add(std::move(f.obj), resols));
169
}
170
171
// Merge all the bitcode files we have seen, codegen the result
172
// and return the resulting objects.
173
std::vector<InputFile *> BitcodeCompiler::compile() {
174
unsigned maxTasks = ltoObj->getMaxTasks();
175
buf.resize(maxTasks);
176
files.resize(maxTasks);
177
file_names.resize(maxTasks);
178
179
// The /lldltocache option specifies the path to a directory in which to cache
180
// native object files for ThinLTO incremental builds. If a path was
181
// specified, configure LTO to use it as the cache directory.
182
FileCache cache;
183
if (!ctx.config.ltoCache.empty())
184
cache = check(localCache("ThinLTO", "Thin", ctx.config.ltoCache,
185
[&](size_t task, const Twine &moduleName,
186
std::unique_ptr<MemoryBuffer> mb) {
187
files[task] = std::move(mb);
188
file_names[task] = moduleName.str();
189
}));
190
191
checkError(ltoObj->run(
192
[&](size_t task, const Twine &moduleName) {
193
buf[task].first = moduleName.str();
194
return std::make_unique<CachedFileStream>(
195
std::make_unique<raw_svector_ostream>(buf[task].second));
196
},
197
cache));
198
199
// Emit empty index files for non-indexed files
200
for (StringRef s : thinIndices) {
201
std::string path = getThinLTOOutputFile(s);
202
openFile(path + ".thinlto.bc");
203
if (ctx.config.thinLTOEmitImportsFiles)
204
openFile(path + ".imports");
205
}
206
207
// ThinLTO with index only option is required to generate only the index
208
// files. After that, we exit from linker and ThinLTO backend runs in a
209
// distributed environment.
210
if (ctx.config.thinLTOIndexOnly) {
211
if (!ctx.config.ltoObjPath.empty())
212
saveBuffer(buf[0].second, ctx.config.ltoObjPath);
213
if (indexFile)
214
indexFile->close();
215
return {};
216
}
217
218
if (!ctx.config.ltoCache.empty())
219
pruneCache(ctx.config.ltoCache, ctx.config.ltoCachePolicy, files);
220
221
std::vector<InputFile *> ret;
222
bool emitASM = ctx.config.emit == EmitKind::ASM;
223
const char *Ext = emitASM ? ".s" : ".obj";
224
for (unsigned i = 0; i != maxTasks; ++i) {
225
StringRef bitcodeFilePath;
226
// Get the native object contents either from the cache or from memory. Do
227
// not use the cached MemoryBuffer directly, or the PDB will not be
228
// deterministic.
229
StringRef objBuf;
230
if (files[i]) {
231
objBuf = files[i]->getBuffer();
232
bitcodeFilePath = file_names[i];
233
} else {
234
objBuf = buf[i].second;
235
bitcodeFilePath = buf[i].first;
236
}
237
if (objBuf.empty())
238
continue;
239
240
// If the input bitcode file is path/to/a.obj, then the corresponding lto
241
// object file name will look something like: path/to/main.exe.lto.a.obj.
242
StringRef ltoObjName;
243
if (bitcodeFilePath == "ld-temp.o") {
244
ltoObjName =
245
saver().save(Twine(ctx.config.outputFile) + ".lto" +
246
(i == 0 ? Twine("") : Twine('.') + Twine(i)) + Ext);
247
} else {
248
StringRef directory = sys::path::parent_path(bitcodeFilePath);
249
StringRef baseName = sys::path::stem(bitcodeFilePath);
250
StringRef outputFileBaseName = sys::path::filename(ctx.config.outputFile);
251
SmallString<64> path;
252
sys::path::append(path, directory,
253
outputFileBaseName + ".lto." + baseName + Ext);
254
sys::path::remove_dots(path, true);
255
ltoObjName = saver().save(path.str());
256
}
257
if (ctx.config.saveTemps || emitASM)
258
saveBuffer(buf[i].second, ltoObjName);
259
if (!emitASM)
260
ret.push_back(make<ObjFile>(ctx, MemoryBufferRef(objBuf, ltoObjName)));
261
}
262
263
return ret;
264
}
265
266