//===- UDTLayout.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 "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 = std::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 *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 = std::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 =
        std::make_unique<VTableLayoutItem>(*this, std::move(VTables[0]));

    VTable = VTLayout.get();

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

  for (auto &Data : Members) {
    auto DM = std::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 = std::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 =
        std::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));
}
