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.inc"
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/Target/TargetOptions.h"
58 #include <system_error>
66 OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
68 cl::Prefix
, cl::ZeroOrMore
, cl::init('2'));
71 IndexStats("thinlto-index-stats",
72 cl::desc("Print statistic for the index in every input files"),
75 static cl::opt
<bool> DisableVerify(
76 "disable-verify", cl::init(false),
77 cl::desc("Do not run the verifier during the optimization pipeline"));
79 static cl::opt
<bool> DisableInline("disable-inlining", cl::init(false),
80 cl::desc("Do not run the inliner pass"));
83 DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
84 cl::desc("Do not run the GVN load PRE pass"));
86 static cl::opt
<bool> DisableLTOVectorization(
87 "disable-lto-vectorization", cl::init(false),
88 cl::desc("Do not run loop or slp vectorization during LTO"));
90 static cl::opt
<bool> EnableFreestanding(
91 "lto-freestanding", cl::init(false),
92 cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
94 static cl::opt
<bool> UseDiagnosticHandler(
95 "use-diagnostic-handler", cl::init(false),
96 cl::desc("Use a diagnostic handler to test the handler interface"));
99 ThinLTO("thinlto", cl::init(false),
100 cl::desc("Only write combined global index for ThinLTO backends"));
114 cl::opt
<ThinLTOModes
> ThinLTOMode(
115 "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
118 THINLINK
, "thinlink",
119 "ThinLink: produces the index by linking only the summaries."),
120 clEnumValN(THINDISTRIBUTE
, "distributedindexes",
121 "Produces individual indexes for distributed backends."),
122 clEnumValN(THINEMITIMPORTS
, "emitimports",
123 "Emit imports files for distributed backends."),
124 clEnumValN(THINPROMOTE
, "promote",
125 "Perform pre-import promotion (requires -thinlto-index)."),
126 clEnumValN(THINIMPORT
, "import", "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")));
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."));
141 static cl::opt
<std::string
> ThinLTOPrefixReplace(
142 "thinlto-prefix-replace",
143 cl::desc("Control where files for distributed backends are "
144 "created. Expects 'oldprefix;newprefix' and if path "
145 "prefix of output file is oldprefix it will be "
146 "replaced with newprefix."));
148 static cl::opt
<std::string
> ThinLTOModuleId(
150 cl::desc("For the module ID for the file to process, useful to "
151 "match what is in the index."));
153 static cl::opt
<std::string
>
154 ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
157 ThinLTOCachePruningInterval("thinlto-cache-pruning-interval",
158 cl::init(1200), cl::desc("Set ThinLTO cache pruning interval."));
160 static cl::opt
<uint64_t> ThinLTOCacheMaxSizeBytes(
161 "thinlto-cache-max-size-bytes",
162 cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."));
165 ThinLTOCacheMaxSizeFiles("thinlto-cache-max-size-files", cl::init(1000000),
166 cl::desc("Set ThinLTO cache pruning directory maximum number of files."));
168 static cl::opt
<unsigned>
169 ThinLTOCacheEntryExpiration("thinlto-cache-entry-expiration", cl::init(604800) /* 1w */,
170 cl::desc("Set ThinLTO cache entry expiration time."));
172 static cl::opt
<std::string
> ThinLTOSaveTempsPrefix(
173 "thinlto-save-temps",
174 cl::desc("Save ThinLTO temp files using filenames created by adding "
175 "suffixes to the given file path prefix."));
177 static cl::opt
<std::string
> ThinLTOGeneratedObjectsDir(
178 "thinlto-save-objects",
179 cl::desc("Save ThinLTO generated object files using filenames created in "
180 "the given directory."));
183 SaveModuleFile("save-merged-module", cl::init(false),
184 cl::desc("Write merged LTO module to file before CodeGen"));
186 static cl::list
<std::string
> InputFilenames(cl::Positional
, cl::OneOrMore
,
187 cl::desc("<input bitcode files>"));
189 static cl::opt
<std::string
> OutputFilename("o", cl::init(""),
190 cl::desc("Override output filename"),
191 cl::value_desc("filename"));
193 static cl::list
<std::string
> ExportedSymbols(
195 cl::desc("List of symbols to export from the resulting object file"),
198 static cl::list
<std::string
>
199 DSOSymbols("dso-symbol",
200 cl::desc("Symbol to put in the symtab in the resulting dso"),
203 static cl::opt
<bool> ListSymbolsOnly(
204 "list-symbols-only", cl::init(false),
205 cl::desc("Instead of running LTO, list the symbols in each IR file"));
207 static cl::opt
<bool> ListDependentLibrariesOnly(
208 "list-dependent-libraries-only", cl::init(false),
209 cl::desc("Instead of running LTO, list the dependent libraries in each IR file"));
211 static cl::opt
<bool> SetMergedModule(
212 "set-merged-module", cl::init(false),
213 cl::desc("Use the first input module as the merged module"));
215 static cl::opt
<unsigned> Parallelism("j", cl::Prefix
, cl::init(1),
216 cl::desc("Number of backend threads"));
218 static cl::opt
<bool> RestoreGlobalsLinkage(
219 "restore-linkage", cl::init(false),
220 cl::desc("Restore original linkage of globals prior to CodeGen"));
222 static cl::opt
<bool> CheckHasObjC(
223 "check-for-objc", cl::init(false),
224 cl::desc("Only check if the module has objective-C defined in it"));
229 std::vector
<bool> CanBeHidden
;
232 } // end anonymous namespace
234 static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity
,
235 const char *Msg
, void *) {
236 errs() << "llvm-lto: ";
242 errs() << "remark: ";
248 errs() << "warning: ";
251 errs() << Msg
<< "\n";
254 static std::string CurrentActivity
;
257 struct LLVMLTODiagnosticHandler
: public DiagnosticHandler
{
258 bool handleDiagnostics(const DiagnosticInfo
&DI
) override
{
259 raw_ostream
&OS
= errs();
261 switch (DI
.getSeverity()) {
275 if (!CurrentActivity
.empty())
276 OS
<< ' ' << CurrentActivity
;
279 DiagnosticPrinterRawOStream
DP(OS
);
283 if (DI
.getSeverity() == DS_Error
)
290 static void error(const Twine
&Msg
) {
291 errs() << "llvm-lto: " << Msg
<< '\n';
295 static void error(std::error_code EC
, const Twine
&Prefix
) {
297 error(Prefix
+ ": " + EC
.message());
300 template <typename T
>
301 static void error(const ErrorOr
<T
> &V
, const Twine
&Prefix
) {
302 error(V
.getError(), Prefix
);
305 static void maybeVerifyModule(const Module
&Mod
) {
306 if (!DisableVerify
&& verifyModule(Mod
, &errs()))
307 error("Broken Module");
310 static std::unique_ptr
<LTOModule
>
311 getLocalLTOModule(StringRef Path
, std::unique_ptr
<MemoryBuffer
> &Buffer
,
312 const TargetOptions
&Options
) {
313 ErrorOr
<std::unique_ptr
<MemoryBuffer
>> BufferOrErr
=
314 MemoryBuffer::getFile(Path
);
315 error(BufferOrErr
, "error loading file '" + Path
+ "'");
316 Buffer
= std::move(BufferOrErr
.get());
317 CurrentActivity
= ("loading file '" + Path
+ "'").str();
318 std::unique_ptr
<LLVMContext
> Context
= std::make_unique
<LLVMContext
>();
319 Context
->setDiagnosticHandler(std::make_unique
<LLVMLTODiagnosticHandler
>(),
321 ErrorOr
<std::unique_ptr
<LTOModule
>> Ret
= LTOModule::createInLocalContext(
322 std::move(Context
), Buffer
->getBufferStart(), Buffer
->getBufferSize(),
324 CurrentActivity
= "";
325 maybeVerifyModule((*Ret
)->getModule());
326 return std::move(*Ret
);
329 /// Print some statistics on the index for each input files.
330 void printIndexStats() {
331 for (auto &Filename
: InputFilenames
) {
332 ExitOnError
ExitOnErr("llvm-lto: error loading file '" + Filename
+ "': ");
333 std::unique_ptr
<ModuleSummaryIndex
> Index
=
334 ExitOnErr(getModuleSummaryIndexForFile(Filename
));
335 // Skip files without a module summary.
337 report_fatal_error(Filename
+ " does not contain an index");
339 unsigned Calls
= 0, Refs
= 0, Functions
= 0, Alias
= 0, Globals
= 0;
340 for (auto &Summaries
: *Index
) {
341 for (auto &Summary
: Summaries
.second
.SummaryList
) {
342 Refs
+= Summary
->refs().size();
343 if (auto *FuncSummary
= dyn_cast
<FunctionSummary
>(Summary
.get())) {
345 Calls
+= FuncSummary
->calls().size();
346 } else if (isa
<AliasSummary
>(Summary
.get()))
352 outs() << "Index " << Filename
<< " contains "
353 << (Alias
+ Globals
+ Functions
) << " nodes (" << Functions
354 << " functions, " << Alias
<< " alias, " << Globals
355 << " globals) and " << (Calls
+ Refs
) << " edges (" << Refs
356 << " refs and " << Calls
<< " calls)\n";
360 /// List symbols in each IR file.
362 /// The main point here is to provide lit-testable coverage for the LTOModule
363 /// functionality that's exposed by the C API to list symbols. Moreover, this
364 /// provides testing coverage for modules that have been created in their own
366 static void listSymbols(const TargetOptions
&Options
) {
367 for (auto &Filename
: InputFilenames
) {
368 std::unique_ptr
<MemoryBuffer
> Buffer
;
369 std::unique_ptr
<LTOModule
> Module
=
370 getLocalLTOModule(Filename
, Buffer
, Options
);
373 outs() << Filename
<< ":\n";
374 for (int I
= 0, E
= Module
->getSymbolCount(); I
!= E
; ++I
)
375 outs() << Module
->getSymbolName(I
) << "\n";
379 static std::unique_ptr
<MemoryBuffer
> loadFile(StringRef Filename
) {
380 ExitOnError
ExitOnErr("llvm-lto: error loading file '" + Filename
.str() +
382 return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename
)));
385 static void listDependentLibraries() {
386 for (auto &Filename
: InputFilenames
) {
387 auto Buffer
= loadFile(Filename
);
389 std::unique_ptr
<lto::InputFile
> Input(LTOModule::createInputFile(
390 Buffer
->getBufferStart(), Buffer
->getBufferSize(), Filename
.c_str(),
395 // List the dependent libraries.
396 outs() << Filename
<< ":\n";
397 for (size_t I
= 0, C
= LTOModule::getDependentLibraryCount(Input
.get());
400 const char *S
= LTOModule::getDependentLibrary(Input
.get(), I
, &L
);
402 outs() << StringRef(S
, L
) << "\n";
407 /// Create a combined index file from the input IR files and write it.
409 /// This is meant to enable testing of ThinLTO combined index generation,
410 /// currently available via the gold plugin via -thinlto.
411 static void createCombinedModuleSummaryIndex() {
412 ModuleSummaryIndex
CombinedIndex(/*HaveGVs=*/false);
413 uint64_t NextModuleId
= 0;
414 for (auto &Filename
: InputFilenames
) {
415 ExitOnError
ExitOnErr("llvm-lto: error loading file '" + Filename
+ "': ");
416 std::unique_ptr
<MemoryBuffer
> MB
=
417 ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename
)));
418 ExitOnErr(readModuleSummaryIndex(*MB
, CombinedIndex
, NextModuleId
++));
421 assert(!OutputFilename
.empty());
422 raw_fd_ostream
OS(OutputFilename
+ ".thinlto.bc", EC
,
423 sys::fs::OpenFlags::OF_None
);
424 error(EC
, "error opening the file '" + OutputFilename
+ ".thinlto.bc'");
425 WriteIndexToFile(CombinedIndex
, OS
);
429 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
430 /// \p NewPrefix strings, if it was specified.
431 static void getThinLTOOldAndNewPrefix(std::string
&OldPrefix
,
432 std::string
&NewPrefix
) {
433 assert(ThinLTOPrefixReplace
.empty() ||
434 ThinLTOPrefixReplace
.find(";") != StringRef::npos
);
435 StringRef PrefixReplace
= ThinLTOPrefixReplace
;
436 std::pair
<StringRef
, StringRef
> Split
= PrefixReplace
.split(";");
437 OldPrefix
= Split
.first
.str();
438 NewPrefix
= Split
.second
.str();
441 /// Given the original \p Path to an output file, replace any path
442 /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
443 /// resulting directory if it does not yet exist.
444 static std::string
getThinLTOOutputFile(const std::string
&Path
,
445 const std::string
&OldPrefix
,
446 const std::string
&NewPrefix
) {
447 if (OldPrefix
.empty() && NewPrefix
.empty())
449 SmallString
<128> NewPath(Path
);
450 llvm::sys::path::replace_path_prefix(NewPath
, OldPrefix
, NewPrefix
);
451 StringRef ParentPath
= llvm::sys::path::parent_path(NewPath
.str());
452 if (!ParentPath
.empty()) {
453 // Make sure the new directory exists, creating it if necessary.
454 if (std::error_code EC
= llvm::sys::fs::create_directories(ParentPath
))
455 error(EC
, "error creating the directory '" + ParentPath
+ "'");
457 return NewPath
.str();
462 std::vector
<std::unique_ptr
<MemoryBuffer
>>
463 loadAllFilesForIndex(const ModuleSummaryIndex
&Index
) {
464 std::vector
<std::unique_ptr
<MemoryBuffer
>> InputBuffers
;
466 for (auto &ModPath
: Index
.modulePaths()) {
467 const auto &Filename
= ModPath
.first();
468 std::string CurrentActivity
= ("loading file '" + Filename
+ "'").str();
469 auto InputOrErr
= MemoryBuffer::getFile(Filename
);
470 error(InputOrErr
, "error " + CurrentActivity
);
471 InputBuffers
.push_back(std::move(*InputOrErr
));
476 std::unique_ptr
<ModuleSummaryIndex
> loadCombinedIndex() {
477 if (ThinLTOIndex
.empty())
478 report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
479 ExitOnError
ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex
+
481 return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex
));
484 static std::unique_ptr
<lto::InputFile
> loadInputFile(MemoryBufferRef Buffer
) {
485 ExitOnError
ExitOnErr("llvm-lto: error loading input '" +
486 Buffer
.getBufferIdentifier().str() + "': ");
487 return ExitOnErr(lto::InputFile::create(Buffer
));
490 static std::unique_ptr
<Module
> loadModuleFromInput(lto::InputFile
&File
,
492 auto &Mod
= File
.getSingleBitcodeModule();
493 auto ModuleOrErr
= Mod
.parseModule(CTX
);
495 handleAllErrors(ModuleOrErr
.takeError(), [&](ErrorInfoBase
&EIB
) {
496 SMDiagnostic Err
= SMDiagnostic(Mod
.getModuleIdentifier(),
497 SourceMgr::DK_Error
, EIB
.message());
498 Err
.print("llvm-lto", errs());
500 report_fatal_error("Can't load module, abort.");
502 maybeVerifyModule(**ModuleOrErr
);
503 if (ThinLTOModuleId
.getNumOccurrences()) {
504 if (InputFilenames
.size() != 1)
505 report_fatal_error("Can't override the module id for multiple files");
506 (*ModuleOrErr
)->setModuleIdentifier(ThinLTOModuleId
);
508 return std::move(*ModuleOrErr
);
511 static void writeModuleToFile(Module
&TheModule
, StringRef Filename
) {
513 raw_fd_ostream
OS(Filename
, EC
, sys::fs::OpenFlags::OF_None
);
514 error(EC
, "error opening the file '" + Filename
+ "'");
515 maybeVerifyModule(TheModule
);
516 WriteBitcodeToFile(TheModule
, OS
, /* ShouldPreserveUseListOrder */ true);
519 class ThinLTOProcessing
{
521 ThinLTOCodeGenerator ThinGenerator
;
523 ThinLTOProcessing(const TargetOptions
&Options
) {
524 ThinGenerator
.setCodePICModel(getRelocModel());
525 ThinGenerator
.setTargetOptions(Options
);
526 ThinGenerator
.setCacheDir(ThinLTOCacheDir
);
527 ThinGenerator
.setCachePruningInterval(ThinLTOCachePruningInterval
);
528 ThinGenerator
.setCacheEntryExpiration(ThinLTOCacheEntryExpiration
);
529 ThinGenerator
.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles
);
530 ThinGenerator
.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes
);
531 ThinGenerator
.setFreestanding(EnableFreestanding
);
533 // Add all the exported symbols to the table of symbols to preserve.
534 for (unsigned i
= 0; i
< ExportedSymbols
.size(); ++i
)
535 ThinGenerator
.preserveSymbol(ExportedSymbols
[i
]);
539 switch (ThinLTOMode
) {
543 return distributedIndexes();
544 case THINEMITIMPORTS
:
545 return emitImports();
550 case THININTERNALIZE
:
551 return internalize();
562 /// Load the input files, create the combined index, and write it out.
564 // Perform "ThinLink": just produce the index
565 if (OutputFilename
.empty())
567 "OutputFilename is necessary to store the combined index.\n");
570 std::vector
<std::unique_ptr
<MemoryBuffer
>> InputBuffers
;
571 for (unsigned i
= 0; i
< InputFilenames
.size(); ++i
) {
572 auto &Filename
= InputFilenames
[i
];
573 std::string CurrentActivity
= "loading file '" + Filename
+ "'";
574 auto InputOrErr
= MemoryBuffer::getFile(Filename
);
575 error(InputOrErr
, "error " + CurrentActivity
);
576 InputBuffers
.push_back(std::move(*InputOrErr
));
577 ThinGenerator
.addModule(Filename
, InputBuffers
.back()->getBuffer());
580 auto CombinedIndex
= ThinGenerator
.linkCombinedIndex();
582 report_fatal_error("ThinLink didn't create an index");
584 raw_fd_ostream
OS(OutputFilename
, EC
, sys::fs::OpenFlags::OF_None
);
585 error(EC
, "error opening the file '" + OutputFilename
+ "'");
586 WriteIndexToFile(*CombinedIndex
, OS
);
589 /// Load the combined index from disk, then compute and generate
590 /// individual index files suitable for ThinLTO distributed backend builds
591 /// on the files mentioned on the command line (these must match the index
593 void distributedIndexes() {
594 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
595 report_fatal_error("Can't handle a single output filename and multiple "
596 "input files, do not provide an output filename and "
597 "the output files will be suffixed from the input "
600 std::string OldPrefix
, NewPrefix
;
601 getThinLTOOldAndNewPrefix(OldPrefix
, NewPrefix
);
603 auto Index
= loadCombinedIndex();
604 for (auto &Filename
: InputFilenames
) {
606 auto Buffer
= loadFile(Filename
);
607 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
608 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
610 // Build a map of module to the GUIDs and summary objects that should
611 // be written to its index.
612 std::map
<std::string
, GVSummaryMapTy
> ModuleToSummariesForIndex
;
613 ThinGenerator
.gatherImportedSummariesForModule(
614 *TheModule
, *Index
, ModuleToSummariesForIndex
, *Input
);
616 std::string OutputName
= OutputFilename
;
617 if (OutputName
.empty()) {
618 OutputName
= Filename
+ ".thinlto.bc";
620 OutputName
= getThinLTOOutputFile(OutputName
, OldPrefix
, NewPrefix
);
622 raw_fd_ostream
OS(OutputName
, EC
, sys::fs::OpenFlags::OF_None
);
623 error(EC
, "error opening the file '" + OutputName
+ "'");
624 WriteIndexToFile(*Index
, OS
, &ModuleToSummariesForIndex
);
628 /// Load the combined index from disk, compute the imports, and emit
629 /// the import file lists for each module to disk.
631 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
632 report_fatal_error("Can't handle a single output filename and multiple "
633 "input files, do not provide an output filename and "
634 "the output files will be suffixed from the input "
637 std::string OldPrefix
, NewPrefix
;
638 getThinLTOOldAndNewPrefix(OldPrefix
, NewPrefix
);
640 auto Index
= loadCombinedIndex();
641 for (auto &Filename
: InputFilenames
) {
643 auto Buffer
= loadFile(Filename
);
644 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
645 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
646 std::string OutputName
= OutputFilename
;
647 if (OutputName
.empty()) {
648 OutputName
= Filename
+ ".imports";
651 getThinLTOOutputFile(OutputName
, OldPrefix
, NewPrefix
);
652 ThinGenerator
.emitImports(*TheModule
, OutputName
, *Index
, *Input
);
656 /// Load the combined index from disk, then load every file referenced by
657 /// the index and add them to the generator, finally perform the promotion
658 /// on the files mentioned on the command line (these must match the index
661 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
662 report_fatal_error("Can't handle a single output filename and multiple "
663 "input files, do not provide an output filename and "
664 "the output files will be suffixed from the input "
667 auto Index
= loadCombinedIndex();
668 for (auto &Filename
: InputFilenames
) {
670 auto Buffer
= loadFile(Filename
);
671 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
672 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
674 ThinGenerator
.promote(*TheModule
, *Index
, *Input
);
676 std::string OutputName
= OutputFilename
;
677 if (OutputName
.empty()) {
678 OutputName
= Filename
+ ".thinlto.promoted.bc";
680 writeModuleToFile(*TheModule
, OutputName
);
684 /// Load the combined index from disk, then load every file referenced by
685 /// the index and add them to the generator, then performs the promotion and
686 /// cross module importing on the files mentioned on the command line
687 /// (these must match the index content).
689 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
690 report_fatal_error("Can't handle a single output filename and multiple "
691 "input files, do not provide an output filename and "
692 "the output files will be suffixed from the input "
695 auto Index
= loadCombinedIndex();
696 auto InputBuffers
= loadAllFilesForIndex(*Index
);
697 for (auto &MemBuffer
: InputBuffers
)
698 ThinGenerator
.addModule(MemBuffer
->getBufferIdentifier(),
699 MemBuffer
->getBuffer());
701 for (auto &Filename
: InputFilenames
) {
703 auto Buffer
= loadFile(Filename
);
704 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
705 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
707 ThinGenerator
.crossModuleImport(*TheModule
, *Index
, *Input
);
709 std::string OutputName
= OutputFilename
;
710 if (OutputName
.empty()) {
711 OutputName
= Filename
+ ".thinlto.imported.bc";
713 writeModuleToFile(*TheModule
, OutputName
);
718 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
719 report_fatal_error("Can't handle a single output filename and multiple "
720 "input files, do not provide an output filename and "
721 "the output files will be suffixed from the input "
724 if (ExportedSymbols
.empty())
725 errs() << "Warning: -internalize will not perform without "
726 "-exported-symbol\n";
728 auto Index
= loadCombinedIndex();
729 auto InputBuffers
= loadAllFilesForIndex(*Index
);
730 for (auto &MemBuffer
: InputBuffers
)
731 ThinGenerator
.addModule(MemBuffer
->getBufferIdentifier(),
732 MemBuffer
->getBuffer());
734 for (auto &Filename
: InputFilenames
) {
736 auto Buffer
= loadFile(Filename
);
737 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
738 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
740 ThinGenerator
.internalize(*TheModule
, *Index
, *Input
);
742 std::string OutputName
= OutputFilename
;
743 if (OutputName
.empty()) {
744 OutputName
= Filename
+ ".thinlto.internalized.bc";
746 writeModuleToFile(*TheModule
, OutputName
);
751 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
752 report_fatal_error("Can't handle a single output filename and multiple "
753 "input files, do not provide an output filename and "
754 "the output files will be suffixed from the input "
756 if (!ThinLTOIndex
.empty())
757 errs() << "Warning: -thinlto-index ignored for optimize stage";
759 for (auto &Filename
: InputFilenames
) {
761 auto Buffer
= loadFile(Filename
);
762 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
763 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
765 ThinGenerator
.optimize(*TheModule
);
767 std::string OutputName
= OutputFilename
;
768 if (OutputName
.empty()) {
769 OutputName
= Filename
+ ".thinlto.imported.bc";
771 writeModuleToFile(*TheModule
, OutputName
);
776 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
777 report_fatal_error("Can't handle a single output filename and multiple "
778 "input files, do not provide an output filename and "
779 "the output files will be suffixed from the input "
781 if (!ThinLTOIndex
.empty())
782 errs() << "Warning: -thinlto-index ignored for codegen stage";
784 std::vector
<std::unique_ptr
<MemoryBuffer
>> InputBuffers
;
785 for (auto &Filename
: InputFilenames
) {
787 auto InputOrErr
= MemoryBuffer::getFile(Filename
);
788 error(InputOrErr
, "error " + CurrentActivity
);
789 InputBuffers
.push_back(std::move(*InputOrErr
));
790 ThinGenerator
.addModule(Filename
, InputBuffers
.back()->getBuffer());
792 ThinGenerator
.setCodeGenOnly(true);
795 zip(ThinGenerator
.getProducedBinaries(), InputFilenames
)) {
796 std::string OutputName
= OutputFilename
;
797 if (OutputName
.empty())
798 OutputName
= std::get
<1>(BinName
) + ".thinlto.o";
799 else if (OutputName
== "-") {
800 outs() << std::get
<0>(BinName
)->getBuffer();
805 raw_fd_ostream
OS(OutputName
, EC
, sys::fs::OpenFlags::OF_None
);
806 error(EC
, "error opening the file '" + OutputName
+ "'");
807 OS
<< std::get
<0>(BinName
)->getBuffer();
811 /// Full ThinLTO process
813 if (!OutputFilename
.empty())
814 report_fatal_error("Do not provide an output filename for ThinLTO "
815 " processing, the output files will be suffixed from "
818 if (!ThinLTOIndex
.empty())
819 errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
822 std::vector
<std::unique_ptr
<MemoryBuffer
>> InputBuffers
;
823 for (unsigned i
= 0; i
< InputFilenames
.size(); ++i
) {
824 auto &Filename
= InputFilenames
[i
];
825 std::string CurrentActivity
= "loading file '" + Filename
+ "'";
826 auto InputOrErr
= MemoryBuffer::getFile(Filename
);
827 error(InputOrErr
, "error " + CurrentActivity
);
828 InputBuffers
.push_back(std::move(*InputOrErr
));
829 ThinGenerator
.addModule(Filename
, InputBuffers
.back()->getBuffer());
832 if (!ThinLTOSaveTempsPrefix
.empty())
833 ThinGenerator
.setSaveTempsDir(ThinLTOSaveTempsPrefix
);
835 if (!ThinLTOGeneratedObjectsDir
.empty()) {
836 ThinGenerator
.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir
);
843 auto &Binaries
= ThinGenerator
.getProducedBinaries();
844 if (Binaries
.size() != InputFilenames
.size())
845 report_fatal_error("Number of output objects does not match the number "
848 for (unsigned BufID
= 0; BufID
< Binaries
.size(); ++BufID
) {
849 auto OutputName
= InputFilenames
[BufID
] + ".thinlto.o";
851 raw_fd_ostream
OS(OutputName
, EC
, sys::fs::OpenFlags::OF_None
);
852 error(EC
, "error opening the file '" + OutputName
+ "'");
853 OS
<< Binaries
[BufID
]->getBuffer();
857 /// Load the combined index from disk, then load every file referenced by
860 } // end namespace thinlto
862 int main(int argc
, char **argv
) {
863 InitLLVM
X(argc
, argv
);
864 cl::ParseCommandLineOptions(argc
, argv
, "llvm LTO linker\n");
866 if (OptLevel
< '0' || OptLevel
> '3')
867 error("optimization level must be between 0 and 3");
869 // Initialize the configured targets.
870 InitializeAllTargets();
871 InitializeAllTargetMCs();
872 InitializeAllAsmPrinters();
873 InitializeAllAsmParsers();
875 // set up the TargetOptions for the machine
876 TargetOptions Options
= InitTargetOptionsFromCodeGenFlags();
878 if (ListSymbolsOnly
) {
879 listSymbols(Options
);
883 if (ListDependentLibrariesOnly
) {
884 listDependentLibraries();
894 for (auto &Filename
: InputFilenames
) {
895 ExitOnError
ExitOnErr(std::string(*argv
) + ": error loading file '" +
897 std::unique_ptr
<MemoryBuffer
> BufferOrErr
=
898 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename
)));
899 auto Buffer
= std::move(BufferOrErr
.get());
900 if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer
)))
901 outs() << "Bitcode " << Filename
<< " contains ObjC\n";
903 outs() << "Bitcode " << Filename
<< " does not contain ObjC\n";
908 if (ThinLTOMode
.getNumOccurrences()) {
909 if (ThinLTOMode
.getNumOccurrences() > 1)
910 report_fatal_error("You can't specify more than one -thinlto-action");
911 thinlto::ThinLTOProcessing
ThinLTOProcessor(Options
);
912 ThinLTOProcessor
.run();
917 createCombinedModuleSummaryIndex();
921 unsigned BaseArg
= 0;
924 Context
.setDiagnosticHandler(std::make_unique
<LLVMLTODiagnosticHandler
>(),
927 LTOCodeGenerator
CodeGen(Context
);
929 if (UseDiagnosticHandler
)
930 CodeGen
.setDiagnosticHandler(handleDiagnostics
, nullptr);
932 CodeGen
.setCodePICModel(getRelocModel());
933 CodeGen
.setFreestanding(EnableFreestanding
);
935 CodeGen
.setDebugInfo(LTO_DEBUG_MODEL_DWARF
);
936 CodeGen
.setTargetOptions(Options
);
937 CodeGen
.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage
);
939 StringSet
<MallocAllocator
> DSOSymbolsSet
;
940 for (unsigned i
= 0; i
< DSOSymbols
.size(); ++i
)
941 DSOSymbolsSet
.insert(DSOSymbols
[i
]);
943 std::vector
<std::string
> KeptDSOSyms
;
945 for (unsigned i
= BaseArg
; i
< InputFilenames
.size(); ++i
) {
946 CurrentActivity
= "loading file '" + InputFilenames
[i
] + "'";
947 ErrorOr
<std::unique_ptr
<LTOModule
>> ModuleOrErr
=
948 LTOModule::createFromFile(Context
, InputFilenames
[i
], Options
);
949 std::unique_ptr
<LTOModule
> &Module
= *ModuleOrErr
;
950 CurrentActivity
= "";
952 unsigned NumSyms
= Module
->getSymbolCount();
953 for (unsigned I
= 0; I
< NumSyms
; ++I
) {
954 StringRef Name
= Module
->getSymbolName(I
);
955 if (!DSOSymbolsSet
.count(Name
))
957 lto_symbol_attributes Attrs
= Module
->getSymbolAttributes(I
);
958 unsigned Scope
= Attrs
& LTO_SYMBOL_SCOPE_MASK
;
959 if (Scope
!= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN
)
960 KeptDSOSyms
.push_back(Name
);
963 // We use the first input module as the destination module when
964 // SetMergedModule is true.
965 if (SetMergedModule
&& i
== BaseArg
) {
966 // Transfer ownership to the code generator.
967 CodeGen
.setModule(std::move(Module
));
968 } else if (!CodeGen
.addModule(Module
.get())) {
969 // Print a message here so that we know addModule() did not abort.
970 error("error adding file '" + InputFilenames
[i
] + "'");
974 // Add all the exported symbols to the table of symbols to preserve.
975 for (unsigned i
= 0; i
< ExportedSymbols
.size(); ++i
)
976 CodeGen
.addMustPreserveSymbol(ExportedSymbols
[i
]);
978 // Add all the dso symbols to the table of symbols to expose.
979 for (unsigned i
= 0; i
< KeptDSOSyms
.size(); ++i
)
980 CodeGen
.addMustPreserveSymbol(KeptDSOSyms
[i
]);
982 // Set cpu and attrs strings for the default target/subtarget.
983 CodeGen
.setCpu(MCPU
.c_str());
985 CodeGen
.setOptLevel(OptLevel
- '0');
988 for (unsigned i
= 0; i
< MAttrs
.size(); ++i
) {
991 attrs
.append(MAttrs
[i
]);
995 CodeGen
.setAttr(attrs
);
997 if (FileType
.getNumOccurrences())
998 CodeGen
.setFileType(FileType
);
1000 if (!OutputFilename
.empty()) {
1001 if (!CodeGen
.optimize(DisableVerify
, DisableInline
, DisableGVNLoadPRE
,
1002 DisableLTOVectorization
)) {
1003 // Diagnostic messages should have been printed by the handler.
1004 error("error optimizing the code");
1007 if (SaveModuleFile
) {
1008 std::string ModuleFilename
= OutputFilename
;
1009 ModuleFilename
+= ".merged.bc";
1012 if (!CodeGen
.writeMergedModules(ModuleFilename
))
1013 error("writing merged module failed.");
1016 std::list
<ToolOutputFile
> OSs
;
1017 std::vector
<raw_pwrite_stream
*> OSPtrs
;
1018 for (unsigned I
= 0; I
!= Parallelism
; ++I
) {
1019 std::string PartFilename
= OutputFilename
;
1020 if (Parallelism
!= 1)
1021 PartFilename
+= "." + utostr(I
);
1023 OSs
.emplace_back(PartFilename
, EC
, sys::fs::OF_None
);
1025 error("error opening the file '" + PartFilename
+ "': " + EC
.message());
1026 OSPtrs
.push_back(&OSs
.back().os());
1029 if (!CodeGen
.compileOptimized(OSPtrs
))
1030 // Diagnostic messages should have been printed by the handler.
1031 error("error compiling the code");
1033 for (ToolOutputFile
&OS
: OSs
)
1036 if (Parallelism
!= 1)
1037 error("-j must be specified together with -o");
1040 error(": -save-merged-module must be specified with -o");
1042 const char *OutputName
= nullptr;
1043 if (!CodeGen
.compile_to_file(&OutputName
, DisableVerify
, DisableInline
,
1044 DisableGVNLoadPRE
, DisableLTOVectorization
))
1045 error("error compiling the code");
1046 // Diagnostic messages should have been printed by the handler.
1048 outs() << "Wrote native object file '" << OutputName
<< "'\n";