//===--- CGExprConstant.cpp - Emit LLVM Code from Constant Expressions ----===//
//
// 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 emit Constant Expr nodes as LLVM code.
//
//===----------------------------------------------------------------------===//

#include "ABIInfoImpl.h"
#include "CGCXXABI.h"
#include "CGObjCRuntime.h"
#include "CGRecordLayout.h"
#include "CodeGenFunction.h"
#include "CodeGenModule.h"
#include "ConstantEmitter.h"
#include "TargetInfo.h"
#include "clang/AST/APValue.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Attr.h"
#include "clang/AST/MatrixUtils.h"
#include "clang/AST/NSAPI.h"
#include "clang/AST/RecordLayout.h"
#include "clang/AST/StmtVisitor.h"
#include "clang/Basic/Builtins.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/Sequence.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/IR/Constants.h"
#include "llvm/IR/DataLayout.h"
#include "llvm/IR/Function.h"
#include "llvm/IR/GlobalVariable.h"
#include "llvm/Support/SipHash.h"
#include <optional>
using namespace clang;
using namespace CodeGen;

//===----------------------------------------------------------------------===//
//                            ConstantAggregateBuilder
//===----------------------------------------------------------------------===//

namespace {
class ConstExprEmitter;

llvm::Constant *getPadding(const CodeGenModule &CGM, CharUnits PadSize) {
  llvm::Type *Ty = CGM.CharTy;
  if (PadSize > CharUnits::One())
    Ty = llvm::ArrayType::get(Ty, PadSize.getQuantity());
  if (CGM.shouldZeroInitPadding()) {
    return llvm::Constant::getNullValue(Ty);
  }
  return llvm::UndefValue::get(Ty);
}

struct ConstantAggregateBuilderUtils {
  CodeGenModule &CGM;

  ConstantAggregateBuilderUtils(CodeGenModule &CGM) : CGM(CGM) {}

  CharUnits getAlignment(const llvm::Constant *C) const {
    return CharUnits::fromQuantity(
        CGM.getDataLayout().getABITypeAlign(C->getType()));
  }

  CharUnits getSize(llvm::Type *Ty) const {
    return CharUnits::fromQuantity(CGM.getDataLayout().getTypeAllocSize(Ty));
  }

  CharUnits getSize(const llvm::Constant *C) const {
    return getSize(C->getType());
  }

  llvm::Constant *getPadding(CharUnits PadSize) const {
    return ::getPadding(CGM, PadSize);
  }

  llvm::Constant *getZeroes(CharUnits ZeroSize) const {
    llvm::Type *Ty = llvm::ArrayType::get(CGM.CharTy, ZeroSize.getQuantity());
    return llvm::ConstantAggregateZero::get(Ty);
  }
};

/// Incremental builder for an llvm::Constant* holding a struct or array
/// constant.
class ConstantAggregateBuilder : private ConstantAggregateBuilderUtils {
  /// The elements of the constant. These two arrays must have the same size;
  /// Offsets[i] describes the offset of Elems[i] within the constant. The
  /// elements are kept in increasing offset order, and we ensure that there
  /// is no overlap: Offsets[i+1] >= Offsets[i] + getSize(Elemes[i]).
  ///
  /// This may contain explicit padding elements (in order to create a
  /// natural layout), but need not. Gaps between elements are implicitly
  /// considered to be filled with undef.
  llvm::SmallVector<llvm::Constant*, 32> Elems;
  llvm::SmallVector<CharUnits, 32> Offsets;

  /// The size of the constant (the maximum end offset of any added element).
  /// May be larger than the end of Elems.back() if we split the last element
  /// and removed some trailing undefs.
  CharUnits Size = CharUnits::Zero();

  /// This is true only if laying out Elems in order as the elements of a
  /// non-packed LLVM struct will give the correct layout.
  bool NaturalLayout = true;

  bool split(size_t Index, CharUnits Hint);
  std::optional<size_t> splitAt(CharUnits Pos);

  static llvm::Constant *buildFrom(CodeGenModule &CGM,
                                   ArrayRef<llvm::Constant *> Elems,
                                   ArrayRef<CharUnits> Offsets,
                                   CharUnits StartOffset, CharUnits Size,
                                   bool NaturalLayout, llvm::Type *DesiredTy,
                                   bool AllowOversized);

public:
  ConstantAggregateBuilder(CodeGenModule &CGM)
      : ConstantAggregateBuilderUtils(CGM) {}

  /// Update or overwrite the value starting at \p Offset with \c C.
  ///
  /// \param AllowOverwrite If \c true, this constant might overwrite (part of)
  ///        a constant that has already been added. This flag is only used to
  ///        detect bugs.
  bool add(llvm::Constant *C, CharUnits Offset, bool AllowOverwrite);

  /// Update or overwrite the bits starting at \p OffsetInBits with \p Bits.
  bool addBits(llvm::APInt Bits, uint64_t OffsetInBits, bool AllowOverwrite);

  /// Attempt to condense the value starting at \p Offset to a constant of type
  /// \p DesiredTy.
  void condense(CharUnits Offset, llvm::Type *DesiredTy);

  /// Produce a constant representing the entire accumulated value, ideally of
  /// the specified type. If \p AllowOversized, the constant might be larger
  /// than implied by \p DesiredTy (eg, if there is a flexible array member).
  /// Otherwise, the constant will be of exactly the same size as \p DesiredTy
  /// even if we can't represent it as that type.
  llvm::Constant *build(llvm::Type *DesiredTy, bool AllowOversized) const {
    return buildFrom(CGM, Elems, Offsets, CharUnits::Zero(), Size,
                     NaturalLayout, DesiredTy, AllowOversized);
  }
};

template<typename Container, typename Range = std::initializer_list<
                                 typename Container::value_type>>
static void replace(Container &C, size_t BeginOff, size_t EndOff, Range Vals) {
  assert(BeginOff <= EndOff && "invalid replacement range");
  llvm::replace(C, C.begin() + BeginOff, C.begin() + EndOff, Vals);
}

bool ConstantAggregateBuilder::add(llvm::Constant *C, CharUnits Offset,
                          bool AllowOverwrite) {
  // Common case: appending to a layout.
  if (Offset >= Size) {
    CharUnits Align = getAlignment(C);
    CharUnits AlignedSize = Size.alignTo(Align);
    if (AlignedSize > Offset || Offset.alignTo(Align) != Offset)
      NaturalLayout = false;
    else if (AlignedSize < Offset) {
      Elems.push_back(getPadding(Offset - Size));
      Offsets.push_back(Size);
    }
    Elems.push_back(C);
    Offsets.push_back(Offset);
    Size = Offset + getSize(C);
    return true;
  }

  // Uncommon case: constant overlaps what we've already created.
  std::optional<size_t> FirstElemToReplace = splitAt(Offset);
  if (!FirstElemToReplace)
    return false;

  CharUnits CSize = getSize(C);
  std::optional<size_t> LastElemToReplace = splitAt(Offset + CSize);
  if (!LastElemToReplace)
    return false;

  assert((FirstElemToReplace == LastElemToReplace || AllowOverwrite) &&
         "unexpectedly overwriting field");

  replace(Elems, *FirstElemToReplace, *LastElemToReplace, {C});
  replace(Offsets, *FirstElemToReplace, *LastElemToReplace, {Offset});
  Size = std::max(Size, Offset + CSize);
  NaturalLayout = false;
  return true;
}

bool ConstantAggregateBuilder::addBits(llvm::APInt Bits, uint64_t OffsetInBits,
                              bool AllowOverwrite) {
  const ASTContext &Context = CGM.getContext();
  const uint64_t CharWidth = CGM.getContext().getCharWidth();

  // Offset of where we want the first bit to go within the bits of the
  // current char.
  unsigned OffsetWithinChar = OffsetInBits % CharWidth;

  // We split bit-fields up into individual bytes. Walk over the bytes and
  // update them.
  for (CharUnits OffsetInChars =
           Context.toCharUnitsFromBits(OffsetInBits - OffsetWithinChar);
       /**/; ++OffsetInChars) {
    // Number of bits we want to fill in this char.
    unsigned WantedBits =
        std::min((uint64_t)Bits.getBitWidth(), CharWidth - OffsetWithinChar);

    // Get a char containing the bits we want in the right places. The other
    // bits have unspecified values.
    llvm::APInt BitsThisChar = Bits;
    if (BitsThisChar.getBitWidth() < CharWidth)
      BitsThisChar = BitsThisChar.zext(CharWidth);
    if (CGM.getDataLayout().isBigEndian()) {
      // Figure out how much to shift by. We may need to left-shift if we have
      // less than one byte of Bits left.
      int Shift = Bits.getBitWidth() - CharWidth + OffsetWithinChar;
      if (Shift > 0)
        BitsThisChar.lshrInPlace(Shift);
      else if (Shift < 0)
        BitsThisChar = BitsThisChar.shl(-Shift);
    } else {
      BitsThisChar = BitsThisChar.shl(OffsetWithinChar);
    }
    if (BitsThisChar.getBitWidth() > CharWidth)
      BitsThisChar = BitsThisChar.trunc(CharWidth);

    if (WantedBits == CharWidth) {
      // Got a full byte: just add it directly.
      add(llvm::ConstantInt::get(CGM.getLLVMContext(), BitsThisChar),
          OffsetInChars, AllowOverwrite);
    } else {
      // Partial byte: update the existing integer if there is one. If we
      // can't split out a 1-CharUnit range to update, then we can't add
      // these bits and fail the entire constant emission.
      std::optional<size_t> FirstElemToUpdate = splitAt(OffsetInChars);
      if (!FirstElemToUpdate)
        return false;
      std::optional<size_t> LastElemToUpdate =
          splitAt(OffsetInChars + CharUnits::One());
      if (!LastElemToUpdate)
        return false;
      assert(*LastElemToUpdate - *FirstElemToUpdate < 2 &&
             "should have at most one element covering one byte");

      // Figure out which bits we want and discard the rest.
      llvm::APInt UpdateMask(CharWidth, 0);
      if (CGM.getDataLayout().isBigEndian())
        UpdateMask.setBits(CharWidth - OffsetWithinChar - WantedBits,
                           CharWidth - OffsetWithinChar);
      else
        UpdateMask.setBits(OffsetWithinChar, OffsetWithinChar + WantedBits);
      BitsThisChar &= UpdateMask;

      if (*FirstElemToUpdate == *LastElemToUpdate ||
          Elems[*FirstElemToUpdate]->isNullValue() ||
          isa<llvm::UndefValue>(Elems[*FirstElemToUpdate])) {
        // All existing bits are either zero or undef.
        add(llvm::ConstantInt::get(CGM.getLLVMContext(), BitsThisChar),
            OffsetInChars, /*AllowOverwrite*/ true);
      } else {
        llvm::Constant *&ToUpdate = Elems[*FirstElemToUpdate];
        // In order to perform a partial update, we need the existing bitwise
        // value, which we can only extract for a constant int.
        auto *CI = dyn_cast<llvm::ConstantInt>(ToUpdate);
        if (!CI)
          return false;
        // Because this is a 1-CharUnit range, the constant occupying it must
        // be exactly one CharUnit wide.
        assert(CI->getBitWidth() == CharWidth && "splitAt failed");
        assert((!(CI->getValue() & UpdateMask) || AllowOverwrite) &&
               "unexpectedly overwriting bitfield");
        BitsThisChar |= (CI->getValue() & ~UpdateMask);
        ToUpdate = llvm::ConstantInt::get(CGM.getLLVMContext(), BitsThisChar);
      }
    }

    // Stop if we've added all the bits.
    if (WantedBits == Bits.getBitWidth())
      break;

    // Remove the consumed bits from Bits.
    if (!CGM.getDataLayout().isBigEndian())
      Bits.lshrInPlace(WantedBits);
    Bits = Bits.trunc(Bits.getBitWidth() - WantedBits);

    // The remanining bits go at the start of the following bytes.
    OffsetWithinChar = 0;
  }

  return true;
}

/// Returns a position within Elems and Offsets such that all elements
/// before the returned index end before Pos and all elements at or after
/// the returned index begin at or after Pos. Splits elements as necessary
/// to ensure this. Returns std::nullopt if we find something we can't split.
std::optional<size_t> ConstantAggregateBuilder::splitAt(CharUnits Pos) {
  if (Pos >= Size)
    return Offsets.size();

  while (true) {
    auto FirstAfterPos = llvm::upper_bound(Offsets, Pos);
    if (FirstAfterPos == Offsets.begin())
      return 0;

    // If we already have an element starting at Pos, we're done.
    size_t LastAtOrBeforePosIndex = FirstAfterPos - Offsets.begin() - 1;
    if (Offsets[LastAtOrBeforePosIndex] == Pos)
      return LastAtOrBeforePosIndex;

    // We found an element starting before Pos. Check for overlap.
    if (Offsets[LastAtOrBeforePosIndex] +
        getSize(Elems[LastAtOrBeforePosIndex]) <= Pos)
      return LastAtOrBeforePosIndex + 1;

    // Try to decompose it into smaller constants.
    if (!split(LastAtOrBeforePosIndex, Pos))
      return std::nullopt;
  }
}

/// Split the constant at index Index, if possible. Return true if we did.
/// Hint indicates the location at which we'd like to split, but may be
/// ignored.
bool ConstantAggregateBuilder::split(size_t Index, CharUnits Hint) {
  NaturalLayout = false;
  llvm::Constant *C = Elems[Index];
  CharUnits Offset = Offsets[Index];

  if (auto *CA = dyn_cast<llvm::ConstantAggregate>(C)) {
    // Expand the sequence into its contained elements.
    // FIXME: This assumes vector elements are byte-sized.
    replace(Elems, Index, Index + 1,
            llvm::map_range(llvm::seq(0u, CA->getNumOperands()),
                            [&](unsigned Op) { return CA->getOperand(Op); }));
    if (isa<llvm::ArrayType>(CA->getType()) ||
        isa<llvm::VectorType>(CA->getType())) {
      // Array or vector.
      llvm::Type *ElemTy =
          llvm::GetElementPtrInst::getTypeAtIndex(CA->getType(), (uint64_t)0);
      CharUnits ElemSize = getSize(ElemTy);
      replace(
          Offsets, Index, Index + 1,
          llvm::map_range(llvm::seq(0u, CA->getNumOperands()),
                          [&](unsigned Op) { return Offset + Op * ElemSize; }));
    } else {
      // Must be a struct.
      auto *ST = cast<llvm::StructType>(CA->getType());
      const llvm::StructLayout *Layout =
          CGM.getDataLayout().getStructLayout(ST);
      replace(Offsets, Index, Index + 1,
              llvm::map_range(
                  llvm::seq(0u, CA->getNumOperands()), [&](unsigned Op) {
                    return Offset + CharUnits::fromQuantity(
                                        Layout->getElementOffset(Op));
                  }));
    }
    return true;
  }

  if (auto *CDS = dyn_cast<llvm::ConstantDataSequential>(C)) {
    // Expand the sequence into its contained elements.
    // FIXME: This assumes vector elements are byte-sized.
    // FIXME: If possible, split into two ConstantDataSequentials at Hint.
    CharUnits ElemSize = getSize(CDS->getElementType());
    replace(Elems, Index, Index + 1,
            llvm::map_range(llvm::seq(uint64_t(0u), CDS->getNumElements()),
                            [&](uint64_t Elem) {
                              return CDS->getElementAsConstant(Elem);
                            }));
    replace(Offsets, Index, Index + 1,
            llvm::map_range(
                llvm::seq(uint64_t(0u), CDS->getNumElements()),
                [&](uint64_t Elem) { return Offset + Elem * ElemSize; }));
    return true;
  }

  if (isa<llvm::ConstantAggregateZero>(C)) {
    // Split into two zeros at the hinted offset.
    CharUnits ElemSize = getSize(C);
    assert(Hint > Offset && Hint < Offset + ElemSize && "nothing to split");
    replace(Elems, Index, Index + 1,
            {getZeroes(Hint - Offset), getZeroes(Offset + ElemSize - Hint)});
    replace(Offsets, Index, Index + 1, {Offset, Hint});
    return true;
  }

  if (isa<llvm::UndefValue>(C)) {
    // Drop undef; it doesn't contribute to the final layout.
    replace(Elems, Index, Index + 1, {});
    replace(Offsets, Index, Index + 1, {});
    return true;
  }

  // FIXME: We could split a ConstantInt if the need ever arose.
  // We don't need to do this to handle bit-fields because we always eagerly
  // split them into 1-byte chunks.

  return false;
}

static llvm::Constant *
EmitArrayConstant(CodeGenModule &CGM, llvm::ArrayType *DesiredType,
                  llvm::Type *CommonElementType, uint64_t ArrayBound,
                  SmallVectorImpl<llvm::Constant *> &Elements,
                  llvm::Constant *Filler);

llvm::Constant *ConstantAggregateBuilder::buildFrom(
    CodeGenModule &CGM, ArrayRef<llvm::Constant *> Elems,
    ArrayRef<CharUnits> Offsets, CharUnits StartOffset, CharUnits Size,
    bool NaturalLayout, llvm::Type *DesiredTy, bool AllowOversized) {
  ConstantAggregateBuilderUtils Utils(CGM);

  if (Elems.empty())
    return llvm::UndefValue::get(DesiredTy);

  auto Offset = [&](size_t I) { return Offsets[I] - StartOffset; };

  // If we want an array type, see if all the elements are the same type and
  // appropriately spaced.
  if (llvm::ArrayType *ATy = dyn_cast<llvm::ArrayType>(DesiredTy)) {
    assert(!AllowOversized && "oversized array emission not supported");

    bool CanEmitArray = true;
    llvm::Type *CommonType = Elems[0]->getType();
    llvm::Constant *Filler = llvm::Constant::getNullValue(CommonType);
    CharUnits ElemSize = Utils.getSize(ATy->getElementType());
    SmallVector<llvm::Constant*, 32> ArrayElements;
    for (size_t I = 0; I != Elems.size(); ++I) {
      // Skip zeroes; we'll use a zero value as our array filler.
      if (Elems[I]->isNullValue())
        continue;

      // All remaining elements must be the same type.
      if (Elems[I]->getType() != CommonType ||
          !Offset(I).isMultipleOf(ElemSize)) {
        CanEmitArray = false;
        break;
      }
      ArrayElements.resize(Offset(I) / ElemSize + 1, Filler);
      ArrayElements.back() = Elems[I];
    }

    if (CanEmitArray) {
      return EmitArrayConstant(CGM, ATy, CommonType, ATy->getNumElements(),
                               ArrayElements, Filler);
    }

    // Can't emit as an array, carry on to emit as a struct.
  }

  // The size of the constant we plan to generate.  This is usually just
  // the size of the initialized type, but in AllowOversized mode (i.e.
  // flexible array init), it can be larger.
  CharUnits DesiredSize = Utils.getSize(DesiredTy);
  if (Size > DesiredSize) {
    assert(AllowOversized && "Elems are oversized");
    DesiredSize = Size;
  }

  // The natural alignment of an unpacked LLVM struct with the given elements.
  CharUnits Align = CharUnits::One();
  for (llvm::Constant *C : Elems)
    Align = std::max(Align, Utils.getAlignment(C));

  // The natural size of an unpacked LLVM struct with the given elements.
  CharUnits AlignedSize = Size.alignTo(Align);

  bool Packed = false;
  ArrayRef<llvm::Constant*> UnpackedElems = Elems;
  llvm::SmallVector<llvm::Constant*, 32> UnpackedElemStorage;
  if (DesiredSize < AlignedSize || DesiredSize.alignTo(Align) != DesiredSize) {
    // The natural layout would be too big; force use of a packed layout.
    NaturalLayout = false;
    Packed = true;
  } else if (DesiredSize > AlignedSize) {
    // The natural layout would be too small. Add padding to fix it. (This
    // is ignored if we choose a packed layout.)
    UnpackedElemStorage.assign(Elems.begin(), Elems.end());
    UnpackedElemStorage.push_back(Utils.getPadding(DesiredSize - Size));
    UnpackedElems = UnpackedElemStorage;
  }

  // If we don't have a natural layout, insert padding as necessary.
  // As we go, double-check to see if we can actually just emit Elems
  // as a non-packed struct and do so opportunistically if possible.
  llvm::SmallVector<llvm::Constant*, 32> PackedElems;
  if (!NaturalLayout) {
    CharUnits SizeSoFar = CharUnits::Zero();
    for (size_t I = 0; I != Elems.size(); ++I) {
      CharUnits Align = Utils.getAlignment(Elems[I]);
      CharUnits NaturalOffset = SizeSoFar.alignTo(Align);
      CharUnits DesiredOffset = Offset(I);
      assert(DesiredOffset >= SizeSoFar && "elements out of order");

      if (DesiredOffset != NaturalOffset)
        Packed = true;
      if (DesiredOffset != SizeSoFar)
        PackedElems.push_back(Utils.getPadding(DesiredOffset - SizeSoFar));
      PackedElems.push_back(Elems[I]);
      SizeSoFar = DesiredOffset + Utils.getSize(Elems[I]);
    }
    // If we're using the packed layout, pad it out to the desired size if
    // necessary.
    if (Packed) {
      assert(SizeSoFar <= DesiredSize &&
             "requested size is too small for contents");
      if (SizeSoFar < DesiredSize)
        PackedElems.push_back(Utils.getPadding(DesiredSize - SizeSoFar));
    }
  }

  llvm::StructType *STy = llvm::ConstantStruct::getTypeForElements(
      CGM.getLLVMContext(), Packed ? PackedElems : UnpackedElems, Packed);

  // Pick the type to use.  If the type is layout identical to the desired
  // type then use it, otherwise use whatever the builder produced for us.
  if (llvm::StructType *DesiredSTy = dyn_cast<llvm::StructType>(DesiredTy)) {
    if (DesiredSTy->isLayoutIdentical(STy))
      STy = DesiredSTy;
  }

  return llvm::ConstantStruct::get(STy, Packed ? PackedElems : UnpackedElems);
}

void ConstantAggregateBuilder::condense(CharUnits Offset,
                                        llvm::Type *DesiredTy) {
  CharUnits Size = getSize(DesiredTy);

  std::optional<size_t> FirstElemToReplace = splitAt(Offset);
  if (!FirstElemToReplace)
    return;
  size_t First = *FirstElemToReplace;

  std::optional<size_t> LastElemToReplace = splitAt(Offset + Size);
  if (!LastElemToReplace)
    return;
  size_t Last = *LastElemToReplace;

  size_t Length = Last - First;
  if (Length == 0)
    return;

  if (Length == 1 && Offsets[First] == Offset &&
      getSize(Elems[First]) == Size) {
    // Re-wrap single element structs if necessary. Otherwise, leave any single
    // element constant of the right size alone even if it has the wrong type.
    auto *STy = dyn_cast<llvm::StructType>(DesiredTy);
    if (STy && STy->getNumElements() == 1 &&
        STy->getElementType(0) == Elems[First]->getType())
      Elems[First] = llvm::ConstantStruct::get(STy, Elems[First]);
    return;
  }

  llvm::Constant *Replacement = buildFrom(
      CGM, ArrayRef(Elems).slice(First, Length),
      ArrayRef(Offsets).slice(First, Length), Offset, getSize(DesiredTy),
      /*known to have natural layout=*/false, DesiredTy, false);
  replace(Elems, First, Last, {Replacement});
  replace(Offsets, First, Last, {Offset});
}

//===----------------------------------------------------------------------===//
//                            ConstStructBuilder
//===----------------------------------------------------------------------===//

class ConstStructBuilder {
  CodeGenModule &CGM;
  ConstantEmitter &Emitter;
  ConstantAggregateBuilder &Builder;
  CharUnits StartOffset;

public:
  static llvm::Constant *BuildStruct(ConstantEmitter &Emitter,
                                     const InitListExpr *ILE,
                                     QualType StructTy);
  static llvm::Constant *BuildStruct(ConstantEmitter &Emitter,
                                     const APValue &Value, QualType ValTy);
  static bool UpdateStruct(ConstantEmitter &Emitter,
                           ConstantAggregateBuilder &Const, CharUnits Offset,
                           const InitListExpr *Updater);

private:
  ConstStructBuilder(ConstantEmitter &Emitter,
                     ConstantAggregateBuilder &Builder, CharUnits StartOffset)
      : CGM(Emitter.CGM), Emitter(Emitter), Builder(Builder),
        StartOffset(StartOffset) {}

