// 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/builtin_types.h"
#include "src/developer/debug/zxdb/expr/eval_dwarf_expr.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(ExprLanguage lang, RegisterID id, VectorRegisterFormat vector_fmt,
                               containers::array_view<uint8_t> data) {
  const debug_ipc::RegisterInfo* info = debug_ipc::InfoForRegister(id);
  if (!info)
    return Err("Unknown register");

  ExprValueSource source(id);

  switch (info->format) {
    case debug_ipc::RegisterFormat::kGeneral:
    case debug_ipc::RegisterFormat::kSpecial: {
      return ExprValue(GetBuiltinUnsignedType(lang, data.size()),
                       std::vector<uint8_t>(data.begin(), data.end()), source);
    }

    case debug_ipc::RegisterFormat::kFloat: {
      return ExprValue(GetBuiltinFloatType(lang, data.size()),
                       std::vector<uint8_t>(data.begin(), data.end()), source);
    }

    case debug_ipc::RegisterFormat::kVector: {
      return VectorRegisterToValue(id, vector_fmt, std::vector<uint8_t>(data.begin(), data.end()));
    }

    case debug_ipc::RegisterFormat::kVoidAddress: {
      // A void* is a pointer to no type.
      return ExprValue(fxl::MakeRefCounted<ModifiedType>(DwarfTag::kPointerType, LazySymbol()),
                       std::vector<uint8_t>(data.begin(), data.end()), source);
    }

    case debug_ipc::RegisterFormat::kWordAddress: {
      auto word_ptr_type = fxl::MakeRefCounted<ModifiedType>(DwarfTag::kPointerType,
                                                             GetBuiltinUnsignedType(lang, 8));
      return ExprValue(word_ptr_type, std::vector<uint8_t>(data.begin(), data.end()), source);
    }
  }

  return Err("Unknown register type");
}

}  // namespace

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

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

  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. The data_provider is in charge
  // of extracting the bits for non-canonical sub registers (like "ah" and "al" on x86) so we
  // can pass the register enums through directly.
  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(language_, reg, GetVectorRegisterFormat(), *opt_reg_data));
  } else {
    data_provider_->GetRegisterAsync(
        reg, [lang = language_, 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(lang, 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->As<Variable>());
    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()->As<Type>());
  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 DwarfExpr* loc_expr = var->location().ExprForIP(symbol_context, ip);
  if (!loc_expr) {
    // 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.
  DwarfExprToValue(RefPtrTo(this), symbol_context, *loc_expr, std::move(type), std::move(cb));
}

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
