//===- UDTLayout.cpp ------------------------------------------------------===//
//
//                     The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#include "llvm/DebugInfo/PDB/UDTLayout.h"
#include "llvm/ADT/ArrayRef.h"
#include "llvm/ADT/BitVector.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/DebugInfo/PDB/IPDBRawSymbol.h"
#include "llvm/DebugInfo/PDB/IPDBSession.h"
#include "llvm/DebugInfo/PDB/PDBSymbol.h"
#include "llvm/DebugInfo/PDB/PDBSymbolData.h"
#include "llvm/DebugInfo/PDB/PDBSymbolFunc.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBaseClass.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeBuiltin.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypePointer.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeUDT.h"
#include "llvm/DebugInfo/PDB/PDBSymbolTypeVTable.h"
#include "llvm/DebugInfo/PDB/PDBTypes.h"
#include "llvm/Support/Casting.h"
#include <algorithm>
#include <cassert>
#include <cstdint>
#include <memory>

using namespace llvm;
using namespace llvm::pdb;

static std::unique_ptr<PDBSymbol> getSymbolType(const PDBSymbol &Symbol) {
  const IPDBSession &Session = Symbol.getSession();
  const IPDBRawSymbol &RawSymbol = Symbol.getRawSymbol();
  uint32_t TypeId = RawSymbol.getTypeId();
  return Session.getSymbolById(TypeId);
}

static uint32_t getTypeLength(const PDBSymbol &Symbol) {
  auto SymbolType = getSymbolType(Symbol);
  const IPDBRawSymbol &RawType = SymbolType->getRawSymbol();

  return RawType.getLength();
}

LayoutItemBase::LayoutItemBase(const UDTLayoutBase *Parent,
                               const PDBSymbol *Symbol, const std::string &Name,
                               uint32_t OffsetInParent, uint32_t Size,
                               bool IsElided)
    : Symbol(Symbol), Parent(Parent), Name(Name),
      OffsetInParent(OffsetInParent), SizeOf(Size), LayoutSize(Size),
      IsElided(IsElided) {
  UsedBytes.resize(SizeOf, true);
}

uint32_t LayoutItemBase::deepPaddingSize() const {
  return UsedBytes.size() - UsedBytes.count();
}

uint32_t LayoutItemBase::tailPadding() const {
  int Last = UsedBytes.find_last();

  return UsedBytes.size() - (Last + 1);
}

DataMemberLayoutItem::DataMemberLayoutItem(
    const UDTLayoutBase &Parent, std::unique_ptr<PDBSymbolData> Member)
    : LayoutItemBase(&Parent, Member.get(), Member->getName(),
                     Member->getOffset(), getTypeLength(*Member), false),
      DataMember(std::move(Member)) {
  auto Type = DataMember->getType();
  if (auto UDT = unique_dyn_cast<PDBSymbolTypeUDT>(Type)) {
    UdtLayout = llvm::make_unique<ClassLayout>(std::move(UDT));
    UsedBytes = UdtLayout->usedBytes();
  }
}

VBPtrLayoutItem::VBPtrLayoutItem(const UDTLayoutBase &Parent,
                                 std::unique_ptr<PDBSymbolTypeBuiltin> Sym,
                                 uint32_t Offset, uint32_t Size)
    : LayoutItemBase(&Parent, Sym.get(), "<vbptr>", Offset, Size, false),
      Type(std::move(Sym)) {
}

const PDBSymbolData &DataMemberLayoutItem::getDataMember() {
  return *dyn_cast<PDBSymbolData>(Symbol);
}

bool DataMemberLayoutItem::hasUDTLayout() const { return UdtLayout != nullptr; }

const ClassLayout &DataMemberLayoutItem::getUDTLayout() const {
  return *UdtLayout;
}

VTableLayoutItem::VTableLayoutItem(const UDTLayoutBase &Parent,
                                   std::unique_ptr<PDBSymbolTypeVTable> VT)
    : LayoutItemBase(&Parent, VT.get(), "<vtbl>", 0, getTypeLength(*VT), false),
      VTable(std::move(VT)) {
  auto VTableType = cast<PDBSymbolTypePointer>(VTable->getType());
  ElementSize = VTableType->getLength();
}