  bool AppendField(const FieldDecl *Field, uint64_t FieldOffset,
                   llvm::Constant *InitExpr, bool AllowOverwrite = false);

  bool AppendBytes(CharUnits FieldOffsetInChars, llvm::Constant *InitCst,
                   bool AllowOverwrite = false);

  bool AppendBitField(const FieldDecl *Field, uint64_t FieldOffset,
                      llvm::Constant *InitExpr, bool AllowOverwrite = false);

  bool Build(const InitListExpr *ILE, bool AllowOverwrite);
  bool Build(const APValue &Val, const RecordDecl *RD, bool IsPrimaryBase,
             const CXXRecordDecl *VTableClass, CharUnits BaseOffset);
  bool DoZeroInitPadding(const ASTRecordLayout &Layout, unsigned FieldNo,
                         const FieldDecl &Field, bool AllowOverwrite,
                         CharUnits &SizeSoFar, bool &ZeroFieldSize);
  bool DoZeroInitPadding(const ASTRecordLayout &Layout, bool AllowOverwrite,
                         CharUnits SizeSoFar);
  llvm::Constant *Finalize(QualType Ty);
};

bool ConstStructBuilder::AppendField(
    const FieldDecl *Field, uint64_t FieldOffset, llvm::Constant *InitCst,
    bool AllowOverwrite) {
  const ASTContext &Context = CGM.getContext();

  CharUnits FieldOffsetInChars = Context.toCharUnitsFromBits(FieldOffset);

  return AppendBytes(FieldOffsetInChars, InitCst, AllowOverwrite);
}

bool ConstStructBuilder::AppendBytes(CharUnits FieldOffsetInChars,
                                     llvm::Constant *InitCst,
                                     bool AllowOverwrite) {
  return Builder.add(InitCst, StartOffset + FieldOffsetInChars, AllowOverwrite);
}

bool ConstStructBuilder::AppendBitField(const FieldDecl *Field,
                                        uint64_t FieldOffset, llvm::Constant *C,
                                        bool AllowOverwrite) {

  llvm::ConstantInt *CI = dyn_cast<llvm::ConstantInt>(C);
  if (!CI) {
    // Constants for long _BitInt types are sometimes split into individual
    // bytes. Try to fold these back into an integer constant. If that doesn't
    // work out, then we are trying to initialize a bitfield with a non-trivial
    // constant, this must require run-time code.
    llvm::Type *LoadType =
        CGM.getTypes().convertTypeForLoadStore(Field->getType(), C->getType());
    llvm::Constant *FoldedConstant = llvm::ConstantFoldLoadFromConst(
        C, LoadType, llvm::APInt::getZero(32), CGM.getDataLayout());
    CI = dyn_cast_if_present<llvm::ConstantInt>(FoldedConstant);
    if (!CI)
      return false;
  }

  const CGRecordLayout &RL =
      CGM.getTypes().getCGRecordLayout(Field->getParent());
  const CGBitFieldInfo &Info = RL.getBitFieldInfo(Field);
  llvm::APInt FieldValue = CI->getValue();

  // Promote the size of FieldValue if necessary
  // FIXME: This should never occur, but currently it can because initializer
  // constants are cast to bool, and because clang is not enforcing bitfield
  // width limits.
  if (Info.Size > FieldValue.getBitWidth())
    FieldValue = FieldValue.zext(Info.Size);

  // Truncate the size of FieldValue to the bit field size.
  if (Info.Size < FieldValue.getBitWidth())
    FieldValue = FieldValue.trunc(Info.Size);

  return Builder.addBits(FieldValue,
                         CGM.getContext().toBits(StartOffset) + FieldOffset,
                         AllowOverwrite);
}

static bool EmitDesignatedInitUpdater(ConstantEmitter &Emitter,
                                      ConstantAggregateBuilder &Const,
                                      CharUnits Offset, QualType Type,
                                      const InitListExpr *Updater) {
  if (Type->isRecordType())
    return ConstStructBuilder::UpdateStruct(Emitter, Const, Offset, Updater);

  auto CAT = Emitter.CGM.getContext().getAsConstantArrayType(Type);
  if (!CAT)
    return false;
  QualType ElemType = CAT->getElementType();
  CharUnits ElemSize = Emitter.CGM.getContext().getTypeSizeInChars(ElemType);
  llvm::Type *ElemTy = Emitter.CGM.getTypes().ConvertTypeForMem(ElemType);

  llvm::Constant *FillC = nullptr;
  if (const Expr *Filler = Updater->getArrayFiller()) {
    if (!isa<NoInitExpr>(Filler)) {
      FillC = Emitter.tryEmitAbstractForMemory(Filler, ElemType);
      if (!FillC)
        return false;
    }
  }

  unsigned NumElementsToUpdate =
      FillC ? CAT->getZExtSize() : Updater->getNumInits();
  for (unsigned I = 0; I != NumElementsToUpdate; ++I, Offset += ElemSize) {
    const Expr *Init = nullptr;
    if (I < Updater->getNumInits())
      Init = Updater->getInit(I);

    if (!Init && FillC) {
      if (!Const.add(FillC, Offset, true))
        return false;
    } else if (!Init || isa<NoInitExpr>(Init)) {
      continue;
    } else if (const auto *ChildILE = dyn_cast<InitListExpr>(Init)) {
      if (!EmitDesignatedInitUpdater(Emitter, Const, Offset, ElemType,
                                     ChildILE))
        return false;
      // Attempt to reduce the array element to a single constant if necessary.
      Const.condense(Offset, ElemTy);
    } else {
      llvm::Constant *Val = Emitter.tryEmitPrivateForMemory(Init, ElemType);
      if (!Const.add(Val, Offset, true))
        return false;
    }
  }

  return true;
}

bool ConstStructBuilder::Build(const InitListExpr *ILE, bool AllowOverwrite) {
  auto *RD = ILE->getType()->castAsRecordDecl();
  const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);

