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

#include "lldb/Core/Value.h"
#include "lldb/Core/ValueObject.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Core/ValueObjectConstResultCast.h"
#include "lldb/Core/ValueObjectConstResultChild.h"
#include "lldb/Symbol/CompilerType.h"
#include "lldb/Target/ExecutionContext.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "lldb/Utility/Endian.h"
#include "lldb/Utility/Scalar.h"

#include <string>

namespace lldb_private {
class DataExtractor;
}
namespace lldb_private {
class Status;
}

using namespace lldb;
using namespace lldb_private;

ValueObjectConstResultImpl::ValueObjectConstResultImpl(
    ValueObject *valobj, lldb::addr_t live_address)
    : m_impl_backend(valobj), m_live_address(live_address),
      m_live_address_type(eAddressTypeLoad),
      m_address_of_backend() {}

lldb::ValueObjectSP ValueObjectConstResultImpl::Dereference(Status &error) {
  if (m_impl_backend == nullptr)
    return lldb::ValueObjectSP();

  return m_impl_backend->ValueObject::Dereference(error);
}

ValueObject *ValueObjectConstResultImpl::CreateChildAtIndex(
    size_t idx, bool synthetic_array_member, int32_t synthetic_index) {
  if (m_impl_backend == nullptr)
    return nullptr;

  m_impl_backend->UpdateValueIfNeeded(false);

  ValueObjectConstResultChild *valobj = nullptr;

  bool omit_empty_base_classes = true;
  bool ignore_array_bounds = synthetic_array_member;
  std::string child_name_str;
  uint32_t child_byte_size = 0;
  int32_t child_byte_offset = 0;
  uint32_t child_bitfield_bit_size = 0;
  uint32_t child_bitfield_bit_offset = 0;
  bool child_is_base_class = false;
  bool child_is_deref_of_parent = false;
  uint64_t language_flags;

  const bool transparent_pointers = !synthetic_array_member;
  CompilerType compiler_type = m_impl_backend->GetCompilerType();
  CompilerType child_compiler_type;

  ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());

  child_compiler_type = compiler_type.GetChildCompilerTypeAtIndex(
      &exe_ctx, idx, transparent_pointers, omit_empty_base_classes,
      ignore_array_bounds, child_name_str, child_byte_size, child_byte_offset,
      child_bitfield_bit_size, child_bitfield_bit_offset, child_is_base_class,
      child_is_deref_of_parent, m_impl_backend, language_flags);

  // One might think we should check that the size of the children
  // is always strictly positive, hence we could avoid creating a
  // ValueObject if that's not the case, but it turns out there
  // are languages out there which allow zero-size types with
  // children (e.g. Swift).
  if (child_compiler_type) {
    if (synthetic_index)
      child_byte_offset += child_byte_size * synthetic_index;

    ConstString child_name;
    if (!child_name_str.empty())
      child_name.SetCString(child_name_str.c_str());

    valobj = new ValueObjectConstResultChild(
        *m_impl_backend, child_compiler_type, child_name, child_byte_size,
        child_byte_offset, child_bitfield_bit_size, child_bitfield_bit_offset,
        child_is_base_class, child_is_deref_of_parent,
        m_live_address == LLDB_INVALID_ADDRESS
            ? m_live_address
            : m_live_address + child_byte_offset,
        language_flags);
  }

  return valobj;
}

lldb::ValueObjectSP ValueObjectConstResultImpl::GetSyntheticChildAtOffset(
    uint32_t offset, const CompilerType &type, bool can_create,
    ConstString name_const_str) {
  if (m_impl_backend == nullptr)
    return lldb::ValueObjectSP();

  return m_impl_backend->ValueObject::GetSyntheticChildAtOffset(
      offset, type, can_create, name_const_str);
}

lldb::ValueObjectSP ValueObjectConstResultImpl::AddressOf(Status &error) {
  if (m_address_of_backend.get() != nullptr)
    return m_address_of_backend;

  if (m_impl_backend == nullptr)
    return lldb::ValueObjectSP();
  if (m_live_address != LLDB_INVALID_ADDRESS) {
    CompilerType compiler_type(m_impl_backend->GetCompilerType());

    lldb::DataBufferSP buffer(new lldb_private::DataBufferHeap(
        &m_live_address, sizeof(lldb::addr_t)));

    std::string new_name("&");
    new_name.append(m_impl_backend->GetName().AsCString(""));
    ExecutionContext exe_ctx(m_impl_backend->GetExecutionContextRef());
    m_address_of_backend = ValueObjectConstResult::Create(
        exe_ctx.GetBestExecutionContextScope(), compiler_type.GetPointerType(),
        ConstString(new_name.c_str()), buffer, endian::InlHostByteOrder(),
        exe_ctx.GetAddressByteSize());

    m_address_of_backend->GetValue().SetValueType(Value::ValueType::Scalar);
    m_address_of_backend->GetValue().GetScalar() = m_live_address;

    return m_address_of_backend;
  } else
    return m_impl_backend->ValueObject::AddressOf(error);
}

lldb::ValueObjectSP
ValueObjectConstResultImpl::Cast(const CompilerType &compiler_type) {
  if (m_impl_backend == nullptr)
    return lldb::ValueObjectSP();

  ValueObjectConstResultCast *result_cast =
      new ValueObjectConstResultCast(*m_impl_backend, m_impl_backend->GetName(),
                                     compiler_type, m_live_address);
  return result_cast->GetSP();
}

lldb::addr_t
ValueObjectConstResultImpl::GetAddressOf(bool scalar_is_load_address,
                                         AddressType *address_type) {

  if (m_impl_backend == nullptr)
    return 0;

  if (m_live_address == LLDB_INVALID_ADDRESS) {
    return m_impl_backend->ValueObject::GetAddressOf(scalar_is_load_address,
                                                     address_type);
  }

  if (address_type)
    *address_type = m_live_address_type;

  return m_live_address;
}

size_t ValueObjectConstResultImpl::GetPointeeData(DataExtractor &data,
                                                  uint32_t item_idx,
                                                  uint32_t item_count) {
  if (m_impl_backend == nullptr)
    return 0;
  return m_impl_backend->ValueObject::GetPointeeData(data, item_idx,
                                                     item_count);
}
