// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "src/developer/debug/zxdb/expr/eval_context_impl.h"

#include <lib/syslog/cpp/macros.h>

#include "src/developer/debug/shared/message_loop.h"
#include "src/developer/debug/zxdb/common/adapters.h"
#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/expr/async_dwarf_expr_eval.h"
#include "src/developer/debug/zxdb/expr/builtin_types.h"
#include "src/developer/debug/zxdb/expr/expr_value.h"
#include "src/developer/debug/zxdb/expr/find_name.h"
#include "src/developer/debug/zxdb/expr/resolve_collection.h"
#include "src/developer/debug/zxdb/expr/resolve_const_value.h"
#include "src/developer/debug/zxdb/expr/resolve_ptr_ref.h"
#include "src/developer/debug/zxdb/expr/resolve_type.h"
#include "src/developer/debug/zxdb/symbols/array_type.h"
#include "src/developer/debug/zxdb/symbols/base_type.h"
#include "src/developer/debug/zxdb/symbols/code_block.h"
#include "src/developer/debug/zxdb/symbols/compile_unit.h"
#include "src/developer/debug/zxdb/symbols/data_member.h"
#include "src/developer/debug/zxdb/symbols/dwarf_expr_eval.h"
#include "src/developer/debug/zxdb/symbols/function.h"
#include "src/developer/debug/zxdb/symbols/identifier.h"
#include "src/developer/debug/zxdb/symbols/input_location.h"
#include "src/developer/debug/zxdb/symbols/location.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"
#include "src/developer/debug/zxdb/symbols/process_symbols.h"
#include "src/developer/debug/zxdb/symbols/symbol_data_provider.h"
#include "src/developer/debug/zxdb/symbols/variable.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {
namespace {

using debug_ipc::RegisterID;

RegisterID GetRegisterID(const ParsedIdentifier& ident) {
  // Check for explicit register identifier annotation.
  if (ident.components().size() == 1 &&
      ident.components()[0].special() == SpecialIdentifier::kRegister) {
    return debug_ipc::StringToRegisterID(ident.components()[0].name());
  }

  // Try to convert the identifier string to a register name.
  auto str = GetSingleComponentIdentifierName(ident);
  if (!str)
    return debug_ipc::RegisterID::kUnknown;
  return debug_ipc::StringToRegisterID(*str);
}

Err GetUnavailableRegisterErr(RegisterID id) {
  return Err("Register %s unavailable in this context.", debug_ipc::RegisterIDToString(id));
}

ErrOrValue RegisterDataToValue(RegisterID id, VectorRegisterFormat vector_fmt,
                               containers::array_view<uint8_t> data) {
  if (ShouldFormatRegisterAsVector(id))
    return VectorRegisterToValue(id, vector_fmt, std::vector<uint8_t>(data.begin(), data.end()));

  ExprValueSource source(id);

  if (data.size() <= sizeof(uint64_t)) {
    uint64_t int_value = 0;
    memcpy(&int_value, &data[0], data.size());

    // Use the types defined by ExprValue for the unsigned number of the corresponding size.
    // Passing a null type will cause ExprValue to create one matching the input type.
    switch (data.size()) {
      case 1:
        return ExprValue(static_cast<uint8_t>(int_value), fxl::RefPtr<Type>(), source);
      case 2:
        return ExprValue(static_cast<uint16_t>(int_value), fxl::RefPtr<Type>(), source);
      case 4:
        return ExprValue(static_cast<uint32_t>(int_value), fxl::RefPtr<Type>(), source);
      case 8:
        return ExprValue(static_cast<uint64_t>(int_value), fxl::RefPtr<Type>(), source);
    }
  }

  // Large and/or weird sized registers.
  const char* type_name;
  if (data.size() == sizeof(uint128_t))
    type_name = "uint128_t";
  else
    type_name = "(register data)";

  return ExprValue(
      fxl::MakeRefCounted<BaseType>(BaseType::kBaseTypeUnsigned, data.size(), type_name),
      std::vector<uint8_t>(data.begin(), data.end()), source);
}

}  // namespace

EvalContextImpl::EvalContextImpl(fxl::WeakPtr<const ProcessSymbols> process_symbols,
                                 fxl::RefPtr<SymbolDataProvider> data_provider,
                                 ExprLanguage language, fxl::RefPtr<CodeBlock> code_block)
    : process_symbols_(std::move(process_symbols)),
      data_provider_(data_provider),
      block_(std::move(code_block)),
      language_(language),
      weak_factory_(this) {}