  unsigned FieldNo = -1;
  unsigned ElementNo = 0;

  // Bail out if we have base classes. We could support these, but they only
  // arise in C++1z where we will have already constant folded most interesting
  // cases. FIXME: There are still a few more cases we can handle this way.
  if (auto *CXXRD = dyn_cast<CXXRecordDecl>(RD))
    if (CXXRD->getNumBases())
      return false;

  const bool ZeroInitPadding = CGM.shouldZeroInitPadding();
  bool ZeroFieldSize = false;
  CharUnits SizeSoFar = CharUnits::Zero();

  for (FieldDecl *Field : RD->fields()) {
    ++FieldNo;

    // If this is a union, skip all the fields that aren't being initialized.
    if (RD->isUnion() &&
        !declaresSameEntity(ILE->getInitializedFieldInUnion(), Field))
      continue;

    // Don't emit anonymous bitfields.
    if (Field->isUnnamedBitField())
      continue;

    // Get the initializer.  A struct can include fields without initializers,
    // we just use explicit null values for them.
    const Expr *Init = nullptr;
    if (ElementNo < ILE->getNumInits())
      Init = ILE->getInit(ElementNo++);
    if (isa_and_nonnull<NoInitExpr>(Init)) {
      if (ZeroInitPadding &&
          !DoZeroInitPadding(Layout, FieldNo, *Field, AllowOverwrite, SizeSoFar,
                             ZeroFieldSize))
        return false;
      continue;
    }

    // Zero-sized fields are not emitted, but their initializers may still
    // prevent emission of this struct as a constant.
    if (isEmptyFieldForLayout(CGM.getContext(), Field)) {
      if (Init && Init->HasSideEffects(CGM.getContext()))
        return false;
      continue;
    }

    if (ZeroInitPadding &&
        !DoZeroInitPadding(Layout, FieldNo, *Field, AllowOverwrite, SizeSoFar,
                           ZeroFieldSize))
      return false;

    // When emitting a DesignatedInitUpdateExpr, a nested InitListExpr
    // represents additional overwriting of our current constant value, and not
    // a new constant to emit independently.
    if (AllowOverwrite &&
        (Field->getType()->isArrayType() || Field->getType()->isRecordType())) {
      if (auto *SubILE = dyn_cast<InitListExpr>(Init)) {
        CharUnits Offset = CGM.getContext().toCharUnitsFromBits(
            Layout.getFieldOffset(FieldNo));
        if (!EmitDesignatedInitUpdater(Emitter, Builder, StartOffset + Offset,
                                       Field->getType(), SubILE))
          return false;
        // If we split apart the field's value, try to collapse it down to a
        // single value now.
        Builder.condense(StartOffset + Offset,
                         CGM.getTypes().ConvertTypeForMem(Field->getType()));
        continue;
      }
    }

    llvm::Constant *EltInit =
        Init ? Emitter.tryEmitPrivateForMemory(Init, Field->getType())
             : Emitter.emitNullForMemory(Field->getType());
    if (!EltInit)
      return false;

    if (ZeroInitPadding && ZeroFieldSize)
      SizeSoFar += CharUnits::fromQuantity(
          CGM.getDataLayout().getTypeAllocSize(EltInit->getType()));

    if (!Field->isBitField()) {
      // Handle non-bitfield members.
      if (!AppendField(Field, Layout.getFieldOffset(FieldNo), EltInit,
                       AllowOverwrite))
        return false;
      // After emitting a non-empty field with [[no_unique_address]], we may
      // need to overwrite its tail padding.
      if (Field->hasAttr<NoUniqueAddressAttr>())
        AllowOverwrite = true;
    } else {
      // Otherwise we have a bitfield.
      if (!AppendBitField(Field, Layout.getFieldOffset(FieldNo), EltInit,
                          AllowOverwrite))
        return false;
    }
  }

  if (ZeroInitPadding && !DoZeroInitPadding(Layout, AllowOverwrite, SizeSoFar))
    return false;

  return true;
}

namespace {
struct BaseInfo {
  BaseInfo(const CXXRecordDecl *Decl, CharUnits Offset, unsigned Index)
    : Decl(Decl), Offset(Offset), Index(Index) {
  }

  const CXXRecordDecl *Decl;
  CharUnits Offset;
  unsigned Index;

  bool operator<(const BaseInfo &O) const { return Offset < O.Offset; }
};
}

bool ConstStructBuilder::Build(const APValue &Val, const RecordDecl *RD,
                               bool IsPrimaryBase,
                               const CXXRecordDecl *VTableClass,
                               CharUnits Offset) {
  const ASTRecordLayout &Layout = CGM.getContext().getASTRecordLayout(RD);

  if (const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD)) {
    // Add a vtable pointer, if we need one and it hasn't already been added.
    if (Layout.hasOwnVFPtr()) {
      llvm::Constant *VTableAddressPoint =
          CGM.getCXXABI().getVTableAddressPoint(BaseSubobject(CD, Offset),
                                                VTableClass);
      if (auto Authentication = CGM.getVTablePointerAuthentication(CD)) {
        VTableAddressPoint = Emitter.tryEmitConstantSignedPointer(
            VTableAddressPoint, *Authentication);
        if (!VTableAddressPoint)
          return false;
      }
      if (!AppendBytes(Offset, VTableAddressPoint))
        return false;
    }

    // Accumulate and sort bases, in order to visit them in address order, which
    // may not be the same as declaration order.
    SmallVector<BaseInfo, 8> Bases;
    Bases.reserve(CD->getNumBases());
    unsigned BaseNo = 0;
    for (CXXRecordDecl::base_class_const_iterator Base = CD->bases_begin(),
         BaseEnd = CD->bases_end(); Base != BaseEnd; ++Base, ++BaseNo) {
      assert(!Base->isVirtual() && "should not have virtual bases here");
      const CXXRecordDecl *BD = Base->getType()->getAsCXXRecordDecl();
      CharUnits BaseOffset = Layout.getBaseClassOffset(BD);
      Bases.push_back(BaseInfo(BD, BaseOffset, BaseNo));
    }
    llvm::stable_sort(Bases);

    for (const BaseInfo &Base : Bases) {
      bool IsPrimaryBase = Layout.getPrimaryBase() == Base.Decl;
      if (!Build(Val.getStructBase(Base.Index), Base.Decl, IsPrimaryBase,
                 VTableClass, Offset + Base.Offset))
        return false;
    }
  }

  unsigned FieldNo = 0;
  uint64_t OffsetBits = CGM.getContext().toBits(Offset);
  const bool ZeroInitPadding = CGM.shouldZeroInitPadding();
  bool ZeroFieldSize = false;
  CharUnits SizeSoFar = CharUnits::Zero();

  bool AllowOverwrite = false;
  for (RecordDecl::field_iterator Field = RD->field_begin(),
       FieldEnd = RD->field_end(); Field != FieldEnd; ++Field, ++FieldNo) {
    // If this is a union, skip all the fields that aren't being initialized.
    if (RD->isUnion() && !declaresSameEntity(Val.getUnionField(), *Field))
      continue;

    // Don't emit anonymous bitfields or zero-sized fields.
    if (Field->isUnnamedBitField() ||
        isEmptyFieldForLayout(CGM.getContext(), *Field))
      continue;

    // Emit the value of the initializer.
    const APValue &FieldValue =
      RD->isUnion() ? Val.getUnionValue() : Val.getStructField(FieldNo);
    llvm::Constant *EltInit =
      Emitter.tryEmitPrivateForMemory(FieldValue, Field->getType());
    if (!EltInit)
      return false;

    if (CGM.getContext().isPFPField(*Field)) {
      llvm::ConstantInt *Disc;
      llvm::Constant *AddrDisc;
      if (CGM.getContext().arePFPFieldsTriviallyCopyable(RD)) {
        uint64_t FieldSignature =
            llvm::getPointerAuthStableSipHash(CGM.getPFPFieldName(*Field));
        Disc = llvm::ConstantInt::get(CGM.Int64Ty, FieldSignature);
        AddrDisc = llvm::ConstantPointerNull::get(CGM.VoidPtrTy);
      } else if (Emitter.isAbstract()) {
        // isAbstract means that we don't know the global's address. Since we
        // can only form a pointer without knowing the address if the fields are
        // trivially copyable, we need to return false otherwise.
        return false;
      } else {
        Disc = llvm::ConstantInt::get(CGM.Int64Ty,
                                      -(Layout.getFieldOffset(FieldNo) / 8));
        AddrDisc = Emitter.getCurrentAddrPrivate();
      }
      EltInit = llvm::ConstantPtrAuth::get(
          EltInit, llvm::ConstantInt::get(CGM.Int32Ty, 2), Disc, AddrDisc,
          CGM.getPFPDeactivationSymbol(*Field));
      if (!CGM.getContext().arePFPFieldsTriviallyCopyable(RD))
        Emitter.registerCurrentAddrPrivate(EltInit,
                                           cast<llvm::GlobalValue>(AddrDisc));
    }

    if (ZeroInitPadding) {
      if (!DoZeroInitPadding(Layout, FieldNo, **Field, AllowOverwrite,
                             SizeSoFar, ZeroFieldSize))
        return false;
      if (ZeroFieldSize)
        SizeSoFar += CharUnits::fromQuantity(
            CGM.getDataLayout().getTypeAllocSize(EltInit->getType()));
    }

    if (!Field->isBitField()) {
      // Handle non-bitfield members.
      if (!AppendField(*Field, Layout.getFieldOffset(FieldNo) + OffsetBits,
                       EltInit, AllowOverwrite))
        return false;
      // After emitting a non-empty field with [[no_unique_address]], we may
      // need to overwrite its tail padding.
      if (Field->hasAttr<NoUniqueAddressAttr>())
        AllowOverwrite = true;
    } else {
      // Otherwise we have a bitfield.
      if (!AppendBitField(*Field, Layout.getFieldOffset(FieldNo) + OffsetBits,
                          EltInit, AllowOverwrite))
        return false;
    }
  }
  if (ZeroInitPadding && !DoZeroInitPadding(Layout, AllowOverwrite, SizeSoFar))
    return false;

  return true;
}

bool ConstStructBuilder::DoZeroInitPadding(
    const ASTRecordLayout &Layout, unsigned FieldNo, const FieldDecl &Field,
    bool AllowOverwrite, CharUnits &SizeSoFar, bool &ZeroFieldSize) {
  uint64_t StartBitOffset = Layout.getFieldOffset(FieldNo);
  CharUnits StartOffset = CGM.getContext().toCharUnitsFromBits(StartBitOffset);
  if (SizeSoFar < StartOffset)
    if (!AppendBytes(SizeSoFar, getPadding(CGM, StartOffset - SizeSoFar),
                     AllowOverwrite))
      return false;

  if (!Field.isBitField()) {
    CharUnits FieldSize = CGM.getContext().getTypeSizeInChars(Field.getType());
    SizeSoFar = StartOffset + FieldSize;
    ZeroFieldSize = FieldSize.isZero();
  } else {
    const CGRecordLayout &RL =
        CGM.getTypes().getCGRecordLayout(Field.getParent());
    const CGBitFieldInfo &Info = RL.getBitFieldInfo(&Field);
    uint64_t EndBitOffset = StartBitOffset + Info.Size;
    SizeSoFar = CGM.getContext().toCharUnitsFromBits(EndBitOffset);
    if (EndBitOffset % CGM.getContext().getCharWidth() != 0) {
      SizeSoFar++;
    }
    ZeroFieldSize = Info.Size == 0;
  }
  return true;
}

bool ConstStructBuilder::DoZeroInitPadding(const ASTRecordLayout &Layout,
                                           bool AllowOverwrite,
                                           CharUnits SizeSoFar) {
  CharUnits TotalSize = Layout.getSize();
  if (SizeSoFar < TotalSize)
    if (!AppendBytes(SizeSoFar, getPadding(CGM, TotalSize - SizeSoFar),
                     AllowOverwrite))
      return false;
  SizeSoFar = TotalSize;
  return true;
}

llvm::Constant *ConstStructBuilder::Finalize(QualType Type) {
  Type = Type.getNonReferenceType();
  auto *RD = Type->castAsRecordDecl();
  llvm::Type *ValTy = CGM.getTypes().ConvertType(Type);
  return Builder.build(ValTy, RD->hasFlexibleArrayMember());
}

llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter,
                                                const InitListExpr *ILE,
                                                QualType ValTy) {
  ConstantAggregateBuilder Const(Emitter.CGM);
  ConstStructBuilder Builder(Emitter, Const, CharUnits::Zero());

  if (!Builder.Build(ILE, /*AllowOverwrite*/false))
    return nullptr;

  return Builder.Finalize(ValTy);
}

llvm::Constant *ConstStructBuilder::BuildStruct(ConstantEmitter &Emitter,
                                                const APValue &Val,
                                                QualType ValTy) {
  ConstantAggregateBuilder Const(Emitter.CGM);
  ConstStructBuilder Builder(Emitter, Const, CharUnits::Zero());

  const auto *RD = ValTy->castAsRecordDecl();
  const CXXRecordDecl *CD = dyn_cast<CXXRecordDecl>(RD);
  if (!Builder.Build(Val, RD, false, CD, CharUnits::Zero()))
    return nullptr;

  return Builder.Finalize(ValTy);
}

bool ConstStructBuilder::UpdateStruct(ConstantEmitter &Emitter,
                                      ConstantAggregateBuilder &Const,
                                      CharUnits Offset,
                                      const InitListExpr *Updater) {
  return ConstStructBuilder(Emitter, Const, Offset)
      .Build(Updater, /*AllowOverwrite*/ true);
}

//===----------------------------------------------------------------------===//
//                             ConstExprEmitter
//===----------------------------------------------------------------------===//

static ConstantAddress
tryEmitGlobalCompoundLiteral(ConstantEmitter &emitter,
                             const CompoundLiteralExpr *E) {
  CodeGenModule &CGM = emitter.CGM;
  CharUnits Align = CGM.getContext().getTypeAlignInChars(E->getType());
  if (llvm::GlobalVariable *Addr =
          CGM.getAddrOfConstantCompoundLiteralIfEmitted(E))
    return ConstantAddress(Addr, Addr->getValueType(), Align);

  LangAS addressSpace = E->getType().getAddressSpace();
  llvm::Constant *C = emitter.tryEmitForInitializer(E->getInitializer(),
                                                    addressSpace, E->getType());
  if (!C) {
    assert(!E->isFileScope() &&
           "file-scope compound literal did not have constant initializer!");
    return ConstantAddress::invalid();
  }

  auto GV = new llvm::GlobalVariable(
      CGM.getModule(), C->getType(),
      E->getType().isConstantStorage(CGM.getContext(), true, false),
      llvm::GlobalValue::InternalLinkage, C, ".compoundliteral", nullptr,
      llvm::GlobalVariable::NotThreadLocal,
      CGM.getContext().getTargetAddressSpace(addressSpace));
  emitter.finalize(GV);
  GV->setAlignment(Align.getAsAlign());
  CGM.setAddrOfConstantCompoundLiteral(E, GV);
  return ConstantAddress(GV, GV->getValueType(), Align);
}

