//===----------------------------------------------------------------------===//
//
// 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
//
//===----------------------------------------------------------------------===//
//
// This contains code to compute the layout of a record.
//
//===----------------------------------------------------------------------===//

#include "CIRGenBuilder.h"
#include "CIRGenModule.h"
#include "CIRGenTypes.h"

#include "clang/AST/ASTContext.h"
#include "clang/AST/Decl.h"
#include "clang/AST/DeclCXX.h"
#include "clang/AST/RecordLayout.h"
#include "clang/CIR/Dialect/IR/CIRAttrs.h"
#include "clang/CIR/Dialect/IR/CIRDataLayout.h"
#include "clang/CIR/MissingFeatures.h"
#include "llvm/Support/Casting.h"

#include <memory>

using namespace llvm;
using namespace clang;
using namespace clang::CIRGen;

namespace {
/// The CIRRecordLowering is responsible for lowering an ASTRecordLayout to an
/// mlir::Type. Some of the lowering is straightforward, some is not.
// TODO: Detail some of the complexities and weirdnesses?
// (See CGRecordLayoutBuilder.cpp)
struct CIRRecordLowering final {

  // MemberInfo is a helper structure that contains information about a record
  // member. In addition to the standard member types, there exists a sentinel
  // member type that ensures correct rounding.
  struct MemberInfo final {
    CharUnits offset;
    enum class InfoKind { Field, Base } kind;
    mlir::Type data;
    union {
      const FieldDecl *fieldDecl;
      const CXXRecordDecl *cxxRecordDecl;
    };
    MemberInfo(CharUnits offset, InfoKind kind, mlir::Type data,
               const FieldDecl *fieldDecl = nullptr)
        : offset{offset}, kind{kind}, data{data}, fieldDecl{fieldDecl} {}
    MemberInfo(CharUnits offset, InfoKind kind, mlir::Type data,
               const CXXRecordDecl *rd)
        : offset{offset}, kind{kind}, data{data}, cxxRecordDecl{rd} {}
    // MemberInfos are sorted so we define a < operator.
    bool operator<(const MemberInfo &other) const {
      return offset < other.offset;
    }
  };
  // The constructor.
  CIRRecordLowering(CIRGenTypes &cirGenTypes, const RecordDecl *recordDecl,
                    bool packed);

  /// Constructs a MemberInfo instance from an offset and mlir::Type.
  MemberInfo makeStorageInfo(CharUnits offset, mlir::Type data) {
    return MemberInfo(offset, MemberInfo::InfoKind::Field, data);
  }

  // Layout routines.
  void setBitFieldInfo(const FieldDecl *fd, CharUnits startOffset,
                       mlir::Type storageType);

  void lower();
  void lowerUnion();

  /// Determines if we need a packed llvm struct.
  void determinePacked();
  /// Inserts padding everywhere it's needed.
  void insertPadding();

  void computeVolatileBitfields();
  void accumulateBases(const CXXRecordDecl *cxxRecordDecl);
  void accumulateVPtrs();
  void accumulateFields();
  RecordDecl::field_iterator
  accumulateBitFields(RecordDecl::field_iterator field,
                      RecordDecl::field_iterator fieldEnd);

  bool isAAPCS() const {
    return astContext.getTargetInfo().getABI().starts_with("aapcs");
  }

  CharUnits bitsToCharUnits(uint64_t bitOffset) {
    return astContext.toCharUnitsFromBits(bitOffset);
  }

  void calculateZeroInit();

  CharUnits getSize(mlir::Type Ty) {
    return CharUnits::fromQuantity(dataLayout.layout.getTypeSize(Ty));
  }
  CharUnits getSizeInBits(mlir::Type ty) {
    return CharUnits::fromQuantity(dataLayout.layout.getTypeSizeInBits(ty));
  }
  CharUnits getAlignment(mlir::Type Ty) {
    return CharUnits::fromQuantity(dataLayout.layout.getTypeABIAlignment(Ty));
  }

