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