static llvm::Constant *
EmitArrayConstant(CodeGenModule &CGM, llvm::ArrayType *DesiredType,
                  llvm::Type *CommonElementType, uint64_t ArrayBound,
                  SmallVectorImpl<llvm::Constant *> &Elements,
                  llvm::Constant *Filler) {
  // Figure out how long the initial prefix of non-zero elements is.
  uint64_t NonzeroLength = ArrayBound;
  if (Elements.size() < NonzeroLength && Filler->isNullValue())
    NonzeroLength = Elements.size();
  if (NonzeroLength == Elements.size()) {
    while (NonzeroLength > 0 && Elements[NonzeroLength - 1]->isNullValue())
      --NonzeroLength;
  }

  if (NonzeroLength == 0)
    return llvm::ConstantAggregateZero::get(DesiredType);

  // Add a zeroinitializer array filler if we have lots of trailing zeroes.
  uint64_t TrailingZeroes = ArrayBound - NonzeroLength;
  if (TrailingZeroes >= 8) {
    assert(Elements.size() >= NonzeroLength &&
           "missing initializer for non-zero element");

    // If all the elements had the same type up to the trailing zeroes, emit a
    // struct of two arrays (the nonzero data and the zeroinitializer).
    if (CommonElementType && NonzeroLength >= 8) {
      llvm::Constant *Initial = llvm::ConstantArray::get(
          llvm::ArrayType::get(CommonElementType, NonzeroLength),
          ArrayRef(Elements).take_front(NonzeroLength));
      Elements.resize(2);
      Elements[0] = Initial;
    } else {
      Elements.resize(NonzeroLength + 1);
    }

    auto *FillerType =
        CommonElementType ? CommonElementType : DesiredType->getElementType();
    FillerType = llvm::ArrayType::get(FillerType, TrailingZeroes);
    Elements.back() = llvm::ConstantAggregateZero::get(FillerType);
    CommonElementType = nullptr;
  } else if (Elements.size() != ArrayBound) {
    // Otherwise pad to the right size with the filler if necessary.
    Elements.resize(ArrayBound, Filler);
    if (Filler->getType() != CommonElementType)
      CommonElementType = nullptr;
  }

  // If all elements have the same type, just emit an array constant.
  if (CommonElementType)
    return llvm::ConstantArray::get(
        llvm::ArrayType::get(CommonElementType, ArrayBound), Elements);

  // We have mixed types. Use a packed struct.
  llvm::SmallVector<llvm::Type *, 16> Types;
  Types.reserve(Elements.size());
  for (llvm::Constant *Elt : Elements)
    Types.push_back(Elt->getType());
  llvm::StructType *SType =
      llvm::StructType::get(CGM.getLLVMContext(), Types, true);
  return llvm::ConstantStruct::get(SType, Elements);
}

// This class only needs to handle arrays, structs and unions. Outside C++11
// mode, we don't currently constant fold those types.  All other types are
// handled by constant folding.
//
// Constant folding is currently missing support for a few features supported
// here: CK_ReinterpretMemberPointer, and DesignatedInitUpdateExpr.
class ConstExprEmitter
    : public ConstStmtVisitor<ConstExprEmitter, llvm::Constant *, QualType> {
  CodeGenModule &CGM;
  ConstantEmitter &Emitter;
  llvm::LLVMContext &VMContext;
public:
  ConstExprEmitter(ConstantEmitter &emitter)
    : CGM(emitter.CGM), Emitter(emitter), VMContext(CGM.getLLVMContext()) {
  }

  //===--------------------------------------------------------------------===//
  //                            Visitor Methods
  //===--------------------------------------------------------------------===//

  llvm::Constant *VisitStmt(const Stmt *S, QualType T) { return nullptr; }

  llvm::Constant *VisitConstantExpr(const ConstantExpr *CE, QualType T) {
    if (llvm::Constant *Result = Emitter.tryEmitConstantExpr(CE))
      return Result;
    return Visit(CE->getSubExpr(), T);
  }

  llvm::Constant *VisitParenExpr(const ParenExpr *PE, QualType T) {
    return Visit(PE->getSubExpr(), T);
  }

  llvm::Constant *
  VisitSubstNonTypeTemplateParmExpr(const SubstNonTypeTemplateParmExpr *PE,
                                    QualType T) {
    return Visit(PE->getReplacement(), T);
  }

  llvm::Constant *VisitGenericSelectionExpr(const GenericSelectionExpr *GE,
                                            QualType T) {
    return Visit(GE->getResultExpr(), T);
  }

  llvm::Constant *VisitChooseExpr(const ChooseExpr *CE, QualType T) {
    return Visit(CE->getChosenSubExpr(), T);
  }

  llvm::Constant *VisitCompoundLiteralExpr(const CompoundLiteralExpr *E,
                                           QualType T) {
    return Visit(E->getInitializer(), T);
  }

  llvm::Constant *ProduceIntToIntCast(const Expr *E, QualType DestType) {
    QualType FromType = E->getType();
    // See also HandleIntToIntCast in ExprConstant.cpp
    if (FromType->isIntegerType())
      if (llvm::Constant *C = Visit(E, FromType))
        if (auto *CI = dyn_cast<llvm::ConstantInt>(C)) {
          unsigned SrcWidth = CGM.getContext().getIntWidth(FromType);
          unsigned DstWidth = CGM.getContext().getIntWidth(DestType);
          if (DstWidth == SrcWidth)
            return CI;
          llvm::APInt A = FromType->isSignedIntegerType()
                              ? CI->getValue().sextOrTrunc(DstWidth)
                              : CI->getValue().zextOrTrunc(DstWidth);
          return llvm::ConstantInt::get(CGM.getLLVMContext(), A);
        }
    return nullptr;
  }

  llvm::Constant *VisitCastExpr(const CastExpr *E, QualType destType) {
    if (const auto *ECE = dyn_cast<ExplicitCastExpr>(E))
      CGM.EmitExplicitCastExprType(ECE, Emitter.CGF);
    const Expr *subExpr = E->getSubExpr();

    switch (E->getCastKind()) {
    case CK_ToUnion: {
      // GCC cast to union extension
      assert(E->getType()->isUnionType() &&
             "Destination type is not union type!");

      auto field = E->getTargetUnionField();

      auto C = Emitter.tryEmitPrivateForMemory(subExpr, field->getType());
      if (!C) return nullptr;

      auto destTy = ConvertType(destType);
      if (C->getType() == destTy) return C;

      // Build a struct with the union sub-element as the first member,
      // and padded to the appropriate size.
      SmallVector<llvm::Constant*, 2> Elts;
      SmallVector<llvm::Type*, 2> Types;
      Elts.push_back(C);
      Types.push_back(C->getType());
      unsigned CurSize = CGM.getDataLayout().getTypeAllocSize(C->getType());
      unsigned TotalSize = CGM.getDataLayout().getTypeAllocSize(destTy);

      assert(CurSize <= TotalSize && "Union size mismatch!");
      if (unsigned NumPadBytes = TotalSize - CurSize) {
        llvm::Constant *Padding =
            getPadding(CGM, CharUnits::fromQuantity(NumPadBytes));
        Elts.push_back(Padding);
        Types.push_back(Padding->getType());
      }

      llvm::StructType *STy = llvm::StructType::get(VMContext, Types, false);
      return llvm::ConstantStruct::get(STy, Elts);
    }

    case CK_AddressSpaceConversion: {
      llvm::Constant *C = Emitter.tryEmitPrivate(subExpr, subExpr->getType());
      if (!C)
        return nullptr;
      llvm::Type *destTy = ConvertType(E->getType());
      return CGM.performAddrSpaceCast(C, destTy);
    }

    case CK_LValueToRValue: {
      // We don't really support doing lvalue-to-rvalue conversions here; any
      // interesting conversions should be done in Evaluate().  But as a
      // special case, allow compound literals to support the gcc extension
      // allowing "struct x {int x;} x = (struct x) {};".
      if (const auto *E =
              dyn_cast<CompoundLiteralExpr>(subExpr->IgnoreParens()))
        return Visit(E->getInitializer(), destType);
      return nullptr;
    }

    case CK_AtomicToNonAtomic:
    case CK_NonAtomicToAtomic:
    case CK_NoOp:
    case CK_ConstructorConversion:
      return Visit(subExpr, destType);

    case CK_ArrayToPointerDecay:
      if (const auto *S = dyn_cast<StringLiteral>(subExpr))
        return CGM.GetAddrOfConstantStringFromLiteral(S).getPointer();
      return nullptr;
    case CK_NullToPointer:
      if (Visit(subExpr, destType))
        return CGM.EmitNullConstant(destType);
      return nullptr;

    case CK_IntToOCLSampler:
      llvm_unreachable("global sampler variables are not generated");

    case CK_IntegralCast:
      return ProduceIntToIntCast(subExpr, destType);

    case CK_Dependent: llvm_unreachable("saw dependent cast!");

    case CK_BuiltinFnToFnPtr:
      llvm_unreachable("builtin functions are handled elsewhere");

    case CK_ReinterpretMemberPointer:
    case CK_DerivedToBaseMemberPointer:
    case CK_BaseToDerivedMemberPointer: {
      auto C = Emitter.tryEmitPrivate(subExpr, subExpr->getType());
      if (!C) return nullptr;
      return CGM.getCXXABI().EmitMemberPointerConversion(E, C);
    }

    // These will never be supported.
    case CK_ObjCObjectLValueCast:
    case CK_ARCProduceObject:
    case CK_ARCConsumeObject:
    case CK_ARCReclaimReturnedObject:
    case CK_ARCExtendBlockObject:
    case CK_CopyAndAutoreleaseBlockObject:
      return nullptr;

    // These don't need to be handled here because Evaluate knows how to
    // evaluate them in the cases where they can be folded.
    case CK_BitCast:
    case CK_ToVoid:
    case CK_Dynamic:
    case CK_LValueBitCast:
    case CK_LValueToRValueBitCast:
    case CK_NullToMemberPointer:
    case CK_UserDefinedConversion:
    case CK_CPointerToObjCPointerCast:
    case CK_BlockPointerToObjCPointerCast:
    case CK_AnyPointerToBlockPointerCast:
    case CK_FunctionToPointerDecay:
    case CK_BaseToDerived:
    case CK_DerivedToBase:
    case CK_UncheckedDerivedToBase:
    case CK_MemberPointerToBoolean:
    case CK_VectorSplat:
    case CK_FloatingRealToComplex:
    case CK_FloatingComplexToReal:
    case CK_FloatingComplexToBoolean:
    case CK_FloatingComplexCast:
    case CK_FloatingComplexToIntegralComplex:
    case CK_IntegralRealToComplex:
    case CK_IntegralComplexToReal:
    case CK_IntegralComplexToBoolean:
    case CK_IntegralComplexCast:
    case CK_IntegralComplexToFloatingComplex:
    case CK_PointerToIntegral:
    case CK_PointerToBoolean:
    case CK_BooleanToSignedIntegral:
    case CK_IntegralToPointer:
    case CK_IntegralToBoolean:
    case CK_IntegralToFloating:
    case CK_FloatingToIntegral:
    case CK_FloatingToBoolean:
    case CK_FloatingCast:
    case CK_FloatingToFixedPoint:
    case CK_FixedPointToFloating:
    case CK_FixedPointCast:
    case CK_FixedPointToBoolean:
    case CK_FixedPointToIntegral:
    case CK_IntegralToFixedPoint:
    case CK_ZeroToOCLOpaqueType:
    case CK_MatrixCast:
    case CK_HLSLVectorTruncation:
    case CK_HLSLMatrixTruncation:
    case CK_HLSLArrayRValue:
    case CK_HLSLElementwiseCast:
    case CK_HLSLAggregateSplatCast:
      return nullptr;
    }
    llvm_unreachable("Invalid CastKind");
  }

  llvm::Constant *VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *DIE,
                                          QualType T) {
    // No need for a DefaultInitExprScope: we don't handle 'this' in a
    // constant expression.
    return Visit(DIE->getExpr(), T);
  }

  llvm::Constant *VisitExprWithCleanups(const ExprWithCleanups *E, QualType T) {
    return Visit(E->getSubExpr(), T);
  }

  llvm::Constant *VisitIntegerLiteral(const IntegerLiteral *I, QualType T) {
    return llvm::ConstantInt::get(CGM.getLLVMContext(), I->getValue());
  }

  static APValue withDestType(ASTContext &Ctx, const Expr *E, QualType SrcType,
                              QualType DestType, const llvm::APSInt &Value) {
    if (!Ctx.hasSameType(SrcType, DestType)) {
      if (DestType->isFloatingType()) {
        llvm::APFloat Result =
            llvm::APFloat(Ctx.getFloatTypeSemantics(DestType), 1);
        llvm::RoundingMode RM =
            E->getFPFeaturesInEffect(Ctx.getLangOpts()).getRoundingMode();
        if (RM == llvm::RoundingMode::Dynamic)
          RM = llvm::RoundingMode::NearestTiesToEven;
        Result.convertFromAPInt(Value, Value.isSigned(), RM);
        return APValue(Result);
      }
    }
    return APValue(Value);
  }

  llvm::Constant *EmitArrayInitialization(const InitListExpr *ILE, QualType T) {
    auto *CAT = CGM.getContext().getAsConstantArrayType(ILE->getType());
    assert(CAT && "can't emit array init for non-constant-bound array");
    uint64_t NumInitElements = ILE->getNumInits();
    const uint64_t NumElements = CAT->getZExtSize();
    for (const auto *Init : ILE->inits()) {
      if (const auto *Embed =
              dyn_cast<EmbedExpr>(Init->IgnoreParenImpCasts())) {
        NumInitElements += Embed->getDataElementCount() - 1;
        if (NumInitElements > NumElements) {
          NumInitElements = NumElements;
          break;
        }
      }
    }

    // Initialising an array requires us to automatically
    // initialise any elements that have not been initialised explicitly
    uint64_t NumInitableElts = std::min<uint64_t>(NumInitElements, NumElements);

    QualType EltType = CAT->getElementType();

    // Initialize remaining array elements.
    llvm::Constant *fillC = nullptr;
    if (const Expr *filler = ILE->getArrayFiller()) {
      fillC = Emitter.tryEmitAbstractForMemory(filler, EltType);
      if (!fillC)
        return nullptr;
    }

    // Copy initializer elements.
    SmallVector<llvm::Constant *, 16> Elts;
    if (fillC && fillC->isNullValue())
      Elts.reserve(NumInitableElts + 1);
    else
      Elts.reserve(NumElements);

    llvm::Type *CommonElementType = nullptr;
    auto Emit = [&](const Expr *Init, unsigned ArrayIndex) {
      llvm::Constant *C = nullptr;
      C = Emitter.tryEmitPrivateForMemory(Init, EltType);
      if (!C)
        return false;
      if (ArrayIndex == 0)
        CommonElementType = C->getType();
      else if (C->getType() != CommonElementType)
        CommonElementType = nullptr;
      Elts.push_back(C);
      return true;
    };

    unsigned ArrayIndex = 0;
    QualType DestTy = CAT->getElementType();
    for (unsigned i = 0; i < ILE->getNumInits(); ++i) {
      const Expr *Init = ILE->getInit(i);
      if (auto *EmbedS = dyn_cast<EmbedExpr>(Init->IgnoreParenImpCasts())) {
        StringLiteral *SL = EmbedS->getDataStringLiteral();
        llvm::APSInt Value(CGM.getContext().getTypeSize(DestTy),
                           DestTy->isUnsignedIntegerType());
        llvm::Constant *C;
        for (unsigned I = EmbedS->getStartingElementPos(),
                      N = EmbedS->getDataElementCount();
             I != EmbedS->getStartingElementPos() + N; ++I) {
          Value = SL->getCodeUnit(I);
          if (DestTy->isIntegerType()) {
            C = llvm::ConstantInt::get(CGM.getLLVMContext(), Value);
          } else {
            C = Emitter.tryEmitPrivateForMemory(
                withDestType(CGM.getContext(), Init, EmbedS->getType(), DestTy,
                             Value),
                EltType);
          }
          if (!C)
            return nullptr;
          Elts.push_back(C);
          ArrayIndex++;
        }
        if ((ArrayIndex - EmbedS->getDataElementCount()) == 0)
          CommonElementType = C->getType();
        else if (C->getType() != CommonElementType)
          CommonElementType = nullptr;
      } else {
        if (!Emit(Init, ArrayIndex))
          return nullptr;
        ArrayIndex++;
      }
    }

    llvm::ArrayType *Desired =
        cast<llvm::ArrayType>(CGM.getTypes().ConvertType(ILE->getType()));
    return EmitArrayConstant(CGM, Desired, CommonElementType, NumElements, Elts,
                             fillC);
  }

  llvm::Constant *EmitRecordInitialization(const InitListExpr *ILE,
                                           QualType T) {
    return ConstStructBuilder::BuildStruct(Emitter, ILE, T);
  }

  llvm::Constant *VisitImplicitValueInitExpr(const ImplicitValueInitExpr *E,
                                             QualType T) {
    return CGM.EmitNullConstant(T);
  }

  llvm::Constant *VisitInitListExpr(const InitListExpr *ILE, QualType T) {
    if (ILE->isTransparent())
      return Visit(ILE->getInit(0), T);

    if (ILE->getType()->isArrayType())
      return EmitArrayInitialization(ILE, T);

    if (ILE->getType()->isRecordType())
      return EmitRecordInitialization(ILE, T);

    return nullptr;
  }

  llvm::Constant *
  VisitDesignatedInitUpdateExpr(const DesignatedInitUpdateExpr *E,
                                QualType destType) {
    auto C = Visit(E->getBase(), destType);
    if (!C)
      return nullptr;

    ConstantAggregateBuilder Const(CGM);
    Const.add(C, CharUnits::Zero(), false);

    if (!EmitDesignatedInitUpdater(Emitter, Const, CharUnits::Zero(), destType,
                                   E->getUpdater()))
      return nullptr;

    llvm::Type *ValTy = CGM.getTypes().ConvertType(destType);
    bool HasFlexibleArray = false;
    if (const auto *RD = destType->getAsRecordDecl())
      HasFlexibleArray = RD->hasFlexibleArrayMember();
    return Const.build(ValTy, HasFlexibleArray);
  }

  llvm::Constant *VisitCXXConstructExpr(const CXXConstructExpr *E,
                                        QualType Ty) {
    if (!E->getConstructor()->isTrivial())
      return nullptr;

    // Only default and copy/move constructors can be trivial.
    if (E->getNumArgs()) {
      assert(E->getNumArgs() == 1 && "trivial ctor with > 1 argument");
      assert(E->getConstructor()->isCopyOrMoveConstructor() &&
             "trivial ctor has argument but isn't a copy/move ctor");

      const Expr *Arg = E->getArg(0);
      assert(CGM.getContext().hasSameUnqualifiedType(Ty, Arg->getType()) &&
             "argument to copy ctor is of wrong type");

      // Look through the temporary; it's just converting the value to an
      // lvalue to pass it to the constructor.
      if (const auto *MTE = dyn_cast<MaterializeTemporaryExpr>(Arg))
        return Visit(MTE->getSubExpr(), Ty);
      // Don't try to support arbitrary lvalue-to-rvalue conversions for now.
      return nullptr;
    }

    return CGM.EmitNullConstant(Ty);
  }

  llvm::Constant *VisitStringLiteral(const StringLiteral *E, QualType T) {
    // This is a string literal initializing an array in an initializer.
    return CGM.GetConstantArrayFromStringLiteral(E);
  }

  llvm::Constant *VisitObjCEncodeExpr(const ObjCEncodeExpr *E, QualType T) {
    // This must be an @encode initializing an array in a static initializer.
    // Don't emit it as the address of the string, emit the string data itself
    // as an inline array.
    std::string Str;
    CGM.getContext().getObjCEncodingForType(E->getEncodedType(), Str);
    const ConstantArrayType *CAT = CGM.getContext().getAsConstantArrayType(T);
    assert(CAT && "String data not of constant array type!");

    // Resize the string to the right size, adding zeros at the end, or
    // truncating as needed.
    Str.resize(CAT->getZExtSize(), '\0');
    return llvm::ConstantDataArray::getString(VMContext, Str, false);
  }

  llvm::Constant *VisitUnaryExtension(const UnaryOperator *E, QualType T) {
    return Visit(E->getSubExpr(), T);
  }

  llvm::Constant *VisitUnaryMinus(const UnaryOperator *U, QualType T) {
    if (llvm::Constant *C = Visit(U->getSubExpr(), T))
      if (auto *CI = dyn_cast<llvm::ConstantInt>(C))
        return llvm::ConstantInt::get(CGM.getLLVMContext(), -CI->getValue());
    return nullptr;
  }

  llvm::Constant *VisitPackIndexingExpr(const PackIndexingExpr *E, QualType T) {
    return Visit(E->getSelectedExpr(), T);
  }

  // Utility methods
  llvm::Type *ConvertType(QualType T) {
    return CGM.getTypes().ConvertType(T);
  }
};

}  // end anonymous namespace.

