//===-- Variable.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/Variable.h"

#include "lldb/Core/Module.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectVariable.h"
#include "lldb/Symbol/Block.h"
#include "lldb/Symbol/CompileUnit.h"
#include "lldb/Symbol/CompilerDecl.h"
#include "lldb/Symbol/CompilerDeclContext.h"
#include "lldb/Symbol/Function.h"
#include "lldb/Symbol/SymbolContext.h"
#include "lldb/Symbol/SymbolFile.h"
#include "lldb/Symbol/Type.h"
#include "lldb/Symbol/TypeSystem.h"
#include "lldb/Symbol/VariableList.h"
#include "lldb/Target/ABI.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Target/StackFrame.h"
#include "lldb/Target/Target.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/RegularExpression.h"
#include "lldb/Utility/Stream.h"

#include "llvm/ADT/Twine.h"

using namespace lldb;
using namespace lldb_private;

Variable::Variable(lldb::user_id_t uid, const char *name, const char *mangled,
                   const lldb::SymbolFileTypeSP &symfile_type_sp,
                   ValueType scope, SymbolContextScope *context,
                   const RangeList &scope_range, Declaration *decl_ptr,
                   const DWARFExpression &location, bool external,
                   bool artificial, bool static_member)
    : UserID(uid), m_name(name), m_mangled(ConstString(mangled)),
      m_symfile_type_sp(symfile_type_sp), m_scope(scope),
      m_owner_scope(context), m_scope_range(scope_range),
      m_declaration(decl_ptr), m_location(location), m_external(external),
      m_artificial(artificial), m_loc_is_const_data(false),
      m_static_member(static_member) {}

Variable::~Variable() {}

lldb::LanguageType Variable::GetLanguage() const {
  lldb::LanguageType lang = m_mangled.GuessLanguage();
  if (lang != lldb::eLanguageTypeUnknown)
    return lang;

  if (auto *func = m_owner_scope->CalculateSymbolContextFunction()) {
    if ((lang = func->GetLanguage()) != lldb::eLanguageTypeUnknown)
      return lang;
  } else if (auto *comp_unit =
                 m_owner_scope->CalculateSymbolContextCompileUnit()) {
    if ((lang = comp_unit->GetLanguage()) != lldb::eLanguageTypeUnknown)
      return lang;
  }

  return lldb::eLanguageTypeUnknown;
}

ConstString Variable::GetName() const {
  ConstString name = m_mangled.GetName();
  if (name)
    return name;
  return m_name;
}

ConstString Variable::GetUnqualifiedName() const { return m_name; }

bool Variable::NameMatches(ConstString name) const {
  if (m_name == name)
    return true;
  SymbolContext variable_sc;
  m_owner_scope->CalculateSymbolContext(&variable_sc);

  return m_mangled.NameMatches(name);
}
bool Variable::NameMatches(const RegularExpression &regex) const {
  if (regex.Execute(m_name.AsCString()))
    return true;
  if (m_mangled)
    return m_mangled.NameMatches(regex);
  return false;
}

Type *Variable::GetType() {
  if (m_symfile_type_sp)
    return m_symfile_type_sp->GetType();
  return nullptr;
}

