Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/tools/llvm-lto/llvm-lto.cpp
35259 views
1
//===- llvm-lto: a simple command-line program to link modules with LTO ---===//
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
// This program takes in a list of bitcode files, links them, performs link-time
10
// optimization, and outputs an object file.
11
//
12
//===----------------------------------------------------------------------===//
13
14
#include "llvm-c/lto.h"
15
#include "llvm/ADT/ArrayRef.h"
16
#include "llvm/ADT/STLExtras.h"
17
#include "llvm/ADT/SmallString.h"
18
#include "llvm/ADT/StringExtras.h"
19
#include "llvm/ADT/StringRef.h"
20
#include "llvm/ADT/StringSet.h"
21
#include "llvm/ADT/Twine.h"
22
#include "llvm/Bitcode/BitcodeReader.h"
23
#include "llvm/Bitcode/BitcodeWriter.h"
24
#include "llvm/CodeGen/CommandFlags.h"
25
#include "llvm/IR/DiagnosticInfo.h"
26
#include "llvm/IR/DiagnosticPrinter.h"
27
#include "llvm/IR/LLVMContext.h"
28
#include "llvm/IR/Module.h"
29
#include "llvm/IR/ModuleSummaryIndex.h"
30
#include "llvm/IR/Verifier.h"
31
#include "llvm/IRReader/IRReader.h"
32
#include "llvm/LTO/legacy/LTOCodeGenerator.h"
33
#include "llvm/LTO/legacy/LTOModule.h"
34
#include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
35
#include "llvm/Support/Allocator.h"
36
#include "llvm/Support/Casting.h"
37
#include "llvm/Support/CommandLine.h"
38
#include "llvm/Support/Error.h"
39
#include "llvm/Support/ErrorHandling.h"
40
#include "llvm/Support/ErrorOr.h"
41
#include "llvm/Support/FileSystem.h"
42
#include "llvm/Support/InitLLVM.h"
43
#include "llvm/Support/MemoryBuffer.h"
44
#include "llvm/Support/Path.h"
45
#include "llvm/Support/SourceMgr.h"
46
#include "llvm/Support/TargetSelect.h"
47
#include "llvm/Support/ToolOutputFile.h"
48
#include "llvm/Support/raw_ostream.h"
49
#include "llvm/Support/WithColor.h"
50
#include "llvm/Target/TargetOptions.h"
51
#include <algorithm>
52
#include <cassert>
53
#include <cstdint>
54
#include <cstdlib>
55
#include <map>
56
#include <memory>
57
#include <string>
58
#include <system_error>
59
#include <tuple>
60
#include <utility>
61
#include <vector>
62
63
using namespace llvm;
64
65
static codegen::RegisterCodeGenFlags CGF;
66
67
static cl::OptionCategory LTOCategory("LTO Options");
68
69
static cl::opt<char>
70
OptLevel("O",
71
cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
72
"(default = '-O2')"),
73
cl::Prefix, cl::init('2'), cl::cat(LTOCategory));
74
75
static cl::opt<bool>
76
IndexStats("thinlto-index-stats",
77
cl::desc("Print statistic for the index in every input files"),
78
cl::init(false), cl::cat(LTOCategory));
79
80
static cl::opt<bool> DisableVerify(
81
"disable-verify", cl::init(false),
82
cl::desc("Do not run the verifier during the optimization pipeline"),
83
cl::cat(LTOCategory));
84
85
static cl::opt<bool> EnableFreestanding(
86
"lto-freestanding", cl::init(false),
87
cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"),
88
cl::cat(LTOCategory));
89
90
static cl::opt<bool> UseDiagnosticHandler(
91
"use-diagnostic-handler", cl::init(false),
92
cl::desc("Use a diagnostic handler to test the handler interface"),
93
cl::cat(LTOCategory));
94
95
static cl::opt<bool>
96
ThinLTO("thinlto", cl::init(false),
97
cl::desc("Only write combined global index for ThinLTO backends"),
98
cl::cat(LTOCategory));
99
100
enum ThinLTOModes {
101
THINLINK,
102
THINDISTRIBUTE,
103
THINEMITIMPORTS,
104
THINPROMOTE,
105
THINIMPORT,
106
THININTERNALIZE,
107
THINOPT,
108
THINCODEGEN,
109
THINALL
110
};
111
112
cl::opt<ThinLTOModes> ThinLTOMode(
113
"thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
114
cl::values(
115
clEnumValN(
116
THINLINK, "thinlink",
117
"ThinLink: produces the index by linking only the summaries."),
118
clEnumValN(THINDISTRIBUTE, "distributedindexes",
119
"Produces individual indexes for distributed backends."),
120
clEnumValN(THINEMITIMPORTS, "emitimports",
121
"Emit imports files for distributed backends."),
122
clEnumValN(THINPROMOTE, "promote",
123
"Perform pre-import promotion (requires -thinlto-index)."),
124
clEnumValN(THINIMPORT, "import",
125
"Perform both promotion and "
126
"cross-module importing (requires "
127
"-thinlto-index)."),
128
clEnumValN(THININTERNALIZE, "internalize",
129
"Perform internalization driven by -exported-symbol "
130
"(requires -thinlto-index)."),
131
clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
132
clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
133
clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end")),
134
cl::cat(LTOCategory));
135
136
static cl::opt<std::string>
137
ThinLTOIndex("thinlto-index",
138
cl::desc("Provide the index produced by a ThinLink, required "
139
"to perform the promotion and/or importing."),
140
cl::cat(LTOCategory));
141
142
static cl::opt<std::string> ThinLTOPrefixReplace(
143
"thinlto-prefix-replace",
144
cl::desc("Control where files for distributed backends are "
145
"created. Expects 'oldprefix;newprefix' and if path "
146
"prefix of output file is oldprefix it will be "
147
"replaced with newprefix."),
148
cl::cat(LTOCategory));
149
150
static cl::opt<std::string> ThinLTOModuleId(
151
"thinlto-module-id",
152
cl::desc("For the module ID for the file to process, useful to "
153
"match what is in the index."),
154
cl::cat(LTOCategory));
155
156
static cl::opt<std::string> ThinLTOCacheDir("thinlto-cache-dir",
157
cl::desc("Enable ThinLTO caching."),
158
cl::cat(LTOCategory));
159
160
static cl::opt<int> ThinLTOCachePruningInterval(
161
"thinlto-cache-pruning-interval", cl::init(1200),
162
cl::desc("Set ThinLTO cache pruning interval."), cl::cat(LTOCategory));
163
164
static cl::opt<uint64_t> ThinLTOCacheMaxSizeBytes(
165
"thinlto-cache-max-size-bytes",
166
cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."),
167
cl::cat(LTOCategory));
168
169
static cl::opt<int> ThinLTOCacheMaxSizeFiles(
170
"thinlto-cache-max-size-files", cl::init(1000000),
171
cl::desc("Set ThinLTO cache pruning directory maximum number of files."),
172
cl::cat(LTOCategory));
173
174
static cl::opt<unsigned> ThinLTOCacheEntryExpiration(
175
"thinlto-cache-entry-expiration", cl::init(604800) /* 1w */,
176
cl::desc("Set ThinLTO cache entry expiration time."), cl::cat(LTOCategory));
177
178
static cl::opt<std::string> ThinLTOSaveTempsPrefix(
179
"thinlto-save-temps",
180
cl::desc("Save ThinLTO temp files using filenames created by adding "
181
"suffixes to the given file path prefix."),
182
cl::cat(LTOCategory));
183
184
static cl::opt<std::string> ThinLTOGeneratedObjectsDir(
185
"thinlto-save-objects",
186
cl::desc("Save ThinLTO generated object files using filenames created in "
187
"the given directory."),
188
cl::cat(LTOCategory));
189
190
static cl::opt<bool> SaveLinkedModuleFile(
191
"save-linked-module", cl::init(false),
192
cl::desc("Write linked LTO module to file before optimize"),
193
cl::cat(LTOCategory));
194
195
static cl::opt<bool>
196
SaveModuleFile("save-merged-module", cl::init(false),
197
cl::desc("Write merged LTO module to file before CodeGen"),
198
cl::cat(LTOCategory));
199
200
static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
201
cl::desc("<input bitcode files>"),
202
cl::cat(LTOCategory));
203
204
static cl::opt<std::string> OutputFilename("o", cl::init(""),
205
cl::desc("Override output filename"),
206
cl::value_desc("filename"),
207
cl::cat(LTOCategory));
208
209
static cl::list<std::string> ExportedSymbols(
210
"exported-symbol",
211
cl::desc("List of symbols to export from the resulting object file"),
212
cl::cat(LTOCategory));
213
214
static cl::list<std::string>
215
DSOSymbols("dso-symbol",
216
cl::desc("Symbol to put in the symtab in the resulting dso"),
217
cl::cat(LTOCategory));
218
219
static cl::opt<bool> ListSymbolsOnly(
220
"list-symbols-only", cl::init(false),
221
cl::desc("Instead of running LTO, list the symbols in each IR file"),
222
cl::cat(LTOCategory));
223
224
static cl::opt<bool> ListDependentLibrariesOnly(
225
"list-dependent-libraries-only", cl::init(false),
226
cl::desc(
227
"Instead of running LTO, list the dependent libraries in each IR file"),
228
cl::cat(LTOCategory));
229
230
static cl::opt<bool> QueryHasCtorDtor(
231
"query-hasCtorDtor", cl::init(false),
232
cl::desc("Queries LTOModule::hasCtorDtor() on each IR file"));
233
234
static cl::opt<bool>
235
SetMergedModule("set-merged-module", cl::init(false),
236
cl::desc("Use the first input module as the merged module"),
237
cl::cat(LTOCategory));
238
239
static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
240
cl::desc("Number of backend threads"),
241
cl::cat(LTOCategory));
242
243
static cl::opt<bool> RestoreGlobalsLinkage(
244
"restore-linkage", cl::init(false),
245
cl::desc("Restore original linkage of globals prior to CodeGen"),
246
cl::cat(LTOCategory));
247
248
static cl::opt<bool> CheckHasObjC(
249
"check-for-objc", cl::init(false),
250
cl::desc("Only check if the module has objective-C defined in it"),
251
cl::cat(LTOCategory));
252
253
static cl::opt<bool> PrintMachOCPUOnly(
254
"print-macho-cpu-only", cl::init(false),
255
cl::desc("Instead of running LTO, print the mach-o cpu in each IR file"),
256
cl::cat(LTOCategory));
257
258
static cl::opt<bool>
259
DebugPassManager("debug-pass-manager", cl::init(false), cl::Hidden,
260
cl::desc("Print pass management debugging information"),
261
cl::cat(LTOCategory));
262
263
static cl::opt<bool>
264
LTOSaveBeforeOpt("lto-save-before-opt", cl::init(false),
265
cl::desc("Save the IR before running optimizations"));
266
267
static cl::opt<bool> TryUseNewDbgInfoFormat(
268
"try-experimental-debuginfo-iterators",
269
cl::desc("Enable debuginfo iterator positions, if they're built in"),
270
cl::init(false), cl::Hidden);
271
272
extern cl::opt<bool> UseNewDbgInfoFormat;
273
extern cl::opt<cl::boolOrDefault> LoadBitcodeIntoNewDbgInfoFormat;
274
extern cl::opt<cl::boolOrDefault> PreserveInputDbgFormat;
275
276
namespace {
277
278
struct ModuleInfo {
279
BitVector CanBeHidden;
280
};
281
282
} // end anonymous namespace
283
284
static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
285
const char *Msg, void *) {
286
errs() << "llvm-lto: ";
287
switch (Severity) {
288
case LTO_DS_NOTE:
289
errs() << "note: ";
290
break;
291
case LTO_DS_REMARK:
292
errs() << "remark: ";
293
break;
294
case LTO_DS_ERROR:
295
errs() << "error: ";
296
break;
297
case LTO_DS_WARNING:
298
errs() << "warning: ";
299
break;
300
}
301
errs() << Msg << "\n";
302
}
303
304
static std::string CurrentActivity;
305
306
namespace {
307
struct LLVMLTODiagnosticHandler : public DiagnosticHandler {
308
bool handleDiagnostics(const DiagnosticInfo &DI) override {
309
raw_ostream &OS = errs();
310
OS << "llvm-lto: ";
311
switch (DI.getSeverity()) {
312
case DS_Error:
313
OS << "error";
314
break;
315
case DS_Warning:
316
OS << "warning";
317
break;
318
case DS_Remark:
319
OS << "remark";
320
break;
321
case DS_Note:
322
OS << "note";
323
break;
324
}
325
if (!CurrentActivity.empty())
326
OS << ' ' << CurrentActivity;
327
OS << ": ";
328
329
DiagnosticPrinterRawOStream DP(OS);
330
DI.print(DP);
331
OS << '\n';
332
333
if (DI.getSeverity() == DS_Error)
334
exit(1);
335
return true;
336
}
337
};
338
}
339
340
static void error(const Twine &Msg) {
341
errs() << "llvm-lto: " << Msg << '\n';
342
exit(1);
343
}
344
345
static void error(std::error_code EC, const Twine &Prefix) {
346
if (EC)
347
error(Prefix + ": " + EC.message());
348
}
349
350
template <typename T>
351
static void error(const ErrorOr<T> &V, const Twine &Prefix) {
352
error(V.getError(), Prefix);
353
}
354
355
static void maybeVerifyModule(const Module &Mod) {
356
if (!DisableVerify && verifyModule(Mod, &errs()))
357
error("Broken Module");
358
}
359
360
static std::unique_ptr<LTOModule>
361
getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
362
const TargetOptions &Options) {
363
ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
364
MemoryBuffer::getFile(Path);
365
error(BufferOrErr, "error loading file '" + Path + "'");
366
Buffer = std::move(BufferOrErr.get());
367
CurrentActivity = ("loading file '" + Path + "'").str();
368
std::unique_ptr<LLVMContext> Context = std::make_unique<LLVMContext>();
369
Context->setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
370
true);
371
ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
372
std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
373
Options, Path);
374
CurrentActivity = "";
375
maybeVerifyModule((*Ret)->getModule());
376
return std::move(*Ret);
377
}
378
379
/// Print some statistics on the index for each input files.
380
static void printIndexStats() {
381
for (auto &Filename : InputFilenames) {
382
ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
383
std::unique_ptr<ModuleSummaryIndex> Index =
384
ExitOnErr(getModuleSummaryIndexForFile(Filename));
385
// Skip files without a module summary.
386
if (!Index)
387
report_fatal_error(Twine(Filename) + " does not contain an index");
388
389
unsigned Calls = 0, Refs = 0, Functions = 0, Alias = 0, Globals = 0;
390
for (auto &Summaries : *Index) {
391
for (auto &Summary : Summaries.second.SummaryList) {
392
Refs += Summary->refs().size();
393
if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
394
Functions++;
395
Calls += FuncSummary->calls().size();
396
} else if (isa<AliasSummary>(Summary.get()))
397
Alias++;
398
else
399
Globals++;
400
}
401
}
402
outs() << "Index " << Filename << " contains "
403
<< (Alias + Globals + Functions) << " nodes (" << Functions
404
<< " functions, " << Alias << " alias, " << Globals
405
<< " globals) and " << (Calls + Refs) << " edges (" << Refs
406
<< " refs and " << Calls << " calls)\n";
407
}
408
}
409
410
/// Load each IR file and dump certain information based on active flags.
411
///
412
/// The main point here is to provide lit-testable coverage for the LTOModule
413
/// functionality that's exposed by the C API. Moreover, this provides testing
414
/// coverage for modules that have been created in their own contexts.
415
static void testLTOModule(const TargetOptions &Options) {
416
for (auto &Filename : InputFilenames) {
417
std::unique_ptr<MemoryBuffer> Buffer;
418
std::unique_ptr<LTOModule> Module =
419
getLocalLTOModule(Filename, Buffer, Options);
420
421
if (ListSymbolsOnly) {
422
// List the symbols.
423
outs() << Filename << ":\n";
424
for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
425
outs() << Module->getSymbolName(I) << "\n";
426
}
427
if (QueryHasCtorDtor)
428
outs() << Filename
429
<< ": hasCtorDtor = " << (Module->hasCtorDtor() ? "true" : "false")
430
<< "\n";
431
}
432
}
433
434
static std::unique_ptr<MemoryBuffer> loadFile(StringRef Filename) {
435
ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename.str() +
436
"': ");
437
return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
438
}
439
440
static void listDependentLibraries() {
441
for (auto &Filename : InputFilenames) {
442
auto Buffer = loadFile(Filename);
443
std::string E;
444
std::unique_ptr<lto::InputFile> Input(LTOModule::createInputFile(
445
Buffer->getBufferStart(), Buffer->getBufferSize(), Filename.c_str(),
446
E));
447
if (!Input)
448
error(E);
449
450
// List the dependent libraries.
451
outs() << Filename << ":\n";
452
for (size_t I = 0, C = LTOModule::getDependentLibraryCount(Input.get());
453
I != C; ++I) {
454
size_t L = 0;
455
const char *S = LTOModule::getDependentLibrary(Input.get(), I, &L);
456
assert(S);
457
outs() << StringRef(S, L) << "\n";
458
}
459
}
460
}
461
462
static void printMachOCPUOnly() {
463
LLVMContext Context;
464
Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
465
true);
466
TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
467
for (auto &Filename : InputFilenames) {
468
ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
469
LTOModule::createFromFile(Context, Filename, Options);
470
if (!ModuleOrErr)
471
error(ModuleOrErr, "llvm-lto: ");
472
473
Expected<uint32_t> CPUType = (*ModuleOrErr)->getMachOCPUType();
474
Expected<uint32_t> CPUSubType = (*ModuleOrErr)->getMachOCPUSubType();
475
if (!CPUType)
476
error("Error while printing mach-o cputype: " +
477
toString(CPUType.takeError()));
478
if (!CPUSubType)
479
error("Error while printing mach-o cpusubtype: " +
480
toString(CPUSubType.takeError()));
481
outs() << llvm::format("%s:\ncputype: %u\ncpusubtype: %u\n",
482
Filename.c_str(), *CPUType, *CPUSubType);
483
}
484
}
485
486
/// Create a combined index file from the input IR files and write it.
487
///
488
/// This is meant to enable testing of ThinLTO combined index generation,
489
/// currently available via the gold plugin via -thinlto.
490
static void createCombinedModuleSummaryIndex() {
491
ModuleSummaryIndex CombinedIndex(/*HaveGVs=*/false);
492
for (auto &Filename : InputFilenames) {
493
ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
494
std::unique_ptr<MemoryBuffer> MB =
495
ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
496
ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex));
497
}
498
// In order to use this index for testing, specifically import testing, we
499
// need to update any indirect call edges created from SamplePGO, so that they
500
// point to the correct GUIDs.
501
updateIndirectCalls(CombinedIndex);
502
std::error_code EC;
503
assert(!OutputFilename.empty());
504
raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
505
sys::fs::OpenFlags::OF_None);
506
error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
507
writeIndexToFile(CombinedIndex, OS);
508
OS.close();
509
}
510
511
/// Parse the thinlto_prefix_replace option into the \p OldPrefix and
512
/// \p NewPrefix strings, if it was specified.
513
static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
514
std::string &NewPrefix) {
515
assert(ThinLTOPrefixReplace.empty() ||
516
ThinLTOPrefixReplace.find(';') != StringRef::npos);
517
StringRef PrefixReplace = ThinLTOPrefixReplace;
518
std::pair<StringRef, StringRef> Split = PrefixReplace.split(";");
519
OldPrefix = Split.first.str();
520
NewPrefix = Split.second.str();
521
}
522
523
/// Given the original \p Path to an output file, replace any path
524
/// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
525
/// resulting directory if it does not yet exist.
526
static std::string getThinLTOOutputFile(StringRef Path, StringRef OldPrefix,
527
StringRef NewPrefix) {
528
if (OldPrefix.empty() && NewPrefix.empty())
529
return std::string(Path);
530
SmallString<128> NewPath(Path);
531
llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
532
StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
533
if (!ParentPath.empty()) {
534
// Make sure the new directory exists, creating it if necessary.
535
if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
536
error(EC, "error creating the directory '" + ParentPath + "'");
537
}
538
return std::string(NewPath);
539
}
540
541
namespace thinlto {
542
543
std::vector<std::unique_ptr<MemoryBuffer>>
544
loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
545
std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
546
547
for (auto &ModPath : Index.modulePaths()) {
548
const auto &Filename = ModPath.first();
549
std::string CurrentActivity = ("loading file '" + Filename + "'").str();
550
auto InputOrErr = MemoryBuffer::getFile(Filename);
551
error(InputOrErr, "error " + CurrentActivity);
552
InputBuffers.push_back(std::move(*InputOrErr));
553
}
554
return InputBuffers;
555
}
556
557
std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() {
558
if (ThinLTOIndex.empty())
559
report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
560
ExitOnError ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex +
561
"': ");
562
return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex));
563
}
564
565
static std::unique_ptr<lto::InputFile> loadInputFile(MemoryBufferRef Buffer) {
566
ExitOnError ExitOnErr("llvm-lto: error loading input '" +
567
Buffer.getBufferIdentifier().str() + "': ");
568
return ExitOnErr(lto::InputFile::create(Buffer));
569
}
570
571
static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile &File,
572
LLVMContext &CTX) {
573
auto &Mod = File.getSingleBitcodeModule();
574
auto ModuleOrErr = Mod.parseModule(CTX);
575
if (!ModuleOrErr) {
576
handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
577
SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
578
SourceMgr::DK_Error, EIB.message());
579
Err.print("llvm-lto", errs());
580
});
581
report_fatal_error("Can't load module, abort.");
582
}
583
maybeVerifyModule(**ModuleOrErr);
584
if (ThinLTOModuleId.getNumOccurrences()) {
585
if (InputFilenames.size() != 1)
586
report_fatal_error("Can't override the module id for multiple files");
587
(*ModuleOrErr)->setModuleIdentifier(ThinLTOModuleId);
588
}
589
return std::move(*ModuleOrErr);
590
}
591
592
static void writeModuleToFile(Module &TheModule, StringRef Filename) {
593
std::error_code EC;
594
raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::OF_None);
595
error(EC, "error opening the file '" + Filename + "'");
596
maybeVerifyModule(TheModule);
597
WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
598
}
599
600
class ThinLTOProcessing {
601
public:
602
ThinLTOCodeGenerator ThinGenerator;
603
604
ThinLTOProcessing(const TargetOptions &Options) {
605
ThinGenerator.setCodePICModel(codegen::getExplicitRelocModel());
606
ThinGenerator.setTargetOptions(Options);
607
ThinGenerator.setCacheDir(ThinLTOCacheDir);
608
ThinGenerator.setCachePruningInterval(ThinLTOCachePruningInterval);
609
ThinGenerator.setCacheEntryExpiration(ThinLTOCacheEntryExpiration);
610
ThinGenerator.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles);
611
ThinGenerator.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes);
612
ThinGenerator.setFreestanding(EnableFreestanding);
613
ThinGenerator.setDebugPassManager(DebugPassManager);
614
615
// Add all the exported symbols to the table of symbols to preserve.
616
for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
617
ThinGenerator.preserveSymbol(ExportedSymbols[i]);
618
}
619
620
void run() {
621
switch (ThinLTOMode) {
622
case THINLINK:
623
return thinLink();
624
case THINDISTRIBUTE:
625
return distributedIndexes();
626
case THINEMITIMPORTS:
627
return emitImports();
628
case THINPROMOTE:
629
return promote();
630
case THINIMPORT:
631
return import();
632
case THININTERNALIZE:
633
return internalize();
634
case THINOPT:
635
return optimize();
636
case THINCODEGEN:
637
return codegen();
638
case THINALL:
639
return runAll();
640
}
641
}
642
643
private:
644
/// Load the input files, create the combined index, and write it out.
645
void thinLink() {
646
// Perform "ThinLink": just produce the index
647
if (OutputFilename.empty())
648
report_fatal_error(
649
"OutputFilename is necessary to store the combined index.\n");
650
651
LLVMContext Ctx;
652
std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
653
for (unsigned i = 0; i < InputFilenames.size(); ++i) {
654
auto &Filename = InputFilenames[i];
655
std::string CurrentActivity = "loading file '" + Filename + "'";
656
auto InputOrErr = MemoryBuffer::getFile(Filename);
657
error(InputOrErr, "error " + CurrentActivity);
658
InputBuffers.push_back(std::move(*InputOrErr));
659
ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
660
}
661
662
auto CombinedIndex = ThinGenerator.linkCombinedIndex();
663
if (!CombinedIndex)
664
report_fatal_error("ThinLink didn't create an index");
665
std::error_code EC;
666
raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::OF_None);
667
error(EC, "error opening the file '" + OutputFilename + "'");
668
writeIndexToFile(*CombinedIndex, OS);
669
}
670
671
/// Load the combined index from disk, then compute and generate
672
/// individual index files suitable for ThinLTO distributed backend builds
673
/// on the files mentioned on the command line (these must match the index
674
/// content).
675
void distributedIndexes() {
676
if (InputFilenames.size() != 1 && !OutputFilename.empty())
677
report_fatal_error("Can't handle a single output filename and multiple "
678
"input files, do not provide an output filename and "
679
"the output files will be suffixed from the input "
680
"ones.");
681
682
std::string OldPrefix, NewPrefix;
683
getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
684
685
auto Index = loadCombinedIndex();
686
for (auto &Filename : InputFilenames) {
687
LLVMContext Ctx;
688
auto Buffer = loadFile(Filename);
689
auto Input = loadInputFile(Buffer->getMemBufferRef());
690
auto TheModule = loadModuleFromInput(*Input, Ctx);
691
692
// Build a map of module to the GUIDs and summary objects that should
693
// be written to its index.
694
std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
695
GVSummaryPtrSet DecSummaries;
696
ThinGenerator.gatherImportedSummariesForModule(
697
*TheModule, *Index, ModuleToSummariesForIndex, DecSummaries, *Input);
698
699
std::string OutputName = OutputFilename;
700
if (OutputName.empty()) {
701
OutputName = Filename + ".thinlto.bc";
702
}
703
OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
704
std::error_code EC;
705
raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
706
error(EC, "error opening the file '" + OutputName + "'");
707
writeIndexToFile(*Index, OS, &ModuleToSummariesForIndex, &DecSummaries);
708
}
709
}
710
711
/// Load the combined index from disk, compute the imports, and emit
712
/// the import file lists for each module to disk.
713
void emitImports() {
714
if (InputFilenames.size() != 1 && !OutputFilename.empty())
715
report_fatal_error("Can't handle a single output filename and multiple "
716
"input files, do not provide an output filename and "
717
"the output files will be suffixed from the input "
718
"ones.");
719
720
std::string OldPrefix, NewPrefix;
721
getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
722
723
auto Index = loadCombinedIndex();
724
for (auto &Filename : InputFilenames) {
725
LLVMContext Ctx;
726
auto Buffer = loadFile(Filename);
727
auto Input = loadInputFile(Buffer->getMemBufferRef());
728
auto TheModule = loadModuleFromInput(*Input, Ctx);
729
std::string OutputName = OutputFilename;
730
if (OutputName.empty()) {
731
OutputName = Filename + ".imports";
732
}
733
OutputName =
734
getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
735
ThinGenerator.emitImports(*TheModule, OutputName, *Index, *Input);
736
}
737
}
738
739
/// Load the combined index from disk, then load every file referenced by
740
/// the index and add them to the generator, finally perform the promotion
741
/// on the files mentioned on the command line (these must match the index
742
/// content).
743
void promote() {
744
if (InputFilenames.size() != 1 && !OutputFilename.empty())
745
report_fatal_error("Can't handle a single output filename and multiple "
746
"input files, do not provide an output filename and "
747
"the output files will be suffixed from the input "
748
"ones.");
749
750
auto Index = loadCombinedIndex();
751
for (auto &Filename : InputFilenames) {
752
LLVMContext Ctx;
753
auto Buffer = loadFile(Filename);
754
auto Input = loadInputFile(Buffer->getMemBufferRef());
755
auto TheModule = loadModuleFromInput(*Input, Ctx);
756
757
ThinGenerator.promote(*TheModule, *Index, *Input);
758
759
std::string OutputName = OutputFilename;
760
if (OutputName.empty()) {
761
OutputName = Filename + ".thinlto.promoted.bc";
762
}
763
writeModuleToFile(*TheModule, OutputName);
764
}
765
}
766
767
/// Load the combined index from disk, then load every file referenced by
768
/// the index and add them to the generator, then performs the promotion and
769
/// cross module importing on the files mentioned on the command line
770
/// (these must match the index content).
771
void import() {
772
if (InputFilenames.size() != 1 && !OutputFilename.empty())
773
report_fatal_error("Can't handle a single output filename and multiple "
774
"input files, do not provide an output filename and "
775
"the output files will be suffixed from the input "
776
"ones.");
777
778
auto Index = loadCombinedIndex();
779
auto InputBuffers = loadAllFilesForIndex(*Index);
780
for (auto &MemBuffer : InputBuffers)
781
ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
782
MemBuffer->getBuffer());
783
784
for (auto &Filename : InputFilenames) {
785
LLVMContext Ctx;
786
auto Buffer = loadFile(Filename);
787
auto Input = loadInputFile(Buffer->getMemBufferRef());
788
auto TheModule = loadModuleFromInput(*Input, Ctx);
789
790
ThinGenerator.crossModuleImport(*TheModule, *Index, *Input);
791
792
std::string OutputName = OutputFilename;
793
if (OutputName.empty()) {
794
OutputName = Filename + ".thinlto.imported.bc";
795
}
796
writeModuleToFile(*TheModule, OutputName);
797
}
798
}
799
800
void internalize() {
801
if (InputFilenames.size() != 1 && !OutputFilename.empty())
802
report_fatal_error("Can't handle a single output filename and multiple "
803
"input files, do not provide an output filename and "
804
"the output files will be suffixed from the input "
805
"ones.");
806
807
if (ExportedSymbols.empty())
808
errs() << "Warning: -internalize will not perform without "
809
"-exported-symbol\n";
810
811
auto Index = loadCombinedIndex();
812
auto InputBuffers = loadAllFilesForIndex(*Index);
813
for (auto &MemBuffer : InputBuffers)
814
ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
815
MemBuffer->getBuffer());
816
817
for (auto &Filename : InputFilenames) {
818
LLVMContext Ctx;
819
auto Buffer = loadFile(Filename);
820
auto Input = loadInputFile(Buffer->getMemBufferRef());
821
auto TheModule = loadModuleFromInput(*Input, Ctx);
822
823
ThinGenerator.internalize(*TheModule, *Index, *Input);
824
825
std::string OutputName = OutputFilename;
826
if (OutputName.empty()) {
827
OutputName = Filename + ".thinlto.internalized.bc";
828
}
829
writeModuleToFile(*TheModule, OutputName);
830
}
831
}
832
833
void optimize() {
834
if (InputFilenames.size() != 1 && !OutputFilename.empty())
835
report_fatal_error("Can't handle a single output filename and multiple "
836
"input files, do not provide an output filename and "
837
"the output files will be suffixed from the input "
838
"ones.");
839
if (!ThinLTOIndex.empty())
840
errs() << "Warning: -thinlto-index ignored for optimize stage";
841
842
for (auto &Filename : InputFilenames) {
843
LLVMContext Ctx;
844
auto Buffer = loadFile(Filename);
845
auto Input = loadInputFile(Buffer->getMemBufferRef());
846
auto TheModule = loadModuleFromInput(*Input, Ctx);
847
848
ThinGenerator.optimize(*TheModule);
849
850
std::string OutputName = OutputFilename;
851
if (OutputName.empty()) {
852
OutputName = Filename + ".thinlto.imported.bc";
853
}
854
writeModuleToFile(*TheModule, OutputName);
855
}
856
}
857
858
void codegen() {
859
if (InputFilenames.size() != 1 && !OutputFilename.empty())
860
report_fatal_error("Can't handle a single output filename and multiple "
861
"input files, do not provide an output filename and "
862
"the output files will be suffixed from the input "
863
"ones.");
864
if (!ThinLTOIndex.empty())
865
errs() << "Warning: -thinlto-index ignored for codegen stage";
866
867
std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
868
for (auto &Filename : InputFilenames) {
869
LLVMContext Ctx;
870
auto InputOrErr = MemoryBuffer::getFile(Filename);
871
error(InputOrErr, "error " + CurrentActivity);
872
InputBuffers.push_back(std::move(*InputOrErr));
873
ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
874
}
875
ThinGenerator.setCodeGenOnly(true);
876
ThinGenerator.run();
877
for (auto BinName :
878
zip(ThinGenerator.getProducedBinaries(), InputFilenames)) {
879
std::string OutputName = OutputFilename;
880
if (OutputName.empty())
881
OutputName = std::get<1>(BinName) + ".thinlto.o";
882
else if (OutputName == "-") {
883
outs() << std::get<0>(BinName)->getBuffer();
884
return;
885
}
886
887
std::error_code EC;
888
raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
889
error(EC, "error opening the file '" + OutputName + "'");
890
OS << std::get<0>(BinName)->getBuffer();
891
}
892
}
893
894
/// Full ThinLTO process
895
void runAll() {
896
if (!OutputFilename.empty())
897
report_fatal_error("Do not provide an output filename for ThinLTO "
898
" processing, the output files will be suffixed from "
899
"the input ones.");
900
901
if (!ThinLTOIndex.empty())
902
errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
903
904
LLVMContext Ctx;
905
std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
906
for (unsigned i = 0; i < InputFilenames.size(); ++i) {
907
auto &Filename = InputFilenames[i];
908
std::string CurrentActivity = "loading file '" + Filename + "'";
909
auto InputOrErr = MemoryBuffer::getFile(Filename);
910
error(InputOrErr, "error " + CurrentActivity);
911
InputBuffers.push_back(std::move(*InputOrErr));
912
ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
913
}
914
915
if (!ThinLTOSaveTempsPrefix.empty())
916
ThinGenerator.setSaveTempsDir(ThinLTOSaveTempsPrefix);
917
918
if (!ThinLTOGeneratedObjectsDir.empty()) {
919
ThinGenerator.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir);
920
ThinGenerator.run();
921
return;
922
}
923
924
ThinGenerator.run();
925
926
auto &Binaries = ThinGenerator.getProducedBinaries();
927
if (Binaries.size() != InputFilenames.size())
928
report_fatal_error("Number of output objects does not match the number "
929
"of inputs");
930
931
for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
932
auto OutputName = InputFilenames[BufID] + ".thinlto.o";
933
std::error_code EC;
934
raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
935
error(EC, "error opening the file '" + OutputName + "'");
936
OS << Binaries[BufID]->getBuffer();
937
}
938
}
939
940
/// Load the combined index from disk, then load every file referenced by
941
};
942
943
} // end namespace thinlto
944
945
int main(int argc, char **argv) {
946
InitLLVM X(argc, argv);
947
cl::HideUnrelatedOptions({&LTOCategory, &getColorCategory()});
948
cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
949
// Load bitcode into the new debug info format by default.
950
if (LoadBitcodeIntoNewDbgInfoFormat == cl::boolOrDefault::BOU_UNSET)
951
LoadBitcodeIntoNewDbgInfoFormat = cl::boolOrDefault::BOU_TRUE;
952
953
// RemoveDIs debug-info transition: tests may request that we /try/ to use the
954
// new debug-info format.
955
if (TryUseNewDbgInfoFormat) {
956
// Turn the new debug-info format on.
957
UseNewDbgInfoFormat = true;
958
}
959
// Since llvm-lto collects multiple IR modules together, for simplicity's sake
960
// we disable the "PreserveInputDbgFormat" flag to enforce a single debug info
961
// format.
962
PreserveInputDbgFormat = cl::boolOrDefault::BOU_FALSE;
963
964
if (OptLevel < '0' || OptLevel > '3')
965
error("optimization level must be between 0 and 3");
966
967
// Initialize the configured targets.
968
InitializeAllTargets();
969
InitializeAllTargetMCs();
970
InitializeAllAsmPrinters();
971
InitializeAllAsmParsers();
972
973
// set up the TargetOptions for the machine
974
TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
975
976
if (ListSymbolsOnly || QueryHasCtorDtor) {
977
testLTOModule(Options);
978
return 0;
979
}
980
981
if (ListDependentLibrariesOnly) {
982
listDependentLibraries();
983
return 0;
984
}
985
986
if (IndexStats) {
987
printIndexStats();
988
return 0;
989
}
990
991
if (CheckHasObjC) {
992
for (auto &Filename : InputFilenames) {
993
ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
994
Filename + "': ");
995
std::unique_ptr<MemoryBuffer> BufferOrErr =
996
ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename)));
997
auto Buffer = std::move(BufferOrErr.get());
998
if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer)))
999
outs() << "Bitcode " << Filename << " contains ObjC\n";
1000
else
1001
outs() << "Bitcode " << Filename << " does not contain ObjC\n";
1002
}
1003
return 0;
1004
}
1005
1006
if (PrintMachOCPUOnly) {
1007
printMachOCPUOnly();
1008
return 0;
1009
}
1010
1011
if (ThinLTOMode.getNumOccurrences()) {
1012
if (ThinLTOMode.getNumOccurrences() > 1)
1013
report_fatal_error("You can't specify more than one -thinlto-action");
1014
thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
1015
ThinLTOProcessor.run();
1016
return 0;
1017
}
1018
1019
if (ThinLTO) {
1020
createCombinedModuleSummaryIndex();
1021
return 0;
1022
}
1023
1024
unsigned BaseArg = 0;
1025
1026
LLVMContext Context;
1027
Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
1028
true);
1029
1030
LTOCodeGenerator CodeGen(Context);
1031
CodeGen.setDisableVerify(DisableVerify);
1032
1033
if (UseDiagnosticHandler)
1034
CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
1035
1036
CodeGen.setCodePICModel(codegen::getExplicitRelocModel());
1037
CodeGen.setFreestanding(EnableFreestanding);
1038
CodeGen.setDebugPassManager(DebugPassManager);
1039
1040
CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
1041
CodeGen.setTargetOptions(Options);
1042
CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
1043
1044
StringSet<MallocAllocator> DSOSymbolsSet;
1045
for (unsigned i = 0; i < DSOSymbols.size(); ++i)
1046
DSOSymbolsSet.insert(DSOSymbols[i]);
1047
1048
std::vector<std::string> KeptDSOSyms;
1049
1050
for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
1051
CurrentActivity = "loading file '" + InputFilenames[i] + "'";
1052
ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
1053
LTOModule::createFromFile(Context, InputFilenames[i], Options);
1054
std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
1055
CurrentActivity = "";
1056
1057
unsigned NumSyms = Module->getSymbolCount();
1058
for (unsigned I = 0; I < NumSyms; ++I) {
1059
StringRef Name = Module->getSymbolName(I);
1060
if (!DSOSymbolsSet.count(Name))
1061
continue;
1062
lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
1063
unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
1064
if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
1065
KeptDSOSyms.push_back(std::string(Name));
1066
}
1067
1068
// We use the first input module as the destination module when
1069
// SetMergedModule is true.
1070
if (SetMergedModule && i == BaseArg) {
1071
// Transfer ownership to the code generator.
1072
CodeGen.setModule(std::move(Module));
1073
} else if (!CodeGen.addModule(Module.get())) {
1074
// Print a message here so that we know addModule() did not abort.
1075
error("error adding file '" + InputFilenames[i] + "'");
1076
}
1077
}
1078
1079
// Add all the exported symbols to the table of symbols to preserve.
1080
for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
1081
CodeGen.addMustPreserveSymbol(ExportedSymbols[i]);
1082
1083
// Add all the dso symbols to the table of symbols to expose.
1084
for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
1085
CodeGen.addMustPreserveSymbol(KeptDSOSyms[i]);
1086
1087
// Set cpu and attrs strings for the default target/subtarget.
1088
CodeGen.setCpu(codegen::getMCPU());
1089
1090
CodeGen.setOptLevel(OptLevel - '0');
1091
CodeGen.setAttrs(codegen::getMAttrs());
1092
1093
if (auto FT = codegen::getExplicitFileType())
1094
CodeGen.setFileType(*FT);
1095
1096
if (!OutputFilename.empty()) {
1097
if (LTOSaveBeforeOpt)
1098
CodeGen.setSaveIRBeforeOptPath(OutputFilename + ".0.preopt.bc");
1099
1100
if (SaveLinkedModuleFile) {
1101
std::string ModuleFilename = OutputFilename;
1102
ModuleFilename += ".linked.bc";
1103
std::string ErrMsg;
1104
1105
if (!CodeGen.writeMergedModules(ModuleFilename))
1106
error("writing linked module failed.");
1107
}
1108
1109
if (!CodeGen.optimize()) {
1110
// Diagnostic messages should have been printed by the handler.
1111
error("error optimizing the code");
1112
}
1113
1114
if (SaveModuleFile) {
1115
std::string ModuleFilename = OutputFilename;
1116
ModuleFilename += ".merged.bc";
1117
std::string ErrMsg;
1118
1119
if (!CodeGen.writeMergedModules(ModuleFilename))
1120
error("writing merged module failed.");
1121
}
1122
1123
auto AddStream =
1124
[&](size_t Task,
1125
const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
1126
std::string PartFilename = OutputFilename;
1127
if (Parallelism != 1)
1128
PartFilename += "." + utostr(Task);
1129
1130
std::error_code EC;
1131
auto S =
1132
std::make_unique<raw_fd_ostream>(PartFilename, EC, sys::fs::OF_None);
1133
if (EC)
1134
error("error opening the file '" + PartFilename + "': " + EC.message());
1135
return std::make_unique<CachedFileStream>(std::move(S));
1136
};
1137
1138
if (!CodeGen.compileOptimized(AddStream, Parallelism))
1139
// Diagnostic messages should have been printed by the handler.
1140
error("error compiling the code");
1141
1142
} else {
1143
if (Parallelism != 1)
1144
error("-j must be specified together with -o");
1145
1146
if (SaveModuleFile)
1147
error(": -save-merged-module must be specified with -o");
1148
1149
const char *OutputName = nullptr;
1150
if (!CodeGen.compile_to_file(&OutputName))
1151
error("error compiling the code");
1152
// Diagnostic messages should have been printed by the handler.
1153
1154
outs() << "Wrote native object file '" << OutputName << "'\n";
1155
}
1156
1157
return 0;
1158
}
1159
1160