//===-- DebugNamesDWARFIndex.cpp ------------------------------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Plugins/SymbolFile/DWARF/DebugNamesDWARFIndex.h"
#include "Plugins/SymbolFile/DWARF/DWARFDebugInfo.h"
#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARFDwo.h"
#include "lldb/Core/Module.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"
#include "lldb/lldb-private-enumerations.h"
#include "llvm/ADT/Sequence.h"
#include <optional>

using namespace lldb;
using namespace lldb_private;
using namespace lldb_private::plugin::dwarf;
using namespace llvm::dwarf;

llvm::Expected<std::unique_ptr<DebugNamesDWARFIndex>>
DebugNamesDWARFIndex::Create(Module &module, DWARFDataExtractor debug_names,
                             DWARFDataExtractor debug_str,
                             SymbolFileDWARF &dwarf) {
  auto index_up = std::make_unique<DebugNames>(debug_names.GetAsLLVMDWARF(),
                                               debug_str.GetAsLLVM());
  if (llvm::Error E = index_up->extract())
    return std::move(E);

  return std::unique_ptr<DebugNamesDWARFIndex>(new DebugNamesDWARFIndex(
      module, std::move(index_up), debug_names, debug_str, dwarf));
}

llvm::DenseSet<uint64_t>
DebugNamesDWARFIndex::GetTypeUnitSignatures(const DebugNames &debug_names) {
  llvm::DenseSet<uint64_t> result;
  for (const DebugNames::NameIndex &ni : debug_names) {
    const uint32_t num_tus = ni.getForeignTUCount();
    for (uint32_t tu = 0; tu < num_tus; ++tu)
      result.insert(ni.getForeignTUSignature(tu));
  }
  return result;
}

llvm::DenseSet<dw_offset_t>
DebugNamesDWARFIndex::GetUnits(const DebugNames &debug_names) {
  llvm::DenseSet<dw_offset_t> result;
  for (const DebugNames::NameIndex &ni : debug_names) {
    const uint32_t num_cus = ni.getCUCount();
    for (uint32_t cu = 0; cu < num_cus; ++cu)
      result.insert(ni.getCUOffset(cu));
    const uint32_t num_tus = ni.getLocalTUCount();
    for (uint32_t tu = 0; tu < num_tus; ++tu)
      result.insert(ni.getLocalTUOffset(tu));
  }
  return result;
}

std::optional<DWARFTypeUnit *>
DebugNamesDWARFIndex::GetForeignTypeUnit(const DebugNames::Entry &entry) const {
  std::optional<uint64_t> type_sig = entry.getForeignTUTypeSignature();
  if (!type_sig.has_value())
    return std::nullopt;

  // Ask the entry for the skeleton compile unit offset and fetch the .dwo
  // file from it and get the type unit by signature from there. If we find
  // the type unit in the .dwo file, we don't need to check that the
  // DW_AT_dwo_name matches because each .dwo file can have its own type unit.
  std::optional<uint64_t> cu_offset = entry.getRelatedCUOffset();
  if (!cu_offset)
    return nullptr; // Return NULL, this is a type unit, but couldn't find it.

  DWARFUnit *cu =
      m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo, *cu_offset);
  if (!cu)
    return nullptr; // Return NULL, this is a type unit, but couldn't find it.

  auto dwp_sp = m_debug_info.GetDwpSymbolFile();
  if (!dwp_sp) {
    // No .dwp file, we need to load the .dwo file.
    DWARFUnit &dwo_cu = cu->GetNonSkeletonUnit();
    // We don't need the check if the type unit matches the .dwo file if we have
    // a .dwo file (not a .dwp), so we can just return the value here.
    if (!dwo_cu.IsDWOUnit())
      return nullptr; // We weren't able to load the .dwo file.
    return dwo_cu.GetSymbolFileDWARF().DebugInfo().GetTypeUnitForHash(
        *type_sig);
  }
  // We have a .dwp file, just get the type unit from there. We need to verify
  // that the type unit that ended up in the final .dwp file is the right type
  // unit. Type units have signatures which are the same across multiple .dwo
  // files, but only one of those type units will end up in the .dwp file. The
  // contents of type units for the same type can be different in different .dwo
  // files, which means the DIE offsets might not be the same between two
  // different type units. So we need to determine if this accelerator table
  // matches the type unit that ended up in the .dwp file. If it doesn't match,
  // then we need to ignore this accelerator table entry as the type unit that
  // is in the .dwp file will have its own index. In order to determine if the
  // type unit that ended up in a .dwp file matches this DebugNames::Entry, we
  // need to find the skeleton compile unit for this entry.
  DWARFTypeUnit *foreign_tu = dwp_sp->DebugInfo().GetTypeUnitForHash(*type_sig);
  if (!foreign_tu)
    return nullptr; // Return NULL, this is a type unit, but couldn't find it.

  DWARFBaseDIE cu_die = cu->GetUnitDIEOnly();
  DWARFBaseDIE tu_die = foreign_tu->GetUnitDIEOnly();
  llvm::StringRef cu_dwo_name =
      cu_die.GetAttributeValueAsString(DW_AT_dwo_name, nullptr);
  llvm::StringRef tu_dwo_name =
      tu_die.GetAttributeValueAsString(DW_AT_dwo_name, nullptr);
  if (cu_dwo_name == tu_dwo_name)
    return foreign_tu; // We found a match!
  return nullptr; // Return NULL, this is a type unit, but couldn't find it.
}

