xref: /freebsd-src/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerImpl.cpp (revision 7a6dacaca14b62ca4b74406814becb87a3fefac0)
11db9f3b2SDimitry Andric //=== DWARFLinkerImpl.cpp -------------------------------------------------===//
21db9f3b2SDimitry Andric //
31db9f3b2SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
41db9f3b2SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
51db9f3b2SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
61db9f3b2SDimitry Andric //
71db9f3b2SDimitry Andric //===----------------------------------------------------------------------===//
81db9f3b2SDimitry Andric 
91db9f3b2SDimitry Andric #include "DWARFLinkerImpl.h"
101db9f3b2SDimitry Andric #include "DIEGenerator.h"
111db9f3b2SDimitry Andric #include "DependencyTracker.h"
12297eecfbSDimitry Andric #include "llvm/DWARFLinker/Utils.h"
131db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
141db9f3b2SDimitry Andric #include "llvm/Support/FormatVariadic.h"
151db9f3b2SDimitry Andric #include "llvm/Support/Parallel.h"
161db9f3b2SDimitry Andric #include "llvm/Support/ThreadPool.h"
171db9f3b2SDimitry Andric 
181db9f3b2SDimitry Andric using namespace llvm;
191db9f3b2SDimitry Andric using namespace dwarf_linker;
201db9f3b2SDimitry Andric using namespace dwarf_linker::parallel;
211db9f3b2SDimitry Andric 
221db9f3b2SDimitry Andric DWARFLinkerImpl::DWARFLinkerImpl(MessageHandlerTy ErrorHandler,
231db9f3b2SDimitry Andric                                  MessageHandlerTy WarningHandler,
241db9f3b2SDimitry Andric                                  TranslatorFuncTy StringsTranslator)
251db9f3b2SDimitry Andric     : UniqueUnitID(0), DebugStrStrings(GlobalData),
261db9f3b2SDimitry Andric       DebugLineStrStrings(GlobalData), CommonSections(GlobalData) {
271db9f3b2SDimitry Andric   GlobalData.setTranslator(StringsTranslator);
281db9f3b2SDimitry Andric   GlobalData.setErrorHandler(ErrorHandler);
291db9f3b2SDimitry Andric   GlobalData.setWarningHandler(WarningHandler);
301db9f3b2SDimitry Andric }
311db9f3b2SDimitry Andric 
321db9f3b2SDimitry Andric DWARFLinkerImpl::LinkContext::LinkContext(LinkingGlobalData &GlobalData,
331db9f3b2SDimitry Andric                                           DWARFFile &File,
341db9f3b2SDimitry Andric                                           StringMap<uint64_t> &ClangModules,
35*7a6dacacSDimitry Andric                                           std::atomic<size_t> &UniqueUnitID)
361db9f3b2SDimitry Andric     : OutputSections(GlobalData), InputDWARFFile(File),
37*7a6dacacSDimitry Andric       ClangModules(ClangModules), UniqueUnitID(UniqueUnitID) {
381db9f3b2SDimitry Andric 
391db9f3b2SDimitry Andric   if (File.Dwarf) {
401db9f3b2SDimitry Andric     if (!File.Dwarf->compile_units().empty())
411db9f3b2SDimitry Andric       CompileUnits.reserve(File.Dwarf->getNumCompileUnits());
421db9f3b2SDimitry Andric 
431db9f3b2SDimitry Andric     // Set context format&endianness based on the input file.
441db9f3b2SDimitry Andric     Format.Version = File.Dwarf->getMaxVersion();
451db9f3b2SDimitry Andric     Format.AddrSize = File.Dwarf->getCUAddrSize();
461db9f3b2SDimitry Andric     Endianness = File.Dwarf->isLittleEndian() ? llvm::endianness::little
471db9f3b2SDimitry Andric                                               : llvm::endianness::big;
481db9f3b2SDimitry Andric   }
491db9f3b2SDimitry Andric }
501db9f3b2SDimitry Andric 
511db9f3b2SDimitry Andric DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit(
521db9f3b2SDimitry Andric     DWARFFile &File, std::unique_ptr<CompileUnit> Unit)
531db9f3b2SDimitry Andric     : File(File), Unit(std::move(Unit)) {}
541db9f3b2SDimitry Andric 
551db9f3b2SDimitry Andric DWARFLinkerImpl::LinkContext::RefModuleUnit::RefModuleUnit(
561db9f3b2SDimitry Andric     LinkContext::RefModuleUnit &&Other)
571db9f3b2SDimitry Andric     : File(Other.File), Unit(std::move(Other.Unit)) {}
581db9f3b2SDimitry Andric 
591db9f3b2SDimitry Andric void DWARFLinkerImpl::LinkContext::addModulesCompileUnit(
601db9f3b2SDimitry Andric     LinkContext::RefModuleUnit &&Unit) {
611db9f3b2SDimitry Andric   ModulesCompileUnits.emplace_back(std::move(Unit));
621db9f3b2SDimitry Andric }
631db9f3b2SDimitry Andric 
641db9f3b2SDimitry Andric void DWARFLinkerImpl::addObjectFile(DWARFFile &File, ObjFileLoaderTy Loader,
651db9f3b2SDimitry Andric                                     CompileUnitHandlerTy OnCUDieLoaded) {
661db9f3b2SDimitry Andric   ObjectContexts.emplace_back(std::make_unique<LinkContext>(
67*7a6dacacSDimitry Andric       GlobalData, File, ClangModules, UniqueUnitID));
681db9f3b2SDimitry Andric 
691db9f3b2SDimitry Andric   if (ObjectContexts.back()->InputDWARFFile.Dwarf) {
701db9f3b2SDimitry Andric     for (const std::unique_ptr<DWARFUnit> &CU :
711db9f3b2SDimitry Andric          ObjectContexts.back()->InputDWARFFile.Dwarf->compile_units()) {
721db9f3b2SDimitry Andric       DWARFDie CUDie = CU->getUnitDIE();
731db9f3b2SDimitry Andric       OverallNumberOfCU++;
741db9f3b2SDimitry Andric 
751db9f3b2SDimitry Andric       if (!CUDie)
761db9f3b2SDimitry Andric         continue;
771db9f3b2SDimitry Andric 
781db9f3b2SDimitry Andric       OnCUDieLoaded(*CU);
791db9f3b2SDimitry Andric 
801db9f3b2SDimitry Andric       // Register mofule reference.
811db9f3b2SDimitry Andric       if (!GlobalData.getOptions().UpdateIndexTablesOnly)
821db9f3b2SDimitry Andric         ObjectContexts.back()->registerModuleReference(CUDie, Loader,
831db9f3b2SDimitry Andric                                                        OnCUDieLoaded);
841db9f3b2SDimitry Andric     }
851db9f3b2SDimitry Andric   }
861db9f3b2SDimitry Andric }
871db9f3b2SDimitry Andric 
881db9f3b2SDimitry Andric void DWARFLinkerImpl::setEstimatedObjfilesAmount(unsigned ObjFilesNum) {
891db9f3b2SDimitry Andric   ObjectContexts.reserve(ObjFilesNum);
901db9f3b2SDimitry Andric }
911db9f3b2SDimitry Andric 
921db9f3b2SDimitry Andric Error DWARFLinkerImpl::link() {
931db9f3b2SDimitry Andric   // reset compile unit unique ID counter.
941db9f3b2SDimitry Andric   UniqueUnitID = 0;
951db9f3b2SDimitry Andric 
961db9f3b2SDimitry Andric   if (Error Err = validateAndUpdateOptions())
971db9f3b2SDimitry Andric     return Err;
981db9f3b2SDimitry Andric 
991db9f3b2SDimitry Andric   dwarf::FormParams GlobalFormat = {GlobalData.getOptions().TargetDWARFVersion,
1001db9f3b2SDimitry Andric                                     0, dwarf::DwarfFormat::DWARF32};
1011db9f3b2SDimitry Andric   llvm::endianness GlobalEndianness = llvm::endianness::native;
1021db9f3b2SDimitry Andric 
103*7a6dacacSDimitry Andric   if (std::optional<std::reference_wrapper<const Triple>> CurTriple =
104*7a6dacacSDimitry Andric           GlobalData.getTargetTriple()) {
105*7a6dacacSDimitry Andric     GlobalEndianness = (*CurTriple).get().isLittleEndian()
1061db9f3b2SDimitry Andric                            ? llvm::endianness::little
1071db9f3b2SDimitry Andric                            : llvm::endianness::big;
1081db9f3b2SDimitry Andric   }
1091db9f3b2SDimitry Andric   std::optional<uint16_t> Language;
1101db9f3b2SDimitry Andric 
1111db9f3b2SDimitry Andric   for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
1121db9f3b2SDimitry Andric     if (Context->InputDWARFFile.Dwarf.get() == nullptr) {
1131db9f3b2SDimitry Andric       Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
1141db9f3b2SDimitry Andric       continue;
1151db9f3b2SDimitry Andric     }
1161db9f3b2SDimitry Andric 
1171db9f3b2SDimitry Andric     if (GlobalData.getOptions().Verbose) {
118*7a6dacacSDimitry Andric       outs() << "DEBUG MAP OBJECT: " << Context->InputDWARFFile.FileName
119*7a6dacacSDimitry Andric              << "\n";
1201db9f3b2SDimitry Andric 
1211db9f3b2SDimitry Andric       for (const std::unique_ptr<DWARFUnit> &OrigCU :
1221db9f3b2SDimitry Andric            Context->InputDWARFFile.Dwarf->compile_units()) {
1231db9f3b2SDimitry Andric         outs() << "Input compilation unit:";
1241db9f3b2SDimitry Andric         DIDumpOptions DumpOpts;
1251db9f3b2SDimitry Andric         DumpOpts.ChildRecurseDepth = 0;
1261db9f3b2SDimitry Andric         DumpOpts.Verbose = GlobalData.getOptions().Verbose;
1271db9f3b2SDimitry Andric         OrigCU->getUnitDIE().dump(outs(), 0, DumpOpts);
1281db9f3b2SDimitry Andric       }
1291db9f3b2SDimitry Andric     }
1301db9f3b2SDimitry Andric 
1311db9f3b2SDimitry Andric     // Verify input DWARF if requested.
1321db9f3b2SDimitry Andric     if (GlobalData.getOptions().VerifyInputDWARF)
1331db9f3b2SDimitry Andric       verifyInput(Context->InputDWARFFile);
1341db9f3b2SDimitry Andric 
135*7a6dacacSDimitry Andric     if (!GlobalData.getTargetTriple())
1361db9f3b2SDimitry Andric       GlobalEndianness = Context->getEndianness();
1371db9f3b2SDimitry Andric     GlobalFormat.AddrSize =
1381db9f3b2SDimitry Andric         std::max(GlobalFormat.AddrSize, Context->getFormParams().AddrSize);
1391db9f3b2SDimitry Andric 
1401db9f3b2SDimitry Andric     Context->setOutputFormat(Context->getFormParams(), GlobalEndianness);
1411db9f3b2SDimitry Andric 
1421db9f3b2SDimitry Andric     // FIXME: move creation of CompileUnits into the addObjectFile.
1431db9f3b2SDimitry Andric     // This would allow to not scan for context Language and Modules state
1441db9f3b2SDimitry Andric     // twice. And then following handling might be removed.
1451db9f3b2SDimitry Andric     for (const std::unique_ptr<DWARFUnit> &OrigCU :
1461db9f3b2SDimitry Andric          Context->InputDWARFFile.Dwarf->compile_units()) {
1471db9f3b2SDimitry Andric       DWARFDie UnitDie = OrigCU.get()->getUnitDIE();
1481db9f3b2SDimitry Andric 
1491db9f3b2SDimitry Andric       if (!Language) {
1501db9f3b2SDimitry Andric         if (std::optional<DWARFFormValue> Val =
1511db9f3b2SDimitry Andric                 UnitDie.find(dwarf::DW_AT_language)) {
1521db9f3b2SDimitry Andric           uint16_t LangVal = dwarf::toUnsigned(Val, 0);
1531db9f3b2SDimitry Andric           if (isODRLanguage(LangVal))
1541db9f3b2SDimitry Andric             Language = LangVal;
1551db9f3b2SDimitry Andric         }
1561db9f3b2SDimitry Andric       }
1571db9f3b2SDimitry Andric     }
1581db9f3b2SDimitry Andric   }
1591db9f3b2SDimitry Andric 
1601db9f3b2SDimitry Andric   if (GlobalFormat.AddrSize == 0) {
161*7a6dacacSDimitry Andric     if (std::optional<std::reference_wrapper<const Triple>> TargetTriple =
162*7a6dacacSDimitry Andric             GlobalData.getTargetTriple())
163*7a6dacacSDimitry Andric       GlobalFormat.AddrSize = (*TargetTriple).get().isArch32Bit() ? 4 : 8;
1641db9f3b2SDimitry Andric     else
1651db9f3b2SDimitry Andric       GlobalFormat.AddrSize = 8;
1661db9f3b2SDimitry Andric   }
1671db9f3b2SDimitry Andric 
1681db9f3b2SDimitry Andric   CommonSections.setOutputFormat(GlobalFormat, GlobalEndianness);
1691db9f3b2SDimitry Andric 
1701db9f3b2SDimitry Andric   if (!GlobalData.Options.NoODR && Language.has_value()) {
1711db9f3b2SDimitry Andric     llvm::parallel::TaskGroup TGroup;
1721db9f3b2SDimitry Andric     TGroup.spawn([&]() {
1731db9f3b2SDimitry Andric       ArtificialTypeUnit = std::make_unique<TypeUnit>(
1741db9f3b2SDimitry Andric           GlobalData, UniqueUnitID++, Language, GlobalFormat, GlobalEndianness);
1751db9f3b2SDimitry Andric     });
1761db9f3b2SDimitry Andric   }
1771db9f3b2SDimitry Andric 
1781db9f3b2SDimitry Andric   // Set parallel options.
1791db9f3b2SDimitry Andric   if (GlobalData.getOptions().Threads == 0)
1801db9f3b2SDimitry Andric     llvm::parallel::strategy = optimal_concurrency(OverallNumberOfCU);
1811db9f3b2SDimitry Andric   else
1821db9f3b2SDimitry Andric     llvm::parallel::strategy =
1831db9f3b2SDimitry Andric         hardware_concurrency(GlobalData.getOptions().Threads);
1841db9f3b2SDimitry Andric 
1851db9f3b2SDimitry Andric   // Link object files.
1861db9f3b2SDimitry Andric   if (GlobalData.getOptions().Threads == 1) {
1871db9f3b2SDimitry Andric     for (std::unique_ptr<LinkContext> &Context : ObjectContexts) {
1881db9f3b2SDimitry Andric       // Link object file.
1891db9f3b2SDimitry Andric       if (Error Err = Context->link(ArtificialTypeUnit.get()))
1901db9f3b2SDimitry Andric         GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
1911db9f3b2SDimitry Andric 
1921db9f3b2SDimitry Andric       Context->InputDWARFFile.unload();
1931db9f3b2SDimitry Andric     }
1941db9f3b2SDimitry Andric   } else {
1951db9f3b2SDimitry Andric     ThreadPool Pool(llvm::parallel::strategy);
1961db9f3b2SDimitry Andric     for (std::unique_ptr<LinkContext> &Context : ObjectContexts)
1971db9f3b2SDimitry Andric       Pool.async([&]() {
1981db9f3b2SDimitry Andric         // Link object file.
1991db9f3b2SDimitry Andric         if (Error Err = Context->link(ArtificialTypeUnit.get()))
2001db9f3b2SDimitry Andric           GlobalData.error(std::move(Err), Context->InputDWARFFile.FileName);
2011db9f3b2SDimitry Andric 
2021db9f3b2SDimitry Andric         Context->InputDWARFFile.unload();
2031db9f3b2SDimitry Andric       });
2041db9f3b2SDimitry Andric 
2051db9f3b2SDimitry Andric     Pool.wait();
2061db9f3b2SDimitry Andric   }
2071db9f3b2SDimitry Andric 
2081db9f3b2SDimitry Andric   if (ArtificialTypeUnit.get() != nullptr && !ArtificialTypeUnit->getTypePool()
2091db9f3b2SDimitry Andric                                                   .getRoot()
2101db9f3b2SDimitry Andric                                                   ->getValue()
2111db9f3b2SDimitry Andric                                                   .load()
2121db9f3b2SDimitry Andric                                                   ->Children.empty()) {
213*7a6dacacSDimitry Andric     if (GlobalData.getTargetTriple().has_value())
214*7a6dacacSDimitry Andric       if (Error Err = ArtificialTypeUnit.get()->finishCloningAndEmit(
215*7a6dacacSDimitry Andric               (*GlobalData.getTargetTriple()).get()))
2161db9f3b2SDimitry Andric         return Err;
2171db9f3b2SDimitry Andric   }
2181db9f3b2SDimitry Andric 
2191db9f3b2SDimitry Andric   // At this stage each compile units are cloned to their own set of debug
2201db9f3b2SDimitry Andric   // sections. Now, update patches, assign offsets and assemble final file
2211db9f3b2SDimitry Andric   // glueing debug tables from each compile unit.
2221db9f3b2SDimitry Andric   glueCompileUnitsAndWriteToTheOutput();
2231db9f3b2SDimitry Andric 
2241db9f3b2SDimitry Andric   return Error::success();
2251db9f3b2SDimitry Andric }
2261db9f3b2SDimitry Andric 
2271db9f3b2SDimitry Andric void DWARFLinkerImpl::verifyInput(const DWARFFile &File) {
2281db9f3b2SDimitry Andric   assert(File.Dwarf);
2291db9f3b2SDimitry Andric 
2301db9f3b2SDimitry Andric   std::string Buffer;
2311db9f3b2SDimitry Andric   raw_string_ostream OS(Buffer);
2321db9f3b2SDimitry Andric   DIDumpOptions DumpOpts;
2331db9f3b2SDimitry Andric   if (!File.Dwarf->verify(OS, DumpOpts.noImplicitRecursion())) {
2341db9f3b2SDimitry Andric     if (GlobalData.getOptions().InputVerificationHandler)
2351db9f3b2SDimitry Andric       GlobalData.getOptions().InputVerificationHandler(File, OS.str());
2361db9f3b2SDimitry Andric   }
2371db9f3b2SDimitry Andric }
2381db9f3b2SDimitry Andric 
2391db9f3b2SDimitry Andric Error DWARFLinkerImpl::validateAndUpdateOptions() {
2401db9f3b2SDimitry Andric   if (GlobalData.getOptions().TargetDWARFVersion == 0)
2411db9f3b2SDimitry Andric     return createStringError(std::errc::invalid_argument,
2421db9f3b2SDimitry Andric                              "target DWARF version is not set");
2431db9f3b2SDimitry Andric 
2441db9f3b2SDimitry Andric   if (GlobalData.getOptions().Verbose && GlobalData.getOptions().Threads != 1) {
2451db9f3b2SDimitry Andric     GlobalData.Options.Threads = 1;
2461db9f3b2SDimitry Andric     GlobalData.warn(
2471db9f3b2SDimitry Andric         "set number of threads to 1 to make --verbose to work properly.", "");
2481db9f3b2SDimitry Andric   }
2491db9f3b2SDimitry Andric 
2501db9f3b2SDimitry Andric   // Do not do types deduplication in case --update.
2511db9f3b2SDimitry Andric   if (GlobalData.getOptions().UpdateIndexTablesOnly &&
2521db9f3b2SDimitry Andric       !GlobalData.Options.NoODR)
2531db9f3b2SDimitry Andric     GlobalData.Options.NoODR = true;
2541db9f3b2SDimitry Andric 
2551db9f3b2SDimitry Andric   return Error::success();
2561db9f3b2SDimitry Andric }
2571db9f3b2SDimitry Andric 
2581db9f3b2SDimitry Andric /// Resolve the relative path to a build artifact referenced by DWARF by
2591db9f3b2SDimitry Andric /// applying DW_AT_comp_dir.
2601db9f3b2SDimitry Andric static void resolveRelativeObjectPath(SmallVectorImpl<char> &Buf, DWARFDie CU) {
2611db9f3b2SDimitry Andric   sys::path::append(Buf, dwarf::toString(CU.find(dwarf::DW_AT_comp_dir), ""));
2621db9f3b2SDimitry Andric }
2631db9f3b2SDimitry Andric 
2641db9f3b2SDimitry Andric static uint64_t getDwoId(const DWARFDie &CUDie) {
2651db9f3b2SDimitry Andric   auto DwoId = dwarf::toUnsigned(
2661db9f3b2SDimitry Andric       CUDie.find({dwarf::DW_AT_dwo_id, dwarf::DW_AT_GNU_dwo_id}));
2671db9f3b2SDimitry Andric   if (DwoId)
2681db9f3b2SDimitry Andric     return *DwoId;
2691db9f3b2SDimitry Andric   return 0;
2701db9f3b2SDimitry Andric }
2711db9f3b2SDimitry Andric 
2721db9f3b2SDimitry Andric static std::string
2731db9f3b2SDimitry Andric remapPath(StringRef Path,
2741db9f3b2SDimitry Andric           const DWARFLinker::ObjectPrefixMapTy &ObjectPrefixMap) {
2751db9f3b2SDimitry Andric   if (ObjectPrefixMap.empty())
2761db9f3b2SDimitry Andric     return Path.str();
2771db9f3b2SDimitry Andric 
2781db9f3b2SDimitry Andric   SmallString<256> p = Path;
2791db9f3b2SDimitry Andric   for (const auto &Entry : ObjectPrefixMap)
2801db9f3b2SDimitry Andric     if (llvm::sys::path::replace_path_prefix(p, Entry.first, Entry.second))
2811db9f3b2SDimitry Andric       break;
2821db9f3b2SDimitry Andric   return p.str().str();
2831db9f3b2SDimitry Andric }
2841db9f3b2SDimitry Andric 
2851db9f3b2SDimitry Andric static std::string getPCMFile(const DWARFDie &CUDie,
2861db9f3b2SDimitry Andric                               DWARFLinker::ObjectPrefixMapTy *ObjectPrefixMap) {
2871db9f3b2SDimitry Andric   std::string PCMFile = dwarf::toString(
2881db9f3b2SDimitry Andric       CUDie.find({dwarf::DW_AT_dwo_name, dwarf::DW_AT_GNU_dwo_name}), "");
2891db9f3b2SDimitry Andric 
2901db9f3b2SDimitry Andric   if (PCMFile.empty())
2911db9f3b2SDimitry Andric     return PCMFile;
2921db9f3b2SDimitry Andric 
2931db9f3b2SDimitry Andric   if (ObjectPrefixMap)
2941db9f3b2SDimitry Andric     PCMFile = remapPath(PCMFile, *ObjectPrefixMap);
2951db9f3b2SDimitry Andric 
2961db9f3b2SDimitry Andric   return PCMFile;
2971db9f3b2SDimitry Andric }
2981db9f3b2SDimitry Andric 
2991db9f3b2SDimitry Andric std::pair<bool, bool> DWARFLinkerImpl::LinkContext::isClangModuleRef(
3001db9f3b2SDimitry Andric     const DWARFDie &CUDie, std::string &PCMFile, unsigned Indent, bool Quiet) {
3011db9f3b2SDimitry Andric   if (PCMFile.empty())
3021db9f3b2SDimitry Andric     return std::make_pair(false, false);
3031db9f3b2SDimitry Andric 
3041db9f3b2SDimitry Andric   // Clang module DWARF skeleton CUs abuse this for the path to the module.
3051db9f3b2SDimitry Andric   uint64_t DwoId = getDwoId(CUDie);
3061db9f3b2SDimitry Andric 
3071db9f3b2SDimitry Andric   std::string Name = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
3081db9f3b2SDimitry Andric   if (Name.empty()) {
3091db9f3b2SDimitry Andric     if (!Quiet)
3101db9f3b2SDimitry Andric       GlobalData.warn("anonymous module skeleton CU for " + PCMFile + ".",
3111db9f3b2SDimitry Andric                       InputDWARFFile.FileName);
3121db9f3b2SDimitry Andric     return std::make_pair(true, true);
3131db9f3b2SDimitry Andric   }
3141db9f3b2SDimitry Andric 
3151db9f3b2SDimitry Andric   if (!Quiet && GlobalData.getOptions().Verbose) {
3161db9f3b2SDimitry Andric     outs().indent(Indent);
3171db9f3b2SDimitry Andric     outs() << "Found clang module reference " << PCMFile;
3181db9f3b2SDimitry Andric   }
3191db9f3b2SDimitry Andric 
3201db9f3b2SDimitry Andric   auto Cached = ClangModules.find(PCMFile);
3211db9f3b2SDimitry Andric   if (Cached != ClangModules.end()) {
3221db9f3b2SDimitry Andric     // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
3231db9f3b2SDimitry Andric     // fixed in clang, only warn about DWO_id mismatches in verbose mode.
3241db9f3b2SDimitry Andric     // ASTFileSignatures will change randomly when a module is rebuilt.
3251db9f3b2SDimitry Andric     if (!Quiet && GlobalData.getOptions().Verbose && (Cached->second != DwoId))
3261db9f3b2SDimitry Andric       GlobalData.warn(
3271db9f3b2SDimitry Andric           Twine("hash mismatch: this object file was built against a "
3281db9f3b2SDimitry Andric                 "different version of the module ") +
3291db9f3b2SDimitry Andric               PCMFile + ".",
3301db9f3b2SDimitry Andric           InputDWARFFile.FileName);
3311db9f3b2SDimitry Andric     if (!Quiet && GlobalData.getOptions().Verbose)
3321db9f3b2SDimitry Andric       outs() << " [cached].\n";
3331db9f3b2SDimitry Andric     return std::make_pair(true, true);
3341db9f3b2SDimitry Andric   }
3351db9f3b2SDimitry Andric 
3361db9f3b2SDimitry Andric   return std::make_pair(true, false);
3371db9f3b2SDimitry Andric }
3381db9f3b2SDimitry Andric 
3391db9f3b2SDimitry Andric /// If this compile unit is really a skeleton CU that points to a
3401db9f3b2SDimitry Andric /// clang module, register it in ClangModules and return true.
3411db9f3b2SDimitry Andric ///
3421db9f3b2SDimitry Andric /// A skeleton CU is a CU without children, a DW_AT_gnu_dwo_name
3431db9f3b2SDimitry Andric /// pointing to the module, and a DW_AT_gnu_dwo_id with the module
3441db9f3b2SDimitry Andric /// hash.
3451db9f3b2SDimitry Andric bool DWARFLinkerImpl::LinkContext::registerModuleReference(
3461db9f3b2SDimitry Andric     const DWARFDie &CUDie, ObjFileLoaderTy Loader,
3471db9f3b2SDimitry Andric     CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
3481db9f3b2SDimitry Andric   std::string PCMFile =
3491db9f3b2SDimitry Andric       getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
3501db9f3b2SDimitry Andric   std::pair<bool, bool> IsClangModuleRef =
3511db9f3b2SDimitry Andric       isClangModuleRef(CUDie, PCMFile, Indent, false);
3521db9f3b2SDimitry Andric 
3531db9f3b2SDimitry Andric   if (!IsClangModuleRef.first)
3541db9f3b2SDimitry Andric     return false;
3551db9f3b2SDimitry Andric 
3561db9f3b2SDimitry Andric   if (IsClangModuleRef.second)
3571db9f3b2SDimitry Andric     return true;
3581db9f3b2SDimitry Andric 
3591db9f3b2SDimitry Andric   if (GlobalData.getOptions().Verbose)
3601db9f3b2SDimitry Andric     outs() << " ...\n";
3611db9f3b2SDimitry Andric 
3621db9f3b2SDimitry Andric   // Cyclic dependencies are disallowed by Clang, but we still
3631db9f3b2SDimitry Andric   // shouldn't run into an infinite loop, so mark it as processed now.
3641db9f3b2SDimitry Andric   ClangModules.insert({PCMFile, getDwoId(CUDie)});
3651db9f3b2SDimitry Andric 
3661db9f3b2SDimitry Andric   if (Error E =
3671db9f3b2SDimitry Andric           loadClangModule(Loader, CUDie, PCMFile, OnCUDieLoaded, Indent + 2)) {
3681db9f3b2SDimitry Andric     consumeError(std::move(E));
3691db9f3b2SDimitry Andric     return false;
3701db9f3b2SDimitry Andric   }
3711db9f3b2SDimitry Andric   return true;
3721db9f3b2SDimitry Andric }
3731db9f3b2SDimitry Andric 
3741db9f3b2SDimitry Andric Error DWARFLinkerImpl::LinkContext::loadClangModule(
3751db9f3b2SDimitry Andric     ObjFileLoaderTy Loader, const DWARFDie &CUDie, const std::string &PCMFile,
3761db9f3b2SDimitry Andric     CompileUnitHandlerTy OnCUDieLoaded, unsigned Indent) {
3771db9f3b2SDimitry Andric 
3781db9f3b2SDimitry Andric   uint64_t DwoId = getDwoId(CUDie);
3791db9f3b2SDimitry Andric   std::string ModuleName = dwarf::toString(CUDie.find(dwarf::DW_AT_name), "");
3801db9f3b2SDimitry Andric 
3811db9f3b2SDimitry Andric   /// Using a SmallString<0> because loadClangModule() is recursive.
3821db9f3b2SDimitry Andric   SmallString<0> Path(GlobalData.getOptions().PrependPath);
3831db9f3b2SDimitry Andric   if (sys::path::is_relative(PCMFile))
3841db9f3b2SDimitry Andric     resolveRelativeObjectPath(Path, CUDie);
3851db9f3b2SDimitry Andric   sys::path::append(Path, PCMFile);
3861db9f3b2SDimitry Andric   // Don't use the cached binary holder because we have no thread-safety
3871db9f3b2SDimitry Andric   // guarantee and the lifetime is limited.
3881db9f3b2SDimitry Andric 
3891db9f3b2SDimitry Andric   if (Loader == nullptr) {
3901db9f3b2SDimitry Andric     GlobalData.error("cann't load clang module: loader is not specified.",
3911db9f3b2SDimitry Andric                      InputDWARFFile.FileName);
3921db9f3b2SDimitry Andric     return Error::success();
3931db9f3b2SDimitry Andric   }
3941db9f3b2SDimitry Andric 
3951db9f3b2SDimitry Andric   auto ErrOrObj = Loader(InputDWARFFile.FileName, Path);
3961db9f3b2SDimitry Andric   if (!ErrOrObj)
3971db9f3b2SDimitry Andric     return Error::success();
3981db9f3b2SDimitry Andric 
3991db9f3b2SDimitry Andric   std::unique_ptr<CompileUnit> Unit;
4001db9f3b2SDimitry Andric   for (const auto &CU : ErrOrObj->Dwarf->compile_units()) {
4011db9f3b2SDimitry Andric     OnCUDieLoaded(*CU);
4021db9f3b2SDimitry Andric     // Recursively get all modules imported by this one.
4031db9f3b2SDimitry Andric     auto ChildCUDie = CU->getUnitDIE();
4041db9f3b2SDimitry Andric     if (!ChildCUDie)
4051db9f3b2SDimitry Andric       continue;
4061db9f3b2SDimitry Andric     if (!registerModuleReference(ChildCUDie, Loader, OnCUDieLoaded, Indent)) {
4071db9f3b2SDimitry Andric       if (Unit) {
4081db9f3b2SDimitry Andric         std::string Err =
4091db9f3b2SDimitry Andric             (PCMFile +
4101db9f3b2SDimitry Andric              ": Clang modules are expected to have exactly 1 compile unit.\n");
4111db9f3b2SDimitry Andric         GlobalData.error(Err, InputDWARFFile.FileName);
4121db9f3b2SDimitry Andric         return make_error<StringError>(Err, inconvertibleErrorCode());
4131db9f3b2SDimitry Andric       }
4141db9f3b2SDimitry Andric       // FIXME: Until PR27449 (https://llvm.org/bugs/show_bug.cgi?id=27449) is
4151db9f3b2SDimitry Andric       // fixed in clang, only warn about DWO_id mismatches in verbose mode.
4161db9f3b2SDimitry Andric       // ASTFileSignatures will change randomly when a module is rebuilt.
4171db9f3b2SDimitry Andric       uint64_t PCMDwoId = getDwoId(ChildCUDie);
4181db9f3b2SDimitry Andric       if (PCMDwoId != DwoId) {
4191db9f3b2SDimitry Andric         if (GlobalData.getOptions().Verbose)
4201db9f3b2SDimitry Andric           GlobalData.warn(
4211db9f3b2SDimitry Andric               Twine("hash mismatch: this object file was built against a "
4221db9f3b2SDimitry Andric                     "different version of the module ") +
4231db9f3b2SDimitry Andric                   PCMFile + ".",
4241db9f3b2SDimitry Andric               InputDWARFFile.FileName);
4251db9f3b2SDimitry Andric         // Update the cache entry with the DwoId of the module loaded from disk.
4261db9f3b2SDimitry Andric         ClangModules[PCMFile] = PCMDwoId;
4271db9f3b2SDimitry Andric       }
4281db9f3b2SDimitry Andric 
4291db9f3b2SDimitry Andric       // Empty modules units should not be cloned.
4301db9f3b2SDimitry Andric       if (!ChildCUDie.hasChildren())
4311db9f3b2SDimitry Andric         continue;
4321db9f3b2SDimitry Andric 
4331db9f3b2SDimitry Andric       // Add this module.
4341db9f3b2SDimitry Andric       Unit = std::make_unique<CompileUnit>(
4351db9f3b2SDimitry Andric           GlobalData, *CU, UniqueUnitID.fetch_add(1), ModuleName, *ErrOrObj,
4361db9f3b2SDimitry Andric           getUnitForOffset, CU->getFormParams(), getEndianness());
4371db9f3b2SDimitry Andric     }
4381db9f3b2SDimitry Andric   }
4391db9f3b2SDimitry Andric 
4401db9f3b2SDimitry Andric   if (Unit) {
4411db9f3b2SDimitry Andric     ModulesCompileUnits.emplace_back(RefModuleUnit{*ErrOrObj, std::move(Unit)});
4421db9f3b2SDimitry Andric     // Preload line table, as it can't be loaded asynchronously.
4431db9f3b2SDimitry Andric     ModulesCompileUnits.back().Unit->loadLineTable();
4441db9f3b2SDimitry Andric   }
4451db9f3b2SDimitry Andric 
4461db9f3b2SDimitry Andric   return Error::success();
4471db9f3b2SDimitry Andric }
4481db9f3b2SDimitry Andric 
4491db9f3b2SDimitry Andric Error DWARFLinkerImpl::LinkContext::link(TypeUnit *ArtificialTypeUnit) {
4501db9f3b2SDimitry Andric   InterCUProcessingStarted = false;
4511db9f3b2SDimitry Andric   if (!InputDWARFFile.Dwarf)
4521db9f3b2SDimitry Andric     return Error::success();
4531db9f3b2SDimitry Andric 
4541db9f3b2SDimitry Andric   // Preload macro tables, as they can't be loaded asynchronously.
4551db9f3b2SDimitry Andric   InputDWARFFile.Dwarf->getDebugMacinfo();
4561db9f3b2SDimitry Andric   InputDWARFFile.Dwarf->getDebugMacro();
4571db9f3b2SDimitry Andric 
4581db9f3b2SDimitry Andric   // Link modules compile units first.
4591db9f3b2SDimitry Andric   parallelForEach(ModulesCompileUnits, [&](RefModuleUnit &RefModule) {
4601db9f3b2SDimitry Andric     linkSingleCompileUnit(*RefModule.Unit, ArtificialTypeUnit);
4611db9f3b2SDimitry Andric   });
4621db9f3b2SDimitry Andric 
4631db9f3b2SDimitry Andric   // Check for live relocations. If there is no any live relocation then we
4641db9f3b2SDimitry Andric   // can skip entire object file.
4651db9f3b2SDimitry Andric   if (!GlobalData.getOptions().UpdateIndexTablesOnly &&
4661db9f3b2SDimitry Andric       !InputDWARFFile.Addresses->hasValidRelocs()) {
4671db9f3b2SDimitry Andric     if (GlobalData.getOptions().Verbose)
4681db9f3b2SDimitry Andric       outs() << "No valid relocations found. Skipping.\n";
4691db9f3b2SDimitry Andric     return Error::success();
4701db9f3b2SDimitry Andric   }
4711db9f3b2SDimitry Andric 
4721db9f3b2SDimitry Andric   OriginalDebugInfoSize = getInputDebugInfoSize();
4731db9f3b2SDimitry Andric 
4741db9f3b2SDimitry Andric   // Create CompileUnit structures to keep information about source
4751db9f3b2SDimitry Andric   // DWARFUnit`s, load line tables.
4761db9f3b2SDimitry Andric   for (const auto &OrigCU : InputDWARFFile.Dwarf->compile_units()) {
4771db9f3b2SDimitry Andric     // Load only unit DIE at this stage.
4781db9f3b2SDimitry Andric     auto CUDie = OrigCU->getUnitDIE();
4791db9f3b2SDimitry Andric     std::string PCMFile =
4801db9f3b2SDimitry Andric         getPCMFile(CUDie, GlobalData.getOptions().ObjectPrefixMap);
4811db9f3b2SDimitry Andric 
4821db9f3b2SDimitry Andric     // The !isClangModuleRef condition effectively skips over fully resolved
4831db9f3b2SDimitry Andric     // skeleton units.
4841db9f3b2SDimitry Andric     if (!CUDie || GlobalData.getOptions().UpdateIndexTablesOnly ||
4851db9f3b2SDimitry Andric         !isClangModuleRef(CUDie, PCMFile, 0, true).first) {
4861db9f3b2SDimitry Andric       CompileUnits.emplace_back(std::make_unique<CompileUnit>(
4871db9f3b2SDimitry Andric           GlobalData, *OrigCU, UniqueUnitID.fetch_add(1), "", InputDWARFFile,
4881db9f3b2SDimitry Andric           getUnitForOffset, OrigCU->getFormParams(), getEndianness()));
4891db9f3b2SDimitry Andric 
4901db9f3b2SDimitry Andric       // Preload line table, as it can't be loaded asynchronously.
4911db9f3b2SDimitry Andric       CompileUnits.back()->loadLineTable();
4921db9f3b2SDimitry Andric     }
4931db9f3b2SDimitry Andric   };
4941db9f3b2SDimitry Andric 
4951db9f3b2SDimitry Andric   HasNewInterconnectedCUs = false;
4961db9f3b2SDimitry Andric 
4971db9f3b2SDimitry Andric   // Link self-sufficient compile units and discover inter-connected compile
4981db9f3b2SDimitry Andric   // units.
4991db9f3b2SDimitry Andric   parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5001db9f3b2SDimitry Andric     linkSingleCompileUnit(*CU, ArtificialTypeUnit);
5011db9f3b2SDimitry Andric   });
5021db9f3b2SDimitry Andric 
5031db9f3b2SDimitry Andric   // Link all inter-connected units.
5041db9f3b2SDimitry Andric   if (HasNewInterconnectedCUs) {
5051db9f3b2SDimitry Andric     InterCUProcessingStarted = true;
5061db9f3b2SDimitry Andric 
5071db9f3b2SDimitry Andric     if (Error Err = finiteLoop([&]() -> Expected<bool> {
5081db9f3b2SDimitry Andric           HasNewInterconnectedCUs = false;
5091db9f3b2SDimitry Andric 
5101db9f3b2SDimitry Andric           // Load inter-connected units.
5111db9f3b2SDimitry Andric           parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5121db9f3b2SDimitry Andric             if (CU->isInterconnectedCU()) {
5131db9f3b2SDimitry Andric               CU->maybeResetToLoadedStage();
5141db9f3b2SDimitry Andric               linkSingleCompileUnit(*CU, ArtificialTypeUnit,
5151db9f3b2SDimitry Andric                                     CompileUnit::Stage::Loaded);
5161db9f3b2SDimitry Andric             }
5171db9f3b2SDimitry Andric           });
5181db9f3b2SDimitry Andric 
5191db9f3b2SDimitry Andric           // Do liveness analysis for inter-connected units.
5201db9f3b2SDimitry Andric           parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5211db9f3b2SDimitry Andric             linkSingleCompileUnit(*CU, ArtificialTypeUnit,
5221db9f3b2SDimitry Andric                                   CompileUnit::Stage::LivenessAnalysisDone);
5231db9f3b2SDimitry Andric           });
5241db9f3b2SDimitry Andric 
5251db9f3b2SDimitry Andric           return HasNewInterconnectedCUs.load();
5261db9f3b2SDimitry Andric         }))
5271db9f3b2SDimitry Andric       return Err;
5281db9f3b2SDimitry Andric 
5291db9f3b2SDimitry Andric     // Update dependencies.
5301db9f3b2SDimitry Andric     if (Error Err = finiteLoop([&]() -> Expected<bool> {
5311db9f3b2SDimitry Andric           HasNewGlobalDependency = false;
5321db9f3b2SDimitry Andric           parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5331db9f3b2SDimitry Andric             linkSingleCompileUnit(
5341db9f3b2SDimitry Andric                 *CU, ArtificialTypeUnit,
5351db9f3b2SDimitry Andric                 CompileUnit::Stage::UpdateDependenciesCompleteness);
5361db9f3b2SDimitry Andric           });
5371db9f3b2SDimitry Andric           return HasNewGlobalDependency.load();
5381db9f3b2SDimitry Andric         }))
5391db9f3b2SDimitry Andric       return Err;
5401db9f3b2SDimitry Andric     parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5411db9f3b2SDimitry Andric       if (CU->isInterconnectedCU() &&
5421db9f3b2SDimitry Andric           CU->getStage() == CompileUnit::Stage::LivenessAnalysisDone)
5431db9f3b2SDimitry Andric         CU->setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);
5441db9f3b2SDimitry Andric     });
5451db9f3b2SDimitry Andric 
5461db9f3b2SDimitry Andric     // Assign type names.
5471db9f3b2SDimitry Andric     parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5481db9f3b2SDimitry Andric       linkSingleCompileUnit(*CU, ArtificialTypeUnit,
5491db9f3b2SDimitry Andric                             CompileUnit::Stage::TypeNamesAssigned);
5501db9f3b2SDimitry Andric     });
5511db9f3b2SDimitry Andric 
5521db9f3b2SDimitry Andric     // Clone inter-connected units.
5531db9f3b2SDimitry Andric     parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5541db9f3b2SDimitry Andric       linkSingleCompileUnit(*CU, ArtificialTypeUnit,
5551db9f3b2SDimitry Andric                             CompileUnit::Stage::Cloned);
5561db9f3b2SDimitry Andric     });
5571db9f3b2SDimitry Andric 
5581db9f3b2SDimitry Andric     // Update patches for inter-connected units.
5591db9f3b2SDimitry Andric     parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5601db9f3b2SDimitry Andric       linkSingleCompileUnit(*CU, ArtificialTypeUnit,
5611db9f3b2SDimitry Andric                             CompileUnit::Stage::PatchesUpdated);
5621db9f3b2SDimitry Andric     });
5631db9f3b2SDimitry Andric 
5641db9f3b2SDimitry Andric     // Release data.
5651db9f3b2SDimitry Andric     parallelForEach(CompileUnits, [&](std::unique_ptr<CompileUnit> &CU) {
5661db9f3b2SDimitry Andric       linkSingleCompileUnit(*CU, ArtificialTypeUnit,
5671db9f3b2SDimitry Andric                             CompileUnit::Stage::Cleaned);
5681db9f3b2SDimitry Andric     });
5691db9f3b2SDimitry Andric   }
5701db9f3b2SDimitry Andric 
5711db9f3b2SDimitry Andric   if (GlobalData.getOptions().UpdateIndexTablesOnly) {
5721db9f3b2SDimitry Andric     // Emit Invariant sections.
5731db9f3b2SDimitry Andric 
5741db9f3b2SDimitry Andric     if (Error Err = emitInvariantSections())
5751db9f3b2SDimitry Andric       return Err;
5761db9f3b2SDimitry Andric   } else if (!CompileUnits.empty()) {
5771db9f3b2SDimitry Andric     // Emit .debug_frame section.
5781db9f3b2SDimitry Andric 
5791db9f3b2SDimitry Andric     Error ResultErr = Error::success();
5801db9f3b2SDimitry Andric     llvm::parallel::TaskGroup TGroup;
5811db9f3b2SDimitry Andric     // We use task group here as PerThreadBumpPtrAllocator should be called from
5821db9f3b2SDimitry Andric     // the threads created by ThreadPoolExecutor.
5831db9f3b2SDimitry Andric     TGroup.spawn([&]() {
5841db9f3b2SDimitry Andric       if (Error Err = cloneAndEmitDebugFrame())
5851db9f3b2SDimitry Andric         ResultErr = std::move(Err);
5861db9f3b2SDimitry Andric     });
5871db9f3b2SDimitry Andric     return ResultErr;
5881db9f3b2SDimitry Andric   }
5891db9f3b2SDimitry Andric 
5901db9f3b2SDimitry Andric   return Error::success();
5911db9f3b2SDimitry Andric }
5921db9f3b2SDimitry Andric 
5931db9f3b2SDimitry Andric void DWARFLinkerImpl::LinkContext::linkSingleCompileUnit(
5941db9f3b2SDimitry Andric     CompileUnit &CU, TypeUnit *ArtificialTypeUnit,
5951db9f3b2SDimitry Andric     enum CompileUnit::Stage DoUntilStage) {
5961db9f3b2SDimitry Andric   if (InterCUProcessingStarted != CU.isInterconnectedCU())
5971db9f3b2SDimitry Andric     return;
5981db9f3b2SDimitry Andric 
5991db9f3b2SDimitry Andric   if (Error Err = finiteLoop([&]() -> Expected<bool> {
6001db9f3b2SDimitry Andric         if (CU.getStage() >= DoUntilStage)
6011db9f3b2SDimitry Andric           return false;
6021db9f3b2SDimitry Andric 
6031db9f3b2SDimitry Andric         switch (CU.getStage()) {
6041db9f3b2SDimitry Andric         case CompileUnit::Stage::CreatedNotLoaded: {
6051db9f3b2SDimitry Andric           // Load input compilation unit DIEs.
6061db9f3b2SDimitry Andric           // Analyze properties of DIEs.
6071db9f3b2SDimitry Andric           if (!CU.loadInputDIEs()) {
6081db9f3b2SDimitry Andric             // We do not need to do liveness analysis for invalid compilation
6091db9f3b2SDimitry Andric             // unit.
6101db9f3b2SDimitry Andric             CU.setStage(CompileUnit::Stage::Skipped);
6111db9f3b2SDimitry Andric           } else {
6121db9f3b2SDimitry Andric             CU.analyzeDWARFStructure();
6131db9f3b2SDimitry Andric 
6141db9f3b2SDimitry Andric             // The registerModuleReference() condition effectively skips
6151db9f3b2SDimitry Andric             // over fully resolved skeleton units. This second pass of
6161db9f3b2SDimitry Andric             // registerModuleReferences doesn't do any new work, but it
6171db9f3b2SDimitry Andric             // will collect top-level errors, which are suppressed. Module
6181db9f3b2SDimitry Andric             // warnings were already displayed in the first iteration.
6191db9f3b2SDimitry Andric             if (registerModuleReference(
6201db9f3b2SDimitry Andric                     CU.getOrigUnit().getUnitDIE(), nullptr,
6211db9f3b2SDimitry Andric                     [](const DWARFUnit &) {}, 0))
6221db9f3b2SDimitry Andric               CU.setStage(CompileUnit::Stage::PatchesUpdated);
6231db9f3b2SDimitry Andric             else
6241db9f3b2SDimitry Andric               CU.setStage(CompileUnit::Stage::Loaded);
6251db9f3b2SDimitry Andric           }
6261db9f3b2SDimitry Andric         } break;
6271db9f3b2SDimitry Andric 
6281db9f3b2SDimitry Andric         case CompileUnit::Stage::Loaded: {
6291db9f3b2SDimitry Andric           // Mark all the DIEs that need to be present in the generated output.
6301db9f3b2SDimitry Andric           // If ODR requested, build type names.
6311db9f3b2SDimitry Andric           if (!CU.resolveDependenciesAndMarkLiveness(InterCUProcessingStarted,
6321db9f3b2SDimitry Andric                                                      HasNewInterconnectedCUs)) {
6331db9f3b2SDimitry Andric             assert(HasNewInterconnectedCUs &&
6341db9f3b2SDimitry Andric                    "Flag indicating new inter-connections is not set");
6351db9f3b2SDimitry Andric             return false;
6361db9f3b2SDimitry Andric           }
6371db9f3b2SDimitry Andric 
6381db9f3b2SDimitry Andric           CU.setStage(CompileUnit::Stage::LivenessAnalysisDone);
6391db9f3b2SDimitry Andric         } break;
6401db9f3b2SDimitry Andric 
6411db9f3b2SDimitry Andric         case CompileUnit::Stage::LivenessAnalysisDone: {
6421db9f3b2SDimitry Andric           if (InterCUProcessingStarted) {
6431db9f3b2SDimitry Andric             if (CU.updateDependenciesCompleteness())
6441db9f3b2SDimitry Andric               HasNewGlobalDependency = true;
6451db9f3b2SDimitry Andric             return false;
6461db9f3b2SDimitry Andric           } else {
6471db9f3b2SDimitry Andric             if (Error Err = finiteLoop([&]() -> Expected<bool> {
6481db9f3b2SDimitry Andric                   return CU.updateDependenciesCompleteness();
6491db9f3b2SDimitry Andric                 }))
6501db9f3b2SDimitry Andric               return std::move(Err);
6511db9f3b2SDimitry Andric 
6521db9f3b2SDimitry Andric             CU.setStage(CompileUnit::Stage::UpdateDependenciesCompleteness);
6531db9f3b2SDimitry Andric           }
6541db9f3b2SDimitry Andric         } break;
6551db9f3b2SDimitry Andric 
6561db9f3b2SDimitry Andric         case CompileUnit::Stage::UpdateDependenciesCompleteness:
6571db9f3b2SDimitry Andric #ifndef NDEBUG
6581db9f3b2SDimitry Andric           CU.verifyDependencies();
6591db9f3b2SDimitry Andric #endif
6601db9f3b2SDimitry Andric 
6611db9f3b2SDimitry Andric           if (ArtificialTypeUnit) {
6621db9f3b2SDimitry Andric             if (Error Err =
6631db9f3b2SDimitry Andric                     CU.assignTypeNames(ArtificialTypeUnit->getTypePool()))
6641db9f3b2SDimitry Andric               return std::move(Err);
6651db9f3b2SDimitry Andric           }
6661db9f3b2SDimitry Andric           CU.setStage(CompileUnit::Stage::TypeNamesAssigned);
6671db9f3b2SDimitry Andric           break;
6681db9f3b2SDimitry Andric 
6691db9f3b2SDimitry Andric         case CompileUnit::Stage::TypeNamesAssigned:
6701db9f3b2SDimitry Andric           // Clone input compile unit.
6711db9f3b2SDimitry Andric           if (CU.isClangModule() ||
6721db9f3b2SDimitry Andric               GlobalData.getOptions().UpdateIndexTablesOnly ||
6731db9f3b2SDimitry Andric               CU.getContaingFile().Addresses->hasValidRelocs()) {
674*7a6dacacSDimitry Andric             if (Error Err = CU.cloneAndEmit(GlobalData.getTargetTriple(),
675*7a6dacacSDimitry Andric                                             ArtificialTypeUnit))
6761db9f3b2SDimitry Andric               return std::move(Err);
6771db9f3b2SDimitry Andric           }
6781db9f3b2SDimitry Andric 
6791db9f3b2SDimitry Andric           CU.setStage(CompileUnit::Stage::Cloned);
6801db9f3b2SDimitry Andric           break;
6811db9f3b2SDimitry Andric 
6821db9f3b2SDimitry Andric         case CompileUnit::Stage::Cloned:
6831db9f3b2SDimitry Andric           // Update DIEs referencies.
6841db9f3b2SDimitry Andric           CU.updateDieRefPatchesWithClonedOffsets();
6851db9f3b2SDimitry Andric           CU.setStage(CompileUnit::Stage::PatchesUpdated);
6861db9f3b2SDimitry Andric           break;
6871db9f3b2SDimitry Andric 
6881db9f3b2SDimitry Andric         case CompileUnit::Stage::PatchesUpdated:
6891db9f3b2SDimitry Andric           // Cleanup resources.
6901db9f3b2SDimitry Andric           CU.cleanupDataAfterClonning();
6911db9f3b2SDimitry Andric           CU.setStage(CompileUnit::Stage::Cleaned);
6921db9f3b2SDimitry Andric           break;
6931db9f3b2SDimitry Andric 
6941db9f3b2SDimitry Andric         case CompileUnit::Stage::Cleaned:
6951db9f3b2SDimitry Andric           assert(false);
6961db9f3b2SDimitry Andric           break;
6971db9f3b2SDimitry Andric 
6981db9f3b2SDimitry Andric         case CompileUnit::Stage::Skipped:
6991db9f3b2SDimitry Andric           // Nothing to do.
7001db9f3b2SDimitry Andric           break;
7011db9f3b2SDimitry Andric         }
7021db9f3b2SDimitry Andric 
7031db9f3b2SDimitry Andric         return true;
7041db9f3b2SDimitry Andric       })) {
7051db9f3b2SDimitry Andric     CU.error(std::move(Err));
7061db9f3b2SDimitry Andric     CU.cleanupDataAfterClonning();
7071db9f3b2SDimitry Andric     CU.setStage(CompileUnit::Stage::Skipped);
7081db9f3b2SDimitry Andric   }
7091db9f3b2SDimitry Andric }
7101db9f3b2SDimitry Andric 
7111db9f3b2SDimitry Andric Error DWARFLinkerImpl::LinkContext::emitInvariantSections() {
712*7a6dacacSDimitry Andric   if (!GlobalData.getTargetTriple().has_value())
7131db9f3b2SDimitry Andric     return Error::success();
7141db9f3b2SDimitry Andric 
7151db9f3b2SDimitry Andric   getOrCreateSectionDescriptor(DebugSectionKind::DebugLoc).OS
7161db9f3b2SDimitry Andric       << InputDWARFFile.Dwarf->getDWARFObj().getLocSection().Data;
7171db9f3b2SDimitry Andric   getOrCreateSectionDescriptor(DebugSectionKind::DebugLocLists).OS
7181db9f3b2SDimitry Andric       << InputDWARFFile.Dwarf->getDWARFObj().getLoclistsSection().Data;
7191db9f3b2SDimitry Andric   getOrCreateSectionDescriptor(DebugSectionKind::DebugRange).OS
7201db9f3b2SDimitry Andric       << InputDWARFFile.Dwarf->getDWARFObj().getRangesSection().Data;
7211db9f3b2SDimitry Andric   getOrCreateSectionDescriptor(DebugSectionKind::DebugRngLists).OS
7221db9f3b2SDimitry Andric       << InputDWARFFile.Dwarf->getDWARFObj().getRnglistsSection().Data;
7231db9f3b2SDimitry Andric   getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges).OS
7241db9f3b2SDimitry Andric       << InputDWARFFile.Dwarf->getDWARFObj().getArangesSection();
7251db9f3b2SDimitry Andric   getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame).OS
7261db9f3b2SDimitry Andric       << InputDWARFFile.Dwarf->getDWARFObj().getFrameSection().Data;
7271db9f3b2SDimitry Andric   getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr).OS
7281db9f3b2SDimitry Andric       << InputDWARFFile.Dwarf->getDWARFObj().getAddrSection().Data;
7291db9f3b2SDimitry Andric 
7301db9f3b2SDimitry Andric   return Error::success();
7311db9f3b2SDimitry Andric }
7321db9f3b2SDimitry Andric 
7331db9f3b2SDimitry Andric Error DWARFLinkerImpl::LinkContext::cloneAndEmitDebugFrame() {
734*7a6dacacSDimitry Andric   if (!GlobalData.getTargetTriple().has_value())
7351db9f3b2SDimitry Andric     return Error::success();
7361db9f3b2SDimitry Andric 
7371db9f3b2SDimitry Andric   if (InputDWARFFile.Dwarf.get() == nullptr)
7381db9f3b2SDimitry Andric     return Error::success();
7391db9f3b2SDimitry Andric 
7401db9f3b2SDimitry Andric   const DWARFObject &InputDWARFObj = InputDWARFFile.Dwarf->getDWARFObj();
7411db9f3b2SDimitry Andric 
7421db9f3b2SDimitry Andric   StringRef OrigFrameData = InputDWARFObj.getFrameSection().Data;
7431db9f3b2SDimitry Andric   if (OrigFrameData.empty())
7441db9f3b2SDimitry Andric     return Error::success();
7451db9f3b2SDimitry Andric 
7461db9f3b2SDimitry Andric   RangesTy AllUnitsRanges;
7471db9f3b2SDimitry Andric   for (std::unique_ptr<CompileUnit> &Unit : CompileUnits) {
7481db9f3b2SDimitry Andric     for (auto CurRange : Unit->getFunctionRanges())
7491db9f3b2SDimitry Andric       AllUnitsRanges.insert(CurRange.Range, CurRange.Value);
7501db9f3b2SDimitry Andric   }
7511db9f3b2SDimitry Andric 
7521db9f3b2SDimitry Andric   unsigned SrcAddrSize = InputDWARFObj.getAddressSize();
7531db9f3b2SDimitry Andric 
7541db9f3b2SDimitry Andric   SectionDescriptor &OutSection =
7551db9f3b2SDimitry Andric       getOrCreateSectionDescriptor(DebugSectionKind::DebugFrame);
7561db9f3b2SDimitry Andric 
7571db9f3b2SDimitry Andric   DataExtractor Data(OrigFrameData, InputDWARFObj.isLittleEndian(), 0);
7581db9f3b2SDimitry Andric   uint64_t InputOffset = 0;
7591db9f3b2SDimitry Andric 
7601db9f3b2SDimitry Andric   // Store the data of the CIEs defined in this object, keyed by their
7611db9f3b2SDimitry Andric   // offsets.
7621db9f3b2SDimitry Andric   DenseMap<uint64_t, StringRef> LocalCIES;
7631db9f3b2SDimitry Andric 
7641db9f3b2SDimitry Andric   /// The CIEs that have been emitted in the output section. The actual CIE
7651db9f3b2SDimitry Andric   /// data serves a the key to this StringMap.
7661db9f3b2SDimitry Andric   StringMap<uint32_t> EmittedCIEs;
7671db9f3b2SDimitry Andric 
7681db9f3b2SDimitry Andric   while (Data.isValidOffset(InputOffset)) {
7691db9f3b2SDimitry Andric     uint64_t EntryOffset = InputOffset;
7701db9f3b2SDimitry Andric     uint32_t InitialLength = Data.getU32(&InputOffset);
7711db9f3b2SDimitry Andric     if (InitialLength == 0xFFFFFFFF)
7721db9f3b2SDimitry Andric       return createFileError(InputDWARFObj.getFileName(),
7731db9f3b2SDimitry Andric                              createStringError(std::errc::invalid_argument,
7741db9f3b2SDimitry Andric                                                "Dwarf64 bits no supported"));
7751db9f3b2SDimitry Andric 
7761db9f3b2SDimitry Andric     uint32_t CIEId = Data.getU32(&InputOffset);
7771db9f3b2SDimitry Andric     if (CIEId == 0xFFFFFFFF) {
7781db9f3b2SDimitry Andric       // This is a CIE, store it.
7791db9f3b2SDimitry Andric       StringRef CIEData = OrigFrameData.substr(EntryOffset, InitialLength + 4);
7801db9f3b2SDimitry Andric       LocalCIES[EntryOffset] = CIEData;
7811db9f3b2SDimitry Andric       // The -4 is to account for the CIEId we just read.
7821db9f3b2SDimitry Andric       InputOffset += InitialLength - 4;
7831db9f3b2SDimitry Andric       continue;
7841db9f3b2SDimitry Andric     }
7851db9f3b2SDimitry Andric 
7861db9f3b2SDimitry Andric     uint64_t Loc = Data.getUnsigned(&InputOffset, SrcAddrSize);
7871db9f3b2SDimitry Andric 
7881db9f3b2SDimitry Andric     // Some compilers seem to emit frame info that doesn't start at
7891db9f3b2SDimitry Andric     // the function entry point, thus we can't just lookup the address
7901db9f3b2SDimitry Andric     // in the debug map. Use the AddressInfo's range map to see if the FDE
7911db9f3b2SDimitry Andric     // describes something that we can relocate.
7921db9f3b2SDimitry Andric     std::optional<AddressRangeValuePair> Range =
7931db9f3b2SDimitry Andric         AllUnitsRanges.getRangeThatContains(Loc);
7941db9f3b2SDimitry Andric     if (!Range) {
7951db9f3b2SDimitry Andric       // The +4 is to account for the size of the InitialLength field itself.
7961db9f3b2SDimitry Andric       InputOffset = EntryOffset + InitialLength + 4;
7971db9f3b2SDimitry Andric       continue;
7981db9f3b2SDimitry Andric     }
7991db9f3b2SDimitry Andric 
8001db9f3b2SDimitry Andric     // This is an FDE, and we have a mapping.
8011db9f3b2SDimitry Andric     // Have we already emitted a corresponding CIE?
8021db9f3b2SDimitry Andric     StringRef CIEData = LocalCIES[CIEId];
8031db9f3b2SDimitry Andric     if (CIEData.empty())
8041db9f3b2SDimitry Andric       return createFileError(
8051db9f3b2SDimitry Andric           InputDWARFObj.getFileName(),
8061db9f3b2SDimitry Andric           createStringError(std::errc::invalid_argument,
8071db9f3b2SDimitry Andric                             "Inconsistent debug_frame content. Dropping."));
8081db9f3b2SDimitry Andric 
8091db9f3b2SDimitry Andric     uint64_t OffsetToCIERecord = OutSection.OS.tell();
8101db9f3b2SDimitry Andric 
8111db9f3b2SDimitry Andric     // Look if we already emitted a CIE that corresponds to the
8121db9f3b2SDimitry Andric     // referenced one (the CIE data is the key of that lookup).
8131db9f3b2SDimitry Andric     auto IteratorInserted =
8141db9f3b2SDimitry Andric         EmittedCIEs.insert(std::make_pair(CIEData, OffsetToCIERecord));
8151db9f3b2SDimitry Andric     OffsetToCIERecord = IteratorInserted.first->getValue();
8161db9f3b2SDimitry Andric 
8171db9f3b2SDimitry Andric     // Emit CIE for this ID if it is not emitted yet.
8181db9f3b2SDimitry Andric     if (IteratorInserted.second)
8191db9f3b2SDimitry Andric       OutSection.OS << CIEData;
8201db9f3b2SDimitry Andric 
8211db9f3b2SDimitry Andric     // Remember offset to the FDE record, so that we might update
8221db9f3b2SDimitry Andric     // field referencing CIE record(containing OffsetToCIERecord),
8231db9f3b2SDimitry Andric     // when final offsets are known. OffsetToCIERecord(which is written later)
8241db9f3b2SDimitry Andric     // is local to the current .debug_frame section, it should be updated
8251db9f3b2SDimitry Andric     // with final offset of the .debug_frame section.
8261db9f3b2SDimitry Andric     OutSection.notePatch(
8271db9f3b2SDimitry Andric         DebugOffsetPatch{OutSection.OS.tell() + 4, &OutSection, true});
8281db9f3b2SDimitry Andric 
8291db9f3b2SDimitry Andric     // Emit the FDE with updated address and CIE pointer.
8301db9f3b2SDimitry Andric     // (4 + AddrSize) is the size of the CIEId + initial_location
8311db9f3b2SDimitry Andric     // fields that will get reconstructed by emitFDE().
8321db9f3b2SDimitry Andric     unsigned FDERemainingBytes = InitialLength - (4 + SrcAddrSize);
8331db9f3b2SDimitry Andric     emitFDE(OffsetToCIERecord, SrcAddrSize, Loc + Range->Value,
8341db9f3b2SDimitry Andric             OrigFrameData.substr(InputOffset, FDERemainingBytes), OutSection);
8351db9f3b2SDimitry Andric     InputOffset += FDERemainingBytes;
8361db9f3b2SDimitry Andric   }
8371db9f3b2SDimitry Andric 
8381db9f3b2SDimitry Andric   return Error::success();
8391db9f3b2SDimitry Andric }
8401db9f3b2SDimitry Andric 
8411db9f3b2SDimitry Andric /// Emit a FDE into the debug_frame section. \p FDEBytes
8421db9f3b2SDimitry Andric /// contains the FDE data without the length, CIE offset and address
8431db9f3b2SDimitry Andric /// which will be replaced with the parameter values.
8441db9f3b2SDimitry Andric void DWARFLinkerImpl::LinkContext::emitFDE(uint32_t CIEOffset,
8451db9f3b2SDimitry Andric                                            uint32_t AddrSize, uint64_t Address,
8461db9f3b2SDimitry Andric                                            StringRef FDEBytes,
8471db9f3b2SDimitry Andric                                            SectionDescriptor &Section) {
8481db9f3b2SDimitry Andric   Section.emitIntVal(FDEBytes.size() + 4 + AddrSize, 4);
8491db9f3b2SDimitry Andric   Section.emitIntVal(CIEOffset, 4);
8501db9f3b2SDimitry Andric   Section.emitIntVal(Address, AddrSize);
8511db9f3b2SDimitry Andric   Section.OS.write(FDEBytes.data(), FDEBytes.size());
8521db9f3b2SDimitry Andric }
8531db9f3b2SDimitry Andric 
8541db9f3b2SDimitry Andric void DWARFLinkerImpl::glueCompileUnitsAndWriteToTheOutput() {
855*7a6dacacSDimitry Andric   if (!GlobalData.getTargetTriple().has_value())
8561db9f3b2SDimitry Andric     return;
857*7a6dacacSDimitry Andric   assert(SectionHandler);
8581db9f3b2SDimitry Andric 
8591db9f3b2SDimitry Andric   // Go through all object files, all compile units and assign
8601db9f3b2SDimitry Andric   // offsets to them.
8611db9f3b2SDimitry Andric   assignOffsets();
8621db9f3b2SDimitry Andric 
8631db9f3b2SDimitry Andric   // Patch size/offsets fields according to the assigned CU offsets.
8641db9f3b2SDimitry Andric   patchOffsetsAndSizes();
8651db9f3b2SDimitry Andric 
8661db9f3b2SDimitry Andric   // Emit common sections and write debug tables from all object files/compile
8671db9f3b2SDimitry Andric   // units into the resulting file.
8681db9f3b2SDimitry Andric   emitCommonSectionsAndWriteCompileUnitsToTheOutput();
8691db9f3b2SDimitry Andric 
8701db9f3b2SDimitry Andric   if (ArtificialTypeUnit.get() != nullptr)
8711db9f3b2SDimitry Andric     ArtificialTypeUnit.reset();
8721db9f3b2SDimitry Andric 
8731db9f3b2SDimitry Andric   // Write common debug sections into the resulting file.
8741db9f3b2SDimitry Andric   writeCommonSectionsToTheOutput();
8751db9f3b2SDimitry Andric 
8761db9f3b2SDimitry Andric   // Cleanup data.
8771db9f3b2SDimitry Andric   cleanupDataAfterDWARFOutputIsWritten();
8781db9f3b2SDimitry Andric 
8791db9f3b2SDimitry Andric   if (GlobalData.getOptions().Statistics)
8801db9f3b2SDimitry Andric     printStatistic();
8811db9f3b2SDimitry Andric }
8821db9f3b2SDimitry Andric 
8831db9f3b2SDimitry Andric void DWARFLinkerImpl::printStatistic() {
8841db9f3b2SDimitry Andric 
8851db9f3b2SDimitry Andric   // For each object file map how many bytes were emitted.
8861db9f3b2SDimitry Andric   StringMap<DebugInfoSize> SizeByObject;
8871db9f3b2SDimitry Andric 
8881db9f3b2SDimitry Andric   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
8891db9f3b2SDimitry Andric     uint64_t AllDebugInfoSectionsSize = 0;
8901db9f3b2SDimitry Andric 
8911db9f3b2SDimitry Andric     for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
8921db9f3b2SDimitry Andric       if (std::optional<SectionDescriptor *> DebugInfo =
8931db9f3b2SDimitry Andric               CU->tryGetSectionDescriptor(DebugSectionKind::DebugInfo))
8941db9f3b2SDimitry Andric         AllDebugInfoSectionsSize += (*DebugInfo)->getContents().size();
8951db9f3b2SDimitry Andric 
8961db9f3b2SDimitry Andric     SizeByObject[Context->InputDWARFFile.FileName].Input =
8971db9f3b2SDimitry Andric         Context->OriginalDebugInfoSize;
8981db9f3b2SDimitry Andric     SizeByObject[Context->InputDWARFFile.FileName].Output =
8991db9f3b2SDimitry Andric         AllDebugInfoSectionsSize;
9001db9f3b2SDimitry Andric   }
9011db9f3b2SDimitry Andric 
9021db9f3b2SDimitry Andric   // Create a vector sorted in descending order by output size.
9031db9f3b2SDimitry Andric   std::vector<std::pair<StringRef, DebugInfoSize>> Sorted;
9041db9f3b2SDimitry Andric   for (auto &E : SizeByObject)
9051db9f3b2SDimitry Andric     Sorted.emplace_back(E.first(), E.second);
9061db9f3b2SDimitry Andric   llvm::sort(Sorted, [](auto &LHS, auto &RHS) {
9071db9f3b2SDimitry Andric     return LHS.second.Output > RHS.second.Output;
9081db9f3b2SDimitry Andric   });
9091db9f3b2SDimitry Andric 
9101db9f3b2SDimitry Andric   auto ComputePercentange = [](int64_t Input, int64_t Output) -> float {
9111db9f3b2SDimitry Andric     const float Difference = Output - Input;
9121db9f3b2SDimitry Andric     const float Sum = Input + Output;
9131db9f3b2SDimitry Andric     if (Sum == 0)
9141db9f3b2SDimitry Andric       return 0;
9151db9f3b2SDimitry Andric     return (Difference / (Sum / 2));
9161db9f3b2SDimitry Andric   };
9171db9f3b2SDimitry Andric 
9181db9f3b2SDimitry Andric   int64_t InputTotal = 0;
9191db9f3b2SDimitry Andric   int64_t OutputTotal = 0;
9201db9f3b2SDimitry Andric   const char *FormatStr = "{0,-45} {1,10}b  {2,10}b {3,8:P}\n";
9211db9f3b2SDimitry Andric 
9221db9f3b2SDimitry Andric   // Print header.
9231db9f3b2SDimitry Andric   outs() << ".debug_info section size (in bytes)\n";
9241db9f3b2SDimitry Andric   outs() << "----------------------------------------------------------------"
9251db9f3b2SDimitry Andric             "---------------\n";
9261db9f3b2SDimitry Andric   outs() << "Filename                                           Object       "
9271db9f3b2SDimitry Andric             "  dSYM   Change\n";
9281db9f3b2SDimitry Andric   outs() << "----------------------------------------------------------------"
9291db9f3b2SDimitry Andric             "---------------\n";
9301db9f3b2SDimitry Andric 
9311db9f3b2SDimitry Andric   // Print body.
9321db9f3b2SDimitry Andric   for (auto &E : Sorted) {
9331db9f3b2SDimitry Andric     InputTotal += E.second.Input;
9341db9f3b2SDimitry Andric     OutputTotal += E.second.Output;
9351db9f3b2SDimitry Andric     llvm::outs() << formatv(
9361db9f3b2SDimitry Andric         FormatStr, sys::path::filename(E.first).take_back(45), E.second.Input,
9371db9f3b2SDimitry Andric         E.second.Output, ComputePercentange(E.second.Input, E.second.Output));
9381db9f3b2SDimitry Andric   }
9391db9f3b2SDimitry Andric   // Print total and footer.
9401db9f3b2SDimitry Andric   outs() << "----------------------------------------------------------------"
9411db9f3b2SDimitry Andric             "---------------\n";
9421db9f3b2SDimitry Andric   llvm::outs() << formatv(FormatStr, "Total", InputTotal, OutputTotal,
9431db9f3b2SDimitry Andric                           ComputePercentange(InputTotal, OutputTotal));
9441db9f3b2SDimitry Andric   outs() << "----------------------------------------------------------------"
9451db9f3b2SDimitry Andric             "---------------\n\n";
9461db9f3b2SDimitry Andric }
9471db9f3b2SDimitry Andric 
9481db9f3b2SDimitry Andric void DWARFLinkerImpl::assignOffsets() {
9491db9f3b2SDimitry Andric   llvm::parallel::TaskGroup TGroup;
9501db9f3b2SDimitry Andric   TGroup.spawn([&]() { assignOffsetsToStrings(); });
9511db9f3b2SDimitry Andric   TGroup.spawn([&]() { assignOffsetsToSections(); });
9521db9f3b2SDimitry Andric }
9531db9f3b2SDimitry Andric 
9541db9f3b2SDimitry Andric void DWARFLinkerImpl::assignOffsetsToStrings() {
9551db9f3b2SDimitry Andric   size_t CurDebugStrIndex = 1; // start from 1 to take into account zero entry.
9561db9f3b2SDimitry Andric   uint64_t CurDebugStrOffset =
9571db9f3b2SDimitry Andric       1; // start from 1 to take into account zero entry.
9581db9f3b2SDimitry Andric   size_t CurDebugLineStrIndex = 0;
9591db9f3b2SDimitry Andric   uint64_t CurDebugLineStrOffset = 0;
9601db9f3b2SDimitry Andric 
9611db9f3b2SDimitry Andric   // Enumerates all strings, add them into the DwarfStringPoolEntry map,
9621db9f3b2SDimitry Andric   // assign offset and index to the string if it is not indexed yet.
9631db9f3b2SDimitry Andric   forEachOutputString([&](StringDestinationKind Kind,
9641db9f3b2SDimitry Andric                           const StringEntry *String) {
9651db9f3b2SDimitry Andric     switch (Kind) {
9661db9f3b2SDimitry Andric     case StringDestinationKind::DebugStr: {
9671db9f3b2SDimitry Andric       DwarfStringPoolEntryWithExtString *Entry = DebugStrStrings.add(String);
9681db9f3b2SDimitry Andric       assert(Entry != nullptr);
9691db9f3b2SDimitry Andric 
9701db9f3b2SDimitry Andric       if (!Entry->isIndexed()) {
9711db9f3b2SDimitry Andric         Entry->Offset = CurDebugStrOffset;
9721db9f3b2SDimitry Andric         CurDebugStrOffset += Entry->String.size() + 1;
9731db9f3b2SDimitry Andric         Entry->Index = CurDebugStrIndex++;
9741db9f3b2SDimitry Andric       }
9751db9f3b2SDimitry Andric     } break;
9761db9f3b2SDimitry Andric     case StringDestinationKind::DebugLineStr: {
9771db9f3b2SDimitry Andric       DwarfStringPoolEntryWithExtString *Entry =
9781db9f3b2SDimitry Andric           DebugLineStrStrings.add(String);
9791db9f3b2SDimitry Andric       assert(Entry != nullptr);
9801db9f3b2SDimitry Andric 
9811db9f3b2SDimitry Andric       if (!Entry->isIndexed()) {
9821db9f3b2SDimitry Andric         Entry->Offset = CurDebugLineStrOffset;
9831db9f3b2SDimitry Andric         CurDebugLineStrOffset += Entry->String.size() + 1;
9841db9f3b2SDimitry Andric         Entry->Index = CurDebugLineStrIndex++;
9851db9f3b2SDimitry Andric       }
9861db9f3b2SDimitry Andric     } break;
9871db9f3b2SDimitry Andric     }
9881db9f3b2SDimitry Andric   });
9891db9f3b2SDimitry Andric }
9901db9f3b2SDimitry Andric 
9911db9f3b2SDimitry Andric void DWARFLinkerImpl::assignOffsetsToSections() {
9921db9f3b2SDimitry Andric   std::array<uint64_t, SectionKindsNum> SectionSizesAccumulator = {0};
9931db9f3b2SDimitry Andric 
9941db9f3b2SDimitry Andric   forEachObjectSectionsSet([&](OutputSections &UnitSections) {
9951db9f3b2SDimitry Andric     UnitSections.assignSectionsOffsetAndAccumulateSize(SectionSizesAccumulator);
9961db9f3b2SDimitry Andric   });
9971db9f3b2SDimitry Andric }
9981db9f3b2SDimitry Andric 
9991db9f3b2SDimitry Andric void DWARFLinkerImpl::forEachOutputString(
10001db9f3b2SDimitry Andric     function_ref<void(StringDestinationKind Kind, const StringEntry *String)>
10011db9f3b2SDimitry Andric         StringHandler) {
10021db9f3b2SDimitry Andric   // To save space we do not create any separate string table.
10031db9f3b2SDimitry Andric   // We use already allocated string patches and accelerator entries:
10041db9f3b2SDimitry Andric   // enumerate them in natural order and assign offsets.
10051db9f3b2SDimitry Andric   // ASSUMPTION: strings should be stored into .debug_str/.debug_line_str
10061db9f3b2SDimitry Andric   // sections in the same order as they were assigned offsets.
10071db9f3b2SDimitry Andric   forEachCompileUnit([&](CompileUnit *CU) {
10081db9f3b2SDimitry Andric     CU->forEach([&](SectionDescriptor &OutSection) {
10091db9f3b2SDimitry Andric       OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
10101db9f3b2SDimitry Andric         StringHandler(StringDestinationKind::DebugStr, Patch.String);
10111db9f3b2SDimitry Andric       });
10121db9f3b2SDimitry Andric 
10131db9f3b2SDimitry Andric       OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
10141db9f3b2SDimitry Andric         StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
10151db9f3b2SDimitry Andric       });
10161db9f3b2SDimitry Andric     });
10171db9f3b2SDimitry Andric 
10181db9f3b2SDimitry Andric     CU->forEachAcceleratorRecord([&](DwarfUnit::AccelInfo &Info) {
10191db9f3b2SDimitry Andric       StringHandler(DebugStr, Info.String);
10201db9f3b2SDimitry Andric     });
10211db9f3b2SDimitry Andric   });
10221db9f3b2SDimitry Andric 
10231db9f3b2SDimitry Andric   if (ArtificialTypeUnit.get() != nullptr) {
10241db9f3b2SDimitry Andric     ArtificialTypeUnit->forEach([&](SectionDescriptor &OutSection) {
10251db9f3b2SDimitry Andric       OutSection.ListDebugStrPatch.forEach([&](DebugStrPatch &Patch) {
10261db9f3b2SDimitry Andric         StringHandler(StringDestinationKind::DebugStr, Patch.String);
10271db9f3b2SDimitry Andric       });
10281db9f3b2SDimitry Andric 
10291db9f3b2SDimitry Andric       OutSection.ListDebugLineStrPatch.forEach([&](DebugLineStrPatch &Patch) {
10301db9f3b2SDimitry Andric         StringHandler(StringDestinationKind::DebugLineStr, Patch.String);
10311db9f3b2SDimitry Andric       });
10321db9f3b2SDimitry Andric 
10331db9f3b2SDimitry Andric       OutSection.ListDebugTypeStrPatch.forEach([&](DebugTypeStrPatch &Patch) {
10341db9f3b2SDimitry Andric         if (Patch.Die == nullptr)
10351db9f3b2SDimitry Andric           return;
10361db9f3b2SDimitry Andric 
10371db9f3b2SDimitry Andric         StringHandler(StringDestinationKind::DebugStr, Patch.String);
10381db9f3b2SDimitry Andric       });
10391db9f3b2SDimitry Andric 
10401db9f3b2SDimitry Andric       OutSection.ListDebugTypeLineStrPatch.forEach(
10411db9f3b2SDimitry Andric           [&](DebugTypeLineStrPatch &Patch) {
10421db9f3b2SDimitry Andric             if (Patch.Die == nullptr)
10431db9f3b2SDimitry Andric               return;
10441db9f3b2SDimitry Andric 
10451db9f3b2SDimitry Andric             StringHandler(StringDestinationKind::DebugStr, Patch.String);
10461db9f3b2SDimitry Andric           });
10471db9f3b2SDimitry Andric     });
10481db9f3b2SDimitry Andric   }
10491db9f3b2SDimitry Andric }
10501db9f3b2SDimitry Andric 
10511db9f3b2SDimitry Andric void DWARFLinkerImpl::forEachObjectSectionsSet(
10521db9f3b2SDimitry Andric     function_ref<void(OutputSections &)> SectionsSetHandler) {
10531db9f3b2SDimitry Andric   // Handle artificial type unit first.
10541db9f3b2SDimitry Andric   if (ArtificialTypeUnit.get() != nullptr)
10551db9f3b2SDimitry Andric     SectionsSetHandler(*ArtificialTypeUnit);
10561db9f3b2SDimitry Andric 
10571db9f3b2SDimitry Andric   // Then all modules(before regular compilation units).
10581db9f3b2SDimitry Andric   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
10591db9f3b2SDimitry Andric     for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
10601db9f3b2SDimitry Andric       if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
10611db9f3b2SDimitry Andric         SectionsSetHandler(*ModuleUnit.Unit);
10621db9f3b2SDimitry Andric 
10631db9f3b2SDimitry Andric   // Finally all compilation units.
10641db9f3b2SDimitry Andric   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts) {
10651db9f3b2SDimitry Andric     // Handle object file common sections.
10661db9f3b2SDimitry Andric     SectionsSetHandler(*Context);
10671db9f3b2SDimitry Andric 
10681db9f3b2SDimitry Andric     // Handle compilation units.
10691db9f3b2SDimitry Andric     for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
10701db9f3b2SDimitry Andric       if (CU->getStage() != CompileUnit::Stage::Skipped)
10711db9f3b2SDimitry Andric         SectionsSetHandler(*CU);
10721db9f3b2SDimitry Andric   }
10731db9f3b2SDimitry Andric }
10741db9f3b2SDimitry Andric 
10751db9f3b2SDimitry Andric void DWARFLinkerImpl::forEachCompileAndTypeUnit(
10761db9f3b2SDimitry Andric     function_ref<void(DwarfUnit *CU)> UnitHandler) {
10771db9f3b2SDimitry Andric   if (ArtificialTypeUnit.get() != nullptr)
10781db9f3b2SDimitry Andric     UnitHandler(ArtificialTypeUnit.get());
10791db9f3b2SDimitry Andric 
10801db9f3b2SDimitry Andric   // Enumerate module units.
10811db9f3b2SDimitry Andric   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
10821db9f3b2SDimitry Andric     for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
10831db9f3b2SDimitry Andric       if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
10841db9f3b2SDimitry Andric         UnitHandler(ModuleUnit.Unit.get());
10851db9f3b2SDimitry Andric 
10861db9f3b2SDimitry Andric   // Enumerate compile units.
10871db9f3b2SDimitry Andric   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
10881db9f3b2SDimitry Andric     for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
10891db9f3b2SDimitry Andric       if (CU->getStage() != CompileUnit::Stage::Skipped)
10901db9f3b2SDimitry Andric         UnitHandler(CU.get());
10911db9f3b2SDimitry Andric }
10921db9f3b2SDimitry Andric 
10931db9f3b2SDimitry Andric void DWARFLinkerImpl::forEachCompileUnit(
10941db9f3b2SDimitry Andric     function_ref<void(CompileUnit *CU)> UnitHandler) {
10951db9f3b2SDimitry Andric   // Enumerate module units.
10961db9f3b2SDimitry Andric   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
10971db9f3b2SDimitry Andric     for (LinkContext::RefModuleUnit &ModuleUnit : Context->ModulesCompileUnits)
10981db9f3b2SDimitry Andric       if (ModuleUnit.Unit->getStage() != CompileUnit::Stage::Skipped)
10991db9f3b2SDimitry Andric         UnitHandler(ModuleUnit.Unit.get());
11001db9f3b2SDimitry Andric 
11011db9f3b2SDimitry Andric   // Enumerate compile units.
11021db9f3b2SDimitry Andric   for (const std::unique_ptr<LinkContext> &Context : ObjectContexts)
11031db9f3b2SDimitry Andric     for (std::unique_ptr<CompileUnit> &CU : Context->CompileUnits)
11041db9f3b2SDimitry Andric       if (CU->getStage() != CompileUnit::Stage::Skipped)
11051db9f3b2SDimitry Andric         UnitHandler(CU.get());
11061db9f3b2SDimitry Andric }
11071db9f3b2SDimitry Andric 
11081db9f3b2SDimitry Andric void DWARFLinkerImpl::patchOffsetsAndSizes() {
11091db9f3b2SDimitry Andric   forEachObjectSectionsSet([&](OutputSections &SectionsSet) {
11101db9f3b2SDimitry Andric     SectionsSet.forEach([&](SectionDescriptor &OutSection) {
11111db9f3b2SDimitry Andric       SectionsSet.applyPatches(OutSection, DebugStrStrings, DebugLineStrStrings,
11121db9f3b2SDimitry Andric                                ArtificialTypeUnit.get());
11131db9f3b2SDimitry Andric     });
11141db9f3b2SDimitry Andric   });
11151db9f3b2SDimitry Andric }
11161db9f3b2SDimitry Andric 
11171db9f3b2SDimitry Andric void DWARFLinkerImpl::emitCommonSectionsAndWriteCompileUnitsToTheOutput() {
11181db9f3b2SDimitry Andric   llvm::parallel::TaskGroup TG;
11191db9f3b2SDimitry Andric 
11201db9f3b2SDimitry Andric   // Create section descriptors ahead if they are not exist at the moment.
11211db9f3b2SDimitry Andric   // SectionDescriptors container is not thread safe. Thus we should be sure
11221db9f3b2SDimitry Andric   // that descriptors would not be created in following parallel tasks.
11231db9f3b2SDimitry Andric 
11241db9f3b2SDimitry Andric   CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugStr);
11251db9f3b2SDimitry Andric   CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugLineStr);
11261db9f3b2SDimitry Andric 
11271db9f3b2SDimitry Andric   if (llvm::is_contained(GlobalData.Options.AccelTables,
11281db9f3b2SDimitry Andric                          AccelTableKind::Apple)) {
11291db9f3b2SDimitry Andric     CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleNames);
11301db9f3b2SDimitry Andric     CommonSections.getOrCreateSectionDescriptor(
11311db9f3b2SDimitry Andric         DebugSectionKind::AppleNamespaces);
11321db9f3b2SDimitry Andric     CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleObjC);
11331db9f3b2SDimitry Andric     CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::AppleTypes);
11341db9f3b2SDimitry Andric   }
11351db9f3b2SDimitry Andric 
11361db9f3b2SDimitry Andric   if (llvm::is_contained(GlobalData.Options.AccelTables,
11371db9f3b2SDimitry Andric                          AccelTableKind::DebugNames))
11381db9f3b2SDimitry Andric     CommonSections.getOrCreateSectionDescriptor(DebugSectionKind::DebugNames);
11391db9f3b2SDimitry Andric 
11401db9f3b2SDimitry Andric   // Emit .debug_str and .debug_line_str sections.
11411db9f3b2SDimitry Andric   TG.spawn([&]() { emitStringSections(); });
11421db9f3b2SDimitry Andric 
11431db9f3b2SDimitry Andric   if (llvm::is_contained(GlobalData.Options.AccelTables,
11441db9f3b2SDimitry Andric                          AccelTableKind::Apple)) {
11451db9f3b2SDimitry Andric     // Emit apple accelerator sections.
1146*7a6dacacSDimitry Andric     TG.spawn([&]() {
1147*7a6dacacSDimitry Andric       emitAppleAcceleratorSections((*GlobalData.getTargetTriple()).get());
1148*7a6dacacSDimitry Andric     });
11491db9f3b2SDimitry Andric   }
11501db9f3b2SDimitry Andric 
11511db9f3b2SDimitry Andric   if (llvm::is_contained(GlobalData.Options.AccelTables,
11521db9f3b2SDimitry Andric                          AccelTableKind::DebugNames)) {
11531db9f3b2SDimitry Andric     // Emit .debug_names section.
1154*7a6dacacSDimitry Andric     TG.spawn([&]() {
1155*7a6dacacSDimitry Andric       emitDWARFv5DebugNamesSection((*GlobalData.getTargetTriple()).get());
1156*7a6dacacSDimitry Andric     });
11571db9f3b2SDimitry Andric   }
11581db9f3b2SDimitry Andric 
11591db9f3b2SDimitry Andric   // Write compile units to the output file.
11601db9f3b2SDimitry Andric   TG.spawn([&]() { writeCompileUnitsToTheOutput(); });
11611db9f3b2SDimitry Andric }
11621db9f3b2SDimitry Andric 
11631db9f3b2SDimitry Andric void DWARFLinkerImpl::emitStringSections() {
11641db9f3b2SDimitry Andric   uint64_t DebugStrNextOffset = 0;
11651db9f3b2SDimitry Andric   uint64_t DebugLineStrNextOffset = 0;
11661db9f3b2SDimitry Andric 
11671db9f3b2SDimitry Andric   // Emit zero length string. Accelerator tables does not work correctly
11681db9f3b2SDimitry Andric   // if the first string is not zero length string.
11691db9f3b2SDimitry Andric   CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
11701db9f3b2SDimitry Andric       .emitInplaceString("");
11711db9f3b2SDimitry Andric   DebugStrNextOffset++;
11721db9f3b2SDimitry Andric 
11731db9f3b2SDimitry Andric   forEachOutputString(
11741db9f3b2SDimitry Andric       [&](StringDestinationKind Kind, const StringEntry *String) {
11751db9f3b2SDimitry Andric         switch (Kind) {
11761db9f3b2SDimitry Andric         case StringDestinationKind::DebugStr: {
11771db9f3b2SDimitry Andric           DwarfStringPoolEntryWithExtString *StringToEmit =
11781db9f3b2SDimitry Andric               DebugStrStrings.getExistingEntry(String);
11791db9f3b2SDimitry Andric           assert(StringToEmit->isIndexed());
11801db9f3b2SDimitry Andric 
11811db9f3b2SDimitry Andric           // Strings may be repeated. Use accumulated DebugStrNextOffset
11821db9f3b2SDimitry Andric           // to understand whether corresponding string is already emitted.
11831db9f3b2SDimitry Andric           // Skip string if its offset less than accumulated offset.
11841db9f3b2SDimitry Andric           if (StringToEmit->Offset >= DebugStrNextOffset) {
11851db9f3b2SDimitry Andric             DebugStrNextOffset =
11861db9f3b2SDimitry Andric                 StringToEmit->Offset + StringToEmit->String.size() + 1;
11871db9f3b2SDimitry Andric             // Emit the string itself.
11881db9f3b2SDimitry Andric             CommonSections.getSectionDescriptor(DebugSectionKind::DebugStr)
11891db9f3b2SDimitry Andric                 .emitInplaceString(StringToEmit->String);
11901db9f3b2SDimitry Andric           }
11911db9f3b2SDimitry Andric         } break;
11921db9f3b2SDimitry Andric         case StringDestinationKind::DebugLineStr: {
11931db9f3b2SDimitry Andric           DwarfStringPoolEntryWithExtString *StringToEmit =
11941db9f3b2SDimitry Andric               DebugLineStrStrings.getExistingEntry(String);
11951db9f3b2SDimitry Andric           assert(StringToEmit->isIndexed());
11961db9f3b2SDimitry Andric 
11971db9f3b2SDimitry Andric           // Strings may be repeated. Use accumulated DebugLineStrStrings
11981db9f3b2SDimitry Andric           // to understand whether corresponding string is already emitted.
11991db9f3b2SDimitry Andric           // Skip string if its offset less than accumulated offset.
12001db9f3b2SDimitry Andric           if (StringToEmit->Offset >= DebugLineStrNextOffset) {
12011db9f3b2SDimitry Andric             DebugLineStrNextOffset =
12021db9f3b2SDimitry Andric                 StringToEmit->Offset + StringToEmit->String.size() + 1;
12031db9f3b2SDimitry Andric             // Emit the string itself.
12041db9f3b2SDimitry Andric             CommonSections.getSectionDescriptor(DebugSectionKind::DebugLineStr)
12051db9f3b2SDimitry Andric                 .emitInplaceString(StringToEmit->String);
12061db9f3b2SDimitry Andric           }
12071db9f3b2SDimitry Andric         } break;
12081db9f3b2SDimitry Andric         }
12091db9f3b2SDimitry Andric       });
12101db9f3b2SDimitry Andric }
12111db9f3b2SDimitry Andric 
12121db9f3b2SDimitry Andric void DWARFLinkerImpl::emitAppleAcceleratorSections(const Triple &TargetTriple) {
12131db9f3b2SDimitry Andric   AccelTable<AppleAccelTableStaticOffsetData> AppleNamespaces;
12141db9f3b2SDimitry Andric   AccelTable<AppleAccelTableStaticOffsetData> AppleNames;
12151db9f3b2SDimitry Andric   AccelTable<AppleAccelTableStaticOffsetData> AppleObjC;
12161db9f3b2SDimitry Andric   AccelTable<AppleAccelTableStaticTypeData> AppleTypes;
12171db9f3b2SDimitry Andric 
12181db9f3b2SDimitry Andric   forEachCompileAndTypeUnit([&](DwarfUnit *CU) {
12191db9f3b2SDimitry Andric     CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
12201db9f3b2SDimitry Andric       uint64_t OutOffset = Info.OutOffset;
12211db9f3b2SDimitry Andric       switch (Info.Type) {
12221db9f3b2SDimitry Andric       case DwarfUnit::AccelType::None: {
12231db9f3b2SDimitry Andric         llvm_unreachable("Unknown accelerator record");
12241db9f3b2SDimitry Andric       } break;
12251db9f3b2SDimitry Andric       case DwarfUnit::AccelType::Namespace: {
12261db9f3b2SDimitry Andric         AppleNamespaces.addName(
12271db9f3b2SDimitry Andric             *DebugStrStrings.getExistingEntry(Info.String),
12281db9f3b2SDimitry Andric             CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
12291db9f3b2SDimitry Andric                 OutOffset);
12301db9f3b2SDimitry Andric       } break;
12311db9f3b2SDimitry Andric       case DwarfUnit::AccelType::Name: {
12321db9f3b2SDimitry Andric         AppleNames.addName(
12331db9f3b2SDimitry Andric             *DebugStrStrings.getExistingEntry(Info.String),
12341db9f3b2SDimitry Andric             CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
12351db9f3b2SDimitry Andric                 OutOffset);
12361db9f3b2SDimitry Andric       } break;
12371db9f3b2SDimitry Andric       case DwarfUnit::AccelType::ObjC: {
12381db9f3b2SDimitry Andric         AppleObjC.addName(
12391db9f3b2SDimitry Andric             *DebugStrStrings.getExistingEntry(Info.String),
12401db9f3b2SDimitry Andric             CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
12411db9f3b2SDimitry Andric                 OutOffset);
12421db9f3b2SDimitry Andric       } break;
12431db9f3b2SDimitry Andric       case DwarfUnit::AccelType::Type: {
12441db9f3b2SDimitry Andric         AppleTypes.addName(
12451db9f3b2SDimitry Andric             *DebugStrStrings.getExistingEntry(Info.String),
12461db9f3b2SDimitry Andric             CU->getSectionDescriptor(DebugSectionKind::DebugInfo).StartOffset +
12471db9f3b2SDimitry Andric                 OutOffset,
12481db9f3b2SDimitry Andric             Info.Tag,
12491db9f3b2SDimitry Andric             Info.ObjcClassImplementation ? dwarf::DW_FLAG_type_implementation
12501db9f3b2SDimitry Andric                                          : 0,
12511db9f3b2SDimitry Andric             Info.QualifiedNameHash);
12521db9f3b2SDimitry Andric       } break;
12531db9f3b2SDimitry Andric       }
12541db9f3b2SDimitry Andric     });
12551db9f3b2SDimitry Andric   });
12561db9f3b2SDimitry Andric 
12571db9f3b2SDimitry Andric   {
12581db9f3b2SDimitry Andric     // FIXME: we use AsmPrinter to emit accelerator sections.
12591db9f3b2SDimitry Andric     // It might be beneficial to directly emit accelerator data
12601db9f3b2SDimitry Andric     // to the raw_svector_ostream.
12611db9f3b2SDimitry Andric     SectionDescriptor &OutSection =
12621db9f3b2SDimitry Andric         CommonSections.getSectionDescriptor(DebugSectionKind::AppleNamespaces);
12631db9f3b2SDimitry Andric     DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
12641db9f3b2SDimitry Andric                              OutSection.OS);
12651db9f3b2SDimitry Andric     if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
12661db9f3b2SDimitry Andric       consumeError(std::move(Err));
12671db9f3b2SDimitry Andric       return;
12681db9f3b2SDimitry Andric     }
12691db9f3b2SDimitry Andric 
12701db9f3b2SDimitry Andric     // Emit table.
12711db9f3b2SDimitry Andric     Emitter.emitAppleNamespaces(AppleNamespaces);
12721db9f3b2SDimitry Andric     Emitter.finish();
12731db9f3b2SDimitry Andric 
12741db9f3b2SDimitry Andric     // Set start offset and size for output section.
12751db9f3b2SDimitry Andric     OutSection.setSizesForSectionCreatedByAsmPrinter();
12761db9f3b2SDimitry Andric   }
12771db9f3b2SDimitry Andric 
12781db9f3b2SDimitry Andric   {
12791db9f3b2SDimitry Andric     // FIXME: we use AsmPrinter to emit accelerator sections.
12801db9f3b2SDimitry Andric     // It might be beneficial to directly emit accelerator data
12811db9f3b2SDimitry Andric     // to the raw_svector_ostream.
12821db9f3b2SDimitry Andric     SectionDescriptor &OutSection =
12831db9f3b2SDimitry Andric         CommonSections.getSectionDescriptor(DebugSectionKind::AppleNames);
12841db9f3b2SDimitry Andric     DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
12851db9f3b2SDimitry Andric                              OutSection.OS);
12861db9f3b2SDimitry Andric     if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
12871db9f3b2SDimitry Andric       consumeError(std::move(Err));
12881db9f3b2SDimitry Andric       return;
12891db9f3b2SDimitry Andric     }
12901db9f3b2SDimitry Andric 
12911db9f3b2SDimitry Andric     // Emit table.
12921db9f3b2SDimitry Andric     Emitter.emitAppleNames(AppleNames);
12931db9f3b2SDimitry Andric     Emitter.finish();
12941db9f3b2SDimitry Andric 
12951db9f3b2SDimitry Andric     // Set start offset ans size for output section.
12961db9f3b2SDimitry Andric     OutSection.setSizesForSectionCreatedByAsmPrinter();
12971db9f3b2SDimitry Andric   }
12981db9f3b2SDimitry Andric 
12991db9f3b2SDimitry Andric   {
13001db9f3b2SDimitry Andric     // FIXME: we use AsmPrinter to emit accelerator sections.
13011db9f3b2SDimitry Andric     // It might be beneficial to directly emit accelerator data
13021db9f3b2SDimitry Andric     // to the raw_svector_ostream.
13031db9f3b2SDimitry Andric     SectionDescriptor &OutSection =
13041db9f3b2SDimitry Andric         CommonSections.getSectionDescriptor(DebugSectionKind::AppleObjC);
13051db9f3b2SDimitry Andric     DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
13061db9f3b2SDimitry Andric                              OutSection.OS);
13071db9f3b2SDimitry Andric     if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
13081db9f3b2SDimitry Andric       consumeError(std::move(Err));
13091db9f3b2SDimitry Andric       return;
13101db9f3b2SDimitry Andric     }
13111db9f3b2SDimitry Andric 
13121db9f3b2SDimitry Andric     // Emit table.
13131db9f3b2SDimitry Andric     Emitter.emitAppleObjc(AppleObjC);
13141db9f3b2SDimitry Andric     Emitter.finish();
13151db9f3b2SDimitry Andric 
13161db9f3b2SDimitry Andric     // Set start offset ans size for output section.
13171db9f3b2SDimitry Andric     OutSection.setSizesForSectionCreatedByAsmPrinter();
13181db9f3b2SDimitry Andric   }
13191db9f3b2SDimitry Andric 
13201db9f3b2SDimitry Andric   {
13211db9f3b2SDimitry Andric     // FIXME: we use AsmPrinter to emit accelerator sections.
13221db9f3b2SDimitry Andric     // It might be beneficial to directly emit accelerator data
13231db9f3b2SDimitry Andric     // to the raw_svector_ostream.
13241db9f3b2SDimitry Andric     SectionDescriptor &OutSection =
13251db9f3b2SDimitry Andric         CommonSections.getSectionDescriptor(DebugSectionKind::AppleTypes);
13261db9f3b2SDimitry Andric     DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
13271db9f3b2SDimitry Andric                              OutSection.OS);
13281db9f3b2SDimitry Andric     if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
13291db9f3b2SDimitry Andric       consumeError(std::move(Err));
13301db9f3b2SDimitry Andric       return;
13311db9f3b2SDimitry Andric     }
13321db9f3b2SDimitry Andric 
13331db9f3b2SDimitry Andric     // Emit table.
13341db9f3b2SDimitry Andric     Emitter.emitAppleTypes(AppleTypes);
13351db9f3b2SDimitry Andric     Emitter.finish();
13361db9f3b2SDimitry Andric 
13371db9f3b2SDimitry Andric     // Set start offset ans size for output section.
13381db9f3b2SDimitry Andric     OutSection.setSizesForSectionCreatedByAsmPrinter();
13391db9f3b2SDimitry Andric   }
13401db9f3b2SDimitry Andric }
13411db9f3b2SDimitry Andric 
13421db9f3b2SDimitry Andric void DWARFLinkerImpl::emitDWARFv5DebugNamesSection(const Triple &TargetTriple) {
13431db9f3b2SDimitry Andric   std::unique_ptr<DWARF5AccelTable> DebugNames;
13441db9f3b2SDimitry Andric 
13451db9f3b2SDimitry Andric   DebugNamesUnitsOffsets CompUnits;
13461db9f3b2SDimitry Andric   CompUnitIDToIdx CUidToIdx;
13471db9f3b2SDimitry Andric 
13481db9f3b2SDimitry Andric   unsigned Id = 0;
13491db9f3b2SDimitry Andric 
13501db9f3b2SDimitry Andric   forEachCompileAndTypeUnit([&](DwarfUnit *CU) {
13511db9f3b2SDimitry Andric     bool HasRecords = false;
13521db9f3b2SDimitry Andric     CU->forEachAcceleratorRecord([&](const DwarfUnit::AccelInfo &Info) {
13531db9f3b2SDimitry Andric       if (DebugNames.get() == nullptr)
13541db9f3b2SDimitry Andric         DebugNames = std::make_unique<DWARF5AccelTable>();
13551db9f3b2SDimitry Andric 
13561db9f3b2SDimitry Andric       HasRecords = true;
13571db9f3b2SDimitry Andric       switch (Info.Type) {
13581db9f3b2SDimitry Andric       case DwarfUnit::AccelType::Name:
13591db9f3b2SDimitry Andric       case DwarfUnit::AccelType::Namespace:
13601db9f3b2SDimitry Andric       case DwarfUnit::AccelType::Type: {
13611db9f3b2SDimitry Andric         DebugNames->addName(*DebugStrStrings.getExistingEntry(Info.String),
1362*7a6dacacSDimitry Andric                             Info.OutOffset, std::nullopt /*ParentDIEOffset*/,
1363*7a6dacacSDimitry Andric                             Info.Tag, CU->getUniqueID());
13641db9f3b2SDimitry Andric       } break;
13651db9f3b2SDimitry Andric 
13661db9f3b2SDimitry Andric       default:
13671db9f3b2SDimitry Andric         break; // Nothing to do.
13681db9f3b2SDimitry Andric       };
13691db9f3b2SDimitry Andric     });
13701db9f3b2SDimitry Andric 
13711db9f3b2SDimitry Andric     if (HasRecords) {
13721db9f3b2SDimitry Andric       CompUnits.push_back(
13731db9f3b2SDimitry Andric           CU->getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo)
13741db9f3b2SDimitry Andric               .StartOffset);
13751db9f3b2SDimitry Andric       CUidToIdx[CU->getUniqueID()] = Id++;
13761db9f3b2SDimitry Andric     }
13771db9f3b2SDimitry Andric   });
13781db9f3b2SDimitry Andric 
13791db9f3b2SDimitry Andric   if (DebugNames.get() != nullptr) {
13801db9f3b2SDimitry Andric     // FIXME: we use AsmPrinter to emit accelerator sections.
13811db9f3b2SDimitry Andric     // It might be beneficial to directly emit accelerator data
13821db9f3b2SDimitry Andric     // to the raw_svector_ostream.
13831db9f3b2SDimitry Andric     SectionDescriptor &OutSection =
13841db9f3b2SDimitry Andric         CommonSections.getSectionDescriptor(DebugSectionKind::DebugNames);
13851db9f3b2SDimitry Andric     DwarfEmitterImpl Emitter(DWARFLinker::OutputFileType::Object,
13861db9f3b2SDimitry Andric                              OutSection.OS);
13871db9f3b2SDimitry Andric     if (Error Err = Emitter.init(TargetTriple, "__DWARF")) {
13881db9f3b2SDimitry Andric       consumeError(std::move(Err));
13891db9f3b2SDimitry Andric       return;
13901db9f3b2SDimitry Andric     }
13911db9f3b2SDimitry Andric 
13921db9f3b2SDimitry Andric     // Emit table.
13931db9f3b2SDimitry Andric     Emitter.emitDebugNames(*DebugNames, CompUnits, CUidToIdx);
13941db9f3b2SDimitry Andric     Emitter.finish();
13951db9f3b2SDimitry Andric 
13961db9f3b2SDimitry Andric     // Set start offset ans size for output section.
13971db9f3b2SDimitry Andric     OutSection.setSizesForSectionCreatedByAsmPrinter();
13981db9f3b2SDimitry Andric   }
13991db9f3b2SDimitry Andric }
14001db9f3b2SDimitry Andric 
14011db9f3b2SDimitry Andric void DWARFLinkerImpl::cleanupDataAfterDWARFOutputIsWritten() {
14021db9f3b2SDimitry Andric   GlobalData.getStringPool().clear();
14031db9f3b2SDimitry Andric   DebugStrStrings.clear();
14041db9f3b2SDimitry Andric   DebugLineStrStrings.clear();
14051db9f3b2SDimitry Andric }
14061db9f3b2SDimitry Andric 
14071db9f3b2SDimitry Andric void DWARFLinkerImpl::writeCompileUnitsToTheOutput() {
14081db9f3b2SDimitry Andric   // Enumerate all sections and store them into the final emitter.
14091db9f3b2SDimitry Andric   forEachObjectSectionsSet([&](OutputSections &Sections) {
1410*7a6dacacSDimitry Andric     Sections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
14111db9f3b2SDimitry Andric       // Emit section content.
1412*7a6dacacSDimitry Andric       SectionHandler(OutSection);
14131db9f3b2SDimitry Andric     });
14141db9f3b2SDimitry Andric   });
14151db9f3b2SDimitry Andric }
14161db9f3b2SDimitry Andric 
14171db9f3b2SDimitry Andric void DWARFLinkerImpl::writeCommonSectionsToTheOutput() {
1418*7a6dacacSDimitry Andric   CommonSections.forEach([&](std::shared_ptr<SectionDescriptor> OutSection) {
1419*7a6dacacSDimitry Andric     SectionHandler(OutSection);
14201db9f3b2SDimitry Andric   });
14211db9f3b2SDimitry Andric }
1422