void Variable::Dump(Stream *s, bool show_context) const {
  s->Printf("%p: ", static_cast<const void *>(this));
  s->Indent();
  *s << "Variable" << (const UserID &)*this;

  if (m_name)
    *s << ", name = \"" << m_name << "\"";

  if (m_symfile_type_sp) {
    Type *type = m_symfile_type_sp->GetType();
    if (type) {
      s->Format(", type = {{{0:x-16}} {1} (", type->GetID(), type);
      type->DumpTypeName(s);
      s->PutChar(')');
    }
  }

  if (m_scope != eValueTypeInvalid) {
    s->PutCString(", scope = ");
    switch (m_scope) {
    case eValueTypeVariableGlobal:
      s->PutCString(m_external ? "global" : "static");
      break;
    case eValueTypeVariableArgument:
      s->PutCString("parameter");
      break;
    case eValueTypeVariableLocal:
      s->PutCString("local");
      break;
    case eValueTypeVariableThreadLocal:
      s->PutCString("thread local");
      break;
    default:
      s->AsRawOstream() << "??? (" << m_scope << ')';
    }
  }

  if (show_context && m_owner_scope != nullptr) {
    s->PutCString(", context = ( ");
    m_owner_scope->DumpSymbolContext(s);
    s->PutCString(" )");
  }

  bool show_fullpaths = false;
  m_declaration.Dump(s, show_fullpaths);

  if (m_location.IsValid()) {
    s->PutCString(", location = ");
    lldb::addr_t loclist_base_addr = LLDB_INVALID_ADDRESS;
    if (m_location.IsLocationList()) {
      SymbolContext variable_sc;
      m_owner_scope->CalculateSymbolContext(&variable_sc);
      if (variable_sc.function)
        loclist_base_addr = variable_sc.function->GetAddressRange()
                                .GetBaseAddress()
                                .GetFileAddress();
    }
    ABISP abi;
    if (m_owner_scope) {
      ModuleSP module_sp(m_owner_scope->CalculateSymbolContextModule());
      if (module_sp)
        abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());
    }
    m_location.GetDescription(s, lldb::eDescriptionLevelBrief,
                              loclist_base_addr, abi.get());
  }

  if (m_external)
    s->PutCString(", external");

  if (m_artificial)
    s->PutCString(", artificial");

  s->EOL();
}

bool Variable::DumpDeclaration(Stream *s, bool show_fullpaths,
                               bool show_module) {
  bool dumped_declaration_info = false;
  if (m_owner_scope) {
    SymbolContext sc;
    m_owner_scope->CalculateSymbolContext(&sc);
    sc.block = nullptr;
    sc.line_entry.Clear();
    bool show_inlined_frames = false;
    const bool show_function_arguments = true;
    const bool show_function_name = true;

    dumped_declaration_info = sc.DumpStopContext(
        s, nullptr, Address(), show_fullpaths, show_module, show_inlined_frames,
        show_function_arguments, show_function_name);

    if (sc.function)
      s->PutChar(':');
  }
  if (m_declaration.DumpStopContext(s, false))
    dumped_declaration_info = true;
  return dumped_declaration_info;
}

size_t Variable::MemorySize() const { return sizeof(Variable); }

CompilerDeclContext Variable::GetDeclContext() {
  Type *type = GetType();
  if (type)
    return type->GetSymbolFile()->GetDeclContextContainingUID(GetID());
  return CompilerDeclContext();
}

CompilerDecl Variable::GetDecl() {
  Type *type = GetType();
  return type ? type->GetSymbolFile()->GetDeclForUID(GetID()) : CompilerDecl();
}

void Variable::CalculateSymbolContext(SymbolContext *sc) {
  if (m_owner_scope) {
    m_owner_scope->CalculateSymbolContext(sc);
    sc->variable = this;
  } else
    sc->Clear(false);
}

bool Variable::LocationIsValidForFrame(StackFrame *frame) {
  // Is the variable is described by a single location?
  if (!m_location.IsLocationList()) {
    // Yes it is, the location is valid.
    return true;
  }

  if (frame) {
    Function *function =
        frame->GetSymbolContext(eSymbolContextFunction).function;
    if (function) {
      TargetSP target_sp(frame->CalculateTarget());

      addr_t loclist_base_load_addr =
          function->GetAddressRange().GetBaseAddress().GetLoadAddress(
              target_sp.get());
      if (loclist_base_load_addr == LLDB_INVALID_ADDRESS)
        return false;
      // It is a location list. We just need to tell if the location list
      // contains the current address when converted to a load address
      return m_location.LocationListContainsAddress(
          loclist_base_load_addr,
          frame->GetFrameCodeAddress().GetLoadAddress(target_sp.get()));
    }
  }
  return false;
}

