//===-- CompileUnit.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 "lldb/Symbol/CompileUnit.h"
#include "lldb/Core/Module.h"
#include "lldb/Symbol/LineTable.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/Language.h"
#include "lldb/Utility/Timer.h"
#include <optional>

using namespace lldb;
using namespace lldb_private;

CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data,
                         const char *pathname, const lldb::user_id_t cu_sym_id,
                         lldb::LanguageType language,
                         lldb_private::LazyBool is_optimized)
    : CompileUnit(module_sp, user_data,
                  std::make_shared<SupportFile>(FileSpec(pathname)), cu_sym_id,
                  language, is_optimized) {}

CompileUnit::CompileUnit(const lldb::ModuleSP &module_sp, void *user_data,
                         SupportFileNSP support_file_nsp,
                         const lldb::user_id_t cu_sym_id,
                         lldb::LanguageType language,
                         lldb_private::LazyBool is_optimized,
                         SupportFileList &&support_files)
    : ModuleChild(module_sp), UserID(cu_sym_id), m_user_data(user_data),
      m_language(language), m_flags(0),
      m_primary_support_file_nsp(support_file_nsp),
      m_support_files(std::move(support_files)), m_is_optimized(is_optimized) {
  if (language != eLanguageTypeUnknown)
    m_flags.Set(flagsParsedLanguage);
  assert(module_sp);
}

void CompileUnit::CalculateSymbolContext(SymbolContext *sc) {
  sc->comp_unit = this;
  GetModule()->CalculateSymbolContext(sc);
}

ModuleSP CompileUnit::CalculateSymbolContextModule() { return GetModule(); }

CompileUnit *CompileUnit::CalculateSymbolContextCompileUnit() { return this; }

void CompileUnit::DumpSymbolContext(Stream *s) {
  GetModule()->DumpSymbolContext(s);
  s->Printf(", CompileUnit{0x%8.8" PRIx64 "}", GetID());
}

void CompileUnit::GetDescription(Stream *s,
                                 lldb::DescriptionLevel level) const {
  const char *language = GetCachedLanguage();
  *s << "id = " << (const UserID &)*this << ", file = \""
     << this->GetPrimaryFile() << "\", language = \"" << language << '"';
}

void CompileUnit::ForeachFunction(
    llvm::function_ref<bool(const FunctionSP &)> lambda) const {
  std::vector<lldb::FunctionSP> sorted_functions;
  sorted_functions.reserve(m_functions_by_uid.size());
  for (auto &p : m_functions_by_uid)
    sorted_functions.push_back(p.second);
  llvm::sort(sorted_functions,
             [](const lldb::FunctionSP &a, const lldb::FunctionSP &b) {
               return a->GetID() < b->GetID();
             });

  for (auto &f : sorted_functions)
    if (lambda(f))
      return;
}

lldb::FunctionSP CompileUnit::FindFunction(
    llvm::function_ref<bool(const FunctionSP &)> matching_lambda) {
  LLDB_SCOPED_TIMER();

  lldb::ModuleSP module = CalculateSymbolContextModule();

  if (!module)
    return {};

  SymbolFile *symbol_file = module->GetSymbolFile();

  if (!symbol_file)
    return {};

  // m_functions_by_uid is filled in lazily but we need all the entries.
  symbol_file->ParseFunctions(*this);

  for (auto &p : m_functions_by_uid) {
    if (matching_lambda(p.second))
      return p.second;
  }
  return {};
}

const char *CompileUnit::GetCachedLanguage() const {
  if (m_flags.IsClear(flagsParsedLanguage))
    return "<not loaded>";
  return Language::GetNameForLanguageType(m_language);
}

// Dump the current contents of this object. No functions that cause on demand
// parsing of functions, globals, statics are called, so this is a good
// function to call to get an idea of the current contents of the CompileUnit
// object.
void CompileUnit::Dump(Stream *s, bool show_context) const {
  const char *language = GetCachedLanguage();

  s->Printf("%p: ", static_cast<const void *>(this));
  s->Indent();
  *s << "CompileUnit" << static_cast<const UserID &>(*this) << ", language = \""
     << language << "\", file = '" << GetPrimaryFile() << "'\n";

  //  m_types.Dump(s);

  if (m_variables.get()) {
    s->IndentMore();
    m_variables->Dump(s, show_context);
    s->IndentLess();
  }

  if (!m_functions_by_uid.empty()) {
    s->IndentMore();
    ForeachFunction([&s, show_context](const FunctionSP &f) {
      f->Dump(s, show_context);
      return false;
    });

    s->IndentLess();
    s->EOL();
  }
}

