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

#include <lib/syslog/cpp/macros.h>

#include "llvm/BinaryFormat/Dwarf.h"
#include "src/developer/debug/zxdb/symbols/mock_symbol_data_provider.h"
#include "src/developer/debug/zxdb/symbols/type_test_support.h"

namespace zxdb {

VirtualInheritanceTestSetup::VirtualInheritanceTestSetup() {
  auto int32_type = MakeInt32Type();

  // Base.
  base = MakeCollectionType(DwarfTag::kClassType, "Base", {{"base_i", int32_type}});

  // IntermediateBase.
  intermediate_base = MakeCollectionType(DwarfTag::kClassType, "IntermediateBase",
                                         {{"intermediate_base_i", int32_type}});
  FX_CHECK(intermediate_base->byte_size() == kBaseAddress - kIntermediateBaseAddress);
  // Make room for "Base" which follows the intermediate_base_i data.
  base_inherited = fxl::MakeRefCounted<InheritedFrom>(base, intermediate_base->byte_size());
  intermediate_base->set_byte_size(intermediate_base->byte_size() + base->byte_size());
  intermediate_base->set_inherited_from({LazySymbol(base_inherited)});

  // IntermediateDerived.
  //
  // The vtable pointer will actually be declared as some kind of pointer. But we never need the
  // type so just make an 8-byte value as a placeholder.
  auto uint64_type = MakeUint64Type();
  intermediate_derived = MakeCollectionType(
      DwarfTag::kClassType, "IntermediateDerived",
      {{"_vptr.IntermediateDerived", uint64_type}, {"intermediate_derived_i", int32_type}});
  FX_CHECK(intermediate_derived->byte_size() ==
           kIntermediateBaseAddress - kIntermediateDerivedAddress);
  // Make room for the base classes.
  intermediate_derived->set_byte_size(intermediate_derived->byte_size() +
                                      intermediate_base->byte_size());

  // Virtual inheritance. This expression is what GCC generated for a simple example. Recall the
  // initial stack state for running this program will have the address of IntermediateDerived.
  DwarfExpr expression({
      llvm::dwarf::DW_OP_dup,    // Make 2 copies of the IntermediateDerived address.
      llvm::dwarf::DW_OP_deref,  // Read the vtable_ptr to top of stack.
      llvm::dwarf::DW_OP_lit24,  // Move pointer backwards 24 bytes to point to the offset.
      llvm::dwarf::DW_OP_minus,  //   (cont)
      llvm::dwarf::DW_OP_deref,  // Read the offset from the computed pointer.
      llvm::dwarf::DW_OP_plus    // Add the IntermediateDerived address and the offset.
  });
  intermediate_base_inherited = fxl::MakeRefCounted<InheritedFrom>(intermediate_base, expression);
  intermediate_derived->set_inherited_from({LazySymbol(intermediate_base_inherited)});

  // Derived.
  derived = MakeCollectionType(DwarfTag::kClassType, "Derived", {{"derived_i", int32_type}});
  FX_CHECK(derived->byte_size() == kIntermediateDerivedAddress - kDerivedAddress);
  intermediate_derived_inherited =
      fxl::MakeRefCounted<InheritedFrom>(intermediate_derived, derived->byte_size());
  derived->set_byte_size(derived->byte_size() + intermediate_derived->byte_size());
  derived->set_inherited_from({LazySymbol(intermediate_derived_inherited)});

  // Object.
  std::vector<uint8_t> derived_data = {
      0x01, 0x00, 0x00, 0x00,                          // derived_i = 1.
      0x1c, 0x03, 0x02, 0x01, 0x00, 0x00, 0x00, 0x00,  // vtable_ptr = kVtablePtr.
      0x02, 0x00, 0x00, 0x00,                          // intermediate_derived_i = 2.
      0x03, 0x00, 0x00, 0x00,                          // intermediate_base_i = 3.
      0x04, 0x00, 0x00, 0x00,                          // base_i = 4.
  };
  FX_CHECK(derived_data.size() == derived->byte_size());
  derived_value = ExprValue(derived, derived_data, ExprValueSource(kDerivedAddress));

  // Vtable data.
  virtual_data = std::vector<uint8_t>{
      // Offset of base in derived for the virtual inheritance, expressed in 64-bit little-endian.
      static_cast<uint8_t>(kIntermediateBaseAddress - kIntermediateDerivedAddress), 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00,

      // This is extra data to cover the whole vtable range. It shouldn't be technically needed.
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
}

void VirtualInheritanceTestSetup::SaveMockData(MockSymbolDataProvider* mock) const {
  mock->AddMemory(kDerivedAddress, derived_value.data().bytes());
  mock->AddMemory(kVirtualDataAddress, virtual_data);
}

}  // namespace zxdb