bool Variable::LocationIsValidForAddress(const Address &address) {
  // Be sure to resolve the address to section offset prior to calling this
  // function.
  if (address.IsSectionOffset()) {
    SymbolContext sc;
    CalculateSymbolContext(&sc);
    if (sc.module_sp == address.GetModule()) {
      // Is the variable is described by a single location?
      if (!m_location.IsLocationList()) {
        // Yes it is, the location is valid.
        return true;
      }

      if (sc.function) {
        addr_t loclist_base_file_addr =
            sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
        if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
          return false;
        // It is a location list. We just need to tell if the location list
        // contains the current address when converted to a load address
        return m_location.LocationListContainsAddress(loclist_base_file_addr,
                                                      address.GetFileAddress());
      }
    }
  }
  return false;
}

bool Variable::IsInScope(StackFrame *frame) {
  switch (m_scope) {
  case eValueTypeRegister:
  case eValueTypeRegisterSet:
    return frame != nullptr;

  case eValueTypeConstResult:
  case eValueTypeVariableGlobal:
  case eValueTypeVariableStatic:
  case eValueTypeVariableThreadLocal:
    return true;

  case eValueTypeVariableArgument:
  case eValueTypeVariableLocal:
    if (frame) {
      // We don't have a location list, we just need to see if the block that
      // this variable was defined in is currently
      Block *deepest_frame_block =
          frame->GetSymbolContext(eSymbolContextBlock).block;
      if (deepest_frame_block) {
        SymbolContext variable_sc;
        CalculateSymbolContext(&variable_sc);

        // Check for static or global variable defined at the compile unit
        // level that wasn't defined in a block
        if (variable_sc.block == nullptr)
          return true;

        // Check if the variable is valid in the current block
        if (variable_sc.block != deepest_frame_block &&
            !variable_sc.block->Contains(deepest_frame_block))
          return false;

        // If no scope range is specified then it means that the scope is the
        // same as the scope of the enclosing lexical block.
        if (m_scope_range.IsEmpty())
          return true;

        addr_t file_address = frame->GetFrameCodeAddress().GetFileAddress();
        return m_scope_range.FindEntryThatContains(file_address) != nullptr;
      }
    }
    break;

  default:
    break;
  }
  return false;
}