DWARFUnit *
DebugNamesDWARFIndex::GetNonSkeletonUnit(const DebugNames::Entry &entry) const {

  if (std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry))
    return foreign_tu.value();

  // Look for a DWARF unit offset (CU offset or local TU offset) as they are
  // both offsets into the .debug_info section.
  std::optional<uint64_t> unit_offset = entry.getCUOffset();
  if (!unit_offset)
    unit_offset = entry.getLocalTUOffset();
  if (unit_offset) {
    if (DWARFUnit *cu = m_debug_info.GetUnitAtOffset(DIERef::Section::DebugInfo,
                                                     *unit_offset))
      return &cu->GetNonSkeletonUnit();
  }
  return nullptr;
}

DWARFDIE DebugNamesDWARFIndex::GetDIE(const DebugNames::Entry &entry) const {
  DWARFUnit *unit = GetNonSkeletonUnit(entry);
  std::optional<uint64_t> die_offset = entry.getDIEUnitOffset();
  if (!unit || !die_offset)
    return DWARFDIE();
  if (DWARFDIE die = unit->GetDIE(unit->GetOffset() + *die_offset))
    return die;

  m_module.ReportErrorIfModifyDetected(
      "the DWARF debug information has been modified (bad offset {0:x} in "
      "debug_names section)\n",
      *die_offset);
  return DWARFDIE();
}

IterationAction DebugNamesDWARFIndex::ProcessEntry(
    const DebugNames::Entry &entry,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  DWARFDIE die = GetDIE(entry);
  if (!die)
    return IterationAction::Continue;
  // Clang used to erroneously emit index entries for declaration DIEs in case
  // when the definition is in a type unit (llvm.org/pr77696).
  if (die.IsStructUnionOrClass() &&
      die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0))
    return IterationAction::Continue;
  return callback(die);
}

void DebugNamesDWARFIndex::MaybeLogLookupError(llvm::Error error,
                                               const DebugNames::NameIndex &ni,
                                               llvm::StringRef name) {
  // Ignore SentinelErrors, log everything else.
  LLDB_LOG_ERROR(
      GetLog(DWARFLog::Lookups),
      handleErrors(std::move(error), [](const DebugNames::SentinelError &) {}),
      "Failed to parse index entries for index at {1:x}, name {2}: {0}",
      ni.getUnitOffset(), name);
}

void DebugNamesDWARFIndex::GetGlobalVariables(
    ConstString basename,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  for (const DebugNames::Entry &entry :
       m_debug_names_up->equal_range(basename.GetStringRef())) {
    if (entry.tag() != DW_TAG_variable)
      continue;

    if (ProcessEntry(entry, callback) == IterationAction::Stop)
      return;
  }

  m_fallback.GetGlobalVariables(basename, callback);
}

