]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - contrib/llvm/tools/llvm-lto/llvm-lto.cpp
Upgrade LDNS to 1.7.0.
[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-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.def"
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/ManagedStatic.h"
44 #include "llvm/Support/MemoryBuffer.h"
45 #include "llvm/Support/Path.h"
46 #include "llvm/Support/PrettyStackTrace.h"
47 #include "llvm/Support/Signals.h"
48 #include "llvm/Support/SourceMgr.h"
49 #include "llvm/Support/TargetSelect.h"
50 #include "llvm/Support/ToolOutputFile.h"
51 #include "llvm/Support/raw_ostream.h"
52 #include "llvm/Target/TargetOptions.h"
53 #include <algorithm>
54 #include <cassert>
55 #include <cstdint>
56 #include <cstdlib>
57 #include <list>
58 #include <map>
59 #include <memory>
60 #include <string>
61 #include <system_error>
62 #include <tuple>
63 #include <utility>
64 #include <vector>
65
66 using namespace llvm;
67
68 static cl::opt<char>
69     OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
70                            "(default = '-O2')"),
71              cl::Prefix, cl::ZeroOrMore, cl::init('2'));
72
73 static cl::opt<bool>
74     IndexStats("thinlto-index-stats",
75                cl::desc("Print statistic for the index in every input files"),
76                cl::init(false));
77
78 static cl::opt<bool> DisableVerify(
79     "disable-verify", cl::init(false),
80     cl::desc("Do not run the verifier during the optimization pipeline"));
81
82 static cl::opt<bool> DisableInline("disable-inlining", cl::init(false),
83                                    cl::desc("Do not run the inliner pass"));
84
85 static cl::opt<bool>
86     DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
87                       cl::desc("Do not run the GVN load PRE pass"));
88
89 static cl::opt<bool> DisableLTOVectorization(
90     "disable-lto-vectorization", cl::init(false),
91     cl::desc("Do not run loop or slp vectorization during LTO"));
92
93 static cl::opt<bool> EnableFreestanding(
94     "lto-freestanding", cl::init(false),
95     cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
96
97 static cl::opt<bool> UseDiagnosticHandler(
98     "use-diagnostic-handler", cl::init(false),
99     cl::desc("Use a diagnostic handler to test the handler interface"));
100
101 static cl::opt<bool>
102     ThinLTO("thinlto", cl::init(false),
103             cl::desc("Only write combined global index for ThinLTO backends"));
104
105 enum ThinLTOModes {
106   THINLINK,
107   THINDISTRIBUTE,
108   THINEMITIMPORTS,
109   THINPROMOTE,
110   THINIMPORT,
111   THININTERNALIZE,
112   THINOPT,
113   THINCODEGEN,
114   THINALL
115 };
116
117 cl::opt<ThinLTOModes> ThinLTOMode(
118     "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
119     cl::values(
120         clEnumValN(
121             THINLINK, "thinlink",
122             "ThinLink: produces the index by linking only the summaries."),
123         clEnumValN(THINDISTRIBUTE, "distributedindexes",
124                    "Produces individual indexes for distributed backends."),
125         clEnumValN(THINEMITIMPORTS, "emitimports",
126                    "Emit imports files for distributed backends."),
127         clEnumValN(THINPROMOTE, "promote",
128                    "Perform pre-import promotion (requires -thinlto-index)."),
129         clEnumValN(THINIMPORT, "import", "Perform both promotion and "
130                                          "cross-module importing (requires "
131                                          "-thinlto-index)."),
132         clEnumValN(THININTERNALIZE, "internalize",
133                    "Perform internalization driven by -exported-symbol "
134                    "(requires -thinlto-index)."),
135         clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
136         clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
137         clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end")));
138
139 static cl::opt<std::string>
140     ThinLTOIndex("thinlto-index",
141                  cl::desc("Provide the index produced by a ThinLink, required "
142                           "to perform the promotion and/or importing."));
143
144 static cl::opt<std::string> ThinLTOPrefixReplace(
145     "thinlto-prefix-replace",
146     cl::desc("Control where files for distributed backends are "
147              "created. Expects 'oldprefix;newprefix' and if path "
148              "prefix of output file is oldprefix it will be "
149              "replaced with newprefix."));
150
151 static cl::opt<std::string> ThinLTOModuleId(
152     "thinlto-module-id",
153     cl::desc("For the module ID for the file to process, useful to "
154              "match what is in the index."));
155
156 static cl::opt<std::string>
157     ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
158
159 static cl::opt<int>
160     ThinLTOCachePruningInterval("thinlto-cache-pruning-interval", cl::desc("Set ThinLTO cache pruning interval."));
161
162 static cl::opt<std::string> ThinLTOSaveTempsPrefix(
163     "thinlto-save-temps",
164     cl::desc("Save ThinLTO temp files using filenames created by adding "
165              "suffixes to the given file path prefix."));
166
167 static cl::opt<std::string> ThinLTOGeneratedObjectsDir(
168     "thinlto-save-objects",
169     cl::desc("Save ThinLTO generated object files using filenames created in "
170              "the given directory."));
171
172 static cl::opt<bool>
173     SaveModuleFile("save-merged-module", cl::init(false),
174                    cl::desc("Write merged LTO module to file before CodeGen"));
175
176 static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
177                                             cl::desc("<input bitcode files>"));
178
179 static cl::opt<std::string> OutputFilename("o", cl::init(""),
180                                            cl::desc("Override output filename"),
181                                            cl::value_desc("filename"));
182
183 static cl::list<std::string> ExportedSymbols(
184     "exported-symbol",
185     cl::desc("List of symbols to export from the resulting object file"),
186     cl::ZeroOrMore);
187
188 static cl::list<std::string>
189     DSOSymbols("dso-symbol",
190                cl::desc("Symbol to put in the symtab in the resulting dso"),
191                cl::ZeroOrMore);
192
193 static cl::opt<bool> ListSymbolsOnly(
194     "list-symbols-only", cl::init(false),
195     cl::desc("Instead of running LTO, list the symbols in each IR file"));
196
197 static cl::opt<bool> SetMergedModule(
198     "set-merged-module", cl::init(false),
199     cl::desc("Use the first input module as the merged module"));
200
201 static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
202                                      cl::desc("Number of backend threads"));
203
204 static cl::opt<bool> RestoreGlobalsLinkage(
205     "restore-linkage", cl::init(false),
206     cl::desc("Restore original linkage of globals prior to CodeGen"));
207
208 static cl::opt<bool> CheckHasObjC(
209     "check-for-objc", cl::init(false),
210     cl::desc("Only check if the module has objective-C defined in it"));
211
212 namespace {
213
214 struct ModuleInfo {
215   std::vector<bool> CanBeHidden;
216 };
217
218 } // end anonymous namespace
219
220 static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
221                               const char *Msg, void *) {
222   errs() << "llvm-lto: ";
223   switch (Severity) {
224   case LTO_DS_NOTE:
225     errs() << "note: ";
226     break;
227   case LTO_DS_REMARK:
228     errs() << "remark: ";
229     break;
230   case LTO_DS_ERROR:
231     errs() << "error: ";
232     break;
233   case LTO_DS_WARNING:
234     errs() << "warning: ";
235     break;
236   }
237   errs() << Msg << "\n";
238 }
239
240 static std::string CurrentActivity;
241
242 namespace {
243   struct LLVMLTODiagnosticHandler : public DiagnosticHandler {
244     bool handleDiagnostics(const DiagnosticInfo &DI) override {
245       raw_ostream &OS = errs();
246       OS << "llvm-lto: ";
247       switch (DI.getSeverity()) {
248       case DS_Error:
249         OS << "error";
250         break;
251       case DS_Warning:
252         OS << "warning";
253         break;
254       case DS_Remark:
255         OS << "remark";
256         break;
257       case DS_Note:
258         OS << "note";
259         break;
260       }
261       if (!CurrentActivity.empty())
262         OS << ' ' << CurrentActivity;
263       OS << ": ";
264   
265       DiagnosticPrinterRawOStream DP(OS);
266       DI.print(DP);
267       OS << '\n';
268   
269       if (DI.getSeverity() == DS_Error)
270         exit(1);
271       return true;
272     }
273   };
274   }
275
276 static void error(const Twine &Msg) {
277   errs() << "llvm-lto: " << Msg << '\n';
278   exit(1);
279 }
280
281 static void error(std::error_code EC, const Twine &Prefix) {
282   if (EC)
283     error(Prefix + ": " + EC.message());
284 }
285
286 template <typename T>
287 static void error(const ErrorOr<T> &V, const Twine &Prefix) {
288   error(V.getError(), Prefix);
289 }
290
291 static void maybeVerifyModule(const Module &Mod) {
292   if (!DisableVerify && verifyModule(Mod, &errs()))
293     error("Broken Module");
294 }
295
296 static std::unique_ptr<LTOModule>
297 getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
298                   const TargetOptions &Options) {
299   ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
300       MemoryBuffer::getFile(Path);
301   error(BufferOrErr, "error loading file '" + Path + "'");
302   Buffer = std::move(BufferOrErr.get());
303   CurrentActivity = ("loading file '" + Path + "'").str();
304   std::unique_ptr<LLVMContext> Context = llvm::make_unique<LLVMContext>();
305   Context->setDiagnosticHandler(llvm::make_unique<LLVMLTODiagnosticHandler>(),
306                                 true);
307   ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
308       std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
309       Options, Path);
310   CurrentActivity = "";
311   maybeVerifyModule((*Ret)->getModule());
312   return std::move(*Ret);
313 }
314
315 /// Print some statistics on the index for each input files.
316 void printIndexStats() {
317   for (auto &Filename : InputFilenames) {
318     ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
319     std::unique_ptr<ModuleSummaryIndex> Index =
320         ExitOnErr(getModuleSummaryIndexForFile(Filename));
321     // Skip files without a module summary.
322     if (!Index)
323       report_fatal_error(Filename + " does not contain an index");
324
325     unsigned Calls = 0, Refs = 0, Functions = 0, Alias = 0, Globals = 0;
326     for (auto &Summaries : *Index) {
327       for (auto &Summary : Summaries.second.SummaryList) {
328         Refs += Summary->refs().size();
329         if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
330           Functions++;
331           Calls += FuncSummary->calls().size();
332         } else if (isa<AliasSummary>(Summary.get()))
333           Alias++;
334         else
335           Globals++;
336       }
337     }
338     outs() << "Index " << Filename << " contains "
339            << (Alias + Globals + Functions) << " nodes (" << Functions
340            << " functions, " << Alias << " alias, " << Globals
341            << " globals) and " << (Calls + Refs) << " edges (" << Refs
342            << " refs and " << Calls << " calls)\n";
343   }
344 }
345
346 /// \brief List symbols in each IR file.
347 ///
348 /// The main point here is to provide lit-testable coverage for the LTOModule
349 /// functionality that's exposed by the C API to list symbols.  Moreover, this
350 /// provides testing coverage for modules that have been created in their own
351 /// contexts.
352 static void listSymbols(const TargetOptions &Options) {
353   for (auto &Filename : InputFilenames) {
354     std::unique_ptr<MemoryBuffer> Buffer;
355     std::unique_ptr<LTOModule> Module =
356         getLocalLTOModule(Filename, Buffer, Options);
357
358     // List the symbols.
359     outs() << Filename << ":\n";
360     for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
361       outs() << Module->getSymbolName(I) << "\n";
362   }
363 }
364
365 /// Create a combined index file from the input IR files and write it.
366 ///
367 /// This is meant to enable testing of ThinLTO combined index generation,
368 /// currently available via the gold plugin via -thinlto.
369 static void createCombinedModuleSummaryIndex() {
370   ModuleSummaryIndex CombinedIndex;
371   uint64_t NextModuleId = 0;
372   for (auto &Filename : InputFilenames) {
373     ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
374     std::unique_ptr<MemoryBuffer> MB =
375         ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
376     ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex, ++NextModuleId));
377   }
378   std::error_code EC;
379   assert(!OutputFilename.empty());
380   raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
381                     sys::fs::OpenFlags::F_None);
382   error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
383   WriteIndexToFile(CombinedIndex, OS);
384   OS.close();
385 }
386
387 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
388 /// \p NewPrefix strings, if it was specified.
389 static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
390                                       std::string &NewPrefix) {
391   assert(ThinLTOPrefixReplace.empty() ||
392          ThinLTOPrefixReplace.find(";") != StringRef::npos);
393   StringRef PrefixReplace = ThinLTOPrefixReplace;
394   std::pair<StringRef, StringRef> Split = PrefixReplace.split(";");
395   OldPrefix = Split.first.str();
396   NewPrefix = Split.second.str();
397 }
398
399 /// Given the original \p Path to an output file, replace any path
400 /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
401 /// resulting directory if it does not yet exist.
402 static std::string getThinLTOOutputFile(const std::string &Path,
403                                         const std::string &OldPrefix,
404                                         const std::string &NewPrefix) {
405   if (OldPrefix.empty() && NewPrefix.empty())
406     return Path;
407   SmallString<128> NewPath(Path);
408   llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
409   StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
410   if (!ParentPath.empty()) {
411     // Make sure the new directory exists, creating it if necessary.
412     if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
413       error(EC, "error creating the directory '" + ParentPath + "'");
414   }
415   return NewPath.str();
416 }
417
418 namespace thinlto {
419
420 std::vector<std::unique_ptr<MemoryBuffer>>
421 loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
422   std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
423
424   for (auto &ModPath : Index.modulePaths()) {
425     const auto &Filename = ModPath.first();
426     std::string CurrentActivity = ("loading file '" + Filename + "'").str();
427     auto InputOrErr = MemoryBuffer::getFile(Filename);
428     error(InputOrErr, "error " + CurrentActivity);
429     InputBuffers.push_back(std::move(*InputOrErr));
430   }
431   return InputBuffers;
432 }
433
434 std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() {
435   if (ThinLTOIndex.empty())
436     report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
437   ExitOnError ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex +
438                         "': ");
439   return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex));
440 }
441
442 static std::unique_ptr<Module> loadModule(StringRef Filename,
443                                           LLVMContext &Ctx) {
444   SMDiagnostic Err;
445   std::unique_ptr<Module> M(parseIRFile(Filename, Err, Ctx));
446   if (!M) {
447     Err.print("llvm-lto", errs());
448     report_fatal_error("Can't load module for file " + Filename);
449   }
450   maybeVerifyModule(*M);
451
452   if (ThinLTOModuleId.getNumOccurrences()) {
453     if (InputFilenames.size() != 1)
454       report_fatal_error("Can't override the module id for multiple files");
455     M->setModuleIdentifier(ThinLTOModuleId);
456   }
457   return M;
458 }
459
460 static void writeModuleToFile(Module &TheModule, StringRef Filename) {
461   std::error_code EC;
462   raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::F_None);
463   error(EC, "error opening the file '" + Filename + "'");
464   maybeVerifyModule(TheModule);
465   WriteBitcodeToFile(&TheModule, OS, /* ShouldPreserveUseListOrder */ true);
466 }
467
468 class ThinLTOProcessing {
469 public:
470   ThinLTOCodeGenerator ThinGenerator;
471
472   ThinLTOProcessing(const TargetOptions &Options) {
473     ThinGenerator.setCodePICModel(getRelocModel());
474     ThinGenerator.setTargetOptions(Options);
475     ThinGenerator.setCacheDir(ThinLTOCacheDir);
476     ThinGenerator.setCachePruningInterval(ThinLTOCachePruningInterval);
477     ThinGenerator.setFreestanding(EnableFreestanding);
478
479     // Add all the exported symbols to the table of symbols to preserve.
480     for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
481       ThinGenerator.preserveSymbol(ExportedSymbols[i]);
482   }
483
484   void run() {
485     switch (ThinLTOMode) {
486     case THINLINK:
487       return thinLink();
488     case THINDISTRIBUTE:
489       return distributedIndexes();
490     case THINEMITIMPORTS:
491       return emitImports();
492     case THINPROMOTE:
493       return promote();
494     case THINIMPORT:
495       return import();
496     case THININTERNALIZE:
497       return internalize();
498     case THINOPT:
499       return optimize();
500     case THINCODEGEN:
501       return codegen();
502     case THINALL:
503       return runAll();
504     }
505   }
506
507 private:
508   /// Load the input files, create the combined index, and write it out.
509   void thinLink() {
510     // Perform "ThinLink": just produce the index
511     if (OutputFilename.empty())
512       report_fatal_error(
513           "OutputFilename is necessary to store the combined index.\n");
514
515     LLVMContext Ctx;
516     std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
517     for (unsigned i = 0; i < InputFilenames.size(); ++i) {
518       auto &Filename = InputFilenames[i];
519       std::string CurrentActivity = "loading file '" + Filename + "'";
520       auto InputOrErr = MemoryBuffer::getFile(Filename);
521       error(InputOrErr, "error " + CurrentActivity);
522       InputBuffers.push_back(std::move(*InputOrErr));
523       ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
524     }
525
526     auto CombinedIndex = ThinGenerator.linkCombinedIndex();
527     if (!CombinedIndex)
528       report_fatal_error("ThinLink didn't create an index");
529     std::error_code EC;
530     raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::F_None);
531     error(EC, "error opening the file '" + OutputFilename + "'");
532     WriteIndexToFile(*CombinedIndex, OS);
533   }
534
535   /// Load the combined index from disk, then compute and generate
536   /// individual index files suitable for ThinLTO distributed backend builds
537   /// on the files mentioned on the command line (these must match the index
538   /// content).
539   void distributedIndexes() {
540     if (InputFilenames.size() != 1 && !OutputFilename.empty())
541       report_fatal_error("Can't handle a single output filename and multiple "
542                          "input files, do not provide an output filename and "
543                          "the output files will be suffixed from the input "
544                          "ones.");
545
546     std::string OldPrefix, NewPrefix;
547     getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
548
549     auto Index = loadCombinedIndex();
550     for (auto &Filename : InputFilenames) {
551       // Build a map of module to the GUIDs and summary objects that should
552       // be written to its index.
553       std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
554       ThinLTOCodeGenerator::gatherImportedSummariesForModule(
555           Filename, *Index, ModuleToSummariesForIndex);
556
557       std::string OutputName = OutputFilename;
558       if (OutputName.empty()) {
559         OutputName = Filename + ".thinlto.bc";
560       }
561       OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
562       std::error_code EC;
563       raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
564       error(EC, "error opening the file '" + OutputName + "'");
565       WriteIndexToFile(*Index, OS, &ModuleToSummariesForIndex);
566     }
567   }
568
569   /// Load the combined index from disk, compute the imports, and emit
570   /// the import file lists for each module to disk.
571   void emitImports() {
572     if (InputFilenames.size() != 1 && !OutputFilename.empty())
573       report_fatal_error("Can't handle a single output filename and multiple "
574                          "input files, do not provide an output filename and "
575                          "the output files will be suffixed from the input "
576                          "ones.");
577
578     std::string OldPrefix, NewPrefix;
579     getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
580
581     auto Index = loadCombinedIndex();
582     for (auto &Filename : InputFilenames) {
583       std::string OutputName = OutputFilename;
584       if (OutputName.empty()) {
585         OutputName = Filename + ".imports";
586       }
587       OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
588       ThinLTOCodeGenerator::emitImports(Filename, OutputName, *Index);
589     }
590   }
591
592   /// Load the combined index from disk, then load every file referenced by
593   /// the index and add them to the generator, finally perform the promotion
594   /// on the files mentioned on the command line (these must match the index
595   /// content).
596   void promote() {
597     if (InputFilenames.size() != 1 && !OutputFilename.empty())
598       report_fatal_error("Can't handle a single output filename and multiple "
599                          "input files, do not provide an output filename and "
600                          "the output files will be suffixed from the input "
601                          "ones.");
602
603     auto Index = loadCombinedIndex();
604     for (auto &Filename : InputFilenames) {
605       LLVMContext Ctx;
606       auto TheModule = loadModule(Filename, Ctx);
607
608       ThinGenerator.promote(*TheModule, *Index);
609
610       std::string OutputName = OutputFilename;
611       if (OutputName.empty()) {
612         OutputName = Filename + ".thinlto.promoted.bc";
613       }
614       writeModuleToFile(*TheModule, OutputName);
615     }
616   }
617
618   /// Load the combined index from disk, then load every file referenced by
619   /// the index and add them to the generator, then performs the promotion and
620   /// cross module importing on the files mentioned on the command line
621   /// (these must match the index content).
622   void import() {
623     if (InputFilenames.size() != 1 && !OutputFilename.empty())
624       report_fatal_error("Can't handle a single output filename and multiple "
625                          "input files, do not provide an output filename and "
626                          "the output files will be suffixed from the input "
627                          "ones.");
628
629     auto Index = loadCombinedIndex();
630     auto InputBuffers = loadAllFilesForIndex(*Index);
631     for (auto &MemBuffer : InputBuffers)
632       ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
633                               MemBuffer->getBuffer());
634
635     for (auto &Filename : InputFilenames) {
636       LLVMContext Ctx;
637       auto TheModule = loadModule(Filename, Ctx);
638
639       ThinGenerator.crossModuleImport(*TheModule, *Index);
640
641       std::string OutputName = OutputFilename;
642       if (OutputName.empty()) {
643         OutputName = Filename + ".thinlto.imported.bc";
644       }
645       writeModuleToFile(*TheModule, OutputName);
646     }
647   }
648
649   void internalize() {
650     if (InputFilenames.size() != 1 && !OutputFilename.empty())
651       report_fatal_error("Can't handle a single output filename and multiple "
652                          "input files, do not provide an output filename and "
653                          "the output files will be suffixed from the input "
654                          "ones.");
655
656     if (ExportedSymbols.empty())
657       errs() << "Warning: -internalize will not perform without "
658                 "-exported-symbol\n";
659
660     auto Index = loadCombinedIndex();
661     auto InputBuffers = loadAllFilesForIndex(*Index);
662     for (auto &MemBuffer : InputBuffers)
663       ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
664                               MemBuffer->getBuffer());
665
666     for (auto &Filename : InputFilenames) {
667       LLVMContext Ctx;
668       auto TheModule = loadModule(Filename, Ctx);
669
670       ThinGenerator.internalize(*TheModule, *Index);
671
672       std::string OutputName = OutputFilename;
673       if (OutputName.empty()) {
674         OutputName = Filename + ".thinlto.internalized.bc";
675       }
676       writeModuleToFile(*TheModule, OutputName);
677     }
678   }
679
680   void optimize() {
681     if (InputFilenames.size() != 1 && !OutputFilename.empty())
682       report_fatal_error("Can't handle a single output filename and multiple "
683                          "input files, do not provide an output filename and "
684                          "the output files will be suffixed from the input "
685                          "ones.");
686     if (!ThinLTOIndex.empty())
687       errs() << "Warning: -thinlto-index ignored for optimize stage";
688
689     for (auto &Filename : InputFilenames) {
690       LLVMContext Ctx;
691       auto TheModule = loadModule(Filename, Ctx);
692
693       ThinGenerator.optimize(*TheModule);
694
695       std::string OutputName = OutputFilename;
696       if (OutputName.empty()) {
697         OutputName = Filename + ".thinlto.imported.bc";
698       }
699       writeModuleToFile(*TheModule, OutputName);
700     }
701   }
702
703   void codegen() {
704     if (InputFilenames.size() != 1 && !OutputFilename.empty())
705       report_fatal_error("Can't handle a single output filename and multiple "
706                          "input files, do not provide an output filename and "
707                          "the output files will be suffixed from the input "
708                          "ones.");
709     if (!ThinLTOIndex.empty())
710       errs() << "Warning: -thinlto-index ignored for codegen stage";
711
712     std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
713     for (auto &Filename : InputFilenames) {
714       LLVMContext Ctx;
715       auto InputOrErr = MemoryBuffer::getFile(Filename);
716       error(InputOrErr, "error " + CurrentActivity);
717       InputBuffers.push_back(std::move(*InputOrErr));
718       ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
719     }
720     ThinGenerator.setCodeGenOnly(true);
721     ThinGenerator.run();
722     for (auto BinName :
723          zip(ThinGenerator.getProducedBinaries(), InputFilenames)) {
724       std::string OutputName = OutputFilename;
725       if (OutputName.empty())
726         OutputName = std::get<1>(BinName) + ".thinlto.o";
727       else if (OutputName == "-") {
728         outs() << std::get<0>(BinName)->getBuffer();
729         return;
730       }
731
732       std::error_code EC;
733       raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
734       error(EC, "error opening the file '" + OutputName + "'");
735       OS << std::get<0>(BinName)->getBuffer();
736     }
737   }
738
739   /// Full ThinLTO process
740   void runAll() {
741     if (!OutputFilename.empty())
742       report_fatal_error("Do not provide an output filename for ThinLTO "
743                          " processing, the output files will be suffixed from "
744                          "the input ones.");
745
746     if (!ThinLTOIndex.empty())
747       errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
748
749     LLVMContext Ctx;
750     std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
751     for (unsigned i = 0; i < InputFilenames.size(); ++i) {
752       auto &Filename = InputFilenames[i];
753       std::string CurrentActivity = "loading file '" + Filename + "'";
754       auto InputOrErr = MemoryBuffer::getFile(Filename);
755       error(InputOrErr, "error " + CurrentActivity);
756       InputBuffers.push_back(std::move(*InputOrErr));
757       ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
758     }
759
760     if (!ThinLTOSaveTempsPrefix.empty())
761       ThinGenerator.setSaveTempsDir(ThinLTOSaveTempsPrefix);
762
763     if (!ThinLTOGeneratedObjectsDir.empty()) {
764       ThinGenerator.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir);
765       ThinGenerator.run();
766       return;
767     }
768
769     ThinGenerator.run();
770
771     auto &Binaries = ThinGenerator.getProducedBinaries();
772     if (Binaries.size() != InputFilenames.size())
773       report_fatal_error("Number of output objects does not match the number "
774                          "of inputs");
775
776     for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
777       auto OutputName = InputFilenames[BufID] + ".thinlto.o";
778       std::error_code EC;
779       raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::F_None);
780       error(EC, "error opening the file '" + OutputName + "'");
781       OS << Binaries[BufID]->getBuffer();
782     }
783   }
784
785   /// Load the combined index from disk, then load every file referenced by
786 };
787
788 } // end namespace thinlto
789
790 int main(int argc, char **argv) {
791   // Print a stack trace if we signal out.
792   sys::PrintStackTraceOnErrorSignal(argv[0]);
793   PrettyStackTraceProgram X(argc, argv);
794
795   llvm_shutdown_obj Y; // Call llvm_shutdown() on exit.
796   cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
797
798   if (OptLevel < '0' || OptLevel > '3')
799     error("optimization level must be between 0 and 3");
800
801   // Initialize the configured targets.
802   InitializeAllTargets();
803   InitializeAllTargetMCs();
804   InitializeAllAsmPrinters();
805   InitializeAllAsmParsers();
806
807   // set up the TargetOptions for the machine
808   TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
809
810   if (ListSymbolsOnly) {
811     listSymbols(Options);
812     return 0;
813   }
814
815   if (IndexStats) {
816     printIndexStats();
817     return 0;
818   }
819
820   if (CheckHasObjC) {
821     for (auto &Filename : InputFilenames) {
822       ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
823                             Filename + "': ");
824       std::unique_ptr<MemoryBuffer> BufferOrErr =
825           ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename)));
826       auto Buffer = std::move(BufferOrErr.get());
827       if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer)))
828         outs() << "Bitcode " << Filename << " contains ObjC\n";
829       else
830         outs() << "Bitcode " << Filename << " does not contain ObjC\n";
831     }
832     return 0;
833   }
834
835   if (ThinLTOMode.getNumOccurrences()) {
836     if (ThinLTOMode.getNumOccurrences() > 1)
837       report_fatal_error("You can't specify more than one -thinlto-action");
838     thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
839     ThinLTOProcessor.run();
840     return 0;
841   }
842
843   if (ThinLTO) {
844     createCombinedModuleSummaryIndex();
845     return 0;
846   }
847
848   unsigned BaseArg = 0;
849
850   LLVMContext Context;
851   Context.setDiagnosticHandler(llvm::make_unique<LLVMLTODiagnosticHandler>(),
852                                true);
853
854   LTOCodeGenerator CodeGen(Context);
855
856   if (UseDiagnosticHandler)
857     CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
858
859   CodeGen.setCodePICModel(getRelocModel());
860   CodeGen.setFreestanding(EnableFreestanding);
861
862   CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
863   CodeGen.setTargetOptions(Options);
864   CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
865
866   StringSet<MallocAllocator> DSOSymbolsSet;
867   for (unsigned i = 0; i < DSOSymbols.size(); ++i)
868     DSOSymbolsSet.insert(DSOSymbols[i]);
869
870   std::vector<std::string> KeptDSOSyms;
871
872   for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
873     CurrentActivity = "loading file '" + InputFilenames[i] + "'";
874     ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
875         LTOModule::createFromFile(Context, InputFilenames[i], Options);
876     std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
877     CurrentActivity = "";
878
879     unsigned NumSyms = Module->getSymbolCount();
880     for (unsigned I = 0; I < NumSyms; ++I) {
881       StringRef Name = Module->getSymbolName(I);
882       if (!DSOSymbolsSet.count(Name))
883         continue;
884       lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
885       unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
886       if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
887         KeptDSOSyms.push_back(Name);
888     }
889
890     // We use the first input module as the destination module when
891     // SetMergedModule is true.
892     if (SetMergedModule && i == BaseArg) {
893       // Transfer ownership to the code generator.
894       CodeGen.setModule(std::move(Module));
895     } else if (!CodeGen.addModule(Module.get())) {
896       // Print a message here so that we know addModule() did not abort.
897       error("error adding file '" + InputFilenames[i] + "'");
898     }
899   }
900
901   // Add all the exported symbols to the table of symbols to preserve.
902   for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
903     CodeGen.addMustPreserveSymbol(ExportedSymbols[i]);
904
905   // Add all the dso symbols to the table of symbols to expose.
906   for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
907     CodeGen.addMustPreserveSymbol(KeptDSOSyms[i]);
908
909   // Set cpu and attrs strings for the default target/subtarget.
910   CodeGen.setCpu(MCPU.c_str());
911
912   CodeGen.setOptLevel(OptLevel - '0');
913
914   std::string attrs;
915   for (unsigned i = 0; i < MAttrs.size(); ++i) {
916     if (i > 0)
917       attrs.append(",");
918     attrs.append(MAttrs[i]);
919   }
920
921   if (!attrs.empty())
922     CodeGen.setAttr(attrs);
923
924   if (FileType.getNumOccurrences())
925     CodeGen.setFileType(FileType);
926
927   if (!OutputFilename.empty()) {
928     if (!CodeGen.optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
929                           DisableLTOVectorization)) {
930       // Diagnostic messages should have been printed by the handler.
931       error("error optimizing the code");
932     }
933
934     if (SaveModuleFile) {
935       std::string ModuleFilename = OutputFilename;
936       ModuleFilename += ".merged.bc";
937       std::string ErrMsg;
938
939       if (!CodeGen.writeMergedModules(ModuleFilename))
940         error("writing merged module failed.");
941     }
942
943     std::list<ToolOutputFile> OSs;
944     std::vector<raw_pwrite_stream *> OSPtrs;
945     for (unsigned I = 0; I != Parallelism; ++I) {
946       std::string PartFilename = OutputFilename;
947       if (Parallelism != 1)
948         PartFilename += "." + utostr(I);
949       std::error_code EC;
950       OSs.emplace_back(PartFilename, EC, sys::fs::F_None);
951       if (EC)
952         error("error opening the file '" + PartFilename + "': " + EC.message());
953       OSPtrs.push_back(&OSs.back().os());
954     }
955
956     if (!CodeGen.compileOptimized(OSPtrs))
957       // Diagnostic messages should have been printed by the handler.
958       error("error compiling the code");
959
960     for (ToolOutputFile &OS : OSs)
961       OS.keep();
962   } else {
963     if (Parallelism != 1)
964       error("-j must be specified together with -o");
965
966     if (SaveModuleFile)
967       error(": -save-merged-module must be specified with -o");
968
969     const char *OutputName = nullptr;
970     if (!CodeGen.compile_to_file(&OutputName, DisableVerify, DisableInline,
971                                  DisableGVNLoadPRE, DisableLTOVectorization))
972       error("error compiling the code");
973       // Diagnostic messages should have been printed by the handler.
974
975     outs() << "Wrote native object file '" << OutputName << "'\n";
976   }
977
978   return 0;
979 }