//===-- DWARFIndex.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/DWARFIndex.h"
#include "DWARFDebugInfoEntry.h"
#include "DWARFDeclContext.h"
#include "Plugins/Language/ObjC/ObjCLanguage.h"
#include "Plugins/SymbolFile/DWARF/DWARFDIE.h"
#include "Plugins/SymbolFile/DWARF/SymbolFileDWARF.h"

#include "lldb/Core/Mangled.h"
#include "lldb/Core/Module.h"
#include "lldb/Target/Language.h"
#include "lldb/lldb-private-enumerations.h"

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

DWARFIndex::~DWARFIndex() = default;

IterationAction DWARFIndex::ProcessFunctionDIE(
    const Module::LookupInfo &lookup_info, DWARFDIE die,
    const CompilerDeclContext &parent_decl_ctx,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  llvm::StringRef name = lookup_info.GetLookupName().GetStringRef();
  FunctionNameType name_type_mask = lookup_info.GetNameTypeMask();

  if (!(name_type_mask & eFunctionNameTypeFull)) {
    ConstString name_to_match_against;
    if (const char *mangled_die_name = die.GetMangledName()) {
      name_to_match_against = ConstString(mangled_die_name);
    } else {
      SymbolFileDWARF *symbols = die.GetDWARF();
      if (ConstString demangled_die_name =
              symbols->ConstructFunctionDemangledName(die))
        name_to_match_against = demangled_die_name;
    }

    if (!lookup_info.NameMatchesLookupInfo(name_to_match_against,
                                           lookup_info.GetLanguageType()))
      return IterationAction::Continue;
  }

  // Exit early if we're searching exclusively for methods or selectors and
  // we have a context specified (no methods in namespaces).
  uint32_t looking_for_nonmethods =
      name_type_mask & ~(eFunctionNameTypeMethod | eFunctionNameTypeSelector);
  if (!looking_for_nonmethods && parent_decl_ctx.IsValid())
    return IterationAction::Continue;

  // Otherwise, we need to also check that the context matches. If it does not
  // match, we do nothing.
  if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die))
    return IterationAction::Continue;

  // In case of a full match, we just insert everything we find.
  if (name_type_mask & eFunctionNameTypeFull && die.GetMangledName() == name)
    return callback(die);

  // If looking for ObjC selectors, we need to also check if the name is a
  // possible selector.
  if (name_type_mask & eFunctionNameTypeSelector &&
      ObjCLanguage::IsPossibleObjCMethodName(die.GetName()))
    return callback(die);

  bool looking_for_methods = name_type_mask & lldb::eFunctionNameTypeMethod;
  bool looking_for_functions = name_type_mask & lldb::eFunctionNameTypeBase;
  if (looking_for_methods || looking_for_functions) {
    // If we're looking for either methods or functions, we definitely want this
    // die. Otherwise, only keep it if the die type matches what we are
    // searching for.
    if ((looking_for_methods && looking_for_functions) ||
        looking_for_methods == die.IsMethod())
      return callback(die);
  }

  return IterationAction::Continue;
}

DWARFIndex::DIERefCallbackImpl::DIERefCallbackImpl(
    const DWARFIndex &index,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback,
    llvm::StringRef name)
    : m_index(index),
      m_dwarf(*llvm::cast<SymbolFileDWARF>(
          index.m_module.GetSymbolFile()->GetBackingSymbolFile())),
      m_callback(callback), m_name(name) {}

IterationAction DWARFIndex::DIERefCallbackImpl::operator()(DIERef ref) const {
  if (DWARFDIE die = m_dwarf.GetDIE(ref))
    return m_callback(die);
  m_index.ReportInvalidDIERef(ref, m_name);
  return IterationAction::Continue;
}

IterationAction DWARFIndex::DIERefCallbackImpl::operator()(
    const llvm::AppleAcceleratorTable::Entry &entry) const {
  return this->operator()(DIERef(std::nullopt, DIERef::Section::DebugInfo,
                                 *entry.getDIESectionOffset()));
}

void DWARFIndex::ReportInvalidDIERef(DIERef ref, llvm::StringRef name) const {
  m_module.ReportErrorIfModifyDetected(
      "the DWARF debug information has been modified (accelerator table had "
      "bad die {0:x16} for '{1}')\n",
      ref.die_offset(), name.str().c_str());
}

void DWARFIndex::GetFullyQualifiedType(
    const DWARFDeclContext &context,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  GetTypes(context, [&](DWARFDIE die) {
    return GetFullyQualifiedTypeImpl(context, die, callback);
  });
}

IterationAction DWARFIndex::GetFullyQualifiedTypeImpl(
    const DWARFDeclContext &context, DWARFDIE die,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  DWARFDeclContext dwarf_decl_ctx = die.GetDWARFDeclContext();
  if (dwarf_decl_ctx == context)
    return callback(die);
  return IterationAction::Continue;
}

void DWARFIndex::GetTypesWithQuery(
    TypeQuery &query,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  GetTypes(query.GetTypeBasename(), [&](DWARFDIE die) {
    return ProcessTypeDIEMatchQuery(query, die, callback);
  });
}

IterationAction DWARFIndex::ProcessTypeDIEMatchQuery(
    TypeQuery &query, DWARFDIE die,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  // Check the language, but only if we have a language filter.
  if (query.HasLanguage() &&
      !query.LanguageMatches(SymbolFileDWARF::GetLanguageFamily(*die.GetCU())))
    return IterationAction::Continue;

  // Since mangled names are unique, we only need to check if the names are
  // the same.
  if (query.GetSearchByMangledName()) {
    if (die.GetMangledName(/*substitute_name_allowed=*/false) !=
        query.GetTypeBasename().GetStringRef())
      return IterationAction::Continue;
    return callback(die);
  }

  std::vector<lldb_private::CompilerContext> die_context;
  if (query.GetModuleSearch())
    die_context = die.GetDeclContext();
  else
    die_context = die.GetTypeLookupContext();

  if (!query.ContextMatches(die_context))
    return IterationAction::Continue;
  return callback(die);
}

void DWARFIndex::GetNamespacesWithParents(
    ConstString name, const CompilerDeclContext &parent_decl_ctx,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  GetNamespaces(name, [&](DWARFDIE die) {
    return ProcessNamespaceDieMatchParents(parent_decl_ctx, die, callback);
  });
}

void DWARFIndex::GetFunctions(
    const std::vector<Module::LookupInfo> &lookup_infos, SymbolFileDWARF &dwarf,
    const CompilerDeclContext &parent_decl_ctx,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  for (auto &lookup_info : lookup_infos)
    GetFunctions(lookup_info, dwarf, parent_decl_ctx, callback);
}

IterationAction DWARFIndex::ProcessNamespaceDieMatchParents(
    const CompilerDeclContext &parent_decl_ctx, DWARFDIE die,
    llvm::function_ref<IterationAction(DWARFDIE die)> callback) {
  if (!SymbolFileDWARF::DIEInDeclContext(parent_decl_ctx, die))
    return IterationAction::Continue;
  return callback(die);
}
