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