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