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