EvalContextImpl::EvalContextImpl(fxl::WeakPtr<const ProcessSymbols> process_symbols,
                                 fxl::RefPtr<SymbolDataProvider> data_provider,
                                 const Location& location,
                                 std::optional<ExprLanguage> force_language)
    : process_symbols_(std::move(process_symbols)),
      data_provider_(data_provider),
      weak_factory_(this) {
  const CodeBlock* function = nullptr;
  if (location.symbol())
    function = location.symbol().Get()->AsCodeBlock();

  if (function) {
    block_ =
        RefPtrTo(function->GetMostSpecificChild(location.symbol_context(), location.address()));
  }

  if (force_language) {
    language_ = *force_language;
  } else if (function) {
    // Extract the language for the code if possible.
    if (auto unit = function->GetCompileUnit())
      language_ = DwarfLangToExprLanguage(unit->language());
  }
}

EvalContextImpl::~EvalContextImpl() = default;

ExprLanguage EvalContextImpl::GetLanguage() const { return language_; }

FindNameContext EvalContextImpl::GetFindNameContext() const {
  // The symbol context for the current location is passed to the FindNameContext to prioritize
  // the current module's values when searching for variables. If relative, this will be ignored.
  SymbolContext symbol_context = SymbolContext::ForRelativeAddresses();
  if (block_ && process_symbols_)
    symbol_context = block_->GetSymbolContext(process_symbols_.get());
  return FindNameContext(process_symbols_.get(), symbol_context, block_.get());
}

void EvalContextImpl::GetNamedValue(const ParsedIdentifier& identifier, EvalCallback cb) const {
  if (FoundName found =
          FindName(GetFindNameContext(), FindNameOptions(FindNameOptions::kAllKinds), identifier)) {
    switch (found.kind()) {
      case FoundName::kVariable:
      case FoundName::kMemberVariable:
        DoResolve(std::move(found), std::move(cb));
        return;
      case FoundName::kNamespace:
        cb(Err("Can not evaluate a namespace."));
        return;
      case FoundName::kTemplate:
        cb(Err("Can not evaluate a template with no parameters."));
        return;
      case FoundName::kType:
        cb(Err("Can not evaluate a type."));
        return;
      case FoundName::kFunction:
      case FoundName::kOtherSymbol:
        break;  // Function pointers not supported yet.
      case FoundName::kNone:
        break;  // Fall through to checking other stuff.
    }
  }

  auto reg = GetRegisterID(identifier);
  if (reg == RegisterID::kUnknown || GetArchForRegisterID(reg) != data_provider_->GetArch())
    return cb(Err("No variable '%s' found.", identifier.GetFullName().c_str()));

  // Fall back to matching registers when no symbol is found.
  if (std::optional<containers::array_view<uint8_t>> opt_reg_data =
          data_provider_->GetRegister(reg)) {
    // Available synchronously.
    if (opt_reg_data->empty())
      cb(GetUnavailableRegisterErr(reg));
    else
      cb(RegisterDataToValue(reg, GetVectorRegisterFormat(), *opt_reg_data));
  } else {
    data_provider_->GetRegisterAsync(
        reg, [reg, vector_fmt = GetVectorRegisterFormat(), cb = std::move(cb)](
                 const Err& err, std::vector<uint8_t> value) mutable {
          if (err.has_error()) {
            cb(err);
          } else if (value.empty()) {
            cb(GetUnavailableRegisterErr(reg));
          } else {
            cb(RegisterDataToValue(reg, vector_fmt, value));
          }
        });
  }
}

void EvalContextImpl::GetVariableValue(fxl::RefPtr<Value> input_val, EvalCallback cb) const {
  // Handle const values.
  if (input_val->const_value().has_value())
    return cb(ResolveConstValue(RefPtrTo(this), input_val.get()));

  fxl::RefPtr<Variable> var;
  if (input_val->is_external()) {
    // Convert extern Variables and DataMembers to the actual variable memory.
    if (Err err = ResolveExternValue(input_val, &var); err.has_error())
      return cb(err);
  } else {
    // Everything else should be a variable.
    var = RefPtrTo(input_val->AsVariable());
    FX_DCHECK(var);
  }

  SymbolContext symbol_context = var->GetSymbolContext(process_symbols_.get());

  // Need to explicitly take a reference to the type.
  fxl::RefPtr<Type> type = RefPtrTo(var->type().Get()->AsType());
  if (!type)
    return cb(Err("Missing type information."));

  std::optional<containers::array_view<uint8_t>> ip_data =
      data_provider_->GetRegister(debug_ipc::GetSpecialRegisterID(
          data_provider_->GetArch(), debug_ipc::SpecialRegisterType::kIP));
  TargetPointer ip;
  if (!ip_data || ip_data->size() != sizeof(ip))  // The IP should never require an async call.
    return cb(Err("No location available."));
  memcpy(&ip, &(*ip_data)[0], ip_data->size());

  const VariableLocation::Entry* loc_entry = var->location().EntryForIP(symbol_context, ip);
  if (!loc_entry) {
    // No DWARF location applies to the current instruction pointer.
    const char* err_str;
    if (var->location().is_null()) {
      // With no locations, this variable has been completely optimized out.
      err_str = "Optimized out";
    } else {
      // There are locations but none of them match the current IP.
      err_str = "Unavailable";
    }
    return cb(Err(ErrType::kOptimizedOut, err_str));
  }

  // Schedule the expression to be evaluated.
  auto evaluator = fxl::MakeRefCounted<AsyncDwarfExprEval>(std::move(cb), std::move(type));
  evaluator->Eval(RefPtrTo(this), symbol_context, loc_entry->expression);
}

