//===-- AppleDWARFIndex.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/AppleDWARFIndex.h"
#include "Plugins/SymbolFile/DWARF/DWARFDeclContext.h"
#include "Plugins/SymbolFile/DWARF/DWARFUnit.h"
#include "Plugins/SymbolFile/DWARF/LogChannelDWARF.h"

#include "lldb/Core/Module.h"
#include "lldb/Symbol/Function.h"

using namespace lldb_private;
using namespace lldb;

std::unique_ptr<AppleDWARFIndex> AppleDWARFIndex::Create(
    Module &module, DWARFDataExtractor apple_names,
    DWARFDataExtractor apple_namespaces, DWARFDataExtractor apple_types,
    DWARFDataExtractor apple_objc, DWARFDataExtractor debug_str) {
  auto apple_names_table_up = std::make_unique<DWARFMappedHash::MemoryTable>(
      apple_names, debug_str, ".apple_names");
  if (!apple_names_table_up->IsValid())
    apple_names_table_up.reset();

  auto apple_namespaces_table_up =
      std::make_unique<DWARFMappedHash::MemoryTable>(
          apple_namespaces, debug_str, ".apple_namespaces");
  if (!apple_namespaces_table_up->IsValid())
    apple_namespaces_table_up.reset();

  auto apple_types_table_up = std::make_unique<DWARFMappedHash::MemoryTable>(
      apple_types, debug_str, ".apple_types");
  if (!apple_types_table_up->IsValid())
    apple_types_table_up.reset();

  auto apple_objc_table_up = std::make_unique<DWARFMappedHash::MemoryTable>(
      apple_objc, debug_str, ".apple_objc");
  if (!apple_objc_table_up->IsValid())
    apple_objc_table_up.reset();

  if (apple_names_table_up || apple_namespaces_table_up ||
      apple_types_table_up || apple_objc_table_up)
    return std::make_unique<AppleDWARFIndex>(
        module, std::move(apple_names_table_up),
        std::move(apple_namespaces_table_up), std::move(apple_types_table_up),
        std::move(apple_objc_table_up));

  return nullptr;
}

void AppleDWARFIndex::GetGlobalVariables(
    ConstString basename, llvm::function_ref<bool(DWARFDIE die)> callback) {
  if (!m_apple_names_up)
    return;
  m_apple_names_up->FindByName(
      basename.GetStringRef(),
      DIERefCallback(callback, basename.GetStringRef()));
}

void AppleDWARFIndex::GetGlobalVariables(
    const RegularExpression &regex,
    llvm::function_ref<bool(DWARFDIE die)> callback) {
  if (!m_apple_names_up)
    return;

  DWARFMappedHash::DIEInfoArray hash_data;
  m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data);
  // This is not really the DIE name.
  DWARFMappedHash::ExtractDIEArray(hash_data,
                                   DIERefCallback(callback, regex.GetText()));
}

void AppleDWARFIndex::GetGlobalVariables(
    const DWARFUnit &cu, llvm::function_ref<bool(DWARFDIE die)> callback) {
  if (!m_apple_names_up)
    return;

  DWARFMappedHash::DIEInfoArray hash_data;
  m_apple_names_up->AppendAllDIEsInRange(cu.GetOffset(), cu.GetNextUnitOffset(),
                                         hash_data);
  DWARFMappedHash::ExtractDIEArray(hash_data, DIERefCallback(callback));
}

void AppleDWARFIndex::GetObjCMethods(
    ConstString class_name, llvm::function_ref<bool(DWARFDIE die)> callback) {
  if (!m_apple_objc_up)
    return;
  m_apple_objc_up->FindByName(
      class_name.GetStringRef(),
      DIERefCallback(callback, class_name.GetStringRef()));
}

void AppleDWARFIndex::GetCompleteObjCClass(
    ConstString class_name, bool must_be_implementation,
    llvm::function_ref<bool(DWARFDIE die)> callback) {
  if (!m_apple_types_up)
    return;
  m_apple_types_up->FindCompleteObjCClassByName(
      class_name.GetStringRef(),
      DIERefCallback(callback, class_name.GetStringRef()),
      must_be_implementation);
}

