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(Path: modulePath, OldPrefix: config->thinLTOPrefixReplaceOld, |
48 | NewPrefix: 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(args: 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(Filename: config->ltoBasicBlockSections.str()); |
80 | if (!MBOrErr) { |
81 | error(msg: "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(x: 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(args: 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.PostInternalizeModuleHook = [](size_t task, const Module &m) { |
151 | if (std::unique_ptr<raw_fd_ostream> os = |
152 | openLTOOutputFile(file: config->outputFile)) |
153 | WriteBitcodeToFile(M: m, Out&: *os, ShouldPreserveUseListOrder: 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(e: c.addSaveTemps(OutputFileName: config->outputFile.str() + "." , |
165 | /*UseInputModulePath*/ true, |
166 | SaveTempsArgs: config->saveTempsArgs)); |
167 | return c; |
168 | } |
169 | |
170 | BitcodeCompiler::BitcodeCompiler() { |
171 | // Initialize indexFile. |
172 | if (!config->thinLTOIndexOnlyArg.empty()) |
173 | indexFile = openFile(file: config->thinLTOIndexOnlyArg); |
174 | |
175 | // Initialize ltoObj. |
176 | lto::ThinBackend backend; |
177 | auto onIndexWrite = [&](StringRef s) { thinIndices.erase(V: s); }; |
178 | if (config->thinLTOIndexOnly) { |
179 | backend = lto::createWriteIndexesThinBackend( |
180 | OldPrefix: std::string(config->thinLTOPrefixReplaceOld), |
181 | NewPrefix: std::string(config->thinLTOPrefixReplaceNew), |
182 | NativeObjectPrefix: std::string(config->thinLTOPrefixReplaceNativeObject), |
183 | ShouldEmitImportsFiles: config->thinLTOEmitImportsFiles, LinkedObjectsFile: indexFile.get(), OnWrite: onIndexWrite); |
184 | } else { |
185 | backend = lto::createInProcessThinBackend( |
186 | Parallelism: llvm::heavyweight_hardware_concurrency(Num: config->thinLTOJobs), |
187 | OnWrite: onIndexWrite, ShouldEmitIndexFiles: config->thinLTOEmitIndexFiles, |
188 | ShouldEmitImportsFiles: 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 | args: createConfig(), args&: backend, args&: config->ltoPartitions, |
197 | args: 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: prefix)) |
208 | usedStartStop.insert(V: s.substr(Start: 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(V: 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(V: 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>(Val: 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&: *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(e: ltoObj->add(Obj: std::move(f.obj), Res: 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(V: f->getName()); |
286 | |
287 | for (BitcodeFile *f : ctx.lazyBitcodeFiles) { |
288 | if (!f->lazy) |
289 | continue; |
290 | if (linkedBitCodeFiles.contains(V: f->getName())) |
291 | continue; |
292 | std::string path = |
293 | replaceThinLTOSuffix(path: getThinLTOOutputFile(modulePath: f->obj->getName())); |
294 | std::unique_ptr<raw_fd_ostream> os = openFile(file: path + ".thinlto.bc" ); |
295 | if (!os) |
296 | continue; |
297 | |
298 | ModuleSummaryIndex m(/*HaveGVs*/ false); |
299 | m.setSkipModuleByDistributedBackend(); |
300 | writeIndexToFile(Index: m, Out&: *os); |
301 | if (config->thinLTOEmitImportsFiles) |
302 | openFile(file: 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(N: maxTasks); |
311 | files.resize(new_size: maxTasks); |
312 | filenames.resize(N: 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(e: localCache(CacheNameRef: "ThinLTO" , TempFilePrefixRef: "Thin" , CacheDirectoryPathRef: config->thinLTOCacheDir, |
320 | AddBuffer: [&](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(e: ltoObj->run( |
328 | AddStream: [&](size_t task, const Twine &moduleName) { |
329 | buf[task].first = moduleName.str(); |
330 | return std::make_unique<CachedFileStream>( |
331 | args: std::make_unique<raw_svector_ostream>(args&: buf[task].second)); |
332 | }, |
333 | Cache: 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(modulePath: s); |
339 | openFile(file: path + ".thinlto.bc" ); |
340 | if (config->thinLTOEmitImportsFiles) |
341 | openFile(file: path + ".imports" ); |
342 | } |
343 | } |
344 | |
345 | if (config->thinLTOEmitIndexFiles) |
346 | thinLTOCreateEmptyIndexFiles(); |
347 | |
348 | if (config->thinLTOIndexOnly) { |
349 | if (!config->ltoObjPath.empty()) |
350 | saveBuffer(buffer: buf[0].second, path: 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(Path: config->thinLTOCacheDir, Policy: config->thinLTOCachePolicy, Files: files); |
362 | |
363 | if (!config->ltoObjPath.empty()) { |
364 | saveBuffer(buffer: buf[0].second, path: config->ltoObjPath); |
365 | for (unsigned i = 1; i != maxTasks; ++i) |
366 | saveBuffer(buffer: buf[i].second, path: config->ltoObjPath + Twine(i)); |
367 | } |
368 | |
369 | bool savePrelink = config->saveTempsArgs.contains(V: "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(S: Twine(config->outputFile) + ".lto" + |
395 | (i == 0 ? Twine("" ) : Twine('.') + Twine(i)) + ext); |
396 | } else { |
397 | StringRef directory = sys::path::parent_path(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(Suffix: ")" ) |
402 | ? sys::path::filename(path: bitcodeFilePath) |
403 | : sys::path::stem(path: bitcodeFilePath); |
404 | StringRef outputFileBaseName = sys::path::filename(path: config->outputFile); |
405 | SmallString<256> path; |
406 | sys::path::append(path, a: directory, |
407 | b: outputFileBaseName + ".lto." + baseName + ext); |
408 | sys::path::remove_dots(path, remove_dot_dot: true); |
409 | ltoObjName = saver().save(S: path.str()); |
410 | } |
411 | if (savePrelink || config->ltoEmitAsm) |
412 | saveBuffer(buffer: buf[i].second, path: ltoObjName); |
413 | if (!config->ltoEmitAsm) |
414 | ret.push_back(x: createObjFile(mb: MemoryBufferRef(objBuf, ltoObjName))); |
415 | } |
416 | return ret; |
417 | } |
418 | |