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