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