void AppleDWARFIndex::GetTypes(
    ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
  if (!m_apple_types_up)
    return;
  m_apple_types_up->FindByName(name.GetStringRef(),
                               DIERefCallback(callback, name.GetStringRef()));
}

void AppleDWARFIndex::GetTypes(
    const DWARFDeclContext &context,
    llvm::function_ref<bool(DWARFDIE die)> callback) {
  if (!m_apple_types_up)
    return;

  Log *log = LogChannelDWARF::GetLogIfAny(DWARF_LOG_TYPE_COMPLETION |
                                          DWARF_LOG_LOOKUPS);
  const bool has_tag = m_apple_types_up->GetHeader().header_data.ContainsAtom(
      DWARFMappedHash::eAtomTypeTag);
  const bool has_qualified_name_hash =
      m_apple_types_up->GetHeader().header_data.ContainsAtom(
          DWARFMappedHash::eAtomTypeQualNameHash);

  const ConstString type_name(context[0].name);
  const dw_tag_t tag = context[0].tag;
  if (has_tag && has_qualified_name_hash) {
    const char *qualified_name = context.GetQualifiedName();
    const uint32_t qualified_name_hash = llvm::djbHash(qualified_name);
    if (log)
      m_module.LogMessage(log, "FindByNameAndTagAndQualifiedNameHash()");
    m_apple_types_up->FindByNameAndTagAndQualifiedNameHash(
        type_name.GetStringRef(), tag, qualified_name_hash,
        DIERefCallback(callback, type_name.GetStringRef()));
    return;
  }

  if (has_tag) {
    // When searching for a scoped type (for example,
    // "std::vector<int>::const_iterator") searching for the innermost
    // name alone ("const_iterator") could yield many false
    // positives. By searching for the parent type ("vector<int>")
    // first we can avoid extracting type DIEs from object files that
    // would fail the filter anyway.
    if (!has_qualified_name_hash && (context.GetSize() > 1) &&
        (context[1].tag == DW_TAG_class_type ||
         context[1].tag == DW_TAG_structure_type)) {
      if (m_apple_types_up->FindByName(context[1].name,
                                       [&](DIERef ref) { return false; }))
        return;
    }

    if (log)
      m_module.LogMessage(log, "FindByNameAndTag()");
    m_apple_types_up->FindByNameAndTag(
        type_name.GetStringRef(), tag,
        DIERefCallback(callback, type_name.GetStringRef()));
    return;
  }

  m_apple_types_up->FindByName(
      type_name.GetStringRef(),
      DIERefCallback(callback, type_name.GetStringRef()));
}

void AppleDWARFIndex::GetNamespaces(
    ConstString name, llvm::function_ref<bool(DWARFDIE die)> callback) {
  if (!m_apple_namespaces_up)
    return;
  m_apple_namespaces_up->FindByName(
      name.GetStringRef(), DIERefCallback(callback, name.GetStringRef()));
}

void AppleDWARFIndex::GetFunctions(
    ConstString name, SymbolFileDWARF &dwarf,
    const CompilerDeclContext &parent_decl_ctx, uint32_t name_type_mask,
    llvm::function_ref<bool(DWARFDIE die)> callback) {
  m_apple_names_up->FindByName(name.GetStringRef(), [&](DIERef die_ref) {
    return ProcessFunctionDIE(name.GetStringRef(), die_ref, dwarf,
                              parent_decl_ctx, name_type_mask, callback);
  });
}

void AppleDWARFIndex::GetFunctions(
    const RegularExpression &regex,
    llvm::function_ref<bool(DWARFDIE die)> callback) {
  if (!m_apple_names_up)
    return;

  DWARFMappedHash::DIEInfoArray hash_data;
  m_apple_names_up->AppendAllDIEsThatMatchingRegex(regex, hash_data);
  DWARFMappedHash::ExtractDIEArray(hash_data,
                                   DIERefCallback(callback, regex.GetText()));
}

void AppleDWARFIndex::Dump(Stream &s) {
  if (m_apple_names_up)
    s.PutCString(".apple_names index present\n");
  if (m_apple_namespaces_up)
    s.PutCString(".apple_namespaces index present\n");
  if (m_apple_types_up)
    s.PutCString(".apple_types index present\n");
  if (m_apple_objc_up)
    s.PutCString(".apple_objc index present\n");
  // TODO: Dump index contents
}