  bool isZeroInitializable(const FieldDecl *fd) {
    return cirGenTypes.isZeroInitializable(fd->getType());
  }
  bool isZeroInitializable(const RecordDecl *rd) {
    return cirGenTypes.isZeroInitializable(rd);
  }

  /// Wraps cir::IntType with some implicit arguments.
  mlir::Type getUIntNType(uint64_t numBits) {
    unsigned alignedBits = llvm::PowerOf2Ceil(numBits);
    alignedBits = std::max(8u, alignedBits);
    return cir::IntType::get(&cirGenTypes.getMLIRContext(), alignedBits,
                             /*isSigned=*/false);
  }

  mlir::Type getCharType() {
    return cir::IntType::get(&cirGenTypes.getMLIRContext(),
                             astContext.getCharWidth(),
                             /*isSigned=*/false);
  }

  mlir::Type getByteArrayType(CharUnits numberOfChars) {
    assert(!numberOfChars.isZero() && "Empty byte arrays aren't allowed.");
    mlir::Type type = getCharType();
    return numberOfChars == CharUnits::One()
               ? type
               : cir::ArrayType::get(type, numberOfChars.getQuantity());
  }

  // Gets the CIR BaseSubobject type from a CXXRecordDecl.
  mlir::Type getStorageType(const CXXRecordDecl *RD) {
    return cirGenTypes.getCIRGenRecordLayout(RD).getBaseSubobjectCIRType();
  }
  // This is different from LLVM traditional codegen because CIRGen uses arrays
  // of bytes instead of arbitrary-sized integers. This is important for packed
  // structures support.
  mlir::Type getBitfieldStorageType(unsigned numBits) {
    unsigned alignedBits = llvm::alignTo(numBits, astContext.getCharWidth());
    if (cir::isValidFundamentalIntWidth(alignedBits))
      return builder.getUIntNTy(alignedBits);

    mlir::Type type = getCharType();
    return cir::ArrayType::get(type, alignedBits / astContext.getCharWidth());
  }

  mlir::Type getStorageType(const FieldDecl *fieldDecl) {
    mlir::Type type = cirGenTypes.convertTypeForMem(fieldDecl->getType());
    if (fieldDecl->isBitField()) {
      cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
                                         "getStorageType for bitfields");
    }
    return type;
  }

  uint64_t getFieldBitOffset(const FieldDecl *fieldDecl) {
    return astRecordLayout.getFieldOffset(fieldDecl->getFieldIndex());
  }

  /// Fills out the structures that are ultimately consumed.
  void fillOutputFields();

  void appendPaddingBytes(CharUnits size) {
    if (!size.isZero()) {
      fieldTypes.push_back(getByteArrayType(size));
      padded = true;
    }
  }

  CIRGenTypes &cirGenTypes;
  CIRGenBuilderTy &builder;
  const ASTContext &astContext;
  const RecordDecl *recordDecl;
  const ASTRecordLayout &astRecordLayout;
  // Helpful intermediate data-structures
  std::vector<MemberInfo> members;
  // Output fields, consumed by CIRGenTypes::computeRecordLayout
  llvm::SmallVector<mlir::Type, 16> fieldTypes;
  llvm::DenseMap<const FieldDecl *, CIRGenBitFieldInfo> bitFields;
  llvm::DenseMap<const FieldDecl *, unsigned> fieldIdxMap;
  llvm::DenseMap<const CXXRecordDecl *, unsigned> nonVirtualBases;
  cir::CIRDataLayout dataLayout;

  LLVM_PREFERRED_TYPE(bool)
  unsigned zeroInitializable : 1;
  LLVM_PREFERRED_TYPE(bool)
  unsigned zeroInitializableAsBase : 1;
  LLVM_PREFERRED_TYPE(bool)
  unsigned packed : 1;
  LLVM_PREFERRED_TYPE(bool)
  unsigned padded : 1;

private:
  CIRRecordLowering(const CIRRecordLowering &) = delete;
  void operator=(const CIRRecordLowering &) = delete;
}; // CIRRecordLowering
} // namespace

