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/ADT/StringSet.h"
16 #include "llvm/Bitcode/BitcodeReader.h"
17 #include "llvm/Bitcode/BitcodeWriter.h"
18 #include "llvm/CodeGen/CommandFlags.h"
19 #include "llvm/IR/DiagnosticPrinter.h"
20 #include "llvm/IR/LLVMContext.h"
21 #include "llvm/IR/Verifier.h"
22 #include "llvm/IRReader/IRReader.h"
23 #include "llvm/LTO/legacy/LTOCodeGenerator.h"
24 #include "llvm/LTO/legacy/LTOModule.h"
25 #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
26 #include "llvm/Support/CommandLine.h"
27 #include "llvm/Support/FileSystem.h"
28 #include "llvm/Support/ManagedStatic.h"
29 #include "llvm/Support/Path.h"
30 #include "llvm/Support/PrettyStackTrace.h"
31 #include "llvm/Support/Signals.h"
32 #include "llvm/Support/SourceMgr.h"
33 #include "llvm/Support/TargetSelect.h"
34 #include "llvm/Support/ToolOutputFile.h"
35 #include "llvm/Support/raw_ostream.h"
41 OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
43 cl::Prefix, cl::ZeroOrMore, cl::init('2'));
46 IndexStats("thinlto-index-stats",
47 cl::desc("Print statistic for the index in every input files"),
50 static cl::opt<bool> DisableVerify(
51 "disable-verify", cl::init(false),
52 cl::desc("Do not run the verifier during the optimization pipeline"));
54 static cl::opt<bool> DisableInline("disable-inlining", cl::init(false),
55 cl::desc("Do not run the inliner pass"));
58 DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
59 cl::desc("Do not run the GVN load PRE pass"));
61 static cl::opt<bool> DisableLTOVectorization(
62 "disable-lto-vectorization", cl::init(false),
63 cl::desc("Do not run loop or slp vectorization during LTO"));
65 static cl::opt<bool> EnableFreestanding(
66 "lto-freestanding", cl::init(false),
67 cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
69 static cl::opt<bool> UseDiagnosticHandler(
70 "use-diagnostic-handler", cl::init(false),
71 cl::desc("Use a diagnostic handler to test the handler interface"));
74 ThinLTO("thinlto", cl::init(false),
75 cl::desc("Only write combined global index for ThinLTO backends"));
89 cl::opt<ThinLTOModes> ThinLTOMode(
90 "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
94 "ThinLink: produces the index by linking only the summaries."),
95 clEnumValN(THINDISTRIBUTE, "distributedindexes",
96 "Produces individual indexes for distributed backends."),
97 clEnumValN(THINEMITIMPORTS, "emitimports",
98 "Emit imports files for distributed backends."),
99 clEnumValN(THINPROMOTE, "promote",
100 "Perform pre-import promotion (requires -thinlto-index)."),
101 clEnumValN(THINIMPORT, "import", "Perform both promotion and "
102 "cross-module importing (requires "
104 clEnumValN(THININTERNALIZE, "internalize",
105 "Perform internalization driven by -exported-symbol "
106 "(requires -thinlto-index)."),
107 clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
108 clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
109 clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end")));
111 static cl::opt<std::string>
112 ThinLTOIndex("thinlto-index",
113 cl::desc("Provide the index produced by a ThinLink, required "
114 "to perform the promotion and/or importing."));
116 static cl::opt<std::string> ThinLTOPrefixReplace(
117 "thinlto-prefix-replace",
118 cl::desc("Control where files for distributed backends are "
119 "created. Expects 'oldprefix;newprefix' and if path "
120 "prefix of output file is oldprefix it will be "
121 "replaced with newprefix."));
123 static cl::opt<std::string> ThinLTOModuleId(
125 cl::desc("For the module ID for the file to process, useful to "
126 "match what is in the index."));
128 static cl::opt<std::string>
129 ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
131 static cl::opt<std::string> ThinLTOSaveTempsPrefix(
132 "thinlto-save-temps",
133 cl::desc("Save ThinLTO temp files using filenames created by adding "
134 "suffixes to the given file path prefix."));
136 static cl::opt<std::string> ThinLTOGeneratedObjectsDir(
137 "thinlto-save-objects",
138 cl::desc("Save ThinLTO generated object files using filenames created in "
139 "the given directory."));
142 SaveModuleFile("save-merged-module", cl::init(false),
143 cl::desc("Write merged LTO module to file before CodeGen"));
145 static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
146 cl::desc("<input bitcode files>"));
148 static cl::opt<std::string> OutputFilename("o", cl::init(""),
149 cl::desc("Override output filename"),
150 cl::value_desc("filename"));
152 static cl::list<std::string> ExportedSymbols(
154 cl::desc("List of symbols to export from the resulting object file"),
157 static cl::list<std::string>
158 DSOSymbols("dso-symbol",
159 cl::desc("Symbol to put in the symtab in the resulting dso"),
162 static cl::opt<bool> ListSymbolsOnly(
163 "list-symbols-only", cl::init(false),
164 cl::desc("Instead of running LTO, list the symbols in each IR file"));
166 static cl::opt<bool> SetMergedModule(
167 "set-merged-module", cl::init(false),
168 cl::desc("Use the first input module as the merged module"));
170 static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
171 cl::desc("Number of backend threads"));
173 static cl::opt<bool> RestoreGlobalsLinkage(
174 "restore-linkage", cl::init(false),
175 cl::desc("Restore original linkage of globals prior to CodeGen"));
177 static cl::opt<bool> CheckHasObjC(
178 "check-for-objc", cl::init(false),
179 cl::desc("Only check if the module has objective-C defined in it"));
183 std::vector<bool> CanBeHidden;
187 static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
188 const char *Msg, void *) {
189 errs() << "llvm-lto: ";
195 errs() << "remark: ";
201 errs() << "warning: ";
204 errs() << Msg << "\n";
207 static std::string CurrentActivity;
208 static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
209 raw_ostream &OS = errs();
211 switch (DI.getSeverity()) {
225 if (!CurrentActivity.empty())
226 OS << ' ' << CurrentActivity;
229 DiagnosticPrinterRawOStream DP(OS);
233 if (DI.getSeverity() == DS_Error)
237 static void error(const Twine &Msg) {
238 errs() << "llvm-lto: " << Msg << '\n';
242 static void error(std::error_code EC, const Twine &Prefix) {
244 error(Prefix + ": " + EC.message());
247 template <typename T>
248 static void error(const ErrorOr<T> &V, const Twine &Prefix) {
249 error(V.getError(), Prefix);
252 static void maybeVerifyModule(const Module &Mod) {
253 if (!DisableVerify && verifyModule(Mod, &errs()))
254 error("Broken Module");
257 static std::unique_ptr<LTOModule>
258 getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
259 const TargetOptions &Options) {
260 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
261 MemoryBuffer::getFile(Path);
262 error(BufferOrErr, "error loading file '" + Path + "'");
263 Buffer = std::move(BufferOrErr.get());
264 CurrentActivity = ("loading file '" + Path + "'").str();
265 std::unique_ptr<LLVMContext> Context = llvm::make_unique<LLVMContext>();
266 Context->setDiagnosticHandler(diagnosticHandler, nullptr, true);
267 ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
268 std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
270 CurrentActivity = "";
271 maybeVerifyModule((*Ret)->getModule());
272 return std::move(*Ret);
275 /// Print some statistics on the index for each input files.
276 void printIndexStats() {
277 for (auto &Filename : InputFilenames) {
278 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
279 std::unique_ptr<ModuleSummaryIndex> Index =
280 ExitOnErr(llvm::getModuleSummaryIndexForFile(Filename));
281 // Skip files without a module summary.
283 report_fatal_error(Filename + " does not contain an index");
285 unsigned Calls = 0, Refs = 0, Functions = 0, Alias = 0, Globals = 0;
286 for (auto &Summaries : *Index) {
287 for (auto &Summary : Summaries.second.SummaryList) {
288 Refs += Summary->refs().size();
289 if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
291 Calls += FuncSummary->calls().size();
292 } else if (isa<AliasSummary>(Summary.get()))
298 outs() << "Index " << Filename << " contains "
299 << (Alias + Globals + Functions) << " nodes (" << Functions
300 << " functions, " << Alias << " alias, " << Globals
301 << " globals) and " << (Calls + Refs) << " edges (" << Refs
302 << " refs and " << Calls << " calls)\n";
306 /// \brief List symbols in each IR file.
308 /// The main point here is to provide lit-testable coverage for the LTOModule
309 /// functionality that's exposed by the C API to list symbols. Moreover, this
310 /// provides testing coverage for modules that have been created in their own
312 static void listSymbols(const TargetOptions &Options) {
313 for (auto &Filename : InputFilenames) {
314 std::unique_ptr<MemoryBuffer> Buffer;
315 std::unique_ptr<LTOModule> Module =
316 getLocalLTOModule(Filename, Buffer, Options);
319 outs() << Filename << ":\n";
320 for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
321 outs() << Module->getSymbolName(I) << "\n";
325 /// Create a combined index file from the input IR files and write it.
327 /// This is meant to enable testing of ThinLTO combined index generation,
328 /// currently available via the gold plugin via -thinlto.
329 static void createCombinedModuleSummaryIndex() {
330 ModuleSummaryIndex CombinedIndex;
331 uint64_t NextModuleId = 0;
332 for (auto &Filename : InputFilenames) {
333 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
334 std::unique_ptr<MemoryBuffer> MB =
335 ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
336 ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex, ++NextModuleId));
339 assert(!OutputFilename.empty());
340 raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
341 sys::fs::OpenFlags::F_None);
342 error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
343 WriteIndexToFile(CombinedIndex, OS);
347 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
348 /// \p NewPrefix strings, if it was specified.
349 static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
350 std::string &NewPrefix) {
351 assert(ThinLTOPrefixReplace.empty() ||
352 ThinLTOPrefixReplace.find(";") != StringRef::npos);
353 StringRef PrefixReplace = ThinLTOPrefixReplace;
354 std::pair<StringRef, StringRef> Split = PrefixReplace.split(";");
355 OldPrefix = Split.first.str();
356 NewPrefix = Split.second.str();
359 /// Given the original \p Path to an output file, replace any path
360 /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
361 /// resulting directory if it does not yet exist.
362 static std::string getThinLTOOutputFile(const std::string &Path,
363 const std::string &OldPrefix,
364 const std::string &NewPrefix) {
365 if (OldPrefix.empty() && NewPrefix.empty())
367 SmallString<128> NewPath(Path);
368 llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
369 StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
370 if (!ParentPath.empty()) {
371 // Make sure the new directory exists, creating it if necessary.
372 if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
373 error(EC, "error creating the directory '" + ParentPath + "'");
375 return NewPath.str();
380 std::vector<std::unique_ptr<MemoryBuffer>>
381 loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
382 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
384 for (auto &ModPath : Index.modulePaths()) {
385 const auto &Filename = ModPath.first();
386 auto CurrentActivity = "loading file '" + Filename + "'";
387 auto InputOrErr = MemoryBuffer::getFile(Filename);
388 error(InputOrErr, "error " + CurrentActivity);
389 InputBuffers.push_back(std::move(*InputOrErr));
394 std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() {
395 if (ThinLTOIndex.empty())
396 report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
397 ExitOnError ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex +
399 return ExitOnErr(llvm::getModuleSummaryIndexForFile(ThinLTOIndex));
402 static std::unique_ptr<Module> loadModule(StringRef Filename,
405 std::unique_ptr<Module> M(parseIRFile(Filename, Err, Ctx));
407 Err.print("llvm-lto", errs());
408 report_fatal_error("Can't load module for file " + Filename);
410 maybeVerifyModule(*M);
412 if (ThinLTOModuleId.getNumOccurrences()) {
413 if (InputFilenames.size() != 1)
414 report_fatal_error("Can't override the module id for multiple files");
415 M->setModuleIdentifier(ThinLTOModuleId);
420 static void writeModuleToFile(Module &TheModule, StringRef Filename) {
422 raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::F_None);
423 error(EC, "error opening the file '" + Filename + "'");
424 maybeVerifyModule(TheModule);
425 WriteBitcodeToFile(&TheModule, OS, /* ShouldPreserveUseListOrder */ true);
428 class ThinLTOProcessing {
430 ThinLTOCodeGenerator ThinGenerator;
432 ThinLTOProcessing(const TargetOptions &Options) {
433 ThinGenerator.setCodePICModel(getRelocModel());
434 ThinGenerator.setTargetOptions(Options);
435 ThinGenerator.setCacheDir(ThinLTOCacheDir);
436 ThinGenerator.setFreestanding(EnableFreestanding);
438 // Add all the exported symbols to the table of symbols to preserve.
439 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
440 ThinGenerator.preserveSymbol(ExportedSymbols[i]);
444 switch (ThinLTOMode) {
448 return distributedIndexes();
449 case THINEMITIMPORTS:
450 return emitImports();
455 case THININTERNALIZE:
456 return internalize();
467 /// Load the input files, create the combined index, and write it out.
469 // Perform "ThinLink": just produce the index
470 if (OutputFilename.empty())
472 "OutputFilename is necessary to store the combined index.\n");
475 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
476 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
477 auto &Filename = InputFilenames[i];
478 StringRef CurrentActivity = "loading file '" + Filename + "'";
479 auto InputOrErr = MemoryBuffer::getFile(Filename);
480 error(InputOrErr, "error " + CurrentActivity);
481 InputBuffers.push_back(std::move(*InputOrErr));
482 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
485 auto CombinedIndex = ThinGenerator.linkCombinedIndex();
487 report_fatal_error("ThinLink didn't create an index");
489 raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::F_None);
490 error(EC, "error opening the file '" + OutputFilename + "'");
491 WriteIndexToFile(*CombinedIndex, OS);
495 /// Load the combined index from disk, then compute and generate
496 /// individual index files suitable for ThinLTO distributed backend builds
497 /// on the files mentioned on the command line (these must match the index
499 void distributedIndexes() {
500 if (InputFilenames.size() != 1 && !OutputFilename.empty())
501 report_fatal_error("Can't handle a single output filename and multiple "
502 "input files, do not provide an output filename and "
503 "the output files will be suffixed from the input "
506 std::string OldPrefix, NewPrefix;
507 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
509 auto Index = loadCombinedIndex();
510 for (auto &Filename : InputFilenames) {
511 // Build a map of module to the GUIDs and summary objects that should
512 // be written to its index.
513 std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
514 ThinLTOCodeGenerator::gatherImportedSummariesForModule(
515 Filename, *Index, ModuleToSummariesForIndex);
517 std::string OutputName = OutputFilename;
518 if (OutputName.empty()) {
519 OutputName = Filename + ".thinlto.bc";
521 OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
523 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
524 error(EC, "error opening the file '" + OutputName + "'");
525 WriteIndexToFile(*Index, OS, &ModuleToSummariesForIndex);
529 /// Load the combined index from disk, compute the imports, and emit
530 /// the import file lists for each module to disk.
532 if (InputFilenames.size() != 1 && !OutputFilename.empty())
533 report_fatal_error("Can't handle a single output filename and multiple "
534 "input files, do not provide an output filename and "
535 "the output files will be suffixed from the input "
538 std::string OldPrefix, NewPrefix;
539 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
541 auto Index = loadCombinedIndex();
542 for (auto &Filename : InputFilenames) {
543 std::string OutputName = OutputFilename;
544 if (OutputName.empty()) {
545 OutputName = Filename + ".imports";
547 OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
548 ThinLTOCodeGenerator::emitImports(Filename, OutputName, *Index);
552 /// Load the combined index from disk, then load every file referenced by
553 /// the index and add them to the generator, finally perform the promotion
554 /// on the files mentioned on the command line (these must match the index
557 if (InputFilenames.size() != 1 && !OutputFilename.empty())
558 report_fatal_error("Can't handle a single output filename and multiple "
559 "input files, do not provide an output filename and "
560 "the output files will be suffixed from the input "
563 auto Index = loadCombinedIndex();
564 for (auto &Filename : InputFilenames) {
566 auto TheModule = loadModule(Filename, Ctx);
568 ThinGenerator.promote(*TheModule, *Index);
570 std::string OutputName = OutputFilename;
571 if (OutputName.empty()) {
572 OutputName = Filename + ".thinlto.promoted.bc";
574 writeModuleToFile(*TheModule, OutputName);
578 /// Load the combined index from disk, then load every file referenced by
579 /// the index and add them to the generator, then performs the promotion and
580 /// cross module importing on the files mentioned on the command line
581 /// (these must match the index content).
583 if (InputFilenames.size() != 1 && !OutputFilename.empty())
584 report_fatal_error("Can't handle a single output filename and multiple "
585 "input files, do not provide an output filename and "
586 "the output files will be suffixed from the input "
589 auto Index = loadCombinedIndex();
590 auto InputBuffers = loadAllFilesForIndex(*Index);
591 for (auto &MemBuffer : InputBuffers)
592 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
593 MemBuffer->getBuffer());
595 for (auto &Filename : InputFilenames) {
597 auto TheModule = loadModule(Filename, Ctx);
599 ThinGenerator.crossModuleImport(*TheModule, *Index);
601 std::string OutputName = OutputFilename;
602 if (OutputName.empty()) {
603 OutputName = Filename + ".thinlto.imported.bc";
605 writeModuleToFile(*TheModule, OutputName);
610 if (InputFilenames.size() != 1 && !OutputFilename.empty())
611 report_fatal_error("Can't handle a single output filename and multiple "
612 "input files, do not provide an output filename and "
613 "the output files will be suffixed from the input "
616 if (ExportedSymbols.empty())
617 errs() << "Warning: -internalize will not perform without "
618 "-exported-symbol\n";
620 auto Index = loadCombinedIndex();
621 auto InputBuffers = loadAllFilesForIndex(*Index);
622 for (auto &MemBuffer : InputBuffers)
623 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
624 MemBuffer->getBuffer());
626 for (auto &Filename : InputFilenames) {
628 auto TheModule = loadModule(Filename, Ctx);
630 ThinGenerator.internalize(*TheModule, *Index);
632 std::string OutputName = OutputFilename;
633 if (OutputName.empty()) {
634 OutputName = Filename + ".thinlto.internalized.bc";
636 writeModuleToFile(*TheModule, OutputName);
641 if (InputFilenames.size() != 1 && !OutputFilename.empty())
642 report_fatal_error("Can't handle a single output filename and multiple "
643 "input files, do not provide an output filename and "
644 "the output files will be suffixed from the input "
646 if (!ThinLTOIndex.empty())
647 errs() << "Warning: -thinlto-index ignored for optimize stage";
649 for (auto &Filename : InputFilenames) {
651 auto TheModule = loadModule(Filename, Ctx);
653 ThinGenerator.optimize(*TheModule);
655 std::string OutputName = OutputFilename;
656 if (OutputName.empty()) {
657 OutputName = Filename + ".thinlto.imported.bc";
659 writeModuleToFile(*TheModule, OutputName);
664 if (InputFilenames.size() != 1 && !OutputFilename.empty())
665 report_fatal_error("Can't handle a single output filename and multiple "
666 "input files, do not provide an output filename and "
667 "the output files will be suffixed from the input "
669 if (!ThinLTOIndex.empty())
670 errs() << "Warning: -thinlto-index ignored for codegen stage";
672 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
673 for (auto &Filename : InputFilenames) {
675 auto InputOrErr = MemoryBuffer::getFile(Filename);
676 error(InputOrErr, "error " + CurrentActivity);
677 InputBuffers.push_back(std::move(*InputOrErr));
678 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
680 ThinGenerator.setCodeGenOnly(true);
683 zip(ThinGenerator.getProducedBinaries(), InputFilenames)) {
684 std::string OutputName = OutputFilename;
685 if (OutputName.empty())
686 OutputName = std::get<1>(BinName) + ".thinlto.o";
687 else if (OutputName == "-") {
688 outs() << std::get<0>(BinName)->getBuffer();
693 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
694 error(EC, "error opening the file '" + OutputName + "'");
695 OS << std::get<0>(BinName)->getBuffer();
699 /// Full ThinLTO process
701 if (!OutputFilename.empty())
702 report_fatal_error("Do not provide an output filename for ThinLTO "
703 " processing, the output files will be suffixed from "
706 if (!ThinLTOIndex.empty())
707 errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
710 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
711 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
712 auto &Filename = InputFilenames[i];
713 StringRef CurrentActivity = "loading file '" + Filename + "'";
714 auto InputOrErr = MemoryBuffer::getFile(Filename);
715 error(InputOrErr, "error " + CurrentActivity);
716 InputBuffers.push_back(std::move(*InputOrErr));
717 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
720 if (!ThinLTOSaveTempsPrefix.empty())
721 ThinGenerator.setSaveTempsDir(ThinLTOSaveTempsPrefix);
723 if (!ThinLTOGeneratedObjectsDir.empty()) {
724 ThinGenerator.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir);
731 auto &Binaries = ThinGenerator.getProducedBinaries();
732 if (Binaries.size() != InputFilenames.size())
733 report_fatal_error("Number of output objects does not match the number "
736 for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
737 auto OutputName = InputFilenames[BufID] + ".thinlto.o";
739 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
740 error(EC, "error opening the file '" + OutputName + "'");
741 OS << Binaries[BufID]->getBuffer();
745 /// Load the combined index from disk, then load every file referenced by
748 } // namespace thinlto
750 int main(int argc, char **argv) {
751 // Print a stack trace if we signal out.
752 sys::PrintStackTraceOnErrorSignal(argv[0]);
753 PrettyStackTraceProgram X(argc, argv);
755 llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
756 cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
758 if (OptLevel < '0' || OptLevel > '3')
759 error("optimization level must be between 0 and 3");
761 // Initialize the configured targets.
762 InitializeAllTargets();
763 InitializeAllTargetMCs();
764 InitializeAllAsmPrinters();
765 InitializeAllAsmParsers();
767 // set up the TargetOptions for the machine
768 TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
770 if (ListSymbolsOnly) {
771 listSymbols(Options);
781 for (auto &Filename : InputFilenames) {
782 ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
784 std::unique_ptr<MemoryBuffer> BufferOrErr =
785 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename)));
786 auto Buffer = std::move(BufferOrErr.get());
787 if (ExitOnErr(llvm::isBitcodeContainingObjCCategory(*Buffer)))
788 outs() << "Bitcode " << Filename << " contains ObjC\n";
790 outs() << "Bitcode " << Filename << " does not contain ObjC\n";
795 if (ThinLTOMode.getNumOccurrences()) {
796 if (ThinLTOMode.getNumOccurrences() > 1)
797 report_fatal_error("You can't specify more than one -thinlto-action");
798 thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
799 ThinLTOProcessor.run();
804 createCombinedModuleSummaryIndex();
808 unsigned BaseArg = 0;
811 Context.setDiagnosticHandler(diagnosticHandler, nullptr, true);
813 LTOCodeGenerator CodeGen(Context);
815 if (UseDiagnosticHandler)
816 CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
818 CodeGen.setCodePICModel(getRelocModel());
819 CodeGen.setFreestanding(EnableFreestanding);
821 CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
822 CodeGen.setTargetOptions(Options);
823 CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
825 llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet;
826 for (unsigned i = 0; i < DSOSymbols.size(); ++i)
827 DSOSymbolsSet.insert(DSOSymbols[i]);
829 std::vector<std::string> KeptDSOSyms;
831 for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
832 CurrentActivity = "loading file '" + InputFilenames[i] + "'";
833 ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
834 LTOModule::createFromFile(Context, InputFilenames[i], Options);
835 std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
836 CurrentActivity = "";
838 unsigned NumSyms = Module->getSymbolCount();
839 for (unsigned I = 0; I < NumSyms; ++I) {
840 StringRef Name = Module->getSymbolName(I);
841 if (!DSOSymbolsSet.count(Name))
843 lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
844 unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
845 if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
846 KeptDSOSyms.push_back(Name);
849 // We use the first input module as the destination module when
850 // SetMergedModule is true.
851 if (SetMergedModule && i == BaseArg) {
852 // Transfer ownership to the code generator.
853 CodeGen.setModule(std::move(Module));
854 } else if (!CodeGen.addModule(Module.get())) {
855 // Print a message here so that we know addModule() did not abort.
856 error("error adding file '" + InputFilenames[i] + "'");
860 // Add all the exported symbols to the table of symbols to preserve.
861 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
862 CodeGen.addMustPreserveSymbol(ExportedSymbols[i]);
864 // Add all the dso symbols to the table of symbols to expose.
865 for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
866 CodeGen.addMustPreserveSymbol(KeptDSOSyms[i]);
868 // Set cpu and attrs strings for the default target/subtarget.
869 CodeGen.setCpu(MCPU.c_str());
871 CodeGen.setOptLevel(OptLevel - '0');
874 for (unsigned i = 0; i < MAttrs.size(); ++i) {
877 attrs.append(MAttrs[i]);
881 CodeGen.setAttr(attrs);
883 if (FileType.getNumOccurrences())
884 CodeGen.setFileType(FileType);
886 if (!OutputFilename.empty()) {
887 if (!CodeGen.optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
888 DisableLTOVectorization)) {
889 // Diagnostic messages should have been printed by the handler.
890 error("error optimizing the code");
893 if (SaveModuleFile) {
894 std::string ModuleFilename = OutputFilename;
895 ModuleFilename += ".merged.bc";
898 if (!CodeGen.writeMergedModules(ModuleFilename))
899 error("writing merged module failed.");
902 std::list<tool_output_file> OSs;
903 std::vector<raw_pwrite_stream *> OSPtrs;
904 for (unsigned I = 0; I != Parallelism; ++I) {
905 std::string PartFilename = OutputFilename;
906 if (Parallelism != 1)
907 PartFilename += "." + utostr(I);
909 OSs.emplace_back(PartFilename, EC, sys::fs::F_None);
911 error("error opening the file '" + PartFilename + "': " + EC.message());
912 OSPtrs.push_back(&OSs.back().os());
915 if (!CodeGen.compileOptimized(OSPtrs))
916 // Diagnostic messages should have been printed by the handler.
917 error("error compiling the code");
919 for (tool_output_file &OS : OSs)
922 if (Parallelism != 1)
923 error("-j must be specified together with -o");
926 error(": -save-merged-module must be specified with -o");
928 const char *OutputName = nullptr;
929 if (!CodeGen.compile_to_file(&OutputName, DisableVerify, DisableInline,
930 DisableGVNLoadPRE, DisableLTOVectorization))
931 error("error compiling the code");
932 // Diagnostic messages should have been printed by the handler.
934 outs() << "Wrote native object file '" << OutputName << "'\n";