xref: /llvm-project-15.0.7/llvm/lib/LTO/LTO.cpp (revision 11eed999)
1 //===-LTO.cpp - LLVM Link Time Optimizer ----------------------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements functions and classes used to support LTO.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "llvm/LTO/LTO.h"
15 #include "llvm/Analysis/TargetLibraryInfo.h"
16 #include "llvm/Analysis/TargetTransformInfo.h"
17 #include "llvm/Bitcode/ReaderWriter.h"
18 #include "llvm/CodeGen/Analysis.h"
19 #include "llvm/IR/AutoUpgrade.h"
20 #include "llvm/IR/DiagnosticPrinter.h"
21 #include "llvm/IR/LegacyPassManager.h"
22 #include "llvm/LTO/LTOBackend.h"
23 #include "llvm/Linker/IRMover.h"
24 #include "llvm/Object/ModuleSummaryIndexObjectFile.h"
25 #include "llvm/Support/ManagedStatic.h"
26 #include "llvm/Support/MemoryBuffer.h"
27 #include "llvm/Support/Path.h"
28 #include "llvm/Support/SourceMgr.h"
29 #include "llvm/Support/TargetRegistry.h"
30 #include "llvm/Support/ThreadPool.h"
31 #include "llvm/Support/raw_ostream.h"
32 #include "llvm/Target/TargetMachine.h"
33 #include "llvm/Target/TargetOptions.h"
34 #include "llvm/Transforms/IPO.h"
35 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
36 #include "llvm/Transforms/Utils/SplitModule.h"
37 
38 #include <set>
39 
40 using namespace llvm;
41 using namespace lto;
42 using namespace object;
43 
44 // Simple helper to load a module from bitcode
45 std::unique_ptr<Module>
46 llvm::loadModuleFromBuffer(const MemoryBufferRef &Buffer, LLVMContext &Context,
47                            bool Lazy) {
48   SMDiagnostic Err;
49   ErrorOr<std::unique_ptr<Module>> ModuleOrErr(nullptr);
50   if (Lazy) {
51     ModuleOrErr =
52         getLazyBitcodeModule(MemoryBuffer::getMemBuffer(Buffer, false), Context,
53                              /* ShouldLazyLoadMetadata */ Lazy);
54   } else {
55     ModuleOrErr = parseBitcodeFile(Buffer, Context);
56   }
57   if (std::error_code EC = ModuleOrErr.getError()) {
58     Err = SMDiagnostic(Buffer.getBufferIdentifier(), SourceMgr::DK_Error,
59                        EC.message());
60     Err.print("ThinLTO", errs());
61     report_fatal_error("Can't load module, abort.");
62   }
63   return std::move(ModuleOrErr.get());
64 }
65 
66 static void thinLTOResolveWeakForLinkerGUID(
67     GlobalValueSummaryList &GVSummaryList, GlobalValue::GUID GUID,
68     DenseSet<GlobalValueSummary *> &GlobalInvolvedWithAlias,
69     function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
70         isPrevailing,
71     function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)>
72         recordNewLinkage) {
73   for (auto &S : GVSummaryList) {
74     if (GlobalInvolvedWithAlias.count(S.get()))
75       continue;
76     GlobalValue::LinkageTypes OriginalLinkage = S->linkage();
77     if (!GlobalValue::isWeakForLinker(OriginalLinkage))
78       continue;
79     // We need to emit only one of these. The prevailing module will keep it,
80     // but turned into a weak, while the others will drop it when possible.
81     if (isPrevailing(GUID, S.get())) {
82       if (GlobalValue::isLinkOnceLinkage(OriginalLinkage))
83         S->setLinkage(GlobalValue::getWeakLinkage(
84             GlobalValue::isLinkOnceODRLinkage(OriginalLinkage)));
85     }
86     // Alias can't be turned into available_externally.
87     else if (!isa<AliasSummary>(S.get()) &&
88              (GlobalValue::isLinkOnceODRLinkage(OriginalLinkage) ||
89               GlobalValue::isWeakODRLinkage(OriginalLinkage)))
90       S->setLinkage(GlobalValue::AvailableExternallyLinkage);
91     if (S->linkage() != OriginalLinkage)
92       recordNewLinkage(S->modulePath(), GUID, S->linkage());
93   }
94 }
95 
96 // Resolve Weak and LinkOnce values in the \p Index.
97 //
98 // We'd like to drop these functions if they are no longer referenced in the
99 // current module. However there is a chance that another module is still
100 // referencing them because of the import. We make sure we always emit at least
101 // one copy.
102 void llvm::thinLTOResolveWeakForLinkerInIndex(
103     ModuleSummaryIndex &Index,
104     function_ref<bool(GlobalValue::GUID, const GlobalValueSummary *)>
105         isPrevailing,
106     function_ref<void(StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes)>
107         recordNewLinkage) {
108   // We won't optimize the globals that are referenced by an alias for now
109   // Ideally we should turn the alias into a global and duplicate the definition
110   // when needed.
111   DenseSet<GlobalValueSummary *> GlobalInvolvedWithAlias;
112   for (auto &I : Index)
113     for (auto &S : I.second)
114       if (auto AS = dyn_cast<AliasSummary>(S.get()))
115         GlobalInvolvedWithAlias.insert(&AS->getAliasee());
116 
117   for (auto &I : Index)
118     thinLTOResolveWeakForLinkerGUID(I.second, I.first, GlobalInvolvedWithAlias,
119                                     isPrevailing, recordNewLinkage);
120 }
121 
122 static void thinLTOInternalizeAndPromoteGUID(
123     GlobalValueSummaryList &GVSummaryList, GlobalValue::GUID GUID,
124     function_ref<bool(StringRef, GlobalValue::GUID)> isExported) {
125   for (auto &S : GVSummaryList) {
126     if (isExported(S->modulePath(), GUID)) {
127       if (GlobalValue::isLocalLinkage(S->linkage()))
128         S->setLinkage(GlobalValue::ExternalLinkage);
129     } else if (!GlobalValue::isLocalLinkage(S->linkage()))
130       S->setLinkage(GlobalValue::InternalLinkage);
131   }
132 }
133 
134 // Update the linkages in the given \p Index to mark exported values
135 // as external and non-exported values as internal.
136 void llvm::thinLTOInternalizeAndPromoteInIndex(
137     ModuleSummaryIndex &Index,
138     function_ref<bool(StringRef, GlobalValue::GUID)> isExported) {
139   for (auto &I : Index)
140     thinLTOInternalizeAndPromoteGUID(I.second, I.first, isExported);
141 }
142 
143 Expected<std::unique_ptr<InputFile>> InputFile::create(MemoryBufferRef Object) {
144   std::unique_ptr<InputFile> File(new InputFile);
145   std::string Msg;
146   auto DiagHandler = [](const DiagnosticInfo &DI, void *MsgP) {
147     auto *Msg = reinterpret_cast<std::string *>(MsgP);
148     raw_string_ostream OS(*Msg);
149     DiagnosticPrinterRawOStream DP(OS);
150     DI.print(DP);
151   };
152   File->Ctx.setDiagnosticHandler(DiagHandler, static_cast<void *>(&Msg));
153 
154   ErrorOr<std::unique_ptr<object::IRObjectFile>> IRObj =
155       IRObjectFile::create(Object, File->Ctx);
156   if (!Msg.empty())
157     return make_error<StringError>(Msg, inconvertibleErrorCode());
158   if (!IRObj)
159     return errorCodeToError(IRObj.getError());
160   File->Obj = std::move(*IRObj);
161 
162   File->Ctx.setDiagnosticHandler(nullptr, nullptr);
163 
164   return std::move(File);
165 }
166 
167 LTO::RegularLTOState::RegularLTOState(unsigned ParallelCodeGenParallelismLevel,
168                                       Config &Conf)
169     : ParallelCodeGenParallelismLevel(ParallelCodeGenParallelismLevel),
170       Ctx(Conf), CombinedModule(llvm::make_unique<Module>("ld-temp.o", Ctx)),
171       Mover(*CombinedModule) {}
172 
173 LTO::ThinLTOState::ThinLTOState(ThinBackend Backend) : Backend(Backend) {
174   if (!Backend)
175     this->Backend = createInProcessThinBackend(thread::hardware_concurrency());
176 }
177 
178 LTO::LTO(Config Conf, ThinBackend Backend,
179          unsigned ParallelCodeGenParallelismLevel)
180     : Conf(std::move(Conf)),
181       RegularLTO(ParallelCodeGenParallelismLevel, this->Conf),
182       ThinLTO(Backend) {}
183 
184 // Add the given symbol to the GlobalResolutions map, and resolve its partition.
185 void LTO::addSymbolToGlobalRes(IRObjectFile *Obj,
186                                SmallPtrSet<GlobalValue *, 8> &Used,
187                                const InputFile::Symbol &Sym,
188                                SymbolResolution Res, unsigned Partition) {
189   GlobalValue *GV = Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
190 
191   auto &GlobalRes = GlobalResolutions[Sym.getName()];
192   if (GV) {
193     GlobalRes.UnnamedAddr &= GV->hasGlobalUnnamedAddr();
194     if (Res.Prevailing)
195       GlobalRes.IRName = GV->getName();
196   }
197   if (Res.VisibleToRegularObj || (GV && Used.count(GV)) ||
198       (GlobalRes.Partition != GlobalResolution::Unknown &&
199        GlobalRes.Partition != Partition))
200     GlobalRes.Partition = GlobalResolution::External;
201   else
202     GlobalRes.Partition = Partition;
203 }
204 
205 void LTO::writeToResolutionFile(InputFile *Input,
206                                 ArrayRef<SymbolResolution> Res) {
207   StringRef Path = Input->Obj->getMemoryBufferRef().getBufferIdentifier();
208   *Conf.ResolutionFile << Path << '\n';
209   auto ResI = Res.begin();
210   for (const InputFile::Symbol &Sym : Input->symbols()) {
211     assert(ResI != Res.end());
212     SymbolResolution Res = *ResI++;
213 
214     *Conf.ResolutionFile << "-r=" << Path << ',' << Sym.getName() << ',';
215     if (Res.Prevailing)
216       *Conf.ResolutionFile << 'p';
217     if (Res.FinalDefinitionInLinkageUnit)
218       *Conf.ResolutionFile << 'l';
219     if (Res.VisibleToRegularObj)
220       *Conf.ResolutionFile << 'x';
221     *Conf.ResolutionFile << '\n';
222   }
223   assert(ResI == Res.end());
224 }
225 
226 Error LTO::add(std::unique_ptr<InputFile> Input,
227                ArrayRef<SymbolResolution> Res) {
228   assert(!CalledGetMaxTasks);
229 
230   if (Conf.ResolutionFile)
231     writeToResolutionFile(Input.get(), Res);
232 
233   Module &M = Input->Obj->getModule();
234   SmallPtrSet<GlobalValue *, 8> Used;
235   collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
236 
237   if (!Conf.OverrideTriple.empty())
238     M.setTargetTriple(Conf.OverrideTriple);
239   else if (M.getTargetTriple().empty())
240     M.setTargetTriple(Conf.DefaultTriple);
241 
242   MemoryBufferRef MBRef = Input->Obj->getMemoryBufferRef();
243   bool HasThinLTOSummary = hasGlobalValueSummary(MBRef, Conf.DiagHandler);
244 
245   if (HasThinLTOSummary)
246     return addThinLTO(std::move(Input), Res);
247   else
248     return addRegularLTO(std::move(Input), Res);
249 }
250 
251 // Add a regular LTO object to the link.
252 Error LTO::addRegularLTO(std::unique_ptr<InputFile> Input,
253                          ArrayRef<SymbolResolution> Res) {
254   RegularLTO.HasModule = true;
255 
256   ErrorOr<std::unique_ptr<object::IRObjectFile>> ObjOrErr =
257       IRObjectFile::create(Input->Obj->getMemoryBufferRef(), RegularLTO.Ctx);
258   if (!ObjOrErr)
259     return errorCodeToError(ObjOrErr.getError());
260   std::unique_ptr<object::IRObjectFile> Obj = std::move(*ObjOrErr);
261 
262   Module &M = Obj->getModule();
263   M.materializeMetadata();
264   UpgradeDebugInfo(M);
265 
266   SmallPtrSet<GlobalValue *, 8> Used;
267   collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
268 
269   std::vector<GlobalValue *> Keep;
270 
271   for (GlobalVariable &GV : M.globals())
272     if (GV.hasAppendingLinkage())
273       Keep.push_back(&GV);
274 
275   auto ResI = Res.begin();
276   for (const InputFile::Symbol &Sym :
277        make_range(InputFile::symbol_iterator(Obj->symbol_begin()),
278                   InputFile::symbol_iterator(Obj->symbol_end()))) {
279     assert(ResI != Res.end());
280     SymbolResolution Res = *ResI++;
281     addSymbolToGlobalRes(Obj.get(), Used, Sym, Res, 0);
282 
283     GlobalValue *GV = Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
284     if (Res.Prevailing && GV) {
285       Keep.push_back(GV);
286       switch (GV->getLinkage()) {
287       default:
288         break;
289       case GlobalValue::LinkOnceAnyLinkage:
290         GV->setLinkage(GlobalValue::WeakAnyLinkage);
291         break;
292       case GlobalValue::LinkOnceODRLinkage:
293         GV->setLinkage(GlobalValue::WeakODRLinkage);
294         break;
295       }
296     }
297 
298     // FIXME: use proposed local attribute for FinalDefinitionInLinkageUnit.
299   }
300   assert(ResI == Res.end());
301 
302   return RegularLTO.Mover.move(Obj->takeModule(), Keep,
303                                [](GlobalValue &, IRMover::ValueAdder) {});
304 }
305 
306 // Add a ThinLTO object to the link.
307 Error LTO::addThinLTO(std::unique_ptr<InputFile> Input,
308                       ArrayRef<SymbolResolution> Res) {
309   Module &M = Input->Obj->getModule();
310   SmallPtrSet<GlobalValue *, 8> Used;
311   collectUsedGlobalVariables(M, Used, /*CompilerUsed*/ false);
312 
313   // We need to initialize the target info for the combined regular LTO module
314   // in case we have no regular LTO objects. In that case we still need to build
315   // it as usual because the client may want to add symbol definitions to it.
316   if (RegularLTO.CombinedModule->getTargetTriple().empty()) {
317     RegularLTO.CombinedModule->setTargetTriple(M.getTargetTriple());
318     RegularLTO.CombinedModule->setDataLayout(M.getDataLayout());
319   }
320 
321   MemoryBufferRef MBRef = Input->Obj->getMemoryBufferRef();
322   ErrorOr<std::unique_ptr<object::ModuleSummaryIndexObjectFile>>
323       SummaryObjOrErr =
324           object::ModuleSummaryIndexObjectFile::create(MBRef, Conf.DiagHandler);
325   if (!SummaryObjOrErr)
326     return errorCodeToError(SummaryObjOrErr.getError());
327   ThinLTO.CombinedIndex.mergeFrom((*SummaryObjOrErr)->takeIndex(),
328                                   ThinLTO.ModuleMap.size());
329 
330   auto ResI = Res.begin();
331   for (const InputFile::Symbol &Sym : Input->symbols()) {
332     assert(ResI != Res.end());
333     SymbolResolution Res = *ResI++;
334     addSymbolToGlobalRes(Input->Obj.get(), Used, Sym, Res,
335                          ThinLTO.ModuleMap.size() + 1);
336 
337     GlobalValue *GV = Input->Obj->getSymbolGV(Sym.I->getRawDataRefImpl());
338     if (Res.Prevailing && GV)
339       ThinLTO.PrevailingModuleForGUID[GV->getGUID()] =
340           MBRef.getBufferIdentifier();
341   }
342   assert(ResI == Res.end());
343 
344   ThinLTO.ModuleMap[MBRef.getBufferIdentifier()] = MBRef;
345   return Error();
346 }
347 
348 unsigned LTO::getMaxTasks() const {
349   CalledGetMaxTasks = true;
350   return RegularLTO.ParallelCodeGenParallelismLevel + ThinLTO.ModuleMap.size();
351 }
352 
353 Error LTO::run(AddOutputFn AddOutput) {
354   // Invoke regular LTO if there was a regular LTO module to start with,
355   // or if there are any hooks that the linker may have used to add
356   // its own resolved symbols to the combined module.
357   if (RegularLTO.HasModule || Conf.PreOptModuleHook ||
358       Conf.PostInternalizeModuleHook || Conf.PostOptModuleHook ||
359       Conf.PreCodeGenModuleHook)
360     if (auto E = runRegularLTO(AddOutput))
361       return E;
362   return runThinLTO(AddOutput);
363 }
364 
365 Error LTO::runRegularLTO(AddOutputFn AddOutput) {
366   if (Conf.PreOptModuleHook &&
367       !Conf.PreOptModuleHook(0, *RegularLTO.CombinedModule))
368     return Error();
369 
370   for (const auto &R : GlobalResolutions) {
371     if (R.second.IRName.empty())
372       continue;
373     if (R.second.Partition != 0 &&
374         R.second.Partition != GlobalResolution::External)
375       continue;
376 
377     GlobalValue *GV = RegularLTO.CombinedModule->getNamedValue(R.second.IRName);
378     // Ignore symbols defined in other partitions.
379     if (!GV || GV->hasLocalLinkage())
380       continue;
381     GV->setUnnamedAddr(R.second.UnnamedAddr ? GlobalValue::UnnamedAddr::Global
382                                             : GlobalValue::UnnamedAddr::None);
383     if (R.second.Partition == 0)
384       GV->setLinkage(GlobalValue::InternalLinkage);
385   }
386 
387   if (Conf.PostInternalizeModuleHook &&
388       !Conf.PostInternalizeModuleHook(0, *RegularLTO.CombinedModule))
389     return Error();
390 
391   return backend(Conf, AddOutput, RegularLTO.ParallelCodeGenParallelismLevel,
392                  std::move(RegularLTO.CombinedModule));
393 }
394 
395 /// This class defines the interface to the ThinLTO backend.
396 class lto::ThinBackendProc {
397 protected:
398   Config &Conf;
399   ModuleSummaryIndex &CombinedIndex;
400   AddOutputFn AddOutput;
401   StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries;
402 
403 public:
404   ThinBackendProc(Config &Conf, ModuleSummaryIndex &CombinedIndex,
405                   AddOutputFn AddOutput,
406                   StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries)
407       : Conf(Conf), CombinedIndex(CombinedIndex), AddOutput(AddOutput),
408         ModuleToDefinedGVSummaries(ModuleToDefinedGVSummaries) {}
409 
410   virtual ~ThinBackendProc() {}
411   virtual Error start(unsigned Task, MemoryBufferRef MBRef,
412                       const FunctionImporter::ImportMapTy &ImportList,
413                       MapVector<StringRef, MemoryBufferRef> &ModuleMap) = 0;
414   virtual Error wait() = 0;
415 };
416 
417 class InProcessThinBackend : public ThinBackendProc {
418   ThreadPool BackendThreadPool;
419 
420   Optional<Error> Err;
421   std::mutex ErrMu;
422 
423 public:
424   InProcessThinBackend(Config &Conf, ModuleSummaryIndex &CombinedIndex,
425                        unsigned ThinLTOParallelismLevel,
426                        StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
427                        AddOutputFn AddOutput)
428       : ThinBackendProc(Conf, CombinedIndex, AddOutput,
429                         ModuleToDefinedGVSummaries),
430         BackendThreadPool(ThinLTOParallelismLevel) {}
431 
432   Error
433   runThinLTOBackendThread(AddOutputFn AddOutput, unsigned Task,
434                           MemoryBufferRef MBRef,
435                           ModuleSummaryIndex &CombinedIndex,
436                           const FunctionImporter::ImportMapTy &ImportList,
437                           const GVSummaryMapTy &DefinedGlobals,
438                           MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
439     LLVMContext BackendContext;
440 
441     ErrorOr<std::unique_ptr<Module>> MOrErr =
442         parseBitcodeFile(MBRef, BackendContext);
443     assert(MOrErr && "Unable to load module in thread?");
444 
445     return thinBackend(Conf, Task, AddOutput, **MOrErr, CombinedIndex,
446                        ImportList, DefinedGlobals, ModuleMap);
447   }
448 
449   Error start(unsigned Task, MemoryBufferRef MBRef,
450               const FunctionImporter::ImportMapTy &ImportList,
451               MapVector<StringRef, MemoryBufferRef> &ModuleMap) override {
452     StringRef ModulePath = MBRef.getBufferIdentifier();
453     BackendThreadPool.async(
454         [=](MemoryBufferRef MBRef, ModuleSummaryIndex &CombinedIndex,
455             const FunctionImporter::ImportMapTy &ImportList,
456             GVSummaryMapTy &DefinedGlobals,
457             MapVector<StringRef, MemoryBufferRef> &ModuleMap) {
458           Error E =
459               runThinLTOBackendThread(AddOutput, Task, MBRef, CombinedIndex,
460                                       ImportList, DefinedGlobals, ModuleMap);
461           if (E) {
462             std::unique_lock<std::mutex> L(ErrMu);
463             if (Err)
464               Err = joinErrors(std::move(*Err), std::move(E));
465             else
466               Err = std::move(E);
467           }
468         },
469         MBRef, std::ref(CombinedIndex), std::ref(ImportList),
470         std::ref(ModuleToDefinedGVSummaries[ModulePath]), std::ref(ModuleMap));
471     return Error();
472   }
473 
474   Error wait() override {
475     BackendThreadPool.wait();
476     if (Err)
477       return std::move(*Err);
478     else
479       return Error();
480   }
481 };
482 
483 ThinBackend lto::createInProcessThinBackend(unsigned ParallelismLevel) {
484   return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex,
485              StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
486              AddOutputFn AddOutput) {
487     return llvm::make_unique<InProcessThinBackend>(
488         Conf, CombinedIndex, ParallelismLevel, ModuleToDefinedGVSummaries,
489         AddOutput);
490   };
491 }
492 
493 class WriteIndexesThinBackend : public ThinBackendProc {
494   std::string OldPrefix, NewPrefix;
495   bool ShouldEmitImportsFiles;
496 
497   std::string LinkedObjectsFileName;
498   std::unique_ptr<llvm::raw_fd_ostream> LinkedObjectsFile;
499 
500 public:
501   WriteIndexesThinBackend(Config &Conf, ModuleSummaryIndex &CombinedIndex,
502                           StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
503                           AddOutputFn AddOutput, std::string OldPrefix,
504                           std::string NewPrefix, bool ShouldEmitImportsFiles,
505                           std::string LinkedObjectsFileName)
506       : ThinBackendProc(Conf, CombinedIndex, AddOutput,
507                         ModuleToDefinedGVSummaries),
508         OldPrefix(OldPrefix), NewPrefix(NewPrefix),
509         ShouldEmitImportsFiles(ShouldEmitImportsFiles),
510         LinkedObjectsFileName(LinkedObjectsFileName) {}
511 
512   /// Given the original \p Path to an output file, replace any path
513   /// prefix matching \p OldPrefix with \p NewPrefix. Also, create the
514   /// resulting directory if it does not yet exist.
515   std::string getThinLTOOutputFile(const std::string &Path,
516                                    const std::string &OldPrefix,
517                                    const std::string &NewPrefix) {
518     if (OldPrefix.empty() && NewPrefix.empty())
519       return Path;
520     SmallString<128> NewPath(Path);
521     llvm::sys::path::replace_path_prefix(NewPath, OldPrefix, NewPrefix);
522     StringRef ParentPath = llvm::sys::path::parent_path(NewPath.str());
523     if (!ParentPath.empty()) {
524       // Make sure the new directory exists, creating it if necessary.
525       if (std::error_code EC = llvm::sys::fs::create_directories(ParentPath))
526         llvm::errs() << "warning: could not create directory '" << ParentPath
527                      << "': " << EC.message() << '\n';
528     }
529     return NewPath.str();
530   }
531 
532   Error start(unsigned Task, MemoryBufferRef MBRef,
533               const FunctionImporter::ImportMapTy &ImportList,
534               MapVector<StringRef, MemoryBufferRef> &ModuleMap) override {
535     StringRef ModulePath = MBRef.getBufferIdentifier();
536     std::string NewModulePath =
537         getThinLTOOutputFile(ModulePath, OldPrefix, NewPrefix);
538 
539     std::error_code EC;
540     if (!LinkedObjectsFileName.empty()) {
541       if (!LinkedObjectsFile) {
542         LinkedObjectsFile = llvm::make_unique<raw_fd_ostream>(
543             LinkedObjectsFileName, EC, sys::fs::OpenFlags::F_None);
544         if (EC)
545           return errorCodeToError(EC);
546       }
547       *LinkedObjectsFile << NewModulePath << '\n';
548     }
549 
550     std::map<std::string, GVSummaryMapTy> ModuleToSummariesForIndex;
551     gatherImportedSummariesForModule(ModulePath, ModuleToDefinedGVSummaries,
552                                      ImportList, ModuleToSummariesForIndex);
553 
554     raw_fd_ostream OS(NewModulePath + ".thinlto.bc", EC,
555                       sys::fs::OpenFlags::F_None);
556     if (EC)
557       return errorCodeToError(EC);
558     WriteIndexToFile(CombinedIndex, OS, &ModuleToSummariesForIndex);
559 
560     if (ShouldEmitImportsFiles)
561       return errorCodeToError(
562           EmitImportsFiles(ModulePath, NewModulePath + ".imports", ImportList));
563     return Error();
564   }
565 
566   Error wait() override { return Error(); }
567 };
568 
569 ThinBackend lto::createWriteIndexesThinBackend(std::string OldPrefix,
570                                                std::string NewPrefix,
571                                                bool ShouldEmitImportsFiles,
572                                                std::string LinkedObjectsFile) {
573   return [=](Config &Conf, ModuleSummaryIndex &CombinedIndex,
574              StringMap<GVSummaryMapTy> &ModuleToDefinedGVSummaries,
575              AddOutputFn AddOutput) {
576     return llvm::make_unique<WriteIndexesThinBackend>(
577         Conf, CombinedIndex, ModuleToDefinedGVSummaries, AddOutput, OldPrefix,
578         NewPrefix, ShouldEmitImportsFiles, LinkedObjectsFile);
579   };
580 }
581 
582 Error LTO::runThinLTO(AddOutputFn AddOutput) {
583   if (ThinLTO.ModuleMap.empty())
584     return Error();
585 
586   if (Conf.CombinedIndexHook && !Conf.CombinedIndexHook(ThinLTO.CombinedIndex))
587     return Error();
588 
589   // Collect for each module the list of function it defines (GUID ->
590   // Summary).
591   StringMap<std::map<GlobalValue::GUID, GlobalValueSummary *>>
592       ModuleToDefinedGVSummaries(ThinLTO.ModuleMap.size());
593   ThinLTO.CombinedIndex.collectDefinedGVSummariesPerModule(
594       ModuleToDefinedGVSummaries);
595 
596   StringMap<FunctionImporter::ImportMapTy> ImportLists(
597       ThinLTO.ModuleMap.size());
598   StringMap<FunctionImporter::ExportSetTy> ExportLists(
599       ThinLTO.ModuleMap.size());
600   ComputeCrossModuleImport(ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries,
601                            ImportLists, ExportLists);
602 
603   std::set<GlobalValue::GUID> ExportedGUIDs;
604   for (auto &Res : GlobalResolutions) {
605     if (!Res.second.IRName.empty() &&
606         Res.second.Partition == GlobalResolution::External)
607       ExportedGUIDs.insert(GlobalValue::getGUID(Res.second.IRName));
608   }
609 
610   auto isPrevailing = [&](GlobalValue::GUID GUID, const GlobalValueSummary *S) {
611     return ThinLTO.PrevailingModuleForGUID[GUID] == S->modulePath();
612   };
613   auto isExported = [&](StringRef ModuleIdentifier, GlobalValue::GUID GUID) {
614     const auto &ExportList = ExportLists.find(ModuleIdentifier);
615     return (ExportList != ExportLists.end() &&
616             ExportList->second.count(GUID)) ||
617            ExportedGUIDs.count(GUID);
618   };
619   thinLTOInternalizeAndPromoteInIndex(ThinLTO.CombinedIndex, isExported);
620   thinLTOResolveWeakForLinkerInIndex(
621       ThinLTO.CombinedIndex, isPrevailing,
622       [](StringRef, GlobalValue::GUID, GlobalValue::LinkageTypes) {});
623 
624   std::unique_ptr<ThinBackendProc> BackendProc = ThinLTO.Backend(
625       Conf, ThinLTO.CombinedIndex, ModuleToDefinedGVSummaries, AddOutput);
626 
627   // Partition numbers for ThinLTO jobs start at 1 (see comments for
628   // GlobalResolution in LTO.h). Task numbers, however, start at
629   // ParallelCodeGenParallelismLevel, as tasks 0 through
630   // ParallelCodeGenParallelismLevel-1 are reserved for parallel code generation
631   // partitions.
632   unsigned Task = RegularLTO.ParallelCodeGenParallelismLevel;
633   unsigned Partition = 1;
634 
635   for (auto &Mod : ThinLTO.ModuleMap) {
636     if (Error E = BackendProc->start(Task, Mod.second, ImportLists[Mod.first],
637                                      ThinLTO.ModuleMap))
638       return E;
639 
640     ++Task;
641     ++Partition;
642   }
643 
644   return BackendProc->wait();
645 }
646