1 //===- llvm-lto: a simple command-line program to link modules with LTO ---===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This program takes in a list of bitcode files, links them, performs link-time
11 // optimization, and outputs an object file.
13 //===----------------------------------------------------------------------===//
15 #include "llvm-c/lto.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/ADT/STLExtras.h"
18 #include "llvm/ADT/SmallString.h"
19 #include "llvm/ADT/StringExtras.h"
20 #include "llvm/ADT/StringRef.h"
21 #include "llvm/ADT/StringSet.h"
22 #include "llvm/ADT/Twine.h"
23 #include "llvm/Bitcode/BitcodeReader.h"
24 #include "llvm/Bitcode/BitcodeWriter.h"
25 #include "llvm/CodeGen/CommandFlags.inc"
26 #include "llvm/IR/DiagnosticInfo.h"
27 #include "llvm/IR/DiagnosticPrinter.h"
28 #include "llvm/IR/LLVMContext.h"
29 #include "llvm/IR/Module.h"
30 #include "llvm/IR/ModuleSummaryIndex.h"
31 #include "llvm/IR/Verifier.h"
32 #include "llvm/IRReader/IRReader.h"
33 #include "llvm/LTO/legacy/LTOCodeGenerator.h"
34 #include "llvm/LTO/legacy/LTOModule.h"
35 #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
36 #include "llvm/Support/Allocator.h"
37 #include "llvm/Support/Casting.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/Error.h"
40 #include "llvm/Support/ErrorHandling.h"
41 #include "llvm/Support/ErrorOr.h"
42 #include "llvm/Support/FileSystem.h"
43 #include "llvm/Support/InitLLVM.h"
44 #include "llvm/Support/MemoryBuffer.h"
45 #include "llvm/Support/Path.h"
46 #include "llvm/Support/SourceMgr.h"
47 #include "llvm/Support/TargetSelect.h"
48 #include "llvm/Support/ToolOutputFile.h"
49 #include "llvm/Support/raw_ostream.h"
50 #include "llvm/Target/TargetOptions.h"
59 #include <system_error>
67 OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
69 cl::Prefix, cl::ZeroOrMore, cl::init('2'));
72 IndexStats("thinlto-index-stats",
73 cl::desc("Print statistic for the index in every input files"),
76 static cl::opt<bool> DisableVerify(
77 "disable-verify", cl::init(false),
78 cl::desc("Do not run the verifier during the optimization pipeline"));
80 static cl::opt<bool> DisableInline("disable-inlining", cl::init(false),
81 cl::desc("Do not run the inliner pass"));
84 DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
85 cl::desc("Do not run the GVN load PRE pass"));
87 static cl::opt<bool> DisableLTOVectorization(
88 "disable-lto-vectorization", cl::init(false),
89 cl::desc("Do not run loop or slp vectorization during LTO"));
91 static cl::opt<bool> EnableFreestanding(
92 "lto-freestanding", cl::init(false),
93 cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
95 static cl::opt<bool> UseDiagnosticHandler(
96 "use-diagnostic-handler", cl::init(false),
97 cl::desc("Use a diagnostic handler to test the handler interface"));
100 ThinLTO("thinlto", cl::init(false),
101 cl::desc("Only write combined global index for ThinLTO backends"));
115 cl::opt<ThinLTOModes> ThinLTOMode(
116 "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
119 THINLINK, "thinlink",
120 "ThinLink: produces the index by linking only the summaries."),
121 clEnumValN(THINDISTRIBUTE, "distributedindexes",
122 "Produces individual indexes for distributed backends."),
123 clEnumValN(THINEMITIMPORTS, "emitimports",
124 "Emit imports files for distributed backends."),
125 clEnumValN(THINPROMOTE, "promote",
126 "Perform pre-import promotion (requires -thinlto-index)."),
127 clEnumValN(THINIMPORT, "import", "Perform both promotion and "
128 "cross-module importing (requires "
130 clEnumValN(THININTERNALIZE, "internalize",
131 "Perform internalization driven by -exported-symbol "
132 "(requires -thinlto-index)."),
133 clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
134 clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
135 clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end")));
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."));
142 static cl::opt<std::string> ThinLTOPrefixReplace(
143 "thinlto-prefix-replace",
144 cl::desc("Control where files for distributed backends are "
145 "created. Expects 'oldprefix;newprefix' and if path "
146 "prefix of output file is oldprefix it will be "
147 "replaced with newprefix."));
149 static cl::opt<std::string> ThinLTOModuleId(
151 cl::desc("For the module ID for the file to process, useful to "
152 "match what is in the index."));
154 static cl::opt<std::string>
155 ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
158 ThinLTOCachePruningInterval("thinlto-cache-pruning-interval",
159 cl::init(1200), cl::desc("Set ThinLTO cache pruning interval."));
162 ThinLTOCacheMaxSizeBytes("thinlto-cache-max-size-bytes",
163 cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."));
166 ThinLTOCacheMaxSizeFiles("thinlto-cache-max-size-files", cl::init(1000000),
167 cl::desc("Set ThinLTO cache pruning directory maximum number of files."));
169 static cl::opt<std::string> ThinLTOSaveTempsPrefix(
170 "thinlto-save-temps",
171 cl::desc("Save ThinLTO temp files using filenames created by adding "
172 "suffixes to the given file path prefix."));
174 static cl::opt<std::string> ThinLTOGeneratedObjectsDir(
175 "thinlto-save-objects",
176 cl::desc("Save ThinLTO generated object files using filenames created in "
177 "the given directory."));
180 SaveModuleFile("save-merged-module", cl::init(false),
181 cl::desc("Write merged LTO module to file before CodeGen"));
183 static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
184 cl::desc("<input bitcode files>"));
186 static cl::opt<std::string> OutputFilename("o", cl::init(""),
187 cl::desc("Override output filename"),
188 cl::value_desc("filename"));
190 static cl::list<std::string> ExportedSymbols(
192 cl::desc("List of symbols to export from the resulting object file"),
195 static cl::list<std::string>
196 DSOSymbols("dso-symbol",
197 cl::desc("Symbol to put in the symtab in the resulting dso"),
200 static cl::opt<bool> ListSymbolsOnly(
201 "list-symbols-only", cl::init(false),
202 cl::desc("Instead of running LTO, list the symbols in each IR file"));
204 static cl::opt<bool> SetMergedModule(
205 "set-merged-module", cl::init(false),
206 cl::desc("Use the first input module as the merged module"));
208 static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
209 cl::desc("Number of backend threads"));
211 static cl::opt<bool> RestoreGlobalsLinkage(
212 "restore-linkage", cl::init(false),
213 cl::desc("Restore original linkage of globals prior to CodeGen"));
215 static cl::opt<bool> CheckHasObjC(
216 "check-for-objc", cl::init(false),
217 cl::desc("Only check if the module has objective-C defined in it"));
222 std::vector<bool> CanBeHidden;
225 } // end anonymous namespace
227 static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
228 const char *Msg, void *) {
229 errs() << "llvm-lto: ";
235 errs() << "remark: ";
241 errs() << "warning: ";
244 errs() << Msg << "\n";
247 static std::string CurrentActivity;
250 struct LLVMLTODiagnosticHandler : public DiagnosticHandler {
251 bool handleDiagnostics(const DiagnosticInfo &DI) override {
252 raw_ostream &OS = errs();
254 switch (DI.getSeverity()) {
268 if (!CurrentActivity.empty())
269 OS << ' ' << CurrentActivity;
272 DiagnosticPrinterRawOStream DP(OS);
276 if (DI.getSeverity() == DS_Error)
283 static void error(const Twine &Msg) {
284 errs() << "llvm-lto: " << Msg << '\n';
288 static void error(std::error_code EC, const Twine &Prefix) {
290 error(Prefix + ": " + EC.message());
293 template <typename T>
294 static void error(const ErrorOr<T> &V, const Twine &Prefix) {
295 error(V.getError(), Prefix);
298 static void maybeVerifyModule(const Module &Mod) {
299 if (!DisableVerify && verifyModule(Mod, &errs()))
300 error("Broken Module");
303 static std::unique_ptr<LTOModule>
304 getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
305 const TargetOptions &Options) {
306 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
307 MemoryBuffer::getFile(Path);
308 error(BufferOrErr, "error loading file '" + Path + "'");
309 Buffer = std::move(BufferOrErr.get());
310 CurrentActivity = ("loading file '" + Path + "'").str();
311 std::unique_ptr<LLVMContext> Context = llvm::make_unique<LLVMContext>();
312 Context->setDiagnosticHandler(llvm::make_unique<LLVMLTODiagnosticHandler>(),
314 ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
315 std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
317 CurrentActivity = "";
318 maybeVerifyModule((*Ret)->getModule());
319 return std::move(*Ret);
322 /// Print some statistics on the index for each input files.
323 void printIndexStats() {
324 for (auto &Filename : InputFilenames) {
325 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
326 std::unique_ptr<ModuleSummaryIndex> Index =
327 ExitOnErr(getModuleSummaryIndexForFile(Filename));
328 // Skip files without a module summary.
330 report_fatal_error(Filename + " does not contain an index");
332 unsigned Calls = 0, Refs = 0, Functions = 0, Alias = 0, Globals = 0;
333 for (auto &Summaries : *Index) {
334 for (auto &Summary : Summaries.second.SummaryList) {
335 Refs += Summary->refs().size();
336 if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
338 Calls += FuncSummary->calls().size();
339 } else if (isa<AliasSummary>(Summary.get()))
345 outs() << "Index " << Filename << " contains "
346 << (Alias + Globals + Functions) << " nodes (" << Functions
347 << " functions, " << Alias << " alias, " << Globals
348 << " globals) and " << (Calls + Refs) << " edges (" << Refs
349 << " refs and " << Calls << " calls)\n";
353 /// List symbols in each IR file.
355 /// The main point here is to provide lit-testable coverage for the LTOModule
356 /// functionality that's exposed by the C API to list symbols. Moreover, this
357 /// provides testing coverage for modules that have been created in their own
359 static void listSymbols(const TargetOptions &Options) {
360 for (auto &Filename : InputFilenames) {
361 std::unique_ptr<MemoryBuffer> Buffer;
362 std::unique_ptr<LTOModule> Module =
363 getLocalLTOModule(Filename, Buffer, Options);
366 outs() << Filename << ":\n";
367 for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
368 outs() << Module->getSymbolName(I) << "\n";
372 /// Create a combined index file from the input IR files and write it.
374 /// This is meant to enable testing of ThinLTO combined index generation,
375 /// currently available via the gold plugin via -thinlto.
376 static void createCombinedModuleSummaryIndex() {
377 ModuleSummaryIndex CombinedIndex(/*HaveGVs=*/false);
378 uint64_t NextModuleId = 0;
379 for (auto &Filename : InputFilenames) {
380 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
381 std::unique_ptr<MemoryBuffer> MB =
382 ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
383 ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex, NextModuleId++));
386 assert(!OutputFilename.empty());
387 raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
388 sys::fs::OpenFlags::F_None);
389 error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
390 WriteIndexToFile(CombinedIndex, OS);
394 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
395 /// \p NewPrefix strings, if it was specified.
396 static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
397 std::string &NewPrefix) {
398 assert(ThinLTOPrefixReplace.empty() ||
399 ThinLTOPrefixReplace.find(";") != StringRef::npos);
400 StringRef PrefixReplace = ThinLTOPrefixReplace;
401 std::pair<StringRef, StringRef> Split = PrefixReplace.split(";");
402 OldPrefix = Split.first.str();
403 NewPrefix = Split.second.str();
406 /// Given the original \p Path to an output file, replace any path
407 /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
408 /// resulting directory if it does not yet exist.
409 static std::string getThinLTOOutputFile(const std::string &Path,
410 const std::string &OldPrefix,
411 const std::string &NewPrefix) {
412 if (OldPrefix.empty() && NewPrefix.empty())
414 SmallString<128> NewPath(Path);
415 llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
416 StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
417 if (!ParentPath.empty()) {
418 // Make sure the new directory exists, creating it if necessary.
419 if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
420 error(EC, "error creating the directory '" + ParentPath + "'");
422 return NewPath.str();
427 std::vector<std::unique_ptr<MemoryBuffer>>
428 loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
429 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
431 for (auto &ModPath : Index.modulePaths()) {
432 const auto &Filename = ModPath.first();
433 std::string CurrentActivity = ("loading file '" + Filename + "'").str();
434 auto InputOrErr = MemoryBuffer::getFile(Filename);
435 error(InputOrErr, "error " + CurrentActivity);
436 InputBuffers.push_back(std::move(*InputOrErr));
441 std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() {
442 if (ThinLTOIndex.empty())
443 report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
444 ExitOnError ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex +
446 return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex));
449 static std::unique_ptr<Module> loadModule(StringRef Filename,
452 std::unique_ptr<Module> M(parseIRFile(Filename, Err, Ctx));
454 Err.print("llvm-lto", errs());
455 report_fatal_error("Can't load module for file " + Filename);
457 maybeVerifyModule(*M);
459 if (ThinLTOModuleId.getNumOccurrences()) {
460 if (InputFilenames.size() != 1)
461 report_fatal_error("Can't override the module id for multiple files");
462 M->setModuleIdentifier(ThinLTOModuleId);
467 static void writeModuleToFile(Module &TheModule, StringRef Filename) {
469 raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::F_None);
470 error(EC, "error opening the file '" + Filename + "'");
471 maybeVerifyModule(TheModule);
472 WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
475 class ThinLTOProcessing {
477 ThinLTOCodeGenerator ThinGenerator;
479 ThinLTOProcessing(const TargetOptions &Options) {
480 ThinGenerator.setCodePICModel(getRelocModel());
481 ThinGenerator.setTargetOptions(Options);
482 ThinGenerator.setCacheDir(ThinLTOCacheDir);
483 ThinGenerator.setCachePruningInterval(ThinLTOCachePruningInterval);
484 ThinGenerator.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles);
485 ThinGenerator.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes);
486 ThinGenerator.setFreestanding(EnableFreestanding);
488 // Add all the exported symbols to the table of symbols to preserve.
489 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
490 ThinGenerator.preserveSymbol(ExportedSymbols[i]);
494 switch (ThinLTOMode) {
498 return distributedIndexes();
499 case THINEMITIMPORTS:
500 return emitImports();
505 case THININTERNALIZE:
506 return internalize();
517 /// Load the input files, create the combined index, and write it out.
519 // Perform "ThinLink": just produce the index
520 if (OutputFilename.empty())
522 "OutputFilename is necessary to store the combined index.\n");
525 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
526 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
527 auto &Filename = InputFilenames[i];
528 std::string CurrentActivity = "loading file '" + Filename + "'";
529 auto InputOrErr = MemoryBuffer::getFile(Filename);
530 error(InputOrErr, "error " + CurrentActivity);
531 InputBuffers.push_back(std::move(*InputOrErr));
532 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
535 auto CombinedIndex = ThinGenerator.linkCombinedIndex();
537 report_fatal_error("ThinLink didn't create an index");
539 raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::F_None);
540 error(EC, "error opening the file '" + OutputFilename + "'");
541 WriteIndexToFile(*CombinedIndex, OS);
544 /// Load the combined index from disk, then compute and generate
545 /// individual index files suitable for ThinLTO distributed backend builds
546 /// on the files mentioned on the command line (these must match the index
548 void distributedIndexes() {
549 if (InputFilenames.size() != 1 && !OutputFilename.empty())
550 report_fatal_error("Can't handle a single output filename and multiple "
551 "input files, do not provide an output filename and "
552 "the output files will be suffixed from the input "
555 std::string OldPrefix, NewPrefix;
556 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
558 auto Index = loadCombinedIndex();
559 for (auto &Filename : InputFilenames) {
560 // Build a map of module to the GUIDs and summary objects that should
561 // be written to its index.
562 std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
563 ThinLTOCodeGenerator::gatherImportedSummariesForModule(
564 Filename, *Index, ModuleToSummariesForIndex);
566 std::string OutputName = OutputFilename;
567 if (OutputName.empty()) {
568 OutputName = Filename + ".thinlto.bc";
570 OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
572 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
573 error(EC, "error opening the file '" + OutputName + "'");
574 WriteIndexToFile(*Index, OS, &ModuleToSummariesForIndex);
578 /// Load the combined index from disk, compute the imports, and emit
579 /// the import file lists for each module to disk.
581 if (InputFilenames.size() != 1 && !OutputFilename.empty())
582 report_fatal_error("Can't handle a single output filename and multiple "
583 "input files, do not provide an output filename and "
584 "the output files will be suffixed from the input "
587 std::string OldPrefix, NewPrefix;
588 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
590 auto Index = loadCombinedIndex();
591 for (auto &Filename : InputFilenames) {
592 std::string OutputName = OutputFilename;
593 if (OutputName.empty()) {
594 OutputName = Filename + ".imports";
596 OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
597 ThinLTOCodeGenerator::emitImports(Filename, OutputName, *Index);
601 /// Load the combined index from disk, then load every file referenced by
602 /// the index and add them to the generator, finally perform the promotion
603 /// on the files mentioned on the command line (these must match the index
606 if (InputFilenames.size() != 1 && !OutputFilename.empty())
607 report_fatal_error("Can't handle a single output filename and multiple "
608 "input files, do not provide an output filename and "
609 "the output files will be suffixed from the input "
612 auto Index = loadCombinedIndex();
613 for (auto &Filename : InputFilenames) {
615 auto TheModule = loadModule(Filename, Ctx);
617 ThinGenerator.promote(*TheModule, *Index);
619 std::string OutputName = OutputFilename;
620 if (OutputName.empty()) {
621 OutputName = Filename + ".thinlto.promoted.bc";
623 writeModuleToFile(*TheModule, OutputName);
627 /// Load the combined index from disk, then load every file referenced by
628 /// the index and add them to the generator, then performs the promotion and
629 /// cross module importing on the files mentioned on the command line
630 /// (these must match the index content).
632 if (InputFilenames.size() != 1 && !OutputFilename.empty())
633 report_fatal_error("Can't handle a single output filename and multiple "
634 "input files, do not provide an output filename and "
635 "the output files will be suffixed from the input "
638 auto Index = loadCombinedIndex();
639 auto InputBuffers = loadAllFilesForIndex(*Index);
640 for (auto &MemBuffer : InputBuffers)
641 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
642 MemBuffer->getBuffer());
644 for (auto &Filename : InputFilenames) {
646 auto TheModule = loadModule(Filename, Ctx);
648 ThinGenerator.crossModuleImport(*TheModule, *Index);
650 std::string OutputName = OutputFilename;
651 if (OutputName.empty()) {
652 OutputName = Filename + ".thinlto.imported.bc";
654 writeModuleToFile(*TheModule, OutputName);
659 if (InputFilenames.size() != 1 && !OutputFilename.empty())
660 report_fatal_error("Can't handle a single output filename and multiple "
661 "input files, do not provide an output filename and "
662 "the output files will be suffixed from the input "
665 if (ExportedSymbols.empty())
666 errs() << "Warning: -internalize will not perform without "
667 "-exported-symbol\n";
669 auto Index = loadCombinedIndex();
670 auto InputBuffers = loadAllFilesForIndex(*Index);
671 for (auto &MemBuffer : InputBuffers)
672 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
673 MemBuffer->getBuffer());
675 for (auto &Filename : InputFilenames) {
677 auto TheModule = loadModule(Filename, Ctx);
679 ThinGenerator.internalize(*TheModule, *Index);
681 std::string OutputName = OutputFilename;
682 if (OutputName.empty()) {
683 OutputName = Filename + ".thinlto.internalized.bc";
685 writeModuleToFile(*TheModule, OutputName);
690 if (InputFilenames.size() != 1 && !OutputFilename.empty())
691 report_fatal_error("Can't handle a single output filename and multiple "
692 "input files, do not provide an output filename and "
693 "the output files will be suffixed from the input "
695 if (!ThinLTOIndex.empty())
696 errs() << "Warning: -thinlto-index ignored for optimize stage";
698 for (auto &Filename : InputFilenames) {
700 auto TheModule = loadModule(Filename, Ctx);
702 ThinGenerator.optimize(*TheModule);
704 std::string OutputName = OutputFilename;
705 if (OutputName.empty()) {
706 OutputName = Filename + ".thinlto.imported.bc";
708 writeModuleToFile(*TheModule, OutputName);
713 if (InputFilenames.size() != 1 && !OutputFilename.empty())
714 report_fatal_error("Can't handle a single output filename and multiple "
715 "input files, do not provide an output filename and "
716 "the output files will be suffixed from the input "
718 if (!ThinLTOIndex.empty())
719 errs() << "Warning: -thinlto-index ignored for codegen stage";
721 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
722 for (auto &Filename : InputFilenames) {
724 auto InputOrErr = MemoryBuffer::getFile(Filename);
725 error(InputOrErr, "error " + CurrentActivity);
726 InputBuffers.push_back(std::move(*InputOrErr));
727 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
729 ThinGenerator.setCodeGenOnly(true);
732 zip(ThinGenerator.getProducedBinaries(), InputFilenames)) {
733 std::string OutputName = OutputFilename;
734 if (OutputName.empty())
735 OutputName = std::get<1>(BinName) + ".thinlto.o";
736 else if (OutputName == "-") {
737 outs() << std::get<0>(BinName)->getBuffer();
742 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
743 error(EC, "error opening the file '" + OutputName + "'");
744 OS << std::get<0>(BinName)->getBuffer();
748 /// Full ThinLTO process
750 if (!OutputFilename.empty())
751 report_fatal_error("Do not provide an output filename for ThinLTO "
752 " processing, the output files will be suffixed from "
755 if (!ThinLTOIndex.empty())
756 errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
759 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
760 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
761 auto &Filename = InputFilenames[i];
762 std::string CurrentActivity = "loading file '" + Filename + "'";
763 auto InputOrErr = MemoryBuffer::getFile(Filename);
764 error(InputOrErr, "error " + CurrentActivity);
765 InputBuffers.push_back(std::move(*InputOrErr));
766 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
769 if (!ThinLTOSaveTempsPrefix.empty())
770 ThinGenerator.setSaveTempsDir(ThinLTOSaveTempsPrefix);
772 if (!ThinLTOGeneratedObjectsDir.empty()) {
773 ThinGenerator.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir);
780 auto &Binaries = ThinGenerator.getProducedBinaries();
781 if (Binaries.size() != InputFilenames.size())
782 report_fatal_error("Number of output objects does not match the number "
785 for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
786 auto OutputName = InputFilenames[BufID] + ".thinlto.o";
788 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
789 error(EC, "error opening the file '" + OutputName + "'");
790 OS << Binaries[BufID]->getBuffer();
794 /// Load the combined index from disk, then load every file referenced by
797 } // end namespace thinlto
799 int main(int argc, char **argv) {
800 InitLLVM X(argc, argv);
801 cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
803 if (OptLevel < '0' || OptLevel > '3')
804 error("optimization level must be between 0 and 3");
806 // Initialize the configured targets.
807 InitializeAllTargets();
808 InitializeAllTargetMCs();
809 InitializeAllAsmPrinters();
810 InitializeAllAsmParsers();
812 // set up the TargetOptions for the machine
813 TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
815 if (ListSymbolsOnly) {
816 listSymbols(Options);
826 for (auto &Filename : InputFilenames) {
827 ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
829 std::unique_ptr<MemoryBuffer> BufferOrErr =
830 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename)));
831 auto Buffer = std::move(BufferOrErr.get());
832 if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer)))
833 outs() << "Bitcode " << Filename << " contains ObjC\n";
835 outs() << "Bitcode " << Filename << " does not contain ObjC\n";
840 if (ThinLTOMode.getNumOccurrences()) {
841 if (ThinLTOMode.getNumOccurrences() > 1)
842 report_fatal_error("You can't specify more than one -thinlto-action");
843 thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
844 ThinLTOProcessor.run();
849 createCombinedModuleSummaryIndex();
853 unsigned BaseArg = 0;
856 Context.setDiagnosticHandler(llvm::make_unique<LLVMLTODiagnosticHandler>(),
859 LTOCodeGenerator CodeGen(Context);
861 if (UseDiagnosticHandler)
862 CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
864 CodeGen.setCodePICModel(getRelocModel());
865 CodeGen.setFreestanding(EnableFreestanding);
867 CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
868 CodeGen.setTargetOptions(Options);
869 CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
871 StringSet<MallocAllocator> DSOSymbolsSet;
872 for (unsigned i = 0; i < DSOSymbols.size(); ++i)
873 DSOSymbolsSet.insert(DSOSymbols[i]);
875 std::vector<std::string> KeptDSOSyms;
877 for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
878 CurrentActivity = "loading file '" + InputFilenames[i] + "'";
879 ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
880 LTOModule::createFromFile(Context, InputFilenames[i], Options);
881 std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
882 CurrentActivity = "";
884 unsigned NumSyms = Module->getSymbolCount();
885 for (unsigned I = 0; I < NumSyms; ++I) {
886 StringRef Name = Module->getSymbolName(I);
887 if (!DSOSymbolsSet.count(Name))
889 lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
890 unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
891 if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
892 KeptDSOSyms.push_back(Name);
895 // We use the first input module as the destination module when
896 // SetMergedModule is true.
897 if (SetMergedModule && i == BaseArg) {
898 // Transfer ownership to the code generator.
899 CodeGen.setModule(std::move(Module));
900 } else if (!CodeGen.addModule(Module.get())) {
901 // Print a message here so that we know addModule() did not abort.
902 error("error adding file '" + InputFilenames[i] + "'");
906 // Add all the exported symbols to the table of symbols to preserve.
907 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
908 CodeGen.addMustPreserveSymbol(ExportedSymbols[i]);
910 // Add all the dso symbols to the table of symbols to expose.
911 for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
912 CodeGen.addMustPreserveSymbol(KeptDSOSyms[i]);
914 // Set cpu and attrs strings for the default target/subtarget.
915 CodeGen.setCpu(MCPU.c_str());
917 CodeGen.setOptLevel(OptLevel - '0');
920 for (unsigned i = 0; i < MAttrs.size(); ++i) {
923 attrs.append(MAttrs[i]);
927 CodeGen.setAttr(attrs);
929 if (FileType.getNumOccurrences())
930 CodeGen.setFileType(FileType);
932 if (!OutputFilename.empty()) {
933 if (!CodeGen.optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
934 DisableLTOVectorization)) {
935 // Diagnostic messages should have been printed by the handler.
936 error("error optimizing the code");
939 if (SaveModuleFile) {
940 std::string ModuleFilename = OutputFilename;
941 ModuleFilename += ".merged.bc";
944 if (!CodeGen.writeMergedModules(ModuleFilename))
945 error("writing merged module failed.");
948 std::list<ToolOutputFile> OSs;
949 std::vector<raw_pwrite_stream *> OSPtrs;
950 for (unsigned I = 0; I != Parallelism; ++I) {
951 std::string PartFilename = OutputFilename;
952 if (Parallelism != 1)
953 PartFilename += "." + utostr(I);
955 OSs.emplace_back(PartFilename, EC, sys::fs::F_None);
957 error("error opening the file '" + PartFilename + "': " + EC.message());
958 OSPtrs.push_back(&OSs.back().os());
961 if (!CodeGen.compileOptimized(OSPtrs))
962 // Diagnostic messages should have been printed by the handler.
963 error("error compiling the code");
965 for (ToolOutputFile &OS : OSs)
968 if (Parallelism != 1)
969 error("-j must be specified together with -o");
972 error(": -save-merged-module must be specified with -o");
974 const char *OutputName = nullptr;
975 if (!CodeGen.compile_to_file(&OutputName, DisableVerify, DisableInline,
976 DisableGVNLoadPRE, DisableLTOVectorization))
977 error("error compiling the code");
978 // Diagnostic messages should have been printed by the handler.
980 outs() << "Wrote native object file '" << OutputName << "'\n";