CIRRecordLowering::CIRRecordLowering(CIRGenTypes &cirGenTypes,
                                     const RecordDecl *recordDecl, bool packed)
    : cirGenTypes(cirGenTypes), builder(cirGenTypes.getBuilder()),
      astContext(cirGenTypes.getASTContext()), recordDecl(recordDecl),
      astRecordLayout(
          cirGenTypes.getASTContext().getASTRecordLayout(recordDecl)),
      dataLayout(cirGenTypes.getCGModule().getModule()),
      zeroInitializable(true), zeroInitializableAsBase(true), packed(packed),
      padded(false) {}

void CIRRecordLowering::setBitFieldInfo(const FieldDecl *fd,
                                        CharUnits startOffset,
                                        mlir::Type storageType) {
  CIRGenBitFieldInfo &info = bitFields[fd->getCanonicalDecl()];
  info.isSigned = fd->getType()->isSignedIntegerOrEnumerationType();
  info.offset =
      (unsigned)(getFieldBitOffset(fd) - astContext.toBits(startOffset));
  info.size = fd->getBitWidthValue();
  info.storageSize = getSizeInBits(storageType).getQuantity();
  info.storageOffset = startOffset;
  info.storageType = storageType;
  info.name = fd->getName();

  if (info.size > info.storageSize)
    info.size = info.storageSize;
  // Reverse the bit offsets for big endian machines. Since bitfields are laid
  // out as packed bits within an integer-sized unit, we can imagine the bits
  // counting from the most-significant-bit instead of the
  // least-significant-bit.
  if (dataLayout.isBigEndian())
    info.offset = info.storageSize - (info.offset + info.size);

  info.volatileStorageSize = 0;
  info.volatileOffset = 0;
  info.volatileStorageOffset = CharUnits::Zero();
}

void CIRRecordLowering::lower() {
  if (recordDecl->isUnion()) {
    lowerUnion();
    computeVolatileBitfields();
    return;
  }

  assert(!cir::MissingFeatures::recordLayoutVirtualBases());
  CharUnits size = astRecordLayout.getSize();

  accumulateFields();

  if (const auto *cxxRecordDecl = dyn_cast<CXXRecordDecl>(recordDecl)) {
    accumulateVPtrs();
    accumulateBases(cxxRecordDecl);
    if (members.empty()) {
      appendPaddingBytes(size);
      computeVolatileBitfields();
      return;
    }
    assert(!cir::MissingFeatures::recordLayoutVirtualBases());
  }

  llvm::stable_sort(members);
  // TODO: implement clipTailPadding once bitfields are implemented
  assert(!cir::MissingFeatures::bitfields());
  assert(!cir::MissingFeatures::recordZeroInit());

  members.push_back(makeStorageInfo(size, getUIntNType(8)));
  determinePacked();
  insertPadding();
  members.pop_back();

  calculateZeroInit();
  fillOutputFields();
  computeVolatileBitfields();
}

void CIRRecordLowering::fillOutputFields() {
  for (const MemberInfo &member : members) {
    if (member.data)
      fieldTypes.push_back(member.data);
    if (member.kind == MemberInfo::InfoKind::Field) {
      if (member.fieldDecl)
        fieldIdxMap[member.fieldDecl->getCanonicalDecl()] =
            fieldTypes.size() - 1;
      // A field without storage must be a bitfield.
      assert(!cir::MissingFeatures::bitfields());
      if (!member.data)
        setBitFieldInfo(member.fieldDecl, member.offset, fieldTypes.back());
    } else if (member.kind == MemberInfo::InfoKind::Base) {
      nonVirtualBases[member.cxxRecordDecl] = fieldTypes.size() - 1;
    }
    assert(!cir::MissingFeatures::recordLayoutVirtualBases());
  }
}