Status Variable::GetValuesForVariableExpressionPath(
    llvm::StringRef variable_expr_path, ExecutionContextScope *scope,
    GetVariableCallback callback, void *baton, VariableList &variable_list,
    ValueObjectList &valobj_list) {
  Status error;
  if (!callback || variable_expr_path.empty()) {
    error.SetErrorString("unknown error");
    return error;
  }

  switch (variable_expr_path.front()) {
  case '*':
    error = Variable::GetValuesForVariableExpressionPath(
        variable_expr_path.drop_front(), scope, callback, baton, variable_list,
        valobj_list);
    if (error.Fail()) {
      error.SetErrorString("unknown error");
      return error;
    }
    for (uint32_t i = 0; i < valobj_list.GetSize();) {
      Status tmp_error;
      ValueObjectSP valobj_sp(
          valobj_list.GetValueObjectAtIndex(i)->Dereference(tmp_error));
      if (tmp_error.Fail()) {
        variable_list.RemoveVariableAtIndex(i);
        valobj_list.RemoveValueObjectAtIndex(i);
      } else {
        valobj_list.SetValueObjectAtIndex(i, valobj_sp);
        ++i;
      }
    }
    return error;
  case '&': {
    error = Variable::GetValuesForVariableExpressionPath(
        variable_expr_path.drop_front(), scope, callback, baton, variable_list,
        valobj_list);
    if (error.Success()) {
      for (uint32_t i = 0; i < valobj_list.GetSize();) {
        Status tmp_error;
        ValueObjectSP valobj_sp(
            valobj_list.GetValueObjectAtIndex(i)->AddressOf(tmp_error));
        if (tmp_error.Fail()) {
          variable_list.RemoveVariableAtIndex(i);
          valobj_list.RemoveValueObjectAtIndex(i);
        } else {
          valobj_list.SetValueObjectAtIndex(i, valobj_sp);
          ++i;
        }
      }
    } else {
      error.SetErrorString("unknown error");
    }
    return error;
  } break;

  default: {
    static RegularExpression g_regex(
        llvm::StringRef("^([A-Za-z_:][A-Za-z_0-9:]*)(.*)"));
    llvm::SmallVector<llvm::StringRef, 2> matches;
    variable_list.Clear();
    if (!g_regex.Execute(variable_expr_path, &matches)) {
      error.SetErrorStringWithFormat(
          "unable to extract a variable name from '%s'",
          variable_expr_path.str().c_str());
      return error;
    }
    std::string variable_name = matches[1].str();
    if (!callback(baton, variable_name.c_str(), variable_list)) {
      error.SetErrorString("unknown error");
      return error;
    }
    uint32_t i = 0;
    while (i < variable_list.GetSize()) {
      VariableSP var_sp(variable_list.GetVariableAtIndex(i));
      ValueObjectSP valobj_sp;
      if (!var_sp) {
        variable_list.RemoveVariableAtIndex(i);
        continue;
      }
      ValueObjectSP variable_valobj_sp(
          ValueObjectVariable::Create(scope, var_sp));
      if (!variable_valobj_sp) {
        variable_list.RemoveVariableAtIndex(i);
        continue;
      }

      llvm::StringRef variable_sub_expr_path =
          variable_expr_path.drop_front(variable_name.size());
      if (!variable_sub_expr_path.empty()) {
        valobj_sp = variable_valobj_sp->GetValueForExpressionPath(
            variable_sub_expr_path);
        if (!valobj_sp) {
          error.SetErrorStringWithFormat(
              "invalid expression path '%s' for variable '%s'",
              variable_sub_expr_path.str().c_str(),
              var_sp->GetName().GetCString());
          variable_list.RemoveVariableAtIndex(i);
          continue;
        }
      } else {
        // Just the name of a variable with no extras
        valobj_sp = variable_valobj_sp;
      }

      valobj_list.Append(valobj_sp);
      ++i;
    }

    if (variable_list.GetSize() > 0) {
      error.Clear();
      return error;
    }
  } break;
  }
  error.SetErrorString("unknown error");
  return error;
}

bool Variable::DumpLocationForAddress(Stream *s, const Address &address) {
  // Be sure to resolve the address to section offset prior to calling this
  // function.
  if (address.IsSectionOffset()) {
    SymbolContext sc;
    CalculateSymbolContext(&sc);
    if (sc.module_sp == address.GetModule()) {
      ABISP abi;
      if (m_owner_scope) {
        ModuleSP module_sp(m_owner_scope->CalculateSymbolContextModule());
        if (module_sp)
          abi = ABI::FindPlugin(ProcessSP(), module_sp->GetArchitecture());
      }

      const addr_t file_addr = address.GetFileAddress();
      if (sc.function) {
        if (sc.function->GetAddressRange().ContainsFileAddress(address)) {
          addr_t loclist_base_file_addr =
              sc.function->GetAddressRange().GetBaseAddress().GetFileAddress();
          if (loclist_base_file_addr == LLDB_INVALID_ADDRESS)
            return false;
          return m_location.DumpLocationForAddress(s, eDescriptionLevelBrief,
                                                   loclist_base_file_addr,
                                                   file_addr, abi.get());
        }
      }
      return m_location.DumpLocationForAddress(s, eDescriptionLevelBrief,
                                               LLDB_INVALID_ADDRESS, file_addr,
                                               abi.get());
    }
  }
  return false;
}

static void PrivateAutoComplete(
    StackFrame *frame, llvm::StringRef partial_path,
    const llvm::Twine
        &prefix_path, // Anything that has been resolved already will be in here
    const CompilerType &compiler_type, CompletionRequest &request);

