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 for (auto &Filename
: InputFilenames
) {
485 ExitOnError
ExitOnErr("llvm-lto: error loading file '" + Filename
+ "': ");
486 std::unique_ptr
<MemoryBuffer
> MB
=
487 ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename
)));
488 ExitOnErr(readModuleSummaryIndex(*MB
, CombinedIndex
));
490 // In order to use this index for testing, specifically import testing, we
491 // need to update any indirect call edges created from SamplePGO, so that they
492 // point to the correct GUIDs.
493 updateIndirectCalls(CombinedIndex
);
495 assert(!OutputFilename
.empty());
496 raw_fd_ostream
OS(OutputFilename
+ ".thinlto.bc", EC
,
497 sys::fs::OpenFlags::OF_None
);
498 error(EC
, "error opening the file '" + OutputFilename
+ ".thinlto.bc'");
499 writeIndexToFile(CombinedIndex
, OS
);
503 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
504 /// \p NewPrefix strings, if it was specified.
505 static void getThinLTOOldAndNewPrefix(std::string
&OldPrefix
,
506 std::string
&NewPrefix
) {
507 assert(ThinLTOPrefixReplace
.empty() ||
508 ThinLTOPrefixReplace
.find(';') != StringRef::npos
);
509 StringRef PrefixReplace
= ThinLTOPrefixReplace
;
510 std::pair
<StringRef
, StringRef
> Split
= PrefixReplace
.split(";");
511 OldPrefix
= Split
.first
.str();
512 NewPrefix
= Split
.second
.str();
515 /// Given the original \p Path to an output file, replace any path
516 /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
517 /// resulting directory if it does not yet exist.
518 static std::string
getThinLTOOutputFile(StringRef Path
, StringRef OldPrefix
,
519 StringRef NewPrefix
) {
520 if (OldPrefix
.empty() && NewPrefix
.empty())
521 return std::string(Path
);
522 SmallString
<128> NewPath(Path
);
523 llvm::sys::path::replace_path_prefix(NewPath
, OldPrefix
, NewPrefix
);
524 StringRef ParentPath
= llvm::sys::path::parent_path(NewPath
.str());
525 if (!ParentPath
.empty()) {
526 // Make sure the new directory exists, creating it if necessary.
527 if (std::error_code EC
= llvm::sys::fs::create_directories(ParentPath
))
528 error(EC
, "error creating the directory '" + ParentPath
+ "'");
530 return std::string(NewPath
.str());
535 std::vector
<std::unique_ptr
<MemoryBuffer
>>
536 loadAllFilesForIndex(const ModuleSummaryIndex
&Index
) {
537 std::vector
<std::unique_ptr
<MemoryBuffer
>> InputBuffers
;
539 for (auto &ModPath
: Index
.modulePaths()) {
540 const auto &Filename
= ModPath
.first();
541 std::string CurrentActivity
= ("loading file '" + Filename
+ "'").str();
542 auto InputOrErr
= MemoryBuffer::getFile(Filename
);
543 error(InputOrErr
, "error " + CurrentActivity
);
544 InputBuffers
.push_back(std::move(*InputOrErr
));
549 std::unique_ptr
<ModuleSummaryIndex
> loadCombinedIndex() {
550 if (ThinLTOIndex
.empty())
551 report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
552 ExitOnError
ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex
+
554 return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex
));
557 static std::unique_ptr
<lto::InputFile
> loadInputFile(MemoryBufferRef Buffer
) {
558 ExitOnError
ExitOnErr("llvm-lto: error loading input '" +
559 Buffer
.getBufferIdentifier().str() + "': ");
560 return ExitOnErr(lto::InputFile::create(Buffer
));
563 static std::unique_ptr
<Module
> loadModuleFromInput(lto::InputFile
&File
,
565 auto &Mod
= File
.getSingleBitcodeModule();
566 auto ModuleOrErr
= Mod
.parseModule(CTX
);
568 handleAllErrors(ModuleOrErr
.takeError(), [&](ErrorInfoBase
&EIB
) {
569 SMDiagnostic Err
= SMDiagnostic(Mod
.getModuleIdentifier(),
570 SourceMgr::DK_Error
, EIB
.message());
571 Err
.print("llvm-lto", errs());
573 report_fatal_error("Can't load module, abort.");
575 maybeVerifyModule(**ModuleOrErr
);
576 if (ThinLTOModuleId
.getNumOccurrences()) {
577 if (InputFilenames
.size() != 1)
578 report_fatal_error("Can't override the module id for multiple files");
579 (*ModuleOrErr
)->setModuleIdentifier(ThinLTOModuleId
);
581 return std::move(*ModuleOrErr
);
584 static void writeModuleToFile(Module
&TheModule
, StringRef Filename
) {
586 raw_fd_ostream
OS(Filename
, EC
, sys::fs::OpenFlags::OF_None
);
587 error(EC
, "error opening the file '" + Filename
+ "'");
588 maybeVerifyModule(TheModule
);
589 WriteBitcodeToFile(TheModule
, OS
, /* ShouldPreserveUseListOrder */ true);
592 class ThinLTOProcessing
{
594 ThinLTOCodeGenerator ThinGenerator
;
596 ThinLTOProcessing(const TargetOptions
&Options
) {
597 ThinGenerator
.setCodePICModel(codegen::getExplicitRelocModel());
598 ThinGenerator
.setTargetOptions(Options
);
599 ThinGenerator
.setCacheDir(ThinLTOCacheDir
);
600 ThinGenerator
.setCachePruningInterval(ThinLTOCachePruningInterval
);
601 ThinGenerator
.setCacheEntryExpiration(ThinLTOCacheEntryExpiration
);
602 ThinGenerator
.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles
);
603 ThinGenerator
.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes
);
604 ThinGenerator
.setFreestanding(EnableFreestanding
);
605 ThinGenerator
.setDebugPassManager(DebugPassManager
);
607 // Add all the exported symbols to the table of symbols to preserve.
608 for (unsigned i
= 0; i
< ExportedSymbols
.size(); ++i
)
609 ThinGenerator
.preserveSymbol(ExportedSymbols
[i
]);
613 switch (ThinLTOMode
) {
617 return distributedIndexes();
618 case THINEMITIMPORTS
:
619 return emitImports();
624 case THININTERNALIZE
:
625 return internalize();
636 /// Load the input files, create the combined index, and write it out.
638 // Perform "ThinLink": just produce the index
639 if (OutputFilename
.empty())
641 "OutputFilename is necessary to store the combined index.\n");
644 std::vector
<std::unique_ptr
<MemoryBuffer
>> InputBuffers
;
645 for (unsigned i
= 0; i
< InputFilenames
.size(); ++i
) {
646 auto &Filename
= InputFilenames
[i
];
647 std::string CurrentActivity
= "loading file '" + Filename
+ "'";
648 auto InputOrErr
= MemoryBuffer::getFile(Filename
);
649 error(InputOrErr
, "error " + CurrentActivity
);
650 InputBuffers
.push_back(std::move(*InputOrErr
));
651 ThinGenerator
.addModule(Filename
, InputBuffers
.back()->getBuffer());
654 auto CombinedIndex
= ThinGenerator
.linkCombinedIndex();
656 report_fatal_error("ThinLink didn't create an index");
658 raw_fd_ostream
OS(OutputFilename
, EC
, sys::fs::OpenFlags::OF_None
);
659 error(EC
, "error opening the file '" + OutputFilename
+ "'");
660 writeIndexToFile(*CombinedIndex
, OS
);
663 /// Load the combined index from disk, then compute and generate
664 /// individual index files suitable for ThinLTO distributed backend builds
665 /// on the files mentioned on the command line (these must match the index
667 void distributedIndexes() {
668 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
669 report_fatal_error("Can't handle a single output filename and multiple "
670 "input files, do not provide an output filename and "
671 "the output files will be suffixed from the input "
674 std::string OldPrefix
, NewPrefix
;
675 getThinLTOOldAndNewPrefix(OldPrefix
, NewPrefix
);
677 auto Index
= loadCombinedIndex();
678 for (auto &Filename
: InputFilenames
) {
680 auto Buffer
= loadFile(Filename
);
681 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
682 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
684 // Build a map of module to the GUIDs and summary objects that should
685 // be written to its index.
686 std::map
<std::string
, GVSummaryMapTy
> ModuleToSummariesForIndex
;
687 ThinGenerator
.gatherImportedSummariesForModule(
688 *TheModule
, *Index
, ModuleToSummariesForIndex
, *Input
);
690 std::string OutputName
= OutputFilename
;
691 if (OutputName
.empty()) {
692 OutputName
= Filename
+ ".thinlto.bc";
694 OutputName
= getThinLTOOutputFile(OutputName
, OldPrefix
, NewPrefix
);
696 raw_fd_ostream
OS(OutputName
, EC
, sys::fs::OpenFlags::OF_None
);
697 error(EC
, "error opening the file '" + OutputName
+ "'");
698 writeIndexToFile(*Index
, OS
, &ModuleToSummariesForIndex
);
702 /// Load the combined index from disk, compute the imports, and emit
703 /// the import file lists for each module to disk.
705 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
706 report_fatal_error("Can't handle a single output filename and multiple "
707 "input files, do not provide an output filename and "
708 "the output files will be suffixed from the input "
711 std::string OldPrefix
, NewPrefix
;
712 getThinLTOOldAndNewPrefix(OldPrefix
, NewPrefix
);
714 auto Index
= loadCombinedIndex();
715 for (auto &Filename
: InputFilenames
) {
717 auto Buffer
= loadFile(Filename
);
718 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
719 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
720 std::string OutputName
= OutputFilename
;
721 if (OutputName
.empty()) {
722 OutputName
= Filename
+ ".imports";
725 getThinLTOOutputFile(OutputName
, OldPrefix
, NewPrefix
);
726 ThinGenerator
.emitImports(*TheModule
, OutputName
, *Index
, *Input
);
730 /// Load the combined index from disk, then load every file referenced by
731 /// the index and add them to the generator, finally perform the promotion
732 /// on the files mentioned on the command line (these must match the index
735 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
736 report_fatal_error("Can't handle a single output filename and multiple "
737 "input files, do not provide an output filename and "
738 "the output files will be suffixed from the input "
741 auto Index
= loadCombinedIndex();
742 for (auto &Filename
: InputFilenames
) {
744 auto Buffer
= loadFile(Filename
);
745 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
746 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
748 ThinGenerator
.promote(*TheModule
, *Index
, *Input
);
750 std::string OutputName
= OutputFilename
;
751 if (OutputName
.empty()) {
752 OutputName
= Filename
+ ".thinlto.promoted.bc";
754 writeModuleToFile(*TheModule
, OutputName
);
758 /// Load the combined index from disk, then load every file referenced by
759 /// the index and add them to the generator, then performs the promotion and
760 /// cross module importing on the files mentioned on the command line
761 /// (these must match the index content).
763 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
764 report_fatal_error("Can't handle a single output filename and multiple "
765 "input files, do not provide an output filename and "
766 "the output files will be suffixed from the input "
769 auto Index
= loadCombinedIndex();
770 auto InputBuffers
= loadAllFilesForIndex(*Index
);
771 for (auto &MemBuffer
: InputBuffers
)
772 ThinGenerator
.addModule(MemBuffer
->getBufferIdentifier(),
773 MemBuffer
->getBuffer());
775 for (auto &Filename
: InputFilenames
) {
777 auto Buffer
= loadFile(Filename
);
778 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
779 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
781 ThinGenerator
.crossModuleImport(*TheModule
, *Index
, *Input
);
783 std::string OutputName
= OutputFilename
;
784 if (OutputName
.empty()) {
785 OutputName
= Filename
+ ".thinlto.imported.bc";
787 writeModuleToFile(*TheModule
, OutputName
);
792 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
793 report_fatal_error("Can't handle a single output filename and multiple "
794 "input files, do not provide an output filename and "
795 "the output files will be suffixed from the input "
798 if (ExportedSymbols
.empty())
799 errs() << "Warning: -internalize will not perform without "
800 "-exported-symbol\n";
802 auto Index
= loadCombinedIndex();
803 auto InputBuffers
= loadAllFilesForIndex(*Index
);
804 for (auto &MemBuffer
: InputBuffers
)
805 ThinGenerator
.addModule(MemBuffer
->getBufferIdentifier(),
806 MemBuffer
->getBuffer());
808 for (auto &Filename
: InputFilenames
) {
810 auto Buffer
= loadFile(Filename
);
811 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
812 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
814 ThinGenerator
.internalize(*TheModule
, *Index
, *Input
);
816 std::string OutputName
= OutputFilename
;
817 if (OutputName
.empty()) {
818 OutputName
= Filename
+ ".thinlto.internalized.bc";
820 writeModuleToFile(*TheModule
, OutputName
);
825 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
826 report_fatal_error("Can't handle a single output filename and multiple "
827 "input files, do not provide an output filename and "
828 "the output files will be suffixed from the input "
830 if (!ThinLTOIndex
.empty())
831 errs() << "Warning: -thinlto-index ignored for optimize stage";
833 for (auto &Filename
: InputFilenames
) {
835 auto Buffer
= loadFile(Filename
);
836 auto Input
= loadInputFile(Buffer
->getMemBufferRef());
837 auto TheModule
= loadModuleFromInput(*Input
, Ctx
);
839 ThinGenerator
.optimize(*TheModule
);
841 std::string OutputName
= OutputFilename
;
842 if (OutputName
.empty()) {
843 OutputName
= Filename
+ ".thinlto.imported.bc";
845 writeModuleToFile(*TheModule
, OutputName
);
850 if (InputFilenames
.size() != 1 && !OutputFilename
.empty())
851 report_fatal_error("Can't handle a single output filename and multiple "
852 "input files, do not provide an output filename and "
853 "the output files will be suffixed from the input "
855 if (!ThinLTOIndex
.empty())
856 errs() << "Warning: -thinlto-index ignored for codegen stage";
858 std::vector
<std::unique_ptr
<MemoryBuffer
>> InputBuffers
;
859 for (auto &Filename
: InputFilenames
) {
861 auto InputOrErr
= MemoryBuffer::getFile(Filename
);
862 error(InputOrErr
, "error " + CurrentActivity
);
863 InputBuffers
.push_back(std::move(*InputOrErr
));
864 ThinGenerator
.addModule(Filename
, InputBuffers
.back()->getBuffer());
866 ThinGenerator
.setCodeGenOnly(true);
869 zip(ThinGenerator
.getProducedBinaries(), InputFilenames
)) {
870 std::string OutputName
= OutputFilename
;
871 if (OutputName
.empty())
872 OutputName
= std::get
<1>(BinName
) + ".thinlto.o";
873 else if (OutputName
== "-") {
874 outs() << std::get
<0>(BinName
)->getBuffer();
879 raw_fd_ostream
OS(OutputName
, EC
, sys::fs::OpenFlags::OF_None
);
880 error(EC
, "error opening the file '" + OutputName
+ "'");
881 OS
<< std::get
<0>(BinName
)->getBuffer();
885 /// Full ThinLTO process
887 if (!OutputFilename
.empty())
888 report_fatal_error("Do not provide an output filename for ThinLTO "
889 " processing, the output files will be suffixed from "
892 if (!ThinLTOIndex
.empty())
893 errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
896 std::vector
<std::unique_ptr
<MemoryBuffer
>> InputBuffers
;
897 for (unsigned i
= 0; i
< InputFilenames
.size(); ++i
) {
898 auto &Filename
= InputFilenames
[i
];
899 std::string CurrentActivity
= "loading file '" + Filename
+ "'";
900 auto InputOrErr
= MemoryBuffer::getFile(Filename
);
901 error(InputOrErr
, "error " + CurrentActivity
);
902 InputBuffers
.push_back(std::move(*InputOrErr
));
903 ThinGenerator
.addModule(Filename
, InputBuffers
.back()->getBuffer());
906 if (!ThinLTOSaveTempsPrefix
.empty())
907 ThinGenerator
.setSaveTempsDir(ThinLTOSaveTempsPrefix
);
909 if (!ThinLTOGeneratedObjectsDir
.empty()) {
910 ThinGenerator
.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir
);
917 auto &Binaries
= ThinGenerator
.getProducedBinaries();
918 if (Binaries
.size() != InputFilenames
.size())
919 report_fatal_error("Number of output objects does not match the number "
922 for (unsigned BufID
= 0; BufID
< Binaries
.size(); ++BufID
) {
923 auto OutputName
= InputFilenames
[BufID
] + ".thinlto.o";
925 raw_fd_ostream
OS(OutputName
, EC
, sys::fs::OpenFlags::OF_None
);
926 error(EC
, "error opening the file '" + OutputName
+ "'");
927 OS
<< Binaries
[BufID
]->getBuffer();
931 /// Load the combined index from disk, then load every file referenced by
934 } // end namespace thinlto
936 int main(int argc
, char **argv
) {
937 InitLLVM
X(argc
, argv
);
938 cl::HideUnrelatedOptions({<OCategory
, &getColorCategory()});
939 cl::ParseCommandLineOptions(argc
, argv
, "llvm LTO linker\n");
941 if (OptLevel
< '0' || OptLevel
> '3')
942 error("optimization level must be between 0 and 3");
944 // Initialize the configured targets.
945 InitializeAllTargets();
946 InitializeAllTargetMCs();
947 InitializeAllAsmPrinters();
948 InitializeAllAsmParsers();
950 // set up the TargetOptions for the machine
951 TargetOptions Options
= codegen::InitTargetOptionsFromCodeGenFlags(Triple());
953 if (ListSymbolsOnly
|| QueryHasCtorDtor
) {
954 testLTOModule(Options
);
958 if (ListDependentLibrariesOnly
) {
959 listDependentLibraries();
969 for (auto &Filename
: InputFilenames
) {
970 ExitOnError
ExitOnErr(std::string(*argv
) + ": error loading file '" +
972 std::unique_ptr
<MemoryBuffer
> BufferOrErr
=
973 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename
)));
974 auto Buffer
= std::move(BufferOrErr
.get());
975 if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer
)))
976 outs() << "Bitcode " << Filename
<< " contains ObjC\n";
978 outs() << "Bitcode " << Filename
<< " does not contain ObjC\n";
983 if (PrintMachOCPUOnly
) {
988 if (ThinLTOMode
.getNumOccurrences()) {
989 if (ThinLTOMode
.getNumOccurrences() > 1)
990 report_fatal_error("You can't specify more than one -thinlto-action");
991 thinlto::ThinLTOProcessing
ThinLTOProcessor(Options
);
992 ThinLTOProcessor
.run();
997 createCombinedModuleSummaryIndex();
1001 unsigned BaseArg
= 0;
1003 LLVMContext Context
;
1004 Context
.setDiagnosticHandler(std::make_unique
<LLVMLTODiagnosticHandler
>(),
1007 LTOCodeGenerator
CodeGen(Context
);
1008 CodeGen
.setDisableVerify(DisableVerify
);
1010 if (UseDiagnosticHandler
)
1011 CodeGen
.setDiagnosticHandler(handleDiagnostics
, nullptr);
1013 CodeGen
.setCodePICModel(codegen::getExplicitRelocModel());
1014 CodeGen
.setFreestanding(EnableFreestanding
);
1015 CodeGen
.setDebugPassManager(DebugPassManager
);
1017 CodeGen
.setDebugInfo(LTO_DEBUG_MODEL_DWARF
);
1018 CodeGen
.setTargetOptions(Options
);
1019 CodeGen
.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage
);
1021 StringSet
<MallocAllocator
> DSOSymbolsSet
;
1022 for (unsigned i
= 0; i
< DSOSymbols
.size(); ++i
)
1023 DSOSymbolsSet
.insert(DSOSymbols
[i
]);
1025 std::vector
<std::string
> KeptDSOSyms
;
1027 for (unsigned i
= BaseArg
; i
< InputFilenames
.size(); ++i
) {
1028 CurrentActivity
= "loading file '" + InputFilenames
[i
] + "'";
1029 ErrorOr
<std::unique_ptr
<LTOModule
>> ModuleOrErr
=
1030 LTOModule::createFromFile(Context
, InputFilenames
[i
], Options
);
1031 std::unique_ptr
<LTOModule
> &Module
= *ModuleOrErr
;
1032 CurrentActivity
= "";
1034 unsigned NumSyms
= Module
->getSymbolCount();
1035 for (unsigned I
= 0; I
< NumSyms
; ++I
) {
1036 StringRef Name
= Module
->getSymbolName(I
);
1037 if (!DSOSymbolsSet
.count(Name
))
1039 lto_symbol_attributes Attrs
= Module
->getSymbolAttributes(I
);
1040 unsigned Scope
= Attrs
& LTO_SYMBOL_SCOPE_MASK
;
1041 if (Scope
!= LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN
)
1042 KeptDSOSyms
.push_back(std::string(Name
));
1045 // We use the first input module as the destination module when
1046 // SetMergedModule is true.
1047 if (SetMergedModule
&& i
== BaseArg
) {
1048 // Transfer ownership to the code generator.
1049 CodeGen
.setModule(std::move(Module
));
1050 } else if (!CodeGen
.addModule(Module
.get())) {
1051 // Print a message here so that we know addModule() did not abort.
1052 error("error adding file '" + InputFilenames
[i
] + "'");
1056 // Add all the exported symbols to the table of symbols to preserve.
1057 for (unsigned i
= 0; i
< ExportedSymbols
.size(); ++i
)
1058 CodeGen
.addMustPreserveSymbol(ExportedSymbols
[i
]);
1060 // Add all the dso symbols to the table of symbols to expose.
1061 for (unsigned i
= 0; i
< KeptDSOSyms
.size(); ++i
)
1062 CodeGen
.addMustPreserveSymbol(KeptDSOSyms
[i
]);
1064 // Set cpu and attrs strings for the default target/subtarget.
1065 CodeGen
.setCpu(codegen::getMCPU());
1067 CodeGen
.setOptLevel(OptLevel
- '0');
1068 CodeGen
.setAttrs(codegen::getMAttrs());
1070 if (auto FT
= codegen::getExplicitFileType())
1071 CodeGen
.setFileType(*FT
);
1073 if (!OutputFilename
.empty()) {
1074 if (LTOSaveBeforeOpt
)
1075 CodeGen
.setSaveIRBeforeOptPath(OutputFilename
+ ".0.preopt.bc");
1077 if (SaveLinkedModuleFile
) {
1078 std::string ModuleFilename
= OutputFilename
;
1079 ModuleFilename
+= ".linked.bc";
1082 if (!CodeGen
.writeMergedModules(ModuleFilename
))
1083 error("writing linked module failed.");
1086 if (!CodeGen
.optimize()) {
1087 // Diagnostic messages should have been printed by the handler.
1088 error("error optimizing the code");
1091 if (SaveModuleFile
) {
1092 std::string ModuleFilename
= OutputFilename
;
1093 ModuleFilename
+= ".merged.bc";
1096 if (!CodeGen
.writeMergedModules(ModuleFilename
))
1097 error("writing merged module failed.");
1102 const Twine
&ModuleName
) -> 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";