RecordDecl::field_iterator
CIRRecordLowering::accumulateBitFields(RecordDecl::field_iterator field,
                                       RecordDecl::field_iterator fieldEnd) {
  assert(!cir::MissingFeatures::isDiscreteBitFieldABI());

  CharUnits regSize =
      bitsToCharUnits(astContext.getTargetInfo().getRegisterWidth());
  unsigned charBits = astContext.getCharWidth();

  // Data about the start of the span we're accumulating to create an access
  // unit from. 'Begin' is the first bitfield of the span. If 'begin' is
  // 'fieldEnd', we've not got a current span. The span starts at the
  // 'beginOffset' character boundary. 'bitSizeSinceBegin' is the size (in bits)
  // of the span -- this might include padding when we've advanced to a
  // subsequent bitfield run.
  RecordDecl::field_iterator begin = fieldEnd;
  CharUnits beginOffset;
  uint64_t bitSizeSinceBegin;

  // The (non-inclusive) end of the largest acceptable access unit we've found
  // since 'begin'. If this is 'begin', we're gathering the initial set of
  // bitfields of a new span. 'bestEndOffset' is the end of that acceptable
  // access unit -- it might extend beyond the last character of the bitfield
  // run, using available padding characters.
  RecordDecl::field_iterator bestEnd = begin;
  CharUnits bestEndOffset;
  bool bestClipped; // Whether the representation must be in a byte array.

  for (;;) {
    // atAlignedBoundary is true if 'field' is the (potential) start of a new
    // span (or the end of the bitfields). When true, limitOffset is the
    // character offset of that span and barrier indicates whether the new
    // span cannot be merged into the current one.
    bool atAlignedBoundary = false;
    bool barrier = false; // a barrier can be a zero Bit Width or non bit member
    if (field != fieldEnd && field->isBitField()) {
      uint64_t bitOffset = getFieldBitOffset(*field);
      if (begin == fieldEnd) {
        // Beginning a new span.
        begin = field;
        bestEnd = begin;

        assert((bitOffset % charBits) == 0 && "Not at start of char");
        beginOffset = bitsToCharUnits(bitOffset);
        bitSizeSinceBegin = 0;
      } else if ((bitOffset % charBits) != 0) {
        // Bitfield occupies the same character as previous bitfield, it must be
        // part of the same span. This can include zero-length bitfields, should
        // the target not align them to character boundaries. Such non-alignment
        // is at variance with the standards, which require zero-length
        // bitfields be a barrier between access units. But of course we can't
        // achieve that in the middle of a character.
        assert(bitOffset ==
                   astContext.toBits(beginOffset) + bitSizeSinceBegin &&
               "Concatenating non-contiguous bitfields");
      } else {
        // Bitfield potentially begins a new span. This includes zero-length
        // bitfields on non-aligning targets that lie at character boundaries
        // (those are barriers to merging).
        if (field->isZeroLengthBitField())
          barrier = true;
        atAlignedBoundary = true;
      }
    } else {
      // We've reached the end of the bitfield run. Either we're done, or this
      // is a barrier for the current span.
      if (begin == fieldEnd)
        break;

      barrier = true;
      atAlignedBoundary = true;
    }

    // 'installBest' indicates whether we should create an access unit for the
    // current best span: fields ['begin', 'bestEnd') occupying characters
    // ['beginOffset', 'bestEndOffset').
    bool installBest = false;
    if (atAlignedBoundary) {
      // 'field' is the start of a new span or the end of the bitfields. The
      // just-seen span now extends to 'bitSizeSinceBegin'.

      // Determine if we can accumulate that just-seen span into the current
      // accumulation.
      CharUnits accessSize = bitsToCharUnits(bitSizeSinceBegin + charBits - 1);
      if (bestEnd == begin) {
        // This is the initial run at the start of a new span. By definition,
        // this is the best seen so far.
        bestEnd = field;
        bestEndOffset = beginOffset + accessSize;
        // Assume clipped until proven not below.
        bestClipped = true;
        if (!bitSizeSinceBegin)
          // A zero-sized initial span -- this will install nothing and reset
          // for another.
          installBest = true;
      } else if (accessSize > regSize) {
        // Accumulating the just-seen span would create a multi-register access
        // unit, which would increase register pressure.
        installBest = true;
      }

      if (!installBest) {
        // Determine if accumulating the just-seen span will create an expensive
        // access unit or not.
        mlir::Type type = getUIntNType(astContext.toBits(accessSize));
        if (!astContext.getTargetInfo().hasCheapUnalignedBitFieldAccess())
          cirGenTypes.getCGModule().errorNYI(
              field->getSourceRange(), "NYI CheapUnalignedBitFieldAccess");

        if (!installBest) {
          // Find the next used storage offset to determine what the limit of
          // the current span is. That's either the offset of the next field
          // with storage (which might be field itself) or the end of the
          // non-reusable tail padding.
          CharUnits limitOffset;
          for (auto probe = field; probe != fieldEnd; ++probe)
            if (!isEmptyFieldForLayout(astContext, *probe)) {
              // A member with storage sets the limit.
              assert((getFieldBitOffset(*probe) % charBits) == 0 &&
                     "Next storage is not byte-aligned");
              limitOffset = bitsToCharUnits(getFieldBitOffset(*probe));
              goto FoundLimit;
            }
          assert(!cir::MissingFeatures::cxxSupport());
          limitOffset = astRecordLayout.getDataSize();
        FoundLimit:
          CharUnits typeSize = getSize(type);
          if (beginOffset + typeSize <= limitOffset) {
            // There is space before limitOffset to create a naturally-sized
            // access unit.
            bestEndOffset = beginOffset + typeSize;
            bestEnd = field;
            bestClipped = false;
          }
          if (barrier) {
            // The next field is a barrier that we cannot merge across.
            installBest = true;
          } else if (cirGenTypes.getCGModule()
                         .getCodeGenOpts()
                         .FineGrainedBitfieldAccesses) {
            assert(!cir::MissingFeatures::nonFineGrainedBitfields());
            cirGenTypes.getCGModule().errorNYI(field->getSourceRange(),
                                               "NYI FineGrainedBitfield");
          } else {
            // Otherwise, we're not installing. Update the bit size
            // of the current span to go all the way to limitOffset, which is
            // the (aligned) offset of next bitfield to consider.
            bitSizeSinceBegin = astContext.toBits(limitOffset - beginOffset);
          }
        }
      }
    }

    if (installBest) {
      assert((field == fieldEnd || !field->isBitField() ||
              (getFieldBitOffset(*field) % charBits) == 0) &&
             "Installing but not at an aligned bitfield or limit");
      CharUnits accessSize = bestEndOffset - beginOffset;
      if (!accessSize.isZero()) {
        // Add the storage member for the access unit to the record. The
        // bitfields get the offset of their storage but come afterward and
        // remain there after a stable sort.
        mlir::Type type;
        if (bestClipped) {
          assert(getSize(getUIntNType(astContext.toBits(accessSize))) >
                     accessSize &&
                 "Clipped access need not be clipped");
          type = getByteArrayType(accessSize);
        } else {
          type = getUIntNType(astContext.toBits(accessSize));
          assert(getSize(type) == accessSize &&
                 "Unclipped access must be clipped");
        }
        members.push_back(makeStorageInfo(beginOffset, type));
        for (; begin != bestEnd; ++begin)
          if (!begin->isZeroLengthBitField())
            members.push_back(MemberInfo(
                beginOffset, MemberInfo::InfoKind::Field, nullptr, *begin));
      }
      // Reset to start a new span.
      field = bestEnd;
      begin = fieldEnd;
    } else {
      assert(field != fieldEnd && field->isBitField() &&
             "Accumulating past end of bitfields");
      assert(!barrier && "Accumulating across barrier");
      // Accumulate this bitfield into the current (potential) span.
      bitSizeSinceBegin += field->getBitWidthValue();
      ++field;
    }
  }

  return field;
}

