1 //===-LTOCodeGenerator.cpp - LLVM Link Time Optimizer ---------------------===// 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 file implements the Link Time Optimization library. This library is 10 // intended to be used by linker to optimize code at link time. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/LTO/legacy/LTOCodeGenerator.h" 15 16 #include "llvm/ADT/Statistic.h" 17 #include "llvm/ADT/StringExtras.h" 18 #include "llvm/Analysis/TargetLibraryInfo.h" 19 #include "llvm/Analysis/TargetTransformInfo.h" 20 #include "llvm/Bitcode/BitcodeWriter.h" 21 #include "llvm/CodeGen/CommandFlags.h" 22 #include "llvm/CodeGen/TargetSubtargetInfo.h" 23 #include "llvm/Config/config.h" 24 #include "llvm/IR/DataLayout.h" 25 #include "llvm/IR/DebugInfo.h" 26 #include "llvm/IR/DerivedTypes.h" 27 #include "llvm/IR/DiagnosticInfo.h" 28 #include "llvm/IR/DiagnosticPrinter.h" 29 #include "llvm/IR/LLVMContext.h" 30 #include "llvm/IR/LLVMRemarkStreamer.h" 31 #include "llvm/IR/LegacyPassManager.h" 32 #include "llvm/IR/Mangler.h" 33 #include "llvm/IR/Module.h" 34 #include "llvm/IR/PassTimingInfo.h" 35 #include "llvm/IR/Verifier.h" 36 #include "llvm/LTO/LTO.h" 37 #include "llvm/LTO/LTOBackend.h" 38 #include "llvm/LTO/legacy/LTOModule.h" 39 #include "llvm/LTO/legacy/UpdateCompilerUsed.h" 40 #include "llvm/Linker/Linker.h" 41 #include "llvm/MC/TargetRegistry.h" 42 #include "llvm/Remarks/HotnessThresholdParser.h" 43 #include "llvm/Support/CommandLine.h" 44 #include "llvm/Support/FileSystem.h" 45 #include "llvm/Support/MemoryBuffer.h" 46 #include "llvm/Support/Process.h" 47 #include "llvm/Support/Signals.h" 48 #include "llvm/Support/ToolOutputFile.h" 49 #include "llvm/Support/raw_ostream.h" 50 #include "llvm/Target/TargetOptions.h" 51 #include "llvm/TargetParser/Host.h" 52 #include "llvm/TargetParser/SubtargetFeature.h" 53 #include "llvm/Transforms/IPO.h" 54 #include "llvm/Transforms/IPO/Internalize.h" 55 #include "llvm/Transforms/IPO/WholeProgramDevirt.h" 56 #include "llvm/Transforms/Utils/ModuleUtils.h" 57 #include <optional> 58 #include <system_error> 59 using namespace llvm; 60 61 const char* LTOCodeGenerator::getVersionString() { 62 return PACKAGE_NAME " version " PACKAGE_VERSION; 63 } 64 65 namespace llvm { 66 cl::opt<bool> LTODiscardValueNames( 67 "lto-discard-value-names", 68 cl::desc("Strip names from Value during LTO (other than GlobalValue)."), 69 #ifdef NDEBUG 70 cl::init(true), 71 #else 72 cl::init(false), 73 #endif 74 cl::Hidden); 75 76 cl::opt<bool> RemarksWithHotness( 77 "lto-pass-remarks-with-hotness", 78 cl::desc("With PGO, include profile count in optimization remarks"), 79 cl::Hidden); 80 81 cl::opt<std::optional<uint64_t>, false, remarks::HotnessThresholdParser> 82 RemarksHotnessThreshold( 83 "lto-pass-remarks-hotness-threshold", 84 cl::desc("Minimum profile count required for an " 85 "optimization remark to be output." 86 " Use 'auto' to apply the threshold from profile summary."), 87 cl::value_desc("uint or 'auto'"), cl::init(0), cl::Hidden); 88 89 cl::opt<std::string> 90 RemarksFilename("lto-pass-remarks-output", 91 cl::desc("Output filename for pass remarks"), 92 cl::value_desc("filename")); 93 94 cl::opt<std::string> 95 RemarksPasses("lto-pass-remarks-filter", 96 cl::desc("Only record optimization remarks from passes whose " 97 "names match the given regular expression"), 98 cl::value_desc("regex")); 99 100 cl::opt<std::string> RemarksFormat( 101 "lto-pass-remarks-format", 102 cl::desc("The format used for serializing remarks (default: YAML)"), 103 cl::value_desc("format"), cl::init("yaml")); 104 105 static cl::opt<std::string> 106 LTOStatsFile("lto-stats-file", 107 cl::desc("Save statistics to the specified file"), cl::Hidden); 108 109 static cl::opt<std::string> AIXSystemAssemblerPath( 110 "lto-aix-system-assembler", 111 cl::desc("Path to a system assembler, picked up on AIX only"), 112 cl::value_desc("path")); 113 114 static cl::opt<bool> 115 LTORunCSIRInstr("cs-profile-generate", 116 cl::desc("Perform context sensitive PGO instrumentation")); 117 118 static cl::opt<std::string> 119 LTOCSIRProfile("cs-profile-path", 120 cl::desc("Context sensitive profile file path")); 121 } // namespace llvm 122 123 LTOCodeGenerator::LTOCodeGenerator(LLVMContext &Context) 124 : Context(Context), MergedModule(new Module("ld-temp.o", Context)), 125 TheLinker(new Linker(*MergedModule)) { 126 Context.setDiscardValueNames(LTODiscardValueNames); 127 Context.enableDebugTypeODRUniquing(); 128 129 Config.CodeModel = std::nullopt; 130 Config.StatsFile = LTOStatsFile; 131 Config.RunCSIRInstr = LTORunCSIRInstr; 132 Config.CSIRProfile = LTOCSIRProfile; 133 } 134 135 LTOCodeGenerator::~LTOCodeGenerator() = default; 136 137 void LTOCodeGenerator::setAsmUndefinedRefs(LTOModule *Mod) { 138 AsmUndefinedRefs.insert_range(Mod->getAsmUndefinedRefs()); 139 } 140 141 bool LTOCodeGenerator::addModule(LTOModule *Mod) { 142 assert(&Mod->getModule().getContext() == &Context && 143 "Expected module in same context"); 144 145 bool ret = TheLinker->linkInModule(Mod->takeModule()); 146 setAsmUndefinedRefs(Mod); 147 148 // We've just changed the input, so let's make sure we verify it. 149 HasVerifiedInput = false; 150 151 return !ret; 152 } 153 154 void LTOCodeGenerator::setModule(std::unique_ptr<LTOModule> Mod) { 155 assert(&Mod->getModule().getContext() == &Context && 156 "Expected module in same context"); 157 158 AsmUndefinedRefs.clear(); 159 160 MergedModule = Mod->takeModule(); 161 TheLinker = std::make_unique<Linker>(*MergedModule); 162 setAsmUndefinedRefs(&*Mod); 163 164 // We've just changed the input, so let's make sure we verify it. 165 HasVerifiedInput = false; 166 } 167 168 void LTOCodeGenerator::setTargetOptions(const TargetOptions &Options) { 169 Config.Options = Options; 170 } 171 172 void LTOCodeGenerator::setDebugInfo(lto_debug_model Debug) { 173 switch (Debug) { 174 case LTO_DEBUG_MODEL_NONE: 175 EmitDwarfDebugInfo = false; 176 return; 177 178 case LTO_DEBUG_MODEL_DWARF: 179 EmitDwarfDebugInfo = true; 180 return; 181 } 182 llvm_unreachable("Unknown debug format!"); 183 } 184 185 void LTOCodeGenerator::setOptLevel(unsigned Level) { 186 Config.OptLevel = Level; 187 Config.PTO.LoopVectorization = Config.OptLevel > 1; 188 Config.PTO.SLPVectorization = Config.OptLevel > 1; 189 std::optional<CodeGenOptLevel> CGOptLevelOrNone = 190 CodeGenOpt::getLevel(Config.OptLevel); 191 assert(CGOptLevelOrNone && "Unknown optimization level!"); 192 Config.CGOptLevel = *CGOptLevelOrNone; 193 } 194 195 bool LTOCodeGenerator::writeMergedModules(StringRef Path) { 196 if (!determineTarget()) 197 return false; 198 199 // We always run the verifier once on the merged module. 200 verifyMergedModuleOnce(); 201 202 // mark which symbols can not be internalized 203 applyScopeRestrictions(); 204 205 // create output file 206 std::error_code EC; 207 ToolOutputFile Out(Path, EC, sys::fs::OF_None); 208 if (EC) { 209 std::string ErrMsg = "could not open bitcode file for writing: "; 210 ErrMsg += Path.str() + ": " + EC.message(); 211 emitError(ErrMsg); 212 return false; 213 } 214 215 // write bitcode to it 216 WriteBitcodeToFile(*MergedModule, Out.os(), ShouldEmbedUselists); 217 Out.os().close(); 218 219 if (Out.os().has_error()) { 220 std::string ErrMsg = "could not write bitcode file: "; 221 ErrMsg += Path.str() + ": " + Out.os().error().message(); 222 emitError(ErrMsg); 223 Out.os().clear_error(); 224 return false; 225 } 226 227 Out.keep(); 228 return true; 229 } 230 231 bool LTOCodeGenerator::useAIXSystemAssembler() { 232 const auto &Triple = TargetMach->getTargetTriple(); 233 return Triple.isOSAIX() && Config.Options.DisableIntegratedAS; 234 } 235 236 bool LTOCodeGenerator::runAIXSystemAssembler(SmallString<128> &AssemblyFile) { 237 assert(useAIXSystemAssembler() && 238 "Runing AIX system assembler when integrated assembler is available!"); 239 240 // Set the system assembler path. 241 SmallString<256> AssemblerPath("/usr/bin/as"); 242 if (!llvm::AIXSystemAssemblerPath.empty()) { 243 if (llvm::sys::fs::real_path(llvm::AIXSystemAssemblerPath, AssemblerPath, 244 /* expand_tilde */ true)) { 245 emitError( 246 "Cannot find the assembler specified by lto-aix-system-assembler"); 247 return false; 248 } 249 } 250 251 // Setup the LDR_CNTRL variable 252 std::string LDR_CNTRL_var = "LDR_CNTRL=MAXDATA32=0xA0000000@DSA"; 253 if (std::optional<std::string> V = sys::Process::GetEnv("LDR_CNTRL")) 254 LDR_CNTRL_var += ("@" + *V); 255 256 // Prepare inputs for the assember. 257 const auto &Triple = TargetMach->getTargetTriple(); 258 const char *Arch = Triple.isArch64Bit() ? "-a64" : "-a32"; 259 std::string ObjectFileName(AssemblyFile); 260 ObjectFileName[ObjectFileName.size() - 1] = 'o'; 261 SmallVector<StringRef, 8> Args = { 262 "/bin/env", LDR_CNTRL_var, 263 AssemblerPath, Arch, 264 "-many", "-o", 265 ObjectFileName, AssemblyFile}; 266 267 // Invoke the assembler. 268 int RC = sys::ExecuteAndWait(Args[0], Args); 269 270 // Handle errors. 271 if (RC < -1) { 272 emitError("LTO assembler exited abnormally"); 273 return false; 274 } 275 if (RC < 0) { 276 emitError("Unable to invoke LTO assembler"); 277 return false; 278 } 279 if (RC > 0) { 280 emitError("LTO assembler invocation returned non-zero"); 281 return false; 282 } 283 284 // Cleanup. 285 remove(AssemblyFile.c_str()); 286 287 // Fix the output file name. 288 AssemblyFile = ObjectFileName; 289 290 return true; 291 } 292 293 bool LTOCodeGenerator::compileOptimizedToFile(const char **Name) { 294 if (useAIXSystemAssembler()) 295 setFileType(CodeGenFileType::AssemblyFile); 296 297 // make unique temp output file to put generated code 298 SmallString<128> Filename; 299 300 auto AddStream = 301 [&](size_t Task, 302 const Twine &ModuleName) -> std::unique_ptr<CachedFileStream> { 303 StringRef Extension( 304 Config.CGFileType == CodeGenFileType::AssemblyFile ? "s" : "o"); 305 306 int FD; 307 std::error_code EC = 308 sys::fs::createTemporaryFile("lto-llvm", Extension, FD, Filename); 309 if (EC) 310 emitError(EC.message()); 311 312 return std::make_unique<CachedFileStream>( 313 std::make_unique<llvm::raw_fd_ostream>(FD, true)); 314 }; 315 316 bool genResult = compileOptimized(AddStream, 1); 317 318 if (!genResult) { 319 sys::fs::remove(Twine(Filename)); 320 return false; 321 } 322 323 // If statistics were requested, save them to the specified file or 324 // print them out after codegen. 325 if (StatsFile) 326 PrintStatisticsJSON(StatsFile->os()); 327 else if (AreStatisticsEnabled()) 328 PrintStatistics(); 329 330 if (useAIXSystemAssembler()) 331 if (!runAIXSystemAssembler(Filename)) 332 return false; 333 334 NativeObjectPath = Filename.c_str(); 335 *Name = NativeObjectPath.c_str(); 336 return true; 337 } 338 339 std::unique_ptr<MemoryBuffer> 340 LTOCodeGenerator::compileOptimized() { 341 const char *name; 342 if (!compileOptimizedToFile(&name)) 343 return nullptr; 344 345 // read .o file into memory buffer 346 ErrorOr<std::unique_ptr<MemoryBuffer>> BufferOrErr = MemoryBuffer::getFile( 347 name, /*IsText=*/false, /*RequiresNullTerminator=*/false); 348 if (std::error_code EC = BufferOrErr.getError()) { 349 emitError(EC.message()); 350 sys::fs::remove(NativeObjectPath); 351 return nullptr; 352 } 353 354 // remove temp files 355 sys::fs::remove(NativeObjectPath); 356 357 return std::move(*BufferOrErr); 358 } 359 360 bool LTOCodeGenerator::compile_to_file(const char **Name) { 361 if (!optimize()) 362 return false; 363 364 return compileOptimizedToFile(Name); 365 } 366 367 std::unique_ptr<MemoryBuffer> LTOCodeGenerator::compile() { 368 if (!optimize()) 369 return nullptr; 370 371 return compileOptimized(); 372 } 373 374 bool LTOCodeGenerator::determineTarget() { 375 if (TargetMach) 376 return true; 377 378 TripleStr = MergedModule->getTargetTriple().str(); 379 llvm::Triple Triple(TripleStr); 380 if (TripleStr.empty()) { 381 TripleStr = sys::getDefaultTargetTriple(); 382 MergedModule->setTargetTriple(Triple); 383 } 384 385 // create target machine from info for merged modules 386 std::string ErrMsg; 387 MArch = TargetRegistry::lookupTarget(TripleStr, ErrMsg); 388 if (!MArch) { 389 emitError(ErrMsg); 390 return false; 391 } 392 393 // Construct LTOModule, hand over ownership of module and target. Use MAttr as 394 // the default set of features. 395 SubtargetFeatures Features(join(Config.MAttrs, "")); 396 Features.getDefaultSubtargetFeatures(Triple); 397 FeatureStr = Features.getString(); 398 if (Config.CPU.empty()) 399 Config.CPU = lto::getThinLTODefaultCPU(Triple); 400 401 // If data-sections is not explicitly set or unset, set data-sections by 402 // default to match the behaviour of lld and gold plugin. 403 if (!codegen::getExplicitDataSections()) 404 Config.Options.DataSections = true; 405 406 TargetMach = createTargetMachine(); 407 assert(TargetMach && "Unable to create target machine"); 408 409 return true; 410 } 411 412 std::unique_ptr<TargetMachine> LTOCodeGenerator::createTargetMachine() { 413 assert(MArch && "MArch is not set!"); 414 return std::unique_ptr<TargetMachine>(MArch->createTargetMachine( 415 Triple(TripleStr), Config.CPU, FeatureStr, Config.Options, 416 Config.RelocModel, std::nullopt, Config.CGOptLevel)); 417 } 418 419 // If a linkonce global is present in the MustPreserveSymbols, we need to make 420 // sure we honor this. To force the compiler to not drop it, we add it to the 421 // "llvm.compiler.used" global. 422 void LTOCodeGenerator::preserveDiscardableGVs( 423 Module &TheModule, 424 llvm::function_ref<bool(const GlobalValue &)> mustPreserveGV) { 425 std::vector<GlobalValue *> Used; 426 auto mayPreserveGlobal = [&](GlobalValue &GV) { 427 if (!GV.isDiscardableIfUnused() || GV.isDeclaration() || 428 !mustPreserveGV(GV)) 429 return; 430 if (GV.hasAvailableExternallyLinkage()) 431 return emitWarning( 432 (Twine("Linker asked to preserve available_externally global: '") + 433 GV.getName() + "'").str()); 434 if (GV.hasInternalLinkage()) 435 return emitWarning((Twine("Linker asked to preserve internal global: '") + 436 GV.getName() + "'").str()); 437 Used.push_back(&GV); 438 }; 439 for (auto &GV : TheModule) 440 mayPreserveGlobal(GV); 441 for (auto &GV : TheModule.globals()) 442 mayPreserveGlobal(GV); 443 for (auto &GV : TheModule.aliases()) 444 mayPreserveGlobal(GV); 445 446 if (Used.empty()) 447 return; 448 449 appendToCompilerUsed(TheModule, Used); 450 } 451 452 void LTOCodeGenerator::applyScopeRestrictions() { 453 if (ScopeRestrictionsDone) 454 return; 455 456 // Declare a callback for the internalize pass that will ask for every 457 // candidate GlobalValue if it can be internalized or not. 458 Mangler Mang; 459 SmallString<64> MangledName; 460 auto mustPreserveGV = [&](const GlobalValue &GV) -> bool { 461 // Unnamed globals can't be mangled, but they can't be preserved either. 462 if (!GV.hasName()) 463 return false; 464 465 // Need to mangle the GV as the "MustPreserveSymbols" StringSet is filled 466 // with the linker supplied name, which on Darwin includes a leading 467 // underscore. 468 MangledName.clear(); 469 MangledName.reserve(GV.getName().size() + 1); 470 Mang.getNameWithPrefix(MangledName, &GV, /*CannotUsePrivateLabel=*/false); 471 return MustPreserveSymbols.count(MangledName); 472 }; 473 474 // Preserve linkonce value on linker request 475 preserveDiscardableGVs(*MergedModule, mustPreserveGV); 476 477 if (!ShouldInternalize) 478 return; 479 480 if (ShouldRestoreGlobalsLinkage) { 481 // Record the linkage type of non-local symbols so they can be restored 482 // prior 483 // to module splitting. 484 auto RecordLinkage = [&](const GlobalValue &GV) { 485 if (!GV.hasAvailableExternallyLinkage() && !GV.hasLocalLinkage() && 486 GV.hasName()) 487 ExternalSymbols.insert(std::make_pair(GV.getName(), GV.getLinkage())); 488 }; 489 for (auto &GV : *MergedModule) 490 RecordLinkage(GV); 491 for (auto &GV : MergedModule->globals()) 492 RecordLinkage(GV); 493 for (auto &GV : MergedModule->aliases()) 494 RecordLinkage(GV); 495 } 496 497 // Update the llvm.compiler_used globals to force preserving libcalls and 498 // symbols referenced from asm 499 updateCompilerUsed(*MergedModule, *TargetMach, AsmUndefinedRefs); 500 501 internalizeModule(*MergedModule, mustPreserveGV); 502 503 ScopeRestrictionsDone = true; 504 } 505 506 /// Restore original linkage for symbols that may have been internalized 507 void LTOCodeGenerator::restoreLinkageForExternals() { 508 if (!ShouldInternalize || !ShouldRestoreGlobalsLinkage) 509 return; 510 511 assert(ScopeRestrictionsDone && 512 "Cannot externalize without internalization!"); 513 514 if (ExternalSymbols.empty()) 515 return; 516 517 auto externalize = [this](GlobalValue &GV) { 518 if (!GV.hasLocalLinkage() || !GV.hasName()) 519 return; 520 521 auto I = ExternalSymbols.find(GV.getName()); 522 if (I == ExternalSymbols.end()) 523 return; 524 525 GV.setLinkage(I->second); 526 }; 527 528 llvm::for_each(MergedModule->functions(), externalize); 529 llvm::for_each(MergedModule->globals(), externalize); 530 llvm::for_each(MergedModule->aliases(), externalize); 531 } 532 533 void LTOCodeGenerator::verifyMergedModuleOnce() { 534 // Only run on the first call. 535 if (HasVerifiedInput) 536 return; 537 HasVerifiedInput = true; 538 539 bool BrokenDebugInfo = false; 540 if (verifyModule(*MergedModule, &dbgs(), &BrokenDebugInfo)) 541 report_fatal_error("Broken module found, compilation aborted!"); 542 if (BrokenDebugInfo) { 543 emitWarning("Invalid debug info found, debug info will be stripped"); 544 StripDebugInfo(*MergedModule); 545 } 546 } 547 548 void LTOCodeGenerator::finishOptimizationRemarks() { 549 if (DiagnosticOutputFile) { 550 DiagnosticOutputFile->keep(); 551 // FIXME: LTOCodeGenerator dtor is not invoked on Darwin 552 DiagnosticOutputFile->os().flush(); 553 } 554 } 555 556 /// Optimize merged modules using various IPO passes 557 bool LTOCodeGenerator::optimize() { 558 if (!this->determineTarget()) 559 return false; 560 561 // libLTO parses options late, so re-set them here. 562 Context.setDiscardValueNames(LTODiscardValueNames); 563 564 auto DiagFileOrErr = lto::setupLLVMOptimizationRemarks( 565 Context, RemarksFilename, RemarksPasses, RemarksFormat, 566 RemarksWithHotness, RemarksHotnessThreshold); 567 if (!DiagFileOrErr) { 568 errs() << "Error: " << toString(DiagFileOrErr.takeError()) << "\n"; 569 report_fatal_error("Can't get an output file for the remarks"); 570 } 571 DiagnosticOutputFile = std::move(*DiagFileOrErr); 572 573 // Setup output file to emit statistics. 574 auto StatsFileOrErr = lto::setupStatsFile(LTOStatsFile); 575 if (!StatsFileOrErr) { 576 errs() << "Error: " << toString(StatsFileOrErr.takeError()) << "\n"; 577 report_fatal_error("Can't get an output file for the statistics"); 578 } 579 StatsFile = std::move(StatsFileOrErr.get()); 580 581 // Currently there is no support for enabling whole program visibility via a 582 // linker option in the old LTO API, but this call allows it to be specified 583 // via the internal option. Must be done before WPD invoked via the optimizer 584 // pipeline run below. 585 updatePublicTypeTestCalls(*MergedModule, 586 /* WholeProgramVisibilityEnabledInLTO */ false); 587 updateVCallVisibilityInModule( 588 *MergedModule, 589 /* WholeProgramVisibilityEnabledInLTO */ false, 590 // FIXME: These need linker information via a 591 // TBD new interface. 592 /*DynamicExportSymbols=*/{}, 593 /*ValidateAllVtablesHaveTypeInfos=*/false, 594 /*IsVisibleToRegularObj=*/[](StringRef) { return true; }); 595 596 // We always run the verifier once on the merged module, the `DisableVerify` 597 // parameter only applies to subsequent verify. 598 verifyMergedModuleOnce(); 599 600 // Mark which symbols can not be internalized 601 this->applyScopeRestrictions(); 602 603 // Add an appropriate DataLayout instance for this module... 604 MergedModule->setDataLayout(TargetMach->createDataLayout()); 605 606 if (!SaveIRBeforeOptPath.empty()) { 607 std::error_code EC; 608 raw_fd_ostream OS(SaveIRBeforeOptPath, EC, sys::fs::OF_None); 609 if (EC) 610 report_fatal_error(Twine("Failed to open ") + SaveIRBeforeOptPath + 611 " to save optimized bitcode\n"); 612 WriteBitcodeToFile(*MergedModule, OS, 613 /* ShouldPreserveUseListOrder */ true); 614 } 615 616 ModuleSummaryIndex CombinedIndex(false); 617 TargetMach = createTargetMachine(); 618 if (!opt(Config, TargetMach.get(), 0, *MergedModule, /*IsThinLTO=*/false, 619 /*ExportSummary=*/&CombinedIndex, /*ImportSummary=*/nullptr, 620 /*CmdArgs*/ std::vector<uint8_t>())) { 621 emitError("LTO middle-end optimizations failed"); 622 return false; 623 } 624 625 return true; 626 } 627 628 bool LTOCodeGenerator::compileOptimized(AddStreamFn AddStream, 629 unsigned ParallelismLevel) { 630 if (!this->determineTarget()) 631 return false; 632 633 // We always run the verifier once on the merged module. If it has already 634 // been called in optimize(), this call will return early. 635 verifyMergedModuleOnce(); 636 637 // Re-externalize globals that may have been internalized to increase scope 638 // for splitting 639 restoreLinkageForExternals(); 640 641 ModuleSummaryIndex CombinedIndex(false); 642 643 Config.CodeGenOnly = true; 644 Error Err = backend(Config, AddStream, ParallelismLevel, *MergedModule, 645 CombinedIndex); 646 assert(!Err && "unexpected code-generation failure"); 647 (void)Err; 648 649 // If statistics were requested, save them to the specified file or 650 // print them out after codegen. 651 if (StatsFile) 652 PrintStatisticsJSON(StatsFile->os()); 653 else if (AreStatisticsEnabled()) 654 PrintStatistics(); 655 656 reportAndResetTimings(); 657 658 finishOptimizationRemarks(); 659 660 return true; 661 } 662 663 void LTOCodeGenerator::setCodeGenDebugOptions(ArrayRef<StringRef> Options) { 664 for (StringRef Option : Options) 665 CodegenOptions.push_back(Option.str()); 666 } 667 668 void LTOCodeGenerator::parseCodeGenDebugOptions() { 669 if (!CodegenOptions.empty()) 670 llvm::parseCommandLineOptions(CodegenOptions); 671 } 672 673 void llvm::parseCommandLineOptions(std::vector<std::string> &Options) { 674 if (!Options.empty()) { 675 // ParseCommandLineOptions() expects argv[0] to be program name. 676 std::vector<const char *> CodegenArgv(1, "libLLVMLTO"); 677 for (std::string &Arg : Options) 678 CodegenArgv.push_back(Arg.c_str()); 679 cl::ParseCommandLineOptions(CodegenArgv.size(), CodegenArgv.data()); 680 } 681 } 682 683 void LTOCodeGenerator::DiagnosticHandler(const DiagnosticInfo &DI) { 684 // Map the LLVM internal diagnostic severity to the LTO diagnostic severity. 685 lto_codegen_diagnostic_severity_t Severity; 686 switch (DI.getSeverity()) { 687 case DS_Error: 688 Severity = LTO_DS_ERROR; 689 break; 690 case DS_Warning: 691 Severity = LTO_DS_WARNING; 692 break; 693 case DS_Remark: 694 Severity = LTO_DS_REMARK; 695 break; 696 case DS_Note: 697 Severity = LTO_DS_NOTE; 698 break; 699 } 700 // Create the string that will be reported to the external diagnostic handler. 701 std::string MsgStorage; 702 raw_string_ostream Stream(MsgStorage); 703 DiagnosticPrinterRawOStream DP(Stream); 704 DI.print(DP); 705 Stream.flush(); 706 707 // If this method has been called it means someone has set up an external 708 // diagnostic handler. Assert on that. 709 assert(DiagHandler && "Invalid diagnostic handler"); 710 (*DiagHandler)(Severity, MsgStorage.c_str(), DiagContext); 711 } 712 713 namespace { 714 struct LTODiagnosticHandler : public DiagnosticHandler { 715 LTOCodeGenerator *CodeGenerator; 716 LTODiagnosticHandler(LTOCodeGenerator *CodeGenPtr) 717 : CodeGenerator(CodeGenPtr) {} 718 bool handleDiagnostics(const DiagnosticInfo &DI) override { 719 CodeGenerator->DiagnosticHandler(DI); 720 return true; 721 } 722 }; 723 } 724 725 void 726 LTOCodeGenerator::setDiagnosticHandler(lto_diagnostic_handler_t DiagHandler, 727 void *Ctxt) { 728 this->DiagHandler = DiagHandler; 729 this->DiagContext = Ctxt; 730 if (!DiagHandler) 731 return Context.setDiagnosticHandler(nullptr); 732 // Register the LTOCodeGenerator stub in the LLVMContext to forward the 733 // diagnostic to the external DiagHandler. 734 Context.setDiagnosticHandler(std::make_unique<LTODiagnosticHandler>(this), 735 true); 736 } 737 738 namespace { 739 class LTODiagnosticInfo : public DiagnosticInfo { 740 const Twine &Msg; 741 public: 742 LTODiagnosticInfo(const Twine &DiagMsg LLVM_LIFETIME_BOUND, 743 DiagnosticSeverity Severity = DS_Error) 744 : DiagnosticInfo(DK_Linker, Severity), Msg(DiagMsg) {} 745 void print(DiagnosticPrinter &DP) const override { DP << Msg; } 746 }; 747 } 748 749 void LTOCodeGenerator::emitError(const std::string &ErrMsg) { 750 if (DiagHandler) 751 (*DiagHandler)(LTO_DS_ERROR, ErrMsg.c_str(), DiagContext); 752 else 753 Context.diagnose(LTODiagnosticInfo(ErrMsg)); 754 } 755 756 void LTOCodeGenerator::emitWarning(const std::string &ErrMsg) { 757 if (DiagHandler) 758 (*DiagHandler)(LTO_DS_WARNING, ErrMsg.c_str(), DiagContext); 759 else 760 Context.diagnose(LTODiagnosticInfo(ErrMsg, DS_Warning)); 761 } 762