1 //===- llvm-lto: a simple command-line program to link modules with LTO ---===//
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
7 //===----------------------------------------------------------------------===//
9 // This program takes in a list of bitcode files, links them, performs link-time
10 // optimization, and outputs an object file.
12 //===----------------------------------------------------------------------===//
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"
59 #include <system_error>
66 static codegen::RegisterCodeGenFlags CGF
;
68 static cl::OptionCategory
LTOCategory("LTO Options");
72 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
74 cl::Prefix
, cl::init('2'), cl::cat(LTOCategory
));
77 IndexStats("thinlto-index-stats",
78 cl::desc("Print statistic for the index in every input files"),
79 cl::init(false), cl::cat(LTOCategory
));
81 static cl::opt
<bool> DisableVerify(
82 "disable-verify", cl::init(false),
83 cl::desc("Do not run the verifier during the optimization pipeline"),
84 cl::cat(LTOCategory
));
86 static cl::opt
<bool> EnableFreestanding(
87 "lto-freestanding", cl::init(false),
88 cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"),
89 cl::cat(LTOCategory
));
91 static cl::opt
<bool> UseDiagnosticHandler(
92 "use-diagnostic-handler", cl::init(false),
93 cl::desc("Use a diagnostic handler to test the handler interface"),
94 cl::cat(LTOCategory
));
97 ThinLTO("thinlto", cl::init(false),
98 cl::desc("Only write combined global index for ThinLTO backends"),
99 cl::cat(LTOCategory
));
113 cl::opt
<ThinLTOModes
> ThinLTOMode(
114 "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
117 THINLINK
, "thinlink",
118 "ThinLink: produces the index by linking only the summaries."),
119 clEnumValN(THINDISTRIBUTE
, "distributedindexes",
120 "Produces individual indexes for distributed backends."),
121 clEnumValN(THINEMITIMPORTS
, "emitimports",
122 "Emit imports files for distributed backends."),
123 clEnumValN(THINPROMOTE
, "promote",
124 "Perform pre-import promotion (requires -thinlto-index)."),
125 clEnumValN(THINIMPORT
, "import",
126 "Perform both promotion and "
127 "cross-module importing (requires "
129 clEnumValN(THININTERNALIZE
, "internalize",
130 "Perform internalization driven by -exported-symbol "
131 "(requires -thinlto-index)."),
132 clEnumValN(THINOPT
, "optimize", "Perform ThinLTO optimizations."),
133 clEnumValN(THINCODEGEN
, "codegen", "CodeGen (expected to match llc)"),
134 clEnumValN(THINALL
, "run", "Perform ThinLTO end-to-end")),
135 cl::cat(LTOCategory
));
137 static cl::opt
<std::string
>
138 ThinLTOIndex("thinlto-index",
139 cl::desc("Provide the index produced by a ThinLink, required "
140 "to perform the promotion and/or importing."),
141 cl::cat(LTOCategory
));
143 static cl::opt
<std::string
> ThinLTOPrefixReplace(
144 "thinlto-prefix-replace",
145 cl::desc("Control where files for distributed backends are "
146 "created. Expects 'oldprefix;newprefix' and if path "
147 "prefix of output file is oldprefix it will be "
148 "replaced with newprefix."),
149 cl::cat(LTOCategory
));
151 static cl::opt
<std::string
> ThinLTOModuleId(
153 cl::desc("For the module ID for the file to process, useful to "
154 "match what is in the index."),
155 cl::cat(LTOCategory
));
157 static cl::opt
<std::string
> ThinLTOCacheDir("thinlto-cache-dir",
158 cl::desc("Enable ThinLTO caching."),
159 cl::cat(LTOCategory
));
161 static cl::opt
<int> ThinLTOCachePruningInterval(
162 "thinlto-cache-pruning-interval", cl::init(1200),
163 cl::desc("Set ThinLTO cache pruning interval."), cl::cat(LTOCategory
));
165 static cl::opt
<uint64_t> ThinLTOCacheMaxSizeBytes(
166 "thinlto-cache-max-size-bytes",
167 cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."),
168 cl::cat(LTOCategory
));
170 static cl::opt
<int> ThinLTOCacheMaxSizeFiles(
171 "thinlto-cache-max-size-files", cl::init(1000000),
172 cl::desc("Set ThinLTO cache pruning directory maximum number of files."),
173 cl::cat(LTOCategory
));
175 static cl::opt
<unsigned> ThinLTOCacheEntryExpiration(
176 "thinlto-cache-entry-expiration", cl::init(604800) /* 1w */,
177 cl::desc("Set ThinLTO cache entry expiration time."), cl::cat(LTOCategory
));
179 static cl::opt
<std::string
> ThinLTOSaveTempsPrefix(
180 "thinlto-save-temps",
181 cl::desc("Save ThinLTO temp files using filenames created by adding "
182 "suffixes to the given file path prefix."),
183 cl::cat(LTOCategory
));
185 static cl::opt
<std::string
> ThinLTOGeneratedObjectsDir(
186 "thinlto-save-objects",
187 cl::desc("Save ThinLTO generated object files using filenames created in "
188 "the given directory."),
189 cl::cat(LTOCategory
));
191 static cl::opt
<bool> SaveLinkedModuleFile(
192 "save-linked-module", cl::init(false),
193 cl::desc("Write linked LTO module to file before optimize"),
194 cl::cat(LTOCategory
));
197 SaveModuleFile("save-merged-module", cl::init(false),
198 cl::desc("Write merged LTO module to file before CodeGen"),
199 cl::cat(LTOCategory
));
201 static cl::list
<std::string
> InputFilenames(cl::Positional
, cl::OneOrMore
,
202 cl::desc("<input bitcode files>"),
203 cl::cat(LTOCategory
));
205 static cl::opt
<std::string
> OutputFilename("o", cl::init(""),
206 cl::desc("Override output filename"),
207 cl::value_desc("filename"),
208 cl::cat(LTOCategory
));
210 static cl::list
<std::string
> ExportedSymbols(
212 cl::desc("List of symbols to export from the resulting object file"),
213 cl::cat(LTOCategory
));
215 static cl::list
<std::string
>
216 DSOSymbols("dso-symbol",
217 cl::desc("Symbol to put in the symtab in the resulting dso"),
218 cl::cat(LTOCategory
));
220 static cl::opt
<bool> ListSymbolsOnly(
221 "list-symbols-only", cl::init(false),
222 cl::desc("Instead of running LTO, list the symbols in each IR file"),
223 cl::cat(LTOCategory
));
225 static cl::opt
<bool> ListDependentLibrariesOnly(
226 "list-dependent-libraries-only", cl::init(false),
228 "Instead of running LTO, list the dependent libraries in each IR file"),
229 cl::cat(LTOCategory
));
231 static cl::opt
<bool> QueryHasCtorDtor(
232 "query-hasCtorDtor", cl::init(false),
233 cl::desc("Queries LTOModule::hasCtorDtor() on each IR file"));
236 SetMergedModule("set-merged-module", cl::init(false),
237 cl::desc("Use the first input module as the merged module"),
238 cl::cat(LTOCategory
));
240 static cl::opt
<unsigned> Parallelism("j", cl::Prefix
, cl::init(1),
241 cl::desc("Number of backend threads"),
242 cl::cat(LTOCategory
));
244 static cl::opt
<bool> RestoreGlobalsLinkage(
245 "restore-linkage", cl::init(false),
246 cl::desc("Restore original linkage of globals prior to CodeGen"),
247 cl::cat(LTOCategory
));
249 static cl::opt
<bool> CheckHasObjC(
250 "check-for-objc", cl::init(false),
251 cl::desc("Only check if the module has objective-C defined in it"),
252 cl::cat(LTOCategory
));
254 static cl::opt
<bool> PrintMachOCPUOnly(
255 "print-macho-cpu-only", cl::init(false),
256 cl::desc("Instead of running LTO, print the mach-o cpu in each IR file"),
257 cl::cat(LTOCategory
));
260 DebugPassManager("debug-pass-manager", cl::init(false), cl::Hidden
,
261 cl::desc("Print pass management debugging information"),
262 cl::cat(LTOCategory
));
265 LTOSaveBeforeOpt("lto-save-before-opt", cl::init(false),
266 cl::desc("Save the IR before running optimizations"));
271 BitVector CanBeHidden
;
274 } // end anonymous namespace
276 static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity
,
277 const char *Msg
, void *) {
278 errs() << "llvm-lto: ";
284 errs() << "remark: ";
290 errs() << "warning: ";
293 errs() << Msg
<< "\n";
296 static std::string CurrentActivity
;
299 struct LLVMLTODiagnosticHandler
: public DiagnosticHandler
{
300 bool handleDiagnostics(const DiagnosticInfo
&DI
) override
{
301 raw_ostream
&OS
= errs();
303 switch (DI
.getSeverity()) {
317 if (!CurrentActivity
.empty())
318 OS
<< ' ' << CurrentActivity
;
321 DiagnosticPrinterRawOStream
DP(OS
);
325 if (DI
.getSeverity() == DS_Error
)
332 static void error(const Twine
&Msg
) {
333 errs() << "llvm-lto: " << Msg
<< '\n';
337 static void error(std::error_code EC
, const Twine
&Prefix
) {
339 error(Prefix
+ ": " + EC
.message());
342 template <typename T
>
343 static void error(const ErrorOr
<T
> &V
, const Twine
&Prefix
) {
344 error(V
.getError(), Prefix
);
347 static void maybeVerifyModule(const Module
&Mod
) {
348 if (!DisableVerify
&& verifyModule(Mod
, &errs()))
349 error("Broken Module");
352 static std::unique_ptr
<LTOModule
>
353 getLocalLTOModule(StringRef Path
, std::unique_ptr
<MemoryBuffer
> &Buffer
,
354 const TargetOptions
&Options
) {
355 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> BufferOrErr
=
356 MemoryBuffer::getFile(Path
);
357 error(BufferOrErr
, "error loading file '" + Path
+ "'");
358 Buffer
= std::move(BufferOrErr
.get());
359 CurrentActivity
= ("loading file '" + Path
+ "'").str();
360 std::unique_ptr
<LLVMContext
> Context
= std::make_unique
<LLVMContext
>();
361 Context
->setDiagnosticHandler(std::make_unique
<LLVMLTODiagnosticHandler
>(),
363 ErrorOr
<std::unique_ptr
<LTOModule
>> Ret
= LTOModule::createInLocalContext(
364 std::move(Context
), Buffer
->getBufferStart(), Buffer
->getBufferSize(),
366 CurrentActivity
= "";
367 maybeVerifyModule((*Ret
)->getModule());
368 return std::move(*Ret
);
371 /// Print some statistics on the index for each input files.
372 static void printIndexStats() {
373 for (auto &Filename
: InputFilenames
) {
374 ExitOnError
ExitOnErr("llvm-lto: error loading file '" + Filename
+ "': ");
375 std::unique_ptr
<ModuleSummaryIndex
> Index
=
376 ExitOnErr(getModuleSummaryIndexForFile(Filename
));
377 // Skip files without a module summary.
379 report_fatal_error(Twine(Filename
) + " does not contain an index");
381 unsigned Calls
= 0, Refs
= 0, Functions
= 0, Alias
= 0, Globals
= 0;
382 for (auto &Summaries
: *Index
) {
383 for (auto &Summary
: Summaries
.second
.SummaryList
) {
384 Refs
+= Summary
->refs().size();
385 if (auto *FuncSummary
= dyn_cast
<FunctionSummary
>(Summary
.get())) {
387 Calls
+= FuncSummary
->calls().size();
388 } else if (isa
<AliasSummary
>(Summary
.get()))
394 outs() << "Index " << Filename
<< " contains "
395 << (Alias
+ Globals
+ Functions
) << " nodes (" << Functions
396 << " functions, " << Alias
<< " alias, " << Globals
397 << " globals) and " << (Calls
+ Refs
) << " edges (" << Refs
398 << " refs and " << Calls
<< " calls)\n";
402 /// Load each IR file and dump certain information based on active flags.
404 /// The main point here is to provide lit-testable coverage for the LTOModule
405 /// functionality that's exposed by the C API. Moreover, this provides testing
406 /// coverage for modules that have been created in their own contexts.
407 static void testLTOModule(const TargetOptions
&Options
) {
408 for (auto &Filename
: InputFilenames
) {
409 std::unique_ptr
<MemoryBuffer
> Buffer
;
410 std::unique_ptr
<LTOModule
> Module
=
411 getLocalLTOModule(Filename
, Buffer
, Options
);
413 if (ListSymbolsOnly
) {
415 outs() << Filename
<< ":\n";
416 for (int I
= 0, E
= Module
->getSymbolCount(); I
!= E
; ++I
)
417 outs() << Module
->getSymbolName(I
) << "\n";
419 if (QueryHasCtorDtor
)
421 << ": hasCtorDtor = " << (Module
->hasCtorDtor() ? "true" : "false")
426 static std::unique_ptr
<MemoryBuffer
> loadFile(StringRef Filename
) {
427 ExitOnError
ExitOnErr("llvm-lto: error loading file '" + Filename
.str() +
429 return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename
)));
432 static void listDependentLibraries() {
433 for (auto &Filename
: InputFilenames
) {
434 auto Buffer
= loadFile(Filename
);
436 std::unique_ptr
<lto::InputFile
> Input(LTOModule::createInputFile(
437 Buffer
->getBufferStart(), Buffer
->getBufferSize(), Filename
.c_str(),
442 // List the dependent libraries.
443 outs() << Filename
<< ":\n";
444 for (size_t I
= 0, C
= LTOModule::getDependentLibraryCount(Input
.get());
447 const char *S
= LTOModule::getDependentLibrary(Input
.get(), I
, &L
);
449 outs() << StringRef(S
, L
) << "\n";
454 static void printMachOCPUOnly() {
456 Context
.setDiagnosticHandler(std::make_unique
<LLVMLTODiagnosticHandler
>(),
458 TargetOptions Options
= codegen::InitTargetOptionsFromCodeGenFlags(Triple());
459 for (auto &Filename
: InputFilenames
) {
460 ErrorOr
<std::unique_ptr
<LTOModule
>> ModuleOrErr
=
461 LTOModule::createFromFile(Context
, Filename
, Options
);
463 error(ModuleOrErr
, "llvm-lto: ");
465 Expected
<uint32_t> CPUType
= (*ModuleOrErr
)->getMachOCPUType();
466 Expected
<uint32_t> CPUSubType
= (*ModuleOrErr
)->getMachOCPUSubType();
468 error("Error while printing mach-o cputype: " +
469 toString(CPUType
.takeError()));
471 error("Error while printing mach-o cpusubtype: " +
472 toString(CPUSubType
.takeError()));
473 outs() << llvm::format("%s:\ncputype: %u\ncpusubtype: %u\n",
474 Filename
.c_str(), *CPUType
, *CPUSubType
);
478 /// Create a combined index file from the input IR files and write it.
480 /// This is meant to enable testing of ThinLTO combined index generation,
481 /// currently available via the gold plugin via -thinlto.
482 static void createCombinedModuleSummaryIndex() {
483 ModuleSummaryIndex
CombinedIndex(/*HaveGVs=*/false);
484 uint64_t NextModuleId
= 0;
485 for (auto &Filename
: InputFilenames
) {
486 ExitOnError
ExitOnErr("llvm-lto: error loading file '" + Filename
+ "': ");
487 std::unique_ptr
<MemoryBuffer
> MB
=
488 ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename
)));
489 ExitOnErr(readModuleSummaryIndex(*MB
, CombinedIndex
, NextModuleId
++));
491 // In order to use this index for testing, specifically import testing, we
492 // need to update any indirect call edges created from SamplePGO, so that they
493 // point to the correct GUIDs.
494 updateIndirectCalls(CombinedIndex
);
496 assert(!OutputFilename
.empty());
497 raw_fd_ostream
OS(OutputFilename
+ ".thinlto.bc", EC
,
498 sys::fs::OpenFlags::OF_None
);
499 error(EC
, "error opening the file '" + OutputFilename
+ ".thinlto.bc'");
500 writeIndexToFile(CombinedIndex
, OS
);
504 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
505 /// \p NewPrefix strings, if it was specified.
506 static void getThinLTOOldAndNewPrefix(std::string
&OldPrefix
,
507 std::string
&NewPrefix
) {
508 assert(ThinLTOPrefixReplace
.empty() ||
509 ThinLTOPrefixReplace
.find(';') != StringRef::npos
);
510 StringRef PrefixReplace
= ThinLTOPrefixReplace
;
511 std::pair
<StringRef
, StringRef
> Split
= PrefixReplace
.split(";");
512 OldPrefix
= Split
.first
.str();
513 NewPrefix
= Split
.second
.str();
516 /// Given the original \p Path to an output file, replace any path
517 /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
518 /// resulting directory if it does not yet exist.
519 static std::string
getThinLTOOutputFile(const std::string
&Path
,
520 const std::string
&OldPrefix
,
521 const std::string
&NewPrefix
) {
522 if (OldPrefix
.empty() && NewPrefix
.empty())
524 SmallString
<128> NewPath(Path
);
525 llvm::sys::path::replace_path_prefix(NewPath
, OldPrefix
, NewPrefix
);
526 StringRef ParentPath
= llvm::sys::path::parent_path(NewPath
.str());
527 if (!ParentPath
.empty()) {
528 // Make sure the new directory exists, creating it if necessary.
529 if (std::error_code EC
= llvm::sys::fs::create_directories(ParentPath
))
530 error(EC
, "error creating the directory '" + ParentPath
+ "'");
532 return std::string(NewPath
.str());
537 std::vector
<std::unique_ptr
<MemoryBuffer
>>
538 loadAllFilesForIndex(const ModuleSummaryIndex
&Index
) {
539 std::vector
<std::unique_ptr
<MemoryBuffer
>> InputBuffers
;
541 for (auto &ModPath
: Index
.modulePaths()) {
542 const auto &Filename
= ModPath
.first();
543 std::string CurrentActivity
= ("loading file '" + Filename
+ "'").str();
544 auto InputOrErr
= MemoryBuffer::getFile(Filename
);
545 error(InputOrErr
, "error " + CurrentActivity
);
546 InputBuffers
.push_back(std::move(*InputOrErr
));
551 std::unique_ptr
<ModuleSummaryIndex
> loadCombinedIndex() {
552 if (ThinLTOIndex
.empty())
553 report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
554 ExitOnError
ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex
+
556 return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex
));
559 static std::unique_ptr
<lto::InputFile
> loadInputFile(MemoryBufferRef Buffer
) {
560 ExitOnError
ExitOnErr("llvm-lto: error loading input '" +
561 Buffer
.getBufferIdentifier().str() + "': ");
562 return ExitOnErr(lto::InputFile::create(Buffer
));
565 static std::unique_ptr
<Module
> loadModuleFromInput(lto::InputFile
&File
,
567 auto &Mod
= File
.getSingleBitcodeModule();
568 auto ModuleOrErr
= Mod
.parseModule(CTX
);
570 handleAllErrors(ModuleOrErr
.takeError(), [&](ErrorInfoBase
&EIB
) {
571 SMDiagnostic Err
= SMDiagnostic(Mod
.getModuleIdentifier(),
572 SourceMgr::DK_Error
, EIB
.message());
573 Err
.print("llvm-lto", errs());
575 report_fatal_error("Can't load module, abort.");
577 maybeVerifyModule(**ModuleOrErr
);
578 if (ThinLTOModuleId
.getNumOccurrences()) {
579 if (InputFilenames
.size() != 1)
580 report_fatal_error("Can't override the module id for multiple files");
581 (*ModuleOrErr
)->setModuleIdentifier(ThinLTOModuleId
);
583 return std::move(*ModuleOrErr
);
586 static void writeModuleToFile(Module
&TheModule
, StringRef Filename
) {
588 raw_fd_ostream
OS(Filename
, EC
, sys::fs::OpenFlags::OF_None
);
589 error(EC
, "error opening the file '" + Filename
+ "'");
590 maybeVerifyModule(TheModule
);
591 WriteBitcodeToFile(TheModule
, OS
, /* ShouldPreserveUseListOrder */ true);
594 class ThinLTOProcessing
{
596 ThinLTOCodeGenerator ThinGenerator
;
598 ThinLTOProcessing(const TargetOptions
&Options
) {
599 ThinGenerator
.setCodePICModel(codegen::getExplicitRelocModel());
600 ThinGenerator
.setTargetOptions(Options
);
601 ThinGenerator
.setCacheDir(ThinLTOCacheDir
);
602 ThinGenerator
.setCachePruningInterval(ThinLTOCachePruningInterval
);
603 ThinGenerator
.setCacheEntryExpiration(ThinLTOCacheEntryExpiration
);
604 ThinGenerator
.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles
);
605 ThinGenerator
.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes
);
606 ThinGenerator
.setFreestanding(EnableFreestanding
);
607 ThinGenerator
.setDebugPassManager(DebugPassManager
);
609 // Add all the exported symbols to the table of symbols to preserve.
610 for (unsigned i
= 0; i
< ExportedSymbols
.size(); ++i
)
611 ThinGenerator
.preserveSymbol(ExportedSymbols
[i
]);
615 switch (ThinLTOMode
) {
619 return distributedIndexes();
620 case THINEMITIMPORTS
:
621 return emitImports();
626 case THININTERNALIZE
:
627 return internalize();
638 /// Load the input files, create the combined index, and write it out.
640 // Perform "ThinLink": just produce the index
641 if (OutputFilename
.empty())
643 "OutputFilename is necessary to store the combined index.\n");
646 std::vector
<std::unique_ptr
<MemoryBuffer
>> InputBuffers
;
647 for (unsigned i
= 0; i
< InputFilenames
.size(); ++i
) {
648 auto &Filename
= InputFilenames
[i
];
649 std::string CurrentActivity
= "loading file '" + Filename
+ "'";
650 auto InputOrErr
= MemoryBuffer::getFile(Filename
);
651 error(InputOrErr
, "error " + CurrentActivity
);
652 InputBuffers
.push_back(std::move(*InputOrErr
));
653 ThinGenerator
.addModule(Filename
, InputBuffers
.back()->getBuffer());
656 auto CombinedIndex
= ThinGenerator
.linkCombinedIndex();
658 report_fatal_error("ThinLink didn't create an index");
660 raw_fd_ostream
OS(OutputFilename
, EC
, sys::fs::OpenFlags::OF_None
);
661 error(EC
, "error opening the file '" + OutputFilename
+ "'");
662 writeIndexToFile(*CombinedIndex
, OS
);
665 /// Load the combined index from disk, then compute and generate
666 /// individual index files suitable for ThinLTO distributed backend builds
667 /// on the files mentioned on the command line (these must match the index
669 void distributedIndexes() {
670 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
671 report_fatal_error("Can't handle a single output filename and multiple "
672 "input files, do not provide an output filename and "
673 "the output files will be suffixed from the input "
676 std::string OldPrefix
, NewPrefix
;
677 getThinLTOOldAndNewPrefix(OldPrefix
, NewPrefix
);
679 auto Index
= loadCombinedIndex();
680 for (auto &Filename
: InputFilenames
) {
682 auto Buffer
= loadFile(Filename
);
683 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
684 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
686 // Build a map of module to the GUIDs and summary objects that should
687 // be written to its index.
688 std::map
<std::string
, GVSummaryMapTy
> ModuleToSummariesForIndex
;
689 ThinGenerator
.gatherImportedSummariesForModule(
690 *TheModule
, *Index
, ModuleToSummariesForIndex
, *Input
);
692 std::string OutputName
= OutputFilename
;
693 if (OutputName
.empty()) {
694 OutputName
= Filename
+ ".thinlto.bc";
696 OutputName
= getThinLTOOutputFile(OutputName
, OldPrefix
, NewPrefix
);
698 raw_fd_ostream
OS(OutputName
, EC
, sys::fs::OpenFlags::OF_None
);
699 error(EC
, "error opening the file '" + OutputName
+ "'");
700 writeIndexToFile(*Index
, OS
, &ModuleToSummariesForIndex
);
704 /// Load the combined index from disk, compute the imports, and emit
705 /// the import file lists for each module to disk.
707 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
708 report_fatal_error("Can't handle a single output filename and multiple "
709 "input files, do not provide an output filename and "
710 "the output files will be suffixed from the input "
713 std::string OldPrefix
, NewPrefix
;
714 getThinLTOOldAndNewPrefix(OldPrefix
, NewPrefix
);
716 auto Index
= loadCombinedIndex();
717 for (auto &Filename
: InputFilenames
) {
719 auto Buffer
= loadFile(Filename
);
720 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
721 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
722 std::string OutputName
= OutputFilename
;
723 if (OutputName
.empty()) {
724 OutputName
= Filename
+ ".imports";
727 getThinLTOOutputFile(OutputName
, OldPrefix
, NewPrefix
);
728 ThinGenerator
.emitImports(*TheModule
, OutputName
, *Index
, *Input
);
732 /// Load the combined index from disk, then load every file referenced by
733 /// the index and add them to the generator, finally perform the promotion
734 /// on the files mentioned on the command line (these must match the index
737 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
738 report_fatal_error("Can't handle a single output filename and multiple "
739 "input files, do not provide an output filename and "
740 "the output files will be suffixed from the input "
743 auto Index
= loadCombinedIndex();
744 for (auto &Filename
: InputFilenames
) {
746 auto Buffer
= loadFile(Filename
);
747 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
748 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
750 ThinGenerator
.promote(*TheModule
, *Index
, *Input
);
752 std::string OutputName
= OutputFilename
;
753 if (OutputName
.empty()) {
754 OutputName
= Filename
+ ".thinlto.promoted.bc";
756 writeModuleToFile(*TheModule
, OutputName
);
760 /// Load the combined index from disk, then load every file referenced by
761 /// the index and add them to the generator, then performs the promotion and
762 /// cross module importing on the files mentioned on the command line
763 /// (these must match the index content).
765 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
766 report_fatal_error("Can't handle a single output filename and multiple "
767 "input files, do not provide an output filename and "
768 "the output files will be suffixed from the input "
771 auto Index
= loadCombinedIndex();
772 auto InputBuffers
= loadAllFilesForIndex(*Index
);
773 for (auto &MemBuffer
: InputBuffers
)
774 ThinGenerator
.addModule(MemBuffer
->getBufferIdentifier(),
775 MemBuffer
->getBuffer());
777 for (auto &Filename
: InputFilenames
) {
779 auto Buffer
= loadFile(Filename
);
780 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
781 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
783 ThinGenerator
.crossModuleImport(*TheModule
, *Index
, *Input
);
785 std::string OutputName
= OutputFilename
;
786 if (OutputName
.empty()) {
787 OutputName
= Filename
+ ".thinlto.imported.bc";
789 writeModuleToFile(*TheModule
, OutputName
);
794 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
795 report_fatal_error("Can't handle a single output filename and multiple "
796 "input files, do not provide an output filename and "
797 "the output files will be suffixed from the input "
800 if (ExportedSymbols
.empty())
801 errs() << "Warning: -internalize will not perform without "
802 "-exported-symbol\n";
804 auto Index
= loadCombinedIndex();
805 auto InputBuffers
= loadAllFilesForIndex(*Index
);
806 for (auto &MemBuffer
: InputBuffers
)
807 ThinGenerator
.addModule(MemBuffer
->getBufferIdentifier(),
808 MemBuffer
->getBuffer());
810 for (auto &Filename
: InputFilenames
) {
812 auto Buffer
= loadFile(Filename
);
813 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
814 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
816 ThinGenerator
.internalize(*TheModule
, *Index
, *Input
);
818 std::string OutputName
= OutputFilename
;
819 if (OutputName
.empty()) {
820 OutputName
= Filename
+ ".thinlto.internalized.bc";
822 writeModuleToFile(*TheModule
, OutputName
);
827 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
828 report_fatal_error("Can't handle a single output filename and multiple "
829 "input files, do not provide an output filename and "
830 "the output files will be suffixed from the input "
832 if (!ThinLTOIndex
.empty())
833 errs() << "Warning: -thinlto-index ignored for optimize stage";
835 for (auto &Filename
: InputFilenames
) {
837 auto Buffer
= loadFile(Filename
);
838 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
839 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
841 ThinGenerator
.optimize(*TheModule
);
843 std::string OutputName
= OutputFilename
;
844 if (OutputName
.empty()) {
845 OutputName
= Filename
+ ".thinlto.imported.bc";
847 writeModuleToFile(*TheModule
, OutputName
);
852 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
853 report_fatal_error("Can't handle a single output filename and multiple "
854 "input files, do not provide an output filename and "
855 "the output files will be suffixed from the input "
857 if (!ThinLTOIndex
.empty())
858 errs() << "Warning: -thinlto-index ignored for codegen stage";
860 std::vector
<std::unique_ptr
<MemoryBuffer
>> InputBuffers
;
861 for (auto &Filename
: InputFilenames
) {
863 auto InputOrErr
= MemoryBuffer::getFile(Filename
);
864 error(InputOrErr
, "error " + CurrentActivity
);
865 InputBuffers
.push_back(std::move(*InputOrErr
));
866 ThinGenerator
.addModule(Filename
, InputBuffers
.back()->getBuffer());
868 ThinGenerator
.setCodeGenOnly(true);
871 zip(ThinGenerator
.getProducedBinaries(), InputFilenames
)) {
872 std::string OutputName
= OutputFilename
;
873 if (OutputName
.empty())
874 OutputName
= std::get
<1>(BinName
) + ".thinlto.o";
875 else if (OutputName
== "-") {
876 outs() << std::get
<0>(BinName
)->getBuffer();
881 raw_fd_ostream
OS(OutputName
, EC
, sys::fs::OpenFlags::OF_None
);
882 error(EC
, "error opening the file '" + OutputName
+ "'");
883 OS
<< std::get
<0>(BinName
)->getBuffer();
887 /// Full ThinLTO process
889 if (!OutputFilename
.empty())
890 report_fatal_error("Do not provide an output filename for ThinLTO "
891 " processing, the output files will be suffixed from "
894 if (!ThinLTOIndex
.empty())
895 errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
898 std::vector
<std::unique_ptr
<MemoryBuffer
>> InputBuffers
;
899 for (unsigned i
= 0; i
< InputFilenames
.size(); ++i
) {
900 auto &Filename
= InputFilenames
[i
];
901 std::string CurrentActivity
= "loading file '" + Filename
+ "'";
902 auto InputOrErr
= MemoryBuffer::getFile(Filename
);
903 error(InputOrErr
, "error " + CurrentActivity
);
904 InputBuffers
.push_back(std::move(*InputOrErr
));
905 ThinGenerator
.addModule(Filename
, InputBuffers
.back()->getBuffer());
908 if (!ThinLTOSaveTempsPrefix
.empty())
909 ThinGenerator
.setSaveTempsDir(ThinLTOSaveTempsPrefix
);
911 if (!ThinLTOGeneratedObjectsDir
.empty()) {
912 ThinGenerator
.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir
);
919 auto &Binaries
= ThinGenerator
.getProducedBinaries();
920 if (Binaries
.size() != InputFilenames
.size())
921 report_fatal_error("Number of output objects does not match the number "
924 for (unsigned BufID
= 0; BufID
< Binaries
.size(); ++BufID
) {
925 auto OutputName
= InputFilenames
[BufID
] + ".thinlto.o";
927 raw_fd_ostream
OS(OutputName
, EC
, sys::fs::OpenFlags::OF_None
);
928 error(EC
, "error opening the file '" + OutputName
+ "'");
929 OS
<< Binaries
[BufID
]->getBuffer();
933 /// Load the combined index from disk, then load every file referenced by
936 } // end namespace thinlto
938 int main(int argc
, char **argv
) {
939 InitLLVM
X(argc
, argv
);
940 cl::HideUnrelatedOptions({<OCategory
, &getColorCategory()});
941 cl::ParseCommandLineOptions(argc
, argv
, "llvm LTO linker\n");
943 if (OptLevel
< '0' || OptLevel
> '3')
944 error("optimization level must be between 0 and 3");
946 // Initialize the configured targets.
947 InitializeAllTargets();
948 InitializeAllTargetMCs();
949 InitializeAllAsmPrinters();
950 InitializeAllAsmParsers();
952 // set up the TargetOptions for the machine
953 TargetOptions Options
= codegen::InitTargetOptionsFromCodeGenFlags(Triple());
955 if (ListSymbolsOnly
|| QueryHasCtorDtor
) {
956 testLTOModule(Options
);
960 if (ListDependentLibrariesOnly
) {
961 listDependentLibraries();
971 for (auto &Filename
: InputFilenames
) {
972 ExitOnError
ExitOnErr(std::string(*argv
) + ": error loading file '" +
974 std::unique_ptr
<MemoryBuffer
> BufferOrErr
=
975 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename
)));
976 auto Buffer
= std::move(BufferOrErr
.get());
977 if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer
)))
978 outs() << "Bitcode " << Filename
<< " contains ObjC\n";
980 outs() << "Bitcode " << Filename
<< " does not contain ObjC\n";
985 if (PrintMachOCPUOnly
) {
990 if (ThinLTOMode
.getNumOccurrences()) {
991 if (ThinLTOMode
.getNumOccurrences() > 1)
992 report_fatal_error("You can't specify more than one -thinlto-action");
993 thinlto::ThinLTOProcessing
ThinLTOProcessor(Options
);
994 ThinLTOProcessor
.run();
999 createCombinedModuleSummaryIndex();
1003 unsigned BaseArg
= 0;
1005 LLVMContext Context
;
1006 Context
.setDiagnosticHandler(std::make_unique
<LLVMLTODiagnosticHandler
>(),
1009 LTOCodeGenerator
CodeGen(Context
);
1010 CodeGen
.setDisableVerify(DisableVerify
);
1012 if (UseDiagnosticHandler
)
1013 CodeGen
.setDiagnosticHandler(handleDiagnostics
, nullptr);
1015 CodeGen
.setCodePICModel(codegen::getExplicitRelocModel());
1016 CodeGen
.setFreestanding(EnableFreestanding
);
1017 CodeGen
.setDebugPassManager(DebugPassManager
);
1019 CodeGen
.setDebugInfo(LTO_DEBUG_MODEL_DWARF
);
1020 CodeGen
.setTargetOptions(Options
);
1021 CodeGen
.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage
);
1023 StringSet
<MallocAllocator
> DSOSymbolsSet
;
1024 for (unsigned i
= 0; i
< DSOSymbols
.size(); ++i
)
1025 DSOSymbolsSet
.insert(DSOSymbols
[i
]);
1027 std::vector
<std::string
> KeptDSOSyms
;
1029 for (unsigned i
= BaseArg
; i
< InputFilenames
.size(); ++i
) {
1030 CurrentActivity
= "loading file '" + InputFilenames
[i
] + "'";
1031 ErrorOr
<std::unique_ptr
<LTOModule
>> ModuleOrErr
=
1032 LTOModule::createFromFile(Context
, InputFilenames
[i
], Options
);
1033 std::unique_ptr
<LTOModule
> &Module
= *ModuleOrErr
;
1034 CurrentActivity
= "";
1036 unsigned NumSyms
= Module
->getSymbolCount();
1037 for (unsigned I
= 0; I
< NumSyms
; ++I
) {
1038 StringRef Name
= Module
->getSymbolName(I
);
1039 if (!DSOSymbolsSet
.count(Name
))
1041 lto_symbol_attributes Attrs
= Module
->getSymbolAttributes(I
);
1042 unsigned Scope
= Attrs
& LTO_SYMBOL_SCOPE_MASK
;
1043 if (Scope
!= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN
)
1044 KeptDSOSyms
.push_back(std::string(Name
));
1047 // We use the first input module as the destination module when
1048 // SetMergedModule is true.
1049 if (SetMergedModule
&& i
== BaseArg
) {
1050 // Transfer ownership to the code generator.
1051 CodeGen
.setModule(std::move(Module
));
1052 } else if (!CodeGen
.addModule(Module
.get())) {
1053 // Print a message here so that we know addModule() did not abort.
1054 error("error adding file '" + InputFilenames
[i
] + "'");
1058 // Add all the exported symbols to the table of symbols to preserve.
1059 for (unsigned i
= 0; i
< ExportedSymbols
.size(); ++i
)
1060 CodeGen
.addMustPreserveSymbol(ExportedSymbols
[i
]);
1062 // Add all the dso symbols to the table of symbols to expose.
1063 for (unsigned i
= 0; i
< KeptDSOSyms
.size(); ++i
)
1064 CodeGen
.addMustPreserveSymbol(KeptDSOSyms
[i
]);
1066 // Set cpu and attrs strings for the default target/subtarget.
1067 CodeGen
.setCpu(codegen::getMCPU());
1069 CodeGen
.setOptLevel(OptLevel
- '0');
1070 CodeGen
.setAttrs(codegen::getMAttrs());
1072 if (auto FT
= codegen::getExplicitFileType())
1073 CodeGen
.setFileType(*FT
);
1075 if (!OutputFilename
.empty()) {
1076 if (LTOSaveBeforeOpt
)
1077 CodeGen
.setSaveIRBeforeOptPath(OutputFilename
+ ".0.preopt.bc");
1079 if (SaveLinkedModuleFile
) {
1080 std::string ModuleFilename
= OutputFilename
;
1081 ModuleFilename
+= ".linked.bc";
1084 if (!CodeGen
.writeMergedModules(ModuleFilename
))
1085 error("writing linked module failed.");
1088 if (!CodeGen
.optimize()) {
1089 // Diagnostic messages should have been printed by the handler.
1090 error("error optimizing the code");
1093 if (SaveModuleFile
) {
1094 std::string ModuleFilename
= OutputFilename
;
1095 ModuleFilename
+= ".merged.bc";
1098 if (!CodeGen
.writeMergedModules(ModuleFilename
))
1099 error("writing merged module failed.");
1102 auto AddStream
= [&](size_t Task
) -> std::unique_ptr
<CachedFileStream
> {
1103 std::string PartFilename
= OutputFilename
;
1104 if (Parallelism
!= 1)
1105 PartFilename
+= "." + utostr(Task
);
1109 std::make_unique
<raw_fd_ostream
>(PartFilename
, EC
, sys::fs::OF_None
);
1111 error("error opening the file '" + PartFilename
+ "': " + EC
.message());
1112 return std::make_unique
<CachedFileStream
>(std::move(S
));
1115 if (!CodeGen
.compileOptimized(AddStream
, Parallelism
))
1116 // Diagnostic messages should have been printed by the handler.
1117 error("error compiling the code");
1120 if (Parallelism
!= 1)
1121 error("-j must be specified together with -o");
1124 error(": -save-merged-module must be specified with -o");
1126 const char *OutputName
= nullptr;
1127 if (!CodeGen
.compile_to_file(&OutputName
))
1128 error("error compiling the code");
1129 // Diagnostic messages should have been printed by the handler.
1131 outs() << "Wrote native object file '" << OutputName
<< "'\n";