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