[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / llvm / tools / llvm-lto / llvm-lto.cpp
blob64c8c1954ec9bbd90ad720f848b091c3fbab3e2a
1 //===- llvm-lto: a simple command-line program to link modules with LTO ---===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This program takes in a list of bitcode files, links them, performs link-time
10 // optimization, and outputs an object file.
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"
51 #include <algorithm>
52 #include <cassert>
53 #include <cstdint>
54 #include <cstdlib>
55 #include <list>
56 #include <map>
57 #include <memory>
58 #include <string>
59 #include <system_error>
60 #include <tuple>
61 #include <utility>
62 #include <vector>
64 using namespace llvm;
66 static codegen::RegisterCodeGenFlags CGF;
68 static cl::OptionCategory LTOCategory("LTO Options");
70 static cl::opt<char>
71 OptLevel("O",
72 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
73 "(default = '-O2')"),
74 cl::Prefix, cl::init('2'), cl::cat(LTOCategory));
76 static cl::opt<bool>
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));
96 static cl::opt<bool>
97 ThinLTO("thinlto", cl::init(false),
98 cl::desc("Only write combined global index for ThinLTO backends"),
99 cl::cat(LTOCategory));
101 enum ThinLTOModes {
102 THINLINK,
103 THINDISTRIBUTE,
104 THINEMITIMPORTS,
105 THINPROMOTE,
106 THINIMPORT,
107 THININTERNALIZE,
108 THINOPT,
109 THINCODEGEN,
110 THINALL
113 cl::opt<ThinLTOModes> ThinLTOMode(
114 "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
115 cl::values(
116 clEnumValN(
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 "
128 "-thinlto-index)."),
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(
152 "thinlto-module-id",
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));
196 static cl::opt<bool>
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(
211 "exported-symbol",
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),
227 cl::desc(
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"));
235 static cl::opt<bool>
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));
259 static cl::opt<bool>
260 DebugPassManager("debug-pass-manager", cl::init(false), cl::Hidden,
261 cl::desc("Print pass management debugging information"),
262 cl::cat(LTOCategory));
264 static cl::opt<bool>
265 LTOSaveBeforeOpt("lto-save-before-opt", cl::init(false),
266 cl::desc("Save the IR before running optimizations"));
268 namespace {
270 struct ModuleInfo {
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: ";
279 switch (Severity) {
280 case LTO_DS_NOTE:
281 errs() << "note: ";
282 break;
283 case LTO_DS_REMARK:
284 errs() << "remark: ";
285 break;
286 case LTO_DS_ERROR:
287 errs() << "error: ";
288 break;
289 case LTO_DS_WARNING:
290 errs() << "warning: ";
291 break;
293 errs() << Msg << "\n";
296 static std::string CurrentActivity;
298 namespace {
299 struct LLVMLTODiagnosticHandler : public DiagnosticHandler {
300 bool handleDiagnostics(const DiagnosticInfo &DI) override {
301 raw_ostream &OS = errs();
302 OS << "llvm-lto: ";
303 switch (DI.getSeverity()) {
304 case DS_Error:
305 OS << "error";
306 break;
307 case DS_Warning:
308 OS << "warning";
309 break;
310 case DS_Remark:
311 OS << "remark";
312 break;
313 case DS_Note:
314 OS << "note";
315 break;
317 if (!CurrentActivity.empty())
318 OS << ' ' << CurrentActivity;
319 OS << ": ";
321 DiagnosticPrinterRawOStream DP(OS);
322 DI.print(DP);
323 OS << '\n';
325 if (DI.getSeverity() == DS_Error)
326 exit(1);
327 return true;
332 static void error(const Twine &Msg) {
333 errs() << "llvm-lto: " << Msg << '\n';
334 exit(1);
337 static void error(std::error_code EC, const Twine &Prefix) {
338 if (EC)
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>(),
362 true);
363 ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
364 std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
365 Options, Path);
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.
378 if (!Index)
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())) {
386 Functions++;
387 Calls += FuncSummary->calls().size();
388 } else if (isa<AliasSummary>(Summary.get()))
389 Alias++;
390 else
391 Globals++;
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) {
414 // List the symbols.
415 outs() << Filename << ":\n";
416 for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
417 outs() << Module->getSymbolName(I) << "\n";
419 if (QueryHasCtorDtor)
420 outs() << Filename
421 << ": hasCtorDtor = " << (Module->hasCtorDtor() ? "true" : "false")
422 << "\n";
426 static std::unique_ptr<MemoryBuffer> loadFile(StringRef Filename) {
427 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename.str() +
428 "': ");
429 return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
432 static void listDependentLibraries() {
433 for (auto &Filename : InputFilenames) {
434 auto Buffer = loadFile(Filename);
435 std::string E;
436 std::unique_ptr<lto::InputFile> Input(LTOModule::createInputFile(
437 Buffer->getBufferStart(), Buffer->getBufferSize(), Filename.c_str(),
438 E));
439 if (!Input)
440 error(E);
442 // List the dependent libraries.
443 outs() << Filename << ":\n";
444 for (size_t I = 0, C = LTOModule::getDependentLibraryCount(Input.get());
445 I != C; ++I) {
446 size_t L = 0;
447 const char *S = LTOModule::getDependentLibrary(Input.get(), I, &L);
448 assert(S);
449 outs() << StringRef(S, L) << "\n";
454 static void printMachOCPUOnly() {
455 LLVMContext Context;
456 Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
457 true);
458 TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
459 for (auto &Filename : InputFilenames) {
460 ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
461 LTOModule::createFromFile(Context, Filename, Options);
462 if (!ModuleOrErr)
463 error(ModuleOrErr, "llvm-lto: ");
465 Expected<uint32_t> CPUType = (*ModuleOrErr)->getMachOCPUType();
466 Expected<uint32_t> CPUSubType = (*ModuleOrErr)->getMachOCPUSubType();
467 if (!CPUType)
468 error("Error while printing mach-o cputype: " +
469 toString(CPUType.takeError()));
470 if (!CPUSubType)
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);
495 std::error_code EC;
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);
501 OS.close();
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())
523 return Path;
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());
535 namespace thinlto {
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));
548 return InputBuffers;
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 +
555 "': ");
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,
566 LLVMContext &CTX) {
567 auto &Mod = File.getSingleBitcodeModule();
568 auto ModuleOrErr = Mod.parseModule(CTX);
569 if (!ModuleOrErr) {
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) {
587 std::error_code EC;
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 {
595 public:
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]);
614 void run() {
615 switch (ThinLTOMode) {
616 case THINLINK:
617 return thinLink();
618 case THINDISTRIBUTE:
619 return distributedIndexes();
620 case THINEMITIMPORTS:
621 return emitImports();
622 case THINPROMOTE:
623 return promote();
624 case THINIMPORT:
625 return import();
626 case THININTERNALIZE:
627 return internalize();
628 case THINOPT:
629 return optimize();
630 case THINCODEGEN:
631 return codegen();
632 case THINALL:
633 return runAll();
637 private:
638 /// Load the input files, create the combined index, and write it out.
639 void thinLink() {
640 // Perform "ThinLink": just produce the index
641 if (OutputFilename.empty())
642 report_fatal_error(
643 "OutputFilename is necessary to store the combined index.\n");
645 LLVMContext Ctx;
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();
657 if (!CombinedIndex)
658 report_fatal_error("ThinLink didn't create an index");
659 std::error_code EC;
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
668 /// content).
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 "
674 "ones.");
676 std::string OldPrefix, NewPrefix;
677 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
679 auto Index = loadCombinedIndex();
680 for (auto &Filename : InputFilenames) {
681 LLVMContext Ctx;
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);
697 std::error_code EC;
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.
706 void emitImports() {
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 "
711 "ones.");
713 std::string OldPrefix, NewPrefix;
714 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
716 auto Index = loadCombinedIndex();
717 for (auto &Filename : InputFilenames) {
718 LLVMContext Ctx;
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";
726 OutputName =
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
735 /// content).
736 void promote() {
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 "
741 "ones.");
743 auto Index = loadCombinedIndex();
744 for (auto &Filename : InputFilenames) {
745 LLVMContext Ctx;
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).
764 void import() {
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 "
769 "ones.");
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) {
778 LLVMContext Ctx;
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);
793 void internalize() {
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 "
798 "ones.");
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) {
811 LLVMContext Ctx;
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);
826 void optimize() {
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 "
831 "ones.");
832 if (!ThinLTOIndex.empty())
833 errs() << "Warning: -thinlto-index ignored for optimize stage";
835 for (auto &Filename : InputFilenames) {
836 LLVMContext Ctx;
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);
851 void codegen() {
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 "
856 "ones.");
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) {
862 LLVMContext Ctx;
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);
869 ThinGenerator.run();
870 for (auto BinName :
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();
877 return;
880 std::error_code EC;
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
888 void runAll() {
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 "
892 "the input ones.");
894 if (!ThinLTOIndex.empty())
895 errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
897 LLVMContext Ctx;
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);
913 ThinGenerator.run();
914 return;
917 ThinGenerator.run();
919 auto &Binaries = ThinGenerator.getProducedBinaries();
920 if (Binaries.size() != InputFilenames.size())
921 report_fatal_error("Number of output objects does not match the number "
922 "of inputs");
924 for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
925 auto OutputName = InputFilenames[BufID] + ".thinlto.o";
926 std::error_code EC;
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({&LTOCategory, &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);
957 return 0;
960 if (ListDependentLibrariesOnly) {
961 listDependentLibraries();
962 return 0;
965 if (IndexStats) {
966 printIndexStats();
967 return 0;
970 if (CheckHasObjC) {
971 for (auto &Filename : InputFilenames) {
972 ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
973 Filename + "': ");
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";
979 else
980 outs() << "Bitcode " << Filename << " does not contain ObjC\n";
982 return 0;
985 if (PrintMachOCPUOnly) {
986 printMachOCPUOnly();
987 return 0;
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();
995 return 0;
998 if (ThinLTO) {
999 createCombinedModuleSummaryIndex();
1000 return 0;
1003 unsigned BaseArg = 0;
1005 LLVMContext Context;
1006 Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
1007 true);
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))
1040 continue;
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";
1082 std::string ErrMsg;
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";
1096 std::string ErrMsg;
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);
1107 std::error_code EC;
1108 auto S =
1109 std::make_unique<raw_fd_ostream>(PartFilename, EC, sys::fs::OF_None);
1110 if (EC)
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");
1119 } else {
1120 if (Parallelism != 1)
1121 error("-j must be specified together with -o");
1123 if (SaveModuleFile)
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";
1134 return 0;