// Add a function to this compile unit
void CompileUnit::AddFunction(FunctionSP &funcSP) {
  m_functions_by_uid[funcSP->GetID()] = funcSP;
}

FunctionSP CompileUnit::FindFunctionByUID(lldb::user_id_t func_uid) {
  auto it = m_functions_by_uid.find(func_uid);
  if (it == m_functions_by_uid.end())
    return FunctionSP();
  return it->second;
}

lldb::LanguageType CompileUnit::GetLanguage() {
  ModuleSP module_sp = GetModule();

  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  if (m_language == eLanguageTypeUnknown) {
    if (m_flags.IsClear(flagsParsedLanguage)) {
      m_flags.Set(flagsParsedLanguage);
      if (SymbolFile *symfile = module_sp->GetSymbolFile())
        m_language = symfile->ParseLanguage(*this);
    }
  }
  return m_language;
}

LineTable *CompileUnit::GetLineTable() {
  ModuleSP module_sp = GetModule();

  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  if (m_line_table_up == nullptr) {
    // The flag is set before parsing so that a SymbolFile that asks for the
    // line table while parsing it doesn't recurse forever.
    if (m_flags.IsClear(flagsParsedLineTable)) {
      m_flags.Set(flagsParsedLineTable);
      if (SymbolFile *symfile = module_sp->GetSymbolFile())
        symfile->ParseLineTable(*this);
    }
  }
  return m_line_table_up.get();
}

void CompileUnit::SetLineTable(LineTable *line_table) {
  // SymbolFile calls this while holding the Module's lock, which is the lock
  // GetLineTable() takes as well.
  if (line_table == nullptr)
    m_flags.Clear(flagsParsedLineTable);
  else
    m_flags.Set(flagsParsedLineTable);
  m_line_table_up.reset(line_table);
}

DebugMacros *CompileUnit::GetDebugMacros() {
  ModuleSP module_sp = GetModule();

  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  if (m_debug_macros_sp.get() == nullptr) {
    if (m_flags.IsClear(flagsParsedDebugMacros)) {
      m_flags.Set(flagsParsedDebugMacros);
      if (SymbolFile *symfile = module_sp->GetSymbolFile())
        symfile->ParseDebugMacros(*this);
    }
  }

  return m_debug_macros_sp.get();
}

void CompileUnit::SetDebugMacros(const DebugMacrosSP &debug_macros_sp) {
  if (debug_macros_sp.get() == nullptr)
    m_flags.Clear(flagsParsedDebugMacros);
  else
    m_flags.Set(flagsParsedDebugMacros);
  m_debug_macros_sp = debug_macros_sp;
}

VariableListSP CompileUnit::GetVariableList(bool can_create) {
  if (m_variables.get() == nullptr && can_create) {
    SymbolContext sc;
    CalculateSymbolContext(&sc);
    assert(sc.module_sp);
    sc.module_sp->GetSymbolFile()->ParseVariablesForContext(sc);
  }

  return m_variables;
}

std::vector<uint32_t>
FindFileIndexes(const SupportFileList &files, const FileSpec &file,
                RealpathPrefixes *realpath_prefixes = nullptr) {
  std::vector<uint32_t> result;
  uint32_t idx = -1;
  while ((idx = files.FindCompatibleIndex(idx + 1, file, realpath_prefixes)) !=
         UINT32_MAX)
    result.push_back(idx);
  return result;
}

uint32_t CompileUnit::FindLineEntry(uint32_t start_idx, uint32_t line,
                                    const FileSpec *file_spec_ptr, bool exact,
                                    LineEntry *line_entry_ptr) {
  if (!file_spec_ptr)
    file_spec_ptr = &GetPrimaryFile();
  std::vector<uint32_t> file_indexes = FindFileIndexes(GetSupportFiles(),
                                                       *file_spec_ptr);
  if (file_indexes.empty())
    return UINT32_MAX;

  // TODO: Handle SourceLocationSpec column information
  SourceLocationSpec location_spec(*file_spec_ptr, line,
                                   /*column=*/std::nullopt,
                                   /*check_inlines=*/false, exact);

  LineTable *line_table = GetLineTable();
  if (line_table)
    return line_table->FindLineEntryIndexByFileIndex(
        start_idx, file_indexes, location_spec, line_entry_ptr);
  return UINT32_MAX;
}

