xref: /freebsd/contrib/llvm-project/llvm/lib/DWARFLinker/Parallel/DWARFLinkerCompileUnit.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
11db9f3b2SDimitry Andric //=== DWARFLinkerCompileUnit.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 "DWARFLinkerCompileUnit.h"
101db9f3b2SDimitry Andric #include "AcceleratorRecordsSaver.h"
111db9f3b2SDimitry Andric #include "DIEAttributeCloner.h"
121db9f3b2SDimitry Andric #include "DIEGenerator.h"
131db9f3b2SDimitry Andric #include "DependencyTracker.h"
141db9f3b2SDimitry Andric #include "SyntheticTypeNameBuilder.h"
15297eecfbSDimitry Andric #include "llvm/DWARFLinker/Utils.h"
161db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugAbbrev.h"
171db9f3b2SDimitry Andric #include "llvm/DebugInfo/DWARF/DWARFDebugMacro.h"
181db9f3b2SDimitry Andric #include "llvm/Support/DJB.h"
191db9f3b2SDimitry Andric #include "llvm/Support/FileSystem.h"
201db9f3b2SDimitry Andric #include "llvm/Support/FormatVariadic.h"
211db9f3b2SDimitry Andric #include "llvm/Support/Path.h"
221db9f3b2SDimitry Andric #include <utility>
231db9f3b2SDimitry Andric 
241db9f3b2SDimitry Andric using namespace llvm;
251db9f3b2SDimitry Andric using namespace dwarf_linker;
261db9f3b2SDimitry Andric using namespace dwarf_linker::parallel;
271db9f3b2SDimitry Andric 
CompileUnit(LinkingGlobalData & GlobalData,unsigned ID,StringRef ClangModuleName,DWARFFile & File,OffsetToUnitTy UnitFromOffset,dwarf::FormParams Format,llvm::endianness Endianess)281db9f3b2SDimitry Andric CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, unsigned ID,
291db9f3b2SDimitry Andric                          StringRef ClangModuleName, DWARFFile &File,
301db9f3b2SDimitry Andric                          OffsetToUnitTy UnitFromOffset,
311db9f3b2SDimitry Andric                          dwarf::FormParams Format, llvm::endianness Endianess)
321db9f3b2SDimitry Andric     : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),
331db9f3b2SDimitry Andric       getUnitFromOffset(UnitFromOffset), Stage(Stage::CreatedNotLoaded),
341db9f3b2SDimitry Andric       AcceleratorRecords(&GlobalData.getAllocator()) {
351db9f3b2SDimitry Andric   UnitName = File.FileName;
361db9f3b2SDimitry Andric   setOutputFormat(Format, Endianess);
371db9f3b2SDimitry Andric   getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
381db9f3b2SDimitry Andric }
391db9f3b2SDimitry Andric 
CompileUnit(LinkingGlobalData & GlobalData,DWARFUnit & OrigUnit,unsigned ID,StringRef ClangModuleName,DWARFFile & File,OffsetToUnitTy UnitFromOffset,dwarf::FormParams Format,llvm::endianness Endianess)401db9f3b2SDimitry Andric CompileUnit::CompileUnit(LinkingGlobalData &GlobalData, DWARFUnit &OrigUnit,
411db9f3b2SDimitry Andric                          unsigned ID, StringRef ClangModuleName,
421db9f3b2SDimitry Andric                          DWARFFile &File, OffsetToUnitTy UnitFromOffset,
431db9f3b2SDimitry Andric                          dwarf::FormParams Format, llvm::endianness Endianess)
441db9f3b2SDimitry Andric     : DwarfUnit(GlobalData, ID, ClangModuleName), File(File),
451db9f3b2SDimitry Andric       OrigUnit(&OrigUnit), getUnitFromOffset(UnitFromOffset),
461db9f3b2SDimitry Andric       Stage(Stage::CreatedNotLoaded),
471db9f3b2SDimitry Andric       AcceleratorRecords(&GlobalData.getAllocator()) {
481db9f3b2SDimitry Andric   setOutputFormat(Format, Endianess);
491db9f3b2SDimitry Andric   getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
501db9f3b2SDimitry Andric 
511db9f3b2SDimitry Andric   DWARFDie CUDie = OrigUnit.getUnitDIE();
521db9f3b2SDimitry Andric   if (!CUDie)
531db9f3b2SDimitry Andric     return;
541db9f3b2SDimitry Andric 
551db9f3b2SDimitry Andric   if (std::optional<DWARFFormValue> Val = CUDie.find(dwarf::DW_AT_language)) {
561db9f3b2SDimitry Andric     uint16_t LangVal = dwarf::toUnsigned(Val, 0);
571db9f3b2SDimitry Andric     if (isODRLanguage(LangVal))
581db9f3b2SDimitry Andric       Language = LangVal;
591db9f3b2SDimitry Andric   }
601db9f3b2SDimitry Andric 
611db9f3b2SDimitry Andric   if (!GlobalData.getOptions().NoODR && Language.has_value())
621db9f3b2SDimitry Andric     NoODR = false;
631db9f3b2SDimitry Andric 
641db9f3b2SDimitry Andric   if (const char *CUName = CUDie.getName(DINameKind::ShortName))
651db9f3b2SDimitry Andric     UnitName = CUName;
661db9f3b2SDimitry Andric   else
671db9f3b2SDimitry Andric     UnitName = File.FileName;
681db9f3b2SDimitry Andric   SysRoot = dwarf::toStringRef(CUDie.find(dwarf::DW_AT_LLVM_sysroot)).str();
691db9f3b2SDimitry Andric }
701db9f3b2SDimitry Andric 
loadLineTable()711db9f3b2SDimitry Andric void CompileUnit::loadLineTable() {
721db9f3b2SDimitry Andric   LineTablePtr = File.Dwarf->getLineTableForUnit(&getOrigUnit());
731db9f3b2SDimitry Andric }
741db9f3b2SDimitry Andric 
maybeResetToLoadedStage()751db9f3b2SDimitry Andric void CompileUnit::maybeResetToLoadedStage() {
761db9f3b2SDimitry Andric   // Nothing to reset if stage is less than "Loaded".
771db9f3b2SDimitry Andric   if (getStage() < Stage::Loaded)
781db9f3b2SDimitry Andric     return;
791db9f3b2SDimitry Andric 
801db9f3b2SDimitry Andric   // Note: We need to do erasing for "Loaded" stage because
811db9f3b2SDimitry Andric   // if live analysys failed then we will have "Loaded" stage
821db9f3b2SDimitry Andric   // with marking from "LivenessAnalysisDone" stage partially
831db9f3b2SDimitry Andric   // done. That marking should be cleared.
841db9f3b2SDimitry Andric 
851db9f3b2SDimitry Andric   for (DIEInfo &Info : DieInfoArray)
861db9f3b2SDimitry Andric     Info.unsetFlagsWhichSetDuringLiveAnalysis();
871db9f3b2SDimitry Andric 
881db9f3b2SDimitry Andric   LowPc = std::nullopt;
891db9f3b2SDimitry Andric   HighPc = 0;
901db9f3b2SDimitry Andric   Labels.clear();
911db9f3b2SDimitry Andric   Ranges.clear();
921db9f3b2SDimitry Andric   Dependencies.reset(nullptr);
931db9f3b2SDimitry Andric 
941db9f3b2SDimitry Andric   if (getStage() < Stage::Cloned) {
951db9f3b2SDimitry Andric     setStage(Stage::Loaded);
961db9f3b2SDimitry Andric     return;
971db9f3b2SDimitry Andric   }
981db9f3b2SDimitry Andric 
991db9f3b2SDimitry Andric   AcceleratorRecords.erase();
1001db9f3b2SDimitry Andric   AbbreviationsSet.clear();
1011db9f3b2SDimitry Andric   Abbreviations.clear();
1021db9f3b2SDimitry Andric   OutUnitDIE = nullptr;
1031db9f3b2SDimitry Andric   DebugAddrIndexMap.clear();
1041db9f3b2SDimitry Andric 
1051db9f3b2SDimitry Andric   for (uint64_t &Offset : OutDieOffsetArray)
1061db9f3b2SDimitry Andric     Offset = 0;
1071db9f3b2SDimitry Andric   for (TypeEntry *&Name : TypeEntries)
1081db9f3b2SDimitry Andric     Name = nullptr;
1091db9f3b2SDimitry Andric   eraseSections();
1101db9f3b2SDimitry Andric 
1111db9f3b2SDimitry Andric   setStage(Stage::CreatedNotLoaded);
1121db9f3b2SDimitry Andric }
1131db9f3b2SDimitry Andric 
loadInputDIEs()1141db9f3b2SDimitry Andric bool CompileUnit::loadInputDIEs() {
1151db9f3b2SDimitry Andric   DWARFDie InputUnitDIE = getUnitDIE(false);
1161db9f3b2SDimitry Andric   if (!InputUnitDIE)
1171db9f3b2SDimitry Andric     return false;
1181db9f3b2SDimitry Andric 
1191db9f3b2SDimitry Andric   // load input dies, resize Info structures array.
1201db9f3b2SDimitry Andric   DieInfoArray.resize(getOrigUnit().getNumDIEs());
1211db9f3b2SDimitry Andric   OutDieOffsetArray.resize(getOrigUnit().getNumDIEs(), 0);
1221db9f3b2SDimitry Andric   if (!NoODR)
1231db9f3b2SDimitry Andric     TypeEntries.resize(getOrigUnit().getNumDIEs());
1241db9f3b2SDimitry Andric   return true;
1251db9f3b2SDimitry Andric }
1261db9f3b2SDimitry Andric 
analyzeDWARFStructureRec(const DWARFDebugInfoEntry * DieEntry,bool IsODRUnavailableFunctionScope)1271db9f3b2SDimitry Andric void CompileUnit::analyzeDWARFStructureRec(const DWARFDebugInfoEntry *DieEntry,
1281db9f3b2SDimitry Andric                                            bool IsODRUnavailableFunctionScope) {
1291db9f3b2SDimitry Andric   CompileUnit::DIEInfo &DieInfo = getDIEInfo(DieEntry);
1301db9f3b2SDimitry Andric 
1311db9f3b2SDimitry Andric   for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry);
1321db9f3b2SDimitry Andric        CurChild && CurChild->getAbbreviationDeclarationPtr();
1331db9f3b2SDimitry Andric        CurChild = getSiblingEntry(CurChild)) {
1341db9f3b2SDimitry Andric     CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild);
1351db9f3b2SDimitry Andric     bool ChildIsODRUnavailableFunctionScope = IsODRUnavailableFunctionScope;
1361db9f3b2SDimitry Andric 
1371db9f3b2SDimitry Andric     if (DieInfo.getIsInMouduleScope())
1381db9f3b2SDimitry Andric       ChildInfo.setIsInMouduleScope();
1391db9f3b2SDimitry Andric 
1401db9f3b2SDimitry Andric     if (DieInfo.getIsInFunctionScope())
1411db9f3b2SDimitry Andric       ChildInfo.setIsInFunctionScope();
1421db9f3b2SDimitry Andric 
1431db9f3b2SDimitry Andric     if (DieInfo.getIsInAnonNamespaceScope())
1441db9f3b2SDimitry Andric       ChildInfo.setIsInAnonNamespaceScope();
1451db9f3b2SDimitry Andric 
1461db9f3b2SDimitry Andric     switch (CurChild->getTag()) {
1471db9f3b2SDimitry Andric     case dwarf::DW_TAG_module:
1481db9f3b2SDimitry Andric       ChildInfo.setIsInMouduleScope();
1491db9f3b2SDimitry Andric       if (DieEntry->getTag() == dwarf::DW_TAG_compile_unit &&
1501db9f3b2SDimitry Andric           dwarf::toString(find(CurChild, dwarf::DW_AT_name), "") !=
1511db9f3b2SDimitry Andric               getClangModuleName())
1521db9f3b2SDimitry Andric         analyzeImportedModule(CurChild);
1531db9f3b2SDimitry Andric       break;
1541db9f3b2SDimitry Andric     case dwarf::DW_TAG_subprogram:
1551db9f3b2SDimitry Andric       ChildInfo.setIsInFunctionScope();
1561db9f3b2SDimitry Andric       if (!ChildIsODRUnavailableFunctionScope &&
1571db9f3b2SDimitry Andric           !ChildInfo.getIsInMouduleScope()) {
1581db9f3b2SDimitry Andric         if (find(CurChild,
1591db9f3b2SDimitry Andric                  {dwarf::DW_AT_abstract_origin, dwarf::DW_AT_specification}))
1601db9f3b2SDimitry Andric           ChildIsODRUnavailableFunctionScope = true;
1611db9f3b2SDimitry Andric       }
1621db9f3b2SDimitry Andric       break;
1631db9f3b2SDimitry Andric     case dwarf::DW_TAG_namespace: {
1641db9f3b2SDimitry Andric       UnitEntryPairTy NamespaceEntry = {this, CurChild};
1651db9f3b2SDimitry Andric 
1661db9f3b2SDimitry Andric       if (find(CurChild, dwarf::DW_AT_extension))
1671db9f3b2SDimitry Andric         NamespaceEntry = NamespaceEntry.getNamespaceOrigin();
1681db9f3b2SDimitry Andric 
1691db9f3b2SDimitry Andric       if (!NamespaceEntry.CU->find(NamespaceEntry.DieEntry, dwarf::DW_AT_name))
1701db9f3b2SDimitry Andric         ChildInfo.setIsInAnonNamespaceScope();
1711db9f3b2SDimitry Andric     } break;
1721db9f3b2SDimitry Andric     default:
1731db9f3b2SDimitry Andric       break;
1741db9f3b2SDimitry Andric     }
1751db9f3b2SDimitry Andric 
1761db9f3b2SDimitry Andric     if (!isClangModule() && !getGlobalData().getOptions().UpdateIndexTablesOnly)
1771db9f3b2SDimitry Andric       ChildInfo.setTrackLiveness();
1781db9f3b2SDimitry Andric 
1791db9f3b2SDimitry Andric     if ((!ChildInfo.getIsInAnonNamespaceScope() &&
1801db9f3b2SDimitry Andric          !ChildIsODRUnavailableFunctionScope && !NoODR))
1811db9f3b2SDimitry Andric       ChildInfo.setODRAvailable();
1821db9f3b2SDimitry Andric 
1831db9f3b2SDimitry Andric     if (CurChild->hasChildren())
1841db9f3b2SDimitry Andric       analyzeDWARFStructureRec(CurChild, ChildIsODRUnavailableFunctionScope);
1851db9f3b2SDimitry Andric   }
1861db9f3b2SDimitry Andric }
1871db9f3b2SDimitry Andric 
getFileName(unsigned FileIdx,StringPool & GlobalStrings)1881db9f3b2SDimitry Andric StringEntry *CompileUnit::getFileName(unsigned FileIdx,
1891db9f3b2SDimitry Andric                                       StringPool &GlobalStrings) {
1901db9f3b2SDimitry Andric   if (LineTablePtr) {
1911db9f3b2SDimitry Andric     if (LineTablePtr->hasFileAtIndex(FileIdx)) {
1921db9f3b2SDimitry Andric       // Cache the resolved paths based on the index in the line table,
1931db9f3b2SDimitry Andric       // because calling realpath is expensive.
1941db9f3b2SDimitry Andric       ResolvedPathsMap::const_iterator It = ResolvedFullPaths.find(FileIdx);
1951db9f3b2SDimitry Andric       if (It == ResolvedFullPaths.end()) {
1961db9f3b2SDimitry Andric         std::string OrigFileName;
1971db9f3b2SDimitry Andric         bool FoundFileName = LineTablePtr->getFileNameByIndex(
1981db9f3b2SDimitry Andric             FileIdx, getOrigUnit().getCompilationDir(),
1991db9f3b2SDimitry Andric             DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath,
2001db9f3b2SDimitry Andric             OrigFileName);
2011db9f3b2SDimitry Andric         (void)FoundFileName;
2021db9f3b2SDimitry Andric         assert(FoundFileName && "Must get file name from line table");
2031db9f3b2SDimitry Andric 
2041db9f3b2SDimitry Andric         // Second level of caching, this time based on the file's parent
2051db9f3b2SDimitry Andric         // path.
2061db9f3b2SDimitry Andric         StringRef FileName = sys::path::filename(OrigFileName);
2071db9f3b2SDimitry Andric         StringRef ParentPath = sys::path::parent_path(OrigFileName);
2081db9f3b2SDimitry Andric 
2091db9f3b2SDimitry Andric         // If the ParentPath has not yet been resolved, resolve and cache it for
2101db9f3b2SDimitry Andric         // future look-ups.
2111db9f3b2SDimitry Andric         StringMap<StringEntry *>::iterator ParentIt =
2121db9f3b2SDimitry Andric             ResolvedParentPaths.find(ParentPath);
2131db9f3b2SDimitry Andric         if (ParentIt == ResolvedParentPaths.end()) {
2141db9f3b2SDimitry Andric           SmallString<256> RealPath;
2151db9f3b2SDimitry Andric           sys::fs::real_path(ParentPath, RealPath);
2161db9f3b2SDimitry Andric           ParentIt =
2171db9f3b2SDimitry Andric               ResolvedParentPaths
2181db9f3b2SDimitry Andric                   .insert({ParentPath, GlobalStrings.insert(RealPath).first})
2191db9f3b2SDimitry Andric                   .first;
2201db9f3b2SDimitry Andric         }
2211db9f3b2SDimitry Andric 
2221db9f3b2SDimitry Andric         // Join the file name again with the resolved path.
2231db9f3b2SDimitry Andric         SmallString<256> ResolvedPath(ParentIt->second->first());
2241db9f3b2SDimitry Andric         sys::path::append(ResolvedPath, FileName);
2251db9f3b2SDimitry Andric 
2261db9f3b2SDimitry Andric         It = ResolvedFullPaths
2271db9f3b2SDimitry Andric                  .insert(std::make_pair(
2281db9f3b2SDimitry Andric                      FileIdx, GlobalStrings.insert(ResolvedPath).first))
2291db9f3b2SDimitry Andric                  .first;
2301db9f3b2SDimitry Andric       }
2311db9f3b2SDimitry Andric 
2321db9f3b2SDimitry Andric       return It->second;
2331db9f3b2SDimitry Andric     }
2341db9f3b2SDimitry Andric   }
2351db9f3b2SDimitry Andric 
2361db9f3b2SDimitry Andric   return nullptr;
2371db9f3b2SDimitry Andric }
2381db9f3b2SDimitry Andric 
cleanupDataAfterClonning()2391db9f3b2SDimitry Andric void CompileUnit::cleanupDataAfterClonning() {
2401db9f3b2SDimitry Andric   AbbreviationsSet.clear();
2411db9f3b2SDimitry Andric   ResolvedFullPaths.shrink_and_clear();
2421db9f3b2SDimitry Andric   ResolvedParentPaths.clear();
2431db9f3b2SDimitry Andric   FileNames.shrink_and_clear();
2441db9f3b2SDimitry Andric   DieInfoArray = SmallVector<DIEInfo>();
2451db9f3b2SDimitry Andric   OutDieOffsetArray = SmallVector<uint64_t>();
2461db9f3b2SDimitry Andric   TypeEntries = SmallVector<TypeEntry *>();
2471db9f3b2SDimitry Andric   Dependencies.reset(nullptr);
2481db9f3b2SDimitry Andric   getOrigUnit().clear();
2491db9f3b2SDimitry Andric }
2501db9f3b2SDimitry Andric 
2511db9f3b2SDimitry Andric /// Collect references to parseable Swift interfaces in imported
2521db9f3b2SDimitry Andric /// DW_TAG_module blocks.
analyzeImportedModule(const DWARFDebugInfoEntry * DieEntry)2531db9f3b2SDimitry Andric void CompileUnit::analyzeImportedModule(const DWARFDebugInfoEntry *DieEntry) {
2541db9f3b2SDimitry Andric   if (!Language || Language != dwarf::DW_LANG_Swift)
2551db9f3b2SDimitry Andric     return;
2561db9f3b2SDimitry Andric 
2571db9f3b2SDimitry Andric   if (!GlobalData.getOptions().ParseableSwiftInterfaces)
2581db9f3b2SDimitry Andric     return;
2591db9f3b2SDimitry Andric 
2601db9f3b2SDimitry Andric   StringRef Path =
2611db9f3b2SDimitry Andric       dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_include_path));
2621db9f3b2SDimitry Andric   if (!Path.ends_with(".swiftinterface"))
2631db9f3b2SDimitry Andric     return;
2641db9f3b2SDimitry Andric   // Don't track interfaces that are part of the SDK.
2651db9f3b2SDimitry Andric   StringRef SysRoot =
2661db9f3b2SDimitry Andric       dwarf::toStringRef(find(DieEntry, dwarf::DW_AT_LLVM_sysroot));
2671db9f3b2SDimitry Andric   if (SysRoot.empty())
2681db9f3b2SDimitry Andric     SysRoot = getSysRoot();
2691db9f3b2SDimitry Andric   if (!SysRoot.empty() && Path.starts_with(SysRoot))
2701db9f3b2SDimitry Andric     return;
2711db9f3b2SDimitry Andric   // Don't track interfaces that are part of the toolchain.
2721db9f3b2SDimitry Andric   // For example: Swift, _Concurrency, ...
273*0fca6ea1SDimitry Andric   StringRef DeveloperDir = guessDeveloperDir(SysRoot);
274*0fca6ea1SDimitry Andric   if (!DeveloperDir.empty() && Path.starts_with(DeveloperDir))
275*0fca6ea1SDimitry Andric     return;
276*0fca6ea1SDimitry Andric   if (isInToolchainDir(Path))
2771db9f3b2SDimitry Andric     return;
2781db9f3b2SDimitry Andric   if (std::optional<DWARFFormValue> Val = find(DieEntry, dwarf::DW_AT_name)) {
2791db9f3b2SDimitry Andric     Expected<const char *> Name = Val->getAsCString();
2801db9f3b2SDimitry Andric     if (!Name) {
2811db9f3b2SDimitry Andric       warn(Name.takeError());
2821db9f3b2SDimitry Andric       return;
2831db9f3b2SDimitry Andric     }
2841db9f3b2SDimitry Andric 
2851db9f3b2SDimitry Andric     auto &Entry = (*GlobalData.getOptions().ParseableSwiftInterfaces)[*Name];
2861db9f3b2SDimitry Andric     // The prepend path is applied later when copying.
2871db9f3b2SDimitry Andric     SmallString<128> ResolvedPath;
2881db9f3b2SDimitry Andric     if (sys::path::is_relative(Path))
2891db9f3b2SDimitry Andric       sys::path::append(
2901db9f3b2SDimitry Andric           ResolvedPath,
2911db9f3b2SDimitry Andric           dwarf::toString(getUnitDIE().find(dwarf::DW_AT_comp_dir), ""));
2921db9f3b2SDimitry Andric     sys::path::append(ResolvedPath, Path);
2931db9f3b2SDimitry Andric     if (!Entry.empty() && Entry != ResolvedPath) {
2941db9f3b2SDimitry Andric       DWARFDie Die = getDIE(DieEntry);
2951db9f3b2SDimitry Andric       warn(Twine("conflicting parseable interfaces for Swift Module ") + *Name +
2961db9f3b2SDimitry Andric                ": " + Entry + " and " + Path + ".",
2971db9f3b2SDimitry Andric            &Die);
2981db9f3b2SDimitry Andric     }
2997a6dacacSDimitry Andric     Entry = std::string(ResolvedPath);
3001db9f3b2SDimitry Andric   }
3011db9f3b2SDimitry Andric }
3021db9f3b2SDimitry Andric 
assignTypeNames(TypePool & TypePoolRef)3031db9f3b2SDimitry Andric Error CompileUnit::assignTypeNames(TypePool &TypePoolRef) {
3041db9f3b2SDimitry Andric   if (!getUnitDIE().isValid())
3051db9f3b2SDimitry Andric     return Error::success();
3061db9f3b2SDimitry Andric 
3071db9f3b2SDimitry Andric   SyntheticTypeNameBuilder NameBuilder(TypePoolRef);
3081db9f3b2SDimitry Andric   return assignTypeNamesRec(getDebugInfoEntry(0), NameBuilder);
3091db9f3b2SDimitry Andric }
3101db9f3b2SDimitry Andric 
assignTypeNamesRec(const DWARFDebugInfoEntry * DieEntry,SyntheticTypeNameBuilder & NameBuilder)3111db9f3b2SDimitry Andric Error CompileUnit::assignTypeNamesRec(const DWARFDebugInfoEntry *DieEntry,
3121db9f3b2SDimitry Andric                                       SyntheticTypeNameBuilder &NameBuilder) {
3131db9f3b2SDimitry Andric   OrderedChildrenIndexAssigner ChildrenIndexAssigner(*this, DieEntry);
3141db9f3b2SDimitry Andric   for (const DWARFDebugInfoEntry *CurChild = getFirstChildEntry(DieEntry);
3151db9f3b2SDimitry Andric        CurChild && CurChild->getAbbreviationDeclarationPtr();
3161db9f3b2SDimitry Andric        CurChild = getSiblingEntry(CurChild)) {
3171db9f3b2SDimitry Andric     CompileUnit::DIEInfo &ChildInfo = getDIEInfo(CurChild);
3181db9f3b2SDimitry Andric     if (!ChildInfo.needToPlaceInTypeTable())
3191db9f3b2SDimitry Andric       continue;
3201db9f3b2SDimitry Andric 
3211db9f3b2SDimitry Andric     assert(ChildInfo.getODRAvailable());
3221db9f3b2SDimitry Andric     if (Error Err = NameBuilder.assignName(
3231db9f3b2SDimitry Andric             {this, CurChild},
3241db9f3b2SDimitry Andric             ChildrenIndexAssigner.getChildIndex(*this, CurChild)))
3251db9f3b2SDimitry Andric       return Err;
3261db9f3b2SDimitry Andric 
3271db9f3b2SDimitry Andric     if (Error Err = assignTypeNamesRec(CurChild, NameBuilder))
3281db9f3b2SDimitry Andric       return Err;
3291db9f3b2SDimitry Andric   }
3301db9f3b2SDimitry Andric 
3311db9f3b2SDimitry Andric   return Error::success();
3321db9f3b2SDimitry Andric }
3331db9f3b2SDimitry Andric 
updateDieRefPatchesWithClonedOffsets()3341db9f3b2SDimitry Andric void CompileUnit::updateDieRefPatchesWithClonedOffsets() {
3351db9f3b2SDimitry Andric   if (std::optional<SectionDescriptor *> DebugInfoSection =
3361db9f3b2SDimitry Andric           tryGetSectionDescriptor(DebugSectionKind::DebugInfo)) {
3371db9f3b2SDimitry Andric 
3381db9f3b2SDimitry Andric     (*DebugInfoSection)
3391db9f3b2SDimitry Andric         ->ListDebugDieRefPatch.forEach([&](DebugDieRefPatch &Patch) {
3401db9f3b2SDimitry Andric           /// Replace stored DIE indexes with DIE output offsets.
3411db9f3b2SDimitry Andric           Patch.RefDieIdxOrClonedOffset =
3421db9f3b2SDimitry Andric               Patch.RefCU.getPointer()->getDieOutOffset(
3431db9f3b2SDimitry Andric                   Patch.RefDieIdxOrClonedOffset);
3441db9f3b2SDimitry Andric         });
3451db9f3b2SDimitry Andric 
3461db9f3b2SDimitry Andric     (*DebugInfoSection)
3471db9f3b2SDimitry Andric         ->ListDebugULEB128DieRefPatch.forEach(
3481db9f3b2SDimitry Andric             [&](DebugULEB128DieRefPatch &Patch) {
3491db9f3b2SDimitry Andric               /// Replace stored DIE indexes with DIE output offsets.
3501db9f3b2SDimitry Andric               Patch.RefDieIdxOrClonedOffset =
3511db9f3b2SDimitry Andric                   Patch.RefCU.getPointer()->getDieOutOffset(
3521db9f3b2SDimitry Andric                       Patch.RefDieIdxOrClonedOffset);
3531db9f3b2SDimitry Andric             });
3541db9f3b2SDimitry Andric   }
3551db9f3b2SDimitry Andric 
3561db9f3b2SDimitry Andric   if (std::optional<SectionDescriptor *> DebugLocSection =
3571db9f3b2SDimitry Andric           tryGetSectionDescriptor(DebugSectionKind::DebugLoc)) {
3581db9f3b2SDimitry Andric     (*DebugLocSection)
3591db9f3b2SDimitry Andric         ->ListDebugULEB128DieRefPatch.forEach(
3601db9f3b2SDimitry Andric             [](DebugULEB128DieRefPatch &Patch) {
3611db9f3b2SDimitry Andric               /// Replace stored DIE indexes with DIE output offsets.
3621db9f3b2SDimitry Andric               Patch.RefDieIdxOrClonedOffset =
3631db9f3b2SDimitry Andric                   Patch.RefCU.getPointer()->getDieOutOffset(
3641db9f3b2SDimitry Andric                       Patch.RefDieIdxOrClonedOffset);
3651db9f3b2SDimitry Andric             });
3661db9f3b2SDimitry Andric   }
3671db9f3b2SDimitry Andric 
3681db9f3b2SDimitry Andric   if (std::optional<SectionDescriptor *> DebugLocListsSection =
3691db9f3b2SDimitry Andric           tryGetSectionDescriptor(DebugSectionKind::DebugLocLists)) {
3701db9f3b2SDimitry Andric     (*DebugLocListsSection)
3711db9f3b2SDimitry Andric         ->ListDebugULEB128DieRefPatch.forEach(
3721db9f3b2SDimitry Andric             [](DebugULEB128DieRefPatch &Patch) {
3731db9f3b2SDimitry Andric               /// Replace stored DIE indexes with DIE output offsets.
3741db9f3b2SDimitry Andric               Patch.RefDieIdxOrClonedOffset =
3751db9f3b2SDimitry Andric                   Patch.RefCU.getPointer()->getDieOutOffset(
3761db9f3b2SDimitry Andric                       Patch.RefDieIdxOrClonedOffset);
3771db9f3b2SDimitry Andric             });
3781db9f3b2SDimitry Andric   }
3791db9f3b2SDimitry Andric }
3801db9f3b2SDimitry Andric 
resolveDIEReference(const DWARFFormValue & RefValue,ResolveInterCUReferencesMode CanResolveInterCUReferences)3811db9f3b2SDimitry Andric std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference(
3821db9f3b2SDimitry Andric     const DWARFFormValue &RefValue,
3831db9f3b2SDimitry Andric     ResolveInterCUReferencesMode CanResolveInterCUReferences) {
384*0fca6ea1SDimitry Andric   CompileUnit *RefCU;
385*0fca6ea1SDimitry Andric   uint64_t RefDIEOffset;
386*0fca6ea1SDimitry Andric   if (std::optional<uint64_t> Offset = RefValue.getAsRelativeReference()) {
387*0fca6ea1SDimitry Andric     RefCU = this;
388*0fca6ea1SDimitry Andric     RefDIEOffset = RefValue.getUnit()->getOffset() + *Offset;
389*0fca6ea1SDimitry Andric   } else if (Offset = RefValue.getAsDebugInfoReference(); Offset) {
390*0fca6ea1SDimitry Andric     RefCU = getUnitFromOffset(*Offset);
391*0fca6ea1SDimitry Andric     RefDIEOffset = *Offset;
392*0fca6ea1SDimitry Andric   } else {
393*0fca6ea1SDimitry Andric     return std::nullopt;
3941db9f3b2SDimitry Andric   }
395*0fca6ea1SDimitry Andric 
3961db9f3b2SDimitry Andric   if (RefCU == this) {
3971db9f3b2SDimitry Andric     // Referenced DIE is in current compile unit.
398*0fca6ea1SDimitry Andric     if (std::optional<uint32_t> RefDieIdx = getDIEIndexForOffset(RefDIEOffset))
3991db9f3b2SDimitry Andric       return UnitEntryPairTy{this, getDebugInfoEntry(*RefDieIdx)};
400*0fca6ea1SDimitry Andric   } else if (RefCU && CanResolveInterCUReferences) {
4011db9f3b2SDimitry Andric     // Referenced DIE is in other compile unit.
4021db9f3b2SDimitry Andric 
4031db9f3b2SDimitry Andric     // Check whether DIEs are loaded for that compile unit.
4041db9f3b2SDimitry Andric     enum Stage ReferredCUStage = RefCU->getStage();
4051db9f3b2SDimitry Andric     if (ReferredCUStage < Stage::Loaded || ReferredCUStage > Stage::Cloned)
4061db9f3b2SDimitry Andric       return UnitEntryPairTy{RefCU, nullptr};
4071db9f3b2SDimitry Andric 
4081db9f3b2SDimitry Andric     if (std::optional<uint32_t> RefDieIdx =
4091db9f3b2SDimitry Andric             RefCU->getDIEIndexForOffset(RefDIEOffset))
4101db9f3b2SDimitry Andric       return UnitEntryPairTy{RefCU, RefCU->getDebugInfoEntry(*RefDieIdx)};
411*0fca6ea1SDimitry Andric   } else {
4121db9f3b2SDimitry Andric     return UnitEntryPairTy{RefCU, nullptr};
4131db9f3b2SDimitry Andric   }
4141db9f3b2SDimitry Andric   return std::nullopt;
4151db9f3b2SDimitry Andric }
4161db9f3b2SDimitry Andric 
resolveDIEReference(const DWARFDebugInfoEntry * DieEntry,dwarf::Attribute Attr,ResolveInterCUReferencesMode CanResolveInterCUReferences)4171db9f3b2SDimitry Andric std::optional<UnitEntryPairTy> CompileUnit::resolveDIEReference(
4181db9f3b2SDimitry Andric     const DWARFDebugInfoEntry *DieEntry, dwarf::Attribute Attr,
4191db9f3b2SDimitry Andric     ResolveInterCUReferencesMode CanResolveInterCUReferences) {
4201db9f3b2SDimitry Andric   if (std::optional<DWARFFormValue> AttrVal = find(DieEntry, Attr))
4211db9f3b2SDimitry Andric     return resolveDIEReference(*AttrVal, CanResolveInterCUReferences);
4221db9f3b2SDimitry Andric 
4231db9f3b2SDimitry Andric   return std::nullopt;
4241db9f3b2SDimitry Andric }
4251db9f3b2SDimitry Andric 
addFunctionRange(uint64_t FuncLowPc,uint64_t FuncHighPc,int64_t PcOffset)4261db9f3b2SDimitry Andric void CompileUnit::addFunctionRange(uint64_t FuncLowPc, uint64_t FuncHighPc,
4271db9f3b2SDimitry Andric                                    int64_t PcOffset) {
4281db9f3b2SDimitry Andric   std::lock_guard<std::mutex> Guard(RangesMutex);
4291db9f3b2SDimitry Andric 
4301db9f3b2SDimitry Andric   Ranges.insert({FuncLowPc, FuncHighPc}, PcOffset);
4311db9f3b2SDimitry Andric   if (LowPc)
4321db9f3b2SDimitry Andric     LowPc = std::min(*LowPc, FuncLowPc + PcOffset);
4331db9f3b2SDimitry Andric   else
4341db9f3b2SDimitry Andric     LowPc = FuncLowPc + PcOffset;
4351db9f3b2SDimitry Andric   this->HighPc = std::max(HighPc, FuncHighPc + PcOffset);
4361db9f3b2SDimitry Andric }
4371db9f3b2SDimitry Andric 
addLabelLowPc(uint64_t LabelLowPc,int64_t PcOffset)4381db9f3b2SDimitry Andric void CompileUnit::addLabelLowPc(uint64_t LabelLowPc, int64_t PcOffset) {
4391db9f3b2SDimitry Andric   std::lock_guard<std::mutex> Guard(LabelsMutex);
4401db9f3b2SDimitry Andric   Labels.insert({LabelLowPc, PcOffset});
4411db9f3b2SDimitry Andric }
4421db9f3b2SDimitry Andric 
cloneAndEmitDebugLocations()4431db9f3b2SDimitry Andric Error CompileUnit::cloneAndEmitDebugLocations() {
4441db9f3b2SDimitry Andric   if (getGlobalData().getOptions().UpdateIndexTablesOnly)
4451db9f3b2SDimitry Andric     return Error::success();
4461db9f3b2SDimitry Andric 
4471db9f3b2SDimitry Andric   if (getOrigUnit().getVersion() < 5) {
4481db9f3b2SDimitry Andric     emitLocations(DebugSectionKind::DebugLoc);
4491db9f3b2SDimitry Andric     return Error::success();
4501db9f3b2SDimitry Andric   }
4511db9f3b2SDimitry Andric 
4521db9f3b2SDimitry Andric   emitLocations(DebugSectionKind::DebugLocLists);
4531db9f3b2SDimitry Andric   return Error::success();
4541db9f3b2SDimitry Andric }
4551db9f3b2SDimitry Andric 
emitLocations(DebugSectionKind LocationSectionKind)4561db9f3b2SDimitry Andric void CompileUnit::emitLocations(DebugSectionKind LocationSectionKind) {
4571db9f3b2SDimitry Andric   SectionDescriptor &DebugInfoSection =
4581db9f3b2SDimitry Andric       getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
4591db9f3b2SDimitry Andric 
4601db9f3b2SDimitry Andric   if (!DebugInfoSection.ListDebugLocPatch.empty()) {
4611db9f3b2SDimitry Andric     SectionDescriptor &OutLocationSection =
4621db9f3b2SDimitry Andric         getOrCreateSectionDescriptor(LocationSectionKind);
4631db9f3b2SDimitry Andric     DWARFUnit &OrigUnit = getOrigUnit();
4641db9f3b2SDimitry Andric 
4651db9f3b2SDimitry Andric     uint64_t OffsetAfterUnitLength = emitLocListHeader(OutLocationSection);
4661db9f3b2SDimitry Andric 
4671db9f3b2SDimitry Andric     DebugInfoSection.ListDebugLocPatch.forEach([&](DebugLocPatch &Patch) {
4681db9f3b2SDimitry Andric       // Get location expressions vector corresponding to the current
4691db9f3b2SDimitry Andric       // attribute from the source DWARF.
4701db9f3b2SDimitry Andric       uint64_t InputDebugLocSectionOffset = DebugInfoSection.getIntVal(
4711db9f3b2SDimitry Andric           Patch.PatchOffset,
4721db9f3b2SDimitry Andric           DebugInfoSection.getFormParams().getDwarfOffsetByteSize());
4731db9f3b2SDimitry Andric       Expected<DWARFLocationExpressionsVector> OriginalLocations =
4741db9f3b2SDimitry Andric           OrigUnit.findLoclistFromOffset(InputDebugLocSectionOffset);
4751db9f3b2SDimitry Andric 
4761db9f3b2SDimitry Andric       if (!OriginalLocations) {
4771db9f3b2SDimitry Andric         warn(OriginalLocations.takeError());
4781db9f3b2SDimitry Andric         return;
4791db9f3b2SDimitry Andric       }
4801db9f3b2SDimitry Andric 
4811db9f3b2SDimitry Andric       LinkedLocationExpressionsVector LinkedLocationExpressions;
4821db9f3b2SDimitry Andric       for (DWARFLocationExpression &CurExpression : *OriginalLocations) {
4831db9f3b2SDimitry Andric         LinkedLocationExpressionsWithOffsetPatches LinkedExpression;
4841db9f3b2SDimitry Andric 
4851db9f3b2SDimitry Andric         if (CurExpression.Range) {
4861db9f3b2SDimitry Andric           // Relocate address range.
4871db9f3b2SDimitry Andric           LinkedExpression.Expression.Range = {
4881db9f3b2SDimitry Andric               CurExpression.Range->LowPC + Patch.AddrAdjustmentValue,
4891db9f3b2SDimitry Andric               CurExpression.Range->HighPC + Patch.AddrAdjustmentValue};
4901db9f3b2SDimitry Andric         }
4911db9f3b2SDimitry Andric 
4921db9f3b2SDimitry Andric         DataExtractor Data(CurExpression.Expr, OrigUnit.isLittleEndian(),
4931db9f3b2SDimitry Andric                            OrigUnit.getAddressByteSize());
4941db9f3b2SDimitry Andric 
4951db9f3b2SDimitry Andric         DWARFExpression InputExpression(Data, OrigUnit.getAddressByteSize(),
4961db9f3b2SDimitry Andric                                         OrigUnit.getFormParams().Format);
4971db9f3b2SDimitry Andric         cloneDieAttrExpression(InputExpression,
4981db9f3b2SDimitry Andric                                LinkedExpression.Expression.Expr,
4991db9f3b2SDimitry Andric                                OutLocationSection, Patch.AddrAdjustmentValue,
5001db9f3b2SDimitry Andric                                LinkedExpression.Patches);
5011db9f3b2SDimitry Andric 
5021db9f3b2SDimitry Andric         LinkedLocationExpressions.push_back({LinkedExpression});
5031db9f3b2SDimitry Andric       }
5041db9f3b2SDimitry Andric 
5051db9f3b2SDimitry Andric       // Emit locations list table fragment corresponding to the CurLocAttr.
5061db9f3b2SDimitry Andric       DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,
5071db9f3b2SDimitry Andric                              OutLocationSection.OS.tell());
5081db9f3b2SDimitry Andric       emitLocListFragment(LinkedLocationExpressions, OutLocationSection);
5091db9f3b2SDimitry Andric     });
5101db9f3b2SDimitry Andric 
5111db9f3b2SDimitry Andric     if (OffsetAfterUnitLength > 0) {
5121db9f3b2SDimitry Andric       assert(OffsetAfterUnitLength -
5131db9f3b2SDimitry Andric                  OutLocationSection.getFormParams().getDwarfOffsetByteSize() <
5141db9f3b2SDimitry Andric              OffsetAfterUnitLength);
5151db9f3b2SDimitry Andric       OutLocationSection.apply(
5161db9f3b2SDimitry Andric           OffsetAfterUnitLength -
5171db9f3b2SDimitry Andric               OutLocationSection.getFormParams().getDwarfOffsetByteSize(),
5181db9f3b2SDimitry Andric           dwarf::DW_FORM_sec_offset,
5191db9f3b2SDimitry Andric           OutLocationSection.OS.tell() - OffsetAfterUnitLength);
5201db9f3b2SDimitry Andric     }
5211db9f3b2SDimitry Andric   }
5221db9f3b2SDimitry Andric }
5231db9f3b2SDimitry Andric 
5241db9f3b2SDimitry Andric /// Emit debug locations(.debug_loc, .debug_loclists) header.
emitLocListHeader(SectionDescriptor & OutLocationSection)5251db9f3b2SDimitry Andric uint64_t CompileUnit::emitLocListHeader(SectionDescriptor &OutLocationSection) {
5261db9f3b2SDimitry Andric   if (getOrigUnit().getVersion() < 5)
5271db9f3b2SDimitry Andric     return 0;
5281db9f3b2SDimitry Andric 
5291db9f3b2SDimitry Andric   // unit_length.
5301db9f3b2SDimitry Andric   OutLocationSection.emitUnitLength(0xBADDEF);
5311db9f3b2SDimitry Andric   uint64_t OffsetAfterUnitLength = OutLocationSection.OS.tell();
5321db9f3b2SDimitry Andric 
5331db9f3b2SDimitry Andric   // Version.
5341db9f3b2SDimitry Andric   OutLocationSection.emitIntVal(5, 2);
5351db9f3b2SDimitry Andric 
5361db9f3b2SDimitry Andric   // Address size.
5371db9f3b2SDimitry Andric   OutLocationSection.emitIntVal(OutLocationSection.getFormParams().AddrSize, 1);
5381db9f3b2SDimitry Andric 
5391db9f3b2SDimitry Andric   // Seg_size
5401db9f3b2SDimitry Andric   OutLocationSection.emitIntVal(0, 1);
5411db9f3b2SDimitry Andric 
5421db9f3b2SDimitry Andric   // Offset entry count
5431db9f3b2SDimitry Andric   OutLocationSection.emitIntVal(0, 4);
5441db9f3b2SDimitry Andric 
5451db9f3b2SDimitry Andric   return OffsetAfterUnitLength;
5461db9f3b2SDimitry Andric }
5471db9f3b2SDimitry Andric 
5481db9f3b2SDimitry Andric /// Emit debug locations(.debug_loc, .debug_loclists) fragment.
emitLocListFragment(const LinkedLocationExpressionsVector & LinkedLocationExpression,SectionDescriptor & OutLocationSection)5491db9f3b2SDimitry Andric uint64_t CompileUnit::emitLocListFragment(
5501db9f3b2SDimitry Andric     const LinkedLocationExpressionsVector &LinkedLocationExpression,
5511db9f3b2SDimitry Andric     SectionDescriptor &OutLocationSection) {
5521db9f3b2SDimitry Andric   uint64_t OffsetBeforeLocationExpression = 0;
5531db9f3b2SDimitry Andric 
5541db9f3b2SDimitry Andric   if (getOrigUnit().getVersion() < 5) {
5551db9f3b2SDimitry Andric     uint64_t BaseAddress = 0;
5561db9f3b2SDimitry Andric     if (std::optional<uint64_t> LowPC = getLowPc())
5571db9f3b2SDimitry Andric       BaseAddress = *LowPC;
5581db9f3b2SDimitry Andric 
5591db9f3b2SDimitry Andric     for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :
5601db9f3b2SDimitry Andric          LinkedLocationExpression) {
5611db9f3b2SDimitry Andric       if (LocExpression.Expression.Range) {
5621db9f3b2SDimitry Andric         OutLocationSection.emitIntVal(
5631db9f3b2SDimitry Andric             LocExpression.Expression.Range->LowPC - BaseAddress,
5641db9f3b2SDimitry Andric             OutLocationSection.getFormParams().AddrSize);
5651db9f3b2SDimitry Andric         OutLocationSection.emitIntVal(
5661db9f3b2SDimitry Andric             LocExpression.Expression.Range->HighPC - BaseAddress,
5671db9f3b2SDimitry Andric             OutLocationSection.getFormParams().AddrSize);
5681db9f3b2SDimitry Andric       }
5691db9f3b2SDimitry Andric 
5701db9f3b2SDimitry Andric       OutLocationSection.emitIntVal(LocExpression.Expression.Expr.size(), 2);
5711db9f3b2SDimitry Andric       OffsetBeforeLocationExpression = OutLocationSection.OS.tell();
5721db9f3b2SDimitry Andric       for (uint64_t *OffsetPtr : LocExpression.Patches)
5731db9f3b2SDimitry Andric         *OffsetPtr += OffsetBeforeLocationExpression;
5741db9f3b2SDimitry Andric 
5751db9f3b2SDimitry Andric       OutLocationSection.OS
5761db9f3b2SDimitry Andric           << StringRef((const char *)LocExpression.Expression.Expr.data(),
5771db9f3b2SDimitry Andric                        LocExpression.Expression.Expr.size());
5781db9f3b2SDimitry Andric     }
5791db9f3b2SDimitry Andric 
5801db9f3b2SDimitry Andric     // Emit the terminator entry.
5811db9f3b2SDimitry Andric     OutLocationSection.emitIntVal(0,
5821db9f3b2SDimitry Andric                                   OutLocationSection.getFormParams().AddrSize);
5831db9f3b2SDimitry Andric     OutLocationSection.emitIntVal(0,
5841db9f3b2SDimitry Andric                                   OutLocationSection.getFormParams().AddrSize);
5851db9f3b2SDimitry Andric     return OffsetBeforeLocationExpression;
5861db9f3b2SDimitry Andric   }
5871db9f3b2SDimitry Andric 
5881db9f3b2SDimitry Andric   std::optional<uint64_t> BaseAddress;
5891db9f3b2SDimitry Andric   for (const LinkedLocationExpressionsWithOffsetPatches &LocExpression :
5901db9f3b2SDimitry Andric        LinkedLocationExpression) {
5911db9f3b2SDimitry Andric     if (LocExpression.Expression.Range) {
5921db9f3b2SDimitry Andric       // Check whether base address is set. If it is not set yet
5931db9f3b2SDimitry Andric       // then set current base address and emit base address selection entry.
5941db9f3b2SDimitry Andric       if (!BaseAddress) {
5951db9f3b2SDimitry Andric         BaseAddress = LocExpression.Expression.Range->LowPC;
5961db9f3b2SDimitry Andric 
5971db9f3b2SDimitry Andric         // Emit base address.
5981db9f3b2SDimitry Andric         OutLocationSection.emitIntVal(dwarf::DW_LLE_base_addressx, 1);
5991db9f3b2SDimitry Andric         encodeULEB128(DebugAddrIndexMap.getValueIndex(*BaseAddress),
6001db9f3b2SDimitry Andric                       OutLocationSection.OS);
6011db9f3b2SDimitry Andric       }
6021db9f3b2SDimitry Andric 
6031db9f3b2SDimitry Andric       // Emit type of entry.
6041db9f3b2SDimitry Andric       OutLocationSection.emitIntVal(dwarf::DW_LLE_offset_pair, 1);
6051db9f3b2SDimitry Andric 
6061db9f3b2SDimitry Andric       // Emit start offset relative to base address.
6071db9f3b2SDimitry Andric       encodeULEB128(LocExpression.Expression.Range->LowPC - *BaseAddress,
6081db9f3b2SDimitry Andric                     OutLocationSection.OS);
6091db9f3b2SDimitry Andric 
6101db9f3b2SDimitry Andric       // Emit end offset relative to base address.
6111db9f3b2SDimitry Andric       encodeULEB128(LocExpression.Expression.Range->HighPC - *BaseAddress,
6121db9f3b2SDimitry Andric                     OutLocationSection.OS);
6131db9f3b2SDimitry Andric     } else
6141db9f3b2SDimitry Andric       // Emit type of entry.
6151db9f3b2SDimitry Andric       OutLocationSection.emitIntVal(dwarf::DW_LLE_default_location, 1);
6161db9f3b2SDimitry Andric 
6171db9f3b2SDimitry Andric     encodeULEB128(LocExpression.Expression.Expr.size(), OutLocationSection.OS);
6181db9f3b2SDimitry Andric     OffsetBeforeLocationExpression = OutLocationSection.OS.tell();
6191db9f3b2SDimitry Andric     for (uint64_t *OffsetPtr : LocExpression.Patches)
6201db9f3b2SDimitry Andric       *OffsetPtr += OffsetBeforeLocationExpression;
6211db9f3b2SDimitry Andric 
6221db9f3b2SDimitry Andric     OutLocationSection.OS << StringRef(
6231db9f3b2SDimitry Andric         (const char *)LocExpression.Expression.Expr.data(),
6241db9f3b2SDimitry Andric         LocExpression.Expression.Expr.size());
6251db9f3b2SDimitry Andric   }
6261db9f3b2SDimitry Andric 
6271db9f3b2SDimitry Andric   // Emit the terminator entry.
6281db9f3b2SDimitry Andric   OutLocationSection.emitIntVal(dwarf::DW_LLE_end_of_list, 1);
6291db9f3b2SDimitry Andric   return OffsetBeforeLocationExpression;
6301db9f3b2SDimitry Andric }
6311db9f3b2SDimitry Andric 
emitDebugAddrSection()6321db9f3b2SDimitry Andric Error CompileUnit::emitDebugAddrSection() {
6331db9f3b2SDimitry Andric   if (GlobalData.getOptions().UpdateIndexTablesOnly)
6341db9f3b2SDimitry Andric     return Error::success();
6351db9f3b2SDimitry Andric 
6361db9f3b2SDimitry Andric   if (getVersion() < 5)
6371db9f3b2SDimitry Andric     return Error::success();
6381db9f3b2SDimitry Andric 
6391db9f3b2SDimitry Andric   if (DebugAddrIndexMap.empty())
6401db9f3b2SDimitry Andric     return Error::success();
6411db9f3b2SDimitry Andric 
6421db9f3b2SDimitry Andric   SectionDescriptor &OutAddrSection =
6431db9f3b2SDimitry Andric       getOrCreateSectionDescriptor(DebugSectionKind::DebugAddr);
6441db9f3b2SDimitry Andric 
6451db9f3b2SDimitry Andric   // Emit section header.
6461db9f3b2SDimitry Andric 
6471db9f3b2SDimitry Andric   //   Emit length.
6481db9f3b2SDimitry Andric   OutAddrSection.emitUnitLength(0xBADDEF);
6491db9f3b2SDimitry Andric   uint64_t OffsetAfterSectionLength = OutAddrSection.OS.tell();
6501db9f3b2SDimitry Andric 
6511db9f3b2SDimitry Andric   //   Emit version.
6521db9f3b2SDimitry Andric   OutAddrSection.emitIntVal(5, 2);
6531db9f3b2SDimitry Andric 
6541db9f3b2SDimitry Andric   //   Emit address size.
6551db9f3b2SDimitry Andric   OutAddrSection.emitIntVal(getFormParams().AddrSize, 1);
6561db9f3b2SDimitry Andric 
6571db9f3b2SDimitry Andric   //   Emit segment size.
6581db9f3b2SDimitry Andric   OutAddrSection.emitIntVal(0, 1);
6591db9f3b2SDimitry Andric 
6601db9f3b2SDimitry Andric   // Emit addresses.
6611db9f3b2SDimitry Andric   for (uint64_t AddrValue : DebugAddrIndexMap.getValues())
6621db9f3b2SDimitry Andric     OutAddrSection.emitIntVal(AddrValue, getFormParams().AddrSize);
6631db9f3b2SDimitry Andric 
6641db9f3b2SDimitry Andric   // Patch section length.
6651db9f3b2SDimitry Andric   OutAddrSection.apply(
6661db9f3b2SDimitry Andric       OffsetAfterSectionLength -
6671db9f3b2SDimitry Andric           OutAddrSection.getFormParams().getDwarfOffsetByteSize(),
6681db9f3b2SDimitry Andric       dwarf::DW_FORM_sec_offset,
6691db9f3b2SDimitry Andric       OutAddrSection.OS.tell() - OffsetAfterSectionLength);
6701db9f3b2SDimitry Andric 
6711db9f3b2SDimitry Andric   return Error::success();
6721db9f3b2SDimitry Andric }
6731db9f3b2SDimitry Andric 
cloneAndEmitRanges()6741db9f3b2SDimitry Andric Error CompileUnit::cloneAndEmitRanges() {
6751db9f3b2SDimitry Andric   if (getGlobalData().getOptions().UpdateIndexTablesOnly)
6761db9f3b2SDimitry Andric     return Error::success();
6771db9f3b2SDimitry Andric 
6781db9f3b2SDimitry Andric   // Build set of linked address ranges for unit function ranges.
6791db9f3b2SDimitry Andric   AddressRanges LinkedFunctionRanges;
6801db9f3b2SDimitry Andric   for (const AddressRangeValuePair &Range : getFunctionRanges())
6811db9f3b2SDimitry Andric     LinkedFunctionRanges.insert(
6821db9f3b2SDimitry Andric         {Range.Range.start() + Range.Value, Range.Range.end() + Range.Value});
6831db9f3b2SDimitry Andric 
6841db9f3b2SDimitry Andric   emitAranges(LinkedFunctionRanges);
6851db9f3b2SDimitry Andric 
6861db9f3b2SDimitry Andric   if (getOrigUnit().getVersion() < 5) {
6871db9f3b2SDimitry Andric     cloneAndEmitRangeList(DebugSectionKind::DebugRange, LinkedFunctionRanges);
6881db9f3b2SDimitry Andric     return Error::success();
6891db9f3b2SDimitry Andric   }
6901db9f3b2SDimitry Andric 
6911db9f3b2SDimitry Andric   cloneAndEmitRangeList(DebugSectionKind::DebugRngLists, LinkedFunctionRanges);
6921db9f3b2SDimitry Andric   return Error::success();
6931db9f3b2SDimitry Andric }
6941db9f3b2SDimitry Andric 
cloneAndEmitRangeList(DebugSectionKind RngSectionKind,AddressRanges & LinkedFunctionRanges)6951db9f3b2SDimitry Andric void CompileUnit::cloneAndEmitRangeList(DebugSectionKind RngSectionKind,
6961db9f3b2SDimitry Andric                                         AddressRanges &LinkedFunctionRanges) {
6971db9f3b2SDimitry Andric   SectionDescriptor &DebugInfoSection =
6981db9f3b2SDimitry Andric       getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
6991db9f3b2SDimitry Andric   SectionDescriptor &OutRangeSection =
7001db9f3b2SDimitry Andric       getOrCreateSectionDescriptor(RngSectionKind);
7011db9f3b2SDimitry Andric 
7021db9f3b2SDimitry Andric   if (!DebugInfoSection.ListDebugRangePatch.empty()) {
7031db9f3b2SDimitry Andric     std::optional<AddressRangeValuePair> CachedRange;
7041db9f3b2SDimitry Andric     uint64_t OffsetAfterUnitLength = emitRangeListHeader(OutRangeSection);
7051db9f3b2SDimitry Andric 
7061db9f3b2SDimitry Andric     DebugRangePatch *CompileUnitRangePtr = nullptr;
7071db9f3b2SDimitry Andric     DebugInfoSection.ListDebugRangePatch.forEach([&](DebugRangePatch &Patch) {
7081db9f3b2SDimitry Andric       if (Patch.IsCompileUnitRanges) {
7091db9f3b2SDimitry Andric         CompileUnitRangePtr = &Patch;
7101db9f3b2SDimitry Andric       } else {
7111db9f3b2SDimitry Andric         // Get ranges from the source DWARF corresponding to the current
7121db9f3b2SDimitry Andric         // attribute.
7131db9f3b2SDimitry Andric         AddressRanges LinkedRanges;
7141db9f3b2SDimitry Andric         uint64_t InputDebugRangesSectionOffset = DebugInfoSection.getIntVal(
7151db9f3b2SDimitry Andric             Patch.PatchOffset,
7161db9f3b2SDimitry Andric             DebugInfoSection.getFormParams().getDwarfOffsetByteSize());
7171db9f3b2SDimitry Andric         if (Expected<DWARFAddressRangesVector> InputRanges =
7181db9f3b2SDimitry Andric                 getOrigUnit().findRnglistFromOffset(
7191db9f3b2SDimitry Andric                     InputDebugRangesSectionOffset)) {
7201db9f3b2SDimitry Andric           // Apply relocation adjustment.
7211db9f3b2SDimitry Andric           for (const auto &Range : *InputRanges) {
7221db9f3b2SDimitry Andric             if (!CachedRange || !CachedRange->Range.contains(Range.LowPC))
7231db9f3b2SDimitry Andric               CachedRange =
7241db9f3b2SDimitry Andric                   getFunctionRanges().getRangeThatContains(Range.LowPC);
7251db9f3b2SDimitry Andric 
7261db9f3b2SDimitry Andric             // All range entries should lie in the function range.
7271db9f3b2SDimitry Andric             if (!CachedRange) {
7281db9f3b2SDimitry Andric               warn("inconsistent range data.");
7291db9f3b2SDimitry Andric               continue;
7301db9f3b2SDimitry Andric             }
7311db9f3b2SDimitry Andric 
7321db9f3b2SDimitry Andric             // Store range for emiting.
7331db9f3b2SDimitry Andric             LinkedRanges.insert({Range.LowPC + CachedRange->Value,
7341db9f3b2SDimitry Andric                                  Range.HighPC + CachedRange->Value});
7351db9f3b2SDimitry Andric           }
7361db9f3b2SDimitry Andric         } else {
7371db9f3b2SDimitry Andric           llvm::consumeError(InputRanges.takeError());
7381db9f3b2SDimitry Andric           warn("invalid range list ignored.");
7391db9f3b2SDimitry Andric         }
7401db9f3b2SDimitry Andric 
7411db9f3b2SDimitry Andric         // Emit linked ranges.
7421db9f3b2SDimitry Andric         DebugInfoSection.apply(Patch.PatchOffset, dwarf::DW_FORM_sec_offset,
7431db9f3b2SDimitry Andric                                OutRangeSection.OS.tell());
7441db9f3b2SDimitry Andric         emitRangeListFragment(LinkedRanges, OutRangeSection);
7451db9f3b2SDimitry Andric       }
7461db9f3b2SDimitry Andric     });
7471db9f3b2SDimitry Andric 
7481db9f3b2SDimitry Andric     if (CompileUnitRangePtr != nullptr) {
7491db9f3b2SDimitry Andric       // Emit compile unit ranges last to be binary compatible with classic
7501db9f3b2SDimitry Andric       // dsymutil.
7511db9f3b2SDimitry Andric       DebugInfoSection.apply(CompileUnitRangePtr->PatchOffset,
7521db9f3b2SDimitry Andric                              dwarf::DW_FORM_sec_offset,
7531db9f3b2SDimitry Andric                              OutRangeSection.OS.tell());
7541db9f3b2SDimitry Andric       emitRangeListFragment(LinkedFunctionRanges, OutRangeSection);
7551db9f3b2SDimitry Andric     }
7561db9f3b2SDimitry Andric 
7571db9f3b2SDimitry Andric     if (OffsetAfterUnitLength > 0) {
7581db9f3b2SDimitry Andric       assert(OffsetAfterUnitLength -
7591db9f3b2SDimitry Andric                  OutRangeSection.getFormParams().getDwarfOffsetByteSize() <
7601db9f3b2SDimitry Andric              OffsetAfterUnitLength);
7611db9f3b2SDimitry Andric       OutRangeSection.apply(
7621db9f3b2SDimitry Andric           OffsetAfterUnitLength -
7631db9f3b2SDimitry Andric               OutRangeSection.getFormParams().getDwarfOffsetByteSize(),
7641db9f3b2SDimitry Andric           dwarf::DW_FORM_sec_offset,
7651db9f3b2SDimitry Andric           OutRangeSection.OS.tell() - OffsetAfterUnitLength);
7661db9f3b2SDimitry Andric     }
7671db9f3b2SDimitry Andric   }
7681db9f3b2SDimitry Andric }
7691db9f3b2SDimitry Andric 
emitRangeListHeader(SectionDescriptor & OutRangeSection)7701db9f3b2SDimitry Andric uint64_t CompileUnit::emitRangeListHeader(SectionDescriptor &OutRangeSection) {
7711db9f3b2SDimitry Andric   if (OutRangeSection.getFormParams().Version < 5)
7721db9f3b2SDimitry Andric     return 0;
7731db9f3b2SDimitry Andric 
7741db9f3b2SDimitry Andric   // unit_length.
7751db9f3b2SDimitry Andric   OutRangeSection.emitUnitLength(0xBADDEF);
7761db9f3b2SDimitry Andric   uint64_t OffsetAfterUnitLength = OutRangeSection.OS.tell();
7771db9f3b2SDimitry Andric 
7781db9f3b2SDimitry Andric   // Version.
7791db9f3b2SDimitry Andric   OutRangeSection.emitIntVal(5, 2);
7801db9f3b2SDimitry Andric 
7811db9f3b2SDimitry Andric   // Address size.
7821db9f3b2SDimitry Andric   OutRangeSection.emitIntVal(OutRangeSection.getFormParams().AddrSize, 1);
7831db9f3b2SDimitry Andric 
7841db9f3b2SDimitry Andric   // Seg_size
7851db9f3b2SDimitry Andric   OutRangeSection.emitIntVal(0, 1);
7861db9f3b2SDimitry Andric 
7871db9f3b2SDimitry Andric   // Offset entry count
7881db9f3b2SDimitry Andric   OutRangeSection.emitIntVal(0, 4);
7891db9f3b2SDimitry Andric 
7901db9f3b2SDimitry Andric   return OffsetAfterUnitLength;
7911db9f3b2SDimitry Andric }
7921db9f3b2SDimitry Andric 
emitRangeListFragment(const AddressRanges & LinkedRanges,SectionDescriptor & OutRangeSection)7931db9f3b2SDimitry Andric void CompileUnit::emitRangeListFragment(const AddressRanges &LinkedRanges,
7941db9f3b2SDimitry Andric                                         SectionDescriptor &OutRangeSection) {
7951db9f3b2SDimitry Andric   if (OutRangeSection.getFormParams().Version < 5) {
7961db9f3b2SDimitry Andric     // Emit ranges.
7971db9f3b2SDimitry Andric     uint64_t BaseAddress = 0;
7981db9f3b2SDimitry Andric     if (std::optional<uint64_t> LowPC = getLowPc())
7991db9f3b2SDimitry Andric       BaseAddress = *LowPC;
8001db9f3b2SDimitry Andric 
8011db9f3b2SDimitry Andric     for (const AddressRange &Range : LinkedRanges) {
8021db9f3b2SDimitry Andric       OutRangeSection.emitIntVal(Range.start() - BaseAddress,
8031db9f3b2SDimitry Andric                                  OutRangeSection.getFormParams().AddrSize);
8041db9f3b2SDimitry Andric       OutRangeSection.emitIntVal(Range.end() - BaseAddress,
8051db9f3b2SDimitry Andric                                  OutRangeSection.getFormParams().AddrSize);
8061db9f3b2SDimitry Andric     }
8071db9f3b2SDimitry Andric 
8081db9f3b2SDimitry Andric     // Add the terminator entry.
8091db9f3b2SDimitry Andric     OutRangeSection.emitIntVal(0, OutRangeSection.getFormParams().AddrSize);
8101db9f3b2SDimitry Andric     OutRangeSection.emitIntVal(0, OutRangeSection.getFormParams().AddrSize);
8111db9f3b2SDimitry Andric     return;
8121db9f3b2SDimitry Andric   }
8131db9f3b2SDimitry Andric 
8141db9f3b2SDimitry Andric   std::optional<uint64_t> BaseAddress;
8151db9f3b2SDimitry Andric   for (const AddressRange &Range : LinkedRanges) {
8161db9f3b2SDimitry Andric     if (!BaseAddress) {
8171db9f3b2SDimitry Andric       BaseAddress = Range.start();
8181db9f3b2SDimitry Andric 
8191db9f3b2SDimitry Andric       // Emit base address.
8201db9f3b2SDimitry Andric       OutRangeSection.emitIntVal(dwarf::DW_RLE_base_addressx, 1);
8211db9f3b2SDimitry Andric       encodeULEB128(getDebugAddrIndex(*BaseAddress), OutRangeSection.OS);
8221db9f3b2SDimitry Andric     }
8231db9f3b2SDimitry Andric 
8241db9f3b2SDimitry Andric     // Emit type of entry.
8251db9f3b2SDimitry Andric     OutRangeSection.emitIntVal(dwarf::DW_RLE_offset_pair, 1);
8261db9f3b2SDimitry Andric 
8271db9f3b2SDimitry Andric     // Emit start offset relative to base address.
8281db9f3b2SDimitry Andric     encodeULEB128(Range.start() - *BaseAddress, OutRangeSection.OS);
8291db9f3b2SDimitry Andric 
8301db9f3b2SDimitry Andric     // Emit end offset relative to base address.
8311db9f3b2SDimitry Andric     encodeULEB128(Range.end() - *BaseAddress, OutRangeSection.OS);
8321db9f3b2SDimitry Andric   }
8331db9f3b2SDimitry Andric 
8341db9f3b2SDimitry Andric   // Emit the terminator entry.
8351db9f3b2SDimitry Andric   OutRangeSection.emitIntVal(dwarf::DW_RLE_end_of_list, 1);
8361db9f3b2SDimitry Andric }
8371db9f3b2SDimitry Andric 
emitAranges(AddressRanges & LinkedFunctionRanges)8381db9f3b2SDimitry Andric void CompileUnit::emitAranges(AddressRanges &LinkedFunctionRanges) {
8391db9f3b2SDimitry Andric   if (LinkedFunctionRanges.empty())
8401db9f3b2SDimitry Andric     return;
8411db9f3b2SDimitry Andric 
8421db9f3b2SDimitry Andric   SectionDescriptor &DebugInfoSection =
8431db9f3b2SDimitry Andric       getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
8441db9f3b2SDimitry Andric   SectionDescriptor &OutArangesSection =
8451db9f3b2SDimitry Andric       getOrCreateSectionDescriptor(DebugSectionKind::DebugARanges);
8461db9f3b2SDimitry Andric 
8471db9f3b2SDimitry Andric   // Emit Header.
8481db9f3b2SDimitry Andric   unsigned HeaderSize =
8491db9f3b2SDimitry Andric       sizeof(int32_t) + // Size of contents (w/o this field
8501db9f3b2SDimitry Andric       sizeof(int16_t) + // DWARF ARange version number
8511db9f3b2SDimitry Andric       sizeof(int32_t) + // Offset of CU in the .debug_info section
8521db9f3b2SDimitry Andric       sizeof(int8_t) +  // Pointer Size (in bytes)
8531db9f3b2SDimitry Andric       sizeof(int8_t);   // Segment Size (in bytes)
8541db9f3b2SDimitry Andric 
8551db9f3b2SDimitry Andric   unsigned TupleSize = OutArangesSection.getFormParams().AddrSize * 2;
8561db9f3b2SDimitry Andric   unsigned Padding = offsetToAlignment(HeaderSize, Align(TupleSize));
8571db9f3b2SDimitry Andric 
8581db9f3b2SDimitry Andric   OutArangesSection.emitOffset(0xBADDEF); // Aranges length
8591db9f3b2SDimitry Andric   uint64_t OffsetAfterArangesLengthField = OutArangesSection.OS.tell();
8601db9f3b2SDimitry Andric 
8611db9f3b2SDimitry Andric   OutArangesSection.emitIntVal(dwarf::DW_ARANGES_VERSION, 2); // Version number
8621db9f3b2SDimitry Andric   OutArangesSection.notePatch(
8631db9f3b2SDimitry Andric       DebugOffsetPatch{OutArangesSection.OS.tell(), &DebugInfoSection});
8641db9f3b2SDimitry Andric   OutArangesSection.emitOffset(0xBADDEF); // Corresponding unit's offset
8651db9f3b2SDimitry Andric   OutArangesSection.emitIntVal(OutArangesSection.getFormParams().AddrSize,
8661db9f3b2SDimitry Andric                                1);    // Address size
8671db9f3b2SDimitry Andric   OutArangesSection.emitIntVal(0, 1); // Segment size
8681db9f3b2SDimitry Andric 
8691db9f3b2SDimitry Andric   for (size_t Idx = 0; Idx < Padding; Idx++)
8701db9f3b2SDimitry Andric     OutArangesSection.emitIntVal(0, 1); // Padding
8711db9f3b2SDimitry Andric 
8721db9f3b2SDimitry Andric   // Emit linked ranges.
8731db9f3b2SDimitry Andric   for (const AddressRange &Range : LinkedFunctionRanges) {
8741db9f3b2SDimitry Andric     OutArangesSection.emitIntVal(Range.start(),
8751db9f3b2SDimitry Andric                                  OutArangesSection.getFormParams().AddrSize);
8761db9f3b2SDimitry Andric     OutArangesSection.emitIntVal(Range.end() - Range.start(),
8771db9f3b2SDimitry Andric                                  OutArangesSection.getFormParams().AddrSize);
8781db9f3b2SDimitry Andric   }
8791db9f3b2SDimitry Andric 
8801db9f3b2SDimitry Andric   // Emit terminator.
8811db9f3b2SDimitry Andric   OutArangesSection.emitIntVal(0, OutArangesSection.getFormParams().AddrSize);
8821db9f3b2SDimitry Andric   OutArangesSection.emitIntVal(0, OutArangesSection.getFormParams().AddrSize);
8831db9f3b2SDimitry Andric 
8841db9f3b2SDimitry Andric   uint64_t OffsetAfterArangesEnd = OutArangesSection.OS.tell();
8851db9f3b2SDimitry Andric 
8861db9f3b2SDimitry Andric   // Update Aranges lentgh.
8871db9f3b2SDimitry Andric   OutArangesSection.apply(
8881db9f3b2SDimitry Andric       OffsetAfterArangesLengthField -
8891db9f3b2SDimitry Andric           OutArangesSection.getFormParams().getDwarfOffsetByteSize(),
8901db9f3b2SDimitry Andric       dwarf::DW_FORM_sec_offset,
8911db9f3b2SDimitry Andric       OffsetAfterArangesEnd - OffsetAfterArangesLengthField);
8921db9f3b2SDimitry Andric }
8931db9f3b2SDimitry Andric 
cloneAndEmitDebugMacro()8941db9f3b2SDimitry Andric Error CompileUnit::cloneAndEmitDebugMacro() {
8951db9f3b2SDimitry Andric   if (getOutUnitDIE() == nullptr)
8961db9f3b2SDimitry Andric     return Error::success();
8971db9f3b2SDimitry Andric 
8981db9f3b2SDimitry Andric   DWARFUnit &OrigUnit = getOrigUnit();
8991db9f3b2SDimitry Andric   DWARFDie OrigUnitDie = OrigUnit.getUnitDIE();
9001db9f3b2SDimitry Andric 
9011db9f3b2SDimitry Andric   // Check for .debug_macro table.
9021db9f3b2SDimitry Andric   if (std::optional<uint64_t> MacroAttr =
9031db9f3b2SDimitry Andric           dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macros))) {
9041db9f3b2SDimitry Andric     if (const DWARFDebugMacro *Table =
9051db9f3b2SDimitry Andric             getContaingFile().Dwarf->getDebugMacro()) {
9061db9f3b2SDimitry Andric       emitMacroTableImpl(Table, *MacroAttr, true);
9071db9f3b2SDimitry Andric     }
9081db9f3b2SDimitry Andric   }
9091db9f3b2SDimitry Andric 
9101db9f3b2SDimitry Andric   // Check for .debug_macinfo table.
9111db9f3b2SDimitry Andric   if (std::optional<uint64_t> MacroAttr =
9121db9f3b2SDimitry Andric           dwarf::toSectionOffset(OrigUnitDie.find(dwarf::DW_AT_macro_info))) {
9131db9f3b2SDimitry Andric     if (const DWARFDebugMacro *Table =
9141db9f3b2SDimitry Andric             getContaingFile().Dwarf->getDebugMacinfo()) {
9151db9f3b2SDimitry Andric       emitMacroTableImpl(Table, *MacroAttr, false);
9161db9f3b2SDimitry Andric     }
9171db9f3b2SDimitry Andric   }
9181db9f3b2SDimitry Andric 
9191db9f3b2SDimitry Andric   return Error::success();
9201db9f3b2SDimitry Andric }
9211db9f3b2SDimitry Andric 
emitMacroTableImpl(const DWARFDebugMacro * MacroTable,uint64_t OffsetToMacroTable,bool hasDWARFv5Header)9221db9f3b2SDimitry Andric void CompileUnit::emitMacroTableImpl(const DWARFDebugMacro *MacroTable,
9231db9f3b2SDimitry Andric                                      uint64_t OffsetToMacroTable,
9241db9f3b2SDimitry Andric                                      bool hasDWARFv5Header) {
9251db9f3b2SDimitry Andric   SectionDescriptor &OutSection =
9261db9f3b2SDimitry Andric       hasDWARFv5Header
9271db9f3b2SDimitry Andric           ? getOrCreateSectionDescriptor(DebugSectionKind::DebugMacro)
9281db9f3b2SDimitry Andric           : getOrCreateSectionDescriptor(DebugSectionKind::DebugMacinfo);
9291db9f3b2SDimitry Andric 
9301db9f3b2SDimitry Andric   bool DefAttributeIsReported = false;
9311db9f3b2SDimitry Andric   bool UndefAttributeIsReported = false;
9321db9f3b2SDimitry Andric   bool ImportAttributeIsReported = false;
9331db9f3b2SDimitry Andric 
9341db9f3b2SDimitry Andric   for (const DWARFDebugMacro::MacroList &List : MacroTable->MacroLists) {
9351db9f3b2SDimitry Andric     if (OffsetToMacroTable == List.Offset) {
9361db9f3b2SDimitry Andric       // Write DWARFv5 header.
9371db9f3b2SDimitry Andric       if (hasDWARFv5Header) {
9381db9f3b2SDimitry Andric         // Write header version.
9391db9f3b2SDimitry Andric         OutSection.emitIntVal(List.Header.Version, sizeof(List.Header.Version));
9401db9f3b2SDimitry Andric 
9411db9f3b2SDimitry Andric         uint8_t Flags = List.Header.Flags;
9421db9f3b2SDimitry Andric 
9431db9f3b2SDimitry Andric         // Check for OPCODE_OPERANDS_TABLE.
9441db9f3b2SDimitry Andric         if (Flags &
9451db9f3b2SDimitry Andric             DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE) {
9461db9f3b2SDimitry Andric           Flags &=
9471db9f3b2SDimitry Andric               ~DWARFDebugMacro::HeaderFlagMask::MACRO_OPCODE_OPERANDS_TABLE;
9481db9f3b2SDimitry Andric           warn("opcode_operands_table is not supported yet.");
9491db9f3b2SDimitry Andric         }
9501db9f3b2SDimitry Andric 
9511db9f3b2SDimitry Andric         // Check for DEBUG_LINE_OFFSET.
9521db9f3b2SDimitry Andric         std::optional<uint64_t> StmtListOffset;
9531db9f3b2SDimitry Andric         if (Flags & DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET) {
9541db9f3b2SDimitry Andric           // Get offset to the line table from the cloned compile unit.
9551db9f3b2SDimitry Andric           for (auto &V : getOutUnitDIE()->values()) {
9561db9f3b2SDimitry Andric             if (V.getAttribute() == dwarf::DW_AT_stmt_list) {
9571db9f3b2SDimitry Andric               StmtListOffset = V.getDIEInteger().getValue();
9581db9f3b2SDimitry Andric               break;
9591db9f3b2SDimitry Andric             }
9601db9f3b2SDimitry Andric           }
9611db9f3b2SDimitry Andric 
9621db9f3b2SDimitry Andric           if (!StmtListOffset) {
9631db9f3b2SDimitry Andric             Flags &= ~DWARFDebugMacro::HeaderFlagMask::MACRO_DEBUG_LINE_OFFSET;
9641db9f3b2SDimitry Andric             warn("couldn`t find line table for macro table.");
9651db9f3b2SDimitry Andric           }
9661db9f3b2SDimitry Andric         }
9671db9f3b2SDimitry Andric 
9681db9f3b2SDimitry Andric         // Write flags.
9691db9f3b2SDimitry Andric         OutSection.emitIntVal(Flags, sizeof(Flags));
9701db9f3b2SDimitry Andric 
9711db9f3b2SDimitry Andric         // Write offset to line table.
9721db9f3b2SDimitry Andric         if (StmtListOffset) {
9731db9f3b2SDimitry Andric           OutSection.notePatch(DebugOffsetPatch{
9741db9f3b2SDimitry Andric               OutSection.OS.tell(),
9751db9f3b2SDimitry Andric               &getOrCreateSectionDescriptor(DebugSectionKind::DebugLine)});
9761db9f3b2SDimitry Andric           // TODO: check that List.Header.getOffsetByteSize() and
9771db9f3b2SDimitry Andric           // DebugOffsetPatch agree on size.
9781db9f3b2SDimitry Andric           OutSection.emitIntVal(0xBADDEF, List.Header.getOffsetByteSize());
9791db9f3b2SDimitry Andric         }
9801db9f3b2SDimitry Andric       }
9811db9f3b2SDimitry Andric 
9821db9f3b2SDimitry Andric       // Write macro entries.
9831db9f3b2SDimitry Andric       for (const DWARFDebugMacro::Entry &MacroEntry : List.Macros) {
9841db9f3b2SDimitry Andric         if (MacroEntry.Type == 0) {
9851db9f3b2SDimitry Andric           encodeULEB128(MacroEntry.Type, OutSection.OS);
9861db9f3b2SDimitry Andric           continue;
9871db9f3b2SDimitry Andric         }
9881db9f3b2SDimitry Andric 
9891db9f3b2SDimitry Andric         uint8_t MacroType = MacroEntry.Type;
9901db9f3b2SDimitry Andric         switch (MacroType) {
9911db9f3b2SDimitry Andric         default: {
9921db9f3b2SDimitry Andric           bool HasVendorSpecificExtension =
9931db9f3b2SDimitry Andric               (!hasDWARFv5Header &&
9941db9f3b2SDimitry Andric                MacroType == dwarf::DW_MACINFO_vendor_ext) ||
9951db9f3b2SDimitry Andric               (hasDWARFv5Header && (MacroType >= dwarf::DW_MACRO_lo_user &&
9961db9f3b2SDimitry Andric                                     MacroType <= dwarf::DW_MACRO_hi_user));
9971db9f3b2SDimitry Andric 
9981db9f3b2SDimitry Andric           if (HasVendorSpecificExtension) {
9991db9f3b2SDimitry Andric             // Write macinfo type.
10001db9f3b2SDimitry Andric             OutSection.emitIntVal(MacroType, 1);
10011db9f3b2SDimitry Andric 
10021db9f3b2SDimitry Andric             // Write vendor extension constant.
10031db9f3b2SDimitry Andric             encodeULEB128(MacroEntry.ExtConstant, OutSection.OS);
10041db9f3b2SDimitry Andric 
10051db9f3b2SDimitry Andric             // Write vendor extension string.
10061db9f3b2SDimitry Andric             OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.ExtStr);
10071db9f3b2SDimitry Andric           } else
10081db9f3b2SDimitry Andric             warn("unknown macro type. skip.");
10091db9f3b2SDimitry Andric         } break;
10101db9f3b2SDimitry Andric         // debug_macro and debug_macinfo share some common encodings.
10111db9f3b2SDimitry Andric         // DW_MACRO_define     == DW_MACINFO_define
10121db9f3b2SDimitry Andric         // DW_MACRO_undef      == DW_MACINFO_undef
10131db9f3b2SDimitry Andric         // DW_MACRO_start_file == DW_MACINFO_start_file
10141db9f3b2SDimitry Andric         // DW_MACRO_end_file   == DW_MACINFO_end_file
10151db9f3b2SDimitry Andric         // For readibility/uniformity we are using DW_MACRO_*.
10161db9f3b2SDimitry Andric         case dwarf::DW_MACRO_define:
10171db9f3b2SDimitry Andric         case dwarf::DW_MACRO_undef: {
10181db9f3b2SDimitry Andric           // Write macinfo type.
10191db9f3b2SDimitry Andric           OutSection.emitIntVal(MacroType, 1);
10201db9f3b2SDimitry Andric 
10211db9f3b2SDimitry Andric           // Write source line.
10221db9f3b2SDimitry Andric           encodeULEB128(MacroEntry.Line, OutSection.OS);
10231db9f3b2SDimitry Andric 
10241db9f3b2SDimitry Andric           // Write macro string.
10251db9f3b2SDimitry Andric           OutSection.emitString(dwarf::DW_FORM_string, MacroEntry.MacroStr);
10261db9f3b2SDimitry Andric         } break;
10271db9f3b2SDimitry Andric         case dwarf::DW_MACRO_define_strp:
10281db9f3b2SDimitry Andric         case dwarf::DW_MACRO_undef_strp:
10291db9f3b2SDimitry Andric         case dwarf::DW_MACRO_define_strx:
10301db9f3b2SDimitry Andric         case dwarf::DW_MACRO_undef_strx: {
10311db9f3b2SDimitry Andric           // DW_MACRO_*_strx forms are not supported currently.
10321db9f3b2SDimitry Andric           // Convert to *_strp.
10331db9f3b2SDimitry Andric           switch (MacroType) {
10341db9f3b2SDimitry Andric           case dwarf::DW_MACRO_define_strx: {
10351db9f3b2SDimitry Andric             MacroType = dwarf::DW_MACRO_define_strp;
10361db9f3b2SDimitry Andric             if (!DefAttributeIsReported) {
10371db9f3b2SDimitry Andric               warn("DW_MACRO_define_strx unsupported yet. Convert to "
10381db9f3b2SDimitry Andric                    "DW_MACRO_define_strp.");
10391db9f3b2SDimitry Andric               DefAttributeIsReported = true;
10401db9f3b2SDimitry Andric             }
10411db9f3b2SDimitry Andric           } break;
10421db9f3b2SDimitry Andric           case dwarf::DW_MACRO_undef_strx: {
10431db9f3b2SDimitry Andric             MacroType = dwarf::DW_MACRO_undef_strp;
10441db9f3b2SDimitry Andric             if (!UndefAttributeIsReported) {
10451db9f3b2SDimitry Andric               warn("DW_MACRO_undef_strx unsupported yet. Convert to "
10461db9f3b2SDimitry Andric                    "DW_MACRO_undef_strp.");
10471db9f3b2SDimitry Andric               UndefAttributeIsReported = true;
10481db9f3b2SDimitry Andric             }
10491db9f3b2SDimitry Andric           } break;
10501db9f3b2SDimitry Andric           default:
10511db9f3b2SDimitry Andric             // Nothing to do.
10521db9f3b2SDimitry Andric             break;
10531db9f3b2SDimitry Andric           }
10541db9f3b2SDimitry Andric 
10551db9f3b2SDimitry Andric           // Write macinfo type.
10561db9f3b2SDimitry Andric           OutSection.emitIntVal(MacroType, 1);
10571db9f3b2SDimitry Andric 
10581db9f3b2SDimitry Andric           // Write source line.
10591db9f3b2SDimitry Andric           encodeULEB128(MacroEntry.Line, OutSection.OS);
10601db9f3b2SDimitry Andric 
10611db9f3b2SDimitry Andric           // Write macro string.
10621db9f3b2SDimitry Andric           OutSection.emitString(dwarf::DW_FORM_strp, MacroEntry.MacroStr);
10631db9f3b2SDimitry Andric           break;
10641db9f3b2SDimitry Andric         }
10651db9f3b2SDimitry Andric         case dwarf::DW_MACRO_start_file: {
10661db9f3b2SDimitry Andric           // Write macinfo type.
10671db9f3b2SDimitry Andric           OutSection.emitIntVal(MacroType, 1);
10681db9f3b2SDimitry Andric           // Write source line.
10691db9f3b2SDimitry Andric           encodeULEB128(MacroEntry.Line, OutSection.OS);
10701db9f3b2SDimitry Andric           // Write source file id.
10711db9f3b2SDimitry Andric           encodeULEB128(MacroEntry.File, OutSection.OS);
10721db9f3b2SDimitry Andric         } break;
10731db9f3b2SDimitry Andric         case dwarf::DW_MACRO_end_file: {
10741db9f3b2SDimitry Andric           // Write macinfo type.
10751db9f3b2SDimitry Andric           OutSection.emitIntVal(MacroType, 1);
10761db9f3b2SDimitry Andric         } break;
10771db9f3b2SDimitry Andric         case dwarf::DW_MACRO_import:
10781db9f3b2SDimitry Andric         case dwarf::DW_MACRO_import_sup: {
10791db9f3b2SDimitry Andric           if (!ImportAttributeIsReported) {
10801db9f3b2SDimitry Andric             warn("DW_MACRO_import and DW_MACRO_import_sup are unsupported "
10811db9f3b2SDimitry Andric                  "yet. remove.");
10821db9f3b2SDimitry Andric             ImportAttributeIsReported = true;
10831db9f3b2SDimitry Andric           }
10841db9f3b2SDimitry Andric         } break;
10851db9f3b2SDimitry Andric         }
10861db9f3b2SDimitry Andric       }
10871db9f3b2SDimitry Andric 
10881db9f3b2SDimitry Andric       return;
10891db9f3b2SDimitry Andric     }
10901db9f3b2SDimitry Andric   }
10911db9f3b2SDimitry Andric }
10921db9f3b2SDimitry Andric 
cloneDieAttrExpression(const DWARFExpression & InputExpression,SmallVectorImpl<uint8_t> & OutputExpression,SectionDescriptor & Section,std::optional<int64_t> VarAddressAdjustment,OffsetsPtrVector & PatchesOffsets)10931db9f3b2SDimitry Andric void CompileUnit::cloneDieAttrExpression(
10941db9f3b2SDimitry Andric     const DWARFExpression &InputExpression,
10951db9f3b2SDimitry Andric     SmallVectorImpl<uint8_t> &OutputExpression, SectionDescriptor &Section,
10961db9f3b2SDimitry Andric     std::optional<int64_t> VarAddressAdjustment,
10971db9f3b2SDimitry Andric     OffsetsPtrVector &PatchesOffsets) {
10981db9f3b2SDimitry Andric   using Encoding = DWARFExpression::Operation::Encoding;
10991db9f3b2SDimitry Andric 
11001db9f3b2SDimitry Andric   DWARFUnit &OrigUnit = getOrigUnit();
11011db9f3b2SDimitry Andric   uint8_t OrigAddressByteSize = OrigUnit.getAddressByteSize();
11021db9f3b2SDimitry Andric 
11031db9f3b2SDimitry Andric   uint64_t OpOffset = 0;
11041db9f3b2SDimitry Andric   for (auto &Op : InputExpression) {
11051db9f3b2SDimitry Andric     auto Desc = Op.getDescription();
11061db9f3b2SDimitry Andric     // DW_OP_const_type is variable-length and has 3
11071db9f3b2SDimitry Andric     // operands. Thus far we only support 2.
11081db9f3b2SDimitry Andric     if ((Desc.Op.size() == 2 && Desc.Op[0] == Encoding::BaseTypeRef) ||
11091db9f3b2SDimitry Andric         (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&
11101db9f3b2SDimitry Andric          Desc.Op[0] != Encoding::Size1))
11111db9f3b2SDimitry Andric       warn("unsupported DW_OP encoding.");
11121db9f3b2SDimitry Andric 
11131db9f3b2SDimitry Andric     if ((Desc.Op.size() == 1 && Desc.Op[0] == Encoding::BaseTypeRef) ||
11141db9f3b2SDimitry Andric         (Desc.Op.size() == 2 && Desc.Op[1] == Encoding::BaseTypeRef &&
11151db9f3b2SDimitry Andric          Desc.Op[0] == Encoding::Size1)) {
11161db9f3b2SDimitry Andric       // This code assumes that the other non-typeref operand fits into 1 byte.
11171db9f3b2SDimitry Andric       assert(OpOffset < Op.getEndOffset());
11181db9f3b2SDimitry Andric       uint32_t ULEBsize = Op.getEndOffset() - OpOffset - 1;
11191db9f3b2SDimitry Andric       assert(ULEBsize <= 16);
11201db9f3b2SDimitry Andric 
11211db9f3b2SDimitry Andric       // Copy over the operation.
11221db9f3b2SDimitry Andric       assert(!Op.getSubCode() && "SubOps not yet supported");
11231db9f3b2SDimitry Andric       OutputExpression.push_back(Op.getCode());
11241db9f3b2SDimitry Andric       uint64_t RefOffset;
11251db9f3b2SDimitry Andric       if (Desc.Op.size() == 1) {
11261db9f3b2SDimitry Andric         RefOffset = Op.getRawOperand(0);
11271db9f3b2SDimitry Andric       } else {
11281db9f3b2SDimitry Andric         OutputExpression.push_back(Op.getRawOperand(0));
11291db9f3b2SDimitry Andric         RefOffset = Op.getRawOperand(1);
11301db9f3b2SDimitry Andric       }
11311db9f3b2SDimitry Andric       uint8_t ULEB[16];
11321db9f3b2SDimitry Andric       uint32_t Offset = 0;
11331db9f3b2SDimitry Andric       unsigned RealSize = 0;
11341db9f3b2SDimitry Andric       // Look up the base type. For DW_OP_convert, the operand may be 0 to
11351db9f3b2SDimitry Andric       // instead indicate the generic type. The same holds for
11361db9f3b2SDimitry Andric       // DW_OP_reinterpret, which is currently not supported.
11371db9f3b2SDimitry Andric       if (RefOffset > 0 || Op.getCode() != dwarf::DW_OP_convert) {
11381db9f3b2SDimitry Andric         RefOffset += OrigUnit.getOffset();
11391db9f3b2SDimitry Andric         uint32_t RefDieIdx = 0;
11401db9f3b2SDimitry Andric         if (std::optional<uint32_t> Idx =
11411db9f3b2SDimitry Andric                 OrigUnit.getDIEIndexForOffset(RefOffset))
11421db9f3b2SDimitry Andric           RefDieIdx = *Idx;
11431db9f3b2SDimitry Andric 
11441db9f3b2SDimitry Andric         // Use fixed size for ULEB128 data, since we need to update that size
11451db9f3b2SDimitry Andric         // later with the proper offsets. Use 5 for DWARF32, 9 for DWARF64.
11461db9f3b2SDimitry Andric         ULEBsize = getFormParams().getDwarfOffsetByteSize() + 1;
11471db9f3b2SDimitry Andric 
11481db9f3b2SDimitry Andric         RealSize = encodeULEB128(0xBADDEF, ULEB, ULEBsize);
11491db9f3b2SDimitry Andric 
11501db9f3b2SDimitry Andric         Section.notePatchWithOffsetUpdate(
11511db9f3b2SDimitry Andric             DebugULEB128DieRefPatch(OutputExpression.size(), this, this,
11521db9f3b2SDimitry Andric                                     RefDieIdx),
11531db9f3b2SDimitry Andric             PatchesOffsets);
11541db9f3b2SDimitry Andric       } else
11551db9f3b2SDimitry Andric         RealSize = encodeULEB128(Offset, ULEB, ULEBsize);
11561db9f3b2SDimitry Andric 
11571db9f3b2SDimitry Andric       if (RealSize > ULEBsize) {
11581db9f3b2SDimitry Andric         // Emit the generic type as a fallback.
11591db9f3b2SDimitry Andric         RealSize = encodeULEB128(0, ULEB, ULEBsize);
11601db9f3b2SDimitry Andric         warn("base type ref doesn't fit.");
11611db9f3b2SDimitry Andric       }
11621db9f3b2SDimitry Andric       assert(RealSize == ULEBsize && "padding failed");
11631db9f3b2SDimitry Andric       ArrayRef<uint8_t> ULEBbytes(ULEB, ULEBsize);
11641db9f3b2SDimitry Andric       OutputExpression.append(ULEBbytes.begin(), ULEBbytes.end());
11651db9f3b2SDimitry Andric     } else if (!getGlobalData().getOptions().UpdateIndexTablesOnly &&
11661db9f3b2SDimitry Andric                Op.getCode() == dwarf::DW_OP_addrx) {
11671db9f3b2SDimitry Andric       if (std::optional<object::SectionedAddress> SA =
11681db9f3b2SDimitry Andric               OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {
11691db9f3b2SDimitry Andric         // DWARFLinker does not use addrx forms since it generates relocated
11701db9f3b2SDimitry Andric         // addresses. Replace DW_OP_addrx with DW_OP_addr here.
11711db9f3b2SDimitry Andric         // Argument of DW_OP_addrx should be relocated here as it is not
11721db9f3b2SDimitry Andric         // processed by applyValidRelocs.
11731db9f3b2SDimitry Andric         OutputExpression.push_back(dwarf::DW_OP_addr);
11741db9f3b2SDimitry Andric         uint64_t LinkedAddress =
11751db9f3b2SDimitry Andric             SA->Address + (VarAddressAdjustment ? *VarAddressAdjustment : 0);
11761db9f3b2SDimitry Andric         if (getEndianness() != llvm::endianness::native)
11771db9f3b2SDimitry Andric           sys::swapByteOrder(LinkedAddress);
11781db9f3b2SDimitry Andric         ArrayRef<uint8_t> AddressBytes(
11791db9f3b2SDimitry Andric             reinterpret_cast<const uint8_t *>(&LinkedAddress),
11801db9f3b2SDimitry Andric             OrigAddressByteSize);
11811db9f3b2SDimitry Andric         OutputExpression.append(AddressBytes.begin(), AddressBytes.end());
11821db9f3b2SDimitry Andric       } else
11831db9f3b2SDimitry Andric         warn("cann't read DW_OP_addrx operand.");
11841db9f3b2SDimitry Andric     } else if (!getGlobalData().getOptions().UpdateIndexTablesOnly &&
11851db9f3b2SDimitry Andric                Op.getCode() == dwarf::DW_OP_constx) {
11861db9f3b2SDimitry Andric       if (std::optional<object::SectionedAddress> SA =
11871db9f3b2SDimitry Andric               OrigUnit.getAddrOffsetSectionItem(Op.getRawOperand(0))) {
11881db9f3b2SDimitry Andric         // DWARFLinker does not use constx forms since it generates relocated
11891db9f3b2SDimitry Andric         // addresses. Replace DW_OP_constx with DW_OP_const[*]u here.
11901db9f3b2SDimitry Andric         // Argument of DW_OP_constx should be relocated here as it is not
11911db9f3b2SDimitry Andric         // processed by applyValidRelocs.
11921db9f3b2SDimitry Andric         std::optional<uint8_t> OutOperandKind;
11931db9f3b2SDimitry Andric         switch (OrigAddressByteSize) {
11941db9f3b2SDimitry Andric         case 2:
11951db9f3b2SDimitry Andric           OutOperandKind = dwarf::DW_OP_const2u;
11961db9f3b2SDimitry Andric           break;
11971db9f3b2SDimitry Andric         case 4:
11981db9f3b2SDimitry Andric           OutOperandKind = dwarf::DW_OP_const4u;
11991db9f3b2SDimitry Andric           break;
12001db9f3b2SDimitry Andric         case 8:
12011db9f3b2SDimitry Andric           OutOperandKind = dwarf::DW_OP_const8u;
12021db9f3b2SDimitry Andric           break;
12031db9f3b2SDimitry Andric         default:
12041db9f3b2SDimitry Andric           warn(
12051db9f3b2SDimitry Andric               formatv(("unsupported address size: {0}."), OrigAddressByteSize));
12061db9f3b2SDimitry Andric           break;
12071db9f3b2SDimitry Andric         }
12081db9f3b2SDimitry Andric 
12091db9f3b2SDimitry Andric         if (OutOperandKind) {
12101db9f3b2SDimitry Andric           OutputExpression.push_back(*OutOperandKind);
12111db9f3b2SDimitry Andric           uint64_t LinkedAddress =
12121db9f3b2SDimitry Andric               SA->Address + (VarAddressAdjustment ? *VarAddressAdjustment : 0);
12131db9f3b2SDimitry Andric           if (getEndianness() != llvm::endianness::native)
12141db9f3b2SDimitry Andric             sys::swapByteOrder(LinkedAddress);
12151db9f3b2SDimitry Andric           ArrayRef<uint8_t> AddressBytes(
12161db9f3b2SDimitry Andric               reinterpret_cast<const uint8_t *>(&LinkedAddress),
12171db9f3b2SDimitry Andric               OrigAddressByteSize);
12181db9f3b2SDimitry Andric           OutputExpression.append(AddressBytes.begin(), AddressBytes.end());
12191db9f3b2SDimitry Andric         }
12201db9f3b2SDimitry Andric       } else
12211db9f3b2SDimitry Andric         warn("cann't read DW_OP_constx operand.");
12221db9f3b2SDimitry Andric     } else {
12231db9f3b2SDimitry Andric       // Copy over everything else unmodified.
12241db9f3b2SDimitry Andric       StringRef Bytes =
12251db9f3b2SDimitry Andric           InputExpression.getData().slice(OpOffset, Op.getEndOffset());
12261db9f3b2SDimitry Andric       OutputExpression.append(Bytes.begin(), Bytes.end());
12271db9f3b2SDimitry Andric     }
12281db9f3b2SDimitry Andric     OpOffset = Op.getEndOffset();
12291db9f3b2SDimitry Andric   }
12301db9f3b2SDimitry Andric }
12311db9f3b2SDimitry Andric 
cloneAndEmit(std::optional<std::reference_wrapper<const Triple>> TargetTriple,TypeUnit * ArtificialTypeUnit)12327a6dacacSDimitry Andric Error CompileUnit::cloneAndEmit(
12337a6dacacSDimitry Andric     std::optional<std::reference_wrapper<const Triple>> TargetTriple,
12341db9f3b2SDimitry Andric     TypeUnit *ArtificialTypeUnit) {
12351db9f3b2SDimitry Andric   BumpPtrAllocator Allocator;
12361db9f3b2SDimitry Andric 
12371db9f3b2SDimitry Andric   DWARFDie OrigUnitDIE = getOrigUnit().getUnitDIE();
12381db9f3b2SDimitry Andric   if (!OrigUnitDIE.isValid())
12391db9f3b2SDimitry Andric     return Error::success();
12401db9f3b2SDimitry Andric 
12411db9f3b2SDimitry Andric   TypeEntry *RootEntry = nullptr;
12421db9f3b2SDimitry Andric   if (ArtificialTypeUnit)
12431db9f3b2SDimitry Andric     RootEntry = ArtificialTypeUnit->getTypePool().getRoot();
12441db9f3b2SDimitry Andric 
12451db9f3b2SDimitry Andric   // Clone input DIE entry recursively.
12461db9f3b2SDimitry Andric   std::pair<DIE *, TypeEntry *> OutCUDie = cloneDIE(
12471db9f3b2SDimitry Andric       OrigUnitDIE.getDebugInfoEntry(), RootEntry, getDebugInfoHeaderSize(),
12481db9f3b2SDimitry Andric       std::nullopt, std::nullopt, Allocator, ArtificialTypeUnit);
12491db9f3b2SDimitry Andric   setOutUnitDIE(OutCUDie.first);
12501db9f3b2SDimitry Andric 
12517a6dacacSDimitry Andric   if (!TargetTriple.has_value() || (OutCUDie.first == nullptr))
12521db9f3b2SDimitry Andric     return Error::success();
12531db9f3b2SDimitry Andric 
12547a6dacacSDimitry Andric   if (Error Err = cloneAndEmitLineTable((*TargetTriple).get()))
12551db9f3b2SDimitry Andric     return Err;
12561db9f3b2SDimitry Andric 
12571db9f3b2SDimitry Andric   if (Error Err = cloneAndEmitDebugMacro())
12581db9f3b2SDimitry Andric     return Err;
12591db9f3b2SDimitry Andric 
12601db9f3b2SDimitry Andric   getOrCreateSectionDescriptor(DebugSectionKind::DebugInfo);
12617a6dacacSDimitry Andric   if (Error Err = emitDebugInfo((*TargetTriple).get()))
12621db9f3b2SDimitry Andric     return Err;
12631db9f3b2SDimitry Andric 
12641db9f3b2SDimitry Andric   // ASSUMPTION: .debug_info section should already be emitted at this point.
12651db9f3b2SDimitry Andric   // cloneAndEmitRanges & cloneAndEmitDebugLocations use .debug_info section
12661db9f3b2SDimitry Andric   // data.
12671db9f3b2SDimitry Andric 
12681db9f3b2SDimitry Andric   if (Error Err = cloneAndEmitRanges())
12691db9f3b2SDimitry Andric     return Err;
12701db9f3b2SDimitry Andric 
12711db9f3b2SDimitry Andric   if (Error Err = cloneAndEmitDebugLocations())
12721db9f3b2SDimitry Andric     return Err;
12731db9f3b2SDimitry Andric 
12741db9f3b2SDimitry Andric   if (Error Err = emitDebugAddrSection())
12751db9f3b2SDimitry Andric     return Err;
12761db9f3b2SDimitry Andric 
12771db9f3b2SDimitry Andric   // Generate Pub accelerator tables.
12781db9f3b2SDimitry Andric   if (llvm::is_contained(GlobalData.getOptions().AccelTables,
12791db9f3b2SDimitry Andric                          DWARFLinker::AccelTableKind::Pub))
12801db9f3b2SDimitry Andric     emitPubAccelerators();
12811db9f3b2SDimitry Andric 
12821db9f3b2SDimitry Andric   if (Error Err = emitDebugStringOffsetSection())
12831db9f3b2SDimitry Andric     return Err;
12841db9f3b2SDimitry Andric 
12851db9f3b2SDimitry Andric   return emitAbbreviations();
12861db9f3b2SDimitry Andric }
12871db9f3b2SDimitry Andric 
cloneDIE(const DWARFDebugInfoEntry * InputDieEntry,TypeEntry * ClonedParentTypeDIE,uint64_t OutOffset,std::optional<int64_t> FuncAddressAdjustment,std::optional<int64_t> VarAddressAdjustment,BumpPtrAllocator & Allocator,TypeUnit * ArtificialTypeUnit)12881db9f3b2SDimitry Andric std::pair<DIE *, TypeEntry *> CompileUnit::cloneDIE(
12891db9f3b2SDimitry Andric     const DWARFDebugInfoEntry *InputDieEntry, TypeEntry *ClonedParentTypeDIE,
12901db9f3b2SDimitry Andric     uint64_t OutOffset, std::optional<int64_t> FuncAddressAdjustment,
12911db9f3b2SDimitry Andric     std::optional<int64_t> VarAddressAdjustment, BumpPtrAllocator &Allocator,
12921db9f3b2SDimitry Andric     TypeUnit *ArtificialTypeUnit) {
12931db9f3b2SDimitry Andric   uint32_t InputDieIdx = getDIEIndex(InputDieEntry);
12941db9f3b2SDimitry Andric   CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx);
12951db9f3b2SDimitry Andric 
12961db9f3b2SDimitry Andric   bool NeedToClonePlainDIE = Info.needToKeepInPlainDwarf();
12971db9f3b2SDimitry Andric   bool NeedToCloneTypeDIE =
12981db9f3b2SDimitry Andric       (InputDieEntry->getTag() != dwarf::DW_TAG_compile_unit) &&
12991db9f3b2SDimitry Andric       Info.needToPlaceInTypeTable();
13001db9f3b2SDimitry Andric   std::pair<DIE *, TypeEntry *> ClonedDIE;
13011db9f3b2SDimitry Andric 
13021db9f3b2SDimitry Andric   DIEGenerator PlainDIEGenerator(Allocator, *this);
13031db9f3b2SDimitry Andric 
13041db9f3b2SDimitry Andric   if (NeedToClonePlainDIE)
13051db9f3b2SDimitry Andric     // Create a cloned DIE which would be placed into the cloned version
13061db9f3b2SDimitry Andric     // of input compile unit.
13071db9f3b2SDimitry Andric     ClonedDIE.first = createPlainDIEandCloneAttributes(
13081db9f3b2SDimitry Andric         InputDieEntry, PlainDIEGenerator, OutOffset, FuncAddressAdjustment,
13091db9f3b2SDimitry Andric         VarAddressAdjustment);
13101db9f3b2SDimitry Andric   if (NeedToCloneTypeDIE) {
13111db9f3b2SDimitry Andric     // Create a cloned DIE which would be placed into the artificial type
13121db9f3b2SDimitry Andric     // unit.
13131db9f3b2SDimitry Andric     assert(ArtificialTypeUnit != nullptr);
13141db9f3b2SDimitry Andric     DIEGenerator TypeDIEGenerator(
13151db9f3b2SDimitry Andric         ArtificialTypeUnit->getTypePool().getThreadLocalAllocator(), *this);
13161db9f3b2SDimitry Andric 
13171db9f3b2SDimitry Andric     ClonedDIE.second = createTypeDIEandCloneAttributes(
13181db9f3b2SDimitry Andric         InputDieEntry, TypeDIEGenerator, ClonedParentTypeDIE,
13191db9f3b2SDimitry Andric         ArtificialTypeUnit);
13201db9f3b2SDimitry Andric   }
13211db9f3b2SDimitry Andric   TypeEntry *TypeParentForChild =
13221db9f3b2SDimitry Andric       ClonedDIE.second ? ClonedDIE.second : ClonedParentTypeDIE;
13231db9f3b2SDimitry Andric 
13241db9f3b2SDimitry Andric   bool HasPlainChildrenToClone =
13251db9f3b2SDimitry Andric       (ClonedDIE.first && Info.getKeepPlainChildren());
13261db9f3b2SDimitry Andric 
13271db9f3b2SDimitry Andric   bool HasTypeChildrenToClone =
13281db9f3b2SDimitry Andric       ((ClonedDIE.second ||
13291db9f3b2SDimitry Andric         InputDieEntry->getTag() == dwarf::DW_TAG_compile_unit) &&
13301db9f3b2SDimitry Andric        Info.getKeepTypeChildren());
13311db9f3b2SDimitry Andric 
13321db9f3b2SDimitry Andric   // Recursively clone children.
13331db9f3b2SDimitry Andric   if (HasPlainChildrenToClone || HasTypeChildrenToClone) {
13341db9f3b2SDimitry Andric     for (const DWARFDebugInfoEntry *CurChild =
13351db9f3b2SDimitry Andric              getFirstChildEntry(InputDieEntry);
13361db9f3b2SDimitry Andric          CurChild && CurChild->getAbbreviationDeclarationPtr();
13371db9f3b2SDimitry Andric          CurChild = getSiblingEntry(CurChild)) {
13381db9f3b2SDimitry Andric       std::pair<DIE *, TypeEntry *> ClonedChild = cloneDIE(
13391db9f3b2SDimitry Andric           CurChild, TypeParentForChild, OutOffset, FuncAddressAdjustment,
13401db9f3b2SDimitry Andric           VarAddressAdjustment, Allocator, ArtificialTypeUnit);
13411db9f3b2SDimitry Andric 
13421db9f3b2SDimitry Andric       if (ClonedChild.first) {
13431db9f3b2SDimitry Andric         OutOffset =
13441db9f3b2SDimitry Andric             ClonedChild.first->getOffset() + ClonedChild.first->getSize();
13451db9f3b2SDimitry Andric         PlainDIEGenerator.addChild(ClonedChild.first);
13461db9f3b2SDimitry Andric       }
13471db9f3b2SDimitry Andric     }
13481db9f3b2SDimitry Andric     assert(ClonedDIE.first == nullptr ||
13491db9f3b2SDimitry Andric            HasPlainChildrenToClone == ClonedDIE.first->hasChildren());
13501db9f3b2SDimitry Andric 
13511db9f3b2SDimitry Andric     // Account for the end of children marker.
13521db9f3b2SDimitry Andric     if (HasPlainChildrenToClone)
13531db9f3b2SDimitry Andric       OutOffset += sizeof(int8_t);
13541db9f3b2SDimitry Andric   }
13551db9f3b2SDimitry Andric 
13561db9f3b2SDimitry Andric   // Update our size.
13571db9f3b2SDimitry Andric   if (ClonedDIE.first != nullptr)
13581db9f3b2SDimitry Andric     ClonedDIE.first->setSize(OutOffset - ClonedDIE.first->getOffset());
13591db9f3b2SDimitry Andric 
13601db9f3b2SDimitry Andric   return ClonedDIE;
13611db9f3b2SDimitry Andric }
13621db9f3b2SDimitry Andric 
createPlainDIEandCloneAttributes(const DWARFDebugInfoEntry * InputDieEntry,DIEGenerator & PlainDIEGenerator,uint64_t & OutOffset,std::optional<int64_t> & FuncAddressAdjustment,std::optional<int64_t> & VarAddressAdjustment)13631db9f3b2SDimitry Andric DIE *CompileUnit::createPlainDIEandCloneAttributes(
13641db9f3b2SDimitry Andric     const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &PlainDIEGenerator,
13651db9f3b2SDimitry Andric     uint64_t &OutOffset, std::optional<int64_t> &FuncAddressAdjustment,
13661db9f3b2SDimitry Andric     std::optional<int64_t> &VarAddressAdjustment) {
13671db9f3b2SDimitry Andric   uint32_t InputDieIdx = getDIEIndex(InputDieEntry);
13681db9f3b2SDimitry Andric   CompileUnit::DIEInfo &Info = getDIEInfo(InputDieIdx);
13691db9f3b2SDimitry Andric   DIE *ClonedDIE = nullptr;
13701db9f3b2SDimitry Andric   bool HasLocationExpressionAddress = false;
13711db9f3b2SDimitry Andric   if (InputDieEntry->getTag() == dwarf::DW_TAG_subprogram) {
13721db9f3b2SDimitry Andric     // Get relocation adjustment value for the current function.
13731db9f3b2SDimitry Andric     FuncAddressAdjustment =
13741db9f3b2SDimitry Andric         getContaingFile().Addresses->getSubprogramRelocAdjustment(
13757a6dacacSDimitry Andric             getDIE(InputDieEntry), false);
13761db9f3b2SDimitry Andric   } else if (InputDieEntry->getTag() == dwarf::DW_TAG_label) {
13771db9f3b2SDimitry Andric     // Get relocation adjustment value for the current label.
13781db9f3b2SDimitry Andric     std::optional<uint64_t> lowPC =
13791db9f3b2SDimitry Andric         dwarf::toAddress(find(InputDieEntry, dwarf::DW_AT_low_pc));
13801db9f3b2SDimitry Andric     if (lowPC) {
13811db9f3b2SDimitry Andric       LabelMapTy::iterator It = Labels.find(*lowPC);
13821db9f3b2SDimitry Andric       if (It != Labels.end())
13831db9f3b2SDimitry Andric         FuncAddressAdjustment = It->second;
13841db9f3b2SDimitry Andric     }
13851db9f3b2SDimitry Andric   } else if (InputDieEntry->getTag() == dwarf::DW_TAG_variable) {
13861db9f3b2SDimitry Andric     // Get relocation adjustment value for the current variable.
13871db9f3b2SDimitry Andric     std::pair<bool, std::optional<int64_t>> LocExprAddrAndRelocAdjustment =
13881db9f3b2SDimitry Andric         getContaingFile().Addresses->getVariableRelocAdjustment(
13897a6dacacSDimitry Andric             getDIE(InputDieEntry), false);
13901db9f3b2SDimitry Andric 
13911db9f3b2SDimitry Andric     HasLocationExpressionAddress = LocExprAddrAndRelocAdjustment.first;
13921db9f3b2SDimitry Andric     if (LocExprAddrAndRelocAdjustment.first &&
13931db9f3b2SDimitry Andric         LocExprAddrAndRelocAdjustment.second)
13941db9f3b2SDimitry Andric       VarAddressAdjustment = *LocExprAddrAndRelocAdjustment.second;
13951db9f3b2SDimitry Andric   }
13961db9f3b2SDimitry Andric 
13971db9f3b2SDimitry Andric   ClonedDIE = PlainDIEGenerator.createDIE(InputDieEntry->getTag(), OutOffset);
13981db9f3b2SDimitry Andric 
13991db9f3b2SDimitry Andric   // Offset to the DIE would be used after output DIE tree is deleted.
14001db9f3b2SDimitry Andric   // Thus we need to remember DIE offset separately.
14011db9f3b2SDimitry Andric   rememberDieOutOffset(InputDieIdx, OutOffset);
14021db9f3b2SDimitry Andric 
14031db9f3b2SDimitry Andric   // Clone Attributes.
14041db9f3b2SDimitry Andric   DIEAttributeCloner AttributesCloner(ClonedDIE, *this, this, InputDieEntry,
14051db9f3b2SDimitry Andric                                       PlainDIEGenerator, FuncAddressAdjustment,
14061db9f3b2SDimitry Andric                                       VarAddressAdjustment,
14071db9f3b2SDimitry Andric                                       HasLocationExpressionAddress);
14081db9f3b2SDimitry Andric   AttributesCloner.clone();
14091db9f3b2SDimitry Andric 
14101db9f3b2SDimitry Andric   // Remember accelerator info.
14111db9f3b2SDimitry Andric   AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this, this);
14121db9f3b2SDimitry Andric   AccelRecordsSaver.save(InputDieEntry, ClonedDIE, AttributesCloner.AttrInfo,
14131db9f3b2SDimitry Andric                          nullptr);
14141db9f3b2SDimitry Andric 
14151db9f3b2SDimitry Andric   OutOffset =
14161db9f3b2SDimitry Andric       AttributesCloner.finalizeAbbreviations(Info.getKeepPlainChildren());
14171db9f3b2SDimitry Andric 
14181db9f3b2SDimitry Andric   return ClonedDIE;
14191db9f3b2SDimitry Andric }
14201db9f3b2SDimitry Andric 
14211db9f3b2SDimitry Andric /// Allocates output DIE for the specified \p TypeDescriptor.
allocateTypeDie(TypeEntryBody * TypeDescriptor,DIEGenerator & TypeDIEGenerator,dwarf::Tag DieTag,bool IsDeclaration,bool IsParentDeclaration)14221db9f3b2SDimitry Andric DIE *CompileUnit::allocateTypeDie(TypeEntryBody *TypeDescriptor,
14231db9f3b2SDimitry Andric                                   DIEGenerator &TypeDIEGenerator,
14241db9f3b2SDimitry Andric                                   dwarf::Tag DieTag, bool IsDeclaration,
14251db9f3b2SDimitry Andric                                   bool IsParentDeclaration) {
14261db9f3b2SDimitry Andric   DIE *DefinitionDie = TypeDescriptor->Die;
14271db9f3b2SDimitry Andric   // Do not allocate any new DIE if definition DIE is already met.
14281db9f3b2SDimitry Andric   if (DefinitionDie)
14291db9f3b2SDimitry Andric     return nullptr;
14301db9f3b2SDimitry Andric 
14311db9f3b2SDimitry Andric   DIE *DeclarationDie = TypeDescriptor->DeclarationDie;
14321db9f3b2SDimitry Andric   bool OldParentIsDeclaration = TypeDescriptor->ParentIsDeclaration;
14331db9f3b2SDimitry Andric 
14341db9f3b2SDimitry Andric   if (IsDeclaration && !DeclarationDie) {
14351db9f3b2SDimitry Andric     // Alocate declaration DIE.
14361db9f3b2SDimitry Andric     DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
14371db9f3b2SDimitry Andric     if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,
14381db9f3b2SDimitry Andric                                                              NewDie))
14391db9f3b2SDimitry Andric       return NewDie;
14401db9f3b2SDimitry Andric   } else if (IsDeclaration && !IsParentDeclaration && OldParentIsDeclaration) {
14411db9f3b2SDimitry Andric     // Overwrite existing declaration DIE if it's parent is also an declaration
14421db9f3b2SDimitry Andric     // while parent of current declaration DIE is a definition.
14431db9f3b2SDimitry Andric     if (TypeDescriptor->ParentIsDeclaration.compare_exchange_weak(
14441db9f3b2SDimitry Andric             OldParentIsDeclaration, false)) {
14451db9f3b2SDimitry Andric       DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
14461db9f3b2SDimitry Andric       TypeDescriptor->DeclarationDie = NewDie;
14471db9f3b2SDimitry Andric       return NewDie;
14481db9f3b2SDimitry Andric     }
14491db9f3b2SDimitry Andric   } else if (!IsDeclaration && IsParentDeclaration && !DeclarationDie) {
14501db9f3b2SDimitry Andric     // Alocate declaration DIE since parent of current DIE is marked as
14511db9f3b2SDimitry Andric     // declaration.
14521db9f3b2SDimitry Andric     DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
14531db9f3b2SDimitry Andric     if (TypeDescriptor->DeclarationDie.compare_exchange_weak(DeclarationDie,
14541db9f3b2SDimitry Andric                                                              NewDie))
14551db9f3b2SDimitry Andric       return NewDie;
14561db9f3b2SDimitry Andric   } else if (!IsDeclaration && !IsParentDeclaration) {
14571db9f3b2SDimitry Andric     // Allocate definition DIE.
14581db9f3b2SDimitry Andric     DIE *NewDie = TypeDIEGenerator.createDIE(DieTag, 0);
14591db9f3b2SDimitry Andric     if (TypeDescriptor->Die.compare_exchange_weak(DefinitionDie, NewDie)) {
14601db9f3b2SDimitry Andric       TypeDescriptor->ParentIsDeclaration = false;
14611db9f3b2SDimitry Andric       return NewDie;
14621db9f3b2SDimitry Andric     }
14631db9f3b2SDimitry Andric   }
14641db9f3b2SDimitry Andric 
14651db9f3b2SDimitry Andric   return nullptr;
14661db9f3b2SDimitry Andric }
14671db9f3b2SDimitry Andric 
createTypeDIEandCloneAttributes(const DWARFDebugInfoEntry * InputDieEntry,DIEGenerator & TypeDIEGenerator,TypeEntry * ClonedParentTypeDIE,TypeUnit * ArtificialTypeUnit)14681db9f3b2SDimitry Andric TypeEntry *CompileUnit::createTypeDIEandCloneAttributes(
14691db9f3b2SDimitry Andric     const DWARFDebugInfoEntry *InputDieEntry, DIEGenerator &TypeDIEGenerator,
14701db9f3b2SDimitry Andric     TypeEntry *ClonedParentTypeDIE, TypeUnit *ArtificialTypeUnit) {
14711db9f3b2SDimitry Andric   assert(ArtificialTypeUnit != nullptr);
14721db9f3b2SDimitry Andric   uint32_t InputDieIdx = getDIEIndex(InputDieEntry);
14731db9f3b2SDimitry Andric 
14741db9f3b2SDimitry Andric   TypeEntry *Entry = getDieTypeEntry(InputDieIdx);
14751db9f3b2SDimitry Andric   assert(Entry != nullptr);
14761db9f3b2SDimitry Andric   assert(ClonedParentTypeDIE != nullptr);
14771db9f3b2SDimitry Andric   TypeEntryBody *EntryBody =
14781db9f3b2SDimitry Andric       ArtificialTypeUnit->getTypePool().getOrCreateTypeEntryBody(
14791db9f3b2SDimitry Andric           Entry, ClonedParentTypeDIE);
14801db9f3b2SDimitry Andric   assert(EntryBody);
14811db9f3b2SDimitry Andric 
14821db9f3b2SDimitry Andric   bool IsDeclaration =
14831db9f3b2SDimitry Andric       dwarf::toUnsigned(find(InputDieEntry, dwarf::DW_AT_declaration), 0);
14841db9f3b2SDimitry Andric 
14851db9f3b2SDimitry Andric   bool ParentIsDeclaration = false;
14861db9f3b2SDimitry Andric   if (std::optional<uint32_t> ParentIdx = InputDieEntry->getParentIdx())
14871db9f3b2SDimitry Andric     ParentIsDeclaration =
14881db9f3b2SDimitry Andric         dwarf::toUnsigned(find(*ParentIdx, dwarf::DW_AT_declaration), 0);
14891db9f3b2SDimitry Andric 
14901db9f3b2SDimitry Andric   DIE *OutDIE =
14911db9f3b2SDimitry Andric       allocateTypeDie(EntryBody, TypeDIEGenerator, InputDieEntry->getTag(),
14921db9f3b2SDimitry Andric                       IsDeclaration, ParentIsDeclaration);
14931db9f3b2SDimitry Andric 
14941db9f3b2SDimitry Andric   if (OutDIE != nullptr) {
14951db9f3b2SDimitry Andric     assert(ArtificialTypeUnit != nullptr);
14961db9f3b2SDimitry Andric     ArtificialTypeUnit->getSectionDescriptor(DebugSectionKind::DebugInfo);
14971db9f3b2SDimitry Andric 
14981db9f3b2SDimitry Andric     DIEAttributeCloner AttributesCloner(OutDIE, *this, ArtificialTypeUnit,
14991db9f3b2SDimitry Andric                                         InputDieEntry, TypeDIEGenerator,
15001db9f3b2SDimitry Andric                                         std::nullopt, std::nullopt, false);
15011db9f3b2SDimitry Andric     AttributesCloner.clone();
15021db9f3b2SDimitry Andric 
15031db9f3b2SDimitry Andric     // Remember accelerator info.
15041db9f3b2SDimitry Andric     AcceleratorRecordsSaver AccelRecordsSaver(getGlobalData(), *this,
15051db9f3b2SDimitry Andric                                               ArtificialTypeUnit);
15061db9f3b2SDimitry Andric     AccelRecordsSaver.save(InputDieEntry, OutDIE, AttributesCloner.AttrInfo,
15071db9f3b2SDimitry Andric                            Entry);
15081db9f3b2SDimitry Andric 
15091db9f3b2SDimitry Andric     // if AttributesCloner.getOutOffset() == 0 then we need to add
15101db9f3b2SDimitry Andric     // 1 to avoid assertion for zero size. We will subtract it back later.
15111db9f3b2SDimitry Andric     OutDIE->setSize(AttributesCloner.getOutOffset() + 1);
15121db9f3b2SDimitry Andric   }
15131db9f3b2SDimitry Andric 
15141db9f3b2SDimitry Andric   return Entry;
15151db9f3b2SDimitry Andric }
15161db9f3b2SDimitry Andric 
cloneAndEmitLineTable(const Triple & TargetTriple)15177a6dacacSDimitry Andric Error CompileUnit::cloneAndEmitLineTable(const Triple &TargetTriple) {
15181db9f3b2SDimitry Andric   const DWARFDebugLine::LineTable *InputLineTable =
15191db9f3b2SDimitry Andric       getContaingFile().Dwarf->getLineTableForUnit(&getOrigUnit());
15201db9f3b2SDimitry Andric   if (InputLineTable == nullptr) {
15211db9f3b2SDimitry Andric     if (getOrigUnit().getUnitDIE().find(dwarf::DW_AT_stmt_list))
15221db9f3b2SDimitry Andric       warn("cann't load line table.");
15231db9f3b2SDimitry Andric     return Error::success();
15241db9f3b2SDimitry Andric   }
15251db9f3b2SDimitry Andric 
15261db9f3b2SDimitry Andric   DWARFDebugLine::LineTable OutLineTable;
15271db9f3b2SDimitry Andric 
15281db9f3b2SDimitry Andric   // Set Line Table header.
15291db9f3b2SDimitry Andric   OutLineTable.Prologue = InputLineTable->Prologue;
15301db9f3b2SDimitry Andric   OutLineTable.Prologue.FormParams.AddrSize = getFormParams().AddrSize;
15311db9f3b2SDimitry Andric 
15321db9f3b2SDimitry Andric   // Set Line Table Rows.
15331db9f3b2SDimitry Andric   if (getGlobalData().getOptions().UpdateIndexTablesOnly) {
15341db9f3b2SDimitry Andric     OutLineTable.Rows = InputLineTable->Rows;
15351db9f3b2SDimitry Andric     // If all the line table contains is a DW_LNE_end_sequence, clear the line
15361db9f3b2SDimitry Andric     // table rows, it will be inserted again in the DWARFStreamer.
15371db9f3b2SDimitry Andric     if (OutLineTable.Rows.size() == 1 && OutLineTable.Rows[0].EndSequence)
15381db9f3b2SDimitry Andric       OutLineTable.Rows.clear();
15391db9f3b2SDimitry Andric 
15401db9f3b2SDimitry Andric     OutLineTable.Sequences = InputLineTable->Sequences;
15411db9f3b2SDimitry Andric   } else {
15421db9f3b2SDimitry Andric     // This vector is the output line table.
15431db9f3b2SDimitry Andric     std::vector<DWARFDebugLine::Row> NewRows;
15441db9f3b2SDimitry Andric     NewRows.reserve(InputLineTable->Rows.size());
15451db9f3b2SDimitry Andric 
15461db9f3b2SDimitry Andric     // Current sequence of rows being extracted, before being inserted
15471db9f3b2SDimitry Andric     // in NewRows.
15481db9f3b2SDimitry Andric     std::vector<DWARFDebugLine::Row> Seq;
15491db9f3b2SDimitry Andric 
15501db9f3b2SDimitry Andric     const auto &FunctionRanges = getFunctionRanges();
15511db9f3b2SDimitry Andric     std::optional<AddressRangeValuePair> CurrRange;
15521db9f3b2SDimitry Andric 
15531db9f3b2SDimitry Andric     // FIXME: This logic is meant to generate exactly the same output as
15541db9f3b2SDimitry Andric     // Darwin's classic dsymutil. There is a nicer way to implement this
15551db9f3b2SDimitry Andric     // by simply putting all the relocated line info in NewRows and simply
15561db9f3b2SDimitry Andric     // sorting NewRows before passing it to emitLineTableForUnit. This
15571db9f3b2SDimitry Andric     // should be correct as sequences for a function should stay
15581db9f3b2SDimitry Andric     // together in the sorted output. There are a few corner cases that
15591db9f3b2SDimitry Andric     // look suspicious though, and that required to implement the logic
15601db9f3b2SDimitry Andric     // this way. Revisit that once initial validation is finished.
15611db9f3b2SDimitry Andric 
15621db9f3b2SDimitry Andric     // Iterate over the object file line info and extract the sequences
15631db9f3b2SDimitry Andric     // that correspond to linked functions.
15641db9f3b2SDimitry Andric     for (DWARFDebugLine::Row Row : InputLineTable->Rows) {
15651db9f3b2SDimitry Andric       // Check whether we stepped out of the range. The range is
15661db9f3b2SDimitry Andric       // half-open, but consider accept the end address of the range if
15671db9f3b2SDimitry Andric       // it is marked as end_sequence in the input (because in that
15681db9f3b2SDimitry Andric       // case, the relocation offset is accurate and that entry won't
15691db9f3b2SDimitry Andric       // serve as the start of another function).
15701db9f3b2SDimitry Andric       if (!CurrRange || !CurrRange->Range.contains(Row.Address.Address)) {
15711db9f3b2SDimitry Andric         // We just stepped out of a known range. Insert a end_sequence
15721db9f3b2SDimitry Andric         // corresponding to the end of the range.
15731db9f3b2SDimitry Andric         uint64_t StopAddress =
15741db9f3b2SDimitry Andric             CurrRange ? CurrRange->Range.end() + CurrRange->Value : -1ULL;
15751db9f3b2SDimitry Andric         CurrRange = FunctionRanges.getRangeThatContains(Row.Address.Address);
15761db9f3b2SDimitry Andric         if (StopAddress != -1ULL && !Seq.empty()) {
15771db9f3b2SDimitry Andric           // Insert end sequence row with the computed end address, but
15781db9f3b2SDimitry Andric           // the same line as the previous one.
15791db9f3b2SDimitry Andric           auto NextLine = Seq.back();
15801db9f3b2SDimitry Andric           NextLine.Address.Address = StopAddress;
15811db9f3b2SDimitry Andric           NextLine.EndSequence = 1;
15821db9f3b2SDimitry Andric           NextLine.PrologueEnd = 0;
15831db9f3b2SDimitry Andric           NextLine.BasicBlock = 0;
15841db9f3b2SDimitry Andric           NextLine.EpilogueBegin = 0;
15851db9f3b2SDimitry Andric           Seq.push_back(NextLine);
15861db9f3b2SDimitry Andric           insertLineSequence(Seq, NewRows);
15871db9f3b2SDimitry Andric         }
15881db9f3b2SDimitry Andric 
15891db9f3b2SDimitry Andric         if (!CurrRange)
15901db9f3b2SDimitry Andric           continue;
15911db9f3b2SDimitry Andric       }
15921db9f3b2SDimitry Andric 
15931db9f3b2SDimitry Andric       // Ignore empty sequences.
15941db9f3b2SDimitry Andric       if (Row.EndSequence && Seq.empty())
15951db9f3b2SDimitry Andric         continue;
15961db9f3b2SDimitry Andric 
15971db9f3b2SDimitry Andric       // Relocate row address and add it to the current sequence.
15981db9f3b2SDimitry Andric       Row.Address.Address += CurrRange->Value;
15991db9f3b2SDimitry Andric       Seq.emplace_back(Row);
16001db9f3b2SDimitry Andric 
16011db9f3b2SDimitry Andric       if (Row.EndSequence)
16021db9f3b2SDimitry Andric         insertLineSequence(Seq, NewRows);
16031db9f3b2SDimitry Andric     }
16041db9f3b2SDimitry Andric 
16051db9f3b2SDimitry Andric     OutLineTable.Rows = std::move(NewRows);
16061db9f3b2SDimitry Andric   }
16071db9f3b2SDimitry Andric 
16081db9f3b2SDimitry Andric   return emitDebugLine(TargetTriple, OutLineTable);
16091db9f3b2SDimitry Andric }
16101db9f3b2SDimitry Andric 
insertLineSequence(std::vector<DWARFDebugLine::Row> & Seq,std::vector<DWARFDebugLine::Row> & Rows)16111db9f3b2SDimitry Andric void CompileUnit::insertLineSequence(std::vector<DWARFDebugLine::Row> &Seq,
16121db9f3b2SDimitry Andric                                      std::vector<DWARFDebugLine::Row> &Rows) {
16131db9f3b2SDimitry Andric   if (Seq.empty())
16141db9f3b2SDimitry Andric     return;
16151db9f3b2SDimitry Andric 
16161db9f3b2SDimitry Andric   if (!Rows.empty() && Rows.back().Address < Seq.front().Address) {
16171db9f3b2SDimitry Andric     llvm::append_range(Rows, Seq);
16181db9f3b2SDimitry Andric     Seq.clear();
16191db9f3b2SDimitry Andric     return;
16201db9f3b2SDimitry Andric   }
16211db9f3b2SDimitry Andric 
16221db9f3b2SDimitry Andric   object::SectionedAddress Front = Seq.front().Address;
16231db9f3b2SDimitry Andric   auto InsertPoint = partition_point(
16241db9f3b2SDimitry Andric       Rows, [=](const DWARFDebugLine::Row &O) { return O.Address < Front; });
16251db9f3b2SDimitry Andric 
16261db9f3b2SDimitry Andric   // FIXME: this only removes the unneeded end_sequence if the
16271db9f3b2SDimitry Andric   // sequences have been inserted in order. Using a global sort like
16281db9f3b2SDimitry Andric   // described in cloneAndEmitLineTable() and delaying the end_sequene
16291db9f3b2SDimitry Andric   // elimination to DebugLineEmitter::emit() we can get rid of all of them.
16301db9f3b2SDimitry Andric   if (InsertPoint != Rows.end() && InsertPoint->Address == Front &&
16311db9f3b2SDimitry Andric       InsertPoint->EndSequence) {
16321db9f3b2SDimitry Andric     *InsertPoint = Seq.front();
16331db9f3b2SDimitry Andric     Rows.insert(InsertPoint + 1, Seq.begin() + 1, Seq.end());
16341db9f3b2SDimitry Andric   } else {
16351db9f3b2SDimitry Andric     Rows.insert(InsertPoint, Seq.begin(), Seq.end());
16361db9f3b2SDimitry Andric   }
16371db9f3b2SDimitry Andric 
16381db9f3b2SDimitry Andric   Seq.clear();
16391db9f3b2SDimitry Andric }
16401db9f3b2SDimitry Andric 
16411db9f3b2SDimitry Andric #if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
dump()16421db9f3b2SDimitry Andric LLVM_DUMP_METHOD void CompileUnit::DIEInfo::dump() {
16431db9f3b2SDimitry Andric   llvm::errs() << "{";
16441db9f3b2SDimitry Andric   llvm::errs() << "  Placement: ";
16451db9f3b2SDimitry Andric   switch (getPlacement()) {
16461db9f3b2SDimitry Andric   case NotSet:
16471db9f3b2SDimitry Andric     llvm::errs() << "NotSet";
16481db9f3b2SDimitry Andric     break;
16491db9f3b2SDimitry Andric   case TypeTable:
16501db9f3b2SDimitry Andric     llvm::errs() << "TypeTable";
16511db9f3b2SDimitry Andric     break;
16521db9f3b2SDimitry Andric   case PlainDwarf:
16531db9f3b2SDimitry Andric     llvm::errs() << "PlainDwarf";
16541db9f3b2SDimitry Andric     break;
16551db9f3b2SDimitry Andric   case Both:
16561db9f3b2SDimitry Andric     llvm::errs() << "Both";
16571db9f3b2SDimitry Andric     break;
16581db9f3b2SDimitry Andric   }
16591db9f3b2SDimitry Andric 
16601db9f3b2SDimitry Andric   llvm::errs() << "  Keep: " << getKeep();
16611db9f3b2SDimitry Andric   llvm::errs() << "  KeepPlainChildren: " << getKeepPlainChildren();
16621db9f3b2SDimitry Andric   llvm::errs() << "  KeepTypeChildren: " << getKeepTypeChildren();
16631db9f3b2SDimitry Andric   llvm::errs() << "  IsInMouduleScope: " << getIsInMouduleScope();
16641db9f3b2SDimitry Andric   llvm::errs() << "  IsInFunctionScope: " << getIsInFunctionScope();
16651db9f3b2SDimitry Andric   llvm::errs() << "  IsInAnonNamespaceScope: " << getIsInAnonNamespaceScope();
16661db9f3b2SDimitry Andric   llvm::errs() << "  ODRAvailable: " << getODRAvailable();
16671db9f3b2SDimitry Andric   llvm::errs() << "  TrackLiveness: " << getTrackLiveness();
16681db9f3b2SDimitry Andric   llvm::errs() << "}\n";
16691db9f3b2SDimitry Andric }
16701db9f3b2SDimitry Andric #endif // if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
16711db9f3b2SDimitry Andric 
16721db9f3b2SDimitry Andric std::optional<std::pair<StringRef, StringRef>>
getDirAndFilenameFromLineTable(const DWARFFormValue & FileIdxValue)16731db9f3b2SDimitry Andric CompileUnit::getDirAndFilenameFromLineTable(
16741db9f3b2SDimitry Andric     const DWARFFormValue &FileIdxValue) {
16751db9f3b2SDimitry Andric   uint64_t FileIdx;
16761db9f3b2SDimitry Andric   if (std::optional<uint64_t> Val = FileIdxValue.getAsUnsignedConstant())
16771db9f3b2SDimitry Andric     FileIdx = *Val;
16781db9f3b2SDimitry Andric   else if (std::optional<int64_t> Val = FileIdxValue.getAsSignedConstant())
16791db9f3b2SDimitry Andric     FileIdx = *Val;
16801db9f3b2SDimitry Andric   else if (std::optional<uint64_t> Val = FileIdxValue.getAsSectionOffset())
16811db9f3b2SDimitry Andric     FileIdx = *Val;
16821db9f3b2SDimitry Andric   else
16831db9f3b2SDimitry Andric     return std::nullopt;
16841db9f3b2SDimitry Andric 
16851db9f3b2SDimitry Andric   return getDirAndFilenameFromLineTable(FileIdx);
16861db9f3b2SDimitry Andric }
16871db9f3b2SDimitry Andric 
16881db9f3b2SDimitry Andric std::optional<std::pair<StringRef, StringRef>>
getDirAndFilenameFromLineTable(uint64_t FileIdx)16891db9f3b2SDimitry Andric CompileUnit::getDirAndFilenameFromLineTable(uint64_t FileIdx) {
16901db9f3b2SDimitry Andric   FileNamesCache::iterator FileData = FileNames.find(FileIdx);
16911db9f3b2SDimitry Andric   if (FileData != FileNames.end())
16921db9f3b2SDimitry Andric     return std::make_pair(StringRef(FileData->second.first),
16931db9f3b2SDimitry Andric                           StringRef(FileData->second.second));
16941db9f3b2SDimitry Andric 
16951db9f3b2SDimitry Andric   if (const DWARFDebugLine::LineTable *LineTable =
16961db9f3b2SDimitry Andric           getOrigUnit().getContext().getLineTableForUnit(&getOrigUnit())) {
16971db9f3b2SDimitry Andric     if (LineTable->hasFileAtIndex(FileIdx)) {
16981db9f3b2SDimitry Andric 
16991db9f3b2SDimitry Andric       const llvm::DWARFDebugLine::FileNameEntry &Entry =
17001db9f3b2SDimitry Andric           LineTable->Prologue.getFileNameEntry(FileIdx);
17011db9f3b2SDimitry Andric 
17021db9f3b2SDimitry Andric       Expected<const char *> Name = Entry.Name.getAsCString();
17031db9f3b2SDimitry Andric       if (!Name) {
17041db9f3b2SDimitry Andric         warn(Name.takeError());
17051db9f3b2SDimitry Andric         return std::nullopt;
17061db9f3b2SDimitry Andric       }
17071db9f3b2SDimitry Andric 
17081db9f3b2SDimitry Andric       std::string FileName = *Name;
17091db9f3b2SDimitry Andric       if (isPathAbsoluteOnWindowsOrPosix(FileName)) {
17101db9f3b2SDimitry Andric         FileNamesCache::iterator FileData =
17111db9f3b2SDimitry Andric             FileNames
17121db9f3b2SDimitry Andric                 .insert(std::make_pair(
17131db9f3b2SDimitry Andric                     FileIdx,
17141db9f3b2SDimitry Andric                     std::make_pair(std::string(""), std::move(FileName))))
17151db9f3b2SDimitry Andric                 .first;
17161db9f3b2SDimitry Andric         return std::make_pair(StringRef(FileData->second.first),
17171db9f3b2SDimitry Andric                               StringRef(FileData->second.second));
17181db9f3b2SDimitry Andric       }
17191db9f3b2SDimitry Andric 
17201db9f3b2SDimitry Andric       SmallString<256> FilePath;
17211db9f3b2SDimitry Andric       StringRef IncludeDir;
17221db9f3b2SDimitry Andric       // Be defensive about the contents of Entry.
17231db9f3b2SDimitry Andric       if (getVersion() >= 5) {
17241db9f3b2SDimitry Andric         // DirIdx 0 is the compilation directory, so don't include it for
17251db9f3b2SDimitry Andric         // relative names.
17261db9f3b2SDimitry Andric         if ((Entry.DirIdx != 0) &&
17271db9f3b2SDimitry Andric             Entry.DirIdx < LineTable->Prologue.IncludeDirectories.size()) {
17281db9f3b2SDimitry Andric           Expected<const char *> DirName =
17291db9f3b2SDimitry Andric               LineTable->Prologue.IncludeDirectories[Entry.DirIdx]
17301db9f3b2SDimitry Andric                   .getAsCString();
17311db9f3b2SDimitry Andric           if (DirName)
17321db9f3b2SDimitry Andric             IncludeDir = *DirName;
17331db9f3b2SDimitry Andric           else {
17341db9f3b2SDimitry Andric             warn(DirName.takeError());
17351db9f3b2SDimitry Andric             return std::nullopt;
17361db9f3b2SDimitry Andric           }
17371db9f3b2SDimitry Andric         }
17381db9f3b2SDimitry Andric       } else {
17391db9f3b2SDimitry Andric         if (0 < Entry.DirIdx &&
17401db9f3b2SDimitry Andric             Entry.DirIdx <= LineTable->Prologue.IncludeDirectories.size()) {
17411db9f3b2SDimitry Andric           Expected<const char *> DirName =
17421db9f3b2SDimitry Andric               LineTable->Prologue.IncludeDirectories[Entry.DirIdx - 1]
17431db9f3b2SDimitry Andric                   .getAsCString();
17441db9f3b2SDimitry Andric           if (DirName)
17451db9f3b2SDimitry Andric             IncludeDir = *DirName;
17461db9f3b2SDimitry Andric           else {
17471db9f3b2SDimitry Andric             warn(DirName.takeError());
17481db9f3b2SDimitry Andric             return std::nullopt;
17491db9f3b2SDimitry Andric           }
17501db9f3b2SDimitry Andric         }
17511db9f3b2SDimitry Andric       }
17521db9f3b2SDimitry Andric 
17531db9f3b2SDimitry Andric       StringRef CompDir = getOrigUnit().getCompilationDir();
17541db9f3b2SDimitry Andric 
17551db9f3b2SDimitry Andric       if (!CompDir.empty() && !isPathAbsoluteOnWindowsOrPosix(IncludeDir)) {
17561db9f3b2SDimitry Andric         sys::path::append(FilePath, sys::path::Style::native, CompDir);
17571db9f3b2SDimitry Andric       }
17581db9f3b2SDimitry Andric 
17591db9f3b2SDimitry Andric       sys::path::append(FilePath, sys::path::Style::native, IncludeDir);
17601db9f3b2SDimitry Andric 
17611db9f3b2SDimitry Andric       FileNamesCache::iterator FileData =
17621db9f3b2SDimitry Andric           FileNames
17631db9f3b2SDimitry Andric               .insert(
17641db9f3b2SDimitry Andric                   std::make_pair(FileIdx, std::make_pair(std::string(FilePath),
17651db9f3b2SDimitry Andric                                                          std::move(FileName))))
17661db9f3b2SDimitry Andric               .first;
17671db9f3b2SDimitry Andric       return std::make_pair(StringRef(FileData->second.first),
17681db9f3b2SDimitry Andric                             StringRef(FileData->second.second));
17691db9f3b2SDimitry Andric     }
17701db9f3b2SDimitry Andric   }
17711db9f3b2SDimitry Andric 
17721db9f3b2SDimitry Andric   return std::nullopt;
17731db9f3b2SDimitry Andric }
17741db9f3b2SDimitry Andric 
17751db9f3b2SDimitry Andric #define MAX_REFERENCIES_DEPTH 1000
getNamespaceOrigin()17761db9f3b2SDimitry Andric UnitEntryPairTy UnitEntryPairTy::getNamespaceOrigin() {
17771db9f3b2SDimitry Andric   UnitEntryPairTy CUDiePair(*this);
17781db9f3b2SDimitry Andric   std::optional<UnitEntryPairTy> RefDiePair;
17791db9f3b2SDimitry Andric   int refDepth = 0;
17801db9f3b2SDimitry Andric   do {
17811db9f3b2SDimitry Andric     RefDiePair = CUDiePair.CU->resolveDIEReference(
17821db9f3b2SDimitry Andric         CUDiePair.DieEntry, dwarf::DW_AT_extension,
17831db9f3b2SDimitry Andric         ResolveInterCUReferencesMode::Resolve);
17841db9f3b2SDimitry Andric     if (!RefDiePair || !RefDiePair->DieEntry)
17851db9f3b2SDimitry Andric       return CUDiePair;
17861db9f3b2SDimitry Andric 
17871db9f3b2SDimitry Andric     CUDiePair = *RefDiePair;
17881db9f3b2SDimitry Andric   } while (refDepth++ < MAX_REFERENCIES_DEPTH);
17891db9f3b2SDimitry Andric 
17901db9f3b2SDimitry Andric   return CUDiePair;
17911db9f3b2SDimitry Andric }
17921db9f3b2SDimitry Andric 
getParent()17931db9f3b2SDimitry Andric std::optional<UnitEntryPairTy> UnitEntryPairTy::getParent() {
17941db9f3b2SDimitry Andric   if (std::optional<uint32_t> ParentIdx = DieEntry->getParentIdx())
17951db9f3b2SDimitry Andric     return UnitEntryPairTy{CU, CU->getDebugInfoEntry(*ParentIdx)};
17961db9f3b2SDimitry Andric 
17971db9f3b2SDimitry Andric   return std::nullopt;
17981db9f3b2SDimitry Andric }
17991db9f3b2SDimitry Andric 
OutputUnitVariantPtr(CompileUnit * U)18001db9f3b2SDimitry Andric CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(CompileUnit *U)
18011db9f3b2SDimitry Andric     : Ptr(U) {
18021db9f3b2SDimitry Andric   assert(U != nullptr);
18031db9f3b2SDimitry Andric }
18041db9f3b2SDimitry Andric 
OutputUnitVariantPtr(TypeUnit * U)18051db9f3b2SDimitry Andric CompileUnit::OutputUnitVariantPtr::OutputUnitVariantPtr(TypeUnit *U) : Ptr(U) {
18061db9f3b2SDimitry Andric   assert(U != nullptr);
18071db9f3b2SDimitry Andric }
18081db9f3b2SDimitry Andric 
operator ->()18091db9f3b2SDimitry Andric DwarfUnit *CompileUnit::OutputUnitVariantPtr::operator->() {
18101db9f3b2SDimitry Andric   if (isCompileUnit())
18111db9f3b2SDimitry Andric     return getAsCompileUnit();
18121db9f3b2SDimitry Andric   else
18131db9f3b2SDimitry Andric     return getAsTypeUnit();
18141db9f3b2SDimitry Andric }
18151db9f3b2SDimitry Andric 
isCompileUnit()18161db9f3b2SDimitry Andric bool CompileUnit::OutputUnitVariantPtr::isCompileUnit() {
18171db9f3b2SDimitry Andric   return Ptr.is<CompileUnit *>();
18181db9f3b2SDimitry Andric }
18191db9f3b2SDimitry Andric 
isTypeUnit()18201db9f3b2SDimitry Andric bool CompileUnit::OutputUnitVariantPtr::isTypeUnit() {
18211db9f3b2SDimitry Andric   return Ptr.is<TypeUnit *>();
18221db9f3b2SDimitry Andric }
18231db9f3b2SDimitry Andric 
getAsCompileUnit()18241db9f3b2SDimitry Andric CompileUnit *CompileUnit::OutputUnitVariantPtr::getAsCompileUnit() {
18251db9f3b2SDimitry Andric   return Ptr.get<CompileUnit *>();
18261db9f3b2SDimitry Andric }
18271db9f3b2SDimitry Andric 
getAsTypeUnit()18281db9f3b2SDimitry Andric TypeUnit *CompileUnit::OutputUnitVariantPtr::getAsTypeUnit() {
18291db9f3b2SDimitry Andric   return Ptr.get<TypeUnit *>();
18301db9f3b2SDimitry Andric }
18311db9f3b2SDimitry Andric 
resolveDependenciesAndMarkLiveness(bool InterCUProcessingStarted,std::atomic<bool> & HasNewInterconnectedCUs)18321db9f3b2SDimitry Andric bool CompileUnit::resolveDependenciesAndMarkLiveness(
18331db9f3b2SDimitry Andric     bool InterCUProcessingStarted, std::atomic<bool> &HasNewInterconnectedCUs) {
1834*0fca6ea1SDimitry Andric   if (!Dependencies)
18351db9f3b2SDimitry Andric     Dependencies.reset(new DependencyTracker(*this));
18361db9f3b2SDimitry Andric 
18371db9f3b2SDimitry Andric   return Dependencies->resolveDependenciesAndMarkLiveness(
18381db9f3b2SDimitry Andric       InterCUProcessingStarted, HasNewInterconnectedCUs);
18391db9f3b2SDimitry Andric }
18401db9f3b2SDimitry Andric 
updateDependenciesCompleteness()18411db9f3b2SDimitry Andric bool CompileUnit::updateDependenciesCompleteness() {
18421db9f3b2SDimitry Andric   assert(Dependencies.get());
18431db9f3b2SDimitry Andric 
1844*0fca6ea1SDimitry Andric   return Dependencies->updateDependenciesCompleteness();
18451db9f3b2SDimitry Andric }
18461db9f3b2SDimitry Andric 
verifyDependencies()18471db9f3b2SDimitry Andric void CompileUnit::verifyDependencies() {
18481db9f3b2SDimitry Andric   assert(Dependencies.get());
18491db9f3b2SDimitry Andric 
1850*0fca6ea1SDimitry Andric   Dependencies->verifyKeepChain();
18511db9f3b2SDimitry Andric }
18521db9f3b2SDimitry Andric 
getODRAttributes()18531db9f3b2SDimitry Andric ArrayRef<dwarf::Attribute> dwarf_linker::parallel::getODRAttributes() {
18541db9f3b2SDimitry Andric   static dwarf::Attribute ODRAttributes[] = {
18551db9f3b2SDimitry Andric       dwarf::DW_AT_type, dwarf::DW_AT_specification,
18561db9f3b2SDimitry Andric       dwarf::DW_AT_abstract_origin, dwarf::DW_AT_import};
18571db9f3b2SDimitry Andric 
18581db9f3b2SDimitry Andric   return ODRAttributes;
18591db9f3b2SDimitry Andric }
1860