UDTLayoutBase::UDTLayoutBase(const UDTLayoutBase *Parent, const PDBSymbol &Sym,
                             const std::string &Name, uint32_t OffsetInParent,
                             uint32_t Size, bool IsElided)
    : LayoutItemBase(Parent, &Sym, Name, OffsetInParent, Size, IsElided) {
  // UDT storage comes from a union of all the children's storage, so start out
  // uninitialized.
  UsedBytes.reset(0, Size);

  initializeChildren(Sym);
  if (LayoutSize < Size)
    UsedBytes.resize(LayoutSize);
}

uint32_t UDTLayoutBase::tailPadding() const {
  uint32_t Abs = LayoutItemBase::tailPadding();
  if (!LayoutItems.empty()) {
    const LayoutItemBase *Back = LayoutItems.back();
    uint32_t ChildPadding = Back->LayoutItemBase::tailPadding();
    if (Abs < ChildPadding)
      Abs = 0;
    else
      Abs -= ChildPadding;
  }
  return Abs;
}

ClassLayout::ClassLayout(const PDBSymbolTypeUDT &UDT)
    : UDTLayoutBase(nullptr, UDT, UDT.getName(), 0, UDT.getLength(), false),
      UDT(UDT) {
  ImmediateUsedBytes.resize(SizeOf, false);
  for (auto &LI : LayoutItems) {
    uint32_t Begin = LI->getOffsetInParent();
    uint32_t End = Begin + LI->getLayoutSize();
    End = std::min(SizeOf, End);
    ImmediateUsedBytes.set(Begin, End);
  }
}

ClassLayout::ClassLayout(std::unique_ptr<PDBSymbolTypeUDT> UDT)
    : ClassLayout(*UDT) {
  OwnedStorage = std::move(UDT);
}

uint32_t ClassLayout::immediatePadding() const {
  return SizeOf - ImmediateUsedBytes.count();
}

BaseClassLayout::BaseClassLayout(const UDTLayoutBase &Parent,
                                 uint32_t OffsetInParent, bool Elide,
                                 std::unique_ptr<PDBSymbolTypeBaseClass> B)
    : UDTLayoutBase(&Parent, *B, B->getName(), OffsetInParent, B->getLength(),
                    Elide),
      Base(std::move(B)) {
  if (isEmptyBase()) {
    // Special case an empty base so that it doesn't get treated as padding.
    UsedBytes.resize(1);
    UsedBytes.set(0);
  }
  IsVirtualBase = Base->isVirtualBaseClass();
}