void DebugNamesDWARFIndex::GetGlobalVariables(
    const RegularExpression &regex,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
    for (DebugNames::NameTableEntry nte: ni) {
      Mangled mangled_name(nte.getString());
      if (!mangled_name.NameMatches(regex))
        continue;

      uint64_t entry_offset = nte.getEntryOffset();
      llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
      for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
        if (entry_or->tag() != DW_TAG_variable)
          continue;

        if (ProcessEntry(*entry_or, callback) == IterationAction::Stop)
          return;
      }
      MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
    }
  }

  m_fallback.GetGlobalVariables(regex, callback);
}

void DebugNamesDWARFIndex::GetGlobalVariables(
    DWARFUnit &cu, llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  uint64_t cu_offset = cu.GetOffset();
  bool found_entry_for_cu = false;
  for (const DebugNames::NameIndex &ni : *m_debug_names_up) {
    // Check if this name index contains an entry for the given CU.
    bool cu_matches = false;
    for (uint32_t i = 0; i < ni.getCUCount(); ++i) {
      if (ni.getCUOffset(i) == cu_offset) {
        cu_matches = true;
        break;
      }
    }
    if (!cu_matches)
      continue;

    for (DebugNames::NameTableEntry nte : ni) {
      uint64_t entry_offset = nte.getEntryOffset();
      llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
      for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
        if (entry_or->tag() != DW_TAG_variable)
          continue;
        if (entry_or->getCUOffset() != cu_offset)
          continue;

        found_entry_for_cu = true;
        if (ProcessEntry(*entry_or, callback) == IterationAction::Stop)
          return;
      }
      MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
    }
  }
  // If no name index for that particular CU was found, fallback to
  // creating the manual index.
  if (!found_entry_for_cu)
    m_fallback.GetGlobalVariables(cu, callback);
}

void DebugNamesDWARFIndex::GetCompleteObjCClass(
    ConstString class_name, bool must_be_implementation,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  // Keep a list of incomplete types as fallback for when we don't find the
  // complete type.
  std::vector<DWARFDIE> incomplete_types;

  for (const DebugNames::Entry &entry :
       m_debug_names_up->equal_range(class_name.GetStringRef())) {
    if (entry.tag() != DW_TAG_structure_type &&
        entry.tag() != DW_TAG_class_type)
      continue;

    DWARFDIE die = GetDIE(entry);
    if (!die) {
      // Report invalid
      continue;
    }

    if (die.GetAttributeValueAsUnsigned(DW_AT_APPLE_objc_complete_type, 0)) {
      // If we find the complete version we're done.
      callback(die);
      return;
    }
    incomplete_types.push_back(die);
  }

  for (DWARFDIE die : incomplete_types)
    if (callback(die) == IterationAction::Stop)
      return;

  m_fallback.GetCompleteObjCClass(class_name, must_be_implementation, callback);
}

namespace {
using Entry = llvm::DWARFDebugNames::Entry;

/// If `entry` and all of its parents have an `IDX_parent`, use that information
/// to build and return a list of at most `max_parents` parent Entries.
/// `entry` itself is not included in the list.
/// If any parent does not have an `IDX_parent`, or the Entry data is corrupted,
/// nullopt is returned.
std::optional<llvm::SmallVector<Entry, 4>>
getParentChain(Entry entry,
               uint32_t max_parents = std::numeric_limits<uint32_t>::max()) {
  llvm::SmallVector<Entry, 4> parent_entries;

  do {
    if (!entry.hasParentInformation())
      return std::nullopt;

    llvm::Expected<std::optional<Entry>> parent = entry.getParentDIEEntry();
    if (!parent) {
      // Bad data.
      LLDB_LOG_ERROR(
          GetLog(DWARFLog::Lookups), parent.takeError(),
          "Failed to extract parent entry from a non-empty IDX_parent: {0}");
      return std::nullopt;
    }

    // Last parent in the chain.
    if (!parent->has_value())
      break;

    parent_entries.push_back(**parent);
    entry = **parent;
  } while (parent_entries.size() < max_parents);

  return parent_entries;
}
} // namespace

