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