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