void DebugNamesDWARFIndex::GetFullyQualifiedType(
    const DWARFDeclContext &context,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  if (context.GetSize() == 0)
    return;

  llvm::StringRef leaf_name = context[0].name;
  llvm::SmallVector<llvm::StringRef> parent_names;
  for (auto idx : llvm::seq<int>(1, context.GetSize()))
    parent_names.emplace_back(context[idx].name);

  // For each entry, grab its parent chain and check if we have a match.
  for (const DebugNames::Entry &entry :
       m_debug_names_up->equal_range(leaf_name)) {
    if (!isType(entry.tag()))
      continue;

    // If we get a NULL foreign_tu back, the entry doesn't match the type unit
    // in the .dwp file, or we were not able to load the .dwo file or the DWO ID
    // didn't match.
    std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry);
    if (foreign_tu && foreign_tu.value() == nullptr)
      continue;

    // Grab at most one extra parent, subsequent parents are not necessary to
    // test equality.
    std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
        getParentChain(entry, parent_names.size() + 1);

    if (!parent_chain) {
      // Fallback: use the base class implementation.
      if (ProcessEntry(entry, [&](DWARFDIE die) {
            return GetFullyQualifiedTypeImpl(context, die, callback);
          }) == IterationAction::Stop)
        return;
      continue;
    }

    if (SameParentChain(parent_names, *parent_chain)) {
      if (ProcessEntry(entry, callback) == IterationAction::Stop)
        return;
    }
  }
  m_fallback.GetFullyQualifiedType(context, callback);
}

bool DebugNamesDWARFIndex::SameAsEntryContext(
    const CompilerContext &query_context,
    const DebugNames::Entry &entry) const {
  // TODO: check dwarf tag matches.
  // Peek at the AT_name of `entry` and test equality to `name`.
  auto maybe_dieoffset = entry.getDIEUnitOffset();
  if (!maybe_dieoffset)
    return false;
  DWARFUnit *unit = GetNonSkeletonUnit(entry);
  if (!unit)
    return false;
  return query_context.name ==
         unit->PeekDIEName(unit->GetOffset() + *maybe_dieoffset);
}

bool DebugNamesDWARFIndex::SameParentChain(
    llvm::ArrayRef<llvm::StringRef> parent_names,
    llvm::ArrayRef<DebugNames::Entry> parent_entries) const {

  if (parent_entries.size() != parent_names.size())
    return false;

  auto SameAsEntryATName = [this](llvm::StringRef name,
                                  const DebugNames::Entry &entry) {
    // Peek at the AT_name of `entry` and test equality to `name`.
    auto maybe_dieoffset = entry.getDIEUnitOffset();
    if (!maybe_dieoffset)
      return false;
    DWARFUnit *unit = GetNonSkeletonUnit(entry);
    if (!unit)
      return false;
    return name == unit->PeekDIEName(unit->GetOffset() + *maybe_dieoffset);
  };

  // If the AT_name of any parent fails to match the expected name, we don't
  // have a match.
  for (auto [parent_name, parent_entry] :
       llvm::zip_equal(parent_names, parent_entries))
    if (!SameAsEntryATName(parent_name, parent_entry))
      return false;
  return true;
}

bool DebugNamesDWARFIndex::SameParentChain(
    llvm::ArrayRef<CompilerContext> parent_contexts,
    llvm::ArrayRef<DebugNames::Entry> parent_entries) const {
  if (parent_entries.size() != parent_contexts.size())
    return false;

  // If the AT_name of any parent fails to match the expected name, we don't
  // have a match.
  for (auto [parent_context, parent_entry] :
       llvm::zip_equal(parent_contexts, parent_entries))
    if (!SameAsEntryContext(parent_context, parent_entry))
      return false;
  return true;
}

bool DebugNamesDWARFIndex::WithinParentChain(
    llvm::ArrayRef<CompilerContext> query_contexts,
    llvm::ArrayRef<DebugNames::Entry> parent_chain) const {
  if (query_contexts.size() == parent_chain.size())
    return SameParentChain(query_contexts, parent_chain);

  // If parent chain does not have enough entries, we can't possibly have a
  // match.
  while (!query_contexts.empty() &&
         query_contexts.size() <= parent_chain.size()) {
    if (SameAsEntryContext(query_contexts.front(), parent_chain.front())) {
      query_contexts = query_contexts.drop_front();
      parent_chain = parent_chain.drop_front();
    } else {
      // Name does not match, try next parent_chain entry if the current entry
      // is namespace because the current one can be an inline namespace.
      if (parent_chain.front().tag() != DW_TAG_namespace)
        return false;
      parent_chain = parent_chain.drop_front();
    }
  }
  return query_contexts.empty();
}