void CompileUnit::ResolveSymbolContext(
    const SourceLocationSpec &src_location_spec,
    SymbolContextItem resolve_scope, SymbolContextList &sc_list,
    RealpathPrefixes *realpath_prefixes) {
  const FileSpec file_spec = src_location_spec.GetFileSpec();
  const uint32_t line =
      src_location_spec.GetLine().value_or(LLDB_INVALID_LINE_NUMBER);
  const uint32_t column_num =
      src_location_spec.GetColumn().value_or(LLDB_INVALID_COLUMN_NUMBER);
  const bool check_inlines = src_location_spec.GetCheckInlines();

  // First find all of the file indexes that match our "file_spec". If
  // "file_spec" has an empty directory, then only compare the basenames when
  // finding file indexes
  bool file_spec_matches_cu_file_spec =
      FileSpec::Match(file_spec, this->GetPrimaryFile());

  // If we are not looking for inlined functions and our file spec doesn't
  // match then we are done...
  if (!file_spec_matches_cu_file_spec && !check_inlines)
    return;

  SymbolContext sc(GetModule());
  sc.comp_unit = this;

  if (line == LLDB_INVALID_LINE_NUMBER) {
    if (file_spec_matches_cu_file_spec && !check_inlines) {
      // only append the context if we aren't looking for inline call sites by
      // file and line and if the file spec matches that of the compile unit
      sc_list.Append(sc);
    }
    return;
  }

  std::vector<uint32_t> file_indexes =
      FindFileIndexes(GetSupportFiles(), file_spec, realpath_prefixes);
  const size_t num_file_indexes = file_indexes.size();
  if (num_file_indexes == 0)
    return;

  // Found a matching source file in this compile unit load its debug info.
  GetModule()->GetSymbolFile()->SetLoadDebugInfoEnabled();

  LineTable *line_table = sc.comp_unit->GetLineTable();

  if (line_table == nullptr) {
    if (file_spec_matches_cu_file_spec && !check_inlines) {
      sc_list.Append(sc);
    }
    return;
  }

  uint32_t line_idx;
  LineEntry line_entry;

  if (num_file_indexes == 1) {
    // We only have a single support file that matches, so use the line
    // table function that searches for a line entries that match a single
    // support file index
    line_idx = line_table->FindLineEntryIndexByFileIndex(
        0, file_indexes.front(), src_location_spec, &line_entry);
  } else {
    // We found multiple support files that match "file_spec" so use the
    // line table function that searches for a line entries that match a
    // multiple support file indexes.
    line_idx = line_table->FindLineEntryIndexByFileIndex(
        0, file_indexes, src_location_spec, &line_entry);
  }

  // If we didn't manage to find a breakpoint that matched the line number
  // requested, that might be because it is only an inline call site, and
  // doesn't have a line entry in the line table.  Scan for that here.
  //
  // We are making the assumption that if there was an inlined function it will
  // contribute at least 1 non-call-site entry to the line table.  That's handy
  // because we don't move line breakpoints over function boundaries, so if we
  // found a hit, and there were also a call site entry, it would have to be in
  // the function containing the PC of the line table match.  That way we can
  // limit the call site search to that function.
  // We will miss functions that ONLY exist as a call site entry.

  if (line_entry.IsValid() &&
      (line_entry.line != line ||
       (column_num != 0 && line_entry.column != column_num)) &&
      (resolve_scope & eSymbolContextLineEntry) && check_inlines) {
    // We don't move lines over function boundaries, so the address in the
    // line entry will be the in function that contained the line that might
    // be a CallSite, and we can just iterate over that function to find any
    // inline records, and dig up their call sites.
    Address start_addr = line_entry.range.GetBaseAddress();
    Function *function = start_addr.CalculateSymbolContextFunction();
    // Record the size of the list to see if we added to it:
    size_t old_sc_list_size = sc_list.GetSize();

    Declaration sought_decl(file_spec, line, column_num);
    // We use this recursive function to descend the block structure looking
    // for a block that has this Declaration as in it's CallSite info.
    // This function recursively scans the sibling blocks of the incoming
    // block parameter.
    std::function<void(Block &)> examine_block =
        [&sought_decl, &sc_list, &src_location_spec, resolve_scope,
         &examine_block](Block &block) -> void {
      // Iterate over the sibling child blocks of the incoming block.
      Block *sibling_block = block.GetFirstChild();
      while (sibling_block) {
        // We only have to descend through the regular blocks, looking for
        // immediate inlines, since those are the only ones that will have this
        // callsite.
        const InlineFunctionInfo *inline_info =
            sibling_block->GetInlinedFunctionInfo();
        if (inline_info) {
          // If this is the call-site we are looking for, record that:
          // We need to be careful because the call site from the debug info
          // will generally have a column, but the user might not have specified
          // it.
          Declaration found_decl = inline_info->GetCallSite();
          uint32_t sought_column = sought_decl.GetColumn();
          if (found_decl.FileAndLineEqual(sought_decl, false) &&
              (sought_column == LLDB_INVALID_COLUMN_NUMBER ||
               sought_column == found_decl.GetColumn())) {
            // If we found a call site, it belongs not in this inlined block,
            // but in the parent block that inlined it.
            Address parent_start_addr;
            if (sibling_block->GetParent()->GetStartAddress(
                    parent_start_addr)) {
              SymbolContext sc;
              parent_start_addr.CalculateSymbolContext(&sc, resolve_scope);
              // Now swap out the line entry for the one we found.
              LineEntry call_site_line = sc.line_entry;
              call_site_line.line = found_decl.GetLine();
              call_site_line.column = found_decl.GetColumn();
              bool matches_spec = true;
              // If the user asked for an exact match, we need to make sure the
              // call site we found actually matches the location.
              if (src_location_spec.GetExactMatch()) {
                matches_spec = false;
                if ((src_location_spec.GetFileSpec() ==
                     sc.line_entry.GetFile()) &&
                    (src_location_spec.GetLine() &&
                     *src_location_spec.GetLine() == call_site_line.line) &&
                    (src_location_spec.GetColumn() &&
                     *src_location_spec.GetColumn() == call_site_line.column))
                  matches_spec = true;
              }
              if (matches_spec &&
                  sibling_block->GetRangeAtIndex(0, call_site_line.range)) {
                SymbolContext call_site_sc(sc.target_sp, sc.module_sp,
                                           sc.comp_unit, sc.function, sc.block,
                                           &call_site_line, sc.symbol);
                sc_list.Append(call_site_sc);
              }
            }
          }
        }

        // Descend into the child blocks:
        examine_block(*sibling_block);
        // Now go to the next sibling:
        sibling_block = sibling_block->GetSibling();
      }
    };

    if (function) {
      // We don't need to examine the function block, it can't be inlined.
      Block &func_block = function->GetBlock(true);
      examine_block(func_block);
    }
    // If we found entries here, we are done.  We only get here because we
    // didn't find an exact line entry for this line & column, but if we found
    // an exact match from the call site info that's strictly better than
    // continuing to look for matches further on in the file.
    // FIXME: Should I also do this for "call site line exists between the
    // given line number and the later line we found in the line table"?  That's
    // a closer approximation to our general sliding algorithm.
    if (sc_list.GetSize() > old_sc_list_size)
      return;
  }

  // If "exact == true", then "found_line" will be the same as "line". If
  // "exact == false", the "found_line" will be the closest line entry
  // with a line number greater than "line" and we will use this for our
  // subsequent line exact matches below.
  const bool inlines = false;
  const bool exact = true;
  const std::optional<uint16_t> column =
      src_location_spec.GetColumn() ? std::optional<uint16_t>(line_entry.column)
                                    : std::nullopt;

  SourceLocationSpec found_entry(line_entry.GetFile(), line_entry.line, column,
                                 inlines, exact);

  while (line_idx != UINT32_MAX) {
    // If they only asked for the line entry, then we're done, we can
    // just copy that over. But if they wanted more than just the line
    // number, fill it in.
    SymbolContext resolved_sc;
    sc.line_entry = line_entry;
    if (resolve_scope == eSymbolContextLineEntry) {
      sc_list.Append(sc);
    } else {
      line_entry.range.GetBaseAddress().CalculateSymbolContext(&resolved_sc,
                                                               resolve_scope);
      // Sometimes debug info is bad and isn't able to resolve the line entry's
      // address back to the same compile unit and/or line entry. If the compile
      // unit changed, then revert back to just the compile unit and line entry.
      // Prior to this fix, the above code might end up not being able to lookup
      // the address, and then it would clear compile unit and the line entry in
      // the symbol context and the breakpoint would fail to get set even though
      // we have a valid line table entry in this compile unit. The address
      // lookup can also end up finding another function in another compiler
      // unit if the DWARF has overlappging address ranges. So if we end up with
      // no compile unit or a different one after the above function call,
      // revert back to the same results as if resolve_scope was set exactly to
      // eSymbolContextLineEntry.
      if (resolved_sc.comp_unit == this) {
        sc_list.Append(resolved_sc);
      } else {
        if (resolved_sc.comp_unit == nullptr && resolved_sc.module_sp) {
          // Only report an error if we don't map back to any compile unit. With
          // link time optimizations, the debug info might have many compile
          // units that have the same address range due to function outlining
          // or other link time optimizations. If the compile unit is NULL, then
          // address resolving is completely failing and more deserving of an
          // error message the user can see.
          resolved_sc.module_sp->ReportError(
              "unable to resolve a line table file address {0:x16} back "
              "to a compile unit, please file a bug and attach the address "
              "and file.",
              line_entry.range.GetBaseAddress().GetFileAddress());
        }
        sc_list.Append(sc);
      }
    }

    if (num_file_indexes == 1)
      line_idx = line_table->FindLineEntryIndexByFileIndex(
          line_idx + 1, file_indexes.front(), found_entry, &line_entry);
    else
      line_idx = line_table->FindLineEntryIndexByFileIndex(
          line_idx + 1, file_indexes, found_entry, &line_entry);
  }
}

