// Copyright 2019 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/bitfield.h"

#include "src/developer/debug/zxdb/common/int128_t.h"
#include "src/developer/debug/zxdb/expr/expr_value.h"
#include "src/developer/debug/zxdb/expr/found_member.h"
#include "src/developer/debug/zxdb/symbols/base_type.h"

namespace zxdb {

namespace {

// We use 128-bit numbers for bitfield computations so we can shift around 64 bit bitfields. This
// allows us to handle anything up to 120 bits, or 128 bits if the beginning is aligned. This
// limitation seems reasonable.

// We treat "signed int" bitfields as being signed and needing sign extensions. Whether "int"
// bitfields are signed or unsigned is actually implementation-defined in the C standard.
bool NeedsSignExtension(const fxl::RefPtr<EvalContext>& context, const Type* type, uint128_t value,
                        uint32_t bit_size) {
  fxl::RefPtr<Type> concrete = context->GetConcreteType(type);
  const BaseType* base_type = concrete->AsBaseType();
  if (!base_type)
    return false;

  if (!BaseType::IsSigned(base_type->base_type()))
    return false;  // Unsigned type.

  // Needs sign extension when the high bit is set.
  return value & (1ull << (bit_size - 1));
}

}  // namespace

ErrOrValue ResolveBitfieldMember(const fxl::RefPtr<EvalContext>& context, const ExprValue& base,
                                 const FoundMember& found_member) {
  const DataMember* data_member = found_member.data_member();
  FX_DCHECK(data_member->is_bitfield());

  if (data_member->data_bit_offset()) {
    // All of our compilers currently use bit_offset instead.
    return Err(
        "DW_AT_data_bit_offset is used for this bitfield but is not supported.\n"
        "Please file a bug with information about your compiler and build configuration.");
  }

  // Use the FoundMember's offset (not DataMember's) because FoundMember's takes into account base
  // classes and their offsets.
  // TODO(bug 41503) handle virtual inheritance.
  auto opt_byte_offset = found_member.GetDataMemberOffset();
  if (!opt_byte_offset) {
    return Err(
        "The debugger does not yet support bitfield access on virtually inherited base "
        "classes (bug 41503) or static members.");
  }

  if (data_member->bit_size() + data_member->bit_offset() > sizeof(uint128_t) * 8) {
    // If the total coverage of this bitfield is more than out number size we can't do the
    // operations and need to rewrite this code to manually do shifts on bytes rather than using
    // numeric operations in C.
    return Err("The bitfield spans more than 128 bits which is unsupported.");
  }

  // Destination type.
  const Type* dest_type = data_member->type().Get()->AsType();
  if (!dest_type)
    return Err("Bitfield member has no type.");
  fxl::RefPtr<Type> concrete_dest_type = context->GetConcreteType(dest_type);

  uint128_t bits = 0;

  // Copy bytes to out bitfield as long as they're in the structure and will mask the valid ones
  // later. This is because the bit offset can actually be negative to indicate it's starting at a
  // higher bit than byte_size (see below). Copyting everything we have means we don't have to worry
  // about that reading off the end of byte_size() and can just do the masking math.
  //
  // This computation assumes little-endian.
  memcpy(&bits, &base.data()[*opt_byte_offset],
         std::min(sizeof(bits), base.data().size() - *opt_byte_offset));

  // Bits count from the high bit within byte_size(). Current compilers seem to always write
  // byte_size == sizeof(declared type) and count the high bit of the result from the high bit of
  // this field (read from memory as little-endian). If bit offsets push the high bit of the
  // result onto a later bit (say it's a 31-bit bitfield and a 32-bit underlying type, starting at
  // a 3 bit offset will make the number cover 5 bytes) the bit offset will actually be negative!
  //
  // So offset 6 in an 8-bit byte_size() selects 0b0000`0010 and we want to shift one bit. This
  // identifies the high bit in the result and we need to shift until the low bit is at the low
  // position.
  uint32_t shift_amount =
      data_member->byte_size() * 8 - data_member->bit_offset() - data_member->bit_size();
  bits >>= shift_amount;

  uint128_t valid_bit_mask = (static_cast<uint128_t>(1) << data_member->bit_size()) - 1;
  bits &= valid_bit_mask;

  if (NeedsSignExtension(context, concrete_dest_type.get(), bits, data_member->bit_size())) {
    // Set non-masked bits to 1.
    bits |= ~valid_bit_mask;
  }

  ExprValueSource source =
      base.source().GetOffsetInto(*opt_byte_offset, data_member->bit_size(), shift_amount);

  // Save the data back to the desired size (assume little-endian so truncation from the right is
  // correct).
  std::vector<uint8_t> new_data(data_member->byte_size());
  memcpy(&new_data[0], &bits, new_data.size());
  return ExprValue(RefPtrTo(dest_type), std::move(new_data), source);
}

void WriteBitfieldToMemory(const fxl::RefPtr<EvalContext>& context, const ExprValueSource& dest,
                           std::vector<uint8_t> data, fit::callback<void(const Err&)> cb) {
  FX_DCHECK(dest.is_bitfield());

  // Expect bitfields to fit in our biggest int.
  if (data.size() > sizeof(uint128_t))
    return cb(Err("Writing bitfields for data > 128-bits is not supported."));

  uint128_t value = 0;
  memcpy(&value, &data[0], data.size());

  // Number of bytes affected by this bitfield.
  size_t byte_size = (dest.bit_size() + dest.bit_shift() + 7) / 8;
  if (!byte_size)
    return cb(Err("Can't write a bitfield with no data."));

  // To only write some bits we need to do a read and a write. Since these are asynchronous there
  // is a possibility of racing with the program, but there will a race if the program is running
  // even if we do the masking in the debug_agent. This implementation is simpler than passing the
  // mask to the agent, so do that.
  context->GetDataProvider()->GetMemoryAsync(
      dest.address(), byte_size,
      [context, dest, value, byte_size, cb = std::move(cb)](
          const Err& err, std::vector<uint8_t> original_data) mutable {
        if (err.has_error())
          return cb(err);
        if (original_data.size() != byte_size)  // Short read means invalid address.
          return cb(Err("Memory at address 0x%" PRIx64 " is invalid.", dest.address()));

        uint128_t original = 0;
        memcpy(&original, &original_data[0], original_data.size());

        uint128_t result = dest.SetBits(original, value);

        // Write out the new data.
        std::vector<uint8_t> new_data(byte_size);
        memcpy(&new_data[0], &result, byte_size);
        context->GetDataProvider()->WriteMemory(dest.address(), std::move(new_data), std::move(cb));
      });
}

}  // namespace zxdb