void UDTLayoutBase::initializeChildren(const PDBSymbol &Sym) {
  // Handled bases first, followed by VTables, followed by data members,
  // followed by functions, followed by other.  This ordering is necessary
  // so that bases and vtables get initialized before any functions which
  // may override them.
  UniquePtrVector<PDBSymbolTypeBaseClass> Bases;
  UniquePtrVector<PDBSymbolTypeVTable> VTables;
  UniquePtrVector<PDBSymbolData> Members;
  UniquePtrVector<PDBSymbolTypeBaseClass> VirtualBaseSyms;

  auto Children = Sym.findAllChildren();
  while (auto Child = Children->getNext()) {
    if (auto Base = unique_dyn_cast<PDBSymbolTypeBaseClass>(Child)) {
      if (Base->isVirtualBaseClass())
        VirtualBaseSyms.push_back(std::move(Base));
      else
        Bases.push_back(std::move(Base));
    }
    else if (auto Data = unique_dyn_cast<PDBSymbolData>(Child)) {
      if (Data->getDataKind() == PDB_DataKind::Member)
        Members.push_back(std::move(Data));
      else
        Other.push_back(std::move(Data));
    } else if (auto VT = unique_dyn_cast<PDBSymbolTypeVTable>(Child))
      VTables.push_back(std::move(VT));
    else if (auto Func = unique_dyn_cast<PDBSymbolFunc>(Child))
      Funcs.push_back(std::move(Func));
    else {
      Other.push_back(std::move(Child));
    }
  }

  // We don't want to have any re-allocations in the list of bases, so make
  // sure to reserve enough space so that our ArrayRefs don't get invalidated.
  AllBases.reserve(Bases.size() + VirtualBaseSyms.size());

  // Only add non-virtual bases to the class first.  Only at the end of the
  // class, after all non-virtual bases and data members have been added do we
  // add virtual bases.  This way the offsets are correctly aligned when we go
  // to lay out virtual bases.
  for (auto &Base : Bases) {
    uint32_t Offset = Base->getOffset();
    // Non-virtual bases never get elided.
    auto BL = llvm::make_unique<BaseClassLayout>(*this, Offset, false,
                                                 std::move(Base));

    AllBases.push_back(BL.get());
    addChildToLayout(std::move(BL));
  }
  NonVirtualBases = AllBases;

  assert(VTables.size() <= 1);
  if (!VTables.empty()) {
    auto VTLayout =
        llvm::make_unique<VTableLayoutItem>(*this, std::move(VTables[0]));

    VTable = VTLayout.get();

    addChildToLayout(std::move(VTLayout));
  }

  for (auto &Data : Members) {
    auto DM = llvm::make_unique<DataMemberLayoutItem>(*this, std::move(Data));

    addChildToLayout(std::move(DM));
  }

  // Make sure add virtual bases before adding functions, since functions may be
  // overrides of virtual functions declared in a virtual base, so the VTables
  // and virtual intros need to be correctly initialized.
  for (auto &VB : VirtualBaseSyms) {
    int VBPO = VB->getVirtualBasePointerOffset();
    if (!hasVBPtrAtOffset(VBPO)) {
      if (auto VBP = VB->getRawSymbol().getVirtualBaseTableType()) {
        auto VBPL = llvm::make_unique<VBPtrLayoutItem>(*this, std::move(VBP),
                                                       VBPO, VBP->getLength());
        VBPtr = VBPL.get();
        addChildToLayout(std::move(VBPL));
      }
    }

    // Virtual bases always go at the end.  So just look for the last place we
    // ended when writing something, and put our virtual base there.
    // Note that virtual bases get elided unless this is a top-most derived
    // class.
    uint32_t Offset = UsedBytes.find_last() + 1;
    bool Elide = (Parent != nullptr);
    auto BL =
        llvm::make_unique<BaseClassLayout>(*this, Offset, Elide, std::move(VB));
    AllBases.push_back(BL.get());

    // Only lay this virtual base out directly inside of *this* class if this
    // is a top-most derived class.  Keep track of it regardless, but only
    // physically lay it out if it's a topmost derived class.
    addChildToLayout(std::move(BL));
  }
  VirtualBases = makeArrayRef(AllBases).drop_front(NonVirtualBases.size());

  if (Parent != nullptr)
    LayoutSize = UsedBytes.find_last() + 1;
}

bool UDTLayoutBase::hasVBPtrAtOffset(uint32_t Off) const {
  if (VBPtr && VBPtr->getOffsetInParent() == Off)
    return true;
  for (BaseClassLayout *BL : AllBases) {
    if (BL->hasVBPtrAtOffset(Off - BL->getOffsetInParent()))
      return true;
  }
  return false;
}

void UDTLayoutBase::addChildToLayout(std::unique_ptr<LayoutItemBase> Child) {
  uint32_t Begin = Child->getOffsetInParent();

  if (!Child->isElided()) {
    BitVector ChildBytes = Child->usedBytes();

    // Suppose the child occupies 4 bytes starting at offset 12 in a 32 byte
    // class.  When we call ChildBytes.resize(32), the Child's storage will
    // still begin at offset 0, so we need to shift it left by offset bytes
    // to get it into the right position.
    ChildBytes.resize(UsedBytes.size());
    ChildBytes <<= Child->getOffsetInParent();
    UsedBytes |= ChildBytes;

    if (ChildBytes.count() > 0) {
      auto Loc = std::upper_bound(LayoutItems.begin(), LayoutItems.end(), Begin,
                                  [](uint32_t Off, const LayoutItemBase *Item) {
                                    return (Off < Item->getOffsetInParent());
                                  });

      LayoutItems.insert(Loc, Child.get());
    }
  }

  ChildStorage.push_back(std::move(Child));
}