void CIRRecordLowering::accumulateFields() {
  for (RecordDecl::field_iterator field = recordDecl->field_begin(),
                                  fieldEnd = recordDecl->field_end();
       field != fieldEnd;) {
    if (field->isBitField()) {
      RecordDecl::field_iterator start = field;
      // Iterate to gather the list of bitfields.
      for (++field; field != fieldEnd && field->isBitField(); ++field)
        ;
      field = accumulateBitFields(start, field);
      assert((field == fieldEnd || !field->isBitField()) &&
             "Failed to accumulate all the bitfields");
    } else if (!field->isZeroSize(astContext)) {
      members.push_back(MemberInfo(bitsToCharUnits(getFieldBitOffset(*field)),
                                   MemberInfo::InfoKind::Field,
                                   getStorageType(*field), *field));
      ++field;
    } else {
      // TODO(cir): do we want to do anything special about zero size members?
      assert(!cir::MissingFeatures::zeroSizeRecordMembers());
      ++field;
    }
  }
}

void CIRRecordLowering::calculateZeroInit() {
  for (const MemberInfo &member : members) {
    if (member.kind == MemberInfo::InfoKind::Field) {
      if (!member.fieldDecl || isZeroInitializable(member.fieldDecl))
        continue;
      zeroInitializable = zeroInitializableAsBase = false;
      return;
    } else if (member.kind == MemberInfo::InfoKind::Base) {
      if (isZeroInitializable(member.cxxRecordDecl))
        continue;
      zeroInitializable = false;
      if (member.kind == MemberInfo::InfoKind::Base)
        zeroInitializableAsBase = false;
    }
    assert(!cir::MissingFeatures::recordLayoutVirtualBases());
  }
}