void DebugNamesDWARFIndex::GetTypes(
    ConstString name,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  for (const DebugNames::Entry &entry :
       m_debug_names_up->equal_range(name.GetStringRef())) {
    if (isType(entry.tag())) {
      if (ProcessEntry(entry, callback) == IterationAction::Stop)
        return;
    }
  }

  m_fallback.GetTypes(name, callback);
}

void DebugNamesDWARFIndex::GetTypes(
    const DWARFDeclContext &context,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  auto name = context[0].name;
  for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) {
    if (entry.tag() == context[0].tag) {
      if (ProcessEntry(entry, callback) == IterationAction::Stop)
        return;
    }
  }

  m_fallback.GetTypes(context, callback);
}

void DebugNamesDWARFIndex::GetNamespaces(
    ConstString name,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  for (const DebugNames::Entry &entry :
       m_debug_names_up->equal_range(name.GetStringRef())) {
    llvm::dwarf::Tag entry_tag = entry.tag();
    if (entry_tag == DW_TAG_namespace ||
        entry_tag == DW_TAG_imported_declaration) {
      if (ProcessEntry(entry, callback) == IterationAction::Stop)
        return;
    }
  }

  m_fallback.GetNamespaces(name, callback);
}

llvm::SmallVector<CompilerContext>
DebugNamesDWARFIndex::GetTypeQueryParentContexts(TypeQuery &query) {
  std::vector<lldb_private::CompilerContext> &query_decl_context =
      query.GetContextRef();
  llvm::SmallVector<CompilerContext> parent_contexts;
  if (!query_decl_context.empty()) {
    // Skip the last entry as it's the type we're matching parents for.
    // Reverse the query decl context to match parent chain order.
    llvm::ArrayRef<CompilerContext> parent_contexts_ref(
        query_decl_context.data(), query_decl_context.size() - 1);
    for (const CompilerContext &ctx : llvm::reverse(parent_contexts_ref)) {
      // Skip any context without name because .debug_names might not encode
      // them. (e.g. annonymous namespace)
      if ((ctx.kind & CompilerContextKind::AnyType) !=
              CompilerContextKind::Invalid &&
          !ctx.name.IsEmpty())
        parent_contexts.push_back(ctx);
    }
  }
  return parent_contexts;
}

void DebugNamesDWARFIndex::GetTypesWithQuery(
    TypeQuery &query,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  ConstString name = query.GetTypeBasename();
  std::vector<lldb_private::CompilerContext> query_context =
      query.GetContextRef();
  if (query_context.size() <= 1 && !query.GetExactMatch())
    return GetTypes(name, callback);

  llvm::SmallVector<CompilerContext> parent_contexts =
      GetTypeQueryParentContexts(query);
  // For each entry, grab its parent chain and check if we have a match.
  for (const DebugNames::Entry &entry : m_debug_names_up->equal_range(name)) {
    if (!isType(entry.tag()))
      continue;

    // If we get a NULL foreign_tu back, the entry doesn't match the type unit
    // in the .dwp file, or we were not able to load the .dwo file or the DWO ID
    // didn't match.
    std::optional<DWARFTypeUnit *> foreign_tu = GetForeignTypeUnit(entry);
    if (foreign_tu && foreign_tu.value() == nullptr)
      continue;

    std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
        getParentChain(entry);
    if (!parent_chain) {
      // Fallback: use the base class implementation.
      if (ProcessEntry(entry, [&](DWARFDIE die) {
            return ProcessTypeDIEMatchQuery(query, die, callback);
          }) == IterationAction::Stop)
        return;
      continue;
    }

    if (WithinParentChain(parent_contexts, *parent_chain)) {
      if (ProcessEntry(entry, [&](DWARFDIE die) {
            // After .debug_names filtering still sending to base
            // class for further filtering before calling the
            // callback.
            return ProcessTypeDIEMatchQuery(query, die, callback);
          }) == IterationAction::Stop)
        return;
    }
  }
  m_fallback.GetTypesWithQuery(query, callback);
}

