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

#include "src/developer/debug/zxdb/common/err.h"
#include "src/developer/debug/zxdb/expr/eval_context.h"
#include "src/developer/debug/zxdb/expr/expr_value.h"
#include "src/developer/debug/zxdb/expr/resolve_base.h"
#include "src/developer/debug/zxdb/symbols/arch.h"
#include "src/developer/debug/zxdb/symbols/modified_type.h"
#include "src/developer/debug/zxdb/symbols/symbol_data_provider.h"
#include "src/developer/debug/zxdb/symbols/type.h"
#include "src/lib/fxl/strings/string_printf.h"

namespace zxdb {

namespace {

// Extracts the value from the ExprValue, assuming it's a pointer. If not,
// return the error, otherwise fill in *pointer_value.
Err GetPointerValue(const ExprValue& value, TargetPointer* pointer_value) {
  Err err = value.EnsureSizeIs(kTargetPointerSize);
  if (err.has_error())
    return err;
  *pointer_value = value.GetAs<TargetPointer>();
  return Err();
}

// Backend for the higher-level variant of ResolvePointer that does not handle upcasting to derived
// types.
void DoResolvePointer(const fxl::RefPtr<EvalContext>& eval_context, const ExprValue& pointer,
                      EvalCallback cb) {
  fxl::RefPtr<Type> pointed_to;
  if (Err err = GetPointedToType(eval_context, pointer.type(), &pointed_to); err.has_error())
    return cb(err);

  TargetPointer pointer_value = 0;
  if (Err err = GetPointerValue(pointer, &pointer_value); err.has_error())
    return cb(err);

  // Forward to low-level pointer resolution.
  ResolvePointer(std::move(eval_context), pointer_value, std::move(pointed_to), std::move(cb));
}

// Backend for EnsureResolveReference that does not handle upcasting to derived types.
void DoEnsureResolveReference(const fxl::RefPtr<EvalContext>& eval_context, ExprValue value,
                              EvalCallback cb) {
  Type* type = value.type();
  if (!type) {
    // Untyped input, pass the value forward and let the callback handle the problem.
    return cb(std::move(value));
  }

  // The computed type will have the same const, etc. on it as the original, so we need to
  // make it concrete.
  fxl::RefPtr<Type> concrete = eval_context->GetConcreteType(type);
  if (concrete->tag() != DwarfTag::kReferenceType &&
      concrete->tag() != DwarfTag::kRvalueReferenceType) {
    // Not a reference, nothing to do.
    return cb(std::move(value));
  }

  // The symbol provider should have created the right object type.
  const ModifiedType* reference = concrete->AsModifiedType();
  FX_DCHECK(reference);
  const Type* underlying_type = reference->modified().Get()->AsType();

  TargetPointer pointer_value = 0;
  if (Err err = GetPointerValue(value, &pointer_value); err.has_error()) {
    cb(err);
  } else {
    ResolvePointer(eval_context, pointer_value, RefPtrTo(underlying_type), std::move(cb));
  }
}

}  // namespace

void ResolvePointer(const fxl::RefPtr<EvalContext>& eval_context, uint64_t address,
                    fxl::RefPtr<Type> type, EvalCallback cb) {
  // We need to be careful to construct the return type with the original type given since it may
  // have const qualifiers, etc., but to use the concrete one (no const, with forward-definitions
  // resolved) for size computation.
  fxl::RefPtr<Type> concrete = eval_context->GetConcreteType(type.get());
  if (!concrete)
    return cb(Err("Missing pointer type."));

  uint32_t type_size = concrete->byte_size();
  eval_context->GetDataProvider()->GetMemoryAsync(
      address, type_size,
      [type = std::move(type), address, type_size, cb = std::move(cb)](
          const Err& err, std::vector<uint8_t> data) mutable {
        // Watch out, "type" may be non-concrete (we need to preserve "const", etc.). Use
        // "type_size" for the concrete size.
        if (err.has_error()) {
          cb(err);
        } else if (data.size() != type_size) {
          // Short read, memory is invalid.
          cb(Err(fxl::StringPrintf("Invalid pointer 0x%" PRIx64, address)));
        } else {
          cb(ExprValue(std::move(type), std::move(data), ExprValueSource(address)));
        }
      });
}

void ResolvePointer(const fxl::RefPtr<EvalContext>& eval_context, const ExprValue& pointer,
                    EvalCallback cb) {
  if (eval_context->ShouldPromoteToDerived()) {
    // Check to see if this is a pointer to a base class that we can convert to a derived class.
    PromotePtrRefToDerived(eval_context, PromoteToDerived::kPtrOnly, pointer,
                           [eval_context, cb = std::move(cb)](ErrOrValue result) mutable {
                             if (result.has_error())
                               cb(result);
                             else
                               DoResolvePointer(eval_context, result.take_value(), std::move(cb));
                           });
  } else {
    // No magic base-class resolution is required, just check the reference.
    DoResolvePointer(eval_context, pointer, std::move(cb));
  }
}

void EnsureResolveReference(const fxl::RefPtr<EvalContext>& eval_context, ExprValue value,
                            EvalCallback cb) {
  if (eval_context->ShouldPromoteToDerived()) {
    // Check to see if this is a reference to a base class that we can convert to a derived class.
    PromotePtrRefToDerived(eval_context, PromoteToDerived::kRefOnly, std::move(value),
                           [eval_context, cb = std::move(cb)](ErrOrValue result) mutable {
                             if (result.has_error()) {
                               cb(result);
                             } else {
                               DoEnsureResolveReference(eval_context, result.take_value(),
                                                        std::move(cb));
                             }
                           });
  } else {
    // No magic base-class resolution is required, just check the reference.
    DoEnsureResolveReference(eval_context, std::move(value), std::move(cb));
  }
}

Err GetPointedToType(const fxl::RefPtr<EvalContext>& eval_context, const Type* input,
                     fxl::RefPtr<Type>* pointed_to) {
  if (!input)
    return Err("No type information.");

  // Convert to a pointer. GetConcreteType() here is more theoretical since current C compilers
  // won't forward-declare pointer types. But it's nice to be sure and this will also strip
  // CV-qualifiers which we do need.
  fxl::RefPtr<Type> input_concrete = eval_context->GetConcreteType(input);
  const ModifiedType* mod_type = input_concrete->AsModifiedType();
  if (!mod_type || mod_type->tag() != DwarfTag::kPointerType) {
    return Err(fxl::StringPrintf("Attempting to dereference '%s' which is not a pointer.",
                                 input->GetFullName().c_str()));
  }

  *pointed_to = fxl::RefPtr<Type>(const_cast<Type*>(mod_type->modified().Get()->AsType()));
  if (!*pointed_to)
    return Err("Can not dereference a pointer to 'void'.");
  return Err();
}

}  // namespace zxdb