static void PrivateAutoCompleteMembers(
    StackFrame *frame, const std::string &partial_member_name,
    llvm::StringRef partial_path,
    const llvm::Twine
        &prefix_path, // Anything that has been resolved already will be in here
    const CompilerType &compiler_type, CompletionRequest &request) {

  // We are in a type parsing child members
  const uint32_t num_bases = compiler_type.GetNumDirectBaseClasses();

  if (num_bases > 0) {
    for (uint32_t i = 0; i < num_bases; ++i) {
      CompilerType base_class_type =
          compiler_type.GetDirectBaseClassAtIndex(i, nullptr);

      PrivateAutoCompleteMembers(frame, partial_member_name, partial_path,
                                 prefix_path,
                                 base_class_type.GetCanonicalType(), request);
    }
  }

  const uint32_t num_vbases = compiler_type.GetNumVirtualBaseClasses();

  if (num_vbases > 0) {
    for (uint32_t i = 0; i < num_vbases; ++i) {
      CompilerType vbase_class_type =
          compiler_type.GetVirtualBaseClassAtIndex(i, nullptr);

      PrivateAutoCompleteMembers(frame, partial_member_name, partial_path,
                                 prefix_path,
                                 vbase_class_type.GetCanonicalType(), request);
    }
  }

  // We are in a type parsing child members
  const uint32_t num_fields = compiler_type.GetNumFields();

  if (num_fields > 0) {
    for (uint32_t i = 0; i < num_fields; ++i) {
      std::string member_name;

      CompilerType member_compiler_type = compiler_type.GetFieldAtIndex(
          i, member_name, nullptr, nullptr, nullptr);

      if (partial_member_name.empty() ||
          llvm::StringRef(member_name).startswith(partial_member_name)) {
        if (member_name == partial_member_name) {
          PrivateAutoComplete(
              frame, partial_path,
              prefix_path + member_name, // Anything that has been resolved
                                         // already will be in here
              member_compiler_type.GetCanonicalType(), request);
        } else {
          request.AddCompletion((prefix_path + member_name).str());
        }
      }
    }
  }
}

