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