Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / llvm / tools / llvm-lto / llvm-lto.cpp
blobabd45b305df0ed84087295252191b8989f3a205d
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.h"
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/Support/WithColor.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>
64 using namespace llvm;
66 static codegen::RegisterCodeGenFlags CGF;
68 static cl::OptionCategory LTOCategory("LTO Options");
70 static cl::opt<char>
71 OptLevel("O",
72 cl::desc("Optimization level. [-O0, -O1, -O2, or -O3] "
73 "(default = '-O2')"),
74 cl::Prefix, cl::init('2'), cl::cat(LTOCategory));
76 static cl::opt<bool>
77 IndexStats("thinlto-index-stats",
78 cl::desc("Print statistic for the index in every input files"),
79 cl::init(false), cl::cat(LTOCategory));
81 static cl::opt<bool> DisableVerify(
82 "disable-verify", cl::init(false),
83 cl::desc("Do not run the verifier during the optimization pipeline"),
84 cl::cat(LTOCategory));
86 static cl::opt<bool> EnableFreestanding(
87 "lto-freestanding", cl::init(false),
88 cl::desc("Enable Freestanding (disable builtins / TLI) during LTO"),
89 cl::cat(LTOCategory));
91 static cl::opt<bool> UseDiagnosticHandler(
92 "use-diagnostic-handler", cl::init(false),
93 cl::desc("Use a diagnostic handler to test the handler interface"),
94 cl::cat(LTOCategory));
96 static cl::opt<bool>
97 ThinLTO("thinlto", cl::init(false),
98 cl::desc("Only write combined global index for ThinLTO backends"),
99 cl::cat(LTOCategory));
101 enum ThinLTOModes {
102 THINLINK,
103 THINDISTRIBUTE,
104 THINEMITIMPORTS,
105 THINPROMOTE,
106 THINIMPORT,
107 THININTERNALIZE,
108 THINOPT,
109 THINCODEGEN,
110 THINALL
113 cl::opt<ThinLTOModes> ThinLTOMode(
114 "thinlto-action", cl::desc("Perform a single ThinLTO stage:"),
115 cl::values(
116 clEnumValN(
117 THINLINK, "thinlink",
118 "ThinLink: produces the index by linking only the summaries."),
119 clEnumValN(THINDISTRIBUTE, "distributedindexes",
120 "Produces individual indexes for distributed backends."),
121 clEnumValN(THINEMITIMPORTS, "emitimports",
122 "Emit imports files for distributed backends."),
123 clEnumValN(THINPROMOTE, "promote",
124 "Perform pre-import promotion (requires -thinlto-index)."),
125 clEnumValN(THINIMPORT, "import",
126 "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")),
135 cl::cat(LTOCategory));
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 cl::cat(LTOCategory));
143 static cl::opt<std::string> ThinLTOPrefixReplace(
144 "thinlto-prefix-replace",
145 cl::desc("Control where files for distributed backends are "
146 "created. Expects 'oldprefix;newprefix' and if path "
147 "prefix of output file is oldprefix it will be "
148 "replaced with newprefix."),
149 cl::cat(LTOCategory));
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 cl::cat(LTOCategory));
157 static cl::opt<std::string> ThinLTOCacheDir("thinlto-cache-dir",
158 cl::desc("Enable ThinLTO caching."),
159 cl::cat(LTOCategory));
161 static cl::opt<int> ThinLTOCachePruningInterval(
162 "thinlto-cache-pruning-interval", cl::init(1200),
163 cl::desc("Set ThinLTO cache pruning interval."), cl::cat(LTOCategory));
165 static cl::opt<uint64_t> ThinLTOCacheMaxSizeBytes(
166 "thinlto-cache-max-size-bytes",
167 cl::desc("Set ThinLTO cache pruning directory maximum size in bytes."),
168 cl::cat(LTOCategory));
170 static cl::opt<int> ThinLTOCacheMaxSizeFiles(
171 "thinlto-cache-max-size-files", cl::init(1000000),
172 cl::desc("Set ThinLTO cache pruning directory maximum number of files."),
173 cl::cat(LTOCategory));
175 static cl::opt<unsigned> ThinLTOCacheEntryExpiration(
176 "thinlto-cache-entry-expiration", cl::init(604800) /* 1w */,
177 cl::desc("Set ThinLTO cache entry expiration time."), cl::cat(LTOCategory));
179 static cl::opt<std::string> ThinLTOSaveTempsPrefix(
180 "thinlto-save-temps",
181 cl::desc("Save ThinLTO temp files using filenames created by adding "
182 "suffixes to the given file path prefix."),
183 cl::cat(LTOCategory));
185 static cl::opt<std::string> ThinLTOGeneratedObjectsDir(
186 "thinlto-save-objects",
187 cl::desc("Save ThinLTO generated object files using filenames created in "
188 "the given directory."),
189 cl::cat(LTOCategory));
191 static cl::opt<bool> SaveLinkedModuleFile(
192 "save-linked-module", cl::init(false),
193 cl::desc("Write linked LTO module to file before optimize"),
194 cl::cat(LTOCategory));
196 static cl::opt<bool>
197 SaveModuleFile("save-merged-module", cl::init(false),
198 cl::desc("Write merged LTO module to file before CodeGen"),
199 cl::cat(LTOCategory));
201 static cl::list<std::string> InputFilenames(cl::Positional, cl::OneOrMore,
202 cl::desc("<input bitcode files>"),
203 cl::cat(LTOCategory));
205 static cl::opt<std::string> OutputFilename("o", cl::init(""),
206 cl::desc("Override output filename"),
207 cl::value_desc("filename"),
208 cl::cat(LTOCategory));
210 static cl::list<std::string> ExportedSymbols(
211 "exported-symbol",
212 cl::desc("List of symbols to export from the resulting object file"),
213 cl::cat(LTOCategory));
215 static cl::list<std::string>
216 DSOSymbols("dso-symbol",
217 cl::desc("Symbol to put in the symtab in the resulting dso"),
218 cl::cat(LTOCategory));
220 static cl::opt<bool> ListSymbolsOnly(
221 "list-symbols-only", cl::init(false),
222 cl::desc("Instead of running LTO, list the symbols in each IR file"),
223 cl::cat(LTOCategory));
225 static cl::opt<bool> ListDependentLibrariesOnly(
226 "list-dependent-libraries-only", cl::init(false),
227 cl::desc(
228 "Instead of running LTO, list the dependent libraries in each IR file"),
229 cl::cat(LTOCategory));
231 static cl::opt<bool> QueryHasCtorDtor(
232 "query-hasCtorDtor", cl::init(false),
233 cl::desc("Queries LTOModule::hasCtorDtor() on each IR file"));
235 static cl::opt<bool>
236 SetMergedModule("set-merged-module", cl::init(false),
237 cl::desc("Use the first input module as the merged module"),
238 cl::cat(LTOCategory));
240 static cl::opt<unsigned> Parallelism("j", cl::Prefix, cl::init(1),
241 cl::desc("Number of backend threads"),
242 cl::cat(LTOCategory));
244 static cl::opt<bool> RestoreGlobalsLinkage(
245 "restore-linkage", cl::init(false),
246 cl::desc("Restore original linkage of globals prior to CodeGen"),
247 cl::cat(LTOCategory));
249 static cl::opt<bool> CheckHasObjC(
250 "check-for-objc", cl::init(false),
251 cl::desc("Only check if the module has objective-C defined in it"),
252 cl::cat(LTOCategory));
254 static cl::opt<bool> PrintMachOCPUOnly(
255 "print-macho-cpu-only", cl::init(false),
256 cl::desc("Instead of running LTO, print the mach-o cpu in each IR file"),
257 cl::cat(LTOCategory));
259 static cl::opt<bool>
260 DebugPassManager("debug-pass-manager", cl::init(false), cl::Hidden,
261 cl::desc("Print pass management debugging information"),
262 cl::cat(LTOCategory));
264 static cl::opt<bool>
265 LTOSaveBeforeOpt("lto-save-before-opt", cl::init(false),
266 cl::desc("Save the IR before running optimizations"));
268 namespace {
270 struct ModuleInfo {
271 BitVector CanBeHidden;
274 } // end anonymous namespace
276 static void handleDiagnostics(lto_codegen_diagnostic_severity_t Severity,
277 const char *Msg, void *) {
278 errs() << "llvm-lto: ";
279 switch (Severity) {
280 case LTO_DS_NOTE:
281 errs() << "note: ";
282 break;
283 case LTO_DS_REMARK:
284 errs() << "remark: ";
285 break;
286 case LTO_DS_ERROR:
287 errs() << "error: ";
288 break;
289 case LTO_DS_WARNING:
290 errs() << "warning: ";
291 break;
293 errs() << Msg << "\n";
296 static std::string CurrentActivity;
298 namespace {
299 struct LLVMLTODiagnosticHandler : public DiagnosticHandler {
300 bool handleDiagnostics(const DiagnosticInfo &DI) override {
301 raw_ostream &OS = errs();
302 OS << "llvm-lto: ";
303 switch (DI.getSeverity()) {
304 case DS_Error:
305 OS << "error";
306 break;
307 case DS_Warning:
308 OS << "warning";
309 break;
310 case DS_Remark:
311 OS << "remark";
312 break;
313 case DS_Note:
314 OS << "note";
315 break;
317 if (!CurrentActivity.empty())
318 OS << ' ' << CurrentActivity;
319 OS << ": ";
321 DiagnosticPrinterRawOStream DP(OS);
322 DI.print(DP);
323 OS << '\n';
325 if (DI.getSeverity() == DS_Error)
326 exit(1);
327 return true;
332 static void error(const Twine &Msg) {
333 errs() << "llvm-lto: " << Msg << '\n';
334 exit(1);
337 static void error(std::error_code EC, const Twine &Prefix) {
338 if (EC)
339 error(Prefix + ": " + EC.message());
342 template <typename T>
343 static void error(const ErrorOr<T> &V, const Twine &Prefix) {
344 error(V.getError(), Prefix);
347 static void maybeVerifyModule(const Module &Mod) {
348 if (!DisableVerify && verifyModule(Mod, &errs()))
349 error("Broken Module");
352 static std::unique_ptr<LTOModule>
353 getLocalLTOModule(StringRef Path, std::unique_ptr<MemoryBuffer> &Buffer,
354 const TargetOptions &Options) {
355 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr =
356 MemoryBuffer::getFile(Path);
357 error(BufferOrErr, "error loading file '" + Path + "'");
358 Buffer = std::move(BufferOrErr.get());
359 CurrentActivity = ("loading file '" + Path + "'").str();
360 std::unique_ptr<LLVMContext> Context = std::make_unique<LLVMContext>();
361 Context->setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
362 true);
363 ErrorOr<std::unique_ptr<LTOModule>> Ret = LTOModule::createInLocalContext(
364 std::move(Context), Buffer->getBufferStart(), Buffer->getBufferSize(),
365 Options, Path);
366 CurrentActivity = "";
367 maybeVerifyModule((*Ret)->getModule());
368 return std::move(*Ret);
371 /// Print some statistics on the index for each input files.
372 static void printIndexStats() {
373 for (auto &Filename : InputFilenames) {
374 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
375 std::unique_ptr<ModuleSummaryIndex> Index =
376 ExitOnErr(getModuleSummaryIndexForFile(Filename));
377 // Skip files without a module summary.
378 if (!Index)
379 report_fatal_error(Twine(Filename) + " does not contain an index");
381 unsigned Calls = 0, Refs = 0, Functions = 0, Alias = 0, Globals = 0;
382 for (auto &Summaries : *Index) {
383 for (auto &Summary : Summaries.second.SummaryList) {
384 Refs += Summary->refs().size();
385 if (auto *FuncSummary = dyn_cast<FunctionSummary>(Summary.get())) {
386 Functions++;
387 Calls += FuncSummary->calls().size();
388 } else if (isa<AliasSummary>(Summary.get()))
389 Alias++;
390 else
391 Globals++;
394 outs() << "Index " << Filename << " contains "
395 << (Alias + Globals + Functions) << " nodes (" << Functions
396 << " functions, " << Alias << " alias, " << Globals
397 << " globals) and " << (Calls + Refs) << " edges (" << Refs
398 << " refs and " << Calls << " calls)\n";
402 /// Load each IR file and dump certain information based on active flags.
404 /// The main point here is to provide lit-testable coverage for the LTOModule
405 /// functionality that's exposed by the C API. Moreover, this provides testing
406 /// coverage for modules that have been created in their own contexts.
407 static void testLTOModule(const TargetOptions &Options) {
408 for (auto &Filename : InputFilenames) {
409 std::unique_ptr<MemoryBuffer> Buffer;
410 std::unique_ptr<LTOModule> Module =
411 getLocalLTOModule(Filename, Buffer, Options);
413 if (ListSymbolsOnly) {
414 // List the symbols.
415 outs() << Filename << ":\n";
416 for (int I = 0, E = Module->getSymbolCount(); I != E; ++I)
417 outs() << Module->getSymbolName(I) << "\n";
419 if (QueryHasCtorDtor)
420 outs() << Filename
421 << ": hasCtorDtor = " << (Module->hasCtorDtor() ? "true" : "false")
422 << "\n";
426 static std::unique_ptr<MemoryBuffer> loadFile(StringRef Filename) {
427 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename.str() +
428 "': ");
429 return ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
432 static void listDependentLibraries() {
433 for (auto &Filename : InputFilenames) {
434 auto Buffer = loadFile(Filename);
435 std::string E;
436 std::unique_ptr<lto::InputFile> Input(LTOModule::createInputFile(
437 Buffer->getBufferStart(), Buffer->getBufferSize(), Filename.c_str(),
438 E));
439 if (!Input)
440 error(E);
442 // List the dependent libraries.
443 outs() << Filename << ":\n";
444 for (size_t I = 0, C = LTOModule::getDependentLibraryCount(Input.get());
445 I != C; ++I) {
446 size_t L = 0;
447 const char *S = LTOModule::getDependentLibrary(Input.get(), I, &L);
448 assert(S);
449 outs() << StringRef(S, L) << "\n";
454 static void printMachOCPUOnly() {
455 LLVMContext Context;
456 Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
457 true);
458 TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
459 for (auto &Filename : InputFilenames) {
460 ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
461 LTOModule::createFromFile(Context, Filename, Options);
462 if (!ModuleOrErr)
463 error(ModuleOrErr, "llvm-lto: ");
465 Expected<uint32_t> CPUType = (*ModuleOrErr)->getMachOCPUType();
466 Expected<uint32_t> CPUSubType = (*ModuleOrErr)->getMachOCPUSubType();
467 if (!CPUType)
468 error("Error while printing mach-o cputype: " +
469 toString(CPUType.takeError()));
470 if (!CPUSubType)
471 error("Error while printing mach-o cpusubtype: " +
472 toString(CPUSubType.takeError()));
473 outs() << llvm::format("%s:\ncputype: %u\ncpusubtype: %u\n",
474 Filename.c_str(), *CPUType, *CPUSubType);
478 /// Create a combined index file from the input IR files and write it.
480 /// This is meant to enable testing of ThinLTO combined index generation,
481 /// currently available via the gold plugin via -thinlto.
482 static void createCombinedModuleSummaryIndex() {
483 ModuleSummaryIndex CombinedIndex(/*HaveGVs=*/false);
484 for (auto &Filename : InputFilenames) {
485 ExitOnError ExitOnErr("llvm-lto: error loading file '" + Filename + "': ");
486 std::unique_ptr<MemoryBuffer> MB =
487 ExitOnErr(errorOrToExpected(MemoryBuffer::getFileOrSTDIN(Filename)));
488 ExitOnErr(readModuleSummaryIndex(*MB, CombinedIndex));
490 // In order to use this index for testing, specifically import testing, we
491 // need to update any indirect call edges created from SamplePGO, so that they
492 // point to the correct GUIDs.
493 updateIndirectCalls(CombinedIndex);
494 std::error_code EC;
495 assert(!OutputFilename.empty());
496 raw_fd_ostream OS(OutputFilename + ".thinlto.bc", EC,
497 sys::fs::OpenFlags::OF_None);
498 error(EC, "error opening the file '" + OutputFilename + ".thinlto.bc'");
499 writeIndexToFile(CombinedIndex, OS);
500 OS.close();
503 /// Parse the thinlto_prefix_replace option into the \p OldPrefix and
504 /// \p NewPrefix strings, if it was specified.
505 static void getThinLTOOldAndNewPrefix(std::string &OldPrefix,
506 std::string &NewPrefix) {
507 assert(ThinLTOPrefixReplace.empty() ||
508 ThinLTOPrefixReplace.find(';') != StringRef::npos);
509 StringRef PrefixReplace = ThinLTOPrefixReplace;
510 std::pair<StringRef, StringRef> Split = PrefixReplace.split(";");
511 OldPrefix = Split.first.str();
512 NewPrefix = Split.second.str();
515 /// Given the original \p Path to an output file, replace any path
516 /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
517 /// resulting directory if it does not yet exist.
518 static std::string getThinLTOOutputFile(StringRef Path, StringRef OldPrefix,
519 StringRef NewPrefix) {
520 if (OldPrefix.empty() && NewPrefix.empty())
521 return std::string(Path);
522 SmallString<128> NewPath(Path);
523 llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
524 StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
525 if (!ParentPath.empty()) {
526 // Make sure the new directory exists, creating it if necessary.
527 if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
528 error(EC, "error creating the directory '" + ParentPath + "'");
530 return std::string(NewPath.str());
533 namespace thinlto {
535 std::vector<std::unique_ptr<MemoryBuffer>>
536 loadAllFilesForIndex(const ModuleSummaryIndex &Index) {
537 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
539 for (auto &ModPath : Index.modulePaths()) {
540 const auto &Filename = ModPath.first();
541 std::string CurrentActivity = ("loading file '" + Filename + "'").str();
542 auto InputOrErr = MemoryBuffer::getFile(Filename);
543 error(InputOrErr, "error " + CurrentActivity);
544 InputBuffers.push_back(std::move(*InputOrErr));
546 return InputBuffers;
549 std::unique_ptr<ModuleSummaryIndex> loadCombinedIndex() {
550 if (ThinLTOIndex.empty())
551 report_fatal_error("Missing -thinlto-index for ThinLTO promotion stage");
552 ExitOnError ExitOnErr("llvm-lto: error loading file '" + ThinLTOIndex +
553 "': ");
554 return ExitOnErr(getModuleSummaryIndexForFile(ThinLTOIndex));
557 static std::unique_ptr<lto::InputFile> loadInputFile(MemoryBufferRef Buffer) {
558 ExitOnError ExitOnErr("llvm-lto: error loading input '" +
559 Buffer.getBufferIdentifier().str() + "': ");
560 return ExitOnErr(lto::InputFile::create(Buffer));
563 static std::unique_ptr<Module> loadModuleFromInput(lto::InputFile &File,
564 LLVMContext &CTX) {
565 auto &Mod = File.getSingleBitcodeModule();
566 auto ModuleOrErr = Mod.parseModule(CTX);
567 if (!ModuleOrErr) {
568 handleAllErrors(ModuleOrErr.takeError(), [&](ErrorInfoBase &EIB) {
569 SMDiagnostic Err = SMDiagnostic(Mod.getModuleIdentifier(),
570 SourceMgr::DK_Error, EIB.message());
571 Err.print("llvm-lto", errs());
573 report_fatal_error("Can't load module, abort.");
575 maybeVerifyModule(**ModuleOrErr);
576 if (ThinLTOModuleId.getNumOccurrences()) {
577 if (InputFilenames.size() != 1)
578 report_fatal_error("Can't override the module id for multiple files");
579 (*ModuleOrErr)->setModuleIdentifier(ThinLTOModuleId);
581 return std::move(*ModuleOrErr);
584 static void writeModuleToFile(Module &TheModule, StringRef Filename) {
585 std::error_code EC;
586 raw_fd_ostream OS(Filename, EC, sys::fs::OpenFlags::OF_None);
587 error(EC, "error opening the file '" + Filename + "'");
588 maybeVerifyModule(TheModule);
589 WriteBitcodeToFile(TheModule, OS, /* ShouldPreserveUseListOrder */ true);
592 class ThinLTOProcessing {
593 public:
594 ThinLTOCodeGenerator ThinGenerator;
596 ThinLTOProcessing(const TargetOptions &Options) {
597 ThinGenerator.setCodePICModel(codegen::getExplicitRelocModel());
598 ThinGenerator.setTargetOptions(Options);
599 ThinGenerator.setCacheDir(ThinLTOCacheDir);
600 ThinGenerator.setCachePruningInterval(ThinLTOCachePruningInterval);
601 ThinGenerator.setCacheEntryExpiration(ThinLTOCacheEntryExpiration);
602 ThinGenerator.setCacheMaxSizeFiles(ThinLTOCacheMaxSizeFiles);
603 ThinGenerator.setCacheMaxSizeBytes(ThinLTOCacheMaxSizeBytes);
604 ThinGenerator.setFreestanding(EnableFreestanding);
605 ThinGenerator.setDebugPassManager(DebugPassManager);
607 // Add all the exported symbols to the table of symbols to preserve.
608 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
609 ThinGenerator.preserveSymbol(ExportedSymbols[i]);
612 void run() {
613 switch (ThinLTOMode) {
614 case THINLINK:
615 return thinLink();
616 case THINDISTRIBUTE:
617 return distributedIndexes();
618 case THINEMITIMPORTS:
619 return emitImports();
620 case THINPROMOTE:
621 return promote();
622 case THINIMPORT:
623 return import();
624 case THININTERNALIZE:
625 return internalize();
626 case THINOPT:
627 return optimize();
628 case THINCODEGEN:
629 return codegen();
630 case THINALL:
631 return runAll();
635 private:
636 /// Load the input files, create the combined index, and write it out.
637 void thinLink() {
638 // Perform "ThinLink": just produce the index
639 if (OutputFilename.empty())
640 report_fatal_error(
641 "OutputFilename is necessary to store the combined index.\n");
643 LLVMContext Ctx;
644 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
645 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
646 auto &Filename = InputFilenames[i];
647 std::string CurrentActivity = "loading file '" + Filename + "'";
648 auto InputOrErr = MemoryBuffer::getFile(Filename);
649 error(InputOrErr, "error " + CurrentActivity);
650 InputBuffers.push_back(std::move(*InputOrErr));
651 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
654 auto CombinedIndex = ThinGenerator.linkCombinedIndex();
655 if (!CombinedIndex)
656 report_fatal_error("ThinLink didn't create an index");
657 std::error_code EC;
658 raw_fd_ostream OS(OutputFilename, EC, sys::fs::OpenFlags::OF_None);
659 error(EC, "error opening the file '" + OutputFilename + "'");
660 writeIndexToFile(*CombinedIndex, OS);
663 /// Load the combined index from disk, then compute and generate
664 /// individual index files suitable for ThinLTO distributed backend builds
665 /// on the files mentioned on the command line (these must match the index
666 /// content).
667 void distributedIndexes() {
668 if (InputFilenames.size() != 1 && !OutputFilename.empty())
669 report_fatal_error("Can't handle a single output filename and multiple "
670 "input files, do not provide an output filename and "
671 "the output files will be suffixed from the input "
672 "ones.");
674 std::string OldPrefix, NewPrefix;
675 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
677 auto Index = loadCombinedIndex();
678 for (auto &Filename : InputFilenames) {
679 LLVMContext Ctx;
680 auto Buffer = loadFile(Filename);
681 auto Input = loadInputFile(Buffer->getMemBufferRef());
682 auto TheModule = loadModuleFromInput(*Input, Ctx);
684 // Build a map of module to the GUIDs and summary objects that should
685 // be written to its index.
686 std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
687 ThinGenerator.gatherImportedSummariesForModule(
688 *TheModule, *Index, ModuleToSummariesForIndex, *Input);
690 std::string OutputName = OutputFilename;
691 if (OutputName.empty()) {
692 OutputName = Filename + ".thinlto.bc";
694 OutputName = getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
695 std::error_code EC;
696 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
697 error(EC, "error opening the file '" + OutputName + "'");
698 writeIndexToFile(*Index, OS, &ModuleToSummariesForIndex);
702 /// Load the combined index from disk, compute the imports, and emit
703 /// the import file lists for each module to disk.
704 void emitImports() {
705 if (InputFilenames.size() != 1 && !OutputFilename.empty())
706 report_fatal_error("Can't handle a single output filename and multiple "
707 "input files, do not provide an output filename and "
708 "the output files will be suffixed from the input "
709 "ones.");
711 std::string OldPrefix, NewPrefix;
712 getThinLTOOldAndNewPrefix(OldPrefix, NewPrefix);
714 auto Index = loadCombinedIndex();
715 for (auto &Filename : InputFilenames) {
716 LLVMContext Ctx;
717 auto Buffer = loadFile(Filename);
718 auto Input = loadInputFile(Buffer->getMemBufferRef());
719 auto TheModule = loadModuleFromInput(*Input, Ctx);
720 std::string OutputName = OutputFilename;
721 if (OutputName.empty()) {
722 OutputName = Filename + ".imports";
724 OutputName =
725 getThinLTOOutputFile(OutputName, OldPrefix, NewPrefix);
726 ThinGenerator.emitImports(*TheModule, OutputName, *Index, *Input);
730 /// Load the combined index from disk, then load every file referenced by
731 /// the index and add them to the generator, finally perform the promotion
732 /// on the files mentioned on the command line (these must match the index
733 /// content).
734 void promote() {
735 if (InputFilenames.size() != 1 && !OutputFilename.empty())
736 report_fatal_error("Can't handle a single output filename and multiple "
737 "input files, do not provide an output filename and "
738 "the output files will be suffixed from the input "
739 "ones.");
741 auto Index = loadCombinedIndex();
742 for (auto &Filename : InputFilenames) {
743 LLVMContext Ctx;
744 auto Buffer = loadFile(Filename);
745 auto Input = loadInputFile(Buffer->getMemBufferRef());
746 auto TheModule = loadModuleFromInput(*Input, Ctx);
748 ThinGenerator.promote(*TheModule, *Index, *Input);
750 std::string OutputName = OutputFilename;
751 if (OutputName.empty()) {
752 OutputName = Filename + ".thinlto.promoted.bc";
754 writeModuleToFile(*TheModule, OutputName);
758 /// Load the combined index from disk, then load every file referenced by
759 /// the index and add them to the generator, then performs the promotion and
760 /// cross module importing on the files mentioned on the command line
761 /// (these must match the index content).
762 void import() {
763 if (InputFilenames.size() != 1 && !OutputFilename.empty())
764 report_fatal_error("Can't handle a single output filename and multiple "
765 "input files, do not provide an output filename and "
766 "the output files will be suffixed from the input "
767 "ones.");
769 auto Index = loadCombinedIndex();
770 auto InputBuffers = loadAllFilesForIndex(*Index);
771 for (auto &MemBuffer : InputBuffers)
772 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
773 MemBuffer->getBuffer());
775 for (auto &Filename : InputFilenames) {
776 LLVMContext Ctx;
777 auto Buffer = loadFile(Filename);
778 auto Input = loadInputFile(Buffer->getMemBufferRef());
779 auto TheModule = loadModuleFromInput(*Input, Ctx);
781 ThinGenerator.crossModuleImport(*TheModule, *Index, *Input);
783 std::string OutputName = OutputFilename;
784 if (OutputName.empty()) {
785 OutputName = Filename + ".thinlto.imported.bc";
787 writeModuleToFile(*TheModule, OutputName);
791 void internalize() {
792 if (InputFilenames.size() != 1 && !OutputFilename.empty())
793 report_fatal_error("Can't handle a single output filename and multiple "
794 "input files, do not provide an output filename and "
795 "the output files will be suffixed from the input "
796 "ones.");
798 if (ExportedSymbols.empty())
799 errs() << "Warning: -internalize will not perform without "
800 "-exported-symbol\n";
802 auto Index = loadCombinedIndex();
803 auto InputBuffers = loadAllFilesForIndex(*Index);
804 for (auto &MemBuffer : InputBuffers)
805 ThinGenerator.addModule(MemBuffer->getBufferIdentifier(),
806 MemBuffer->getBuffer());
808 for (auto &Filename : InputFilenames) {
809 LLVMContext Ctx;
810 auto Buffer = loadFile(Filename);
811 auto Input = loadInputFile(Buffer->getMemBufferRef());
812 auto TheModule = loadModuleFromInput(*Input, Ctx);
814 ThinGenerator.internalize(*TheModule, *Index, *Input);
816 std::string OutputName = OutputFilename;
817 if (OutputName.empty()) {
818 OutputName = Filename + ".thinlto.internalized.bc";
820 writeModuleToFile(*TheModule, OutputName);
824 void optimize() {
825 if (InputFilenames.size() != 1 && !OutputFilename.empty())
826 report_fatal_error("Can't handle a single output filename and multiple "
827 "input files, do not provide an output filename and "
828 "the output files will be suffixed from the input "
829 "ones.");
830 if (!ThinLTOIndex.empty())
831 errs() << "Warning: -thinlto-index ignored for optimize stage";
833 for (auto &Filename : InputFilenames) {
834 LLVMContext Ctx;
835 auto Buffer = loadFile(Filename);
836 auto Input = loadInputFile(Buffer->getMemBufferRef());
837 auto TheModule = loadModuleFromInput(*Input, Ctx);
839 ThinGenerator.optimize(*TheModule);
841 std::string OutputName = OutputFilename;
842 if (OutputName.empty()) {
843 OutputName = Filename + ".thinlto.imported.bc";
845 writeModuleToFile(*TheModule, OutputName);
849 void codegen() {
850 if (InputFilenames.size() != 1 && !OutputFilename.empty())
851 report_fatal_error("Can't handle a single output filename and multiple "
852 "input files, do not provide an output filename and "
853 "the output files will be suffixed from the input "
854 "ones.");
855 if (!ThinLTOIndex.empty())
856 errs() << "Warning: -thinlto-index ignored for codegen stage";
858 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
859 for (auto &Filename : InputFilenames) {
860 LLVMContext Ctx;
861 auto InputOrErr = MemoryBuffer::getFile(Filename);
862 error(InputOrErr, "error " + CurrentActivity);
863 InputBuffers.push_back(std::move(*InputOrErr));
864 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
866 ThinGenerator.setCodeGenOnly(true);
867 ThinGenerator.run();
868 for (auto BinName :
869 zip(ThinGenerator.getProducedBinaries(), InputFilenames)) {
870 std::string OutputName = OutputFilename;
871 if (OutputName.empty())
872 OutputName = std::get<1>(BinName) + ".thinlto.o";
873 else if (OutputName == "-") {
874 outs() << std::get<0>(BinName)->getBuffer();
875 return;
878 std::error_code EC;
879 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
880 error(EC, "error opening the file '" + OutputName + "'");
881 OS << std::get<0>(BinName)->getBuffer();
885 /// Full ThinLTO process
886 void runAll() {
887 if (!OutputFilename.empty())
888 report_fatal_error("Do not provide an output filename for ThinLTO "
889 " processing, the output files will be suffixed from "
890 "the input ones.");
892 if (!ThinLTOIndex.empty())
893 errs() << "Warning: -thinlto-index ignored for full ThinLTO process";
895 LLVMContext Ctx;
896 std::vector<std::unique_ptr<MemoryBuffer>> InputBuffers;
897 for (unsigned i = 0; i < InputFilenames.size(); ++i) {
898 auto &Filename = InputFilenames[i];
899 std::string CurrentActivity = "loading file '" + Filename + "'";
900 auto InputOrErr = MemoryBuffer::getFile(Filename);
901 error(InputOrErr, "error " + CurrentActivity);
902 InputBuffers.push_back(std::move(*InputOrErr));
903 ThinGenerator.addModule(Filename, InputBuffers.back()->getBuffer());
906 if (!ThinLTOSaveTempsPrefix.empty())
907 ThinGenerator.setSaveTempsDir(ThinLTOSaveTempsPrefix);
909 if (!ThinLTOGeneratedObjectsDir.empty()) {
910 ThinGenerator.setGeneratedObjectsDirectory(ThinLTOGeneratedObjectsDir);
911 ThinGenerator.run();
912 return;
915 ThinGenerator.run();
917 auto &Binaries = ThinGenerator.getProducedBinaries();
918 if (Binaries.size() != InputFilenames.size())
919 report_fatal_error("Number of output objects does not match the number "
920 "of inputs");
922 for (unsigned BufID = 0; BufID < Binaries.size(); ++BufID) {
923 auto OutputName = InputFilenames[BufID] + ".thinlto.o";
924 std::error_code EC;
925 raw_fd_ostream OS(OutputName, EC, sys::fs::OpenFlags::OF_None);
926 error(EC, "error opening the file '" + OutputName + "'");
927 OS << Binaries[BufID]->getBuffer();
931 /// Load the combined index from disk, then load every file referenced by
934 } // end namespace thinlto
936 int main(int argc, char **argv) {
937 InitLLVM X(argc, argv);
938 cl::HideUnrelatedOptions({&LTOCategory, &getColorCategory()});
939 cl::ParseCommandLineOptions(argc, argv, "llvm LTO linker\n");
941 if (OptLevel < '0' || OptLevel > '3')
942 error("optimization level must be between 0 and 3");
944 // Initialize the configured targets.
945 InitializeAllTargets();
946 InitializeAllTargetMCs();
947 InitializeAllAsmPrinters();
948 InitializeAllAsmParsers();
950 // set up the TargetOptions for the machine
951 TargetOptions Options = codegen::InitTargetOptionsFromCodeGenFlags(Triple());
953 if (ListSymbolsOnly || QueryHasCtorDtor) {
954 testLTOModule(Options);
955 return 0;
958 if (ListDependentLibrariesOnly) {
959 listDependentLibraries();
960 return 0;
963 if (IndexStats) {
964 printIndexStats();
965 return 0;
968 if (CheckHasObjC) {
969 for (auto &Filename : InputFilenames) {
970 ExitOnError ExitOnErr(std::string(*argv) + ": error loading file '" +
971 Filename + "': ");
972 std::unique_ptr<MemoryBuffer> BufferOrErr =
973 ExitOnErr(errorOrToExpected(MemoryBuffer::getFile(Filename)));
974 auto Buffer = std::move(BufferOrErr.get());
975 if (ExitOnErr(isBitcodeContainingObjCCategory(*Buffer)))
976 outs() << "Bitcode " << Filename << " contains ObjC\n";
977 else
978 outs() << "Bitcode " << Filename << " does not contain ObjC\n";
980 return 0;
983 if (PrintMachOCPUOnly) {
984 printMachOCPUOnly();
985 return 0;
988 if (ThinLTOMode.getNumOccurrences()) {
989 if (ThinLTOMode.getNumOccurrences() > 1)
990 report_fatal_error("You can't specify more than one -thinlto-action");
991 thinlto::ThinLTOProcessing ThinLTOProcessor(Options);
992 ThinLTOProcessor.run();
993 return 0;
996 if (ThinLTO) {
997 createCombinedModuleSummaryIndex();
998 return 0;
1001 unsigned BaseArg = 0;
1003 LLVMContext Context;
1004 Context.setDiagnosticHandler(std::make_unique<LLVMLTODiagnosticHandler>(),
1005 true);
1007 LTOCodeGenerator CodeGen(Context);
1008 CodeGen.setDisableVerify(DisableVerify);
1010 if (UseDiagnosticHandler)
1011 CodeGen.setDiagnosticHandler(handleDiagnostics, nullptr);
1013 CodeGen.setCodePICModel(codegen::getExplicitRelocModel());
1014 CodeGen.setFreestanding(EnableFreestanding);
1015 CodeGen.setDebugPassManager(DebugPassManager);
1017 CodeGen.setDebugInfo(LTO_DEBUG_MODEL_DWARF);
1018 CodeGen.setTargetOptions(Options);
1019 CodeGen.setShouldRestoreGlobalsLinkage(RestoreGlobalsLinkage);
1021 StringSet<MallocAllocator> DSOSymbolsSet;
1022 for (unsigned i = 0; i < DSOSymbols.size(); ++i)
1023 DSOSymbolsSet.insert(DSOSymbols[i]);
1025 std::vector<std::string> KeptDSOSyms;
1027 for (unsigned i = BaseArg; i < InputFilenames.size(); ++i) {
1028 CurrentActivity = "loading file '" + InputFilenames[i] + "'";
1029 ErrorOr<std::unique_ptr<LTOModule>> ModuleOrErr =
1030 LTOModule::createFromFile(Context, InputFilenames[i], Options);
1031 std::unique_ptr<LTOModule> &Module = *ModuleOrErr;
1032 CurrentActivity = "";
1034 unsigned NumSyms = Module->getSymbolCount();
1035 for (unsigned I = 0; I < NumSyms; ++I) {
1036 StringRef Name = Module->getSymbolName(I);
1037 if (!DSOSymbolsSet.count(Name))
1038 continue;
1039 lto_symbol_attributes Attrs = Module->getSymbolAttributes(I);
1040 unsigned Scope = Attrs & LTO_SYMBOL_SCOPE_MASK;
1041 if (Scope != LTO_SYMBOL_SCOPE_DEFAULT_CAN_BE_HIDDEN)
1042 KeptDSOSyms.push_back(std::string(Name));
1045 // We use the first input module as the destination module when
1046 // SetMergedModule is true.
1047 if (SetMergedModule && i == BaseArg) {
1048 // Transfer ownership to the code generator.
1049 CodeGen.setModule(std::move(Module));
1050 } else if (!CodeGen.addModule(Module.get())) {
1051 // Print a message here so that we know addModule() did not abort.
1052 error("error adding file '" + InputFilenames[i] + "'");
1056 // Add all the exported symbols to the table of symbols to preserve.
1057 for (unsigned i = 0; i < ExportedSymbols.size(); ++i)
1058 CodeGen.addMustPreserveSymbol(ExportedSymbols[i]);
1060 // Add all the dso symbols to the table of symbols to expose.
1061 for (unsigned i = 0; i < KeptDSOSyms.size(); ++i)
1062 CodeGen.addMustPreserveSymbol(KeptDSOSyms[i]);
1064 // Set cpu and attrs strings for the default target/subtarget.
1065 CodeGen.setCpu(codegen::getMCPU());
1067 CodeGen.setOptLevel(OptLevel - '0');
1068 CodeGen.setAttrs(codegen::getMAttrs());
1070 if (auto FT = codegen::getExplicitFileType())
1071 CodeGen.setFileType(*FT);
1073 if (!OutputFilename.empty()) {
1074 if (LTOSaveBeforeOpt)
1075 CodeGen.setSaveIRBeforeOptPath(OutputFilename + ".0.preopt.bc");
1077 if (SaveLinkedModuleFile) {
1078 std::string ModuleFilename = OutputFilename;
1079 ModuleFilename += ".linked.bc";
1080 std::string ErrMsg;
1082 if (!CodeGen.writeMergedModules(ModuleFilename))
1083 error("writing linked module failed.");
1086 if (!CodeGen.optimize()) {
1087 // Diagnostic messages should have been printed by the handler.
1088 error("error optimizing the code");
1091 if (SaveModuleFile) {
1092 std::string ModuleFilename = OutputFilename;
1093 ModuleFilename += ".merged.bc";
1094 std::string ErrMsg;
1096 if (!CodeGen.writeMergedModules(ModuleFilename))
1097 error("writing merged module failed.");
1100 auto AddStream =
1101 [&](size_t Task,
1102 const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> {
1103 std::string PartFilename = OutputFilename;
1104 if (Parallelism != 1)
1105 PartFilename += "." + utostr(Task);
1107 std::error_code EC;
1108 auto S =
1109 std::make_unique<raw_fd_ostream>(PartFilename, EC, sys::fs::OF_None);
1110 if (EC)
1111 error("error opening the file '" + PartFilename + "': " + EC.message());
1112 return std::make_unique<CachedFileStream>(std::move(S));
1115 if (!CodeGen.compileOptimized(AddStream, Parallelism))
1116 // Diagnostic messages should have been printed by the handler.
1117 error("error compiling the code");
1119 } else {
1120 if (Parallelism != 1)
1121 error("-j must be specified together with -o");
1123 if (SaveModuleFile)
1124 error(": -save-merged-module must be specified with -o");
1126 const char *OutputName = nullptr;
1127 if (!CodeGen.compile_to_file(&OutputName))
1128 error("error compiling the code");
1129 // Diagnostic messages should have been printed by the handler.
1131 outs() << "Wrote native object file '" << OutputName << "'\n";
1134 return 0;