// 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();
  FXL_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) {
  FXL_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