const ProcessSymbols* EvalContextImpl::GetProcessSymbols() const {
  if (!process_symbols_)
    return nullptr;
  return process_symbols_.get();
}

fxl::RefPtr<SymbolDataProvider> EvalContextImpl::GetDataProvider() { return data_provider_; }

NameLookupCallback EvalContextImpl::GetSymbolNameLookupCallback() {
  // The contract for this function is that the callback must not be stored
  // so the callback can reference |this|.
  return [this](const ParsedIdentifier& ident, const FindNameOptions& opts) -> FoundName {
    // Look up the symbols in the symbol table if possible.
    FoundName result = FindName(GetFindNameContext(), opts, ident);

    // Fall back on builtin types.
    if (result.kind() == FoundName::kNone && opts.find_types) {
      if (auto type = GetBuiltinType(language_, ident.GetFullName()))
        return FoundName(std::move(type));
    }
    return result;
  };
}

Location EvalContextImpl::GetLocationForAddress(uint64_t address) const {
  if (!process_symbols_)
    return Location(Location::State::kAddress, address);  // Can't symbolize.

  auto locations = process_symbols_->ResolveInputLocation(InputLocation(address));

  // Given an exact address, ResolveInputLocation() should only return one result.
  FX_DCHECK(locations.size() == 1u);
  return locations[0];
}

Err EvalContextImpl::ResolveExternValue(const fxl::RefPtr<Value>& input_value,
                                        fxl::RefPtr<Variable>* resolved) const {
  FX_DCHECK(input_value->is_external());

  FindNameOptions options(FindNameOptions::kNoKinds);
  options.find_vars = true;

  // Passing a null block in the FindNameContext will bypass searching the current scope and
  // "this" object and instead only search global names. This is what we want since the extern
  // Value name will be fully qualified.
  FindNameContext context = GetFindNameContext();
  context.block = nullptr;

  FoundName found = FindName(context, options, ToParsedIdentifier(input_value->GetIdentifier()));
  if (!found || !found.variable())
    return Err("Extern variable '%s' not found.", input_value->GetFullName().c_str());

  *resolved = found.variable_ref();
  return Err();
}

void EvalContextImpl::DoResolve(FoundName found, EvalCallback cb) const {
  if (found.kind() == FoundName::kVariable) {
    // Simple variable resolution.
    GetVariableValue(found.variable_ref(), std::move(cb));
    return;
  }

  // Everything below here is an object variable resolution.
  FX_DCHECK(found.kind() == FoundName::kMemberVariable);

  // Static ("external") data members don't require a "this" pointer.
  if (found.member().data_member()->is_external())
    return GetVariableValue(RefPtrTo(found.member().data_member()), std::move(cb));

  // Get the value of of the |this| variable to resolve.
  GetVariableValue(found.object_ptr_ref(), [weak_this = weak_factory_.GetWeakPtr(), found,
                                            cb = std::move(cb)](ErrOrValue value) mutable {
    if (!weak_this)
      return;  // Don't issue callbacks if we've been destroyed.

    if (value.has_error())  // |this| not available, probably optimized out.
      return cb(value);

    // Got |this|, resolve |this-><DataMember>|.
    //
    // Here we do not support automatically converting a base class pointer to a derived class if
    // we can. First, that's more difficult to implement because it requires asynchronously
    // computing the derived class based on |this|'s vtable pointer. Second, it's not linguistically
    // in scope and it could be surprising, especially if it shadows another value. The user can
    // always do "this->foo" to expicitly request the conversion if enabled.
    ResolveMemberByPointer(fxl::RefPtr<EvalContextImpl>(weak_this.get()), value.value(),
                           found.member(),
                           [weak_this, found, cb = std::move(cb)](ErrOrValue value) mutable {
                             if (weak_this) {
                               // Only issue callbacks if we're still alive.
                               cb(std::move(value));
                             }
                           });
  });
}

FoundName EvalContextImpl::DoTargetSymbolsNameLookup(const ParsedIdentifier& ident) {
  return FindName(GetFindNameContext(), FindNameOptions(FindNameOptions::kAllKinds), ident);
}

}  // namespace zxdb
