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