void CIRRecordLowering::determinePacked() {
  if (packed)
    return;
  CharUnits alignment = CharUnits::One();

  // TODO(cir): handle non-virtual base types
  assert(!cir::MissingFeatures::cxxSupport());

  for (const MemberInfo &member : members) {
    if (!member.data)
      continue;
    // If any member falls at an offset that it not a multiple of its alignment,
    // then the entire record must be packed.
    if (member.offset % getAlignment(member.data))
      packed = true;
    alignment = std::max(alignment, getAlignment(member.data));
  }
  // If the size of the record (the capstone's offset) is not a multiple of the
  // record's alignment, it must be packed.
  if (members.back().offset % alignment)
    packed = true;
  // Update the alignment of the sentinel.
  if (!packed)
    members.back().data = getUIntNType(astContext.toBits(alignment));
}

void CIRRecordLowering::insertPadding() {
  std::vector<std::pair<CharUnits, CharUnits>> padding;
  CharUnits size = CharUnits::Zero();
  for (const MemberInfo &member : members) {
    if (!member.data)
      continue;
    CharUnits offset = member.offset;
    assert(offset >= size);
    // Insert padding if we need to.
    if (offset !=
        size.alignTo(packed ? CharUnits::One() : getAlignment(member.data)))
      padding.push_back(std::make_pair(size, offset - size));
    size = offset + getSize(member.data);
  }
  if (padding.empty())
    return;
  padded = true;
  // Add the padding to the Members list and sort it.
  for (const std::pair<CharUnits, CharUnits> &paddingPair : padding)
    members.push_back(makeStorageInfo(paddingPair.first,
                                      getByteArrayType(paddingPair.second)));
  llvm::stable_sort(members);
}