static void PrivateAutoComplete(
    StackFrame *frame, llvm::StringRef partial_path,
    const llvm::Twine
        &prefix_path, // Anything that has been resolved already will be in here
    const CompilerType &compiler_type, CompletionRequest &request) {
  //    printf ("\nPrivateAutoComplete()\n\tprefix_path = '%s'\n\tpartial_path =
  //    '%s'\n", prefix_path.c_str(), partial_path.c_str());
  std::string remaining_partial_path;

  const lldb::TypeClass type_class = compiler_type.GetTypeClass();
  if (partial_path.empty()) {
    if (compiler_type.IsValid()) {
      switch (type_class) {
      default:
      case eTypeClassArray:
      case eTypeClassBlockPointer:
      case eTypeClassBuiltin:
      case eTypeClassComplexFloat:
      case eTypeClassComplexInteger:
      case eTypeClassEnumeration:
      case eTypeClassFunction:
      case eTypeClassMemberPointer:
      case eTypeClassReference:
      case eTypeClassTypedef:
      case eTypeClassVector: {
        request.AddCompletion(prefix_path.str());
      } break;

      case eTypeClassClass:
      case eTypeClassStruct:
      case eTypeClassUnion:
        if (prefix_path.str().back() != '.')
          request.AddCompletion((prefix_path + ".").str());
        break;

      case eTypeClassObjCObject:
      case eTypeClassObjCInterface:
        break;
      case eTypeClassObjCObjectPointer:
      case eTypeClassPointer: {
        bool omit_empty_base_classes = true;
        if (compiler_type.GetNumChildren(omit_empty_base_classes, nullptr) > 0)
          request.AddCompletion((prefix_path + "->").str());
        else {
          request.AddCompletion(prefix_path.str());
        }
      } break;
      }
    } else {
      if (frame) {
        const bool get_file_globals = true;

        VariableList *variable_list = frame->GetVariableList(get_file_globals);

        if (variable_list) {
          for (const VariableSP &var_sp : *variable_list)
            request.AddCompletion(var_sp->GetName().AsCString());
        }
      }
    }
  } else {
    const char ch = partial_path[0];
    switch (ch) {
    case '*':
      if (prefix_path.str().empty()) {
        PrivateAutoComplete(frame, partial_path.substr(1), "*", compiler_type,
                            request);
      }
      break;

    case '&':
      if (prefix_path.isTriviallyEmpty()) {
        PrivateAutoComplete(frame, partial_path.substr(1), std::string("&"),
                            compiler_type, request);
      }
      break;

    case '-':
      if (partial_path.size() > 1 && partial_path[1] == '>' &&
          !prefix_path.str().empty()) {
        switch (type_class) {
        case lldb::eTypeClassPointer: {
          CompilerType pointee_type(compiler_type.GetPointeeType());
          if (partial_path.size() > 2 && partial_path[2]) {
            // If there is more after the "->", then search deeper
            PrivateAutoComplete(frame, partial_path.substr(2),
                                prefix_path + "->",
                                pointee_type.GetCanonicalType(), request);
          } else {
            // Nothing after the "->", so list all members
            PrivateAutoCompleteMembers(
                frame, std::string(), std::string(), prefix_path + "->",
                pointee_type.GetCanonicalType(), request);
          }
        } break;
        default:
          break;
        }
      }
      break;

    case '.':
      if (compiler_type.IsValid()) {
        switch (type_class) {
        case lldb::eTypeClassUnion:
        case lldb::eTypeClassStruct:
        case lldb::eTypeClassClass:
          if (partial_path.size() > 1 && partial_path[1]) {
            // If there is more after the ".", then search deeper
            PrivateAutoComplete(frame, partial_path.substr(1),
                                prefix_path + ".", compiler_type, request);

          } else {
            // Nothing after the ".", so list all members
            PrivateAutoCompleteMembers(frame, std::string(), partial_path,
                                       prefix_path + ".", compiler_type,
                                       request);
          }
          break;
        default:
          break;
        }
      }
      break;
    default:
      if (isalpha(ch) || ch == '_' || ch == '$') {
        const size_t partial_path_len = partial_path.size();
        size_t pos = 1;
        while (pos < partial_path_len) {
          const char curr_ch = partial_path[pos];
          if (isalnum(curr_ch) || curr_ch == '_' || curr_ch == '$') {
            ++pos;
            continue;
          }
          break;
        }

        std::string token(std::string(partial_path), 0, pos);
        remaining_partial_path = std::string(partial_path.substr(pos));

        if (compiler_type.IsValid()) {
          PrivateAutoCompleteMembers(frame, token, remaining_partial_path,
                                     prefix_path, compiler_type, request);
        } else if (frame) {
          // We haven't found our variable yet
          const bool get_file_globals = true;

          VariableList *variable_list =
              frame->GetVariableList(get_file_globals);

          if (!variable_list)
            break;

          for (VariableSP var_sp : *variable_list) {

            if (!var_sp)
              continue;

            llvm::StringRef variable_name = var_sp->GetName().GetStringRef();
            if (variable_name.startswith(token)) {
              if (variable_name == token) {
                Type *variable_type = var_sp->GetType();
                if (variable_type) {
                  CompilerType variable_compiler_type(
                      variable_type->GetForwardCompilerType());
                  PrivateAutoComplete(
                      frame, remaining_partial_path,
                      prefix_path + token, // Anything that has been resolved
                                           // already will be in here
                      variable_compiler_type.GetCanonicalType(), request);
                } else {
                  request.AddCompletion((prefix_path + variable_name).str());
                }
              } else if (remaining_partial_path.empty()) {
                request.AddCompletion((prefix_path + variable_name).str());
              }
            }
          }
        }
      }
      break;
    }
  }
}

void Variable::AutoComplete(const ExecutionContext &exe_ctx,
                            CompletionRequest &request) {
  CompilerType compiler_type;

  PrivateAutoComplete(exe_ctx.GetFramePtr(), request.GetCursorArgumentPrefix(),
                      "", compiler_type, request);
}