bool CompileUnit::GetIsOptimized() {
  ModuleSP module_sp = GetModule();

  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  if (m_is_optimized == eLazyBoolCalculate) {
    m_is_optimized = eLazyBoolNo;
    if (SymbolFile *symfile = module_sp->GetSymbolFile()) {
      if (symfile->ParseIsOptimized(*this))
        m_is_optimized = eLazyBoolYes;
    }
  }
  return m_is_optimized;
}

std::recursive_mutex &CompileUnit::GetMutex() const {
  ModuleSP module_sp = GetModule();
  assert(module_sp && "Called without module?");
  return module_sp->GetMutex();
}

void CompileUnit::SetVariableList(VariableListSP &variables) {
  m_variables = variables;
}

const std::vector<SourceModule> &CompileUnit::GetImportedModules() {
  ModuleSP module_sp = GetModule();

  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  if (m_imported_modules.empty() &&
      m_flags.IsClear(flagsParsedImportedModules)) {
    m_flags.Set(flagsParsedImportedModules);
    if (SymbolFile *symfile = module_sp->GetSymbolFile()) {
      SymbolContext sc;
      CalculateSymbolContext(&sc);
      symfile->ParseImportedModules(sc, m_imported_modules);
    }
  }
  return m_imported_modules;
}

bool CompileUnit::ForEachExternalModule(
    llvm::DenseSet<SymbolFile *> &visited_symbol_files,
    llvm::function_ref<bool(Module &)> lambda) {
  if (SymbolFile *symfile = GetModule()->GetSymbolFile())
    return symfile->ForEachExternalModule(*this, visited_symbol_files, lambda);
  return false;
}

const SupportFileList &CompileUnit::GetSupportFiles() {
  ModuleSP module_sp = GetModule();

  std::lock_guard<std::recursive_mutex> guard(GetMutex());
  if (m_support_files.GetSize() == 0) {
    if (m_flags.IsClear(flagsParsedSupportFiles)) {
      m_flags.Set(flagsParsedSupportFiles);
      if (SymbolFile *symfile = module_sp->GetSymbolFile())
        symfile->ParseSupportFiles(*this, m_support_files);
    }
  }
  return m_support_files;
}

void *CompileUnit::GetUserData() const { return m_user_data; }