llvm::Constant *ConstantEmitter::validateAndPopAbstract(llvm::Constant *C,
                                                        AbstractState saved) {
  Abstract = saved.OldValue;

  assert(saved.OldPlaceholdersSize == PlaceholderAddresses.size() &&
         "created a placeholder while doing an abstract emission?");

  // No validation necessary for now.
  // No cleanup to do for now.
  return C;
}

llvm::Constant *
ConstantEmitter::tryEmitAbstractForInitializer(const VarDecl &D) {
  auto state = pushAbstract();
  auto C = tryEmitPrivateForVarInit(D);
  return validateAndPopAbstract(C, state);
}

llvm::Constant *
ConstantEmitter::tryEmitAbstract(const Expr *E, QualType destType) {
  auto state = pushAbstract();
  auto C = tryEmitPrivate(E, destType);
  return validateAndPopAbstract(C, state);
}

llvm::Constant *
ConstantEmitter::tryEmitAbstract(const APValue &value, QualType destType) {
  auto state = pushAbstract();
  auto C = tryEmitPrivate(value, destType);
  return validateAndPopAbstract(C, state);
}

llvm::Constant *ConstantEmitter::tryEmitConstantExpr(const ConstantExpr *CE) {
  if (!CE->hasAPValueResult())
    return nullptr;

  QualType RetType = CE->getType();
  if (CE->isGLValue())
    RetType = CGM.getContext().getLValueReferenceType(RetType);

  return tryEmitAbstract(CE->getAPValueResult(), RetType);
}

llvm::Constant *
ConstantEmitter::emitAbstract(const Expr *E, QualType destType) {
  auto state = pushAbstract();
  auto C = tryEmitPrivate(E, destType);
  C = validateAndPopAbstract(C, state);
  if (!C) {
    CGM.Error(E->getExprLoc(),
              "internal error: could not emit constant value \"abstractly\"");
    C = CGM.EmitNullConstant(destType);
  }
  return C;
}

llvm::Constant *
ConstantEmitter::emitAbstract(SourceLocation loc, const APValue &value,
                              QualType destType,
                              bool EnablePtrAuthFunctionTypeDiscrimination) {
  auto state = pushAbstract();
  auto C =
      tryEmitPrivate(value, destType, EnablePtrAuthFunctionTypeDiscrimination);
  C = validateAndPopAbstract(C, state);
  if (!C) {
    CGM.Error(loc,
              "internal error: could not emit constant value \"abstractly\"");
    C = CGM.EmitNullConstant(destType);
  }
  return C;
}

llvm::Constant *ConstantEmitter::tryEmitForInitializer(const VarDecl &D) {
  initializeNonAbstract(D.getType().getAddressSpace());
  llvm::Constant *Init = tryEmitPrivateForVarInit(D);

  // If a placeholder address was needed for a TLS variable, implying that the
  // initializer's value depends on its address, then the object may not be
  // initialized in .tdata because the initializer will be memcpy'd to the
  // thread's TLS. Instead the initialization must be done in code.
  if (!PlaceholderAddresses.empty() && D.getTLSKind() != VarDecl::TLS_None) {
    for (auto [_, GV] : PlaceholderAddresses)
      GV->eraseFromParent();
    PlaceholderAddresses.clear();
    Init = nullptr;
  }

  return markIfFailed(Init);
}

llvm::Constant *ConstantEmitter::tryEmitForInitializer(const Expr *E,
                                                       LangAS destAddrSpace,
                                                       QualType destType) {
  initializeNonAbstract(destAddrSpace);
  return markIfFailed(tryEmitPrivateForMemory(E, destType));
}

llvm::Constant *ConstantEmitter::emitForInitializer(const APValue &value,
                                                    LangAS destAddrSpace,
                                                    QualType destType) {
  initializeNonAbstract(destAddrSpace);
  auto C = tryEmitPrivateForMemory(value, destType);
  assert(C && "couldn't emit constant value non-abstractly?");
  return C;
}

llvm::GlobalValue *ConstantEmitter::getCurrentAddrPrivate() {
  assert(!Abstract && "cannot get current address for abstract constant");



  // Make an obviously ill-formed global that should blow up compilation
  // if it survives.
  auto global = new llvm::GlobalVariable(CGM.getModule(), CGM.Int8Ty, true,
                                         llvm::GlobalValue::PrivateLinkage,
                                         /*init*/ nullptr,
                                         /*name*/ "",
                                         /*before*/ nullptr,
                                         llvm::GlobalVariable::NotThreadLocal,
                                         CGM.getContext().getTargetAddressSpace(DestAddressSpace));

  PlaceholderAddresses.push_back(std::make_pair(nullptr, global));

  return global;
}

void ConstantEmitter::registerCurrentAddrPrivate(llvm::Constant *signal,
                                           llvm::GlobalValue *placeholder) {
  assert(!PlaceholderAddresses.empty());
  assert(PlaceholderAddresses.back().first == nullptr);
  assert(PlaceholderAddresses.back().second == placeholder);
  PlaceholderAddresses.back().first = signal;
}

namespace {
  struct ReplacePlaceholders {
    CodeGenModule &CGM;

    /// The base address of the global.
    llvm::Constant *Base;
    llvm::Type *BaseValueTy = nullptr;

    /// The placeholder addresses that were registered during emission.
    llvm::DenseMap<llvm::Constant*, llvm::GlobalVariable*> PlaceholderAddresses;

    /// The locations of the placeholder signals.
    llvm::DenseMap<llvm::GlobalVariable*, llvm::Constant*> Locations;

    /// The current index stack.  We use a simple unsigned stack because
    /// we assume that placeholders will be relatively sparse in the
    /// initializer, but we cache the index values we find just in case.
    llvm::SmallVector<unsigned, 8> Indices;
    llvm::SmallVector<llvm::Constant*, 8> IndexValues;

    ReplacePlaceholders(CodeGenModule &CGM, llvm::Constant *base,
                        ArrayRef<std::pair<llvm::Constant*,
                                           llvm::GlobalVariable*>> addresses)
        : CGM(CGM), Base(base),
          PlaceholderAddresses(addresses.begin(), addresses.end()) {
    }

    void replaceInInitializer(llvm::Constant *init) {
      // Remember the type of the top-most initializer.
      BaseValueTy = init->getType();

      // Initialize the stack.
      Indices.push_back(0);
      IndexValues.push_back(nullptr);

      // Recurse into the initializer.
      findLocations(init);

      // Check invariants.
      assert(IndexValues.size() == Indices.size() && "mismatch");
      assert(Indices.size() == 1 && "didn't pop all indices");

      // Do the replacement; this basically invalidates 'init'.
      assert(Locations.size() == PlaceholderAddresses.size() &&
             "missed a placeholder?");

      // We're iterating over a hashtable, so this would be a source of
      // non-determinism in compiler output *except* that we're just
      // messing around with llvm::Constant structures, which never itself
      // does anything that should be visible in compiler output.
      for (auto &entry : Locations) {
        assert(entry.first->getName() == "" && "not a placeholder!");
        entry.first->replaceAllUsesWith(entry.second);
        entry.first->eraseFromParent();
      }
    }

  private:
    void findLocations(llvm::Constant *init) {
      // Recurse into aggregates.
      if (auto agg = dyn_cast<llvm::ConstantAggregate>(init)) {
        for (unsigned i = 0, e = agg->getNumOperands(); i != e; ++i) {
          Indices.push_back(i);
          IndexValues.push_back(nullptr);

          findLocations(agg->getOperand(i));

          IndexValues.pop_back();
          Indices.pop_back();
        }
        return;
      }

      // Otherwise, check for registered constants.
      while (true) {
        auto it = PlaceholderAddresses.find(init);
        if (it != PlaceholderAddresses.end()) {
          setLocation(it->second);
          break;
        }

        // Look through bitcasts or other expressions.
        if (auto expr = dyn_cast<llvm::ConstantExpr>(init)) {
          init = expr->getOperand(0);
        } else {
          break;
        }
      }
    }

