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