void DebugNamesDWARFIndex::GetNamespacesWithParents(
    ConstString name, const CompilerDeclContext &parent_decl_ctx,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  std::vector<lldb_private::CompilerContext> parent_contexts =
      parent_decl_ctx.GetCompilerContext();
  llvm::SmallVector<CompilerContext> parent_named_contexts;
  std::copy_if(parent_contexts.rbegin(), parent_contexts.rend(),
               std::back_inserter(parent_named_contexts),
               [](const CompilerContext &ctx) { return !ctx.name.IsEmpty(); });
  for (const DebugNames::Entry &entry :
       m_debug_names_up->equal_range(name.GetStringRef())) {
    llvm::dwarf::Tag entry_tag = entry.tag();
    if (entry_tag == DW_TAG_namespace ||
        entry_tag == DW_TAG_imported_declaration) {
      std::optional<llvm::SmallVector<Entry, 4>> parent_chain =
          getParentChain(entry);
      if (!parent_chain) {
        // Fallback: use the base class implementation.
        if (ProcessEntry(entry, [&](DWARFDIE die) {
              return ProcessNamespaceDieMatchParents(parent_decl_ctx, die,
                                                     callback);
            }) == IterationAction::Stop)
          return;
        continue;
      }

      if (WithinParentChain(parent_named_contexts, *parent_chain)) {
        if (ProcessEntry(entry, [&](DWARFDIE die) {
              // After .debug_names filtering still sending to
              // base class for further filtering before calling
              // the callback.
              return ProcessNamespaceDieMatchParents(parent_decl_ctx, die,
                                                     callback);
            }) == IterationAction::Stop)
          return;
      }
    }
  }
  m_fallback.GetNamespacesWithParents(name, parent_decl_ctx, callback);
}

void DebugNamesDWARFIndex::GetFunctions(
    const Module::LookupInfo &lookup_info, SymbolFileDWARF &dwarf,
    const CompilerDeclContext &parent_decl_ctx,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  ConstString name = lookup_info.GetLookupName();
  std::set<DWARFDebugInfoEntry *> seen;
  for (const DebugNames::Entry &entry :
       m_debug_names_up->equal_range(name.GetStringRef())) {
    Tag tag = entry.tag();
    if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
      continue;

    if (DWARFDIE die = GetDIE(entry)) {
      if (ProcessFunctionDIE(lookup_info, die, parent_decl_ctx,
                             [&](DWARFDIE die) {
                               if (!seen.insert(die.GetDIE()).second)
                                 return IterationAction::Continue;
                               return callback(die);
                             }) == IterationAction::Stop)
        return;
    }
  }

  m_fallback.GetFunctions(lookup_info, dwarf, parent_decl_ctx, callback);
}

void DebugNamesDWARFIndex::GetFunctions(
    const RegularExpression &regex,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  for (const DebugNames::NameIndex &ni: *m_debug_names_up) {
    for (DebugNames::NameTableEntry nte: ni) {
      if (!regex.Execute(nte.getString()))
        continue;

      uint64_t entry_offset = nte.getEntryOffset();
      llvm::Expected<DebugNames::Entry> entry_or = ni.getEntry(&entry_offset);
      for (; entry_or; entry_or = ni.getEntry(&entry_offset)) {
        Tag tag = entry_or->tag();
        if (tag != DW_TAG_subprogram && tag != DW_TAG_inlined_subroutine)
          continue;

        if (ProcessEntry(*entry_or, callback) == IterationAction::Stop)
          return;
      }
      MaybeLogLookupError(entry_or.takeError(), ni, nte.getString());
    }
  }

  m_fallback.GetFunctions(regex, callback);
}

void DebugNamesDWARFIndex::Dump(Stream &s) {
  m_fallback.Dump(s);

  std::string data;
  llvm::raw_string_ostream os(data);
  m_debug_names_up->dump(os);
  s.PutCString(data);
}