    void setLocation(llvm::GlobalVariable *placeholder) {
      assert(!Locations.contains(placeholder) &&
             "already found location for placeholder!");

      // Lazily fill in IndexValues with the values from Indices.
      // We do this in reverse because we should always have a strict
      // prefix of indices from the start.
      assert(Indices.size() == IndexValues.size());
      for (size_t i = Indices.size() - 1; i != size_t(-1); --i) {
        if (IndexValues[i]) {
#ifndef NDEBUG
          for (size_t j = 0; j != i + 1; ++j) {
            assert(IndexValues[j] &&
                   isa<llvm::ConstantInt>(IndexValues[j]) &&
                   cast<llvm::ConstantInt>(IndexValues[j])->getZExtValue()
                     == Indices[j]);
          }
#endif
          break;
        }

        IndexValues[i] = llvm::ConstantInt::get(CGM.Int32Ty, Indices[i]);
      }

      llvm::Constant *location = llvm::ConstantExpr::getInBoundsGetElementPtr(
          BaseValueTy, Base, IndexValues);

      Locations.insert({placeholder, location});
    }
  };
}

void ConstantEmitter::finalize(llvm::GlobalVariable *global) {
  assert(InitializedNonAbstract &&
         "finalizing emitter that was used for abstract emission?");
  assert(!Finalized && "finalizing emitter multiple times");
  assert(global->getInitializer());

  // Note that we might also be Failed.
  Finalized = true;

  if (!PlaceholderAddresses.empty()) {
    ReplacePlaceholders(CGM, global, PlaceholderAddresses)
      .replaceInInitializer(global->getInitializer());
    PlaceholderAddresses.clear(); // satisfy
  }
}

ConstantEmitter::~ConstantEmitter() {
  assert((!InitializedNonAbstract || Finalized || Failed) &&
         "not finalized after being initialized for non-abstract emission");
  assert(PlaceholderAddresses.empty() && "unhandled placeholders");
}

static QualType getNonMemoryType(CodeGenModule &CGM, QualType type) {
  if (auto AT = type->getAs<AtomicType>()) {
    return CGM.getContext().getQualifiedType(AT->getValueType(),
                                             type.getQualifiers());
  }
  return type;
}

llvm::Constant *ConstantEmitter::tryEmitPrivateForVarInit(const VarDecl &D) {
  // Make a quick check if variable can be default NULL initialized
  // and avoid going through rest of code which may do, for c++11,
  // initialization of memory to all NULLs.
  if (!D.hasLocalStorage()) {
    QualType Ty = CGM.getContext().getBaseElementType(D.getType());
    if (Ty->isRecordType())
      if (const CXXConstructExpr *E =
          dyn_cast_or_null<CXXConstructExpr>(D.getInit())) {
        const CXXConstructorDecl *CD = E->getConstructor();
        if (CD->isTrivial() && CD->isDefaultConstructor())
          return CGM.EmitNullConstant(D.getType());
      }
  }
  InConstantContext = D.hasConstantInitialization();

  QualType destType = D.getType();
  const Expr *E = D.getInit();
  assert(E && "No initializer to emit");

  if (!destType->isReferenceType()) {
    QualType nonMemoryDestType = getNonMemoryType(CGM, destType);
    if (llvm::Constant *C = ConstExprEmitter(*this).Visit(E, nonMemoryDestType))
      return emitForMemory(C, destType);
  }

  // Try to emit the initializer.  Note that this can allow some things that
  // are not allowed by tryEmitPrivateForMemory alone.
  if (APValue *value = D.evaluateValue()) {
    assert(!value->allowConstexprUnknown() &&
           "Constexpr unknown values are not allowed in CodeGen");
    return tryEmitPrivateForMemory(*value, destType);
  }

  return nullptr;
}

llvm::Constant *
ConstantEmitter::tryEmitAbstractForMemory(const Expr *E, QualType destType) {
  auto nonMemoryDestType = getNonMemoryType(CGM, destType);
  auto C = tryEmitAbstract(E, nonMemoryDestType);
  return (C ? emitForMemory(C, destType) : nullptr);
}

llvm::Constant *
ConstantEmitter::tryEmitAbstractForMemory(const APValue &value,
                                          QualType destType) {
  auto nonMemoryDestType = getNonMemoryType(CGM, destType);
  auto C = tryEmitAbstract(value, nonMemoryDestType);
  return (C ? emitForMemory(C, destType) : nullptr);
}

llvm::Constant *ConstantEmitter::tryEmitPrivateForMemory(const Expr *E,
                                                         QualType destType) {
  auto nonMemoryDestType = getNonMemoryType(CGM, destType);
  llvm::Constant *C = tryEmitPrivate(E, nonMemoryDestType);
  return (C ? emitForMemory(C, destType) : nullptr);
}

llvm::Constant *ConstantEmitter::tryEmitPrivateForMemory(const APValue &value,
                                                         QualType destType) {
  auto nonMemoryDestType = getNonMemoryType(CGM, destType);
  auto C = tryEmitPrivate(value, nonMemoryDestType);
  return (C ? emitForMemory(C, destType) : nullptr);
}

/// Try to emit a constant signed pointer, given a raw pointer and the
/// destination ptrauth qualifier.
///
/// This can fail if the qualifier needs address discrimination and the
/// emitter is in an abstract mode.
llvm::Constant *
ConstantEmitter::tryEmitConstantSignedPointer(llvm::Constant *UnsignedPointer,
                                              PointerAuthQualifier Schema) {
  assert(Schema && "applying trivial ptrauth schema");

  if (Schema.hasKeyNone())
    return UnsignedPointer;

  unsigned Key = Schema.getKey();

  // Create an address placeholder if we're using address discrimination.
  llvm::GlobalValue *StorageAddress = nullptr;
  if (Schema.isAddressDiscriminated()) {
    // We can't do this if the emitter is in an abstract state.
    if (isAbstract())
      return nullptr;

    StorageAddress = getCurrentAddrPrivate();
  }

  llvm::ConstantInt *Discriminator =
      llvm::ConstantInt::get(CGM.IntPtrTy, Schema.getExtraDiscriminator());

  llvm::Constant *SignedPointer = CGM.getConstantSignedPointer(
      UnsignedPointer, Key, StorageAddress, Discriminator);

  if (Schema.isAddressDiscriminated())
    registerCurrentAddrPrivate(SignedPointer, StorageAddress);

  return SignedPointer;
}

llvm::Constant *ConstantEmitter::emitForMemory(CodeGenModule &CGM,
                                               llvm::Constant *C,
                                               QualType destType) {
  // For an _Atomic-qualified constant, we may need to add tail padding.
  if (auto AT = destType->getAs<AtomicType>()) {
    QualType destValueType = AT->getValueType();
    C = emitForMemory(CGM, C, destValueType);

    uint64_t innerSize = CGM.getContext().getTypeSize(destValueType);
    uint64_t outerSize = CGM.getContext().getTypeSize(destType);
    if (innerSize == outerSize)
      return C;

    assert(innerSize < outerSize && "emitted over-large constant for atomic");
    llvm::Constant *elts[] = {
      C,
      llvm::ConstantAggregateZero::get(
          llvm::ArrayType::get(CGM.Int8Ty, (outerSize - innerSize) / 8))
    };
    return llvm::ConstantStruct::getAnon(elts);
  }

  // Zero-extend bool.
  // In HLSL bool vectors are stored in memory as a vector of i32
  if ((C->getType()->isIntegerTy(1) && !destType->isBitIntType()) ||
      (destType->isExtVectorBoolType() &&
       !destType->isPackedVectorBoolType(CGM.getContext()))) {
    llvm::Type *boolTy = CGM.getTypes().ConvertTypeForMem(destType);
    llvm::Constant *Res = llvm::ConstantFoldCastOperand(
        llvm::Instruction::ZExt, C, boolTy, CGM.getDataLayout());
    assert(Res && "Constant folding must succeed");
    return Res;
  }

  if (destType->isBitIntType()) {
    llvm::Type *MemTy = CGM.getTypes().ConvertTypeForMem(destType);
    if (C->getType() != MemTy) {
      ConstantAggregateBuilder Builder(CGM);
      llvm::Type *LoadStoreTy =
          CGM.getTypes().convertTypeForLoadStore(destType);
      // ptrtoint/inttoptr should not involve _BitInt in constant expressions,
      // so casting to ConstantInt is safe here.
      auto *CI = cast<llvm::ConstantInt>(C);
      llvm::Constant *Res = llvm::ConstantFoldCastOperand(
          destType->isSignedIntegerOrEnumerationType()
              ? llvm::Instruction::SExt
              : llvm::Instruction::ZExt,
          CI, LoadStoreTy, CGM.getDataLayout());
      if (CGM.getTypes().typeRequiresSplitIntoByteArray(destType,
                                                        C->getType())) {
        // Long _BitInt has array of bytes as in-memory type.
        // So, split constant into individual bytes.
        llvm::APInt Value = cast<llvm::ConstantInt>(Res)->getValue();
        Builder.addBits(Value, /*OffsetInBits=*/0, /*AllowOverwrite=*/false);
        return Builder.build(MemTy, /*AllowOversized*/ false);
      }
      return Res;
    }
  }

  return C;
}

llvm::Constant *ConstantEmitter::tryEmitPrivate(const Expr *E,
                                                QualType destType) {
  assert(!destType->isVoidType() && "can't emit a void constant");

  if (!destType->isReferenceType())
    if (llvm::Constant *C = ConstExprEmitter(*this).Visit(E, destType))
      return C;

  Expr::EvalResult Result;

  bool Success = false;

  if (destType->isReferenceType())
    Success = E->EvaluateAsLValue(Result, CGM.getContext());
  else
    Success = E->EvaluateAsRValue(Result, CGM.getContext(), InConstantContext);

  if (Success && !Result.HasSideEffects)
    return tryEmitPrivate(Result.Val, destType);

  return nullptr;
}

llvm::Constant *CodeGenModule::getNullPointer(llvm::PointerType *T, QualType QT) {
  return getTargetCodeGenInfo().getNullPointer(*this, T, QT);
}

namespace {
/// A struct which can be used to peephole certain kinds of finalization
/// that normally happen during l-value emission.
struct ConstantLValue {
  llvm::Constant *Value;
  bool HasOffsetApplied;
  bool HasDestPointerAuth;

  /*implicit*/ ConstantLValue(llvm::Constant *value,
                              bool hasOffsetApplied = false,
                              bool hasDestPointerAuth = false)
      : Value(value), HasOffsetApplied(hasOffsetApplied),
        HasDestPointerAuth(hasDestPointerAuth) {}

  /*implicit*/ ConstantLValue(ConstantAddress address)
    : ConstantLValue(address.getPointer()) {}
};

/// A helper class for emitting constant l-values.
class ConstantLValueEmitter : public ConstStmtVisitor<ConstantLValueEmitter,
                                                      ConstantLValue> {
  CodeGenModule &CGM;
  ConstantEmitter &Emitter;
  const APValue &Value;
  QualType DestType;
  bool EnablePtrAuthFunctionTypeDiscrimination;

  // Befriend StmtVisitorBase so that we don't have to expose Visit*.
  friend StmtVisitorBase;

public:
  ConstantLValueEmitter(ConstantEmitter &emitter, const APValue &value,
                        QualType destType,
                        bool EnablePtrAuthFunctionTypeDiscrimination = true)
      : CGM(emitter.CGM), Emitter(emitter), Value(value), DestType(destType),
        EnablePtrAuthFunctionTypeDiscrimination(
            EnablePtrAuthFunctionTypeDiscrimination) {}

  llvm::Constant *tryEmit();

private:
  llvm::Constant *tryEmitAbsolute(llvm::Type *destTy);
  ConstantLValue tryEmitBase(const APValue::LValueBase &base);

  ConstantLValue VisitStmt(const Stmt *S) { return nullptr; }
  ConstantLValue VisitConstantExpr(const ConstantExpr *E);
  ConstantLValue VisitCompoundLiteralExpr(const CompoundLiteralExpr *E);
  ConstantLValue VisitStringLiteral(const StringLiteral *E);
  ConstantLValue VisitObjCBoxedExpr(const ObjCBoxedExpr *E);
  ConstantLValue VisitObjCEncodeExpr(const ObjCEncodeExpr *E);
  ConstantLValue VisitObjCStringLiteral(const ObjCStringLiteral *E);
  llvm::Constant *VisitObjCCollectionElement(const Expr *E);
  ConstantLValue VisitObjCArrayLiteral(const ObjCArrayLiteral *E);
  ConstantLValue VisitObjCDictionaryLiteral(const ObjCDictionaryLiteral *E);
  ConstantLValue VisitPredefinedExpr(const PredefinedExpr *E);
  ConstantLValue VisitAddrLabelExpr(const AddrLabelExpr *E);
  ConstantLValue VisitCallExpr(const CallExpr *E);
  ConstantLValue VisitBlockExpr(const BlockExpr *E);
  ConstantLValue VisitCXXTypeidExpr(const CXXTypeidExpr *E);
  ConstantLValue VisitMaterializeTemporaryExpr(
                                         const MaterializeTemporaryExpr *E);

  ConstantLValue emitPointerAuthSignConstant(const CallExpr *E);
  llvm::Constant *emitPointerAuthPointer(const Expr *E);
  unsigned emitPointerAuthKey(const Expr *E);
  std::pair<llvm::Constant *, llvm::ConstantInt *>
  emitPointerAuthDiscriminator(const Expr *E);

  bool hasNonZeroOffset() const {
    return !Value.getLValueOffset().isZero();
  }

  /// Return the value offset.
  llvm::Constant *getOffset() {
    return llvm::ConstantInt::get(CGM.Int64Ty,
                                  Value.getLValueOffset().getQuantity());
  }

  /// Apply the value offset to the given constant.
  llvm::Constant *applyOffset(llvm::Constant *C) {
    if (!hasNonZeroOffset())
      return C;

    return llvm::ConstantExpr::getPtrAdd(C, getOffset());
  }
};

}

llvm::Constant *ConstantLValueEmitter::tryEmit() {
  const APValue::LValueBase &base = Value.getLValueBase();

  // The destination type should be a pointer or reference
  // type, but it might also be a cast thereof.
  //
  // FIXME: the chain of casts required should be reflected in the APValue.
  // We need this in order to correctly handle things like a ptrtoint of a
  // non-zero null pointer and addrspace casts that aren't trivially
  // represented in LLVM IR.
  auto destTy = CGM.getTypes().ConvertTypeForMem(DestType);
  assert(isa<llvm::IntegerType>(destTy) || isa<llvm::PointerType>(destTy));

  // If there's no base at all, this is a null or absolute pointer,
  // possibly cast back to an integer type.
  if (!base) {
    return tryEmitAbsolute(destTy);
  }

  // Otherwise, try to emit the base.
  ConstantLValue result = tryEmitBase(base);

  // If that failed, we're done.
  llvm::Constant *value = result.Value;
  if (!value) return nullptr;

  // Apply the offset if necessary and not already done.
  if (!result.HasOffsetApplied) {
    value = applyOffset(value);
  }

  // Apply pointer-auth signing from the destination type.
  if (PointerAuthQualifier PointerAuth = DestType.getPointerAuth();
      PointerAuth && !result.HasDestPointerAuth) {
    value = Emitter.tryEmitConstantSignedPointer(value, PointerAuth);
    if (!value)
      return nullptr;
  }

  // Convert to the appropriate type; this could be an lvalue for
  // an integer.  FIXME: performAddrSpaceCast
  if (isa<llvm::PointerType>(destTy))
    return llvm::ConstantExpr::getPointerCast(value, destTy);

  return llvm::ConstantExpr::getPtrToInt(value, destTy);
}