std::unique_ptr<CIRGenRecordLayout>
CIRGenTypes::computeRecordLayout(const RecordDecl *rd, cir::RecordType *ty) {
  CIRRecordLowering lowering(*this, rd, /*packed=*/false);
  assert(ty->isIncomplete() && "recomputing record layout?");
  lowering.lower();

  // If we're in C++, compute the base subobject type.
  cir::RecordType baseTy;
  if (llvm::isa<CXXRecordDecl>(rd) && !rd->isUnion() &&
      !rd->hasAttr<FinalAttr>()) {
    baseTy = *ty;
    if (lowering.astRecordLayout.getNonVirtualSize() !=
        lowering.astRecordLayout.getSize()) {
      CIRRecordLowering baseLowering(*this, rd, /*Packed=*/lowering.packed);
      baseLowering.lower();
      std::string baseIdentifier = getRecordTypeName(rd, ".base");
      baseTy =
          builder.getCompleteRecordTy(baseLowering.fieldTypes, baseIdentifier,
                                      baseLowering.packed, baseLowering.padded);
      // TODO(cir): add something like addRecordTypeName

      // BaseTy and Ty must agree on their packedness for getCIRFieldNo to work
      // on both of them with the same index.
      assert(lowering.packed == baseLowering.packed &&
             "Non-virtual and complete types must agree on packedness");
    }
  }

  // Fill in the record *after* computing the base type.  Filling in the body
  // signifies that the type is no longer opaque and record layout is complete,
  // but we may need to recursively layout rd while laying D out as a base type.
  assert(!cir::MissingFeatures::astRecordDeclAttr());
  ty->complete(lowering.fieldTypes, lowering.packed, lowering.padded);

  auto rl = std::make_unique<CIRGenRecordLayout>(
      ty ? *ty : cir::RecordType{}, baseTy ? baseTy : cir::RecordType{},
      (bool)lowering.zeroInitializable, (bool)lowering.zeroInitializableAsBase);

  assert(!cir::MissingFeatures::recordZeroInit());

  rl->nonVirtualBases.swap(lowering.nonVirtualBases);

  assert(!cir::MissingFeatures::cxxSupport());
  assert(!cir::MissingFeatures::bitfields());

  // Add all the field numbers.
  rl->fieldIdxMap.swap(lowering.fieldIdxMap);

  rl->bitFields.swap(lowering.bitFields);

  // Dump the layout, if requested.
  if (getASTContext().getLangOpts().DumpRecordLayouts) {
    llvm::outs() << "\n*** Dumping CIRgen Record Layout\n";
    llvm::outs() << "Record: ";
    rd->dump(llvm::outs());
    llvm::outs() << "\nLayout: ";
    rl->print(llvm::outs());
  }

  // TODO: implement verification
  return rl;
}

void CIRGenRecordLayout::print(raw_ostream &os) const {
  os << "<CIRecordLayout\n";
  os << "   CIR Type:" << completeObjectType << "\n";
  if (baseSubobjectType)
    os << "   NonVirtualBaseCIRType:" << baseSubobjectType << "\n";
  os << "   IsZeroInitializable:" << zeroInitializable << "\n";
  os << "   BitFields:[\n";
  std::vector<std::pair<unsigned, const CIRGenBitFieldInfo *>> bitInfo;
  for (auto &[decl, info] : bitFields) {
    const RecordDecl *rd = decl->getParent();
    unsigned index = 0;
    for (RecordDecl::field_iterator it = rd->field_begin(); *it != decl; ++it)
      ++index;
    bitInfo.push_back(std::make_pair(index, &info));
  }
  llvm::array_pod_sort(bitInfo.begin(), bitInfo.end());
  for (std::pair<unsigned, const CIRGenBitFieldInfo *> &info : bitInfo) {
    os.indent(4);
    info.second->print(os);
    os << "\n";
  }
  os << "   ]>\n";
}

void CIRGenBitFieldInfo::print(raw_ostream &os) const {
  os << "<CIRBitFieldInfo" << " name:" << name << " offset:" << offset
     << " size:" << size << " isSigned:" << isSigned
     << " storageSize:" << storageSize
     << " storageOffset:" << storageOffset.getQuantity()
     << " volatileOffset:" << volatileOffset
     << " volatileStorageSize:" << volatileStorageSize
     << " volatileStorageOffset:" << volatileStorageOffset.getQuantity() << ">";
}

void CIRGenRecordLayout::dump() const { print(llvm::errs()); }

void CIRGenBitFieldInfo::dump() const { print(llvm::errs()); }

