]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-lto/llvm-lto.cpp
Merge llvm, clang, lld, lldb, compiler-rt and libc++ r306956, and update
[FreeBSD/FreeBSD.git] / contrib / llvm / tools / llvm-lto / llvm-lto.cpp
1 //===-- llvm-lto: a simple command-line program to link modules with LTO --===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This program takes in a list of bitcode files, links them, performs link-time
11 // optimization, and outputs an object file.
12 //
13 //===----------------------------------------------------------------------===//
14
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"
36 #include <list>
37
38 using namespace llvm;
39
40 static cl::opt<char>
41     OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
42                            "(default = '-O2')"),
43              cl::Prefix, cl::ZeroOrMore, cl::init('2'));
44
45 static cl::opt<bool>
46     IndexStats("thinlto-index-stats",
47                cl::desc("Print statistic for the index in every input files"),
48                cl::init(false));
49
50 static cl::opt<bool> DisableVerify(
51     "disable-verify", cl::init(false),
52     cl::desc("Do not run the verifier during the optimization pipeline"));
53
54 static cl::opt<bool> DisableInline("disable-inlining", cl::init(false),
55                                    cl::desc("Do not run the inliner pass"));
56
57 static cl::opt<bool>
58     DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
59                       cl::desc("Do not run the GVN load PRE pass"));
60
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"));
64
65 static cl::opt<bool> EnableFreestanding(
66     "lto-freestanding", cl::init(false),
67     cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
68
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"));
72
73 static cl::opt<bool>
74     ThinLTO("thinlto", cl::init(false),
75             cl::desc("Only write combined global index for ThinLTO backends"));
76
77 enum ThinLTOModes {
78   THINLINK,
79   THINDISTRIBUTE,
80   THINEMITIMPORTS,
81   THINPROMOTE,
82   THINIMPORT,
83   THININTERNALIZE,
84   THINOPT,
85   THINCODEGEN,
86   THINALL
87 };
88
89 cl::opt<ThinLTOModes> ThinLTOMode(
90     "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
91     cl::values(
92         clEnumValN(
93             THINLINK, "thinlink",
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 "
103                                          "-thinlto-index)."),
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")));
110
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."));
115
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."));
122
123 static cl::opt<std::string> ThinLTOModuleId(
124     "thinlto-module-id",
125     cl::desc("For the module ID for the file to process, useful to "
126              "match what is in the index."));
127
128 static cl::opt<std::string>
129     ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
130
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."));
135
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."));
140
141 static cl::opt<bool>
142     SaveModuleFile("save-merged-module", cl::init(false),
143                    cl::desc("Write merged LTO module to file before CodeGen"));
144
145 static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
146                                             cl::desc("<input bitcode files>"));
147
148 static cl::opt<std::string> OutputFilename("o", cl::init(""),
149                                            cl::desc("Override output filename"),
150                                            cl::value_desc("filename"));
151
152 static cl::list<std::string> ExportedSymbols(
153     "exported-symbol",
154     cl::desc("List of symbols to export from the resulting object file"),
155     cl::ZeroOrMore);
156
157 static cl::list<std::string>
158     DSOSymbols("dso-symbol",
159                cl::desc("Symbol to put in the symtab in the resulting dso"),
160                cl::ZeroOrMore);
161
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"));
165
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"));
169
170 static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
171                                      cl::desc("Number of backend threads"));
172
173 static cl::opt<bool> RestoreGlobalsLinkage(
174     "restore-linkage", cl::init(false),
175     cl::desc("Restore original linkage of globals prior to CodeGen"));
176
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"));
180
181 namespace {
182 struct ModuleInfo {
183   std::vector<bool> CanBeHidden;
184 };
185 }
186
187 static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
188                               const char *Msg, void *) {
189   errs() << "llvm-lto: ";
190   switch (Severity) {
191   case LTO_DS_NOTE:
192     errs() << "note: ";
193     break;
194   case LTO_DS_REMARK:
195     errs() << "remark: ";
196     break;
197   case LTO_DS_ERROR:
198     errs() << "error: ";
199     break;
200   case LTO_DS_WARNING:
201     errs() << "warning: ";
202     break;
203   }
204   errs() << Msg << "\n";
205 }
206
207 static std::string CurrentActivity;
208 static void diagnosticHandler(const DiagnosticInfo &DI, void *Context) {
209   raw_ostream &OS = errs();
210   OS << "llvm-lto: ";
211   switch (DI.getSeverity()) {
212   case DS_Error:
213     OS << "error";
214     break;
215   case DS_Warning:
216     OS << "warning";
217     break;
218   case DS_Remark:
219     OS << "remark";
220     break;
221   case DS_Note:
222     OS << "note";
223     break;
224   }
225   if (!CurrentActivity.empty())
226     OS << ' ' << CurrentActivity;
227   OS << ": ";
228
229   DiagnosticPrinterRawOStream DP(OS);
230   DI.print(DP);
231   OS << '\n';
232
233   if (DI.getSeverity() == DS_Error)
234     exit(1);
235 }
236
237 static void error(const Twine &Msg) {
238   errs() << "llvm-lto: " << Msg << '\n';
239   exit(1);
240 }
241
242 static void error(std::error_code EC, const Twine &Prefix) {
243   if (EC)
244     error(Prefix + ": " + EC.message());
245 }
246
247 template <typename T>
248 static void error(const ErrorOr<T> &V, const Twine &Prefix) {
249   error(V.getError(), Prefix);
250 }
251
252 static void maybeVerifyModule(const Module &Mod) {
253   if (!DisableVerify && verifyModule(Mod, &errs()))
254     error("Broken Module");
255 }
256
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(),
269       Options, Path);
270   CurrentActivity = "";
271   maybeVerifyModule((*Ret)->getModule());
272   return std::move(*Ret);
273 }
274
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.
282     if (!Index)
283       report_fatal_error(Filename + " does not contain an index");
284
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())) {
290           Functions++;
291           Calls += FuncSummary->calls().size();
292         } else if (isa<AliasSummary>(Summary.get()))
293           Alias++;
294         else
295           Globals++;
296       }
297     }
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";
303   }
304 }
305
306 /// \brief List symbols in each IR file.
307 ///
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
311 /// contexts.
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);
317
318     // List the symbols.
319     outs() << Filename << ":\n";
320     for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
321       outs() << Module->getSymbolName(I) << "\n";
322   }
323 }
324
325 /// Create a combined index file from the input IR files and write it.
326 ///
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));
337   }
338   std::error_code EC;
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);
344   OS.close();
345 }
346
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();
357 }
358
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())
366     return Path;
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 + "'");
374   }
375   return NewPath.str();
376 }
377
378 namespace thinlto {
379
380 std::vector<std::unique_ptr<MemoryBuffer>>
381 loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
382   std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
383
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));
390   }
391   return InputBuffers;
392 }
393
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 +
398                         "': ");
399   return ExitOnErr(llvm::getModuleSummaryIndexForFile(ThinLTOIndex));
400 }
401
402 static std::unique_ptr<Module> loadModule(StringRef Filename,
403                                           LLVMContext &Ctx) {
404   SMDiagnostic Err;
405   std::unique_ptr<Module> M(parseIRFile(Filename, Err, Ctx));
406   if (!M) {
407     Err.print("llvm-lto", errs());
408     report_fatal_error("Can't load module for file " + Filename);
409   }
410   maybeVerifyModule(*M);
411
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);
416   }
417   return M;
418 }
419
420 static void writeModuleToFile(Module &TheModule, StringRef Filename) {
421   std::error_code EC;
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);
426 }
427
428 class ThinLTOProcessing {
429 public:
430   ThinLTOCodeGenerator ThinGenerator;
431
432   ThinLTOProcessing(const TargetOptions &Options) {
433     ThinGenerator.setCodePICModel(getRelocModel());
434     ThinGenerator.setTargetOptions(Options);
435     ThinGenerator.setCacheDir(ThinLTOCacheDir);
436     ThinGenerator.setFreestanding(EnableFreestanding);
437
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]);
441   }
442
443   void run() {
444     switch (ThinLTOMode) {
445     case THINLINK:
446       return thinLink();
447     case THINDISTRIBUTE:
448       return distributedIndexes();
449     case THINEMITIMPORTS:
450       return emitImports();
451     case THINPROMOTE:
452       return promote();
453     case THINIMPORT:
454       return import();
455     case THININTERNALIZE:
456       return internalize();
457     case THINOPT:
458       return optimize();
459     case THINCODEGEN:
460       return codegen();
461     case THINALL:
462       return runAll();
463     }
464   }
465
466 private:
467   /// Load the input files, create the combined index, and write it out.
468   void thinLink() {
469     // Perform "ThinLink": just produce the index
470     if (OutputFilename.empty())
471       report_fatal_error(
472           "OutputFilename is necessary to store the combined index.\n");
473
474     LLVMContext Ctx;
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());
483     }
484
485     auto CombinedIndex = ThinGenerator.linkCombinedIndex();
486     if (!CombinedIndex)
487       report_fatal_error("ThinLink didn't create an index");
488     std::error_code EC;
489     raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::F_None);
490     error(EC, "error opening the file '" + OutputFilename + "'");
491     WriteIndexToFile(*CombinedIndex, OS);
492     return;
493   }
494
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
498   /// content).
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 "
504                          "ones.");
505
506     std::string OldPrefix, NewPrefix;
507     getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
508
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);
516
517       std::string OutputName = OutputFilename;
518       if (OutputName.empty()) {
519         OutputName = Filename + ".thinlto.bc";
520       }
521       OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
522       std::error_code EC;
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);
526     }
527   }
528
529   /// Load the combined index from disk, compute the imports, and emit
530   /// the import file lists for each module to disk.
531   void emitImports() {
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 "
536                          "ones.");
537
538     std::string OldPrefix, NewPrefix;
539     getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
540
541     auto Index = loadCombinedIndex();
542     for (auto &Filename : InputFilenames) {
543       std::string OutputName = OutputFilename;
544       if (OutputName.empty()) {
545         OutputName = Filename + ".imports";
546       }
547       OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
548       ThinLTOCodeGenerator::emitImports(Filename, OutputName, *Index);
549     }
550   }
551
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
555   /// content).
556   void promote() {
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 "
561                          "ones.");
562
563     auto Index = loadCombinedIndex();
564     for (auto &Filename : InputFilenames) {
565       LLVMContext Ctx;
566       auto TheModule = loadModule(Filename, Ctx);
567
568       ThinGenerator.promote(*TheModule, *Index);
569
570       std::string OutputName = OutputFilename;
571       if (OutputName.empty()) {
572         OutputName = Filename + ".thinlto.promoted.bc";
573       }
574       writeModuleToFile(*TheModule, OutputName);
575     }
576   }
577
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).
582   void import() {
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 "
587                          "ones.");
588
589     auto Index = loadCombinedIndex();
590     auto InputBuffers = loadAllFilesForIndex(*Index);
591     for (auto &MemBuffer : InputBuffers)
592       ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
593                               MemBuffer->getBuffer());
594
595     for (auto &Filename : InputFilenames) {
596       LLVMContext Ctx;
597       auto TheModule = loadModule(Filename, Ctx);
598
599       ThinGenerator.crossModuleImport(*TheModule, *Index);
600
601       std::string OutputName = OutputFilename;
602       if (OutputName.empty()) {
603         OutputName = Filename + ".thinlto.imported.bc";
604       }
605       writeModuleToFile(*TheModule, OutputName);
606     }
607   }
608
609   void internalize() {
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 "
614                          "ones.");
615
616     if (ExportedSymbols.empty())
617       errs() << "Warning: -internalize will not perform without "
618                 "-exported-symbol\n";
619
620     auto Index = loadCombinedIndex();
621     auto InputBuffers = loadAllFilesForIndex(*Index);
622     for (auto &MemBuffer : InputBuffers)
623       ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
624                               MemBuffer->getBuffer());
625
626     for (auto &Filename : InputFilenames) {
627       LLVMContext Ctx;
628       auto TheModule = loadModule(Filename, Ctx);
629
630       ThinGenerator.internalize(*TheModule, *Index);
631
632       std::string OutputName = OutputFilename;
633       if (OutputName.empty()) {
634         OutputName = Filename + ".thinlto.internalized.bc";
635       }
636       writeModuleToFile(*TheModule, OutputName);
637     }
638   }
639
640   void optimize() {
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 "
645                          "ones.");
646     if (!ThinLTOIndex.empty())
647       errs() << "Warning: -thinlto-index ignored for optimize stage";
648
649     for (auto &Filename : InputFilenames) {
650       LLVMContext Ctx;
651       auto TheModule = loadModule(Filename, Ctx);
652
653       ThinGenerator.optimize(*TheModule);
654
655       std::string OutputName = OutputFilename;
656       if (OutputName.empty()) {
657         OutputName = Filename + ".thinlto.imported.bc";
658       }
659       writeModuleToFile(*TheModule, OutputName);
660     }
661   }
662
663   void codegen() {
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 "
668                          "ones.");
669     if (!ThinLTOIndex.empty())
670       errs() << "Warning: -thinlto-index ignored for codegen stage";
671
672     std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
673     for (auto &Filename : InputFilenames) {
674       LLVMContext Ctx;
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());
679     }
680     ThinGenerator.setCodeGenOnly(true);
681     ThinGenerator.run();
682     for (auto BinName :
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();
689         return;
690       }
691
692       std::error_code EC;
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();
696     }
697   }
698
699   /// Full ThinLTO process
700   void runAll() {
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 "
704                          "the input ones.");
705
706     if (!ThinLTOIndex.empty())
707       errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
708
709     LLVMContext Ctx;
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());
718     }
719
720     if (!ThinLTOSaveTempsPrefix.empty())
721       ThinGenerator.setSaveTempsDir(ThinLTOSaveTempsPrefix);
722
723     if (!ThinLTOGeneratedObjectsDir.empty()) {
724       ThinGenerator.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir);
725       ThinGenerator.run();
726       return;
727     }
728
729     ThinGenerator.run();
730
731     auto &Binaries = ThinGenerator.getProducedBinaries();
732     if (Binaries.size() != InputFilenames.size())
733       report_fatal_error("Number of output objects does not match the number "
734                          "of inputs");
735
736     for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
737       auto OutputName = InputFilenames[BufID] + ".thinlto.o";
738       std::error_code EC;
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();
742     }
743   }
744
745   /// Load the combined index from disk, then load every file referenced by
746 };
747
748 } // namespace thinlto
749
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);
754
755   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
756   cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
757
758   if (OptLevel < '0' || OptLevel > '3')
759     error("optimization level must be between 0 and 3");
760
761   // Initialize the configured targets.
762   InitializeAllTargets();
763   InitializeAllTargetMCs();
764   InitializeAllAsmPrinters();
765   InitializeAllAsmParsers();
766
767   // set up the TargetOptions for the machine
768   TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
769
770   if (ListSymbolsOnly) {
771     listSymbols(Options);
772     return 0;
773   }
774
775   if (IndexStats) {
776     printIndexStats();
777     return 0;
778   }
779
780   if (CheckHasObjC) {
781     for (auto &Filename : InputFilenames) {
782       ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
783                             Filename + "': ");
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";
789       else
790         outs() << "Bitcode " << Filename << " does not contain ObjC\n";
791     }
792     return 0;
793   }
794
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();
800     return 0;
801   }
802
803   if (ThinLTO) {
804     createCombinedModuleSummaryIndex();
805     return 0;
806   }
807
808   unsigned BaseArg = 0;
809
810   LLVMContext Context;
811   Context.setDiagnosticHandler(diagnosticHandler, nullptr, true);
812
813   LTOCodeGenerator CodeGen(Context);
814
815   if (UseDiagnosticHandler)
816     CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
817
818   CodeGen.setCodePICModel(getRelocModel());
819   CodeGen.setFreestanding(EnableFreestanding);
820
821   CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
822   CodeGen.setTargetOptions(Options);
823   CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
824
825   llvm::StringSet<llvm::MallocAllocator> DSOSymbolsSet;
826   for (unsigned i = 0; i < DSOSymbols.size(); ++i)
827     DSOSymbolsSet.insert(DSOSymbols[i]);
828
829   std::vector<std::string> KeptDSOSyms;
830
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 = "";
837
838     unsigned NumSyms = Module->getSymbolCount();
839     for (unsigned I = 0; I < NumSyms; ++I) {
840       StringRef Name = Module->getSymbolName(I);
841       if (!DSOSymbolsSet.count(Name))
842         continue;
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);
847     }
848
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] + "'");
857     }
858   }
859
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]);
863
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]);
867
868   // Set cpu and attrs strings for the default target/subtarget.
869   CodeGen.setCpu(MCPU.c_str());
870
871   CodeGen.setOptLevel(OptLevel - '0');
872
873   std::string attrs;
874   for (unsigned i = 0; i < MAttrs.size(); ++i) {
875     if (i > 0)
876       attrs.append(",");
877     attrs.append(MAttrs[i]);
878   }
879
880   if (!attrs.empty())
881     CodeGen.setAttr(attrs);
882
883   if (FileType.getNumOccurrences())
884     CodeGen.setFileType(FileType);
885
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");
891     }
892
893     if (SaveModuleFile) {
894       std::string ModuleFilename = OutputFilename;
895       ModuleFilename += ".merged.bc";
896       std::string ErrMsg;
897
898       if (!CodeGen.writeMergedModules(ModuleFilename))
899         error("writing merged module failed.");
900     }
901
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);
908       std::error_code EC;
909       OSs.emplace_back(PartFilename, EC, sys::fs::F_None);
910       if (EC)
911         error("error opening the file '" + PartFilename + "': " + EC.message());
912       OSPtrs.push_back(&OSs.back().os());
913     }
914
915     if (!CodeGen.compileOptimized(OSPtrs))
916       // Diagnostic messages should have been printed by the handler.
917       error("error compiling the code");
918
919     for (tool_output_file &OS : OSs)
920       OS.keep();
921   } else {
922     if (Parallelism != 1)
923       error("-j must be specified together with -o");
924
925     if (SaveModuleFile)
926       error(": -save-merged-module must be specified with -o");
927
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.
933
934     outs() << "Wrote native object file '" << OutputName << "'\n";
935   }
936
937   return 0;
938 }