/// Try to emit an absolute l-value, such as a null pointer or an integer
/// bitcast to pointer type.
llvm::Constant *
ConstantLValueEmitter::tryEmitAbsolute(llvm::Type *destTy) {
  // If we're producing a pointer, this is easy.
  auto destPtrTy = cast<llvm::PointerType>(destTy);
  if (Value.isNullPointer()) {
    // FIXME: integer offsets from non-zero null pointers.
    return CGM.getNullPointer(destPtrTy, DestType);
  }

  // Convert the integer to a pointer-sized integer before converting it
  // to a pointer.
  // FIXME: signedness depends on the original integer type.
  auto intptrTy = CGM.getDataLayout().getIntPtrType(destPtrTy);
  llvm::Constant *C;
  C = llvm::ConstantFoldIntegerCast(getOffset(), intptrTy, /*isSigned*/ false,
                                    CGM.getDataLayout());
  assert(C && "Must have folded, as Offset is a ConstantInt");
  C = llvm::ConstantExpr::getIntToPtr(C, destPtrTy);
  return C;
}

ConstantLValue
ConstantLValueEmitter::tryEmitBase(const APValue::LValueBase &base) {
  // Handle values.
  if (const ValueDecl *D = base.dyn_cast<const ValueDecl*>()) {
    // The constant always points to the canonical declaration. We want to look
    // at properties of the most recent declaration at the point of emission.
    D = cast<ValueDecl>(D->getMostRecentDecl());

    if (D->hasAttr<WeakRefAttr>())
      return CGM.GetWeakRefReference(D).getPointer();

    auto PtrAuthSign = [&](llvm::Constant *C) {
      if (PointerAuthQualifier PointerAuth = DestType.getPointerAuth()) {
        C = applyOffset(C);
        C = Emitter.tryEmitConstantSignedPointer(C, PointerAuth);
        return ConstantLValue(C, /*applied offset*/ true, /*signed*/ true);
      }

      CGPointerAuthInfo AuthInfo;

      if (EnablePtrAuthFunctionTypeDiscrimination)
        AuthInfo = CGM.getFunctionPointerAuthInfo(DestType);

      if (AuthInfo) {
        if (hasNonZeroOffset())
          return ConstantLValue(nullptr);

        C = applyOffset(C);
        C = CGM.getConstantSignedPointer(
            C, AuthInfo.getKey(), nullptr,
            cast_or_null<llvm::ConstantInt>(AuthInfo.getDiscriminator()));
        return ConstantLValue(C, /*applied offset*/ true, /*signed*/ true);
      }

      return ConstantLValue(C);
    };

    if (const auto *FD = dyn_cast<FunctionDecl>(D)) {
      llvm::Constant *C = CGM.getRawFunctionPointer(FD);
      if (FD->getType()->isCFIUncheckedCalleeFunctionType())
        C = llvm::NoCFIValue::get(cast<llvm::GlobalValue>(C));
      return PtrAuthSign(C);
    }

    if (const auto *VD = dyn_cast<VarDecl>(D)) {
      // We can never refer to a variable with local storage.
      if (!VD->hasLocalStorage()) {
        if (VD->isFileVarDecl() || VD->hasExternalStorage())
          return CGM.GetAddrOfGlobalVar(VD);

        if (VD->isLocalVarDecl()) {
          return CGM.getOrCreateStaticVarDecl(
              *VD, CGM.getLLVMLinkageVarDefinition(VD));
        }
      }
    }

    if (const auto *GD = dyn_cast<MSGuidDecl>(D))
      return CGM.GetAddrOfMSGuidDecl(GD);

    if (const auto *GCD = dyn_cast<UnnamedGlobalConstantDecl>(D))
      return CGM.GetAddrOfUnnamedGlobalConstantDecl(GCD);

    if (const auto *TPO = dyn_cast<TemplateParamObjectDecl>(D))
      return CGM.GetAddrOfTemplateParamObject(TPO);

    return nullptr;
  }

  // Handle typeid(T).
  if (TypeInfoLValue TI = base.dyn_cast<TypeInfoLValue>())
    return CGM.GetAddrOfRTTIDescriptor(QualType(TI.getType(), 0));

  // Otherwise, it must be an expression.
  return Visit(base.get<const Expr*>());
}

ConstantLValue
ConstantLValueEmitter::VisitConstantExpr(const ConstantExpr *E) {
  if (llvm::Constant *Result = Emitter.tryEmitConstantExpr(E))
    return Result;
  return Visit(E->getSubExpr());
}

ConstantLValue
ConstantLValueEmitter::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
  ConstantEmitter CompoundLiteralEmitter(CGM, Emitter.CGF);
  CompoundLiteralEmitter.setInConstantContext(Emitter.isInConstantContext());
  return tryEmitGlobalCompoundLiteral(CompoundLiteralEmitter, E);
}

ConstantLValue
ConstantLValueEmitter::VisitStringLiteral(const StringLiteral *E) {
  return CGM.GetAddrOfConstantStringFromLiteral(E);
}

ConstantLValue
ConstantLValueEmitter::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
  return CGM.GetAddrOfConstantStringFromObjCEncode(E);
}

static ConstantLValue emitConstantObjCStringLiteral(const StringLiteral *S,
                                                    QualType T,
                                                    CodeGenModule &CGM) {
  auto C = CGM.getObjCRuntime().GenerateConstantString(S);
  return C.withElementType(CGM.getTypes().ConvertTypeForMem(T));
}

ConstantLValue
ConstantLValueEmitter::VisitObjCStringLiteral(const ObjCStringLiteral *E) {
  return emitConstantObjCStringLiteral(E->getString(), E->getType(), CGM);
}

ConstantLValue
ConstantLValueEmitter::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
  ASTContext &Context = CGM.getContext();
  CGObjCRuntime &Runtime = CGM.getObjCRuntime();
  const Expr *SubExpr = E->getSubExpr();
  const QualType &Ty = SubExpr->IgnoreParens()->getType();

  assert(SubExpr->isEvaluatable(Context) &&
         "Non const NSNumber is being emitted as a constant");

  if (const auto *SL = dyn_cast<StringLiteral>(SubExpr->IgnoreParenCasts()))
    return emitConstantObjCStringLiteral(SL, E->getType(), CGM);

  // Note `@YES` `@NO` need to be handled explicitly
  // to meet existing plist encoding / decoding expectations
  const bool IsBoolType =
      (Ty->isBooleanType() || NSAPI(Context).isObjCBOOLType(Ty));
  bool BoolValue = false;
  if (IsBoolType && SubExpr->EvaluateAsBooleanCondition(BoolValue, Context)) {
    ConstantAddress C = Runtime.GenerateConstantNumber(BoolValue, Ty);
    return C.withElementType(CGM.getTypes().ConvertTypeForMem(E->getType()));
  }

  Expr::EvalResult IntResult{};
  if (SubExpr->EvaluateAsInt(IntResult, Context)) {
    ConstantAddress C =
        Runtime.GenerateConstantNumber(IntResult.Val.getInt(), Ty);
    return C.withElementType(CGM.getTypes().ConvertTypeForMem(E->getType()));
  }

  llvm::APFloat FloatValue(0.0);
  if (SubExpr->EvaluateAsFloat(FloatValue, Context)) {
    ConstantAddress C = Runtime.GenerateConstantNumber(FloatValue, Ty);
    return C.withElementType(CGM.getTypes().ConvertTypeForMem(E->getType()));
  }

  llvm_unreachable("SubExpr is expected to be evaluated as a numeric type");
}

llvm::Constant *
ConstantLValueEmitter::VisitObjCCollectionElement(const Expr *E) {
  auto CE = cast<CastExpr>(E);
  const Expr *Elm = CE->getSubExpr();
  QualType DestTy = CE->getType();

  assert(CE->getCastKind() == CK_BitCast &&
         "Expected a CK_BitCast type for valid items in constant objc "
         "collection literals");

  llvm::Type *DstTy = CGM.getTypes().ConvertType(DestTy);
  ConstantLValue LV = Visit(Elm);
  llvm::Constant *ConstVal = cast<llvm::Constant>(LV.Value);
  llvm::Constant *Val = llvm::ConstantExpr::getBitCast(ConstVal, DstTy);
  return Val;
}

ConstantLValue
ConstantLValueEmitter::VisitObjCArrayLiteral(const ObjCArrayLiteral *E) {
  SmallVector<llvm::Constant *, 16> ObjectExpressions;
  uint64_t NumElements = E->getNumElements();
  ObjectExpressions.reserve(NumElements);

  for (uint64_t i = 0; i < NumElements; i++) {
    llvm::Constant *Val = VisitObjCCollectionElement(E->getElement(i));
    ObjectExpressions.push_back(Val);
  }
  ConstantAddress C =
      CGM.getObjCRuntime().GenerateConstantArray(ObjectExpressions);
  return C.withElementType(CGM.getTypes().ConvertTypeForMem(E->getType()));
}

ConstantLValue ConstantLValueEmitter::VisitObjCDictionaryLiteral(
    const ObjCDictionaryLiteral *E) {
  SmallVector<std::pair<llvm::Constant *, llvm::Constant *>, 16> KeysAndObjects;
  uint64_t NumElements = E->getNumElements();
  KeysAndObjects.reserve(NumElements);

  for (uint64_t i = 0; i < NumElements; i++) {
    llvm::Constant *Key =
        VisitObjCCollectionElement(E->getKeyValueElement(i).Key);
    llvm::Constant *Val =
        VisitObjCCollectionElement(E->getKeyValueElement(i).Value);
    KeysAndObjects.push_back({Key, Val});
  }
  ConstantAddress C =
      CGM.getObjCRuntime().GenerateConstantDictionary(E, KeysAndObjects);
  return C.withElementType(CGM.getTypes().ConvertTypeForMem(E->getType()));
}

ConstantLValue
ConstantLValueEmitter::VisitPredefinedExpr(const PredefinedExpr *E) {
  return CGM.GetAddrOfConstantStringFromLiteral(E->getFunctionName());
}

ConstantLValue
ConstantLValueEmitter::VisitAddrLabelExpr(const AddrLabelExpr *E) {
  assert(Emitter.CGF && "Invalid address of label expression outside function");
  llvm::Constant *Ptr = Emitter.CGF->GetAddrOfLabel(E->getLabel());
  return Ptr;
}

ConstantLValue
ConstantLValueEmitter::VisitCallExpr(const CallExpr *E) {
  unsigned builtin = E->getBuiltinCallee();
  if (builtin == Builtin::BI__builtin_function_start)
    return CGM.GetFunctionStart(
        E->getArg(0)->getAsBuiltinConstantDeclRef(CGM.getContext()));

  if (builtin == Builtin::BI__builtin_ptrauth_sign_constant)
    return emitPointerAuthSignConstant(E);

  if (builtin != Builtin::BI__builtin___CFStringMakeConstantString &&
      builtin != Builtin::BI__builtin___NSStringMakeConstantString)
    return nullptr;

  const auto *Literal = cast<StringLiteral>(E->getArg(0)->IgnoreParenCasts());
  if (builtin == Builtin::BI__builtin___NSStringMakeConstantString) {
    return CGM.getObjCRuntime().GenerateConstantString(Literal);
  } else {
    // FIXME: need to deal with UCN conversion issues.
    return CGM.GetAddrOfConstantCFString(Literal);
  }
}

ConstantLValue
ConstantLValueEmitter::emitPointerAuthSignConstant(const CallExpr *E) {
  llvm::Constant *UnsignedPointer = emitPointerAuthPointer(E->getArg(0));
  unsigned Key = emitPointerAuthKey(E->getArg(1));
  auto [StorageAddress, OtherDiscriminator] =
      emitPointerAuthDiscriminator(E->getArg(2));

  llvm::Constant *SignedPointer = CGM.getConstantSignedPointer(
      UnsignedPointer, Key, StorageAddress, OtherDiscriminator);
  return SignedPointer;
}

llvm::Constant *ConstantLValueEmitter::emitPointerAuthPointer(const Expr *E) {
  Expr::EvalResult Result;
  bool Succeeded = E->EvaluateAsRValue(Result, CGM.getContext());
  assert(Succeeded);
  (void)Succeeded;

  // The assertions here are all checked by Sema.
  assert(Result.Val.isLValue());
  if (isa<FunctionDecl>(Result.Val.getLValueBase().get<const ValueDecl *>()))
    assert(Result.Val.getLValueOffset().isZero());
  return ConstantEmitter(CGM, Emitter.CGF)
      .emitAbstract(E->getExprLoc(), Result.Val, E->getType(), false);
}

unsigned ConstantLValueEmitter::emitPointerAuthKey(const Expr *E) {
  return E->EvaluateKnownConstInt(CGM.getContext()).getZExtValue();
}

std::pair<llvm::Constant *, llvm::ConstantInt *>
ConstantLValueEmitter::emitPointerAuthDiscriminator(const Expr *E) {
  E = E->IgnoreParens();

  if (const auto *Call = dyn_cast<CallExpr>(E)) {
    if (Call->getBuiltinCallee() ==
        Builtin::BI__builtin_ptrauth_blend_discriminator) {
      llvm::Constant *Pointer = ConstantEmitter(CGM).emitAbstract(
          Call->getArg(0), Call->getArg(0)->getType());
      auto *Extra = cast<llvm::ConstantInt>(ConstantEmitter(CGM).emitAbstract(
          Call->getArg(1), Call->getArg(1)->getType()));
      return {Pointer, Extra};
    }
  }

  llvm::Constant *Result = ConstantEmitter(CGM).emitAbstract(E, E->getType());
  if (Result->getType()->isPointerTy())
    return {Result, nullptr};
  return {nullptr, cast<llvm::ConstantInt>(Result)};
}

ConstantLValue
ConstantLValueEmitter::VisitBlockExpr(const BlockExpr *E) {
  StringRef functionName;
  if (auto CGF = Emitter.CGF)
    functionName = CGF->CurFn->getName();
  else
    functionName = "global";

  return CGM.GetAddrOfGlobalBlock(E, functionName);
}

ConstantLValue
ConstantLValueEmitter::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
  QualType T;
  if (E->isTypeOperand())
    T = E->getTypeOperand(CGM.getContext());
  else
    T = E->getExprOperand()->getType();
  return CGM.GetAddrOfRTTIDescriptor(T);
}

ConstantLValue
ConstantLValueEmitter::VisitMaterializeTemporaryExpr(
                                            const MaterializeTemporaryExpr *E) {
  assert(E->getStorageDuration() == SD_Static);
  const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();
  return CGM.GetAddrOfGlobalTemporary(E, Inner);
}