void CIRRecordLowering::lowerUnion() {
  CharUnits layoutSize = astRecordLayout.getSize();
  mlir::Type storageType = nullptr;
  bool seenNamedMember = false;

  // Iterate through the fields setting bitFieldInfo and the Fields array. Also
  // locate the "most appropriate" storage type.
  for (const FieldDecl *field : recordDecl->fields()) {
    mlir::Type fieldType;
    if (field->isBitField()) {
      if (field->isZeroLengthBitField())
        continue;
      fieldType = getBitfieldStorageType(field->getBitWidthValue());
      setBitFieldInfo(field, CharUnits::Zero(), fieldType);
    } else {
      fieldType = getStorageType(field);
    }

    // This maps a field to its index. For unions, the index is always 0.
    fieldIdxMap[field->getCanonicalDecl()] = 0;

    // Compute zero-initializable status.
    // This union might not be zero initialized: it may contain a pointer to
    // data member which might have some exotic initialization sequence.
    // If this is the case, then we ought not to try and come up with a "better"
    // type, it might not be very easy to come up with a Constant which
    // correctly initializes it.
    if (!seenNamedMember) {
      seenNamedMember = field->getIdentifier();
      if (!seenNamedMember)
        if (const RecordDecl *fieldRD = field->getType()->getAsRecordDecl())
          seenNamedMember = fieldRD->findFirstNamedDataMember();
      if (seenNamedMember && !isZeroInitializable(field)) {
        zeroInitializable = zeroInitializableAsBase = false;
        storageType = fieldType;
      }
    }

    // Because our union isn't zero initializable, we won't be getting a better
    // storage type.
    if (!zeroInitializable)
      continue;

    // Conditionally update our storage type if we've got a new "better" one.
    if (!storageType || getAlignment(fieldType) > getAlignment(storageType) ||
        (getAlignment(fieldType) == getAlignment(storageType) &&
         getSize(fieldType) > getSize(storageType)))
      storageType = fieldType;

    // NOTE(cir): Track all union member's types, not just the largest one. It
    // allows for proper type-checking and retain more info for analisys.
    fieldTypes.push_back(fieldType);
  }

  if (!storageType)
    cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
                                       "No-storage Union NYI");

  if (layoutSize < getSize(storageType))
    storageType = getByteArrayType(layoutSize);
  else
    appendPaddingBytes(layoutSize - getSize(storageType));

  // Set packed if we need it.
  if (layoutSize % getAlignment(storageType))
    packed = true;
}

/// The AAPCS that defines that, when possible, bit-fields should
/// be accessed using containers of the declared type width:
/// When a volatile bit-field is read, and its container does not overlap with
/// any non-bit-field member or any zero length bit-field member, its container
/// must be read exactly once using the access width appropriate to the type of
/// the container. When a volatile bit-field is written, and its container does
/// not overlap with any non-bit-field member or any zero-length bit-field
/// member, its container must be read exactly once and written exactly once
/// using the access width appropriate to the type of the container. The two
/// accesses are not atomic.
///
/// Enforcing the width restriction can be disabled using
/// -fno-aapcs-bitfield-width.
void CIRRecordLowering::computeVolatileBitfields() {
  if (!isAAPCS() ||
      !cirGenTypes.getCGModule().getCodeGenOpts().AAPCSBitfieldWidth)
    return;

  assert(!cir::MissingFeatures::armComputeVolatileBitfields());
}

void CIRRecordLowering::accumulateBases(const CXXRecordDecl *cxxRecordDecl) {
  // If we've got a primary virtual base, we need to add it with the bases.
  if (astRecordLayout.isPrimaryBaseVirtual()) {
    cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
                                       "accumulateBases: primary virtual base");
  }

  // Accumulate the non-virtual bases.
  for ([[maybe_unused]] const auto &base : cxxRecordDecl->bases()) {
    if (base.isVirtual()) {
      cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
                                         "accumulateBases: virtual base");
      continue;
    }
    // Bases can be zero-sized even if not technically empty if they
    // contain only a trailing array member.
    const CXXRecordDecl *baseDecl = base.getType()->getAsCXXRecordDecl();
    if (!baseDecl->isEmpty() &&
        !astContext.getASTRecordLayout(baseDecl).getNonVirtualSize().isZero()) {
      members.push_back(MemberInfo(astRecordLayout.getBaseClassOffset(baseDecl),
                                   MemberInfo::InfoKind::Base,
                                   getStorageType(baseDecl), baseDecl));
    }
  }
}

void CIRRecordLowering::accumulateVPtrs() {
  if (astRecordLayout.hasOwnVFPtr())
    cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
                                       "accumulateVPtrs: hasOwnVFPtr");
  if (astRecordLayout.hasOwnVBPtr())
    cirGenTypes.getCGModule().errorNYI(recordDecl->getSourceRange(),
                                       "accumulateVPtrs: hasOwnVBPtr");
}
