[lib/ObjectYAML] - Change interface to return `bool` instead of `int`. NFCI
[llvm-complete.git] / tools / llvm-lto / llvm-lto.cpp
blobb47e68e82850c6cc715e2d6d213cc14a1621d082
1 //===- llvm-lto: a simple command-line program to link modules with LTO ---===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This program takes in a list of bitcode files, links them, performs link-time
10 // optimization, and outputs an object file.
12 //===----------------------------------------------------------------------===//
14 #include "llvm-c/lto.h"
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/ADT/StringExtras.h"
19 #include "llvm/ADT/StringRef.h"
20 #include "llvm/ADT/StringSet.h"
21 #include "llvm/ADT/Twine.h"
22 #include "llvm/Bitcode/BitcodeReader.h"
23 #include "llvm/Bitcode/BitcodeWriter.h"
24 #include "llvm/CodeGen/CommandFlags.inc"
25 #include "llvm/IR/DiagnosticInfo.h"
26 #include "llvm/IR/DiagnosticPrinter.h"
27 #include "llvm/IR/LLVMContext.h"
28 #include "llvm/IR/Module.h"
29 #include "llvm/IR/ModuleSummaryIndex.h"
30 #include "llvm/IR/Verifier.h"
31 #include "llvm/IRReader/IRReader.h"
32 #include "llvm/LTO/legacy/LTOCodeGenerator.h"
33 #include "llvm/LTO/legacy/LTOModule.h"
34 #include "llvm/LTO/legacy/ThinLTOCodeGenerator.h"
35 #include "llvm/Support/Allocator.h"
36 #include "llvm/Support/Casting.h"
37 #include "llvm/Support/CommandLine.h"
38 #include "llvm/Support/Error.h"
39 #include "llvm/Support/ErrorHandling.h"
40 #include "llvm/Support/ErrorOr.h"
41 #include "llvm/Support/FileSystem.h"
42 #include "llvm/Support/InitLLVM.h"
43 #include "llvm/Support/MemoryBuffer.h"
44 #include "llvm/Support/Path.h"
45 #include "llvm/Support/SourceMgr.h"
46 #include "llvm/Support/TargetSelect.h"
47 #include "llvm/Support/ToolOutputFile.h"
48 #include "llvm/Support/raw_ostream.h"
49 #include "llvm/Target/TargetOptions.h"
50 #include <algorithm>
51 #include <cassert>
52 #include <cstdint>
53 #include <cstdlib>
54 #include <list>
55 #include <map>
56 #include <memory>
57 #include <string>
58 #include <system_error>
59 #include <tuple>
60 #include <utility>
61 #include <vector>
63 using namespace llvm;
65 static cl::opt<char>
66 OptLevel("O", cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
67 "(default = '-O2')"),
68 cl::Prefix, cl::ZeroOrMore, cl::init('2'));
70 static cl::opt<bool>
71 IndexStats("thinlto-index-stats",
72 cl::desc("Print statistic for the index in every input files"),
73 cl::init(false));
75 static cl::opt<bool> DisableVerify(
76 "disable-verify", cl::init(false),
77 cl::desc("Do not run the verifier during the optimization pipeline"));
79 static cl::opt<bool> DisableInline("disable-inlining", cl::init(false),
80 cl::desc("Do not run the inliner pass"));
82 static cl::opt<bool>
83 DisableGVNLoadPRE("disable-gvn-loadpre", cl::init(false),
84 cl::desc("Do not run the GVN load PRE pass"));
86 static cl::opt<bool> DisableLTOVectorization(
87 "disable-lto-vectorization", cl::init(false),
88 cl::desc("Do not run loop or slp vectorization during LTO"));
90 static cl::opt<bool> EnableFreestanding(
91 "lto-freestanding", cl::init(false),
92 cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"));
94 static cl::opt<bool> UseDiagnosticHandler(
95 "use-diagnostic-handler", cl::init(false),
96 cl::desc("Use a diagnostic handler to test the handler interface"));
98 static cl::opt<bool>
99 ThinLTO("thinlto", cl::init(false),
100 cl::desc("Only write combined global index for ThinLTO backends"));
102 enum ThinLTOModes {
103 THINLINK,
104 THINDISTRIBUTE,
105 THINEMITIMPORTS,
106 THINPROMOTE,
107 THINIMPORT,
108 THININTERNALIZE,
109 THINOPT,
110 THINCODEGEN,
111 THINALL
114 cl::opt<ThinLTOModes> ThinLTOMode(
115 "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
116 cl::values(
117 clEnumValN(
118 THINLINK, "thinlink",
119 "ThinLink: produces the index by linking only the summaries."),
120 clEnumValN(THINDISTRIBUTE, "distributedindexes",
121 "Produces individual indexes for distributed backends."),
122 clEnumValN(THINEMITIMPORTS, "emitimports",
123 "Emit imports files for distributed backends."),
124 clEnumValN(THINPROMOTE, "promote",
125 "Perform pre-import promotion (requires -thinlto-index)."),
126 clEnumValN(THINIMPORT, "import", "Perform both promotion and "
127 "cross-module importing (requires "
128 "-thinlto-index)."),
129 clEnumValN(THININTERNALIZE, "internalize",
130 "Perform internalization driven by -exported-symbol "
131 "(requires -thinlto-index)."),
132 clEnumValN(THINOPT, "optimize", "Perform ThinLTO optimizations."),
133 clEnumValN(THINCODEGEN, "codegen", "CodeGen (expected to match llc)"),
134 clEnumValN(THINALL, "run", "Perform ThinLTO end-to-end")));
136 static cl::opt<std::string>
137 ThinLTOIndex("thinlto-index",
138 cl::desc("Provide the index produced by a ThinLink, required "
139 "to perform the promotion and/or importing."));
141 static cl::opt<std::string> ThinLTOPrefixReplace(
142 "thinlto-prefix-replace",
143 cl::desc("Control where files for distributed backends are "
144 "created. Expects 'oldprefix;newprefix' and if path "
145 "prefix of output file is oldprefix it will be "
146 "replaced with newprefix."));
148 static cl::opt<std::string> ThinLTOModuleId(
149 "thinlto-module-id",
150 cl::desc("For the module ID for the file to process, useful to "
151 "match what is in the index."));
153 static cl::opt<std::string>
154 ThinLTOCacheDir("thinlto-cache-dir", cl::desc("Enable ThinLTO caching."));
156 static cl::opt<int>
157 ThinLTOCachePruningInterval("thinlto-cache-pruning-interval",
158 cl::init(1200), cl::desc("Set ThinLTO cache pruning interval."));
160 static cl::opt<uint64_t> ThinLTOCacheMaxSizeBytes(
161 "thinlto-cache-max-size-bytes",
162 cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."));
164 static cl::opt<int>
165 ThinLTOCacheMaxSizeFiles("thinlto-cache-max-size-files", cl::init(1000000),
166 cl::desc("Set ThinLTO cache pruning directory maximum number of files."));
168 static cl::opt<unsigned>
169 ThinLTOCacheEntryExpiration("thinlto-cache-entry-expiration", cl::init(604800) /* 1w */,
170 cl::desc("Set ThinLTO cache entry expiration time."));
172 static cl::opt<std::string> ThinLTOSaveTempsPrefix(
173 "thinlto-save-temps",
174 cl::desc("Save ThinLTO temp files using filenames created by adding "
175 "suffixes to the given file path prefix."));
177 static cl::opt<std::string> ThinLTOGeneratedObjectsDir(
178 "thinlto-save-objects",
179 cl::desc("Save ThinLTO generated object files using filenames created in "
180 "the given directory."));
182 static cl::opt<bool>
183 SaveModuleFile("save-merged-module", cl::init(false),
184 cl::desc("Write merged LTO module to file before CodeGen"));
186 static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
187 cl::desc("<input bitcode files>"));
189 static cl::opt<std::string> OutputFilename("o", cl::init(""),
190 cl::desc("Override output filename"),
191 cl::value_desc("filename"));
193 static cl::list<std::string> ExportedSymbols(
194 "exported-symbol",
195 cl::desc("List of symbols to export from the resulting object file"),
196 cl::ZeroOrMore);
198 static cl::list<std::string>
199 DSOSymbols("dso-symbol",
200 cl::desc("Symbol to put in the symtab in the resulting dso"),
201 cl::ZeroOrMore);
203 static cl::opt<bool> ListSymbolsOnly(
204 "list-symbols-only", cl::init(false),
205 cl::desc("Instead of running LTO, list the symbols in each IR file"));
207 static cl::opt<bool> ListDependentLibrariesOnly(
208 "list-dependent-libraries-only", cl::init(false),
209 cl::desc("Instead of running LTO, list the dependent libraries in each IR file"));
211 static cl::opt<bool> SetMergedModule(
212 "set-merged-module", cl::init(false),
213 cl::desc("Use the first input module as the merged module"));
215 static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
216 cl::desc("Number of backend threads"));
218 static cl::opt<bool> RestoreGlobalsLinkage(
219 "restore-linkage", cl::init(false),
220 cl::desc("Restore original linkage of globals prior to CodeGen"));
222 static cl::opt<bool> CheckHasObjC(
223 "check-for-objc", cl::init(false),
224 cl::desc("Only check if the module has objective-C defined in it"));
226 namespace {
228 struct ModuleInfo {
229 std::vector<bool> CanBeHidden;
232 } // end anonymous namespace
234 static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
235 const char *Msg, void *) {
236 errs() << "llvm-lto: ";
237 switch (Severity) {
238 case LTO_DS_NOTE:
239 errs() << "note: ";
240 break;
241 case LTO_DS_REMARK:
242 errs() << "remark: ";
243 break;
244 case LTO_DS_ERROR:
245 errs() << "error: ";
246 break;
247 case LTO_DS_WARNING:
248 errs() << "warning: ";
249 break;
251 errs() << Msg << "\n";
254 static std::string CurrentActivity;
256 namespace {
257 struct LLVMLTODiagnosticHandler : public DiagnosticHandler {
258 bool handleDiagnostics(const DiagnosticInfo &DI) override {
259 raw_ostream &OS = errs();
260 OS << "llvm-lto: ";
261 switch (DI.getSeverity()) {
262 case DS_Error:
263 OS << "error";
264 break;
265 case DS_Warning:
266 OS << "warning";
267 break;
268 case DS_Remark:
269 OS << "remark";
270 break;
271 case DS_Note:
272 OS << "note";
273 break;
275 if (!CurrentActivity.empty())
276 OS << ' ' << CurrentActivity;
277 OS << ": ";
279 DiagnosticPrinterRawOStream DP(OS);
280 DI.print(DP);
281 OS << '\n';
283 if (DI.getSeverity() == DS_Error)
284 exit(1);
285 return true;
290 static void error(const Twine &Msg) {
291 errs() << "llvm-lto: " << Msg << '\n';
292 exit(1);
295 static void error(std::error_code EC, const Twine &Prefix) {
296 if (EC)
297 error(Prefix + ": " + EC.message());
300 template <typename T>
301 static void error(const ErrorOr<T> &V, const Twine &Prefix) {
302 error(V.getError(), Prefix);
305 static void maybeVerifyModule(const Module &Mod) {
306 if (!DisableVerify && verifyModule(Mod, &errs()))
307 error("Broken Module");
310 static std::unique_ptr<LTOModule>
311 getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
312 const TargetOptions &Options) {
313 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
314 MemoryBuffer::getFile(Path);
315 error(BufferOrErr, "error loading file '" + Path + "'");
316 Buffer = std::move(BufferOrErr.get());
317 CurrentActivity = ("loading file '" + Path + "'").str();
318 std::unique_ptr<LLVMContext> Context = std::make_unique<LLVMContext>();
319 Context->setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
320 true);
321 ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
322 std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
323 Options, Path);
324 CurrentActivity = "";
325 maybeVerifyModule((*Ret)->getModule());
326 return std::move(*Ret);
329 /// Print some statistics on the index for each input files.
330 void printIndexStats() {
331 for (auto &Filename : InputFilenames) {
332 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
333 std::unique_ptr<ModuleSummaryIndex> Index =
334 ExitOnErr(getModuleSummaryIndexForFile(Filename));
335 // Skip files without a module summary.
336 if (!Index)
337 report_fatal_error(Filename + " does not contain an index");
339 unsigned Calls = 0, Refs = 0, Functions = 0, Alias = 0, Globals = 0;
340 for (auto &Summaries : *Index) {
341 for (auto &Summary : Summaries.second.SummaryList) {
342 Refs += Summary->refs().size();
343 if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
344 Functions++;
345 Calls += FuncSummary->calls().size();
346 } else if (isa<AliasSummary>(Summary.get()))
347 Alias++;
348 else
349 Globals++;
352 outs() << "Index " << Filename << " contains "
353 << (Alias + Globals + Functions) << " nodes (" << Functions
354 << " functions, " << Alias << " alias, " << Globals
355 << " globals) and " << (Calls + Refs) << " edges (" << Refs
356 << " refs and " << Calls << " calls)\n";
360 /// List symbols in each IR file.
362 /// The main point here is to provide lit-testable coverage for the LTOModule
363 /// functionality that's exposed by the C API to list symbols. Moreover, this
364 /// provides testing coverage for modules that have been created in their own
365 /// contexts.
366 static void listSymbols(const TargetOptions &Options) {
367 for (auto &Filename : InputFilenames) {
368 std::unique_ptr<MemoryBuffer> Buffer;
369 std::unique_ptr<LTOModule> Module =
370 getLocalLTOModule(Filename, Buffer, Options);
372 // List the symbols.
373 outs() << Filename << ":\n";
374 for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
375 outs() << Module->getSymbolName(I) << "\n";
379 static std::unique_ptr<MemoryBuffer> loadFile(StringRef Filename) {
380 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename.str() +
381 "': ");
382 return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
385 static void listDependentLibraries() {
386 for (auto &Filename : InputFilenames) {
387 auto Buffer = loadFile(Filename);
388 std::string E;
389 std::unique_ptr<lto::InputFile> Input(LTOModule::createInputFile(
390 Buffer->getBufferStart(), Buffer->getBufferSize(), Filename.c_str(),
391 E));
392 if (!Input)
393 error(E);
395 // List the dependent libraries.
396 outs() << Filename << ":\n";
397 for (size_t I = 0, C = LTOModule::getDependentLibraryCount(Input.get());
398 I != C; ++I) {
399 size_t L = 0;
400 const char *S = LTOModule::getDependentLibrary(Input.get(), I, &L);
401 assert(S);
402 outs() << StringRef(S, L) << "\n";
407 /// Create a combined index file from the input IR files and write it.
409 /// This is meant to enable testing of ThinLTO combined index generation,
410 /// currently available via the gold plugin via -thinlto.
411 static void createCombinedModuleSummaryIndex() {
412 ModuleSummaryIndex CombinedIndex(/*HaveGVs=*/false);
413 uint64_t NextModuleId = 0;
414 for (auto &Filename : InputFilenames) {
415 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
416 std::unique_ptr<MemoryBuffer> MB =
417 ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
418 ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex, NextModuleId++));
420 std::error_code EC;
421 assert(!OutputFilename.empty());
422 raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
423 sys::fs::OpenFlags::OF_None);
424 error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
425 WriteIndexToFile(CombinedIndex, OS);
426 OS.close();
429 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
430 /// \p NewPrefix strings, if it was specified.
431 static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
432 std::string &NewPrefix) {
433 assert(ThinLTOPrefixReplace.empty() ||
434 ThinLTOPrefixReplace.find(";") != StringRef::npos);
435 StringRef PrefixReplace = ThinLTOPrefixReplace;
436 std::pair<StringRef, StringRef> Split = PrefixReplace.split(";");
437 OldPrefix = Split.first.str();
438 NewPrefix = Split.second.str();
441 /// Given the original \p Path to an output file, replace any path
442 /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
443 /// resulting directory if it does not yet exist.
444 static std::string getThinLTOOutputFile(const std::string &Path,
445 const std::string &OldPrefix,
446 const std::string &NewPrefix) {
447 if (OldPrefix.empty() && NewPrefix.empty())
448 return Path;
449 SmallString<128> NewPath(Path);
450 llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
451 StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
452 if (!ParentPath.empty()) {
453 // Make sure the new directory exists, creating it if necessary.
454 if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
455 error(EC, "error creating the directory '" + ParentPath + "'");
457 return NewPath.str();
460 namespace thinlto {
462 std::vector<std::unique_ptr<MemoryBuffer>>
463 loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
464 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
466 for (auto &ModPath : Index.modulePaths()) {
467 const auto &Filename = ModPath.first();
468 std::string CurrentActivity = ("loading file '" + Filename + "'").str();
469 auto InputOrErr = MemoryBuffer::getFile(Filename);
470 error(InputOrErr, "error " + CurrentActivity);
471 InputBuffers.push_back(std::move(*InputOrErr));
473 return InputBuffers;
476 std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() {
477 if (ThinLTOIndex.empty())
478 report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
479 ExitOnError ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex +
480 "': ");
481 return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex));
484 static std::unique_ptr<lto::InputFile> loadInputFile(MemoryBufferRef Buffer) {
485 ExitOnError ExitOnErr("llvm-lto: error loading input '" +
486 Buffer.getBufferIdentifier().str() + "': ");
487 return ExitOnErr(lto::InputFile::create(Buffer));
490 static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile &File,
491 LLVMContext &CTX) {
492 auto &Mod = File.getSingleBitcodeModule();
493 auto ModuleOrErr = Mod.parseModule(CTX);
494 if (!ModuleOrErr) {
495 handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
496 SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
497 SourceMgr::DK_Error, EIB.message());
498 Err.print("llvm-lto", errs());
500 report_fatal_error("Can't load module, abort.");
502 maybeVerifyModule(**ModuleOrErr);
503 if (ThinLTOModuleId.getNumOccurrences()) {
504 if (InputFilenames.size() != 1)
505 report_fatal_error("Can't override the module id for multiple files");
506 (*ModuleOrErr)->setModuleIdentifier(ThinLTOModuleId);
508 return std::move(*ModuleOrErr);
511 static void writeModuleToFile(Module &TheModule, StringRef Filename) {
512 std::error_code EC;
513 raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::OF_None);
514 error(EC, "error opening the file '" + Filename + "'");
515 maybeVerifyModule(TheModule);
516 WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
519 class ThinLTOProcessing {
520 public:
521 ThinLTOCodeGenerator ThinGenerator;
523 ThinLTOProcessing(const TargetOptions &Options) {
524 ThinGenerator.setCodePICModel(getRelocModel());
525 ThinGenerator.setTargetOptions(Options);
526 ThinGenerator.setCacheDir(ThinLTOCacheDir);
527 ThinGenerator.setCachePruningInterval(ThinLTOCachePruningInterval);
528 ThinGenerator.setCacheEntryExpiration(ThinLTOCacheEntryExpiration);
529 ThinGenerator.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles);
530 ThinGenerator.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes);
531 ThinGenerator.setFreestanding(EnableFreestanding);
533 // Add all the exported symbols to the table of symbols to preserve.
534 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
535 ThinGenerator.preserveSymbol(ExportedSymbols[i]);
538 void run() {
539 switch (ThinLTOMode) {
540 case THINLINK:
541 return thinLink();
542 case THINDISTRIBUTE:
543 return distributedIndexes();
544 case THINEMITIMPORTS:
545 return emitImports();
546 case THINPROMOTE:
547 return promote();
548 case THINIMPORT:
549 return import();
550 case THININTERNALIZE:
551 return internalize();
552 case THINOPT:
553 return optimize();
554 case THINCODEGEN:
555 return codegen();
556 case THINALL:
557 return runAll();
561 private:
562 /// Load the input files, create the combined index, and write it out.
563 void thinLink() {
564 // Perform "ThinLink": just produce the index
565 if (OutputFilename.empty())
566 report_fatal_error(
567 "OutputFilename is necessary to store the combined index.\n");
569 LLVMContext Ctx;
570 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
571 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
572 auto &Filename = InputFilenames[i];
573 std::string CurrentActivity = "loading file '" + Filename + "'";
574 auto InputOrErr = MemoryBuffer::getFile(Filename);
575 error(InputOrErr, "error " + CurrentActivity);
576 InputBuffers.push_back(std::move(*InputOrErr));
577 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
580 auto CombinedIndex = ThinGenerator.linkCombinedIndex();
581 if (!CombinedIndex)
582 report_fatal_error("ThinLink didn't create an index");
583 std::error_code EC;
584 raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::OF_None);
585 error(EC, "error opening the file '" + OutputFilename + "'");
586 WriteIndexToFile(*CombinedIndex, OS);
589 /// Load the combined index from disk, then compute and generate
590 /// individual index files suitable for ThinLTO distributed backend builds
591 /// on the files mentioned on the command line (these must match the index
592 /// content).
593 void distributedIndexes() {
594 if (InputFilenames.size() != 1 && !OutputFilename.empty())
595 report_fatal_error("Can't handle a single output filename and multiple "
596 "input files, do not provide an output filename and "
597 "the output files will be suffixed from the input "
598 "ones.");
600 std::string OldPrefix, NewPrefix;
601 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
603 auto Index = loadCombinedIndex();
604 for (auto &Filename : InputFilenames) {
605 LLVMContext Ctx;
606 auto Buffer = loadFile(Filename);
607 auto Input = loadInputFile(Buffer->getMemBufferRef());
608 auto TheModule = loadModuleFromInput(*Input, Ctx);
610 // Build a map of module to the GUIDs and summary objects that should
611 // be written to its index.
612 std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
613 ThinGenerator.gatherImportedSummariesForModule(
614 *TheModule, *Index, ModuleToSummariesForIndex, *Input);
616 std::string OutputName = OutputFilename;
617 if (OutputName.empty()) {
618 OutputName = Filename + ".thinlto.bc";
620 OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
621 std::error_code EC;
622 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
623 error(EC, "error opening the file '" + OutputName + "'");
624 WriteIndexToFile(*Index, OS, &ModuleToSummariesForIndex);
628 /// Load the combined index from disk, compute the imports, and emit
629 /// the import file lists for each module to disk.
630 void emitImports() {
631 if (InputFilenames.size() != 1 && !OutputFilename.empty())
632 report_fatal_error("Can't handle a single output filename and multiple "
633 "input files, do not provide an output filename and "
634 "the output files will be suffixed from the input "
635 "ones.");
637 std::string OldPrefix, NewPrefix;
638 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
640 auto Index = loadCombinedIndex();
641 for (auto &Filename : InputFilenames) {
642 LLVMContext Ctx;
643 auto Buffer = loadFile(Filename);
644 auto Input = loadInputFile(Buffer->getMemBufferRef());
645 auto TheModule = loadModuleFromInput(*Input, Ctx);
646 std::string OutputName = OutputFilename;
647 if (OutputName.empty()) {
648 OutputName = Filename + ".imports";
650 OutputName =
651 getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
652 ThinGenerator.emitImports(*TheModule, OutputName, *Index, *Input);
656 /// Load the combined index from disk, then load every file referenced by
657 /// the index and add them to the generator, finally perform the promotion
658 /// on the files mentioned on the command line (these must match the index
659 /// content).
660 void promote() {
661 if (InputFilenames.size() != 1 && !OutputFilename.empty())
662 report_fatal_error("Can't handle a single output filename and multiple "
663 "input files, do not provide an output filename and "
664 "the output files will be suffixed from the input "
665 "ones.");
667 auto Index = loadCombinedIndex();
668 for (auto &Filename : InputFilenames) {
669 LLVMContext Ctx;
670 auto Buffer = loadFile(Filename);
671 auto Input = loadInputFile(Buffer->getMemBufferRef());
672 auto TheModule = loadModuleFromInput(*Input, Ctx);
674 ThinGenerator.promote(*TheModule, *Index, *Input);
676 std::string OutputName = OutputFilename;
677 if (OutputName.empty()) {
678 OutputName = Filename + ".thinlto.promoted.bc";
680 writeModuleToFile(*TheModule, OutputName);
684 /// Load the combined index from disk, then load every file referenced by
685 /// the index and add them to the generator, then performs the promotion and
686 /// cross module importing on the files mentioned on the command line
687 /// (these must match the index content).
688 void import() {
689 if (InputFilenames.size() != 1 && !OutputFilename.empty())
690 report_fatal_error("Can't handle a single output filename and multiple "
691 "input files, do not provide an output filename and "
692 "the output files will be suffixed from the input "
693 "ones.");
695 auto Index = loadCombinedIndex();
696 auto InputBuffers = loadAllFilesForIndex(*Index);
697 for (auto &MemBuffer : InputBuffers)
698 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
699 MemBuffer->getBuffer());
701 for (auto &Filename : InputFilenames) {
702 LLVMContext Ctx;
703 auto Buffer = loadFile(Filename);
704 auto Input = loadInputFile(Buffer->getMemBufferRef());
705 auto TheModule = loadModuleFromInput(*Input, Ctx);
707 ThinGenerator.crossModuleImport(*TheModule, *Index, *Input);
709 std::string OutputName = OutputFilename;
710 if (OutputName.empty()) {
711 OutputName = Filename + ".thinlto.imported.bc";
713 writeModuleToFile(*TheModule, OutputName);
717 void internalize() {
718 if (InputFilenames.size() != 1 && !OutputFilename.empty())
719 report_fatal_error("Can't handle a single output filename and multiple "
720 "input files, do not provide an output filename and "
721 "the output files will be suffixed from the input "
722 "ones.");
724 if (ExportedSymbols.empty())
725 errs() << "Warning: -internalize will not perform without "
726 "-exported-symbol\n";
728 auto Index = loadCombinedIndex();
729 auto InputBuffers = loadAllFilesForIndex(*Index);
730 for (auto &MemBuffer : InputBuffers)
731 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
732 MemBuffer->getBuffer());
734 for (auto &Filename : InputFilenames) {
735 LLVMContext Ctx;
736 auto Buffer = loadFile(Filename);
737 auto Input = loadInputFile(Buffer->getMemBufferRef());
738 auto TheModule = loadModuleFromInput(*Input, Ctx);
740 ThinGenerator.internalize(*TheModule, *Index, *Input);
742 std::string OutputName = OutputFilename;
743 if (OutputName.empty()) {
744 OutputName = Filename + ".thinlto.internalized.bc";
746 writeModuleToFile(*TheModule, OutputName);
750 void optimize() {
751 if (InputFilenames.size() != 1 && !OutputFilename.empty())
752 report_fatal_error("Can't handle a single output filename and multiple "
753 "input files, do not provide an output filename and "
754 "the output files will be suffixed from the input "
755 "ones.");
756 if (!ThinLTOIndex.empty())
757 errs() << "Warning: -thinlto-index ignored for optimize stage";
759 for (auto &Filename : InputFilenames) {
760 LLVMContext Ctx;
761 auto Buffer = loadFile(Filename);
762 auto Input = loadInputFile(Buffer->getMemBufferRef());
763 auto TheModule = loadModuleFromInput(*Input, Ctx);
765 ThinGenerator.optimize(*TheModule);
767 std::string OutputName = OutputFilename;
768 if (OutputName.empty()) {
769 OutputName = Filename + ".thinlto.imported.bc";
771 writeModuleToFile(*TheModule, OutputName);
775 void codegen() {
776 if (InputFilenames.size() != 1 && !OutputFilename.empty())
777 report_fatal_error("Can't handle a single output filename and multiple "
778 "input files, do not provide an output filename and "
779 "the output files will be suffixed from the input "
780 "ones.");
781 if (!ThinLTOIndex.empty())
782 errs() << "Warning: -thinlto-index ignored for codegen stage";
784 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
785 for (auto &Filename : InputFilenames) {
786 LLVMContext Ctx;
787 auto InputOrErr = MemoryBuffer::getFile(Filename);
788 error(InputOrErr, "error " + CurrentActivity);
789 InputBuffers.push_back(std::move(*InputOrErr));
790 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
792 ThinGenerator.setCodeGenOnly(true);
793 ThinGenerator.run();
794 for (auto BinName :
795 zip(ThinGenerator.getProducedBinaries(), InputFilenames)) {
796 std::string OutputName = OutputFilename;
797 if (OutputName.empty())
798 OutputName = std::get<1>(BinName) + ".thinlto.o";
799 else if (OutputName == "-") {
800 outs() << std::get<0>(BinName)->getBuffer();
801 return;
804 std::error_code EC;
805 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
806 error(EC, "error opening the file '" + OutputName + "'");
807 OS << std::get<0>(BinName)->getBuffer();
811 /// Full ThinLTO process
812 void runAll() {
813 if (!OutputFilename.empty())
814 report_fatal_error("Do not provide an output filename for ThinLTO "
815 " processing, the output files will be suffixed from "
816 "the input ones.");
818 if (!ThinLTOIndex.empty())
819 errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
821 LLVMContext Ctx;
822 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
823 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
824 auto &Filename = InputFilenames[i];
825 std::string CurrentActivity = "loading file '" + Filename + "'";
826 auto InputOrErr = MemoryBuffer::getFile(Filename);
827 error(InputOrErr, "error " + CurrentActivity);
828 InputBuffers.push_back(std::move(*InputOrErr));
829 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
832 if (!ThinLTOSaveTempsPrefix.empty())
833 ThinGenerator.setSaveTempsDir(ThinLTOSaveTempsPrefix);
835 if (!ThinLTOGeneratedObjectsDir.empty()) {
836 ThinGenerator.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir);
837 ThinGenerator.run();
838 return;
841 ThinGenerator.run();
843 auto &Binaries = ThinGenerator.getProducedBinaries();
844 if (Binaries.size() != InputFilenames.size())
845 report_fatal_error("Number of output objects does not match the number "
846 "of inputs");
848 for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
849 auto OutputName = InputFilenames[BufID] + ".thinlto.o";
850 std::error_code EC;
851 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
852 error(EC, "error opening the file '" + OutputName + "'");
853 OS << Binaries[BufID]->getBuffer();
857 /// Load the combined index from disk, then load every file referenced by
860 } // end namespace thinlto
862 int main(int argc, char **argv) {
863 InitLLVM X(argc, argv);
864 cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
866 if (OptLevel < '0' || OptLevel > '3')
867 error("optimization level must be between 0 and 3");
869 // Initialize the configured targets.
870 InitializeAllTargets();
871 InitializeAllTargetMCs();
872 InitializeAllAsmPrinters();
873 InitializeAllAsmParsers();
875 // set up the TargetOptions for the machine
876 TargetOptions Options = InitTargetOptionsFromCodeGenFlags();
878 if (ListSymbolsOnly) {
879 listSymbols(Options);
880 return 0;
883 if (ListDependentLibrariesOnly) {
884 listDependentLibraries();
885 return 0;
888 if (IndexStats) {
889 printIndexStats();
890 return 0;
893 if (CheckHasObjC) {
894 for (auto &Filename : InputFilenames) {
895 ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
896 Filename + "': ");
897 std::unique_ptr<MemoryBuffer> BufferOrErr =
898 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename)));
899 auto Buffer = std::move(BufferOrErr.get());
900 if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer)))
901 outs() << "Bitcode " << Filename << " contains ObjC\n";
902 else
903 outs() << "Bitcode " << Filename << " does not contain ObjC\n";
905 return 0;
908 if (ThinLTOMode.getNumOccurrences()) {
909 if (ThinLTOMode.getNumOccurrences() > 1)
910 report_fatal_error("You can't specify more than one -thinlto-action");
911 thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
912 ThinLTOProcessor.run();
913 return 0;
916 if (ThinLTO) {
917 createCombinedModuleSummaryIndex();
918 return 0;
921 unsigned BaseArg = 0;
923 LLVMContext Context;
924 Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
925 true);
927 LTOCodeGenerator CodeGen(Context);
929 if (UseDiagnosticHandler)
930 CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
932 CodeGen.setCodePICModel(getRelocModel());
933 CodeGen.setFreestanding(EnableFreestanding);
935 CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
936 CodeGen.setTargetOptions(Options);
937 CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
939 StringSet<MallocAllocator> DSOSymbolsSet;
940 for (unsigned i = 0; i < DSOSymbols.size(); ++i)
941 DSOSymbolsSet.insert(DSOSymbols[i]);
943 std::vector<std::string> KeptDSOSyms;
945 for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
946 CurrentActivity = "loading file '" + InputFilenames[i] + "'";
947 ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
948 LTOModule::createFromFile(Context, InputFilenames[i], Options);
949 std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
950 CurrentActivity = "";
952 unsigned NumSyms = Module->getSymbolCount();
953 for (unsigned I = 0; I < NumSyms; ++I) {
954 StringRef Name = Module->getSymbolName(I);
955 if (!DSOSymbolsSet.count(Name))
956 continue;
957 lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
958 unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
959 if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
960 KeptDSOSyms.push_back(Name);
963 // We use the first input module as the destination module when
964 // SetMergedModule is true.
965 if (SetMergedModule && i == BaseArg) {
966 // Transfer ownership to the code generator.
967 CodeGen.setModule(std::move(Module));
968 } else if (!CodeGen.addModule(Module.get())) {
969 // Print a message here so that we know addModule() did not abort.
970 error("error adding file '" + InputFilenames[i] + "'");
974 // Add all the exported symbols to the table of symbols to preserve.
975 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
976 CodeGen.addMustPreserveSymbol(ExportedSymbols[i]);
978 // Add all the dso symbols to the table of symbols to expose.
979 for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
980 CodeGen.addMustPreserveSymbol(KeptDSOSyms[i]);
982 // Set cpu and attrs strings for the default target/subtarget.
983 CodeGen.setCpu(MCPU.c_str());
985 CodeGen.setOptLevel(OptLevel - '0');
987 std::string attrs;
988 for (unsigned i = 0; i < MAttrs.size(); ++i) {
989 if (i > 0)
990 attrs.append(",");
991 attrs.append(MAttrs[i]);
994 if (!attrs.empty())
995 CodeGen.setAttr(attrs);
997 if (FileType.getNumOccurrences())
998 CodeGen.setFileType(FileType);
1000 if (!OutputFilename.empty()) {
1001 if (!CodeGen.optimize(DisableVerify, DisableInline, DisableGVNLoadPRE,
1002 DisableLTOVectorization)) {
1003 // Diagnostic messages should have been printed by the handler.
1004 error("error optimizing the code");
1007 if (SaveModuleFile) {
1008 std::string ModuleFilename = OutputFilename;
1009 ModuleFilename += ".merged.bc";
1010 std::string ErrMsg;
1012 if (!CodeGen.writeMergedModules(ModuleFilename))
1013 error("writing merged module failed.");
1016 std::list<ToolOutputFile> OSs;
1017 std::vector<raw_pwrite_stream *> OSPtrs;
1018 for (unsigned I = 0; I != Parallelism; ++I) {
1019 std::string PartFilename = OutputFilename;
1020 if (Parallelism != 1)
1021 PartFilename += "." + utostr(I);
1022 std::error_code EC;
1023 OSs.emplace_back(PartFilename, EC, sys::fs::OF_None);
1024 if (EC)
1025 error("error opening the file '" + PartFilename + "': " + EC.message());
1026 OSPtrs.push_back(&OSs.back().os());
1029 if (!CodeGen.compileOptimized(OSPtrs))
1030 // Diagnostic messages should have been printed by the handler.
1031 error("error compiling the code");
1033 for (ToolOutputFile &OS : OSs)
1034 OS.keep();
1035 } else {
1036 if (Parallelism != 1)
1037 error("-j must be specified together with -o");
1039 if (SaveModuleFile)
1040 error(": -save-merged-module must be specified with -o");
1042 const char *OutputName = nullptr;
1043 if (!CodeGen.compile_to_file(&OutputName, DisableVerify, DisableInline,
1044 DisableGVNLoadPRE, DisableLTOVectorization))
1045 error("error compiling the code");
1046 // Diagnostic messages should have been printed by the handler.
1048 outs() << "Wrote native object file '" << OutputName << "'\n";
1051 return 0;