llvm::Constant *
ConstantEmitter::tryEmitPrivate(const APValue &Value, QualType DestType,
                                bool EnablePtrAuthFunctionTypeDiscrimination) {
  switch (Value.getKind()) {
  case APValue::None:
  case APValue::Indeterminate:
    // Out-of-lifetime and indeterminate values can be modeled as 'undef'.
    return llvm::UndefValue::get(CGM.getTypes().ConvertType(DestType));
  case APValue::LValue:
    return ConstantLValueEmitter(*this, Value, DestType,
                                 EnablePtrAuthFunctionTypeDiscrimination)
        .tryEmit();
  case APValue::Int:
    if (PointerAuthQualifier PointerAuth = DestType.getPointerAuth();
        PointerAuth &&
        (PointerAuth.authenticatesNullValues() || Value.getInt() != 0))
      return nullptr;
    return llvm::ConstantInt::get(CGM.getLLVMContext(), Value.getInt());
  case APValue::FixedPoint:
    return llvm::ConstantInt::get(CGM.getLLVMContext(),
                                  Value.getFixedPoint().getValue());
  case APValue::ComplexInt: {
    llvm::Constant *Complex[2];

    Complex[0] = llvm::ConstantInt::get(CGM.getLLVMContext(),
                                        Value.getComplexIntReal());
    Complex[1] = llvm::ConstantInt::get(CGM.getLLVMContext(),
                                        Value.getComplexIntImag());

    // FIXME: the target may want to specify that this is packed.
    llvm::StructType *STy =
        llvm::StructType::get(Complex[0]->getType(), Complex[1]->getType());
    return llvm::ConstantStruct::get(STy, Complex);
  }
  case APValue::Float: {
    const llvm::APFloat &Init = Value.getFloat();
    if (&Init.getSemantics() == &llvm::APFloat::IEEEhalf() &&
        !CGM.getContext().getLangOpts().NativeHalfType &&
        CGM.getContext().getTargetInfo().useFP16ConversionIntrinsics())
      return llvm::ConstantInt::get(CGM.getLLVMContext(),
                                    Init.bitcastToAPInt());
    else
      return llvm::ConstantFP::get(CGM.getLLVMContext(), Init);
  }
  case APValue::ComplexFloat: {
    llvm::Constant *Complex[2];

    Complex[0] = llvm::ConstantFP::get(CGM.getLLVMContext(),
                                       Value.getComplexFloatReal());
    Complex[1] = llvm::ConstantFP::get(CGM.getLLVMContext(),
                                       Value.getComplexFloatImag());

    // FIXME: the target may want to specify that this is packed.
    llvm::StructType *STy =
        llvm::StructType::get(Complex[0]->getType(), Complex[1]->getType());
    return llvm::ConstantStruct::get(STy, Complex);
  }
  case APValue::Vector: {
    unsigned NumElts = Value.getVectorLength();
    SmallVector<llvm::Constant *, 4> Inits(NumElts);

    for (unsigned I = 0; I != NumElts; ++I) {
      const APValue &Elt = Value.getVectorElt(I);
      if (Elt.isInt())
        Inits[I] = llvm::ConstantInt::get(CGM.getLLVMContext(), Elt.getInt());
      else if (Elt.isFloat())
        Inits[I] = llvm::ConstantFP::get(CGM.getLLVMContext(), Elt.getFloat());
      else if (Elt.isIndeterminate())
        Inits[I] = llvm::UndefValue::get(CGM.getTypes().ConvertType(
            DestType->castAs<VectorType>()->getElementType()));
      else
        llvm_unreachable("unsupported vector element type");
    }
    return llvm::ConstantVector::get(Inits);
  }
  case APValue::Matrix: {
    const auto *MT = DestType->castAs<ConstantMatrixType>();
    unsigned NumRows = Value.getMatrixNumRows();
    unsigned NumCols = Value.getMatrixNumColumns();
    unsigned NumElts = NumRows * NumCols;
    SmallVector<llvm::Constant *, 16> Inits(NumElts);

    bool IsRowMajor = isMatrixRowMajor(CGM.getLangOpts(), DestType);

    for (unsigned Row = 0; Row != NumRows; ++Row) {
      for (unsigned Col = 0; Col != NumCols; ++Col) {
        const APValue &Elt = Value.getMatrixElt(Row, Col);
        unsigned Idx = MT->getFlattenedIndex(Row, Col, IsRowMajor);
        if (Elt.isInt())
          Inits[Idx] =
              llvm::ConstantInt::get(CGM.getLLVMContext(), Elt.getInt());
        else if (Elt.isFloat())
          Inits[Idx] =
              llvm::ConstantFP::get(CGM.getLLVMContext(), Elt.getFloat());
        else if (Elt.isIndeterminate())
          Inits[Idx] = llvm::PoisonValue::get(
              CGM.getTypes().ConvertType(MT->getElementType()));
        else
          llvm_unreachable("unsupported matrix element type");
      }
    }
    return llvm::ConstantVector::get(Inits);
  }
  case APValue::AddrLabelDiff: {
    const AddrLabelExpr *LHSExpr = Value.getAddrLabelDiffLHS();
    const AddrLabelExpr *RHSExpr = Value.getAddrLabelDiffRHS();
    llvm::Constant *LHS = tryEmitPrivate(LHSExpr, LHSExpr->getType());
    llvm::Constant *RHS = tryEmitPrivate(RHSExpr, RHSExpr->getType());
    if (!LHS || !RHS) return nullptr;

    // Compute difference
    llvm::Type *ResultType = CGM.getTypes().ConvertType(DestType);
    LHS = llvm::ConstantExpr::getPtrToInt(LHS, CGM.IntPtrTy);
    RHS = llvm::ConstantExpr::getPtrToInt(RHS, CGM.IntPtrTy);
    llvm::Constant *AddrLabelDiff = llvm::ConstantExpr::getSub(LHS, RHS);

    // LLVM is a bit sensitive about the exact format of the
    // address-of-label difference; make sure to truncate after
    // the subtraction.
    return llvm::ConstantExpr::getTruncOrBitCast(AddrLabelDiff, ResultType);
  }
  case APValue::Struct:
  case APValue::Union:
    return ConstStructBuilder::BuildStruct(*this, Value, DestType);
  case APValue::Array: {
    const ArrayType *ArrayTy = CGM.getContext().getAsArrayType(DestType);
    unsigned NumElements = Value.getArraySize();
    unsigned NumInitElts = Value.getArrayInitializedElts();

    // Emit array filler, if there is one.
    llvm::Constant *Filler = nullptr;
    if (Value.hasArrayFiller()) {
      Filler = tryEmitAbstractForMemory(Value.getArrayFiller(),
                                        ArrayTy->getElementType());
      if (!Filler)
        return nullptr;
    }

    // Emit initializer elements.
    SmallVector<llvm::Constant*, 16> Elts;
    if (Filler && Filler->isNullValue())
      Elts.reserve(NumInitElts + 1);
    else
      Elts.reserve(NumElements);

    llvm::Type *CommonElementType = nullptr;
    for (unsigned I = 0; I < NumInitElts; ++I) {
      llvm::Constant *C = tryEmitPrivateForMemory(
          Value.getArrayInitializedElt(I), ArrayTy->getElementType());
      if (!C) return nullptr;

      if (I == 0)
        CommonElementType = C->getType();
      else if (C->getType() != CommonElementType)
        CommonElementType = nullptr;
      Elts.push_back(C);
    }

    llvm::ArrayType *Desired =
        cast<llvm::ArrayType>(CGM.getTypes().ConvertType(DestType));

    // Fix the type of incomplete arrays if the initializer isn't empty.
    if (DestType->isIncompleteArrayType() && !Elts.empty())
      Desired = llvm::ArrayType::get(Desired->getElementType(), Elts.size());

    return EmitArrayConstant(CGM, Desired, CommonElementType, NumElements, Elts,
                             Filler);
  }
  case APValue::MemberPointer:
    return CGM.getCXXABI().EmitMemberPointer(Value, DestType);
  }
  llvm_unreachable("Unknown APValue kind");
}

llvm::GlobalVariable *CodeGenModule::getAddrOfConstantCompoundLiteralIfEmitted(
    const CompoundLiteralExpr *E) {
  return EmittedCompoundLiterals.lookup(E);
}

void CodeGenModule::setAddrOfConstantCompoundLiteral(
    const CompoundLiteralExpr *CLE, llvm::GlobalVariable *GV) {
  bool Ok = EmittedCompoundLiterals.insert(std::make_pair(CLE, GV)).second;
  (void)Ok;
  assert(Ok && "CLE has already been emitted!");
}

ConstantAddress
CodeGenModule::GetAddrOfConstantCompoundLiteral(const CompoundLiteralExpr *E) {
  assert(E->isFileScope() && "not a file-scope compound literal expr");
  ConstantEmitter emitter(*this);
  return tryEmitGlobalCompoundLiteral(emitter, E);
}

llvm::Constant *
CodeGenModule::getMemberPointerConstant(const UnaryOperator *uo) {
  // Member pointer constants always have a very particular form.
  const MemberPointerType *type = cast<MemberPointerType>(uo->getType());
  const ValueDecl *decl = cast<DeclRefExpr>(uo->getSubExpr())->getDecl();

  // A member function pointer.
  if (const CXXMethodDecl *method = dyn_cast<CXXMethodDecl>(decl))
    return getCXXABI().EmitMemberFunctionPointer(method);

  // Otherwise, a member data pointer.
  getContext().recordMemberDataPointerEvaluation(decl);
  uint64_t fieldOffset = getContext().getFieldOffset(decl);
  CharUnits chars = getContext().toCharUnitsFromBits((int64_t) fieldOffset);
  return getCXXABI().EmitMemberDataPointer(type, chars);
}

static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM,
                                               llvm::Type *baseType,
                                               const CXXRecordDecl *base);

static llvm::Constant *EmitNullConstant(CodeGenModule &CGM,
                                        const RecordDecl *record,
                                        bool asCompleteObject) {
  const CGRecordLayout &layout = CGM.getTypes().getCGRecordLayout(record);
  llvm::StructType *structure =
    (asCompleteObject ? layout.getLLVMType()
                      : layout.getBaseSubobjectLLVMType());

  unsigned numElements = structure->getNumElements();
  std::vector<llvm::Constant *> elements(numElements);

  auto CXXR = dyn_cast<CXXRecordDecl>(record);
  // Fill in all the bases.
  if (CXXR) {
    for (const auto &I : CXXR->bases()) {
      if (I.isVirtual()) {
        // Ignore virtual bases; if we're laying out for a complete
        // object, we'll lay these out later.
        continue;
      }

      const auto *base = I.getType()->castAsCXXRecordDecl();
      // Ignore empty bases.
      if (isEmptyRecordForLayout(CGM.getContext(), I.getType()) ||
          CGM.getContext()
              .getASTRecordLayout(base)
              .getNonVirtualSize()
              .isZero())
        continue;

      unsigned fieldIndex = layout.getNonVirtualBaseLLVMFieldNo(base);
      llvm::Type *baseType = structure->getElementType(fieldIndex);
      elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base);
    }
  }

  // Fill in all the fields.
  for (const auto *Field : record->fields()) {
    // Fill in non-bitfields. (Bitfields always use a zero pattern, which we
    // will fill in later.)
    if (!Field->isBitField() &&
        !isEmptyFieldForLayout(CGM.getContext(), Field)) {
      unsigned fieldIndex = layout.getLLVMFieldNo(Field);
      elements[fieldIndex] = CGM.EmitNullConstant(Field->getType());
    }

    // For unions, stop after the first named field.
    if (record->isUnion()) {
      if (Field->getIdentifier())
        break;
      if (const auto *FieldRD = Field->getType()->getAsRecordDecl())
        if (FieldRD->findFirstNamedDataMember())
          break;
    }
  }

  // Fill in the virtual bases, if we're working with the complete object.
  if (CXXR && asCompleteObject) {
    for (const auto &I : CXXR->vbases()) {
      const auto *base = I.getType()->castAsCXXRecordDecl();
      // Ignore empty bases.
      if (isEmptyRecordForLayout(CGM.getContext(), I.getType()))
        continue;

      unsigned fieldIndex = layout.getVirtualBaseIndex(base);

      // We might have already laid this field out.
      if (elements[fieldIndex]) continue;

      llvm::Type *baseType = structure->getElementType(fieldIndex);
      elements[fieldIndex] = EmitNullConstantForBase(CGM, baseType, base);
    }
  }

  // Now go through all other fields and zero them out.
  for (unsigned i = 0; i != numElements; ++i) {
    if (!elements[i])
      elements[i] = llvm::Constant::getNullValue(structure->getElementType(i));
  }

  return llvm::ConstantStruct::get(structure, elements);
}

/// Emit the null constant for a base subobject.
static llvm::Constant *EmitNullConstantForBase(CodeGenModule &CGM,
                                               llvm::Type *baseType,
                                               const CXXRecordDecl *base) {
  const CGRecordLayout &baseLayout = CGM.getTypes().getCGRecordLayout(base);

  // Just zero out bases that don't have any pointer to data members.
  if (baseLayout.isZeroInitializableAsBase())
    return llvm::Constant::getNullValue(baseType);

  // Otherwise, we can just use its null constant.
  return EmitNullConstant(CGM, base, /*asCompleteObject=*/false);
}

llvm::Constant *ConstantEmitter::emitNullForMemory(CodeGenModule &CGM,
                                                   QualType T) {
  return emitForMemory(CGM, CGM.EmitNullConstant(T), T);
}

llvm::Constant *CodeGenModule::EmitNullConstant(QualType T) {
  if (T->getAs<PointerType>())
    return getNullPointer(
        cast<llvm::PointerType>(getTypes().ConvertTypeForMem(T)), T);

  if (getTypes().isZeroInitializable(T))
    return llvm::Constant::getNullValue(getTypes().ConvertTypeForMem(T));

  if (const ConstantArrayType *CAT = Context.getAsConstantArrayType(T)) {
    llvm::ArrayType *ATy =
      cast<llvm::ArrayType>(getTypes().ConvertTypeForMem(T));

    QualType ElementTy = CAT->getElementType();

    llvm::Constant *Element =
      ConstantEmitter::emitNullForMemory(*this, ElementTy);
    unsigned NumElements = CAT->getZExtSize();
    SmallVector<llvm::Constant *, 8> Array(NumElements, Element);
    return llvm::ConstantArray::get(ATy, Array);
  }

  if (const auto *RD = T->getAsRecordDecl())
    return ::EmitNullConstant(*this, RD,
                              /*asCompleteObject=*/true);

  assert(T->isMemberDataPointerType() &&
         "Should only see pointers to data members here!");

  return getCXXABI().EmitNullMemberPointer(T->castAs<MemberPointerType>());
}

llvm::Constant *
CodeGenModule::EmitNullConstantForBase(const CXXRecordDecl *Record) {
  return ::EmitNullConstant(*this, Record, false);
}
