//===--- Compiler.cpp - Code generator for expressions ---*- C++ -*-===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "Compiler.h"
#include "ByteCodeEmitter.h"
#include "Context.h"
#include "FixedPoint.h"
#include "Floating.h"
#include "Function.h"
#include "InterpShared.h"
#include "PrimType.h"
#include "Program.h"
#include "clang/AST/Attr.h"
#include "llvm/Support/SaveAndRestore.h"

using namespace clang;
using namespace clang::interp;

using APSInt = llvm::APSInt;

namespace clang {
namespace interp {

static std::optional<bool> getBoolValue(const Expr *E) {
  if (const auto *CE = dyn_cast_if_present<ConstantExpr>(E);
      CE && CE->hasAPValueResult() &&
      CE->getResultAPValueKind() == APValue::ValueKind::Int) {
    return CE->getResultAsAPSInt().getBoolValue();
  }

  return std::nullopt;
}

/// Scope used to handle temporaries in toplevel variable declarations.
template <class Emitter> class DeclScope final : public LocalScope<Emitter> {
public:
  DeclScope(Compiler<Emitter> *Ctx, const ValueDecl *VD)
      : LocalScope<Emitter>(Ctx), Scope(Ctx->P),
        OldInitializingDecl(Ctx->InitializingDecl) {
    Ctx->InitializingDecl = VD;
    Ctx->InitStack.push_back(InitLink::Decl(VD));
  }

  ~DeclScope() {
    this->Ctx->InitializingDecl = OldInitializingDecl;
    this->Ctx->InitStack.pop_back();
  }

private:
  Program::DeclScope Scope;
  const ValueDecl *OldInitializingDecl;
};

/// Scope used to handle initialization methods.
template <class Emitter> class OptionScope final {
public:
  /// Root constructor, compiling or discarding primitives.
  OptionScope(Compiler<Emitter> *Ctx, bool NewDiscardResult,
              bool NewInitializing, bool NewToLValue)
      : Ctx(Ctx), OldDiscardResult(Ctx->DiscardResult),
        OldInitializing(Ctx->Initializing), OldToLValue(Ctx->ToLValue) {
    Ctx->DiscardResult = NewDiscardResult;
    Ctx->Initializing = NewInitializing;
    Ctx->ToLValue = NewToLValue;
  }

  ~OptionScope() {
    Ctx->DiscardResult = OldDiscardResult;
    Ctx->Initializing = OldInitializing;
    Ctx->ToLValue = OldToLValue;
  }

private:
  /// Parent context.
  Compiler<Emitter> *Ctx;
  /// Old discard flag to restore.
  bool OldDiscardResult;
  bool OldInitializing;
  bool OldToLValue;
};

template <class Emitter>
bool InitLink::emit(Compiler<Emitter> *Ctx, const Expr *E) const {
  switch (Kind) {
  case K_This:
    return Ctx->emitThis(E);
  case K_Field:
    // We're assuming there's a base pointer on the stack already.
    return Ctx->emitGetPtrFieldPop(Offset, E);
  case K_Temp:
    return Ctx->emitGetPtrLocal(Offset, E);
  case K_Decl:
    return Ctx->visitDeclRef(D, E);
  case K_Elem:
    if (!Ctx->emitConstUint32(Offset, E))
      return false;
    return Ctx->emitArrayElemPtrPopUint32(E);
  case K_RVO:
    return Ctx->emitRVOPtr(E);
  case K_InitList:
    return true;
  default:
    llvm_unreachable("Unhandled InitLink kind");
  }
  return true;
}

/// Sets the context for break/continue statements.
template <class Emitter> class LoopScope final {
public:
  using LabelTy = typename Compiler<Emitter>::LabelTy;
  using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
  using LabelInfo = typename Compiler<Emitter>::LabelInfo;

  LoopScope(Compiler<Emitter> *Ctx, const Stmt *Name, LabelTy BreakLabel,
            LabelTy ContinueLabel)
      : Ctx(Ctx) {
#ifndef NDEBUG
    for (const LabelInfo &LI : Ctx->LabelInfoStack)
      assert(LI.Name != Name);
#endif

    this->Ctx->LabelInfoStack.emplace_back(Name, BreakLabel, ContinueLabel,
                                           /*DefaultLabel=*/std::nullopt,
                                           Ctx->VarScope);
  }

  ~LoopScope() { this->Ctx->LabelInfoStack.pop_back(); }

private:
  Compiler<Emitter> *Ctx;
};

// Sets the context for a switch scope, mapping labels.
template <class Emitter> class SwitchScope final {
public:
  using LabelTy = typename Compiler<Emitter>::LabelTy;
  using OptLabelTy = typename Compiler<Emitter>::OptLabelTy;
  using CaseMap = typename Compiler<Emitter>::CaseMap;
  using LabelInfo = typename Compiler<Emitter>::LabelInfo;

  SwitchScope(Compiler<Emitter> *Ctx, const Stmt *Name, CaseMap &&CaseLabels,
              LabelTy BreakLabel, OptLabelTy DefaultLabel)
      : Ctx(Ctx), OldCaseLabels(std::move(this->Ctx->CaseLabels)) {
#ifndef NDEBUG
    for (const LabelInfo &LI : Ctx->LabelInfoStack)
      assert(LI.Name != Name);
#endif

    this->Ctx->CaseLabels = std::move(CaseLabels);
    this->Ctx->LabelInfoStack.emplace_back(Name, BreakLabel,
                                           /*ContinueLabel=*/std::nullopt,
                                           DefaultLabel, Ctx->VarScope);
  }

  ~SwitchScope() {
    this->Ctx->CaseLabels = std::move(OldCaseLabels);
    this->Ctx->LabelInfoStack.pop_back();
  }

private:
  Compiler<Emitter> *Ctx;
  CaseMap OldCaseLabels;
};

template <class Emitter> class StmtExprScope final {
public:
  StmtExprScope(Compiler<Emitter> *Ctx) : Ctx(Ctx), OldFlag(Ctx->InStmtExpr) {
    Ctx->InStmtExpr = true;
  }

  ~StmtExprScope() { Ctx->InStmtExpr = OldFlag; }

private:
  Compiler<Emitter> *Ctx;
  bool OldFlag;
};

/// When generating code for e.g. implicit field initializers in constructors,
/// we don't have anything to point to in case the initializer causes an error.
/// In that case, we need to disable location tracking for the initializer so
/// we later point to the call range instead.
template <class Emitter> class LocOverrideScope final {
public:
  LocOverrideScope(Compiler<Emitter> *Ctx, SourceInfo NewValue,
                   bool Enabled = true)
      : Ctx(Ctx), OldFlag(Ctx->LocOverride), Enabled(Enabled) {

    if (Enabled)
      Ctx->LocOverride = NewValue;
  }

  ~LocOverrideScope() {
    if (Enabled)
      Ctx->LocOverride = OldFlag;
  }

private:
  Compiler<Emitter> *Ctx;
  std::optional<SourceInfo> OldFlag;
  bool Enabled;
};

} // namespace interp
} // namespace clang

template <class Emitter>
bool Compiler<Emitter>::VisitCastExpr(const CastExpr *E) {
  const Expr *SubExpr = E->getSubExpr();

  if (DiscardResult)
    return this->delegate(SubExpr);

  switch (E->getCastKind()) {
  case CK_LValueToRValue: {
    if (ToLValue && E->getType()->isPointerType())
      return this->delegate(SubExpr);

    if (SubExpr->getType().isVolatileQualified())
      return this->emitInvalidCast(CastKind::Volatile, /*Fatal=*/true, E);

    OptPrimType SubExprT = classify(SubExpr->getType());
    // Try to load the value directly. This is purely a performance
    // optimization.
    if (SubExprT) {
      if (const auto *DRE = dyn_cast<DeclRefExpr>(SubExpr)) {
        const ValueDecl *D = DRE->getDecl();
        bool IsReference = D->getType()->isReferenceType();

        if (!IsReference) {
          if (Context::shouldBeGloballyIndexed(D)) {
            if (auto GlobalIndex = P.getGlobal(D))
              return this->emitGetGlobal(*SubExprT, *GlobalIndex, E);
          } else if (auto It = Locals.find(D); It != Locals.end()) {
            return this->emitGetLocal(*SubExprT, It->second.Offset, E);
          } else if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
            if (auto It = this->Params.find(PVD); It != this->Params.end()) {
              return this->emitGetParam(*SubExprT, It->second.Index, E);
            }
          }
        }
      }
    }

    // Prepare storage for the result.
    if (!Initializing && !SubExprT) {
      UnsignedOrNone LocalIndex = allocateLocal(SubExpr);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }

    if (!this->visit(SubExpr))
      return false;

    if (SubExprT)
      return this->emitLoadPop(*SubExprT, E);

    // If the subexpr type is not primitive, we need to perform a copy here.
    // This happens for example in C when dereferencing a pointer of struct
    // type.
    return this->emitMemcpy(E);
  }

  case CK_DerivedToBaseMemberPointer: {
    if (E->containsErrors())
      return false;
    assert(classifyPrim(E) == PT_MemberPtr);
    assert(classifyPrim(SubExpr) == PT_MemberPtr);

    if (!this->delegate(SubExpr))
      return false;

    const CXXRecordDecl *CurDecl = SubExpr->getType()
                                       ->castAs<MemberPointerType>()
                                       ->getMostRecentCXXRecordDecl();
    for (const CXXBaseSpecifier *B : E->path()) {
      const CXXRecordDecl *ToDecl = B->getType()->getAsCXXRecordDecl();
      unsigned DerivedOffset = Ctx.collectBaseOffset(ToDecl, CurDecl);

      if (!this->emitCastMemberPtrBasePop(DerivedOffset, ToDecl, E))
        return false;
      CurDecl = ToDecl;
    }

    return true;
  }

  case CK_BaseToDerivedMemberPointer: {
    if (E->containsErrors())
      return false;
    assert(classifyPrim(E) == PT_MemberPtr);
    assert(classifyPrim(SubExpr) == PT_MemberPtr);

    if (!this->delegate(SubExpr))
      return false;

    const CXXRecordDecl *CurDecl = SubExpr->getType()
                                       ->castAs<MemberPointerType>()
                                       ->getMostRecentCXXRecordDecl();
    // Base-to-derived member pointer casts store the path in derived-to-base
    // order, so iterate backwards. The CXXBaseSpecifier also provides us with
    // the wrong end of the derived->base arc, so stagger the path by one class.
    typedef std::reverse_iterator<CastExpr::path_const_iterator> ReverseIter;
    for (ReverseIter PathI(E->path_end() - 1), PathE(E->path_begin());
         PathI != PathE; ++PathI) {
      const CXXRecordDecl *ToDecl = (*PathI)->getType()->getAsCXXRecordDecl();
      unsigned DerivedOffset = Ctx.collectBaseOffset(CurDecl, ToDecl);

      if (!this->emitCastMemberPtrDerivedPop(-DerivedOffset, ToDecl, E))
        return false;
      CurDecl = ToDecl;
    }

    const CXXRecordDecl *ToDecl =
        E->getType()->castAs<MemberPointerType>()->getMostRecentCXXRecordDecl();
    assert(ToDecl != CurDecl);
    unsigned DerivedOffset = Ctx.collectBaseOffset(CurDecl, ToDecl);

    if (!this->emitCastMemberPtrDerivedPop(-DerivedOffset, ToDecl, E))
      return false;

    return true;
  }

  case CK_UncheckedDerivedToBase:
  case CK_DerivedToBase: {
    if (!this->delegate(SubExpr))
      return false;

    const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {
      if (const auto *PT = dyn_cast<PointerType>(Ty))
        return PT->getPointeeType()->getAsCXXRecordDecl();
      return Ty->getAsCXXRecordDecl();
    };

    // FIXME: We can express a series of non-virtual casts as a single
    // GetPtrBasePop op.
    QualType CurType = SubExpr->getType();
    for (const CXXBaseSpecifier *B : E->path()) {
      if (B->isVirtual()) {
        if (!this->emitGetPtrVirtBasePop(extractRecordDecl(B->getType()), E))
          return false;
        CurType = B->getType();
      } else {
        unsigned DerivedOffset = collectBaseOffset(B->getType(), CurType);
        if (!this->emitGetPtrBasePop(
                DerivedOffset, /*NullOK=*/E->getType()->isPointerType(), E))
          return false;
        CurType = B->getType();
      }
    }

    return true;
  }

  case CK_BaseToDerived: {
    if (!this->delegate(SubExpr))
      return false;
    unsigned DerivedOffset =
        collectBaseOffset(SubExpr->getType(), E->getType());

    const Type *TargetType = E->getType().getTypePtr();
    if (TargetType->isPointerOrReferenceType())
      TargetType = TargetType->getPointeeType().getTypePtr();
    return this->emitGetPtrDerivedPop(DerivedOffset,
                                      /*NullOK=*/E->getType()->isPointerType(),
                                      TargetType, E);
  }

  case CK_FloatingCast: {
    // HLSL uses CK_FloatingCast to cast between vectors.
    if (E->getType()->isVectorType())
      return this->emitVectorConversion(E->getSubExpr(), E);
    if (!SubExpr->getType()->isFloatingType() ||
        !E->getType()->isFloatingType())
      return false;
    if (!this->visit(SubExpr))
      return false;
    const auto *TargetSemantics = &Ctx.getFloatSemantics(E->getType());
    return this->emitCastFP(TargetSemantics, getRoundingMode(E), E);
  }

  case CK_IntegralToFloating: {
    if (E->getType()->isVectorType())
      return this->emitVectorConversion(E->getSubExpr(), E);
    if (!E->getType()->isRealFloatingType())
      return false;
    if (!this->visit(SubExpr))
      return false;
    const auto *TargetSemantics = &Ctx.getFloatSemantics(E->getType());
    return this->emitCastIntegralFloating(classifyPrim(SubExpr),
                                          TargetSemantics, getFPOptions(E), E);
  }

  case CK_FloatingToBoolean: {
    if (E->getType()->isVectorType())
      return this->emitVectorConversion(E->getSubExpr(), E);
    if (!SubExpr->getType()->isRealFloatingType() ||
        !E->getType()->isBooleanType())
      return false;
    if (const auto *FL = dyn_cast<FloatingLiteral>(SubExpr))
      return this->emitConstBool(FL->getValue().isNonZero(), E);
    if (!this->visit(SubExpr))
      return false;
    return this->emitCastFloatingIntegralBool(getFPOptions(E), E);
  }

  case CK_FloatingToIntegral: {
    if (E->getType()->isVectorType())
      return this->emitVectorConversion(E->getSubExpr(), E);
    if (!E->getType()->isIntegralOrEnumerationType())
      return false;
    if (!this->visit(SubExpr))
      return false;
    PrimType ToT = classifyPrim(E);
    if (ToT == PT_IntAP)
      return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(E->getType()),
                                              getFPOptions(E), E);
    if (ToT == PT_IntAPS)
      return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(E->getType()),
                                               getFPOptions(E), E);

    return this->emitCastFloatingIntegral(ToT, getFPOptions(E), E);
  }

  case CK_NullToPointer:
  case CK_NullToMemberPointer: {
    if (!this->discard(SubExpr))
      return false;
    uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType());
    return this->emitNull(classifyPrim(E->getType()), Val,
                          E->getType().getTypePtr(), E);
  }

  case CK_PointerToIntegral: {
    if (!this->visit(SubExpr))
      return false;

    // If SubExpr doesn't result in a pointer, make it one.
    if (PrimType FromT = classifyPrim(SubExpr->getType()); FromT != PT_Ptr) {
      assert(isPtrType(FromT));
      if (!this->emitDecayPtr(FromT, PT_Ptr, E))
        return false;
    }

    PrimType T = classifyPrim(E->getType());
    if (T == PT_IntAP)
      return this->emitCastPointerIntegralAP(Ctx.getBitWidth(E->getType()), E);
    if (T == PT_IntAPS)
      return this->emitCastPointerIntegralAPS(Ctx.getBitWidth(E->getType()), E);
    return this->emitCastPointerIntegral(T, E);
  }

  case CK_ArrayToPointerDecay: {
    if (!this->visit(SubExpr))
      return false;
    return this->emitArrayDecay(E);
  }

  case CK_IntegralToPointer: {
    QualType IntType = SubExpr->getType();
    assert(IntType->isIntegralOrEnumerationType());
    if (!this->visit(SubExpr))
      return false;
    // FIXME: I think the discard is wrong since the int->ptr cast might cause a
    // diagnostic.
    PrimType T = classifyPrim(IntType);
    if (!this->emitGetIntPtr(T, E->getType().getTypePtr(), E))
      return false;

    QualType PtrType = E->getType();
    PrimType DestPtrT = classifyPrim(PtrType);
    if (DestPtrT == PT_Ptr)
      return true;

    // In case we're converting the integer to a non-Pointer.
    return this->emitDecayPtr(PT_Ptr, DestPtrT, E);
  }

  case CK_AtomicToNonAtomic:
  case CK_ConstructorConversion:
  case CK_FunctionToPointerDecay:
  case CK_NonAtomicToAtomic:
  case CK_NoOp:
  case CK_UserDefinedConversion:
  case CK_AddressSpaceConversion:
  case CK_CPointerToObjCPointerCast:
    return this->delegate(SubExpr);

  case CK_BitCast: {
    if (E->containsErrors())
      return false;
    QualType ETy = E->getType();
    // Reject bitcasts to atomic types.
    if (ETy->isAtomicType()) {
      if (!this->discard(SubExpr))
        return false;
      return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, E);
    }
    QualType SubExprTy = SubExpr->getType();
    OptPrimType FromT = classify(SubExprTy);
    // Casts from integer/vector to vector.
    if (E->getType()->isVectorType())
      return this->emitBuiltinBitCast(E);

    OptPrimType ToT = classify(E->getType());
    if (!FromT || !ToT)
      return false;

    assert(isPtrType(*FromT));
    assert(isPtrType(*ToT));
    bool SrcIsVoidPtr = SubExprTy->isVoidPointerType();
    if (FromT == ToT) {
      if (E->getType()->isVoidPointerType() &&
          !SubExprTy->isFunctionPointerType()) {
        return this->delegate(SubExpr);
      }

      if (!this->visit(SubExpr))
        return false;
      if (!this->emitCheckBitCast(ETy->getPointeeType().getTypePtr(),
                                  SrcIsVoidPtr, E))
        return false;

      if (E->getType()->isFunctionPointerType() ||
          SubExprTy->isFunctionPointerType()) {
        return this->emitFnPtrCast(E);
      }
      if (FromT == PT_Ptr)
        return this->emitPtrPtrCast(SubExprTy->isVoidPointerType(), E);
      return true;
    }

    if (!this->visit(SubExpr))
      return false;
    return this->emitDecayPtr(*FromT, *ToT, E);
  }
  case CK_IntegralToBoolean:
  case CK_FixedPointToBoolean: {
    if (E->getType()->isVectorType())
      return this->emitVectorConversion(E->getSubExpr(), E);
    // HLSL uses this to cast to one-element vectors.
    OptPrimType FromT = classify(SubExpr->getType());
    if (!FromT)
      return false;

    if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr))
      return this->emitConst(IL->getValue(), E);
    if (!this->visit(SubExpr))
      return false;
    return this->emitCast(*FromT, classifyPrim(E), E);
  }

  case CK_IntegralCast:
    if (E->getType()->isVectorType())
      return this->emitVectorConversion(E->getSubExpr(), E);
    [[fallthrough]];
  case CK_BooleanToSignedIntegral: {
    OptPrimType FromT = classify(SubExpr->getType());
    OptPrimType ToT = classify(E->getType());
    if (!FromT || !ToT)
      return false;

    // Try to emit a casted known constant value directly.
    if (const auto *IL = dyn_cast<IntegerLiteral>(SubExpr)) {
      if (ToT != PT_IntAP && ToT != PT_IntAPS && FromT != PT_IntAP &&
          FromT != PT_IntAPS && !E->getType()->isEnumeralType())
        return this->emitConst(APSInt(IL->getValue(), !isSignedType(*FromT)),
                               E);
      if (!this->emitConst(IL->getValue(), SubExpr))
        return false;
    } else {
      if (!this->visit(SubExpr))
        return false;
    }

    // Possibly diagnose casts to enum types if the target type does not
    // have a fixed size.
    if (Ctx.getLangOpts().CPlusPlus && E->getType()->isEnumeralType()) {
      const auto *ED = E->getType()->castAsEnumDecl();
      if (!ED->isFixed()) {
        if (!this->emitCheckEnumValue(*FromT, ED, E))
          return false;
      }
    }

    if (ToT == PT_IntAP) {
      if (!this->emitCastAP(*FromT, Ctx.getBitWidth(E->getType()), E))
        return false;
    } else if (ToT == PT_IntAPS) {
      if (!this->emitCastAPS(*FromT, Ctx.getBitWidth(E->getType()), E))
        return false;
    } else {
      if (FromT == ToT)
        return true;
      if (!this->emitCast(*FromT, *ToT, E))
        return false;
    }
    if (E->getCastKind() == CK_BooleanToSignedIntegral)
      return this->emitNeg(*ToT, E);
    return true;
  }

  case CK_PointerToBoolean:
  case CK_MemberPointerToBoolean: {
    PrimType PtrT = classifyPrim(SubExpr->getType());

    if (!this->visit(SubExpr))
      return false;
    return this->emitIsNonNull(PtrT, E);
  }

  case CK_IntegralComplexToBoolean:
  case CK_FloatingComplexToBoolean: {
    if (!this->visit(SubExpr))
      return false;
    return this->emitComplexBoolCast(SubExpr);
  }

  case CK_IntegralComplexToReal:
  case CK_FloatingComplexToReal:
    return this->emitComplexReal(SubExpr);

  case CK_IntegralRealToComplex:
  case CK_FloatingRealToComplex: {
    // We're creating a complex value here, so we need to
    // allocate storage for it.
    if (!Initializing) {
      UnsignedOrNone LocalIndex = allocateTemporary(E);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }

    PrimType T = classifyPrim(SubExpr->getType());
    // Init the complex value to {SubExpr, 0}.
    if (!this->visitArrayElemInit(0, SubExpr, T))
      return false;
    // Zero-init the second element.
    if (!this->visitZeroInitializer(T, SubExpr->getType(), SubExpr))
      return false;
    return this->emitInitElem(T, 1, SubExpr);
  }

  case CK_IntegralComplexCast:
  case CK_FloatingComplexCast:
  case CK_IntegralComplexToFloatingComplex:
  case CK_FloatingComplexToIntegralComplex: {
    assert(E->getType()->isAnyComplexType());
    assert(SubExpr->getType()->isAnyComplexType());
    if (!Initializing) {
      UnsignedOrNone LocalIndex = allocateLocal(E);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }

    // Location for the SubExpr.
    // Since SubExpr is of complex type, visiting it results in a pointer
    // anyway, so we just create a temporary pointer variable.
    unsigned SubExprOffset =
        allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);
    if (!this->visit(SubExpr))
      return false;
    if (!this->emitSetLocal(PT_Ptr, SubExprOffset, E))
      return false;

    PrimType SourceElemT = classifyComplexElementType(SubExpr->getType());
    QualType DestElemType =
        E->getType()->getAs<ComplexType>()->getElementType();
    PrimType DestElemT = classifyPrim(DestElemType);
    // Cast both elements individually.
    for (unsigned I = 0; I != 2; ++I) {
      if (!this->emitGetLocal(PT_Ptr, SubExprOffset, E))
        return false;
      if (!this->emitArrayElemPop(SourceElemT, I, E))
        return false;

      // Do the cast.
      if (!this->emitPrimCast(SourceElemT, DestElemT, DestElemType, E))
        return false;

      // Save the value.
      if (!this->emitInitElem(DestElemT, I, E))
        return false;
    }
    return true;
  }

  case CK_VectorSplat: {
    assert(!canClassify(E->getType()));
    assert(E->getType()->isVectorType());

    if (!canClassify(SubExpr->getType()))
      return false;

    if (!Initializing) {
      UnsignedOrNone LocalIndex = allocateLocal(E);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }

    const auto *VT = E->getType()->getAs<VectorType>();
    PrimType ElemT = classifyPrim(SubExpr->getType());
    unsigned ElemOffset =
        allocateLocalPrimitive(SubExpr, ElemT, /*IsConst=*/true);

    // Prepare a local variable for the scalar value.
    if (!this->visit(SubExpr))
      return false;
    if (classifyPrim(SubExpr) == PT_Ptr && !this->emitLoadPop(ElemT, E))
      return false;

    if (!this->emitSetLocal(ElemT, ElemOffset, E))
      return false;

    for (unsigned I = 0; I != VT->getNumElements(); ++I) {
      if (!this->emitGetLocal(ElemT, ElemOffset, E))
        return false;
      if (!this->emitInitElem(ElemT, I, E))
        return false;
    }

    return true;
  }

  case CK_HLSLVectorTruncation: {
    assert(SubExpr->getType()->isVectorType());
    if (OptPrimType ResultT = classify(E)) {
      assert(!DiscardResult);
      // Result must be either a float or integer. Take the first element.
      if (!this->visit(SubExpr))
        return false;
      return this->emitArrayElemPop(*ResultT, 0, E);
    }
    // Otherwise, this truncates from one vector type to another.
    assert(E->getType()->isVectorType());

    if (!Initializing) {
      UnsignedOrNone LocalIndex = allocateTemporary(E);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }
    unsigned ToSize = E->getType()->getAs<VectorType>()->getNumElements();
    assert(SubExpr->getType()->getAs<VectorType>()->getNumElements() > ToSize);
    if (!this->visit(SubExpr))
      return false;
    return this->emitCopyArray(classifyVectorElementType(E->getType()), 0, 0,
                               ToSize, E);
  };

  case CK_IntegralToFixedPoint: {
    if (!this->visit(SubExpr))
      return false;

    auto Sem =
        Ctx.getASTContext().getFixedPointSemantics(E->getType()).toOpaqueInt();
    if (!this->emitCastIntegralFixedPoint(classifyPrim(SubExpr->getType()), Sem,
                                          E))
      return false;
    if (DiscardResult)
      return this->emitPopFixedPoint(E);
    return true;
  }
  case CK_FloatingToFixedPoint: {
    if (!this->visit(SubExpr))
      return false;

    auto Sem =
        Ctx.getASTContext().getFixedPointSemantics(E->getType()).toOpaqueInt();
    if (!this->emitCastFloatingFixedPoint(Sem, E))
      return false;
    if (DiscardResult)
      return this->emitPopFixedPoint(E);
    return true;
  }
  case CK_FixedPointToFloating: {
    if (!this->visit(SubExpr))
      return false;
    const auto *TargetSemantics = &Ctx.getFloatSemantics(E->getType());
    if (!this->emitCastFixedPointFloating(TargetSemantics, E))
      return false;
    if (DiscardResult)
      return this->emitPopFloat(E);
    return true;
  }
  case CK_FixedPointToIntegral: {
    if (!this->visit(SubExpr))
      return false;
    PrimType IntegralT = classifyPrim(E->getType());
    if (!this->emitCastFixedPointIntegral(IntegralT, E))
      return false;
    if (DiscardResult)
      return this->emitPop(IntegralT, E);
    return true;
  }
  case CK_FixedPointCast: {
    if (!this->visit(SubExpr))
      return false;
    auto Sem =
        Ctx.getASTContext().getFixedPointSemantics(E->getType()).toOpaqueInt();
    if (!this->emitCastFixedPoint(Sem, E))
      return false;
    if (DiscardResult)
      return this->emitPopFixedPoint(E);
    return true;
  }

  case CK_ToVoid:
    return discard(SubExpr);

  case CK_Dynamic:
    // This initially goes through VisitCXXDynamicCastExpr, where we emit
    // a diagnostic if appropriate.
    return this->delegate(SubExpr);

  case CK_LValueBitCast:
    if (!this->emitInvalidCast(CastKind::ReinterpretLike, /*Fatal=*/false, E))
      return false;
    return this->delegate(SubExpr);

  case CK_HLSLArrayRValue: {
    // Non-decaying array rvalue cast - creates an rvalue copy of an lvalue
    // array, similar to LValueToRValue for composite types.
    if (!Initializing) {
      UnsignedOrNone LocalIndex = allocateLocal(E);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }
    if (!this->visit(SubExpr))
      return false;
    return this->emitMemcpy(E);
  }

  case CK_HLSLMatrixTruncation: {
    assert(SubExpr->getType()->isConstantMatrixType());
    if (OptPrimType ResultT = classify(E)) {
      assert(!DiscardResult);
      // Result must be either a float or integer. Take the first element.
      if (!this->visit(SubExpr))
        return false;
      return this->emitArrayElemPop(*ResultT, 0, E);
    }
    // Otherwise, this truncates to a a constant matrix type.
    assert(E->getType()->isConstantMatrixType());

    if (!Initializing) {
      UnsignedOrNone LocalIndex = allocateTemporary(E);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }
    unsigned ToSize =
        E->getType()->getAs<ConstantMatrixType>()->getNumElementsFlattened();
    if (!this->visit(SubExpr))
      return false;
    return this->emitCopyArray(classifyMatrixElementType(SubExpr->getType()), 0,
                               0, ToSize, E);
  }

  case CK_HLSLAggregateSplatCast: {
    // Aggregate splat cast: convert a scalar value to one of an aggregate type
    // by replicating and casting the scalar to every element of the destination
    // aggregate (vector, matrix, array, or struct).
    assert(canClassify(SubExpr->getType()));

    if (!Initializing) {
      UnsignedOrNone LocalIndex = allocateLocal(E);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }

    // The scalar to be splatted is stored in a local to be repeatedly loaded
    // once for every scalar element of the destination.
    PrimType SrcElemT = classifyPrim(SubExpr->getType());
    unsigned SrcOffset =
        allocateLocalPrimitive(SubExpr, SrcElemT, /*IsConst=*/true);

    if (!this->visit(SubExpr))
      return false;
    if (!this->emitSetLocal(SrcElemT, SrcOffset, E))
      return false;

    // Recursively splat the scalar into every element of the destination.
    return emitHLSLAggregateSplat(SrcElemT, SrcOffset, E->getType(), E);
  }

  case CK_HLSLElementwiseCast: {
    // Elementwise cast: flatten the elements of one aggregate source type and
    // store to a destination scalar or aggregate type of the same or fewer
    // number of elements. Casts are inserted element-wise to convert each
    // source scalar element to its corresponding destination scalar element.
    QualType SrcType = SubExpr->getType();
    QualType DestType = E->getType();

    if (OptPrimType DestT = classify(DestType)) {
      // When the destination is a scalar, we only need the first scalar
      // element of the source.
      unsigned SrcPtrOffset =
          allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);
      if (!this->visit(SubExpr))
        return false;
      if (!this->emitSetLocal(PT_Ptr, SrcPtrOffset, E))
        return false;

      SmallVector<HLSLFlatElement, 1> Elements;
      if (!emitHLSLFlattenAggregate(SrcType, SrcPtrOffset, Elements, 1, E))
        return false;
      if (Elements.empty())
        return false;

      const HLSLFlatElement &Src = Elements[0];
      if (!this->emitGetLocal(Src.Type, Src.LocalOffset, E))
        return false;
      return this->emitPrimCast(Src.Type, *DestT, DestType, E);
    }

    if (!Initializing) {
      UnsignedOrNone LocalIndex = allocateLocal(E);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }

    unsigned SrcOffset =
        allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);
    if (!this->visit(SubExpr))
      return false;
    if (!this->emitSetLocal(PT_Ptr, SrcOffset, E))
      return false;

    // Only flatten as many source elements as the destination requires.
    unsigned ElemCount = countHLSLFlatElements(DestType);

    SmallVector<HLSLFlatElement, 16> Elements;
    Elements.reserve(ElemCount);
    if (!emitHLSLFlattenAggregate(SrcType, SrcOffset, Elements, ElemCount, E))
      return false;

    // Sema is expected to reject an elementwise cast whose source has fewer
    // scalar elements than the destination.
    assert(Elements.size() == ElemCount &&
           "Source type has fewer scalar elements than the destination type");

    return emitHLSLConstructAggregate(DestType, Elements, E);
  }

  case CK_ToUnion: {
    const FieldDecl *UnionField = E->getTargetUnionField();
    const Record *R = this->getRecord(E->getType());
    assert(R);
    const Record::Field *RF = R->getField(UnionField);
    QualType FieldType = RF->Decl->getType();

    if (OptPrimType PT = classify(FieldType)) {
      if (!this->visit(SubExpr))
        return false;
      if (RF->isBitField())
        return this->emitInitBitFieldActivate(*PT, RF->Offset, RF->bitWidth(),
                                              E);
      return this->emitInitFieldActivate(*PT, RF->Offset, E);
    }

    if (!this->emitGetPtrField(RF->Offset, E))
      return false;
    if (!this->emitActivate(E))
      return false;
    return this->visitInitializerPop(SubExpr);
  }

  default:
    return this->emitInvalid(E);
  }
  llvm_unreachable("Unhandled clang::CastKind enum");
}

template <class Emitter>
bool Compiler<Emitter>::VisitBuiltinBitCastExpr(const BuiltinBitCastExpr *E) {
  return this->emitBuiltinBitCast(E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitIntegerLiteral(const IntegerLiteral *LE) {
  if (DiscardResult)
    return true;

  return this->emitConst(LE->getValue(), LE);
}

template <class Emitter>
bool Compiler<Emitter>::VisitFloatingLiteral(const FloatingLiteral *E) {
  if (DiscardResult)
    return true;

  APFloat F = E->getValue();
  return this->emitFloat(F, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitImaginaryLiteral(const ImaginaryLiteral *E) {
  assert(E->getType()->isAnyComplexType());
  if (DiscardResult)
    return true;

  if (!Initializing) {
    UnsignedOrNone LocalIndex = allocateTemporary(E);
    if (!LocalIndex)
      return false;
    if (!this->emitGetPtrLocal(*LocalIndex, E))
      return false;
  }

  const Expr *SubExpr = E->getSubExpr();
  PrimType SubExprT = classifyPrim(SubExpr->getType());

  if (!this->visitZeroInitializer(SubExprT, SubExpr->getType(), SubExpr))
    return false;
  if (!this->emitInitElem(SubExprT, 0, SubExpr))
    return false;
  return this->visitArrayElemInit(1, SubExpr, SubExprT);
}

template <class Emitter>
bool Compiler<Emitter>::VisitFixedPointLiteral(const FixedPointLiteral *E) {
  assert(E->getType()->isFixedPointType());
  assert(classifyPrim(E) == PT_FixedPoint);

  if (DiscardResult)
    return true;

  auto Sem = Ctx.getASTContext().getFixedPointSemantics(E->getType());
  APInt Value = E->getValue();
  return this->emitConstFixedPoint(FixedPoint(Value, Sem), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitParenExpr(const ParenExpr *E) {
  return this->delegate(E->getSubExpr());
}

template <class Emitter>
bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *E) {
  // Need short-circuiting for these.
  if (E->isLogicalOp() && !E->getType()->isVectorType())
    return this->VisitLogicalBinOp(E);

  const Expr *LHS = E->getLHS();
  const Expr *RHS = E->getRHS();

  // Handle comma operators. Just discard the LHS
  // and delegate to RHS.
  if (E->isCommaOp()) {
    if (!this->discard(LHS))
      return false;
    if (RHS->getType()->isVoidType())
      return this->discard(RHS);

    return this->delegate(RHS);
  }

  if (E->getType()->isAnyComplexType())
    return this->VisitComplexBinOp(E);
  if (E->getType()->isVectorType())
    return this->VisitVectorBinOp(E);
  if ((LHS->getType()->isAnyComplexType() ||
       RHS->getType()->isAnyComplexType()) &&
      E->isComparisonOp())
    return this->emitComplexComparison(LHS, RHS, E);
  if (LHS->getType()->isFixedPointType() || RHS->getType()->isFixedPointType())
    return this->VisitFixedPointBinOp(E);

  if (E->isPtrMemOp()) {
    if (E->containsErrors())
      return false;

    if (!this->visit(LHS))
      return false;

    if (!this->visit(RHS))
      return false;

    if (!this->emitToMemberPtr(E))
      return false;

    if (classifyPrim(E) == PT_MemberPtr)
      return true;

    if (!this->emitCastMemberPtrPtr(E))
      return false;
    return DiscardResult ? this->emitPopPtr(E) : true;
  }

  // Typecheck the args.
  OptPrimType LT = classify(LHS);
  OptPrimType RT = classify(RHS);
  OptPrimType T = classify(E->getType());

  // Special case for C++'s three-way/spaceship operator <=>, which
  // returns a std::{strong,weak,partial}_ordering (which is a class, so doesn't
  // have a PrimType).
  if (!T && E->getOpcode() == BO_Cmp) {
    if (DiscardResult)
      return true;
    const ComparisonCategoryInfo *CmpInfo =
        Ctx.getASTContext().CompCategories.lookupInfoForType(E->getType());
    assert(CmpInfo);

    // We need a temporary variable holding our return value.
    if (!Initializing) {
      UnsignedOrNone ResultIndex = this->allocateLocal(E);
      if (!this->emitGetPtrLocal(*ResultIndex, E))
        return false;
    }

    if (!visit(LHS) || !visit(RHS))
      return false;

    return this->emitCMP3(*LT, CmpInfo, E);
  }

  if (!LT || !RT || !T)
    return false;

  // Pointer arithmetic special case.
  if (E->getOpcode() == BO_Add || E->getOpcode() == BO_Sub) {
    if (isPtrType(*T) || (isPtrType(*LT) && isPtrType(*RT)))
      return this->VisitPointerArithBinOp(E);
  }

  if (E->getOpcode() == BO_Assign)
    return this->visitAssignment(LHS, RHS, E);

  if (!visit(LHS) || !visit(RHS))
    return false;

  // For languages such as C, cast the result of one
  // of our comparision opcodes to T (which is usually int).
  auto MaybeCastToBool = [this, T, E](bool Result) {
    if (!Result)
      return false;
    if (DiscardResult)
      return this->emitPopBool(E);
    if (T != PT_Bool)
      return this->emitCast(PT_Bool, *T, E);
    return true;
  };

  auto Discard = [this, T, E](bool Result) {
    if (!Result)
      return false;
    return DiscardResult ? this->emitPop(*T, E) : true;
  };

  switch (E->getOpcode()) {
  case BO_EQ:
    return MaybeCastToBool(this->emitEQ(*LT, E));
  case BO_NE:
    return MaybeCastToBool(this->emitNE(*LT, E));
  case BO_LT:
    return MaybeCastToBool(this->emitLT(*LT, E));
  case BO_LE:
    return MaybeCastToBool(this->emitLE(*LT, E));
  case BO_GT:
    return MaybeCastToBool(this->emitGT(*LT, E));
  case BO_GE:
    return MaybeCastToBool(this->emitGE(*LT, E));
  case BO_Sub:
    if (E->getType()->isFloatingType())
      return Discard(this->emitSubf(getFPOptions(E), E));
    return Discard(this->emitSub(*T, E));
  case BO_Add:
    if (E->getType()->isFloatingType())
      return Discard(this->emitAddf(getFPOptions(E), E));
    return Discard(this->emitAdd(*T, E));
  case BO_Mul:
    if (E->getType()->isFloatingType())
      return Discard(this->emitMulf(getFPOptions(E), E));
    return Discard(this->emitMul(*T, E));
  case BO_Rem:
    return Discard(this->emitRem(*T, E));
  case BO_Div:
    if (E->getType()->isFloatingType())
      return Discard(this->emitDivf(getFPOptions(E), E));
    return Discard(this->emitDiv(*T, E));
  case BO_And:
    return Discard(this->emitBitAnd(*T, E));
  case BO_Or:
    return Discard(this->emitBitOr(*T, E));
  case BO_Shl:
    return Discard(this->emitShl(*LT, *RT, E));
  case BO_Shr:
    return Discard(this->emitShr(*LT, *RT, E));
  case BO_Xor:
    return Discard(this->emitBitXor(*T, E));
  case BO_LOr:
  case BO_LAnd:
    llvm_unreachable("Already handled earlier");
  default:
    return false;
  }

  llvm_unreachable("Unhandled binary op");
}

/// Perform addition/subtraction of a pointer and an integer or
/// subtraction of two pointers.
template <class Emitter>
bool Compiler<Emitter>::VisitPointerArithBinOp(const BinaryOperator *E) {
  BinaryOperatorKind Op = E->getOpcode();
  const Expr *LHS = E->getLHS();
  const Expr *RHS = E->getRHS();

  if ((Op != BO_Add && Op != BO_Sub) ||
      (!LHS->getType()->isPointerType() && !RHS->getType()->isPointerType()))
    return false;

  OptPrimType LT = classify(LHS);
  OptPrimType RT = classify(RHS);

  if (!LT || !RT)
    return false;

  // Visit the given pointer expression and optionally convert to a PT_Ptr.
  auto visitAsPointer = [&](const Expr *E, PrimType T) -> bool {
    if (!this->visit(E))
      return false;
    if (T != PT_Ptr)
      return this->emitDecayPtr(T, PT_Ptr, E);
    return true;
  };

  if (LHS->getType()->isPointerType() && RHS->getType()->isPointerType()) {
    if (Op != BO_Sub)
      return false;

    assert(E->getType()->isIntegerType());
    if (!visitAsPointer(RHS, *RT) || !visitAsPointer(LHS, *LT))
      return false;

    QualType ElemType = LHS->getType()->getPointeeType();
    CharUnits ElemTypeSize;
    if (ElemType->isVoidType() || ElemType->isFunctionType())
      ElemTypeSize = CharUnits::One();
    else
      ElemTypeSize = Ctx.getASTContext().getTypeSizeInChars(ElemType);

    PrimType IntT = classifyPrim(E->getType());
    if (!this->emitSubPtr(IntT, ElemTypeSize.isZero(), E))
      return false;
    return DiscardResult ? this->emitPop(IntT, E) : true;
  }

  PrimType OffsetType;
  if (LHS->getType()->isIntegerType()) {
    if (!visitAsPointer(RHS, *RT))
      return false;
    if (!this->visit(LHS))
      return false;
    OffsetType = *LT;
  } else if (RHS->getType()->isIntegerType()) {
    if (!visitAsPointer(LHS, *LT))
      return false;
    if (!this->visit(RHS))
      return false;
    OffsetType = *RT;
  } else {
    return false;
  }

  // Do the operation and optionally transform to
  // result pointer type.
  switch (Op) {
  case BO_Add:
    if (!this->emitAddOffset(OffsetType, E))
      return false;
    break;
  case BO_Sub:
    if (!this->emitSubOffset(OffsetType, E))
      return false;
    break;
  default:
    return false;
  }

  if (classifyPrim(E) != PT_Ptr) {
    if (!this->emitDecayPtr(PT_Ptr, classifyPrim(E), E))
      return false;
  }

  if (DiscardResult)
    return this->emitPop(classifyPrim(E), E);
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitLogicalBinOp(const BinaryOperator *E) {
  assert(E->isLogicalOp());
  BinaryOperatorKind Op = E->getOpcode();
  const Expr *LHS = E->getLHS();
  const Expr *RHS = E->getRHS();
  OptPrimType T = classify(E->getType());

  if (Op == BO_LOr) {
    // Logical OR. Visit LHS and only evaluate RHS if LHS was FALSE.
    LabelTy LabelTrue = this->getLabel();
    LabelTy LabelEnd = this->getLabel();

    if (!this->visitBool(LHS))
      return false;
    if (!this->jumpTrue(LabelTrue, E))
      return false;

    if (!this->visitBool(RHS))
      return false;
    if (!this->jump(LabelEnd, E))
      return false;

    this->emitLabel(LabelTrue);
    this->emitConstBool(true, E);
    this->fallthrough(LabelEnd);
    this->emitLabel(LabelEnd);

  } else {
    assert(Op == BO_LAnd);
    // Logical AND.
    // Visit LHS. Only visit RHS if LHS was TRUE.
    LabelTy LabelFalse = this->getLabel();
    LabelTy LabelEnd = this->getLabel();

    if (!this->visitBool(LHS))
      return false;
    if (!this->jumpFalse(LabelFalse, E))
      return false;

    if (!this->visitBool(RHS))
      return false;
    if (!this->jump(LabelEnd, E))
      return false;

    this->emitLabel(LabelFalse);
    this->emitConstBool(false, E);
    this->fallthrough(LabelEnd);
    this->emitLabel(LabelEnd);
  }

  if (DiscardResult)
    return this->emitPopBool(E);

  // For C, cast back to integer type.
  assert(T);
  if (T != PT_Bool)
    return this->emitCast(PT_Bool, *T, E);
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
  // Prepare storage for result.
  if (!Initializing) {
    UnsignedOrNone LocalIndex = allocateTemporary(E);
    if (!LocalIndex)
      return false;
    if (!this->emitGetPtrLocal(*LocalIndex, E))
      return false;
  }

  // Both LHS and RHS might _not_ be of complex type, but one of them
  // needs to be.
  const Expr *LHS = E->getLHS();
  const Expr *RHS = E->getRHS();

  PrimType ResultElemT = this->classifyComplexElementType(E->getType());
  unsigned ResultOffset = ~0u;
  if (!DiscardResult)
    ResultOffset = this->allocateLocalPrimitive(E, PT_Ptr, /*IsConst=*/true);

  // Save result pointer in ResultOffset
  if (!this->DiscardResult) {
    if (!this->emitDupPtr(E))
      return false;
    if (!this->emitSetLocal(PT_Ptr, ResultOffset, E))
      return false;
  }
  QualType LHSType = LHS->getType();
  if (const auto *AT = LHSType->getAs<AtomicType>())
    LHSType = AT->getValueType();
  QualType RHSType = RHS->getType();
  if (const auto *AT = RHSType->getAs<AtomicType>())
    RHSType = AT->getValueType();

  bool LHSIsComplex = LHSType->isAnyComplexType();
  unsigned LHSOffset;
  bool RHSIsComplex = RHSType->isAnyComplexType();

  // For ComplexComplex Mul, we have special ops to make their implementation
  // easier.
  BinaryOperatorKind Op = E->getOpcode();
  if (Op == BO_Mul && LHSIsComplex && RHSIsComplex) {
    assert(classifyPrim(LHSType->getAs<ComplexType>()->getElementType()) ==
           classifyPrim(RHSType->getAs<ComplexType>()->getElementType()));
    PrimType ElemT =
        classifyPrim(LHSType->getAs<ComplexType>()->getElementType());
    if (!this->visit(LHS))
      return false;
    if (!this->visit(RHS))
      return false;
    if (!this->emitMulc(ElemT, E))
      return false;
    if (DiscardResult)
      return this->emitPopPtr(E);
    return true;
  }

  if (Op == BO_Div && RHSIsComplex) {
    QualType ElemQT = RHSType->getAs<ComplexType>()->getElementType();
    PrimType ElemT = classifyPrim(ElemQT);
    // If the LHS is not complex, we still need to do the full complex
    // division, so just stub create a complex value and stub it out with
    // the LHS and a zero.

    if (!LHSIsComplex) {
      // This is using the RHS type for the fake-complex LHS.
      UnsignedOrNone LocalIndex = allocateTemporary(RHS);
      if (!LocalIndex)
        return false;
      LHSOffset = *LocalIndex;

      if (!this->emitGetPtrLocal(LHSOffset, E))
        return false;

      if (!this->visit(LHS))
        return false;
      // real is LHS
      if (!this->emitInitElem(ElemT, 0, E))
        return false;
      // imag is zero
      if (!this->visitZeroInitializer(ElemT, ElemQT, E))
        return false;
      if (!this->emitInitElem(ElemT, 1, E))
        return false;
    } else {
      if (!this->visit(LHS))
        return false;
    }

    if (!this->visit(RHS))
      return false;
    if (!this->emitDivc(ElemT, E))
      return false;
    if (DiscardResult)
      return this->emitPopPtr(E);
    return true;
  }

  // Evaluate LHS and save value to LHSOffset.
  if (LHSType->isAnyComplexType()) {
    LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);
    if (!this->visit(LHS))
      return false;
    if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
      return false;
  } else {
    PrimType LHST = classifyPrim(LHSType);
    LHSOffset = this->allocateLocalPrimitive(LHS, LHST, /*IsConst=*/true);
    if (!this->visit(LHS))
      return false;
    if (!this->emitSetLocal(LHST, LHSOffset, E))
      return false;
  }

  // Same with RHS.
  unsigned RHSOffset;
  if (RHSType->isAnyComplexType()) {
    RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);
    if (!this->visit(RHS))
      return false;
    if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
      return false;
  } else {
    PrimType RHST = classifyPrim(RHSType);
    RHSOffset = this->allocateLocalPrimitive(RHS, RHST, /*IsConst=*/true);
    if (!this->visit(RHS))
      return false;
    if (!this->emitSetLocal(RHST, RHSOffset, E))
      return false;
  }

  // For both LHS and RHS, either load the value from the complex pointer, or
  // directly from the local variable. For index 1 (i.e. the imaginary part),
  // just load 0 and do the operation anyway.
  auto loadComplexValue = [this](bool IsComplex, bool LoadZero,
                                 unsigned ElemIndex, unsigned Offset,
                                 const Expr *E) -> bool {
    if (IsComplex) {
      if (!this->emitGetLocal(PT_Ptr, Offset, E))
        return false;
      return this->emitArrayElemPop(classifyComplexElementType(E->getType()),
                                    ElemIndex, E);
    }
    if (ElemIndex == 0 || !LoadZero)
      return this->emitGetLocal(classifyPrim(E->getType()), Offset, E);
    return this->visitZeroInitializer(classifyPrim(E->getType()), E->getType(),
                                      E);
  };

  // Now we can get pointers to the LHS and RHS from the offsets above.
  for (unsigned ElemIndex = 0; ElemIndex != 2; ++ElemIndex) {
    // Result pointer for the store later.
    if (!this->DiscardResult) {
      if (!this->emitGetLocal(PT_Ptr, ResultOffset, E))
        return false;
    }

    // The actual operation.
    switch (Op) {
    case BO_Add:
      if (!loadComplexValue(LHSIsComplex, true, ElemIndex, LHSOffset, LHS))
        return false;

      if (!loadComplexValue(RHSIsComplex, true, ElemIndex, RHSOffset, RHS))
        return false;
      if (ResultElemT == PT_Float) {
        if (!this->emitAddf(getFPOptions(E), E))
          return false;
      } else {
        if (!this->emitAdd(ResultElemT, E))
          return false;
      }
      break;
    case BO_Sub:
      if (!loadComplexValue(LHSIsComplex, true, ElemIndex, LHSOffset, LHS))
        return false;

      if (!loadComplexValue(RHSIsComplex, true, ElemIndex, RHSOffset, RHS))
        return false;
      if (ResultElemT == PT_Float) {
        if (!this->emitSubf(getFPOptions(E), E))
          return false;
      } else {
        if (!this->emitSub(ResultElemT, E))
          return false;
      }
      break;
    case BO_Mul:
      if (!loadComplexValue(LHSIsComplex, false, ElemIndex, LHSOffset, LHS))
        return false;

      if (!loadComplexValue(RHSIsComplex, false, ElemIndex, RHSOffset, RHS))
        return false;

      if (ResultElemT == PT_Float) {
        if (!this->emitMulf(getFPOptions(E), E))
          return false;
      } else {
        if (!this->emitMul(ResultElemT, E))
          return false;
      }
      break;
    case BO_Div:
      assert(!RHSIsComplex);
      if (!loadComplexValue(LHSIsComplex, false, ElemIndex, LHSOffset, LHS))
        return false;

      if (!loadComplexValue(RHSIsComplex, false, ElemIndex, RHSOffset, RHS))
        return false;

      if (ResultElemT == PT_Float) {
        if (!this->emitDivf(getFPOptions(E), E))
          return false;
      } else {
        if (!this->emitDiv(ResultElemT, E))
          return false;
      }
      break;

    default:
      return false;
    }

    if (!this->DiscardResult) {
      // Initialize array element with the value we just computed.
      if (!this->emitInitElemPop(ResultElemT, ElemIndex, E))
        return false;
    } else {
      if (!this->emitPop(ResultElemT, E))
        return false;
      // Remove the Complex temporary pointer we created ourselves at the
      // beginning of this function.
      if (!Initializing)
        return this->emitPopPtr(E);
    }
  }
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
  const Expr *LHS = E->getLHS();
  const Expr *RHS = E->getRHS();
  assert(!E->isCommaOp() &&
         "Comma op should be handled in VisitBinaryOperator");
  assert(E->getType()->isVectorType());
  assert(LHS->getType()->isVectorType());
  assert(RHS->getType()->isVectorType());

  // We can only handle vectors with primitive element types.
  if (!canClassify(LHS->getType()->castAs<VectorType>()->getElementType()))
    return false;

  // Prepare storage for result.
  if (!Initializing && !E->isCompoundAssignmentOp() && !E->isAssignmentOp()) {
    UnsignedOrNone LocalIndex = allocateTemporary(E);
    if (!LocalIndex)
      return false;
    if (!this->emitGetPtrLocal(*LocalIndex, E))
      return false;
  }

  const auto *VecTy = E->getType()->getAs<VectorType>();
  auto Op = E->isCompoundAssignmentOp()
                ? BinaryOperator::getOpForCompoundAssignment(E->getOpcode())
                : E->getOpcode();

  PrimType ElemT = this->classifyVectorElementType(LHS->getType());
  PrimType RHSElemT = this->classifyVectorElementType(RHS->getType());
  PrimType ResultElemT = this->classifyVectorElementType(E->getType());

  if (E->getOpcode() == BO_Assign) {
    assert(Ctx.getASTContext().hasSameUnqualifiedType(
        LHS->getType()->castAs<VectorType>()->getElementType(),
        RHS->getType()->castAs<VectorType>()->getElementType()));
    if (!this->visit(LHS))
      return false;
    if (!this->visit(RHS))
      return false;
    if (!this->emitCopyArray(ElemT, 0, 0, VecTy->getNumElements(), E))
      return false;
    if (DiscardResult)
      return this->emitPopPtr(E);
    return true;
  }

  // Evaluate LHS and save value to LHSOffset.
  unsigned LHSOffset =
      this->allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);
  if (!this->visit(LHS))
    return false;
  if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
    return false;

  // Evaluate RHS and save value to RHSOffset.
  unsigned RHSOffset =
      this->allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);
  if (!this->visit(RHS))
    return false;
  if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
    return false;

  if (E->isCompoundAssignmentOp() && !this->emitGetLocal(PT_Ptr, LHSOffset, E))
    return false;

  // BitAdd/BitOr/BitXor/Shl/Shr doesn't support bool type, we need perform the
  // integer promotion.
  bool NeedIntPromot = ElemT == PT_Bool && (E->isBitwiseOp() || E->isShiftOp());
  QualType PromotTy;
  PrimType PromotT = PT_Bool;
  PrimType OpT = ElemT;
  if (NeedIntPromot) {
    PromotTy =
        Ctx.getASTContext().getPromotedIntegerType(Ctx.getASTContext().BoolTy);
    PromotT = classifyPrim(PromotTy);
    OpT = PromotT;
  }

  auto getElem = [=](unsigned Offset, PrimType ElemT, unsigned Index) {
    if (!this->emitGetLocal(PT_Ptr, Offset, E))
      return false;
    if (!this->emitArrayElemPop(ElemT, Index, E))
      return false;
    if (E->isLogicalOp()) {
      if (!this->emitPrimCast(ElemT, PT_Bool, Ctx.getASTContext().BoolTy, E))
        return false;
      if (!this->emitPrimCast(PT_Bool, ResultElemT, VecTy->getElementType(), E))
        return false;
    } else if (NeedIntPromot) {
      if (!this->emitPrimCast(ElemT, PromotT, PromotTy, E))
        return false;
    }
    return true;
  };

#define EMIT_ARITH_OP(OP)                                                      \
  {                                                                            \
    if (ElemT == PT_Float) {                                                   \
      if (!this->emit##OP##f(getFPOptions(E), E))                              \
        return false;                                                          \
    } else {                                                                   \
      if (!this->emit##OP(ElemT, E))                                           \
        return false;                                                          \
    }                                                                          \
    break;                                                                     \
  }

  for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {
    if (!getElem(LHSOffset, ElemT, I))
      return false;
    if (!getElem(RHSOffset, RHSElemT, I))
      return false;
    switch (Op) {
    case BO_Add:
      EMIT_ARITH_OP(Add)
    case BO_Sub:
      EMIT_ARITH_OP(Sub)
    case BO_Mul:
      EMIT_ARITH_OP(Mul)
    case BO_Div:
      EMIT_ARITH_OP(Div)
    case BO_Rem:
      if (!this->emitRem(ElemT, E))
        return false;
      break;
    case BO_And:
      if (!this->emitBitAnd(OpT, E))
        return false;
      break;
    case BO_Or:
      if (!this->emitBitOr(OpT, E))
        return false;
      break;
    case BO_Xor:
      if (!this->emitBitXor(OpT, E))
        return false;
      break;
    case BO_Shl:
      if (!this->emitShl(OpT, RHSElemT, E))
        return false;
      break;
    case BO_Shr:
      if (!this->emitShr(OpT, RHSElemT, E))
        return false;
      break;
    case BO_EQ:
      if (!this->emitEQ(ElemT, E))
        return false;
      break;
    case BO_NE:
      if (!this->emitNE(ElemT, E))
        return false;
      break;
    case BO_LE:
      if (!this->emitLE(ElemT, E))
        return false;
      break;
    case BO_LT:
      if (!this->emitLT(ElemT, E))
        return false;
      break;
    case BO_GE:
      if (!this->emitGE(ElemT, E))
        return false;
      break;
    case BO_GT:
      if (!this->emitGT(ElemT, E))
        return false;
      break;
    case BO_LAnd:
      // a && b is equivalent to a!=0 & b!=0
      if (!this->emitBitAnd(ResultElemT, E))
        return false;
      break;
    case BO_LOr:
      // a || b is equivalent to a!=0 | b!=0
      if (!this->emitBitOr(ResultElemT, E))
        return false;
      break;
    default:
      return this->emitInvalid(E);
    }

    // The result of the comparison is a vector of the same width and number
    // of elements as the comparison operands with a signed integral element
    // type.
    //
    // https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
    if (E->isComparisonOp()) {
      if (!this->emitPrimCast(PT_Bool, ResultElemT, VecTy->getElementType(), E))
        return false;
      if (!this->emitNeg(ResultElemT, E))
        return false;
    }

    // If we performed an integer promotion, we need to cast the compute result
    // into result vector element type.
    if (NeedIntPromot &&
        !this->emitPrimCast(PromotT, ResultElemT, VecTy->getElementType(), E))
      return false;

    // Initialize array element with the value we just computed.
    if (!this->emitInitElem(ResultElemT, I, E))
      return false;
  }

  if (DiscardResult && E->isCompoundAssignmentOp() && !this->emitPopPtr(E))
    return false;
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitFixedPointBinOp(const BinaryOperator *E) {
  const Expr *LHS = E->getLHS();
  const Expr *RHS = E->getRHS();
  const ASTContext &ASTCtx = Ctx.getASTContext();

  assert(LHS->getType()->isFixedPointType() ||
         RHS->getType()->isFixedPointType());

  auto LHSSema = ASTCtx.getFixedPointSemantics(LHS->getType());
  auto LHSSemaInt = LHSSema.toOpaqueInt();
  auto RHSSema = ASTCtx.getFixedPointSemantics(RHS->getType());
  auto RHSSemaInt = RHSSema.toOpaqueInt();

  if (!this->visit(LHS))
    return false;
  if (!LHS->getType()->isFixedPointType()) {
    if (!this->emitCastIntegralFixedPoint(classifyPrim(LHS->getType()),
                                          LHSSemaInt, E))
      return false;
  }

  if (!this->visit(RHS))
    return false;
  if (!RHS->getType()->isFixedPointType()) {
    if (!this->emitCastIntegralFixedPoint(classifyPrim(RHS->getType()),
                                          RHSSemaInt, E))
      return false;
  }

  // Convert the result to the target semantics.
  auto ConvertResult = [&](bool R) -> bool {
    if (!R)
      return false;
    auto ResultSema = ASTCtx.getFixedPointSemantics(E->getType()).toOpaqueInt();
    auto CommonSema = LHSSema.getCommonSemantics(RHSSema).toOpaqueInt();
    if (ResultSema != CommonSema)
      return this->emitCastFixedPoint(ResultSema, E);
    return true;
  };

  auto MaybeCastToBool = [&](bool Result) {
    if (!Result)
      return false;
    PrimType T = classifyPrim(E);
    if (DiscardResult)
      return this->emitPop(T, E);
    if (T != PT_Bool)
      return this->emitCast(PT_Bool, T, E);
    return true;
  };

  switch (E->getOpcode()) {
  case BO_EQ:
    return MaybeCastToBool(this->emitEQFixedPoint(E));
  case BO_NE:
    return MaybeCastToBool(this->emitNEFixedPoint(E));
  case BO_LT:
    return MaybeCastToBool(this->emitLTFixedPoint(E));
  case BO_LE:
    return MaybeCastToBool(this->emitLEFixedPoint(E));
  case BO_GT:
    return MaybeCastToBool(this->emitGTFixedPoint(E));
  case BO_GE:
    return MaybeCastToBool(this->emitGEFixedPoint(E));
  case BO_Add:
    return ConvertResult(this->emitAddFixedPoint(E));
  case BO_Sub:
    return ConvertResult(this->emitSubFixedPoint(E));
  case BO_Mul:
    return ConvertResult(this->emitMulFixedPoint(E));
  case BO_Div:
    return ConvertResult(this->emitDivFixedPoint(E));
  case BO_Shl:
    return ConvertResult(this->emitShiftFixedPoint(/*Left=*/true, E));
  case BO_Shr:
    return ConvertResult(this->emitShiftFixedPoint(/*Left=*/false, E));

  default:
    return this->emitInvalid(E);
  }

  llvm_unreachable("unhandled binop opcode");
}

template <class Emitter>
bool Compiler<Emitter>::VisitFixedPointUnaryOperator(const UnaryOperator *E) {
  const Expr *SubExpr = E->getSubExpr();
  assert(SubExpr->getType()->isFixedPointType());

  switch (E->getOpcode()) {
  case UO_Plus:
    return this->delegate(SubExpr);
  case UO_Minus:
    if (!this->visit(SubExpr))
      return false;
    if (!this->emitNegFixedPoint(E))
      return false;
    if (DiscardResult)
      return this->emitPopFixedPoint(E);
    return true;
  default:
    return false;
  }

  llvm_unreachable("Unhandled unary opcode");
}

template <class Emitter>
bool Compiler<Emitter>::VisitImplicitValueInitExpr(
    const ImplicitValueInitExpr *E) {
  if (DiscardResult)
    return true;

  QualType QT = E->getType();

  if (OptPrimType T = classify(QT))
    return this->visitZeroInitializer(*T, QT, E);

  if (QT->isRecordType()) {
    const RecordDecl *RD = QT->getAsRecordDecl();
    assert(RD);
    if (RD->isInvalidDecl())
      return false;

    if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(RD);
        CXXRD && CXXRD->getNumVBases() > 0) {
      // TODO: Diagnose.
      return false;
    }

    const Record *R = getRecord(QT);
    if (!R)
      return false;

    assert(Initializing);
    return this->visitZeroRecordInitializer(R, E);
  }

  if (QT->isIncompleteArrayType())
    return true;

  if (QT->isArrayType())
    return this->visitZeroArrayInitializer(QT, E);

  if (const auto *ComplexTy = E->getType()->getAs<ComplexType>()) {
    assert(Initializing);
    QualType ElemQT = ComplexTy->getElementType();
    PrimType ElemT = classifyPrim(ElemQT);
    for (unsigned I = 0; I < 2; ++I) {
      if (!this->visitZeroInitializer(ElemT, ElemQT, E))
        return false;
      if (!this->emitInitElem(ElemT, I, E))
        return false;
    }
    return true;
  }

  if (const auto *VecT = E->getType()->getAs<VectorType>()) {
    unsigned NumVecElements = VecT->getNumElements();
    QualType ElemQT = VecT->getElementType();
    PrimType ElemT = classifyPrim(ElemQT);

    for (unsigned I = 0; I < NumVecElements; ++I) {
      if (!this->visitZeroInitializer(ElemT, ElemQT, E))
        return false;
      if (!this->emitInitElem(ElemT, I, E))
        return false;
    }
    return true;
  }

  if (const auto *MT = E->getType()->getAs<ConstantMatrixType>()) {
    unsigned NumElems = MT->getNumElementsFlattened();
    QualType ElemQT = MT->getElementType();
    PrimType ElemT = classifyPrim(ElemQT);

    for (unsigned I = 0; I != NumElems; ++I) {
      if (!this->visitZeroInitializer(ElemT, ElemQT, E))
        return false;
      if (!this->emitInitElem(ElemT, I, E))
        return false;
    }
    return true;
  }

  return false;
}

template <class Emitter>
bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
  if (E->getType()->isVoidType() || E->containsErrors())
    return false;

  const Expr *LHS = E->getLHS();
  const Expr *RHS = E->getRHS();
  const Expr *Index = E->getIdx();
  const Expr *Base = E->getBase();

  // C++17's rules require us to evaluate the LHS first, regardless of which
  // side is the base.
  bool Success = true;
  for (const Expr *SubExpr : {LHS, RHS}) {
    if (!this->visit(SubExpr)) {
      Success = false;
      continue;
    }

    // Expand the base if this is a subscript on a
    // pointer expression.
    if (SubExpr == Base && Base->getType()->isPointerType()) {
      if (!this->emitExpandPtr(E))
        Success = false;
    }
  }

  if (!Success)
    return false;

  OptPrimType IndexT = classify(Index->getType());
  // In error-recovery cases, the index expression has a dependent type.
  if (!IndexT)
    return this->emitError(E);
  // If the index is first, we need to change that.
  if (LHS == Index) {
    if (!this->emitFlip(PT_Ptr, *IndexT, E))
      return false;
  }

  if (!this->emitArrayElemPtrPop(*IndexT, E))
    return false;
  if (DiscardResult)
    return this->emitPopPtr(E);

  if (E->isGLValue())
    return true;

  OptPrimType T = classifyPrim(E);
  return this->emitLoadPop(*T, E);
}

template <class Emitter>
bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits,
                                      const Expr *ArrayFiller, const Expr *E) {
  InitLinkScope<Emitter> ILS(this, InitLink::InitList());

  QualType QT = E->getType();
  if (const auto *AT = QT->getAs<AtomicType>())
    QT = AT->getValueType();

  if (QT->isVoidType()) {
    if (Inits.size() == 0)
      return true;
    return this->emitInvalid(E);
  }

  // Handle discarding first.
  if (DiscardResult) {
    for (const Expr *Init : Inits) {
      if (!this->discard(Init))
        return false;
    }
    return true;
  }

  // Primitive values.
  if (OptPrimType T = classify(QT)) {
    assert(!DiscardResult);
    if (Inits.size() == 0)
      return this->visitZeroInitializer(*T, QT, E);
    assert(Inits.size() == 1);
    return this->delegate(Inits[0]);
  }

  if (QT->isRecordType()) {
    const Record *R = getRecord(QT);

    if (Inits.size() == 1 && E->getType() == Inits[0]->getType())
      return this->delegate(Inits[0]);

    if (!R)
      return false;

    auto initPrimitiveField = [=](const Record::Field *FieldToInit,
                                  const Expr *Init, PrimType T,
                                  bool Activate = false) -> bool {
      InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(Init));
      if (!this->visit(Init))
        return false;

      bool BitField = FieldToInit->isBitField();
      if (BitField && Activate)
        return this->emitInitBitFieldActivate(T, FieldToInit->Offset,
                                              FieldToInit->bitWidth(), E);
      if (BitField)
        return this->emitInitBitField(T, FieldToInit->Offset,
                                      FieldToInit->bitWidth(), E);
      if (Activate)
        return this->emitInitFieldActivate(T, FieldToInit->Offset, E);
      return this->emitInitField(T, FieldToInit->Offset, E);
    };

    auto initCompositeField = [=](const Record::Field *FieldToInit,
                                  const Expr *Init,
                                  bool Activate = false) -> bool {
      InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(Init));
      InitLinkScope<Emitter> ILS(this, InitLink::Field(FieldToInit->Offset));

      // Non-primitive case. Get a pointer to the field-to-initialize
      // on the stack and recurse into visitInitializer().
      if (!this->emitGetPtrField(FieldToInit->Offset, Init))
        return false;

      if (Activate && !this->emitActivate(E))
        return false;

      return this->visitInitializerPop(Init);
    };

    if (R->isUnion()) {
      if (Inits.size() == 0) {
        if (!this->visitZeroRecordInitializer(R, E))
          return false;
      } else {
        const Expr *Init = Inits[0];
        const FieldDecl *FToInit = nullptr;
        if (const auto *ILE = dyn_cast<InitListExpr>(E))
          FToInit = ILE->getInitializedFieldInUnion();
        else
          FToInit = cast<CXXParenListInitExpr>(E)->getInitializedFieldInUnion();

        const Record::Field *FieldToInit = R->getField(FToInit);
        if (OptPrimType T = classify(Init)) {
          if (!initPrimitiveField(FieldToInit, Init, *T, /*Activate=*/true))
            return false;
        } else {
          if (!initCompositeField(FieldToInit, Init, /*Activate=*/true))
            return false;
        }
      }
      return this->emitFinishInit(E);
    }

    assert(!R->isUnion());
    unsigned InitIndex = 0;
    for (const Expr *Init : Inits) {
      // Skip unnamed bitfields.
      while (InitIndex < R->getNumFields() &&
             R->getField(InitIndex)->isUnnamedBitField())
        ++InitIndex;

      // If this is a child of a DesignatedInitUpdateExpr, skip elements which
      // aren't supposed to be modified.
      if (isa<NoInitExpr>(Init)) {
        ++InitIndex;
        continue;
      }

      if (OptPrimType T = classify(Init)) {
        const Record::Field *FieldToInit = R->getField(InitIndex);
        if (!initPrimitiveField(FieldToInit, Init, *T))
          return false;
        ++InitIndex;
      } else {
        // Initializer for a direct base class.
        if (const Record::Base *B = R->getBase(Init->getType())) {
          if (!this->emitGetPtrBase(B->Offset, Init))
            return false;

          if (!this->visitInitializerPop(Init))
            return false;
          // Base initializers don't increase InitIndex, since they don't count
          // into the Record's fields.
        } else {
          const Record::Field *FieldToInit = R->getField(InitIndex);
          if (!initCompositeField(FieldToInit, Init))
            return false;
          ++InitIndex;
        }
      }
    }
    return this->emitFinishInit(E);
  }

  if (QT->isArrayType()) {
    const ConstantArrayType *CAT =
        Ctx.getASTContext().getAsConstantArrayType(QT);
    uint64_t NumElems = CAT->getZExtSize();

    if (Initializing && !this->emitCheckArrayDestSize(NumElems, E))
      return false;

    if (Inits.size() == 1 && QT == Inits[0]->getType())
      return this->delegate(Inits[0]);

    OptPrimType InitT = classify(CAT->getElementType());
    unsigned ElementIndex = 0;
    for (const Expr *Init : Inits) {
      if (const auto *EmbedS =
              dyn_cast<EmbedExpr>(Init->IgnoreParenImpCasts())) {
        PrimType TargetT = classifyPrim(Init->getType());

        auto Eval = [&](const IntegerLiteral *IL, unsigned ElemIndex) {
          if (TargetT == PT_Float) {
            if (!this->emitConst(IL->getValue(), classifyPrim(IL), Init))
              return false;
            const auto *Sem = &Ctx.getFloatSemantics(CAT->getElementType());
            if (!this->emitCastIntegralFloating(classifyPrim(IL), Sem,
                                                getFPOptions(E), E))
              return false;
          } else {
            if (!this->emitConst(IL->getValue(), TargetT, Init))
              return false;
          }
          return this->emitInitElem(TargetT, ElemIndex, IL);
        };
        if (!EmbedS->doForEachDataElement(Eval, ElementIndex))
          return false;
      } else if (isa<NoInitExpr>(Init)) {
        // If this is a child of a DesignatedInitUpdateExpr, skip elements which
        // aren't supposed to be modified.
        ++ElementIndex;
      } else {
        if (!this->visitArrayElemInit(ElementIndex, Init, InitT))
          return false;
        ++ElementIndex;
      }
    }

    // Expand the filler expression.
    // FIXME: This should go away.
    if (ArrayFiller && !isa<NoInitExpr>(ArrayFiller)) {
      for (; ElementIndex != NumElems; ++ElementIndex) {
        if (!this->visitArrayElemInit(ElementIndex, ArrayFiller, InitT))
          return false;
      }
    }

    return this->emitFinishInit(E);
  }

  if (const auto *ComplexTy = QT->getAs<ComplexType>()) {
    unsigned NumInits = Inits.size();

    if (NumInits == 1)
      return this->delegate(Inits[0]);

    QualType ElemQT = ComplexTy->getElementType();
    PrimType ElemT = classifyPrim(ElemQT);
    if (NumInits == 0) {
      // Zero-initialize both elements.
      for (unsigned I = 0; I < 2; ++I) {
        if (!this->visitZeroInitializer(ElemT, ElemQT, E))
          return false;
        if (!this->emitInitElem(ElemT, I, E))
          return false;
      }
    } else if (NumInits == 2) {
      unsigned InitIndex = 0;
      for (const Expr *Init : Inits) {
        if (!this->visit(Init))
          return false;

        if (!this->emitInitElem(ElemT, InitIndex, E))
          return false;
        ++InitIndex;
      }
    }
    return true;
  }

  if (const auto *VecT = QT->getAs<VectorType>()) {
    unsigned NumVecElements = VecT->getNumElements();
    assert(NumVecElements >= Inits.size());

    QualType ElemQT = VecT->getElementType();
    PrimType ElemT = classifyPrim(ElemQT);

    // All initializer elements.
    unsigned InitIndex = 0;
    for (const Expr *Init : Inits) {
      if (!this->visit(Init))
        return false;

      // If the initializer is of vector type itself, we have to deconstruct
      // that and initialize all the target fields from the initializer fields.
      if (const auto *InitVecT = Init->getType()->getAs<VectorType>()) {
        if (!this->emitCopyArray(ElemT, 0, InitIndex,
                                 InitVecT->getNumElements(), E))
          return false;
        InitIndex += InitVecT->getNumElements();
      } else {
        if (!this->emitInitElem(ElemT, InitIndex, E))
          return false;
        ++InitIndex;
      }
    }

    assert(InitIndex <= NumVecElements);

    // Fill the rest with zeroes.
    for (; InitIndex != NumVecElements; ++InitIndex) {
      if (!this->visitZeroInitializer(ElemT, ElemQT, E))
        return false;
      if (!this->emitInitElem(ElemT, InitIndex, E))
        return false;
    }
    return true;
  }

  if (const auto *MT = QT->getAs<ConstantMatrixType>()) {
    unsigned NumElems = MT->getNumElementsFlattened();
    assert(Inits.size() == NumElems);

    QualType ElemQT = MT->getElementType();
    PrimType ElemT = classifyPrim(ElemQT);

    // Matrix initializer list elements are in row-major order, which matches
    // the matrix APValue convention and therefore no index remapping is
    // required.
    for (unsigned I = 0; I != NumElems; ++I) {
      if (!this->visit(Inits[I]))
        return false;
      if (!this->emitInitElem(ElemT, I, E))
        return false;
    }
    return true;
  }

  return false;
}

/// Pointer to the array(not the element!) must be on the stack when calling
/// this.
template <class Emitter>
bool Compiler<Emitter>::visitArrayElemInit(unsigned ElemIndex, const Expr *Init,
                                           OptPrimType InitT) {
  if (InitT) {
    // Visit the primitive element like normal.
    if (!this->visit(Init))
      return false;
    return this->emitInitElem(*InitT, ElemIndex, Init);
  }

  InitLinkScope<Emitter> ILS(this, InitLink::Elem(ElemIndex));
  // Advance the pointer currently on the stack to the given
  // dimension.
  if (!this->emitConstUint32(ElemIndex, Init))
    return false;
  if (!this->emitArrayElemPtrUint32(Init))
    return false;
  return this->visitInitializerPop(Init);
}

template <class Emitter>
bool Compiler<Emitter>::visitCallArgs(ArrayRef<const Expr *> Args,
                                      const FunctionDecl *FuncDecl,
                                      bool Activate, bool IsOperatorCall) {
  assert(VarScope->getKind() == ScopeKind::Call);
  llvm::BitVector NonNullArgs;
  if (FuncDecl && FuncDecl->hasAttr<NonNullAttr>())
    NonNullArgs = collectNonNullArgs(FuncDecl, Args);

  bool ExplicitMemberFn = false;
  if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(FuncDecl))
    ExplicitMemberFn = MD->isExplicitObjectMemberFunction();

  unsigned ArgIndex = 0;
  for (const Expr *Arg : Args) {
    if (canClassify(Arg)) {
      if (!this->visit(Arg))
        return false;
    } else {

      DeclTy Source = Arg;
      if (FuncDecl) {
        // Try to use the parameter declaration instead of the argument
        // expression as a source.
        unsigned DeclIndex = ArgIndex - IsOperatorCall + ExplicitMemberFn;
        if (DeclIndex < FuncDecl->getNumParams())
          Source = FuncDecl->getParamDecl(ArgIndex - IsOperatorCall +
                                          ExplicitMemberFn);
      }

      UnsignedOrNone LocalIndex =
          allocateLocal(std::move(Source), Arg->getType(), ScopeKind::Call);
      if (!LocalIndex)
        return false;

      if (!this->emitGetPtrLocal(*LocalIndex, Arg))
        return false;
      InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));
      if (!this->visitInitializer(Arg))
        return false;
    }

    if (ArgIndex == 1 && Activate) {
      if (!this->emitActivate(Arg))
        return false;
    }

    if (!NonNullArgs.empty() && NonNullArgs[ArgIndex]) {
      PrimType ArgT = classify(Arg).value_or(PT_Ptr);
      if (ArgT == PT_Ptr) {
        if (!this->emitCheckNonNullArg(ArgT, Arg))
          return false;
      }
    }

    ++ArgIndex;
  }

  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitInitListExpr(const InitListExpr *E) {
  return this->visitInitList(E->inits(), E->getArrayFiller(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXParenListInitExpr(
    const CXXParenListInitExpr *E) {
  return this->visitInitList(E->getInitExprs(), E->getArrayFiller(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitSubstNonTypeTemplateParmExpr(
    const SubstNonTypeTemplateParmExpr *E) {
  return this->delegate(E->getReplacement());
}

template <class Emitter>
bool Compiler<Emitter>::VisitConstantExpr(const ConstantExpr *E) {
  if (!E->hasAPValueResult())
    return this->delegate(E->getSubExpr());

  if (OptPrimType T = classify(E)) {
    // Try to emit the APValue directly, without visiting the subexpr.
    // This will only fail if we can't emit the APValue, so won't emit any
    // diagnostics or any double values.
    if (DiscardResult)
      return true;
    return this->visitAPValue(E->getAPValueResult(), *T, E);
  }

  // Fall back to the subexpr for non-primitive APValues.
  return this->delegate(E->getSubExpr());
}

template <class Emitter>
bool Compiler<Emitter>::VisitEmbedExpr(const EmbedExpr *E) {
  auto It = E->begin();
  return this->visit(*It);
}

static CharUnits AlignOfType(QualType T, const ASTContext &ASTCtx,
                             UnaryExprOrTypeTrait Kind) {
  bool AlignOfReturnsPreferred =
      ASTCtx.getLangOpts().isCompatibleWith(LangOptions::ClangABI::Ver7);

  // C++ [expr.alignof]p3:
  //     When alignof is applied to a reference type, the result is the
  //     alignment of the referenced type.
  if (const auto *Ref = T->getAs<ReferenceType>())
    T = Ref->getPointeeType();

  if (T.getQualifiers().hasUnaligned())
    return CharUnits::One();

  // __alignof is defined to return the preferred alignment.
  // Before 8, clang returned the preferred alignment for alignof and
  // _Alignof as well.
  if (Kind == UETT_PreferredAlignOf || AlignOfReturnsPreferred)
    return ASTCtx.toCharUnitsFromBits(ASTCtx.getPreferredTypeAlign(T));

  return ASTCtx.getTypeAlignInChars(T);
}

template <class Emitter>
bool Compiler<Emitter>::VisitUnaryExprOrTypeTraitExpr(
    const UnaryExprOrTypeTraitExpr *E) {

  UnaryExprOrTypeTrait Kind = E->getKind();
  const ASTContext &ASTCtx = Ctx.getASTContext();

  if (Kind == UETT_SizeOf || Kind == UETT_DataSizeOf) {
    QualType ArgType = E->getTypeOfArgument();

    // C++ [expr.sizeof]p2: "When applied to a reference or a reference type,
    //   the result is the size of the referenced type."
    if (const auto *Ref = ArgType->getAs<ReferenceType>())
      ArgType = Ref->getPointeeType();

    CharUnits Size;
    if (ArgType->isVoidType() || ArgType->isFunctionType())
      Size = CharUnits::One();
    else {
      if (ArgType->isDependentType() || !ArgType->isConstantSizeType())
        return this->emitInvalid(E);

      if (Kind == UETT_SizeOf)
        Size = ASTCtx.getTypeSizeInChars(ArgType);
      else
        Size = ASTCtx.getTypeInfoDataSizeInChars(ArgType).Width;
    }

    if (DiscardResult)
      return true;

    return this->emitConst(Size.getQuantity(), E);
  }

  if (Kind == UETT_CountOf) {
    QualType Ty = E->getTypeOfArgument();
    assert(Ty->isArrayType());

    // We don't need to worry about array element qualifiers, so getting the
    // unsafe array type is fine.
    if (const auto *CAT =
            dyn_cast<ConstantArrayType>(Ty->getAsArrayTypeUnsafe())) {
      if (DiscardResult)
        return true;
      return this->emitConst(CAT->getSize(), E);
    }

    assert(!Ty->isConstantSizeType());

    // If it's a variable-length array type, we need to check whether it is a
    // multidimensional array. If so, we need to check the size expression of
    // the VLA to see if it's a constant size. If so, we can return that value.
    const auto *VAT = ASTCtx.getAsVariableArrayType(Ty);
    assert(VAT);
    if (VAT->getElementType()->isArrayType()) {
      std::optional<APSInt> Res =
          VAT->getSizeExpr()
              ? VAT->getSizeExpr()->getIntegerConstantExpr(ASTCtx)
              : std::nullopt;
      if (Res) {
        if (DiscardResult)
          return true;
        return this->emitConst(*Res, E);
      }
    }
  }

  if (Kind == UETT_AlignOf || Kind == UETT_PreferredAlignOf) {
    CharUnits Size;

    if (E->isArgumentType()) {
      QualType ArgType = E->getTypeOfArgument();

      Size = AlignOfType(ArgType, ASTCtx, Kind);
    } else {
      // Argument is an expression, not a type.
      const Expr *Arg = E->getArgumentExpr()->IgnoreParens();

      if (Arg->getType()->isDependentType())
        return false;

      // The kinds of expressions that we have special-case logic here for
      // should be kept up to date with the special checks for those
      // expressions in Sema.

      // alignof decl is always accepted, even if it doesn't make sense: we
      // default to 1 in those cases.
      if (const auto *DRE = dyn_cast<DeclRefExpr>(Arg))
        Size = ASTCtx.getDeclAlign(DRE->getDecl(),
                                   /*RefAsPointee*/ true);
      else if (const auto *ME = dyn_cast<MemberExpr>(Arg))
        Size = ASTCtx.getDeclAlign(ME->getMemberDecl(),
                                   /*RefAsPointee*/ true);
      else
        Size = AlignOfType(Arg->getType(), ASTCtx, Kind);
    }

    if (DiscardResult)
      return true;

    return this->emitConst(Size.getQuantity(), E);
  }

  if (Kind == UETT_VectorElements) {
    if (E->containsErrors())
      return false;

    if (const auto *VT = E->getTypeOfArgument()->getAs<VectorType>())
      return this->emitConst(VT->getNumElements(), E);
    assert(E->getTypeOfArgument()->isSizelessVectorType());
    return this->emitSizelessVectorElementSize(E);
  }

  if (Kind == UETT_VecStep) {
    if (const auto *VT = E->getTypeOfArgument()->getAs<VectorType>()) {
      unsigned N = VT->getNumElements();

      // The vec_step built-in functions that take a 3-component
      // vector return 4. (OpenCL 1.1 spec 6.11.12)
      if (N == 3)
        N = 4;

      return this->emitConst(N, E);
    }
    return this->emitConst(1, E);
  }

  if (Kind == UETT_OpenMPRequiredSimdAlign) {
    if (E->containsErrors())
      return false;
    assert(E->isArgumentType());
    unsigned Bits = ASTCtx.getOpenMPDefaultSimdAlign(E->getArgumentType());

    return this->emitConst(ASTCtx.toCharUnitsFromBits(Bits).getQuantity(), E);
  }

  if (Kind == UETT_PtrAuthTypeDiscriminator) {
    if (E->getArgumentType()->isDependentType())
      return this->emitInvalid(E);

    return this->emitConst(
        const_cast<ASTContext &>(ASTCtx).getPointerAuthTypeDiscriminator(
            E->getArgumentType()),
        E);
  }

  return false;
}

template <class Emitter>
bool Compiler<Emitter>::VisitMemberExpr(const MemberExpr *E) {
  // 'Base.Member'
  const Expr *Base = E->getBase();
  const ValueDecl *Member = E->getMemberDecl();

  if (DiscardResult)
    return this->discard(Base);

  if (const auto *VD = dyn_cast<VarDecl>(Member)) {
    // I am almost confident in saying that a var decl must be static
    // and therefore registered as a global variable.
    if (auto GlobalIndex = P.getGlobal(VD)) {
      if (!this->emitGetPtrGlobal(*GlobalIndex, E))
        return false;
      if (Member->getType()->isReferenceType())
        return this->emitLoadPopPtr(E);
      return true;
    }
    return false;
  }

  if (!isa<FieldDecl>(Member)) {
    // A non-static member function access only makes sense as part of the
    // enclosing call here. Don't try to evaluate it in isolation.
    if (const auto *MD = dyn_cast<CXXMethodDecl>(Member);
        MD && !MD->isStatic()) {
      return false;
    }

    if (!this->discard(Base) && !this->emitSideEffect(E))
      return false;

    return this->visitDeclRef(Member, E);
  }

  if (!this->visit(Base))
    return false;

  // Base above gives us a pointer on the stack.
  const auto *FD = cast<FieldDecl>(Member);
  const RecordDecl *RD = FD->getParent();
  const Record *R = getRecord(RD);
  if (!R)
    return false;
  const Record::Field *F = R->getField(FD);

  // MemberExprs are almost always lvalues, in which case we don't need to
  // do the load. But sometimes they aren't.
  const auto maybeLoadValue = [&]() -> bool {
    if (E->isGLValue())
      return true;
    if (OptPrimType T = classify(E))
      return this->emitLoadPop(*T, E);
    return false;
  };

  // Leave a pointer to the field on the stack.
  if (F->Decl->getType()->isReferenceType())
    return this->emitGetFieldPop(PT_Ptr, F->Offset, E) && maybeLoadValue();
  return this->emitGetPtrFieldPop(F->Offset, E) && maybeLoadValue();
}

template <class Emitter>
bool Compiler<Emitter>::VisitArrayInitIndexExpr(const ArrayInitIndexExpr *E) {
  assert(!DiscardResult);
  // ArrayIndex might not be set if a ArrayInitIndexExpr is being evaluated
  // stand-alone, e.g. via EvaluateAsInt().
  if (!ArrayIndex)
    return false;
  return this->emitConst(*ArrayIndex, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitArrayInitLoopExpr(const ArrayInitLoopExpr *E) {
  assert(Initializing);
  assert(!DiscardResult);

  const Expr *Common = E->getCommonExpr();
  const Expr *SubExpr = E->getSubExpr();
  OptPrimType SubExprT = classify(SubExpr);
  size_t Size = E->getArraySize().getZExtValue();

  if (SubExprT) {
    // Unwrap the OpaqueValueExpr so we don't cache something we won't reuse.
    Common = cast<OpaqueValueExpr>(Common)->getSourceExpr();

    if (!this->visit(Common))
      return false;
    return this->emitCopyArray(*SubExprT, 0, 0, Size, E);
  }

  // We visit the common opaque expression here once so we have its value
  // cached.
  if (!this->discard(Common))
    return false;

  // TODO: This compiles to quite a lot of bytecode if the array is larger.
  //   Investigate compiling this to a loop.

  // So, every iteration, we execute an assignment here
  // where the LHS is on the stack (the target array)
  // and the RHS is our SubExpr.
  for (size_t I = 0; I != Size; ++I) {
    ArrayIndexScope<Emitter> IndexScope(this, I);
    LocalScope<Emitter> BS(this, ScopeKind::FullExpression);

    if (!this->visitArrayElemInit(I, SubExpr, SubExprT))
      return false;
    if (!BS.destroyLocals())
      return false;
  }
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitOpaqueValueExpr(const OpaqueValueExpr *E) {
  const Expr *SourceExpr = E->getSourceExpr();
  if (!SourceExpr)
    return false;

  if (Initializing) {
    assert(!DiscardResult);
    return this->visitInitializer(SourceExpr);
  }

  PrimType SubExprT = classify(SourceExpr).value_or(PT_Ptr);
  if (auto It = OpaqueExprs.find(E); It != OpaqueExprs.end()) {
    if (DiscardResult)
      return true;
    return this->emitGetLocal(SubExprT, It->second, E);
  }

  if (!this->visit(SourceExpr))
    return false;

  // At this point we either have the evaluated source expression or a pointer
  // to an object on the stack. We want to create a local variable that stores
  // this value.
  unsigned LocalIndex = allocateLocalPrimitive(E, SubExprT, /*IsConst=*/true);
  if (!this->emitSetLocal(SubExprT, LocalIndex, E))
    return false;

  // This is cleaned up when the local variable is destroyed.
  OpaqueExprs.insert({E, LocalIndex});

  // Here the local variable is created but the value is removed from the stack,
  // so we put it back if the caller needs it.
  if (!DiscardResult)
    return this->emitGetLocal(SubExprT, LocalIndex, E);
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitAbstractConditionalOperator(
    const AbstractConditionalOperator *E) {
  const Expr *Condition = E->getCond();
  const Expr *TrueExpr = E->getTrueExpr();
  const Expr *FalseExpr = E->getFalseExpr();

  if (std::optional<bool> BoolValue = getBoolValue(Condition)) {
    if (*BoolValue)
      return this->delegate(TrueExpr);
    return this->delegate(FalseExpr);
  }

  bool IsBcpCall = false;
  if (const auto *CE = dyn_cast<CallExpr>(Condition->IgnoreParenCasts());
      CE && CE->getBuiltinCallee() == Builtin::BI__builtin_constant_p) {
    IsBcpCall = true;
  }

  LabelTy LabelEnd = this->getLabel();   // Label after the operator.
  LabelTy LabelFalse = this->getLabel(); // Label for the false expr.

  if (IsBcpCall) {
    if (!this->emitPushIgnoreDiags(E))
      return false;
  }

  if (!this->visitBool(Condition)) {
    // If the condition failed and we're checking for undefined behavior
    // (which only happens with EvalEmitter) check the TrueExpr and FalseExpr
    // as well.
    if (this->checkingForUndefinedBehavior()) {
      if (!this->discard(TrueExpr))
        return false;
      if (!this->discard(FalseExpr))
        return false;
    }
    return false;
  }

  // Force-init the scope, which creates a InitScope op. This is necessary so
  // the scope is not only initialized in one arm of the conditional operator.
  this->VarScope->forceInit();
  // The TrueExpr and FalseExpr of a conditional operator do _not_ create a
  // scope, which means the local variables created within them unconditionally
  // always exist. However, we need to later differentiate which branch was
  // taken and only destroy the varibles of the active branch. This is what the
  // "enabled" flags on local variables are used for.
  llvm::SaveAndRestore LAAA(this->VarScope->LocalsAlwaysEnabled,
                            /*NewValue=*/false);

  if (!this->jumpFalse(LabelFalse, E))
    return false;
  if (!this->delegate(TrueExpr))
    return false;

  if (!this->jump(LabelEnd, E))
    return false;
  this->emitLabel(LabelFalse);
  if (!this->delegate(FalseExpr))
    return false;

  this->fallthrough(LabelEnd);
  this->emitLabel(LabelEnd);

  if (IsBcpCall)
    return this->emitPopIgnoreDiags(E);
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitStringLiteral(const StringLiteral *E) {
  if (DiscardResult)
    return true;

  if (!Initializing) {
    unsigned StringIndex = P.createGlobalString(E);
    return this->emitGetPtrGlobal(StringIndex, E);
  }

  // We are initializing an array on the stack.
  const ConstantArrayType *CAT =
      Ctx.getASTContext().getAsConstantArrayType(E->getType());
  assert(CAT && "a string literal that's not a constant array?");

  // If the initializer string is too long, a diagnostic has already been
  // emitted. Read only the array length from the string literal.
  unsigned ArraySize = CAT->getZExtSize();
  unsigned N = std::min(ArraySize, E->getLength());
  unsigned CharWidth = E->getCharByteWidth();

  for (unsigned I = 0; I != N; ++I) {
    uint32_t CodeUnit = E->getCodeUnit(I);

    if (CharWidth == 1) {
      this->emitConstSint8(CodeUnit, E);
      this->emitInitElemSint8(I, E);
    } else if (CharWidth == 2) {
      this->emitConstUint16(CodeUnit, E);
      this->emitInitElemUint16(I, E);
    } else if (CharWidth == 4) {
      this->emitConstUint32(CodeUnit, E);
      this->emitInitElemUint32(I, E);
    } else {
      llvm_unreachable("unsupported character width");
    }
  }

  // Fill up the rest of the char array with NUL bytes.
  for (unsigned I = N; I != ArraySize; ++I) {
    if (CharWidth == 1) {
      this->emitConstSint8(0, E);
      this->emitInitElemSint8(I, E);
    } else if (CharWidth == 2) {
      this->emitConstUint16(0, E);
      this->emitInitElemUint16(I, E);
    } else if (CharWidth == 4) {
      this->emitConstUint32(0, E);
      this->emitInitElemUint32(I, E);
    } else {
      llvm_unreachable("unsupported character width");
    }
  }

  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitObjCStringLiteral(const ObjCStringLiteral *E) {
  if (DiscardResult)
    return true;
  return this->emitDummyPtr(E, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitObjCEncodeExpr(const ObjCEncodeExpr *E) {
  auto &A = Ctx.getASTContext();
  std::string Str;
  A.getObjCEncodingForType(E->getEncodedType(), Str);
  StringLiteral *SL =
      StringLiteral::Create(A, Str, StringLiteralKind::Ordinary,
                            /*Pascal=*/false, E->getType(), E->getAtLoc());
  return this->delegate(SL);
}

template <class Emitter>
bool Compiler<Emitter>::VisitSYCLUniqueStableNameExpr(
    const SYCLUniqueStableNameExpr *E) {
  if (DiscardResult)
    return true;

  assert(!Initializing);

  auto &A = Ctx.getASTContext();
  std::string ResultStr = E->ComputeName(A);

  QualType CharTy = A.CharTy.withConst();
  APInt Size(A.getTypeSize(A.getSizeType()), ResultStr.size() + 1);
  QualType ArrayTy = A.getConstantArrayType(CharTy, Size, nullptr,
                                            ArraySizeModifier::Normal, 0);

  StringLiteral *SL =
      StringLiteral::Create(A, ResultStr, StringLiteralKind::Ordinary,
                            /*Pascal=*/false, ArrayTy, E->getLocation());

  unsigned StringIndex = P.createGlobalString(SL);
  return this->emitGetPtrGlobal(StringIndex, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCharacterLiteral(const CharacterLiteral *E) {
  if (DiscardResult)
    return true;
  return this->emitConst(E->getValue(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitFloatCompoundAssignOperator(
    const CompoundAssignOperator *E) {

  const Expr *LHS = E->getLHS();
  const Expr *RHS = E->getRHS();
  QualType LHSType = LHS->getType();
  QualType LHSComputationType = E->getComputationLHSType();
  QualType ResultType = E->getComputationResultType();
  OptPrimType LT = classify(LHSComputationType);
  OptPrimType RT = classify(ResultType);

  assert(ResultType->isFloatingType());

  if (!LT || !RT)
    return false;

  PrimType LHST = classifyPrim(LHSType);

  // C++17 onwards require that we evaluate the RHS first.
  // Compute RHS and save it in a temporary variable so we can
  // load it again later.
  if (!visit(RHS))
    return false;

  unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);
  if (!this->emitSetLocal(*RT, TempOffset, E))
    return false;

  // First, visit LHS.
  if (!visit(LHS))
    return false;
  if (!this->emitLoad(LHST, E))
    return false;

  // If necessary, convert LHS to its computation type.
  if (!this->emitPrimCast(LHST, classifyPrim(LHSComputationType),
                          LHSComputationType, E))
    return false;

  // Now load RHS.
  if (!this->emitGetLocal(*RT, TempOffset, E))
    return false;

  switch (E->getOpcode()) {
  case BO_AddAssign:
    if (!this->emitAddf(getFPOptions(E), E))
      return false;
    break;
  case BO_SubAssign:
    if (!this->emitSubf(getFPOptions(E), E))
      return false;
    break;
  case BO_MulAssign:
    if (!this->emitMulf(getFPOptions(E), E))
      return false;
    break;
  case BO_DivAssign:
    if (!this->emitDivf(getFPOptions(E), E))
      return false;
    break;
  default:
    return false;
  }

  if (!this->emitPrimCast(classifyPrim(ResultType), LHST, LHS->getType(), E))
    return false;

  if (DiscardResult)
    return this->emitStorePop(LHST, E);
  return this->emitStore(LHST, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitPointerCompoundAssignOperator(
    const CompoundAssignOperator *E) {
  BinaryOperatorKind Op = E->getOpcode();
  const Expr *LHS = E->getLHS();
  const Expr *RHS = E->getRHS();
  OptPrimType LT = classify(LHS->getType());
  OptPrimType RT = classify(RHS->getType());

  if (Op != BO_AddAssign && Op != BO_SubAssign)
    return false;

  if (!LT || !RT)
    return false;

  if (!visit(LHS))
    return false;

  if (!this->emitLoad(*LT, LHS))
    return false;

  if (!visit(RHS))
    return false;

  if (Op == BO_AddAssign) {
    if (!this->emitAddOffset(*RT, E))
      return false;
  } else {
    if (!this->emitSubOffset(*RT, E))
      return false;
  }

  if (DiscardResult)
    return this->emitStorePopPtr(E);
  return this->emitStorePtr(E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCompoundAssignOperator(
    const CompoundAssignOperator *E) {
  if (E->getType()->isVectorType())
    return VisitVectorBinOp(E);

  const Expr *LHS = E->getLHS();
  const Expr *RHS = E->getRHS();
  OptPrimType LHSComputationT = classify(E->getComputationLHSType());
  OptPrimType LT = classify(LHS->getType());
  OptPrimType RT = classify(RHS->getType());
  OptPrimType ResultT = classify(E->getType());

  if (!Ctx.getLangOpts().CPlusPlus14)
    return this->visit(RHS) && this->visit(LHS) && this->emitError(E);

  if (!LT || !RT || !ResultT || !LHSComputationT)
    return false;

  // Handle floating point operations separately here, since they
  // require special care.

  if (ResultT == PT_Float || RT == PT_Float)
    return VisitFloatCompoundAssignOperator(E);

  if (E->getType()->isPointerType())
    return VisitPointerCompoundAssignOperator(E);

  assert(!E->getType()->isPointerType() && "Handled above");
  assert(!E->getType()->isFloatingType() && "Handled above");

  // C++17 onwards require that we evaluate the RHS first.
  // Compute RHS and save it in a temporary variable so we can
  // load it again later.
  // FIXME: Compound assignments are unsequenced in C, so we might
  //   have to figure out how to reject them.
  if (!visit(RHS))
    return false;

  unsigned TempOffset = this->allocateLocalPrimitive(E, *RT, /*IsConst=*/true);

  if (!this->emitSetLocal(*RT, TempOffset, E))
    return false;

  // Get LHS pointer, load its value and cast it to the
  // computation type if necessary.
  if (!visit(LHS))
    return false;
  if (!this->emitLoad(*LT, E))
    return false;
  if (LT != LHSComputationT &&
      !this->emitIntegralCast(*LT, *LHSComputationT, E->getComputationLHSType(),
                              E))
    return false;

  // Get the RHS value on the stack.
  if (!this->emitGetLocal(*RT, TempOffset, E))
    return false;

  // Perform operation.
  switch (E->getOpcode()) {
  case BO_AddAssign:
    if (!this->emitAdd(*LHSComputationT, E))
      return false;
    break;
  case BO_SubAssign:
    if (!this->emitSub(*LHSComputationT, E))
      return false;
    break;
  case BO_MulAssign:
    if (!this->emitMul(*LHSComputationT, E))
      return false;
    break;
  case BO_DivAssign:
    if (!this->emitDiv(*LHSComputationT, E))
      return false;
    break;
  case BO_RemAssign:
    if (!this->emitRem(*LHSComputationT, E))
      return false;
    break;
  case BO_ShlAssign:
    if (!this->emitShl(*LHSComputationT, *RT, E))
      return false;
    break;
  case BO_ShrAssign:
    if (!this->emitShr(*LHSComputationT, *RT, E))
      return false;
    break;
  case BO_AndAssign:
    if (!this->emitBitAnd(*LHSComputationT, E))
      return false;
    break;
  case BO_XorAssign:
    if (!this->emitBitXor(*LHSComputationT, E))
      return false;
    break;
  case BO_OrAssign:
    if (!this->emitBitOr(*LHSComputationT, E))
      return false;
    break;
  default:
    llvm_unreachable("Unimplemented compound assign operator");
  }

  // And now cast from LHSComputationT to ResultT.
  if (ResultT != LHSComputationT &&
      !this->emitIntegralCast(*LHSComputationT, *ResultT, E->getType(), E))
    return false;

  // And store the result in LHS.
  if (DiscardResult) {
    if (LHS->refersToBitField())
      return this->emitStoreBitFieldPop(*ResultT, E);
    return this->emitStorePop(*ResultT, E);
  }
  if (LHS->refersToBitField())
    return this->emitStoreBitField(*ResultT, E);
  return this->emitStore(*ResultT, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitExprWithCleanups(const ExprWithCleanups *E) {
  LocalScope<Emitter> ES(this, ScopeKind::FullExpression);
  const Expr *SubExpr = E->getSubExpr();

  return this->delegate(SubExpr) && ES.destroyLocals(E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitMaterializeTemporaryExpr(
    const MaterializeTemporaryExpr *E) {
  if (Initializing) {
    // We already have a value, just initialize that.
    return this->delegate(E->getSubExpr());
  }
  // If we don't end up using the materialized temporary anyway, don't
  // bother creating it.
  if (DiscardResult)
    return this->discard(E->getSubExpr());

  SmallVector<const Expr *, 2> CommaLHSs;
  SmallVector<SubobjectAdjustment, 2> Adjustments;
  const Expr *Inner;
  if (!Ctx.getLangOpts().CPlusPlus11)
    Inner =
        E->getSubExpr()->skipRValueSubobjectAdjustments(CommaLHSs, Adjustments);
  else
    Inner = E->getSubExpr();

  // If we passed any comma operators, evaluate their LHSs.
  for (const Expr *LHS : CommaLHSs) {
    if (!this->discard(LHS))
      return false;
  }

  // FIXME: Find a test case where Adjustments matters.

  // When we're extending a global variable *or* the storage duration of
  // the temporary is explicitly static, create a global variable.
  OptPrimType InnerT = classify(Inner);
  const ValueDecl *ExtendingDecl = E->getExtendingDecl();
  bool IsStatic = E->getStorageDuration() == SD_Static;
  if (IsStatic ||
      (ExtendingDecl && Context::shouldBeGloballyIndexed(ExtendingDecl))) {
    UnsignedOrNone GlobalIndex = P.createGlobal(E, Inner->getType());
    if (!GlobalIndex)
      return false;

    const LifetimeExtendedTemporaryDecl *TempDecl =
        E->getLifetimeExtendedTemporaryDecl();

    if (InnerT) {
      if (!this->visit(Inner))
        return false;

      if (IsStatic) {
        assert(TempDecl);
        if (!this->emitInitGlobalTemp(*InnerT, *GlobalIndex, TempDecl, E))
          return false;
      } else {
        if (!this->emitInitGlobal(*InnerT, *GlobalIndex, E))
          return false;
      }
      return this->emitGetPtrGlobal(*GlobalIndex, E);
    }

    if (!this->checkLiteralType(Inner))
      return false;
    // Non-primitive values.
    if (!this->emitGetPtrGlobal(*GlobalIndex, E))
      return false;
    if (!this->visitInitializer(Inner))
      return false;
    if (IsStatic) {
      assert(TempDecl);
      return this->emitInitGlobalTempComp(TempDecl, E);
    }
    return true;
  }

  ScopeKind VarScope = E->getStorageDuration() == SD_FullExpression
                           ? ScopeKind::FullExpression
                           : ScopeKind::Block;

  // For everyhing else, use local variables.
  if (InnerT) {
    bool IsConst = Inner->getType().isConstQualified();
    bool IsVolatile = Inner->getType().isVolatileQualified();
    unsigned LocalIndex =
        allocateLocalPrimitive(E, *InnerT, IsConst, IsVolatile, VarScope);
    if (!this->VarScope->LocalsAlwaysEnabled &&
        !this->emitEnableLocal(LocalIndex, E))
      return false;

    if (!this->visit(Inner))
      return false;
    if (!this->emitSetLocal(*InnerT, LocalIndex, E))
      return false;

    return this->emitGetPtrLocal(LocalIndex, E);
  }

  if (!this->checkLiteralType(Inner))
    return false;

  if (UnsignedOrNone LocalIndex =
          allocateLocal(E, Inner->getType(), VarScope)) {
    InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));

    if (!this->VarScope->LocalsAlwaysEnabled &&
        !this->emitEnableLocal(*LocalIndex, E))
      return false;

    if (!this->emitGetPtrLocal(*LocalIndex, E))
      return false;
    return this->visitInitializer(Inner);
  }
  return false;
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXBindTemporaryExpr(
    const CXXBindTemporaryExpr *E) {
  const Expr *SubExpr = E->getSubExpr();

  if (Initializing)
    return this->delegate(SubExpr);

  // Make sure we create a temporary even if we're discarding, since that will
  // make sure we will also call the destructor.

  if (!this->visit(SubExpr))
    return false;

  if (DiscardResult)
    return this->emitPopPtr(E);
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitCompoundLiteralExpr(const CompoundLiteralExpr *E) {
  const Expr *Init = E->getInitializer();
  if (DiscardResult)
    return this->discard(Init);

  if (Initializing) {
    // We already have a value, just initialize that.
    return this->visitInitializer(Init);
  }

  OptPrimType T = classify(E->getType());
  if (E->isFileScope()) {
    // Avoid creating a variable if this is a primitive RValue anyway.
    if (T && !E->isLValue())
      return this->delegate(Init);

    UnsignedOrNone GlobalIndex = P.createGlobal(E, E->getType());
    if (!GlobalIndex)
      return false;

    if (!this->emitGetPtrGlobal(*GlobalIndex, E))
      return false;

    // Since this is a global variable, we might've already seen,
    // don't do it again.
    if (P.isGlobalInitialized(*GlobalIndex))
      return true;

    if (T) {
      if (!this->visit(Init))
        return false;
      return this->emitInitGlobal(*T, *GlobalIndex, E);
    }

    return this->visitInitializer(Init);
  }

  // Otherwise, use a local variable.
  if (T && !E->isLValue()) {
    // For primitive types, we just visit the initializer.
    return this->delegate(Init);
  }

  unsigned LocalIndex;
  if (T)
    LocalIndex = this->allocateLocalPrimitive(Init, *T, /*IsConst=*/false);
  else if (UnsignedOrNone MaybeIndex = this->allocateLocal(Init))
    LocalIndex = *MaybeIndex;
  else
    return false;

  if (!this->emitGetPtrLocal(LocalIndex, E))
    return false;

  if (T)
    return this->visit(Init) && this->emitInit(*T, E);
  return this->visitInitializer(Init);
}

template <class Emitter>
bool Compiler<Emitter>::VisitTypeTraitExpr(const TypeTraitExpr *E) {
  if (DiscardResult)
    return true;
  if (E->isStoredAsBoolean()) {
    if (E->getType()->isBooleanType())
      return this->emitConstBool(E->getBoolValue(), E);
    return this->emitConst(E->getBoolValue(), E);
  }
  PrimType T = classifyPrim(E->getType());
  return this->visitAPValue(E->getAPValue(), T, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitArrayTypeTraitExpr(const ArrayTypeTraitExpr *E) {
  if (DiscardResult)
    return true;
  return this->emitConst(E->getValue(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitLambdaExpr(const LambdaExpr *E) {
  if (DiscardResult)
    return true;

  assert(Initializing);
  const Record *R = P.getOrCreateRecord(E->getLambdaClass());
  if (!R)
    return false;

  auto *CaptureInitIt = E->capture_init_begin();
  // Initialize all fields (which represent lambda captures) of the
  // record with their initializers.
  for (const Record::Field &F : R->fields()) {
    const Expr *Init = *CaptureInitIt;
    if (!Init || Init->containsErrors())
      continue;
    ++CaptureInitIt;

    if (OptPrimType T = classify(Init)) {
      if (!this->visit(Init))
        return false;

      if (!this->emitInitField(*T, F.Offset, E))
        return false;
    } else {
      if (!this->emitGetPtrField(F.Offset, E))
        return false;

      if (!this->visitInitializerPop(Init))
        return false;
    }
  }

  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitPredefinedExpr(const PredefinedExpr *E) {
  if (DiscardResult)
    return true;

  if (!Initializing) {
    unsigned StringIndex = P.createGlobalString(E->getFunctionName(), E);
    return this->emitGetPtrGlobal(StringIndex, E);
  }

  return this->delegate(E->getFunctionName());
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXThrowExpr(const CXXThrowExpr *E) {
  if (E->getSubExpr() && !this->discard(E->getSubExpr()))
    return false;

  return this->emitInvalid(E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXReinterpretCastExpr(
    const CXXReinterpretCastExpr *E) {
  const Expr *SubExpr = E->getSubExpr();

  OptPrimType FromT = classify(SubExpr);
  OptPrimType ToT = classify(E);

  if (!FromT || !ToT)
    return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, E);

  if (FromT == PT_Ptr || ToT == PT_Ptr) {
    // Both types could be PT_Ptr because their expressions are glvalues.
    OptPrimType PointeeFromT;
    if (SubExpr->getType()->isPointerOrReferenceType())
      PointeeFromT = classify(SubExpr->getType()->getPointeeType());
    else
      PointeeFromT = classify(SubExpr->getType());

    OptPrimType PointeeToT;
    if (E->getType()->isPointerOrReferenceType())
      PointeeToT = classify(E->getType()->getPointeeType());
    else
      PointeeToT = classify(E->getType());

    bool Fatal = true;
    if (PointeeToT && PointeeFromT) {
      if (isIntegerOrBoolType(*PointeeFromT) &&
          isIntegerOrBoolType(*PointeeToT))
        Fatal = false;
      else if (E->getCastKind() == CK_LValueBitCast)
        Fatal = false;
    } else {
      Fatal = SubExpr->getType().getTypePtr() != E->getType().getTypePtr();
    }

    if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))
      return false;

    if (E->getCastKind() == CK_LValueBitCast)
      return this->delegate(SubExpr);
    return this->VisitCastExpr(E);
  }

  // Try to actually do the cast.
  bool Fatal = (ToT != FromT);
  if (!this->emitInvalidCast(CastKind::Reinterpret, Fatal, E))
    return false;

  return this->VisitCastExpr(E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXDynamicCastExpr(const CXXDynamicCastExpr *E) {

  if (!Ctx.getLangOpts().CPlusPlus20) {
    if (!this->emitInvalidCast(CastKind::Dynamic, /*Fatal=*/false, E))
      return false;
    return this->VisitCastExpr(E);
  }

  if (!this->visit(E->getSubExpr()))
    return false;
  if (!this->emitCheckDynamicCast(E))
    return false;

  if (DiscardResult)
    return this->emitPopPtr(E);
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXNoexceptExpr(const CXXNoexceptExpr *E) {
  assert(E->getType()->isBooleanType());

  if (DiscardResult)
    return true;
  return this->emitConstBool(E->getValue(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXConstructExpr(const CXXConstructExpr *E) {
  QualType T = E->getType();
  assert(!canClassify(T));

  if (T->isRecordType()) {
    const CXXConstructorDecl *Ctor = E->getConstructor();

    // If we're discarding a construct expression, we still need
    // to allocate a variable and call the constructor and destructor.
    if (DiscardResult) {
      if (Ctor->isTrivial())
        return true;
      assert(!Initializing);
      UnsignedOrNone LocalIndex = allocateLocal(E);

      if (!LocalIndex)
        return false;

      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }

    // Trivial copy/move constructor. Avoid copy.
    if (Ctor->isDefaulted() && Ctor->isCopyOrMoveConstructor() &&
        Ctor->isTrivial() &&
        E->getArg(0)->isTemporaryObject(Ctx.getASTContext(),
                                        T->getAsCXXRecordDecl()))
      return this->visitInitializer(E->getArg(0));

    // Zero initialization.
    bool ZeroInit = E->requiresZeroInitialization();
    if (ZeroInit) {
      const Record *R = getRecord(E->getType());
      if (!R)
        return false;

      if (!this->visitZeroRecordInitializer(R, E))
        return false;

      // If the constructor is trivial anyway, we're done.
      if (Ctor->isTrivial())
        return true;
    }

    // Avoid materializing a temporary for an elidable copy/move constructor.
    if (!ZeroInit && E->isElidable()) {
      const Expr *SrcObj = E->getArg(0);
      assert(SrcObj->isTemporaryObject(Ctx.getASTContext(), Ctor->getParent()));
      assert(Ctx.getASTContext().hasSameUnqualifiedType(E->getType(),
                                                        SrcObj->getType()));
      if (const auto *ME = dyn_cast<MaterializeTemporaryExpr>(SrcObj)) {
        if (!this->emitCheckFunctionDecl(Ctor, E))
          return false;
        return this->visitInitializer(ME->getSubExpr());
      }
    }

    const Function *Func = getFunction(Ctor);

    if (!Func)
      return false;

    assert(Func->hasThisPointer());
    assert(!Func->hasRVO());

    //  The This pointer is already on the stack because this is an initializer,
    //  but we need to dup() so the call() below has its own copy.
    if (!this->emitDupPtr(E))
      return false;

    // Constructor arguments.
    for (const auto *Arg : E->arguments()) {
      if (!this->visit(Arg))
        return false;
    }

    if (Func->isVariadic()) {
      uint32_t VarArgSize = 0;
      unsigned NumParams = Func->getNumWrittenParams();
      for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I) {
        VarArgSize +=
            align(primSize(classify(E->getArg(I)->getType()).value_or(PT_Ptr)));
      }
      if (!this->emitCallVar(Func, VarArgSize, E))
        return false;
    } else {
      if (!this->emitCall(Func, 0, E)) {
        // When discarding, we don't need the result anyway, so clean up
        // the instance dup we did earlier in case surrounding code wants
        // to keep evaluating.
        if (DiscardResult)
          (void)this->emitPopPtr(E);
        return false;
      }
    }

    if (DiscardResult)
      return this->emitPopPtr(E);
    return true;
  }

  if (T->isArrayType()) {
    const Function *Func = getFunction(E->getConstructor());
    if (!Func)
      return false;

    if (!this->emitDupPtr(E))
      return false;

    std::function<bool(QualType)> initArrayDimension;
    initArrayDimension = [&](QualType T) -> bool {
      if (!T->isArrayType()) {
        // Constructor arguments.
        for (const auto *Arg : E->arguments()) {
          if (!this->visit(Arg))
            return false;
        }

        return this->emitCall(Func, 0, E);
      }

      const ConstantArrayType *CAT =
          Ctx.getASTContext().getAsConstantArrayType(T);
      if (!CAT)
        return false;
      QualType ElemTy = CAT->getElementType();
      unsigned NumElems = CAT->getZExtSize();
      for (size_t I = 0; I != NumElems; ++I) {
        if (!this->emitConstUint64(I, E))
          return false;
        if (!this->emitArrayElemPtrUint64(E))
          return false;
        if (!initArrayDimension(ElemTy))
          return false;
      }
      return this->emitPopPtr(E);
    };

    return initArrayDimension(E->getType());
  }

  return false;
}

template <class Emitter>
bool Compiler<Emitter>::VisitSourceLocExpr(const SourceLocExpr *E) {
  if (DiscardResult)
    return true;

  const APValue Val =
      E->EvaluateInContext(Ctx.getASTContext(), SourceLocDefaultExpr);

  // Things like __builtin_LINE().
  if (E->getType()->isIntegerType()) {
    assert(Val.isInt());
    const APSInt &I = Val.getInt();
    return this->emitConst(I, E);
  }
  // Otherwise, the APValue is an LValue, with only one element.
  // Theoretically, we don't need the APValue at all of course.
  assert(E->getType()->isPointerType());
  assert(Val.isLValue());
  const APValue::LValueBase &Base = Val.getLValueBase();
  if (const Expr *LValueExpr = Base.dyn_cast<const Expr *>())
    return this->visit(LValueExpr);

  // Otherwise, we have a decl (which is the case for
  // __builtin_source_location).
  assert(Base.is<const ValueDecl *>());
  assert(Val.getLValuePath().size() == 0);
  const auto *BaseDecl = Base.dyn_cast<const ValueDecl *>();
  assert(BaseDecl);

  auto *UGCD = cast<UnnamedGlobalConstantDecl>(BaseDecl);

  UnsignedOrNone GlobalIndex = P.getOrCreateGlobal(UGCD);
  if (!GlobalIndex)
    return false;

  if (!this->emitGetPtrGlobal(*GlobalIndex, E))
    return false;

  const Record *R = getRecord(E->getType());
  const APValue &V = UGCD->getValue();
  for (unsigned I = 0, N = R->getNumFields(); I != N; ++I) {
    const Record::Field *F = R->getField(I);
    const APValue &FieldValue = V.getStructField(I);

    PrimType FieldT = classifyPrim(F->Decl->getType());

    if (!this->visitAPValue(FieldValue, FieldT, E))
      return false;
    if (!this->emitInitField(FieldT, F->Offset, E))
      return false;
  }

  // Leave the pointer to the global on the stack.
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitOffsetOfExpr(const OffsetOfExpr *E) {
  unsigned N = E->getNumComponents();
  if (N == 0)
    return false;

  for (unsigned I = 0; I != N; ++I) {
    const OffsetOfNode &Node = E->getComponent(I);
    if (Node.getKind() == OffsetOfNode::Array) {
      const Expr *ArrayIndexExpr = E->getIndexExpr(Node.getArrayExprIndex());
      PrimType IndexT = classifyPrim(ArrayIndexExpr->getType());

      if (DiscardResult) {
        if (!this->discard(ArrayIndexExpr))
          return false;
        continue;
      }

      if (!this->visit(ArrayIndexExpr))
        return false;
      // Cast to Sint64.
      if (IndexT != PT_Sint64) {
        if (!this->emitCast(IndexT, PT_Sint64, E))
          return false;
      }
    }
  }

  if (DiscardResult)
    return true;

  PrimType T = classifyPrim(E->getType());
  return this->emitOffsetOf(T, E, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXScalarValueInitExpr(
    const CXXScalarValueInitExpr *E) {
  QualType Ty = E->getType();

  if (DiscardResult || Ty->isVoidType())
    return true;

  if (OptPrimType T = classify(Ty))
    return this->visitZeroInitializer(*T, Ty, E);

  if (Ty->isAnyComplexType() || Ty->isVectorType()) {
    if (!Initializing) {
      UnsignedOrNone LocalIndex = allocateLocal(E);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }

    QualType ElemQT;
    unsigned NumElems;
    if (const auto *CT = Ty->getAs<ComplexType>()) {
      NumElems = 2;
      ElemQT = CT->getElementType();
    } else {
      const auto *VT = Ty->castAs<VectorType>();
      NumElems = VT->getNumElements();
      ElemQT = VT->getElementType();
    }

    PrimType ElemT = classifyPrim(ElemQT);

    // Initialize all fields to 0.
    for (unsigned I = 0, N = NumElems; I != N; ++I) {
      if (!this->visitZeroInitializer(ElemT, ElemQT, E))
        return false;
      if (!this->emitInitElem(ElemT, I, E))
        return false;
    }
    return true;
  }

  return false;
}

template <class Emitter>
bool Compiler<Emitter>::VisitSizeOfPackExpr(const SizeOfPackExpr *E) {
  return this->emitConst(E->getPackLength(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitGenericSelectionExpr(
    const GenericSelectionExpr *E) {
  return this->delegate(E->getResultExpr());
}

template <class Emitter>
bool Compiler<Emitter>::VisitChooseExpr(const ChooseExpr *E) {
  return this->delegate(E->getChosenSubExpr());
}

template <class Emitter>
bool Compiler<Emitter>::VisitObjCBoolLiteralExpr(const ObjCBoolLiteralExpr *E) {
  if (DiscardResult)
    return true;

  return this->emitConst(E->getValue(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXInheritedCtorInitExpr(
    const CXXInheritedCtorInitExpr *E) {
  const CXXConstructorDecl *Ctor = E->getConstructor();
  assert(!Ctor->isTrivial() &&
         "Trivial CXXInheritedCtorInitExpr, implement. (possible?)");
  const Function *F = this->getFunction(Ctor);
  assert(F);
  assert(!F->hasRVO());
  assert(F->hasThisPointer());

  if (!this->emitDupPtr(SourceInfo{}))
    return false;

  // Forward all arguments of the current function (which should be a
  // constructor itself) to the inherited ctor.
  // This is necessary because the calling code has pushed the pointer
  // of the correct base for  us already, but the arguments need
  // to come after.
  unsigned ParamIndex = 0;
  for (const ParmVarDecl *PD : Ctor->parameters()) {
    PrimType PT = this->classify(PD->getType()).value_or(PT_Ptr);

    if (!this->emitGetParam(PT, ParamIndex, E))
      return false;
    ++ParamIndex;
  }

  return this->emitCall(F, 0, E);
}

// FIXME: This function has become rather unwieldy, especially
// the part where we initialize an array allocation of dynamic size.
template <class Emitter>
bool Compiler<Emitter>::VisitCXXNewExpr(const CXXNewExpr *E) {
  assert(classifyPrim(E->getType()) == PT_Ptr);
  const Expr *Init = E->getInitializer();
  QualType ElementType = E->getAllocatedType();
  OptPrimType ElemT = classify(ElementType);
  unsigned PlacementArgs = E->getNumPlacementArgs();
  const FunctionDecl *OperatorNew = E->getOperatorNew();
  const Expr *PlacementDest = nullptr;
  bool IsNoThrow = false;

  if (E->containsErrors())
    return false;

  if (PlacementArgs != 0) {
    // FIXME: There is no restriction on this, but it's not clear that any
    // other form makes any sense. We get here for cases such as:
    //
    //   new (std::align_val_t{N}) X(int)
    //
    // (which should presumably be valid only if N is a multiple of
    // alignof(int), and in any case can't be deallocated unless N is
    // alignof(X) and X has new-extended alignment).
    if (PlacementArgs == 1) {
      const Expr *Arg1 = E->getPlacementArg(0);
      if (Arg1->getType()->isNothrowT()) {
        if (!this->discard(Arg1))
          return false;
        IsNoThrow = true;
      } else {
        // Invalid unless we have C++26 or are in a std:: function.
        if (!this->emitInvalidNewDeleteExpr(E, E))
          return false;

        // If we have a placement-new destination, we'll later use that instead
        // of allocating.
        if (OperatorNew->isReservedGlobalPlacementOperator())
          PlacementDest = Arg1;
      }
    } else {
      // Always invalid.
      return this->emitInvalid(E);
    }
  } else if (!OperatorNew
                  ->isUsableAsGlobalAllocationFunctionInConstantEvaluation())
    return this->emitInvalidNewDeleteExpr(E, E);

  const Descriptor *Desc;
  if (!PlacementDest) {
    if (ElemT) {
      if (E->isArray())
        Desc = nullptr; // We're not going to use it in this case.
      else
        Desc = P.createDescriptor(E, *ElemT, /*SourceTy=*/nullptr,
                                  Descriptor::InlineDescMD);
    } else {
      Desc = P.createDescriptor(
          E, ElementType.getTypePtr(),
          E->isArray() ? std::nullopt : Descriptor::InlineDescMD,
          /*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false,
          /*IsVolatile=*/false, Init);
    }
  }

  if (E->isArray()) {
    std::optional<const Expr *> ArraySizeExpr = E->getArraySize();
    if (!ArraySizeExpr)
      return false;

    const Expr *Stripped = *ArraySizeExpr;
    for (; auto *ICE = dyn_cast<ImplicitCastExpr>(Stripped);
         Stripped = ICE->getSubExpr())
      if (ICE->getCastKind() != CK_NoOp &&
          ICE->getCastKind() != CK_IntegralCast)
        break;

    PrimType SizeT = classifyPrim(Stripped->getType());

    // Save evaluated array size to a variable.
    unsigned ArrayLen =
        allocateLocalPrimitive(Stripped, SizeT, /*IsConst=*/false);
    if (!this->visit(Stripped))
      return false;
    if (!this->emitSetLocal(SizeT, ArrayLen, E))
      return false;

    if (PlacementDest) {
      if (!this->visit(PlacementDest))
        return false;
      if (!this->emitGetLocal(SizeT, ArrayLen, E))
        return false;
      if (!this->emitCheckNewTypeMismatchArray(SizeT, E, E))
        return false;
    } else {
      if (!this->emitGetLocal(SizeT, ArrayLen, E))
        return false;

      if (ElemT) {
        // N primitive elements.
        if (!this->emitAllocN(SizeT, *ElemT, E, IsNoThrow, E))
          return false;
      } else {
        // N Composite elements.
        if (!this->emitAllocCN(SizeT, Desc, IsNoThrow, E))
          return false;
      }
    }

    if (Init) {
      QualType InitType = Init->getType();
      size_t StaticInitElems = 0;
      const Expr *DynamicInit = nullptr;
      OptPrimType ElemT;

      if (const ConstantArrayType *CAT =
              Ctx.getASTContext().getAsConstantArrayType(InitType)) {
        StaticInitElems = CAT->getZExtSize();
        // Initialize the first S element from the initializer.
        if (!this->visitInitializer(Init))
          return false;

        if (const auto *ILE = dyn_cast<InitListExpr>(Init)) {
          if (ILE->hasArrayFiller())
            DynamicInit = ILE->getArrayFiller();
          else if (StaticInitElems > 0 && isa<StringLiteral>(ILE->getInit(0)))
            ElemT = classifyPrim(CAT->getElementType());
        }
      }

      // The initializer initializes a certain number of elements, S.
      // However, the complete number of elements, N, might be larger than that.
      // In this case, we need to get an initializer for the remaining elements.
      // There are three cases:
      //   1) For the form 'new Struct[n];', the initializer is a
      //      CXXConstructExpr and its type is an IncompleteArrayType.
      //   2) For the form 'new Struct[n]{1,2,3}', the initializer is an
      //      InitListExpr and the initializer for the remaining elements
      //      is the array filler.
      //   3) StringLiterals don't have an array filler, so we need to zero
      //      the remaining elements.

      if (DynamicInit || ElemT || InitType->isIncompleteArrayType()) {
        const Function *CtorFunc = nullptr;
        if (const auto *CE = dyn_cast<CXXConstructExpr>(Init)) {
          CtorFunc = getFunction(CE->getConstructor());
          if (!CtorFunc)
            return false;
        } else if (!DynamicInit && !ElemT)
          DynamicInit = Init;

        LabelTy EndLabel = this->getLabel();
        LabelTy StartLabel = this->getLabel();

        // In the nothrow case, the alloc above might have returned nullptr.
        // Don't call any constructors that case.
        if (IsNoThrow) {
          if (!this->emitDupPtr(E))
            return false;
          if (!this->emitNullPtr(0, nullptr, E))
            return false;
          if (!this->emitEQPtr(E))
            return false;
          if (!this->jumpTrue(EndLabel, E))
            return false;
        }

        // Create loop variables.
        unsigned Iter =
            allocateLocalPrimitive(Stripped, SizeT, /*IsConst=*/false);
        if (!this->emitConst(StaticInitElems, SizeT, E))
          return false;
        if (!this->emitSetLocal(SizeT, Iter, E))
          return false;

        this->fallthrough(StartLabel);
        this->emitLabel(StartLabel);
        // Condition. Iter < ArrayLen?
        if (!this->emitGetLocal(SizeT, Iter, E))
          return false;
        if (!this->emitGetLocal(SizeT, ArrayLen, E))
          return false;
        if (!this->emitLT(SizeT, E))
          return false;
        if (!this->jumpFalse(EndLabel, E))
          return false;

        // Pointer to the allocated array is already on the stack.
        if (!this->emitGetLocal(SizeT, Iter, E))
          return false;
        if (!this->emitArrayElemPtr(SizeT, E))
          return false;

        if (isa_and_nonnull<ImplicitValueInitExpr>(DynamicInit) &&
            DynamicInit->getType()->isArrayType()) {
          QualType ElemType =
              DynamicInit->getType()->getAsArrayTypeUnsafe()->getElementType();
          PrimType InitT = classifyPrim(ElemType);
          if (!this->visitZeroInitializer(InitT, ElemType, E))
            return false;
          if (!this->emitStorePop(InitT, E))
            return false;
        } else if (DynamicInit) {
          if (OptPrimType InitT = classify(DynamicInit)) {
            if (!this->visit(DynamicInit))
              return false;
            if (!this->emitStorePop(*InitT, E))
              return false;
          } else {
            if (!this->visitInitializerPop(DynamicInit))
              return false;
          }
        } else if (ElemT) {
          if (!this->visitZeroInitializer(
                  *ElemT, InitType->getAsArrayTypeUnsafe()->getElementType(),
                  Init))
            return false;
          if (!this->emitStorePop(*ElemT, E))
            return false;
        } else {
          assert(CtorFunc);
          if (!this->emitCall(CtorFunc, 0, E))
            return false;
        }

        // ++Iter;
        if (!this->emitGetPtrLocal(Iter, E))
          return false;
        if (!this->emitIncPop(SizeT, false, E))
          return false;

        if (!this->jump(StartLabel, E))
          return false;

        this->fallthrough(EndLabel);
        this->emitLabel(EndLabel);
      }
    }
  } else { // Non-array.
    if (PlacementDest) {
      if (!this->visit(PlacementDest))
        return false;
      if (!this->emitCheckNewTypeMismatch(E, E))
        return false;

    } else {
      // Allocate just one element.
      if (!this->emitAlloc(Desc, E))
        return false;
    }

    if (Init) {
      if (ElemT) {
        if (!this->visit(Init))
          return false;

        if (!this->emitInit(*ElemT, E))
          return false;
      } else {
        // Composite.
        if (!this->visitInitializer(Init))
          return false;
      }
    }
  }

  if (DiscardResult)
    return this->emitPopPtr(E);

  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXDeleteExpr(const CXXDeleteExpr *E) {
  if (E->containsErrors())
    return false;
  const FunctionDecl *OperatorDelete = E->getOperatorDelete();

  if (!OperatorDelete->isUsableAsGlobalAllocationFunctionInConstantEvaluation())
    return this->emitInvalidNewDeleteExpr(E, E);

  // Arg must be an lvalue.
  if (!this->visit(E->getArgument()))
    return false;

  return this->emitFree(E->isArrayForm(), E->isGlobalDelete(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitBlockExpr(const BlockExpr *E) {
  if (DiscardResult)
    return true;

  const Function *Func = nullptr;
  if (const Function *F = Ctx.getOrCreateObjCBlock(E))
    Func = F;

  if (!Func)
    return false;
  return this->emitGetFnPtr(Func, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXTypeidExpr(const CXXTypeidExpr *E) {
  const Type *TypeInfoType = E->getType().getTypePtr();

  auto canonType = [](const Type *T) {
    return T->getCanonicalTypeUnqualified().getTypePtr();
  };

  if (!E->isPotentiallyEvaluated()) {
    if (DiscardResult)
      return true;

    if (E->isTypeOperand())
      return this->emitGetTypeid(
          canonType(E->getTypeOperand(Ctx.getASTContext()).getTypePtr()),
          TypeInfoType, E);

    return this->emitGetTypeid(
        canonType(E->getExprOperand()->getType().getTypePtr()), TypeInfoType,
        E);
  }

  // Otherwise, we need to evaluate the expression operand.
  assert(E->getExprOperand());
  assert(E->getExprOperand()->isLValue());

  if (!Ctx.getLangOpts().CPlusPlus20 && !this->emitDiagTypeid(E))
    return false;

  if (!this->visit(E->getExprOperand()))
    return false;

  if (!this->emitGetTypeidPtr(TypeInfoType, E))
    return false;
  if (DiscardResult)
    return this->emitPopPtr(E);
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitObjCDictionaryLiteral(
    const ObjCDictionaryLiteral *E) {
  if (E->isExpressibleAsConstantInitializer())
    return this->emitDummyPtr(E, E);
  return this->emitError(E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitObjCArrayLiteral(const ObjCArrayLiteral *E) {
  if (E->isExpressibleAsConstantInitializer())
    return this->emitDummyPtr(E, E);
  return this->emitError(E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitExpressionTraitExpr(const ExpressionTraitExpr *E) {
  assert(Ctx.getLangOpts().CPlusPlus);
  return this->emitConstBool(E->getValue(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXUuidofExpr(const CXXUuidofExpr *E) {
  if (DiscardResult)
    return true;
  assert(!Initializing);

  const MSGuidDecl *GuidDecl = E->getGuidDecl();
  const RecordDecl *RD = GuidDecl->getType()->getAsRecordDecl();
  assert(RD);
  // If the definiton of the result type is incomplete, just return a dummy.
  // If (and when) that is read from, we will fail, but not now.
  if (!RD->isCompleteDefinition())
    return this->emitDummyPtr(GuidDecl, E);

  UnsignedOrNone GlobalIndex = P.getOrCreateGlobal(GuidDecl);
  if (!GlobalIndex)
    return false;
  if (!this->emitGetPtrGlobal(*GlobalIndex, E))
    return false;

  assert(this->getRecord(E->getType()));

  const APValue &V = GuidDecl->getAsAPValue();
  if (V.getKind() == APValue::None)
    return true;

  assert(V.isStruct());
  assert(V.getStructNumBases() == 0);
  if (!this->visitAPValueInitializer(V, E, E->getType()))
    return false;

  return this->emitFinishInit(E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitRequiresExpr(const RequiresExpr *E) {
  assert(classifyPrim(E->getType()) == PT_Bool);
  if (E->isValueDependent())
    return false;
  if (DiscardResult)
    return true;
  return this->emitConstBool(E->isSatisfied(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitConceptSpecializationExpr(
    const ConceptSpecializationExpr *E) {
  assert(classifyPrim(E->getType()) == PT_Bool);
  if (DiscardResult)
    return true;
  return this->emitConstBool(E->isSatisfied(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXRewrittenBinaryOperator(
    const CXXRewrittenBinaryOperator *E) {
  return this->delegate(E->getSemanticForm());
}

template <class Emitter>
bool Compiler<Emitter>::VisitPseudoObjectExpr(const PseudoObjectExpr *E) {

  for (const Expr *SemE : E->semantics()) {
    if (auto *OVE = dyn_cast<OpaqueValueExpr>(SemE)) {
      if (SemE == E->getResultExpr())
        return false;

      if (OVE->isUnique())
        continue;

      if (!this->discard(OVE))
        return false;
    } else if (SemE == E->getResultExpr()) {
      if (!this->delegate(SemE))
        return false;
    } else {
      if (!this->discard(SemE))
        return false;
    }
  }
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitPackIndexingExpr(const PackIndexingExpr *E) {
  return this->delegate(E->getSelectedExpr());
}

template <class Emitter>
bool Compiler<Emitter>::VisitRecoveryExpr(const RecoveryExpr *E) {
  return this->emitError(E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitAddrLabelExpr(const AddrLabelExpr *E) {
  assert(E->getType()->isVoidPointerType());
  if (DiscardResult)
    return true;

  return this->emitDummyPtr(E, E);
}

template <class Emitter>
bool Compiler<Emitter>::emitVectorConversion(const Expr *Src, const Expr *E) {
  if (Src->containsErrors())
    return false;

  const auto *VT = E->getType()->castAs<VectorType>();
  QualType ElemType = VT->getElementType();
  PrimType ElemT = classifyPrim(ElemType);
  QualType SrcType = Src->getType();
  PrimType SrcElemT = classifyVectorElementType(SrcType);

  if (!Initializing) {
    UnsignedOrNone LocalIndex = allocateLocal(E);
    if (!LocalIndex)
      return false;
    if (!this->emitGetPtrLocal(*LocalIndex, E))
      return false;
  }

  unsigned SrcOffset =
      this->allocateLocalPrimitive(Src, PT_Ptr, /*IsConst=*/true);
  if (!this->visit(Src))
    return false;
  if (!this->emitSetLocal(PT_Ptr, SrcOffset, E))
    return false;

  for (unsigned I = 0; I != VT->getNumElements(); ++I) {
    if (!this->emitGetLocal(PT_Ptr, SrcOffset, E))
      return false;
    if (!this->emitArrayElemPop(SrcElemT, I, E))
      return false;

    // Cast to the desired result element type.
    if (SrcElemT != ElemT) {
      if (!this->emitPrimCast(SrcElemT, ElemT, ElemType, E))
        return false;
    } else if (ElemType->isFloatingType() && SrcType != ElemType) {
      const auto *TargetSemantics = &Ctx.getFloatSemantics(ElemType);
      if (!this->emitCastFP(TargetSemantics, getRoundingMode(E), E))
        return false;
    }
    if (!this->emitInitElem(ElemT, I, E))
      return false;
  }
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
  return emitVectorConversion(E->getSrcExpr(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
  // FIXME: Unary shuffle with mask not currently supported.
  if (E->getNumSubExprs() == 2)
    return this->emitInvalid(E);

  assert(E->getNumSubExprs() > 2);

  const Expr *Vecs[] = {E->getExpr(0), E->getExpr(1)};
  const VectorType *VT = Vecs[0]->getType()->castAs<VectorType>();
  PrimType ElemT = classifyPrim(VT->getElementType());
  unsigned NumInputElems = VT->getNumElements();
  unsigned NumOutputElems = E->getNumSubExprs() - 2;
  assert(NumOutputElems > 0);

  if (!Initializing) {
    UnsignedOrNone LocalIndex = allocateLocal(E);
    if (!LocalIndex)
      return false;
    if (!this->emitGetPtrLocal(*LocalIndex, E))
      return false;
  }

  // Save both input vectors to a local variable.
  unsigned VectorOffsets[2];
  for (unsigned I = 0; I != 2; ++I) {
    VectorOffsets[I] =
        this->allocateLocalPrimitive(Vecs[I], PT_Ptr, /*IsConst=*/true);
    if (!this->visit(Vecs[I]))
      return false;
    if (!this->emitSetLocal(PT_Ptr, VectorOffsets[I], E))
      return false;
  }
  for (unsigned I = 0; I != NumOutputElems; ++I) {
    APSInt ShuffleIndex = E->getShuffleMaskIdx(I);
    assert(ShuffleIndex >= -1);
    if (ShuffleIndex == -1)
      return this->emitInvalidShuffleVectorIndex(I, E);

    assert(ShuffleIndex < (NumInputElems * 2));
    if (!this->emitGetLocal(PT_Ptr,
                            VectorOffsets[ShuffleIndex >= NumInputElems], E))
      return false;
    unsigned InputVectorIndex = ShuffleIndex.getZExtValue() % NumInputElems;
    if (!this->emitArrayElemPop(ElemT, InputVectorIndex, E))
      return false;

    if (!this->emitInitElem(ElemT, I, E))
      return false;
  }

  if (DiscardResult)
    return this->emitPopPtr(E);

  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitExtVectorElementExpr(
    const ExtVectorElementExpr *E) {
  const Expr *Base = E->getBase();
  assert(
      Base->getType()->isVectorType() ||
      Base->getType()->getAs<PointerType>()->getPointeeType()->isVectorType());

  SmallVector<uint32_t, 4> Indices;
  E->getEncodedElementAccess(Indices);

  if (Indices.size() == 1) {
    if (!this->visit(Base))
      return false;

    if (E->isGLValue()) {
      if (!this->emitConstUint32(Indices[0], E))
        return false;
      return this->emitArrayElemPtrPop(PT_Uint32, E);
    }
    // Else, also load the value.
    return this->emitArrayElemPop(classifyPrim(E->getType()), Indices[0], E);
  }

  // Create a local variable for the base.
  unsigned BaseOffset = allocateLocalPrimitive(Base, PT_Ptr, /*IsConst=*/true);
  if (!this->visit(Base))
    return false;
  if (!this->emitSetLocal(PT_Ptr, BaseOffset, E))
    return false;

  // Now the vector variable for the return value.
  if (!Initializing) {
    UnsignedOrNone ResultIndex = allocateLocal(E);
    if (!ResultIndex)
      return false;
    if (!this->emitGetPtrLocal(*ResultIndex, E))
      return false;
  }

  assert(Indices.size() == E->getType()->getAs<VectorType>()->getNumElements());

  PrimType ElemT =
      classifyPrim(E->getType()->getAs<VectorType>()->getElementType());
  uint32_t DstIndex = 0;
  for (uint32_t I : Indices) {
    if (!this->emitGetLocal(PT_Ptr, BaseOffset, E))
      return false;
    if (!this->emitArrayElemPop(ElemT, I, E))
      return false;
    if (!this->emitInitElem(ElemT, DstIndex, E))
      return false;
    ++DstIndex;
  }

  // Leave the result pointer on the stack.
  assert(!DiscardResult);
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitObjCBoxedExpr(const ObjCBoxedExpr *E) {
  const Expr *SubExpr = E->getSubExpr();
  if (!E->isExpressibleAsConstantInitializer())
    return this->discard(SubExpr) && this->emitInvalid(E);

  if (DiscardResult)
    return true;

  assert(classifyPrim(E) == PT_Ptr);
  return this->emitDummyPtr(E, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXStdInitializerListExpr(
    const CXXStdInitializerListExpr *E) {
  const Expr *SubExpr = E->getSubExpr();
  const ConstantArrayType *ArrayType =
      Ctx.getASTContext().getAsConstantArrayType(SubExpr->getType());
  const Record *R = getRecord(E->getType());
  assert(Initializing);
  assert(SubExpr->isGLValue());

  if (!this->visit(SubExpr))
    return false;
  if (!this->emitConstUint8(0, E))
    return false;
  if (!this->emitArrayElemPtrPopUint8(E))
    return false;
  if (!this->emitInitFieldPtr(R->getField(0u)->Offset, E))
    return false;

  PrimType SecondFieldT = classifyPrim(R->getField(1u)->Decl->getType());
  if (isIntegerOrBoolType(SecondFieldT)) {
    if (!this->emitConst(ArrayType->getSize(), SecondFieldT, E))
      return false;
    return this->emitInitField(SecondFieldT, R->getField(1u)->Offset, E);
  }
  assert(SecondFieldT == PT_Ptr);

  if (!this->emitGetFieldPtr(R->getField(0u)->Offset, E))
    return false;
  if (!this->emitExpandPtr(E))
    return false;
  if (!this->emitConst(ArrayType->getSize(), PT_Uint64, E))
    return false;
  if (!this->emitArrayElemPtrPop(PT_Uint64, E))
    return false;
  return this->emitInitFieldPtr(R->getField(1u)->Offset, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitStmtExpr(const StmtExpr *E) {
  LocalScope<Emitter> BS(this);
  StmtExprScope<Emitter> SS(this);

  const CompoundStmt *CS = E->getSubStmt();
  const Stmt *Result = CS->body_back();
  for (const Stmt *S : CS->body()) {
    if (S != Result) {
      if (!this->visitStmt(S))
        return false;
      continue;
    }

    assert(S == Result);
    if (const Expr *ResultExpr = dyn_cast<Expr>(S))
      return this->delegate(ResultExpr);
    return this->emitUnsupported(E);
  }

  return BS.destroyLocals();
}

template <class Emitter> bool Compiler<Emitter>::discard(const Expr *E) {
  OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true,
                             /*NewInitializing=*/false, /*ToLValue=*/false);
  return this->Visit(E);
}

template <class Emitter> bool Compiler<Emitter>::delegate(const Expr *E) {
  // We're basically doing:
  // OptionScope<Emitter> Scope(this, DicardResult, Initializing, ToLValue);
  // but that's unnecessary of course.
  return this->Visit(E);
}

static const Expr *stripCheckedDerivedToBaseCasts(const Expr *E) {
  if (const auto *PE = dyn_cast<ParenExpr>(E))
    return stripCheckedDerivedToBaseCasts(PE->getSubExpr());

  if (const auto *CE = dyn_cast<CastExpr>(E);
      CE &&
      (CE->getCastKind() == CK_DerivedToBase || CE->getCastKind() == CK_NoOp))
    return stripCheckedDerivedToBaseCasts(CE->getSubExpr());

  return E;
}

static const Expr *stripDerivedToBaseCasts(const Expr *E) {
  if (const auto *PE = dyn_cast<ParenExpr>(E))
    return stripDerivedToBaseCasts(PE->getSubExpr());

  if (const auto *CE = dyn_cast<CastExpr>(E);
      CE && (CE->getCastKind() == CK_DerivedToBase ||
             CE->getCastKind() == CK_UncheckedDerivedToBase ||
             CE->getCastKind() == CK_NoOp))
    return stripDerivedToBaseCasts(CE->getSubExpr());

  return E;
}

template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) {
  if (E->getType().isNull())
    return false;

  if (E->getType()->isVoidType())
    return this->discard(E);

  // Create local variable to hold the return value.
  if (!E->isGLValue() && !canClassify(E->getType())) {
    UnsignedOrNone LocalIndex = allocateLocal(
        stripDerivedToBaseCasts(E), QualType(), ScopeKind::FullExpression);
    if (!LocalIndex)
      return false;

    if (!this->emitGetPtrLocal(*LocalIndex, E))
      return false;
    InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));
    return this->visitInitializer(E);
  }

  //  Otherwise,we have a primitive return value, produce the value directly
  //  and push it on the stack.
  OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
                             /*NewInitializing=*/false, /*ToLValue=*/ToLValue);
  return this->Visit(E);
}

template <class Emitter>
bool Compiler<Emitter>::visitInitializer(const Expr *E) {
  assert(!canClassify(E->getType()));

  OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
                             /*NewInitializing=*/true, /*ToLValue=*/false);
  return this->Visit(E) && this->emitFinishInit(E);
}

template <class Emitter>
bool Compiler<Emitter>::visitInitializerPop(const Expr *E) {
  assert(!canClassify(E->getType()));

  OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
                             /*NewInitializing=*/true, /*ToLValue=*/false);
  return this->Visit(E) && this->emitFinishInitPop(E);
}

template <class Emitter> bool Compiler<Emitter>::visitAsLValue(const Expr *E) {
  OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
                             /*NewInitializing=*/false, /*ToLValue=*/true);
  return this->Visit(E);
}

template <class Emitter> bool Compiler<Emitter>::visitBool(const Expr *E) {
  OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
                             /*NewInitializing=*/false, /*ToLValue=*/ToLValue);

  OptPrimType T = classify(E->getType());
  if (!T) {
    // Convert complex values to bool.
    if (E->getType()->isAnyComplexType()) {
      if (!this->visit(E))
        return false;
      return this->emitComplexBoolCast(E);
    }
    return false;
  }

  if (!this->visit(E))
    return false;

  if (T == PT_Bool)
    return true;

  // Convert pointers to bool.
  if (T == PT_Ptr)
    return this->emitIsNonNullPtr(E);

  // Or Floats.
  if (T == PT_Float)
    return this->emitCastFloatingIntegralBool(getFPOptions(E), E);

  // Or anything else we can.
  return this->emitCast(*T, PT_Bool, E);
}

template <class Emitter>
bool Compiler<Emitter>::visitZeroInitializer(PrimType T, QualType QT,
                                             const Expr *E) {
  if (const auto *AT = QT->getAs<AtomicType>())
    QT = AT->getValueType();

  switch (T) {
  case PT_Bool:
    return this->emitZeroBool(E);
  case PT_Sint8:
    return this->emitZeroSint8(E);
  case PT_Uint8:
    return this->emitZeroUint8(E);
  case PT_Sint16:
    return this->emitZeroSint16(E);
  case PT_Uint16:
    return this->emitZeroUint16(E);
  case PT_Sint32:
    return this->emitZeroSint32(E);
  case PT_Uint32:
    return this->emitZeroUint32(E);
  case PT_Sint64:
    return this->emitZeroSint64(E);
  case PT_Uint64:
    return this->emitZeroUint64(E);
  case PT_IntAP:
    return this->emitZeroIntAP(Ctx.getBitWidth(QT), E);
  case PT_IntAPS:
    return this->emitZeroIntAPS(Ctx.getBitWidth(QT), E);
  case PT_Ptr:
    return this->emitNullPtr(Ctx.getASTContext().getTargetNullPointerValue(QT),
                             nullptr, E);
  case PT_MemberPtr:
    return this->emitNullMemberPtr(0, nullptr, E);
  case PT_Float: {
    APFloat F = APFloat::getZero(Ctx.getFloatSemantics(QT));
    return this->emitFloat(F, E);
  }
  case PT_FixedPoint: {
    auto Sem = Ctx.getASTContext().getFixedPointSemantics(QT);
    return this->emitConstFixedPoint(FixedPoint::zero(Sem), E);
  }
  }
  llvm_unreachable("unknown primitive type");
}

template <class Emitter>
bool Compiler<Emitter>::visitZeroRecordInitializer(const Record *R,
                                                   const Expr *E) {
  assert(E);
  assert(R);
  // Fields
  for (const Record::Field &Field : R->fields()) {
    if (Field.isUnnamedBitField())
      continue;

    const Descriptor *D = Field.Desc;
    if (D->isPrimitive()) {
      QualType QT = D->getType();
      PrimType T = D->getPrimType();
      if (!this->visitZeroInitializer(T, QT, E))
        return false;
      if (R->isUnion()) {
        if (!this->emitInitFieldActivate(T, Field.Offset, E))
          return false;
        break;
      }
      if (!this->emitInitField(T, Field.Offset, E))
        return false;
      continue;
    }

    if (!this->emitGetPtrField(Field.Offset, E))
      return false;

    if (D->isPrimitiveArray()) {
      QualType ET = D->getElemQualType();
      PrimType T = D->getPrimType();
      for (uint32_t I = 0, N = D->getNumElems(); I != N; ++I) {
        if (!this->visitZeroInitializer(T, ET, E))
          return false;
        if (!this->emitInitElem(T, I, E))
          return false;
      }
    } else if (D->isCompositeArray()) {
      // Can't be a vector or complex field.
      if (!this->visitZeroArrayInitializer(D->getType(), E))
        return false;
    } else if (D->isRecord()) {
      if (!this->visitZeroRecordInitializer(D->ElemRecord, E))
        return false;
    } else
      return false;

    // C++11 [dcl.init]p5: If T is a (possibly cv-qualified) union type, the
    // object's first non-static named data member is zero-initialized
    if (R->isUnion()) {
      if (!this->emitFinishInitActivatePop(E))
        return false;
      break;
    }
    if (!this->emitFinishInitPop(E))
      return false;
  }

  for (const Record::Base &B : R->bases()) {
    if (!this->emitGetPtrBase(B.Offset, E))
      return false;
    if (!this->visitZeroRecordInitializer(B.R, E))
      return false;
    if (!this->emitFinishInitPop(E))
      return false;
  }

  // FIXME: Virtual bases.

  return true;
}

template <class Emitter>
bool Compiler<Emitter>::visitZeroArrayInitializer(QualType T, const Expr *E) {
  assert(T->isArrayType() || T->isAnyComplexType() || T->isVectorType());
  const ArrayType *AT = T->getAsArrayTypeUnsafe();
  QualType ElemType = AT->getElementType();
  size_t NumElems = cast<ConstantArrayType>(AT)->getZExtSize();

  if (OptPrimType ElemT = classify(ElemType)) {
    for (size_t I = 0; I != NumElems; ++I) {
      if (!this->visitZeroInitializer(*ElemT, ElemType, E))
        return false;
      if (!this->emitInitElem(*ElemT, I, E))
        return false;
    }
    return true;
  }
  if (ElemType->isRecordType()) {
    const Record *R = getRecord(ElemType);
    if (!R)
      return false;

    for (size_t I = 0; I != NumElems; ++I) {
      if (!this->emitConstUint32(I, E))
        return false;
      if (!this->emitArrayElemPtr(PT_Uint32, E))
        return false;
      if (!this->visitZeroRecordInitializer(R, E))
        return false;
      if (!this->emitPopPtr(E))
        return false;
    }
    return true;
  }
  if (ElemType->isArrayType()) {
    for (size_t I = 0; I != NumElems; ++I) {
      if (!this->emitConstUint32(I, E))
        return false;
      if (!this->emitArrayElemPtr(PT_Uint32, E))
        return false;
      if (!this->visitZeroArrayInitializer(ElemType, E))
        return false;
      if (!this->emitPopPtr(E))
        return false;
    }
    return true;
  }

  return false;
}

template <class Emitter>
bool Compiler<Emitter>::visitAssignment(const Expr *LHS, const Expr *RHS,
                                        const Expr *E) {
  if (!canClassify(E->getType()))
    return false;

  if (!this->visit(RHS))
    return false;
  if (!this->visit(LHS))
    return false;

  if (LHS->getType().isVolatileQualified())
    return this->emitInvalidStore(LHS->getType().getTypePtr(), E);

  // We don't support assignments in C.
  if (!Ctx.getLangOpts().CPlusPlus && !this->emitInvalid(E))
    return false;

  PrimType RHT = classifyPrim(RHS);
  bool Activates = refersToUnion(LHS);
  bool BitField = LHS->refersToBitField();

  if (!this->emitFlip(PT_Ptr, RHT, E))
    return false;

  if (DiscardResult) {
    if (BitField && Activates)
      return this->emitStoreBitFieldActivatePop(RHT, E);
    if (BitField)
      return this->emitStoreBitFieldPop(RHT, E);
    if (Activates)
      return this->emitStoreActivatePop(RHT, E);
    // Otherwise, regular non-activating store.
    return this->emitStorePop(RHT, E);
  }

  auto maybeLoad = [&](bool Result) -> bool {
    if (!Result)
      return false;
    // Assignments aren't necessarily lvalues in C.
    // Load from them in that case.
    if (!E->isLValue())
      return this->emitLoadPop(RHT, E);
    return true;
  };

  if (BitField && Activates)
    return maybeLoad(this->emitStoreBitFieldActivate(RHT, E));
  if (BitField)
    return maybeLoad(this->emitStoreBitField(RHT, E));
  if (Activates)
    return maybeLoad(this->emitStoreActivate(RHT, E));
  // Otherwise, regular non-activating store.
  return maybeLoad(this->emitStore(RHT, E));
}

template <class Emitter>
template <typename T>
bool Compiler<Emitter>::emitConst(T Value, PrimType Ty, const Expr *E) {
  switch (Ty) {
  case PT_Sint8:
    return this->emitConstSint8(Value, E);
  case PT_Uint8:
    return this->emitConstUint8(Value, E);
  case PT_Sint16:
    return this->emitConstSint16(Value, E);
  case PT_Uint16:
    return this->emitConstUint16(Value, E);
  case PT_Sint32:
    return this->emitConstSint32(Value, E);
  case PT_Uint32:
    return this->emitConstUint32(Value, E);
  case PT_Sint64:
    return this->emitConstSint64(Value, E);
  case PT_Uint64:
    return this->emitConstUint64(Value, E);
  case PT_Bool:
    return this->emitConstBool(Value, E);
  case PT_Ptr:
  case PT_MemberPtr:
  case PT_Float:
  case PT_IntAP:
  case PT_IntAPS:
  case PT_FixedPoint:
    llvm_unreachable("Invalid integral type");
    break;
  }
  llvm_unreachable("unknown primitive type");
}

template <class Emitter>
template <typename T>
bool Compiler<Emitter>::emitConst(T Value, const Expr *E) {
  return this->emitConst(Value, classifyPrim(E->getType()), E);
}

template <class Emitter>
bool Compiler<Emitter>::emitConst(const APSInt &Value, PrimType Ty,
                                  const Expr *E) {
  if (Ty == PT_IntAPS)
    return this->emitConstIntAPS(Value, E);
  if (Ty == PT_IntAP)
    return this->emitConstIntAP(Value, E);

  if (Value.isSigned())
    return this->emitConst(Value.getSExtValue(), Ty, E);
  return this->emitConst(Value.getZExtValue(), Ty, E);
}

template <class Emitter>
bool Compiler<Emitter>::emitConst(const APInt &Value, PrimType Ty,
                                  const Expr *E) {
  if (Ty == PT_IntAPS)
    return this->emitConstIntAPS(Value, E);
  if (Ty == PT_IntAP)
    return this->emitConstIntAP(Value, E);

  if (isSignedType(Ty))
    return this->emitConst(Value.getSExtValue(), Ty, E);
  return this->emitConst(Value.getZExtValue(), Ty, E);
}

template <class Emitter>
bool Compiler<Emitter>::emitConst(const APSInt &Value, const Expr *E) {
  return this->emitConst(Value, classifyPrim(E->getType()), E);
}

template <class Emitter>
unsigned Compiler<Emitter>::allocateLocalPrimitive(DeclTy &&Src, PrimType Ty,
                                                   bool IsConst,
                                                   bool IsVolatile,
                                                   ScopeKind SC) {
  // FIXME: There are cases where Src.is<Expr*>() is wrong, e.g.
  //   (int){12} in C. Consider using Expr::isTemporaryObject() instead
  //   or isa<MaterializeTemporaryExpr>().
  Descriptor *D = P.createDescriptor(Src, Ty, nullptr, Descriptor::InlineDescMD,
                                     IsConst, isa<const Expr *>(Src),
                                     /*IsMutable=*/false, IsVolatile);
  D->IsConstexprUnknown = this->VariablesAreConstexprUnknown;
  Scope::Local Local = this->createLocal(D);
  if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))
    Locals.insert({VD, Local});
  VarScope->addForScopeKind(Local, SC);
  return Local.Offset;
}

template <class Emitter>
UnsignedOrNone Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty,
                                                ScopeKind SC) {
  const ValueDecl *Key = nullptr;
  const Expr *Init = nullptr;
  bool IsTemporary = false;
  if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>())) {
    Key = VD;

    if (const auto *VarD = dyn_cast<VarDecl>(VD))
      Init = VarD->getInit();
  }
  if (auto *E = Src.dyn_cast<const Expr *>()) {
    IsTemporary = true;
    if (Ty.isNull())
      Ty = E->getType();
  }

  Descriptor *D = P.createDescriptor(
      Src, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(),
      IsTemporary, /*IsMutable=*/false, /*IsVolatile=*/Ty.isVolatileQualified(),
      Init);
  if (!D)
    return std::nullopt;
  D->IsConstexprUnknown = this->VariablesAreConstexprUnknown;

  Scope::Local Local = this->createLocal(D);
  if (Key)
    Locals.insert({Key, Local});
  VarScope->addForScopeKind(Local, SC);
  return Local.Offset;
}

template <class Emitter>
UnsignedOrNone Compiler<Emitter>::allocateTemporary(const Expr *E) {
  QualType Ty = E->getType();
  assert(!Ty->isRecordType());

  Descriptor *D = P.createDescriptor(
      E, Ty.getTypePtr(), Descriptor::InlineDescMD, Ty.isConstQualified(),
      /*IsTemporary=*/true);

  if (!D)
    return std::nullopt;

  Scope::Local Local = this->createLocal(D);
  VariableScope<Emitter> *S = VarScope;
  assert(S);
  // Attach to topmost scope.
  while (S->getParent())
    S = S->getParent();
  assert(S && !S->getParent());
  S->addLocal(Local);
  return Local.Offset;
}

template <class Emitter>
const RecordType *Compiler<Emitter>::getRecordTy(QualType Ty) {
  if (const PointerType *PT = dyn_cast<PointerType>(Ty))
    return PT->getPointeeType()->getAsCanonical<RecordType>();
  return Ty->getAsCanonical<RecordType>();
}

template <class Emitter> Record *Compiler<Emitter>::getRecord(QualType Ty) {
  if (const auto *RecordTy = getRecordTy(Ty))
    return getRecord(RecordTy->getDecl()->getDefinitionOrSelf());
  return nullptr;
}

template <class Emitter>
Record *Compiler<Emitter>::getRecord(const RecordDecl *RD) {
  return P.getOrCreateRecord(RD);
}

template <class Emitter>
const Function *Compiler<Emitter>::getFunction(const FunctionDecl *FD) {
  return Ctx.getOrCreateFunction(FD);
}

template <class Emitter>
bool Compiler<Emitter>::visitExpr(const Expr *E, bool DestroyToplevelScope) {
  LocalScope<Emitter> RootScope(this, ScopeKind::FullExpression);

  auto maybeDestroyLocals = [&]() -> bool {
    if (DestroyToplevelScope)
      return RootScope.destroyLocals() && this->emitCheckAllocations(E);
    return this->emitCheckAllocations(E);
  };

  // Void expressions.
  if (E->getType()->isVoidType()) {
    if (!visit(E))
      return false;
    return this->emitRetVoid(E) && maybeDestroyLocals();
  }

  // Expressions with a primitive return type.
  if (OptPrimType T = classify(E)) {
    if (!visit(E))
      return false;

    return this->emitRet(*T, E) && maybeDestroyLocals();
  }

  // Expressions with a composite return type.
  // For us, that means everything we don't
  // have a PrimType for.
  if (UnsignedOrNone LocalOffset = this->allocateLocal(E)) {
    InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalOffset));
    if (!this->emitGetPtrLocal(*LocalOffset, E))
      return false;

    if (!visitInitializer(E))
      return false;
    // We are destroying the locals AFTER the Ret op.
    // The Ret op needs to copy the (alive) values, but the
    // destructors may still turn the entire expression invalid.
    return this->emitRetValue(E) && maybeDestroyLocals();
  }

  return maybeDestroyLocals() && false;
}

template <class Emitter>
bool Compiler<Emitter>::visitLValueExpr(const Expr *E,
                                        bool DestroyToplevelScope) {
  OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false,
                             /*NewInitializing=*/false, /*ToLValue=*/true);

  return this->visitExpr(E, DestroyToplevelScope);
}

template <class Emitter>
VarCreationState Compiler<Emitter>::visitDecl(const VarDecl *VD) {

  auto R = this->visitVarDecl(VD, VD->getInit(), /*Toplevel=*/true);

  if (R.notCreated())
    return R;

  if (R)
    return true;

  if (!R && Context::shouldBeGloballyIndexed(VD)) {
    if (auto GlobalIndex = P.getGlobal(VD)) {
      Block *GlobalBlock = P.getGlobal(*GlobalIndex);
      auto &GD = GlobalBlock->getBlockDesc<GlobalInlineDescriptor>();

      GD.InitState = GlobalInitState::InitializerFailed;
      GlobalBlock->invokeDtor();
    }
  }

  return R;
}

/// Toplevel visitDeclAndReturn().
/// We get here from evaluateAsInitializer().
/// We need to evaluate the initializer and return its value.
template <class Emitter>
bool Compiler<Emitter>::visitDeclAndReturn(const VarDecl *VD, const Expr *Init,
                                           bool ConstantContext) {
  // We only create variables if we're evaluating in a constant context.
  // Otherwise, just evaluate the initializer and return it.
  if (!ConstantContext) {
    DeclScope<Emitter> LS(this, VD);
    if (!this->visit(Init))
      return false;
    return this->emitRet(classify(Init).value_or(PT_Ptr), VD) &&
           LS.destroyLocals() && this->emitCheckAllocations(VD);
  }

  LocalScope<Emitter> VDScope(this);
  if (!this->visitVarDecl(VD, Init, /*Toplevel=*/true))
    return false;

  OptPrimType VarT = classify(VD->getType());
  if (Context::shouldBeGloballyIndexed(VD)) {
    auto GlobalIndex = P.getGlobal(VD);
    assert(GlobalIndex); // visitVarDecl() didn't return false.
    if (VarT) {
      if (!this->emitGetGlobalUnchecked(*VarT, *GlobalIndex, VD))
        return false;
    } else {
      if (!this->emitGetPtrGlobal(*GlobalIndex, VD))
        return false;
    }
  } else {
    auto Local = Locals.find(VD);
    assert(Local != Locals.end()); // Same here.
    if (VarT) {
      if (!this->emitGetLocal(*VarT, Local->second.Offset, VD))
        return false;
    } else {
      if (!this->emitGetPtrLocal(Local->second.Offset, VD))
        return false;
    }
  }

  // Return the value.
  if (!this->emitRet(VarT.value_or(PT_Ptr), VD)) {
    // If the Ret above failed and this is a global variable, mark it as
    // uninitialized, even everything else succeeded.
    if (Context::shouldBeGloballyIndexed(VD)) {
      auto GlobalIndex = P.getGlobal(VD);
      assert(GlobalIndex);
      Block *GlobalBlock = P.getGlobal(*GlobalIndex);
      auto &GD = GlobalBlock->getBlockDesc<GlobalInlineDescriptor>();

      GD.InitState = GlobalInitState::InitializerFailed;
      GlobalBlock->invokeDtor();
    }
    return false;
  }

  return VDScope.destroyLocals() && this->emitCheckAllocations(VD);
}

template <class Emitter>
VarCreationState Compiler<Emitter>::visitVarDecl(const VarDecl *VD,
                                                 const Expr *Init,
                                                 bool Toplevel) {
  QualType VarTy = VD->getType();
  // We don't know what to do with these, so just return false.
  if (VarTy.isNull())
    return false;

  // This case is EvalEmitter-only. If we won't create any instructions for the
  // initializer anyway, don't bother creating the variable in the first place.
  if (!this->isActive())
    return VarCreationState::NotCreated();

  OptPrimType VarT = classify(VD->getType());

  if (Init && Init->isValueDependent())
    return false;

  if (Context::shouldBeGloballyIndexed(VD)) {
    auto checkDecl = [&]() -> bool {
      bool NeedsOp = !Toplevel && VD->isLocalVarDecl() && VD->isStaticLocal();
      return !NeedsOp || this->emitCheckDecl(VD, VD);
    };

    DeclScope<Emitter> LocalScope(this, VD);
    UnsignedOrNone GlobalIndex = P.getGlobal(VD);
    if (GlobalIndex) {
      // The global was previously created but the initializer failed.
      if (!P.getGlobal(*GlobalIndex)->isInitialized())
        return false;
      // We've already seen and initialized this global.
      if (P.isGlobalInitialized(*GlobalIndex))
        return checkDecl();
      // The previous attempt at initialization might've been unsuccessful,
      // so let's try this one.
    } else if ((GlobalIndex =
                    P.createGlobal(VD, Init, VariablesAreConstexprUnknown))) {
    } else {
      return false;
    }
    if (!Init)
      return true;

    if (!checkDecl())
      return false;

    if (VarT) {
      if (!this->visit(Init))
        return false;

      return this->emitInitGlobal(*VarT, *GlobalIndex, VD);
    }

    if (!this->emitGetPtrGlobal(*GlobalIndex, Init))
      return false;

    if (!this->emitStartInit(Init))
      return false;

    if (!visitInitializer(Init))
      return false;

    if (!this->emitEndInit(Init))
      return false;

    return this->emitFinishInitGlobal(Init);
  }
  // Local variables.
  InitLinkScope<Emitter> ILS(this, InitLink::Decl(VD));

  if (VarT) {
    unsigned Offset = this->allocateLocalPrimitive(
        VD, *VarT, VarTy.isConstQualified(), VarTy.isVolatileQualified(),
        ScopeKind::Block);

    if (!Init || Init->getType()->isVoidType())
      return true;

    // If this is a toplevel declaration, create a scope for the
    // initializer.
    if (Toplevel) {
      LocalScope<Emitter> Scope(this);
      if (!this->visit(Init))
        return false;
      return this->emitSetLocal(*VarT, Offset, VD) && Scope.destroyLocals();
    }
    if (!this->visit(Init))
      return false;

    if (VarTy->isReferenceType()) {
      // [C++26][decl.ref]
      // The object designated by such a glvalue can be outside its lifetime
      // Because a null pointer value or a pointer past the end of an object
      // does not point to an object, a reference in a well-defined program
      // cannot refer to such things;
      assert(classifyPrim(VarTy) == PT_Ptr);
      if (!this->emitCheckRefInit(Init))
        return false;
    }

    return this->emitSetLocal(*VarT, Offset, VD);
  }
  // Local composite variables.
  if (UnsignedOrNone Offset =
          this->allocateLocal(VD, VarTy, ScopeKind::Block)) {
    if (!Init)
      return true;

    if (!this->emitGetPtrLocal(*Offset, Init))
      return false;

    return visitInitializerPop(Init);
  }
  return false;
}

template <class Emitter>
bool Compiler<Emitter>::visitDtorCall(const VarDecl *VD, const APValue &Value) {
  assert(!canClassify(VD->getType()));

  DeclScope<Emitter> LocalScope(this, VD);
  // Create a local variable to use as the instance.
  QualType Ty = VD->getType();
  Descriptor *D = P.createDescriptor(
      VD, Ty.getTypePtr(), Descriptor::InlineDescMD, /*IsConst=*/false,
      /*IsTemporary=*/false, /*IsMutable=*/false,
      /*IsVolatile=*/Ty.isVolatileQualified(), nullptr);
  if (!D)
    return false;

  // FIXME: Would be nice if we didn't allocate the descriptor at all in this
  // case.
  if (D->hasTrivialDtor())
    return true;

  Scope::Local Local = this->createLocal(D);
  Locals.insert({VD, Local});
  VarScope->addForScopeKind(Local, ScopeKind::Block);

  if (!this->emitGetPtrLocal(Local.Offset, VD))
    return false;
  if (!this->visitAPValueInitializer(Value, nullptr, Ty))
    return false;
  return this->emitDestructionPop(D, VD);
}

template <class Emitter>
bool Compiler<Emitter>::visitAPValue(const APValue &Val, PrimType ValType,
                                     const Expr *E) {
  assert(!DiscardResult);
  if (Val.isInt())
    return this->emitConst(Val.getInt(), ValType, E);
  if (Val.isFloat()) {
    APFloat F = Val.getFloat();
    return this->emitFloat(F, E);
  }

  if (Val.isMemberPointer()) {
    if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl()) {
      if (!this->emitGetMemberPtr(MemberDecl, E))
        return false;

      bool IsDerived = Val.isMemberPointerToDerivedMember();
      // Apply the member pointer path.
      for (const CXXRecordDecl *PathEntry : Val.getMemberPointerPath()) {
        if (!this->emitCopyMemberPtrPath(PathEntry, IsDerived, E))
          return false;
      }

      return true;
    }
    return this->emitNullMemberPtr(0, nullptr, E);
  }

  if (Val.isLValue()) {
    if (Val.isNullPointer())
      return this->emitNull(ValType, 0, nullptr, E);

    APValue::LValueBase Base = Val.getLValueBase();
    ArrayRef<APValue::LValuePathEntry> Path = Val.getLValuePath();

    if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>())
      return this->visit(BaseExpr);
    if (const auto *VD = Base.dyn_cast<const ValueDecl *>()) {
      if (!this->visitDeclRef(VD, E))
        return false;

      QualType EntryType = VD->getType();
      for (auto &Entry : Path) {
        if (EntryType->isArrayType()) {
          uint64_t Index = Entry.getAsArrayIndex();
          QualType ElemType =
              EntryType->getAsArrayTypeUnsafe()->getElementType();
          if (!this->emitConst(Index, PT_Uint64, E))
            return false;
          if (!this->emitArrayElemPtrPop(PT_Uint64, E))
            return false;
          EntryType = ElemType;
        } else {
          assert(EntryType->isRecordType());
          const Record *EntryRecord = getRecord(EntryType);
          if (!EntryRecord) {
            assert(false);

            return false;
          }

          const Decl *BaseOrMember = Entry.getAsBaseOrMember().getPointer();
          if (const auto *FD = dyn_cast<FieldDecl>(BaseOrMember)) {
            unsigned EntryOffset = EntryRecord->getField(FD)->Offset;
            if (!this->emitGetPtrFieldPop(EntryOffset, E))
              return false;
            EntryType = FD->getType();
          } else {
            const auto *Base = cast<CXXRecordDecl>(BaseOrMember);
            unsigned BaseOffset = EntryRecord->getBase(Base)->Offset;
            if (!this->emitGetPtrBasePop(BaseOffset, /*NullOK=*/false, E))
              return false;
            EntryType = Ctx.getASTContext().getCanonicalTagType(Base);
          }
        }
      }

      return true;
    }
  }

  return false;
}

template <class Emitter>
bool Compiler<Emitter>::visitAPValueInitializer(const APValue &Val,
                                                const Expr *E, QualType T) {
  if (Val.isStruct()) {
    const Record *R = this->getRecord(T);
    assert(R);
    for (unsigned I = 0, N = Val.getStructNumFields(); I != N; ++I) {
      const APValue &F = Val.getStructField(I);
      const Record::Field *RF = R->getField(I);
      QualType FieldType = RF->Decl->getType();

      // Fields.
      if (OptPrimType PT = classify(FieldType)) {
        if (!this->visitAPValue(F, *PT, E))
          return false;
        if (!this->emitInitField(*PT, RF->Offset, E))
          return false;
      } else {
        if (!this->emitGetPtrField(RF->Offset, E))
          return false;
        if (!this->visitAPValueInitializer(F, E, FieldType))
          return false;
        if (!this->emitFinishInitPop(E))
          return false;
      }
    }

    // Bases.
    for (unsigned I = 0, N = Val.getStructNumBases(); I != N; ++I) {
      const APValue &B = Val.getStructBase(I);
      const Record::Base *RB = R->getBase(I);
      QualType BaseType = Ctx.getASTContext().getCanonicalTagType(RB->Decl);

      if (!this->emitGetPtrBase(RB->Offset, E))
        return false;
      if (!this->visitAPValueInitializer(B, E, BaseType))
        return false;
      if (!this->emitFinishInitPop(E))
        return false;
    }

    return true;
  }
  if (Val.isUnion()) {
    const FieldDecl *UnionField = Val.getUnionField();
    if (!UnionField)
      return true;
    const Record *R = this->getRecord(T);
    assert(R);
    const APValue &F = Val.getUnionValue();
    const Record::Field *RF = R->getField(UnionField);
    QualType FieldType = RF->Decl->getType();

    if (OptPrimType PT = classify(FieldType)) {
      if (!this->visitAPValue(F, *PT, E))
        return false;
      if (RF->isBitField())
        return this->emitInitBitFieldActivate(*PT, RF->Offset, RF->bitWidth(),
                                              E);
      return this->emitInitFieldActivate(*PT, RF->Offset, E);
    }

    if (!this->emitGetPtrField(RF->Offset, E))
      return false;
    if (!this->emitActivate(E))
      return false;
    if (!this->visitAPValueInitializer(F, E, FieldType))
      return false;
    return this->emitPopPtr(E);
  }
  if (Val.isArray()) {
    unsigned InitializedElems = Val.getArrayInitializedElts();
    const auto *ArrType = T->getAsArrayTypeUnsafe();
    QualType ElemType = ArrType->getElementType();
    OptPrimType ElemT = classify(ElemType);

    for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) {
      const APValue &Elem = A >= InitializedElems
                                ? Val.getArrayFiller()
                                : Val.getArrayInitializedElt(A);

      if (ElemT) {
        if (!this->visitAPValue(Elem, *ElemT, E))
          return false;
        if (!this->emitInitElem(*ElemT, A, E))
          return false;
      } else {
        if (!this->emitConstUint32(A, E))
          return false;
        if (!this->emitArrayElemPtrUint32(E))
          return false;
        if (!this->visitAPValueInitializer(Elem, E, ElemType))
          return false;
        if (!this->emitPopPtr(E))
          return false;
      }
    }
    return true;
  }
  // TODO: Other types.

  return false;
}

template <class Emitter>
bool Compiler<Emitter>::VisitBuiltinCallExpr(const CallExpr *E,
                                             unsigned BuiltinID) {
  if (BuiltinID == Builtin::BI__builtin_constant_p) {
    // Void argument is always invalid and harder to handle later.
    if (E->getArg(0)->getType()->isVoidType()) {
      if (DiscardResult)
        return true;
      return this->emitConst(0, E);
    }

    if (!this->emitStartSpeculation(E))
      return false;
    LabelTy EndLabel = this->getLabel();
    if (!this->speculate(E, EndLabel))
      return false;
    if (!this->emitEndSpeculation(E))
      return false;
    this->fallthrough(EndLabel);
    if (DiscardResult)
      return this->emitPop(classifyPrim(E), E);
    return true;
  }

  // For these, we're expected to ultimately return an APValue pointing
  // to the CallExpr. This is needed to get the correct codegen.
  if (BuiltinID == Builtin::BI__builtin___CFStringMakeConstantString ||
      BuiltinID == Builtin::BI__builtin___NSStringMakeConstantString ||
      BuiltinID == Builtin::BI__builtin_ptrauth_sign_constant ||
      BuiltinID == Builtin::BI__builtin_function_start) {
    if (DiscardResult)
      return true;
    return this->emitDummyPtr(E, E);
  }

  QualType ReturnType = E->getType();
  OptPrimType ReturnT = classify(E);

  // Non-primitive return type. Prepare storage.
  if (!Initializing && !ReturnT && !ReturnType->isVoidType()) {
    UnsignedOrNone LocalIndex = allocateLocal(E);
    if (!LocalIndex)
      return false;
    if (!this->emitGetPtrLocal(*LocalIndex, E))
      return false;
  }

  // Prepare function arguments including special cases.
  switch (BuiltinID) {
  case Builtin::BI__builtin_object_size:
  case Builtin::BI__builtin_dynamic_object_size: {
    assert(E->getNumArgs() == 2);
    const Expr *Arg0 = E->getArg(0);
    if (Arg0->isGLValue()) {
      if (!this->visit(Arg0))
        return false;

    } else {
      if (!this->visitAsLValue(Arg0))
        return false;
    }
    if (!this->visit(E->getArg(1)))
      return false;

  } break;
  case Builtin::BI__assume:
  case Builtin::BI__builtin_assume:
    // Argument is not evaluated.
    break;
  case Builtin::BI__atomic_is_lock_free:
  case Builtin::BI__atomic_always_lock_free: {
    assert(E->getNumArgs() == 2);
    if (!this->visit(E->getArg(0)))
      return false;
    if (!this->visitAsLValue(E->getArg(1)))
      return false;
  } break;

  default:
    if (!Context::isUnevaluatedBuiltin(BuiltinID)) {
      // Put arguments on the stack.
      for (const auto *Arg : E->arguments()) {
        if (!this->visit(Arg))
          return false;
      }
    }
  }

  if (!this->emitCallBI(E, BuiltinID, E))
    return false;

  if (DiscardResult && !ReturnType->isVoidType())
    return this->emitPop(ReturnT.value_or(PT_Ptr), E);

  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
  if (E->containsErrors())
    return false;
  const FunctionDecl *FuncDecl = E->getDirectCallee();

  if (FuncDecl) {
    if (unsigned BuiltinID = FuncDecl->getBuiltinID())
      return VisitBuiltinCallExpr(E, BuiltinID);

    // Calls to replaceable operator new/operator delete.
    if (FuncDecl->isUsableAsGlobalAllocationFunctionInConstantEvaluation()) {
      if (FuncDecl->getDeclName().isAnyOperatorNew())
        return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_new);
      assert(FuncDecl->getDeclName().getCXXOverloadedOperator() == OO_Delete ||
             FuncDecl->getDeclName().getCXXOverloadedOperator() ==
                 OO_Array_Delete);
      return VisitBuiltinCallExpr(E, Builtin::BI__builtin_operator_delete);
    }

    // Explicit calls to trivial destructors
    if (const auto *DD = dyn_cast<CXXDestructorDecl>(FuncDecl);
        DD && DD->isTrivial()) {
      const auto *MemberCall = cast<CXXMemberCallExpr>(E);
      if (!this->visit(MemberCall->getImplicitObjectArgument()))
        return false;
      return this->emitCheckDestruction(E) && this->emitEndLifetime(E) &&
             this->emitPopPtr(E);
    }
  }

  LocalScope<Emitter> CallScope(this, ScopeKind::Call);

  QualType ReturnType = E->getCallReturnType(Ctx.getASTContext());
  OptPrimType T = classify(ReturnType);
  bool HasRVO = !ReturnType->isVoidType() && !T;

  if (HasRVO) {
    if (DiscardResult) {
      // If we need to discard the return value but the function returns its
      // value via an RVO pointer, we need to create one such pointer just
      // for this call.
      if (UnsignedOrNone LocalIndex = allocateLocal(E)) {
        if (!this->emitGetPtrLocal(*LocalIndex, E))
          return false;
      }
    } else {
      // We need the result. Prepare a pointer to return or
      // dup the current one.
      if (!Initializing) {
        if (UnsignedOrNone LocalIndex = allocateLocal(E)) {
          if (!this->emitGetPtrLocal(*LocalIndex, E))
            return false;
        }
      }
      if (!this->emitDupPtr(E))
        return false;
    }
  }

  SmallVector<const Expr *, 8> Args(ArrayRef(E->getArgs(), E->getNumArgs()));

  bool IsAssignmentOperatorCall = false;
  bool ActivateLHS = false;
  if (const auto *OCE = dyn_cast<CXXOperatorCallExpr>(E);
      OCE && OCE->isAssignmentOp()) {
    // Just like with regular assignments, we need to special-case assignment
    // operators here and evaluate the RHS (the second arg) before the LHS (the
    // first arg). We fix this by using a Flip op later.
    assert(Args.size() == 2);
    const CXXRecordDecl *LHSRecord = Args[0]->getType()->getAsCXXRecordDecl();
    ActivateLHS = LHSRecord && LHSRecord->hasTrivialDefaultConstructor();
    IsAssignmentOperatorCall = true;
    std::reverse(Args.begin(), Args.end());
  }
  // Calling a static operator will still
  // pass the instance, but we don't need it.
  // Discard it here.
  if (isa<CXXOperatorCallExpr>(E)) {
    if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(FuncDecl);
        MD && MD->isStatic()) {
      if (!this->discard(E->getArg(0)))
        return false;
      // Drop first arg.
      Args.erase(Args.begin());
    }
  }

  bool Devirtualized = false;
  UnsignedOrNone CalleeOffset = std::nullopt;
  // Add the (optional, implicit) This pointer.
  if (const auto *MC = dyn_cast<CXXMemberCallExpr>(E)) {
    if (!FuncDecl && classifyPrim(E->getCallee()) == PT_MemberPtr) {
      // If we end up creating a CallPtr op for this, we need the base of the
      // member pointer as the instance pointer, and later extract the function
      // decl as the function pointer.
      const Expr *Callee = E->getCallee();
      CalleeOffset =
          this->allocateLocalPrimitive(Callee, PT_MemberPtr, /*IsConst=*/true);
      if (!this->visit(Callee))
        return false;
      if (!this->emitSetLocal(PT_MemberPtr, *CalleeOffset, E))
        return false;
      if (!this->emitGetLocal(PT_MemberPtr, *CalleeOffset, E))
        return false;
      if (!this->emitGetMemberPtrBase(E))
        return false;
    } else {
      const auto *InstancePtr = MC->getImplicitObjectArgument();
      if (isa_and_nonnull<CXXDestructorDecl>(CompilingFunction) ||
          isa_and_nonnull<CXXConstructorDecl>(CompilingFunction)) {
        const auto *Stripped = stripCheckedDerivedToBaseCasts(InstancePtr);
        if (isa<CXXThisExpr>(Stripped)) {
          FuncDecl =
              cast<CXXMethodDecl>(FuncDecl)->getCorrespondingMethodInClass(
                  Stripped->getType()->getPointeeType()->getAsCXXRecordDecl());
          Devirtualized = true;
          if (!this->visit(Stripped))
            return false;
        } else {
          if (!this->visit(InstancePtr))
            return false;
        }
      } else {
        if (!this->visit(InstancePtr))
          return false;
      }
    }
  } else if (const auto *PD =
                 dyn_cast<CXXPseudoDestructorExpr>(E->getCallee())) {
    if (!this->emitCheckPseudoDtor(E))
      return false;
    const Expr *Base = PD->getBase();
    // E.g. `using T = int; 0.~T();`.
    if (OptPrimType BaseT = classify(Base); !BaseT || BaseT != PT_Ptr)
      return this->discard(Base);
    if (!this->visit(Base))
      return false;
    return this->emitEndLifetimePop(E);
  } else if (!FuncDecl) {
    const Expr *Callee = E->getCallee();
    CalleeOffset =
        this->allocateLocalPrimitive(Callee, PT_Ptr, /*IsConst=*/true);
    if (!this->visit(Callee))
      return false;
    if (!this->emitSetLocal(PT_Ptr, *CalleeOffset, E))
      return false;
  }

  if (!this->visitCallArgs(Args, FuncDecl, ActivateLHS,
                           isa<CXXOperatorCallExpr>(E)))
    return false;

  // Undo the argument reversal we did earlier.
  if (IsAssignmentOperatorCall) {
    assert(Args.size() == 2);
    PrimType Arg1T = classify(Args[0]).value_or(PT_Ptr);
    PrimType Arg2T = classify(Args[1]).value_or(PT_Ptr);
    if (!this->emitFlip(Arg2T, Arg1T, E))
      return false;
  }

  if (FuncDecl) {
    const Function *Func = getFunction(FuncDecl);
    if (!Func)
      return false;

    // In error cases, the function may be called with fewer arguments than
    // parameters.
    if (E->getNumArgs() < Func->getNumWrittenParams())
      return false;

    assert(HasRVO == Func->hasRVO());

    bool HasQualifier = false;
    if (const auto *ME = dyn_cast<MemberExpr>(E->getCallee()))
      HasQualifier = ME->hasQualifier();

    bool IsVirtual = false;
    if (const auto *MD = dyn_cast<CXXMethodDecl>(FuncDecl))
      IsVirtual = !Devirtualized && MD->isVirtual();

    // In any case call the function. The return value will end up on the stack
    // and if the function has RVO, we already have the pointer on the stack to
    // write the result into.
    if (IsVirtual && !HasQualifier) {
      uint32_t VarArgSize = 0;
      unsigned NumParams =
          Func->getNumWrittenParams() +
          (isa<CXXOperatorCallExpr>(E) && Func->hasImplicitThisParam());
      for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
        VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));

      if (!this->emitCallVirt(Func, VarArgSize, E))
        return false;
    } else if (Func->isVariadic()) {
      uint32_t VarArgSize = 0;
      unsigned NumParams =
          Func->getNumWrittenParams() +
          (isa<CXXOperatorCallExpr>(E) && Func->hasImplicitThisParam());
      for (unsigned I = NumParams, N = E->getNumArgs(); I != N; ++I)
        VarArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));
      if (!this->emitCallVar(Func, VarArgSize, E))
        return false;
    } else {
      if (!this->emitCall(Func, 0, E))
        return false;
    }
  } else {
    // Indirect call. Visit the callee, which will leave a FunctionPointer on
    // the stack. Cleanup of the returned value if necessary will be done after
    // the function call completed.

    // Sum the size of all args from the call expr.
    uint32_t ArgSize = 0;
    for (unsigned I = 0, N = E->getNumArgs(); I != N; ++I)
      ArgSize += align(primSize(classify(E->getArg(I)).value_or(PT_Ptr)));

    // Get the callee, either from a member pointer or function pointer saved in
    // CalleeOffset.
    if (isa<CXXMemberCallExpr>(E) && CalleeOffset) {
      if (!this->emitGetLocal(PT_MemberPtr, *CalleeOffset, E))
        return false;
      if (!this->emitGetMemberPtrDecl(E))
        return false;
    } else {
      if (!this->emitGetLocal(PT_Ptr, *CalleeOffset, E))
        return false;
    }
    if (!this->emitCallPtr(ArgSize, E, E))
      return false;
  }

  // Cleanup for discarded return values.
  if (DiscardResult && !ReturnType->isVoidType() && T)
    return this->emitPop(*T, E) && CallScope.destroyLocals();

  return CallScope.destroyLocals();
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXDefaultInitExpr(const CXXDefaultInitExpr *E) {
  SourceLocScope<Emitter> SLS(this, E);

  return this->delegate(E->getExpr());
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E) {
  SourceLocScope<Emitter> SLS(this, E);

  return this->delegate(E->getExpr());
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXBoolLiteralExpr(const CXXBoolLiteralExpr *E) {
  if (DiscardResult)
    return true;

  return this->emitConstBool(E->getValue(), E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXNullPtrLiteralExpr(
    const CXXNullPtrLiteralExpr *E) {
  if (DiscardResult)
    return true;

  uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(E->getType());
  return this->emitNullPtr(Val, nullptr, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitGNUNullExpr(const GNUNullExpr *E) {
  if (DiscardResult)
    return true;

  assert(E->getType()->isIntegerType());

  PrimType T = classifyPrim(E->getType());
  return this->emitZero(T, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitCXXThisExpr(const CXXThisExpr *E) {
  if (DiscardResult)
    return true;

  if constexpr (!std::is_same_v<Emitter, EvalEmitter>) {
    if (this->LambdaThisCapture.Offset > 0) {
      if (this->LambdaThisCapture.IsPtr)
        return this->emitGetThisFieldPtr(this->LambdaThisCapture.Offset, E);
      return this->emitGetPtrThisField(this->LambdaThisCapture.Offset, E);
    }
  }

  // In some circumstances, the 'this' pointer does not actually refer to the
  // instance pointer of the current function frame, but e.g. to the declaration
  // currently being initialized. Here we emit the necessary instruction(s) for
  // this scenario.
  if (!InitStackActive || InitStack.empty())
    return this->emitThis(E);

  // If our init stack is, for example:
  // 0 Stack: 3 (decl)
  // 1 Stack: 6 (init list)
  // 2 Stack: 1 (field)
  // 3 Stack: 6 (init list)
  // 4 Stack: 1 (field)
  //
  // We want to find the LAST element in it that's an init list,
  // which is marked with the K_InitList marker. The index right
  // before that points to an init list. We need to find the
  // elements before the K_InitList element that point to a base
  // (e.g. a decl or This), optionally followed by field, elem, etc.
  // In the example above, we want to emit elements [0..2].
  unsigned StartIndex = 0;
  unsigned EndIndex = 0;
  // Find the init list.
  for (StartIndex = InitStack.size() - 1; StartIndex > 0; --StartIndex) {
    if (InitStack[StartIndex].Kind == InitLink::K_DIE) {
      EndIndex = StartIndex;
      --StartIndex;
      break;
    }
  }

  // Walk backwards to find the base.
  for (; StartIndex > 0; --StartIndex) {
    if (InitStack[StartIndex].Kind == InitLink::K_InitList)
      continue;

    if (InitStack[StartIndex].Kind != InitLink::K_Field &&
        InitStack[StartIndex].Kind != InitLink::K_Elem &&
        InitStack[StartIndex].Kind != InitLink::K_DIE)
      break;
  }

  if (StartIndex == 0 && EndIndex == 0)
    EndIndex = InitStack.size() - 1;

  assert(StartIndex < EndIndex);

  // Emit the instructions.
  for (unsigned I = StartIndex; I != (EndIndex + 1); ++I) {
    if (InitStack[I].Kind == InitLink::K_InitList ||
        InitStack[I].Kind == InitLink::K_DIE)
      continue;
    if (!InitStack[I].template emit<Emitter>(this, E))
      return false;
  }
  return true;
}

template <class Emitter> bool Compiler<Emitter>::visitStmt(const Stmt *S) {
  switch (S->getStmtClass()) {
  case Stmt::CompoundStmtClass:
    return visitCompoundStmt(cast<CompoundStmt>(S));
  case Stmt::DeclStmtClass:
    return visitDeclStmt(cast<DeclStmt>(S), /*EvaluateConditionDecl=*/true);
  case Stmt::ReturnStmtClass:
    return visitReturnStmt(cast<ReturnStmt>(S));
  case Stmt::IfStmtClass:
    return visitIfStmt(cast<IfStmt>(S));
  case Stmt::WhileStmtClass:
    return visitWhileStmt(cast<WhileStmt>(S));
  case Stmt::DoStmtClass:
    return visitDoStmt(cast<DoStmt>(S));
  case Stmt::ForStmtClass:
    return visitForStmt(cast<ForStmt>(S));
  case Stmt::CXXForRangeStmtClass:
    return visitCXXForRangeStmt(cast<CXXForRangeStmt>(S));
  case Stmt::BreakStmtClass:
    return visitBreakStmt(cast<BreakStmt>(S));
  case Stmt::ContinueStmtClass:
    return visitContinueStmt(cast<ContinueStmt>(S));
  case Stmt::SwitchStmtClass:
    return visitSwitchStmt(cast<SwitchStmt>(S));
  case Stmt::CaseStmtClass:
    return visitCaseStmt(cast<CaseStmt>(S));
  case Stmt::DefaultStmtClass:
    return visitDefaultStmt(cast<DefaultStmt>(S));
  case Stmt::AttributedStmtClass:
    return visitAttributedStmt(cast<AttributedStmt>(S));
  case Stmt::CXXTryStmtClass:
    return visitCXXTryStmt(cast<CXXTryStmt>(S));
  case Stmt::NullStmtClass:
    return true;
  // Always invalid statements.
  case Stmt::GCCAsmStmtClass:
  case Stmt::MSAsmStmtClass:
  case Stmt::GotoStmtClass:
    return this->emitInvalid(S);
  case Stmt::LabelStmtClass:
    return this->visitStmt(cast<LabelStmt>(S)->getSubStmt());
  default: {
    if (const auto *E = dyn_cast<Expr>(S))
      return this->discard(E);
    return false;
  }
  }
}

template <class Emitter>
bool Compiler<Emitter>::visitCompoundStmt(const CompoundStmt *S) {
  LocalScope<Emitter> Scope(this);
  for (const auto *InnerStmt : S->body())
    if (!visitStmt(InnerStmt))
      return false;
  return Scope.destroyLocals();
}

template <class Emitter>
bool Compiler<Emitter>::maybeEmitDeferredVarInit(const VarDecl *VD) {
  if (auto *DD = dyn_cast_if_present<DecompositionDecl>(VD)) {
    for (auto *BD : DD->flat_bindings())
      if (auto *KD = BD->getHoldingVar();
          KD && !this->visitVarDecl(KD, KD->getInit()))
        return false;
  }
  return true;
}

static bool hasTrivialDefaultCtorParent(const FieldDecl *FD) {
  assert(FD);
  assert(FD->getParent()->isUnion());
  const CXXRecordDecl *CXXRD =
      FD->getType()->getBaseElementTypeUnsafe()->getAsCXXRecordDecl();
  return !CXXRD || CXXRD->hasTrivialDefaultConstructor();
}

template <class Emitter> bool Compiler<Emitter>::refersToUnion(const Expr *E) {
  for (;;) {
    if (const auto *ME = dyn_cast<MemberExpr>(E)) {
      if (const auto *FD = dyn_cast<FieldDecl>(ME->getMemberDecl());
          FD && FD->getParent()->isUnion() && hasTrivialDefaultCtorParent(FD))
        return true;
      E = ME->getBase();
      continue;
    }

    if (const auto *ASE = dyn_cast<ArraySubscriptExpr>(E)) {
      E = ASE->getBase()->IgnoreImplicit();
      continue;
    }

    if (const auto *ICE = dyn_cast<ImplicitCastExpr>(E);
        ICE && (ICE->getCastKind() == CK_NoOp ||
                ICE->getCastKind() == CK_DerivedToBase ||
                ICE->getCastKind() == CK_UncheckedDerivedToBase)) {
      E = ICE->getSubExpr();
      continue;
    }

    if (const auto *This = dyn_cast<CXXThisExpr>(E)) {
      const auto *ThisRecord =
          This->getType()->getPointeeType()->getAsRecordDecl();
      if (!ThisRecord->isUnion())
        return false;
      // Otherwise, always activate if we're in the ctor.
      if (const auto *Ctor =
              dyn_cast_if_present<CXXConstructorDecl>(CompilingFunction))
        return Ctor->getParent() == ThisRecord;
      return false;
    }

    break;
  }
  return false;
}

template <class Emitter>
bool Compiler<Emitter>::visitDeclStmt(const DeclStmt *DS,
                                      bool EvaluateConditionDecl) {
  for (const auto *D : DS->decls()) {
    if (isa<StaticAssertDecl, TagDecl, TypedefNameDecl, BaseUsingDecl,
            FunctionDecl, NamespaceAliasDecl, UsingDirectiveDecl>(D))
      continue;

    const auto *VD = dyn_cast<VarDecl>(D);
    if (!VD)
      return false;
    if (!this->visitVarDecl(VD, VD->getInit()))
      return false;

    // Register decomposition decl holding vars.
    if (EvaluateConditionDecl && !this->maybeEmitDeferredVarInit(VD))
      return false;
  }

  return true;
}

template <class Emitter>
bool Compiler<Emitter>::visitReturnStmt(const ReturnStmt *RS) {
  if (this->InStmtExpr)
    return this->emitUnsupported(RS);

  if (const Expr *RE = RS->getRetValue()) {
    LocalScope<Emitter> RetScope(this);
    if (ReturnType) {
      // Primitive types are simply returned.
      if (!this->visit(RE))
        return false;
      this->emitCleanup();
      return this->emitRet(*ReturnType, RS);
    }

    if (RE->getType()->isVoidType()) {
      if (!this->visit(RE))
        return false;
    } else {
      if (RE->containsErrors())
        return false;

      InitLinkScope<Emitter> ILS(this, InitLink::RVO());
      // RVO - construct the value in the return location.
      if (!this->emitRVOPtr(RE))
        return false;
      if (!this->visitInitializerPop(RE))
        return false;

      this->emitCleanup();
      return this->emitRetVoid(RS);
    }
  }

  // Void return.
  this->emitCleanup();
  return this->emitRetVoid(RS);
}

template <class Emitter> bool Compiler<Emitter>::visitIfStmt(const IfStmt *IS) {
  LocalScope<Emitter> IfScope(this);

  auto visitChildStmt = [&](const Stmt *S) -> bool {
    LocalScope<Emitter> SScope(this);
    if (!visitStmt(S))
      return false;
    return SScope.destroyLocals();
  };

  if (auto *CondInit = IS->getInit()) {
    if (!visitStmt(CondInit))
      return false;
  }

  if (const DeclStmt *CondDecl = IS->getConditionVariableDeclStmt()) {
    if (!visitDeclStmt(CondDecl))
      return false;
  }

  // Save ourselves compiling some code and the jumps, etc. if the condition is
  // stataically known to be either true or false. We could look at more cases
  // here, but I think all the ones that actually happen are using a
  // ConstantExpr.
  if (std::optional<bool> BoolValue = getBoolValue(IS->getCond())) {
    if (*BoolValue)
      return visitChildStmt(IS->getThen());
    if (const Stmt *Else = IS->getElse())
      return visitChildStmt(Else);
    return true;
  }

  // Otherwise, compile the condition.
  if (IS->isNonNegatedConsteval()) {
    if (!this->emitIsConstantContext(IS))
      return false;
  } else if (IS->isNegatedConsteval()) {
    if (!this->emitIsConstantContext(IS))
      return false;
    if (!this->emitInv(IS))
      return false;
  } else {
    LocalScope<Emitter> CondScope(this, ScopeKind::FullExpression);
    if (!this->visitBool(IS->getCond()))
      return false;
    if (!CondScope.destroyLocals())
      return false;
  }

  if (!this->maybeEmitDeferredVarInit(IS->getConditionVariable()))
    return false;

  if (const Stmt *Else = IS->getElse()) {
    LabelTy LabelElse = this->getLabel();
    LabelTy LabelEnd = this->getLabel();
    if (!this->jumpFalse(LabelElse, IS))
      return false;
    if (!visitChildStmt(IS->getThen()))
      return false;
    if (!this->jump(LabelEnd, IS))
      return false;
    this->emitLabel(LabelElse);
    if (!visitChildStmt(Else))
      return false;
    this->emitLabel(LabelEnd);
  } else {
    LabelTy LabelEnd = this->getLabel();
    if (!this->jumpFalse(LabelEnd, IS))
      return false;
    if (!visitChildStmt(IS->getThen()))
      return false;
    this->emitLabel(LabelEnd);
  }

  if (!IfScope.destroyLocals())
    return false;

  return true;
}

template <class Emitter>
bool Compiler<Emitter>::visitWhileStmt(const WhileStmt *S) {
  const Expr *Cond = S->getCond();
  const Stmt *Body = S->getBody();

  LabelTy CondLabel = this->getLabel(); // Label before the condition.
  LabelTy EndLabel = this->getLabel();  // Label after the loop.
  LocalScope<Emitter> WholeLoopScope(this);
  LoopScope<Emitter> LS(this, S, EndLabel, CondLabel);

  this->fallthrough(CondLabel);
  this->emitLabel(CondLabel);

  // Start of the loop body {
  LocalScope<Emitter> CondScope(this);

  if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt()) {
    if (!visitDeclStmt(CondDecl))
      return false;
  }

  if (!this->visitBool(Cond))
    return false;

  if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))
    return false;

  if (!this->jumpFalse(EndLabel, S))
    return false;

  if (!this->visitStmt(Body))
    return false;

  if (!CondScope.destroyLocals())
    return false;
  // } End of loop body.

  if (!this->jump(CondLabel, S))
    return false;
  this->fallthrough(EndLabel);
  this->emitLabel(EndLabel);

  return CondScope.destroyLocals() && WholeLoopScope.destroyLocals();
}

template <class Emitter> bool Compiler<Emitter>::visitDoStmt(const DoStmt *S) {
  const Expr *Cond = S->getCond();
  const Stmt *Body = S->getBody();

  LabelTy StartLabel = this->getLabel();
  LabelTy EndLabel = this->getLabel();
  LabelTy CondLabel = this->getLabel();
  LocalScope<Emitter> WholeLoopScope(this);
  LoopScope<Emitter> LS(this, S, EndLabel, CondLabel);

  this->fallthrough(StartLabel);
  this->emitLabel(StartLabel);

  {
    LocalScope<Emitter> CondScope(this);
    if (!this->visitStmt(Body))
      return false;
    this->fallthrough(CondLabel);
    this->emitLabel(CondLabel);
    if (!this->visitBool(Cond))
      return false;

    if (!CondScope.destroyLocals())
      return false;
  }
  if (!this->jumpTrue(StartLabel, S))
    return false;

  this->fallthrough(EndLabel);
  this->emitLabel(EndLabel);
  return WholeLoopScope.destroyLocals();
}

template <class Emitter>
bool Compiler<Emitter>::visitForStmt(const ForStmt *S) {
  // for (Init; Cond; Inc) { Body }
  const Stmt *Init = S->getInit();
  const Expr *Cond = S->getCond();
  const Expr *Inc = S->getInc();
  const Stmt *Body = S->getBody();

  LabelTy EndLabel = this->getLabel();
  LabelTy CondLabel = this->getLabel();
  LabelTy IncLabel = this->getLabel();

  LocalScope<Emitter> WholeLoopScope(this);
  if (Init && !this->visitStmt(Init))
    return false;

  // Start of the loop body {
  this->fallthrough(CondLabel);
  this->emitLabel(CondLabel);

  LocalScope<Emitter> CondScope(this);
  LoopScope<Emitter> LS(this, S, EndLabel, IncLabel);
  if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt()) {
    if (!visitDeclStmt(CondDecl))
      return false;
  }

  if (Cond) {
    if (!this->visitBool(Cond))
      return false;
    if (!this->jumpFalse(EndLabel, S))
      return false;
  }
  if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))
    return false;

  if (Body && !this->visitStmt(Body))
    return false;

  this->fallthrough(IncLabel);
  this->emitLabel(IncLabel);
  if (Inc && !this->discard(Inc))
    return false;

  if (!CondScope.destroyLocals())
    return false;
  if (!this->jump(CondLabel, S))
    return false;
  // } End of loop body.

  this->emitLabel(EndLabel);
  // If we jumped out of the loop above, we still need to clean up the condition
  // scope.
  return CondScope.destroyLocals() && WholeLoopScope.destroyLocals();
}

template <class Emitter>
bool Compiler<Emitter>::visitCXXForRangeStmt(const CXXForRangeStmt *S) {
  const Stmt *Init = S->getInit();
  const Expr *Cond = S->getCond();
  const Expr *Inc = S->getInc();
  const Stmt *Body = S->getBody();
  const Stmt *BeginStmt = S->getBeginStmt();
  const Stmt *RangeStmt = S->getRangeStmt();
  const Stmt *EndStmt = S->getEndStmt();

  LabelTy EndLabel = this->getLabel();
  LabelTy CondLabel = this->getLabel();
  LabelTy IncLabel = this->getLabel();
  LocalScope<Emitter> WholeLoopScope(this);
  LoopScope<Emitter> LS(this, S, EndLabel, IncLabel);

  // Emit declarations needed in the loop.
  if (Init && !this->visitStmt(Init))
    return false;
  if (!this->visitStmt(RangeStmt))
    return false;
  if (!this->visitStmt(BeginStmt))
    return false;
  if (!this->visitStmt(EndStmt))
    return false;

  // Now the condition as well as the loop variable assignment.
  this->fallthrough(CondLabel);
  this->emitLabel(CondLabel);
  if (!this->visitBool(Cond))
    return false;
  if (!this->jumpFalse(EndLabel, S))
    return false;

  if (!this->visitDeclStmt(S->getLoopVarStmt(), /*EvaluateConditionDecl=*/true))
    return false;

  // Body.
  {
    if (!this->visitStmt(Body))
      return false;

    this->fallthrough(IncLabel);
    this->emitLabel(IncLabel);
    if (!this->discard(Inc))
      return false;
  }

  if (!this->jump(CondLabel, S))
    return false;

  this->fallthrough(EndLabel);
  this->emitLabel(EndLabel);
  return WholeLoopScope.destroyLocals();
}

template <class Emitter>
bool Compiler<Emitter>::visitBreakStmt(const BreakStmt *S) {
  if (LabelInfoStack.empty())
    return false;

  OptLabelTy TargetLabel = std::nullopt;
  const Stmt *TargetLoop = S->getNamedLoopOrSwitch();
  const VariableScope<Emitter> *BreakScope = nullptr;

  if (!TargetLoop) {
    for (const auto &LI : llvm::reverse(LabelInfoStack)) {
      if (LI.BreakLabel) {
        TargetLabel = *LI.BreakLabel;
        BreakScope = LI.BreakOrContinueScope;
        break;
      }
    }
  } else {
    for (auto LI : LabelInfoStack) {
      if (LI.Name == TargetLoop) {
        TargetLabel = *LI.BreakLabel;
        BreakScope = LI.BreakOrContinueScope;
        break;
      }
    }
  }

  // Faulty break statement (e.g. label redefined or named loops disabled).
  if (!TargetLabel)
    return false;

  for (VariableScope<Emitter> *C = this->VarScope; C != BreakScope;
       C = C->getParent()) {
    if (!C->destroyLocals())
      return false;
  }

  return this->jump(*TargetLabel, S);
}

template <class Emitter>
bool Compiler<Emitter>::visitContinueStmt(const ContinueStmt *S) {
  if (LabelInfoStack.empty())
    return false;

  OptLabelTy TargetLabel = std::nullopt;
  const Stmt *TargetLoop = S->getNamedLoopOrSwitch();
  const VariableScope<Emitter> *ContinueScope = nullptr;

  if (!TargetLoop) {
    for (const auto &LI : llvm::reverse(LabelInfoStack)) {
      if (LI.ContinueLabel) {
        TargetLabel = *LI.ContinueLabel;
        ContinueScope = LI.BreakOrContinueScope;
        break;
      }
    }
  } else {
    for (auto LI : LabelInfoStack) {
      if (LI.Name == TargetLoop) {
        TargetLabel = *LI.ContinueLabel;
        ContinueScope = LI.BreakOrContinueScope;
        break;
      }
    }
  }
  assert(TargetLabel);

  for (VariableScope<Emitter> *C = VarScope; C != ContinueScope;
       C = C->getParent()) {
    if (!C->destroyLocals())
      return false;
  }

  return this->jump(*TargetLabel, S);
}

template <class Emitter>
bool Compiler<Emitter>::visitSwitchStmt(const SwitchStmt *S) {
  const Expr *Cond = S->getCond();
  if (Cond->containsErrors())
    return false;

  PrimType CondT = this->classifyPrim(Cond->getType());
  LocalScope<Emitter> LS(this);

  LabelTy EndLabel = this->getLabel();
  UnsignedOrNone DefaultLabel = std::nullopt;
  unsigned CondVar =
      this->allocateLocalPrimitive(Cond, CondT, /*IsConst=*/true);

  if (const auto *CondInit = S->getInit())
    if (!visitStmt(CondInit))
      return false;

  if (const DeclStmt *CondDecl = S->getConditionVariableDeclStmt())
    if (!visitDeclStmt(CondDecl))
      return false;

  // Initialize condition variable.
  if (!this->visit(Cond))
    return false;
  if (!this->emitSetLocal(CondT, CondVar, S))
    return false;

  if (!this->maybeEmitDeferredVarInit(S->getConditionVariable()))
    return false;

  CaseMap CaseLabels;
  // Create labels and comparison ops for all case statements.
  for (const SwitchCase *SC = S->getSwitchCaseList(); SC;
       SC = SC->getNextSwitchCase()) {
    if (const auto *CS = dyn_cast<CaseStmt>(SC)) {
      CaseLabels[SC] = this->getLabel();

      if (CS->caseStmtIsGNURange()) {
        LabelTy EndOfRangeCheck = this->getLabel();
        const Expr *Low = CS->getLHS();
        const Expr *High = CS->getRHS();
        if (Low->isValueDependent() || High->isValueDependent())
          return false;

        if (!this->emitGetLocal(CondT, CondVar, CS))
          return false;
        if (!this->visit(Low))
          return false;
        PrimType LT = this->classifyPrim(Low->getType());
        if (!this->emitGE(LT, S))
          return false;
        if (!this->jumpFalse(EndOfRangeCheck, S))
          return false;

        if (!this->emitGetLocal(CondT, CondVar, CS))
          return false;
        if (!this->visit(High))
          return false;
        PrimType HT = this->classifyPrim(High->getType());
        if (!this->emitLE(HT, S))
          return false;
        if (!this->jumpTrue(CaseLabels[CS], S))
          return false;
        this->emitLabel(EndOfRangeCheck);
        continue;
      }

      const Expr *Value = CS->getLHS();
      if (Value->isValueDependent())
        return false;
      PrimType ValueT = this->classifyPrim(Value->getType());

      // Compare the case statement's value to the switch condition.
      if (!this->emitGetLocal(CondT, CondVar, CS))
        return false;
      if (!this->visit(Value))
        return false;

      // Compare and jump to the case label.
      if (!this->emitEQ(ValueT, S))
        return false;
      if (!this->jumpTrue(CaseLabels[CS], S))
        return false;
    } else {
      assert(!DefaultLabel);
      DefaultLabel = this->getLabel();
    }
  }

  // If none of the conditions above were true, fall through to the default
  // statement or jump after the switch statement.
  if (DefaultLabel) {
    if (!this->jump(*DefaultLabel, S))
      return false;
  } else {
    if (!this->jump(EndLabel, S))
      return false;
  }

  SwitchScope<Emitter> SS(this, S, std::move(CaseLabels), EndLabel,
                          DefaultLabel);
  if (!this->visitStmt(S->getBody()))
    return false;
  this->fallthrough(EndLabel);
  this->emitLabel(EndLabel);

  return LS.destroyLocals();
}

template <class Emitter>
bool Compiler<Emitter>::visitCaseStmt(const CaseStmt *S) {
  this->fallthrough(CaseLabels[S]);
  this->emitLabel(CaseLabels[S]);
  return this->visitStmt(S->getSubStmt());
}

template <class Emitter>
bool Compiler<Emitter>::visitDefaultStmt(const DefaultStmt *S) {
  if (LabelInfoStack.empty())
    return false;

  LabelTy DefaultLabel;
  for (const LabelInfo &LI : llvm::reverse(LabelInfoStack)) {
    if (LI.DefaultLabel) {
      DefaultLabel = *LI.DefaultLabel;
      break;
    }
  }

  this->emitLabel(DefaultLabel);
  return this->visitStmt(S->getSubStmt());
}

template <class Emitter>
bool Compiler<Emitter>::visitAttributedStmt(const AttributedStmt *S) {
  const Stmt *SubStmt = S->getSubStmt();

  bool IsMSVCConstexprAttr = isa<ReturnStmt>(SubStmt) &&
                             hasSpecificAttr<MSConstexprAttr>(S->getAttrs());

  if (IsMSVCConstexprAttr && !this->emitPushMSVCCE(S))
    return false;

  if (this->Ctx.getLangOpts().CXXAssumptions &&
      !this->Ctx.getLangOpts().MSVCCompat) {
    for (const Attr *A : S->getAttrs()) {
      auto *AA = dyn_cast<CXXAssumeAttr>(A);
      if (!AA)
        continue;

      assert(isa<NullStmt>(SubStmt));

      const Expr *Assumption = AA->getAssumption();
      if (Assumption->isValueDependent())
        return false;

      if (Assumption->HasSideEffects(this->Ctx.getASTContext()))
        continue;

      // Evaluate assumption.
      if (!this->visitBool(Assumption))
        return false;

      if (!this->emitAssume(Assumption))
        return false;
    }
  }

  // Ignore other attributes.
  if (!this->visitStmt(SubStmt))
    return false;

  if (IsMSVCConstexprAttr)
    return this->emitPopMSVCCE(S);
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::visitCXXTryStmt(const CXXTryStmt *S) {
  // Ignore all handlers.
  return this->visitStmt(S->getTryBlock());
}

template <class Emitter>
bool Compiler<Emitter>::emitLambdaStaticInvokerBody(const CXXMethodDecl *MD) {
  assert(MD->isLambdaStaticInvoker());
  assert(MD->hasBody());
  assert(cast<CompoundStmt>(MD->getBody())->body_empty());

  const CXXRecordDecl *ClosureClass = MD->getParent();
  const FunctionDecl *LambdaCallOp;
  assert(ClosureClass->captures().empty());
  if (ClosureClass->isGenericLambda()) {
    LambdaCallOp = ClosureClass->getLambdaCallOperator();
    assert(MD->isFunctionTemplateSpecialization() &&
           "A generic lambda's static-invoker function must be a "
           "template specialization");
    const TemplateArgumentList *TAL = MD->getTemplateSpecializationArgs();
    FunctionTemplateDecl *CallOpTemplate =
        LambdaCallOp->getDescribedFunctionTemplate();
    void *InsertPos = nullptr;
    const FunctionDecl *CorrespondingCallOpSpecialization =
        CallOpTemplate->findSpecialization(TAL->asArray(), InsertPos);
    assert(CorrespondingCallOpSpecialization);
    LambdaCallOp = CorrespondingCallOpSpecialization;
  } else {
    LambdaCallOp = ClosureClass->getLambdaCallOperator();
  }
  assert(ClosureClass->captures().empty());
  const Function *Func = this->getFunction(LambdaCallOp);
  if (!Func)
    return false;
  assert(Func->hasThisPointer());
  assert(Func->getNumParams() == (MD->getNumParams() + 1 + Func->hasRVO()));

  if (Func->hasRVO()) {
    if (!this->emitRVOPtr(MD))
      return false;
  }

  // The lambda call operator needs an instance pointer, but we don't have
  // one here, and we don't need one either because the lambda cannot have
  // any captures, as verified above. Emit a null pointer. This is then
  // special-cased when interpreting to not emit any misleading diagnostics.
  if (!this->emitNullPtr(0, nullptr, MD))
    return false;

  // Forward all arguments from the static invoker to the lambda call operator.
  for (const ParmVarDecl *PVD : MD->parameters()) {
    auto It = this->Params.find(PVD);
    assert(It != this->Params.end());

    // We do the lvalue-to-rvalue conversion manually here, so no need
    // to care about references.
    PrimType ParamType = this->classify(PVD->getType()).value_or(PT_Ptr);
    if (!this->emitGetParam(ParamType, It->second.Index, MD))
      return false;
  }

  if (!this->emitCall(Func, 0, LambdaCallOp))
    return false;

  this->emitCleanup();
  if (ReturnType)
    return this->emitRet(*ReturnType, MD);

  // Nothing to do, since we emitted the RVO pointer above.
  return this->emitRetVoid(MD);
}

template <class Emitter>
bool Compiler<Emitter>::checkLiteralType(const Expr *E) {
  if (Ctx.getLangOpts().CPlusPlus23)
    return true;

  if (!E->isPRValue() || E->getType()->isLiteralType(Ctx.getASTContext()))
    return true;

  return this->emitCheckLiteralType(E->getType().getTypePtr(), E);
}

static bool initNeedsOverridenLoc(const CXXCtorInitializer *Init) {
  const Expr *InitExpr = Init->getInit();

  if (!Init->isWritten() && !Init->isInClassMemberInitializer() &&
      !isa<CXXConstructExpr>(InitExpr))
    return true;

  if (const auto *CE = dyn_cast<CXXConstructExpr>(InitExpr)) {
    const CXXConstructorDecl *Ctor = CE->getConstructor();
    if (Ctor->isDefaulted() && Ctor->isCopyOrMoveConstructor() &&
        Ctor->isTrivial())
      return true;
  }

  return false;
}

template <class Emitter>
bool Compiler<Emitter>::compileConstructor(const CXXConstructorDecl *Ctor) {
  assert(!ReturnType);

  // Only start the lifetime of the instance pointer.
  if (!this->emitStartThisLifetime1(Ctor))
    return false;

  auto emitFieldInitializer = [&](const Record::Field *F, unsigned FieldOffset,
                                  const Expr *InitExpr,
                                  bool Activate = false) -> bool {
    // We don't know what to do with these, so just return false.
    if (InitExpr->getType().isNull())
      return false;

    if (OptPrimType T = this->classify(InitExpr)) {
      if (Activate && !this->emitActivateThisField(FieldOffset, InitExpr))
        return false;

      if (!this->visit(InitExpr))
        return false;

      if (F->isBitField())
        return this->emitInitThisBitField(*T, FieldOffset, F->bitWidth(),
                                          InitExpr);
      return this->emitInitThisField(*T, FieldOffset, InitExpr);
    }
    // Non-primitive case. Get a pointer to the field-to-initialize
    // on the stack and call visitInitialzer() for it.
    InitLinkScope<Emitter> FieldScope(this, InitLink::Field(F->Offset));
    if (!this->emitGetPtrThisField(FieldOffset, InitExpr))
      return false;

    if (Activate && !this->emitActivate(InitExpr))
      return false;

    return this->visitInitializerPop(InitExpr);
  };

  const RecordDecl *RD = Ctor->getParent();
  const Record *R = this->getRecord(RD);
  if (!R)
    return false;
  bool IsUnion = R->isUnion();

  // Default union copy and move ctors are special.
  if (IsUnion && Ctor->isCopyOrMoveConstructor() && Ctor->isDefaulted()) {
    LocOverrideScope<Emitter> LOS(this, SourceInfo{});

    // No special case for NumFields == 0 here, so the Memcpy op
    // below also does its checks in those cases.

    assert(cast<CompoundStmt>(Ctor->getBody())->body_empty());
    if (!this->emitThis(Ctor))
      return false;

    if (!this->emitGetParam(PT_Ptr, /*ParamIndex=*/0, Ctor))
      return false;

    return this->emitMemcpy(Ctor) && this->emitPopPtr(Ctor) &&
           this->emitRetVoid(Ctor);
  }

  unsigned FieldInits = 0;
  InitLinkScope<Emitter> InitScope(this, InitLink::This());
  for (const auto *Init : Ctor->inits()) {
    // Scope needed for the initializers.
    LocalScope<Emitter> Scope(this, ScopeKind::FullExpression);

    const Expr *InitExpr = Init->getInit();
    if (const FieldDecl *Member = Init->getMember()) {
      const Record::Field *F = R->getField(Member);

      LocOverrideScope<Emitter> LOS(this, SourceInfo{},
                                    initNeedsOverridenLoc(Init));
      if (!emitFieldInitializer(F, F->Offset, InitExpr, IsUnion))
        return false;
      ++FieldInits;
    } else if (const Type *Base = Init->getBaseClass()) {
      const auto *BaseDecl = Base->getAsCXXRecordDecl();
      assert(BaseDecl);

      if (Init->isBaseVirtual()) {
        assert(R->getVirtualBase(BaseDecl));
        if (!this->emitGetPtrThisVirtBase(BaseDecl, InitExpr))
          return false;

      } else {
        // Base class initializer.
        // Get This Base and call initializer on it.
        const Record::Base *B = R->getBase(BaseDecl);
        assert(B);
        if (!this->emitGetPtrThisBase(B->Offset, InitExpr))
          return false;
      }

      if (IsUnion && !this->emitActivate(InitExpr))
        return false;

      if (!this->visitInitializerPop(InitExpr))
        return false;
    } else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {
      LocOverrideScope<Emitter> LOS(this, SourceInfo{},
                                    initNeedsOverridenLoc(Init));
      unsigned ChainSize = IFD->getChainingSize();
      assert(ChainSize >= 2);

      unsigned NestedFieldOffset = 0;
      const Record::Field *NestedField = nullptr;
      for (unsigned I = 0; I != ChainSize; ++I) {
        const auto *FD = cast<FieldDecl>(IFD->chain()[I]);
        const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());
        assert(FieldRecord);

        NestedField = FieldRecord->getField(FD);
        assert(NestedField);
        IsUnion = IsUnion || FieldRecord->isUnion();

        NestedFieldOffset += NestedField->Offset;

        // Add a new InitChainLink for the record, but not for the final field.
        if (I != ChainSize - 1)
          InitStack.push_back(InitLink::Field(NestedField->Offset));
      }
      assert(NestedField);

      InitStackScope<Emitter> ISS(this, isa<CXXDefaultInitExpr>(InitExpr));
      if (!emitFieldInitializer(NestedField, NestedFieldOffset, InitExpr,
                                IsUnion))
        return false;

      // Mark all chain links as initialized.
      unsigned InitFieldOffset = 0;
      for (const NamedDecl *ND : IFD->chain().drop_back()) {
        const auto *FD = cast<FieldDecl>(ND);
        const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());
        assert(FieldRecord);
        NestedField = FieldRecord->getField(FD);
        InitFieldOffset += NestedField->Offset;
        assert(NestedField);
        if (!this->emitGetPtrThisField(InitFieldOffset, InitExpr))
          return false;
        if (!this->emitFinishInitPop(InitExpr))
          return false;
      }

      InitStack.pop_back_n(ChainSize - 1);

    } else {
      assert(Init->isDelegatingInitializer());
      if (!this->emitThis(InitExpr))
        return false;
      if (!this->visitInitializerPop(Init->getInit()))
        return false;
    }

    if (!Scope.destroyLocals())
      return false;
  }

  if (FieldInits != R->getNumFields()) {
    assert(FieldInits < R->getNumFields());
    // Start the lifetime of all members.
    if (!this->emitStartThisLifetime(Ctor))
      return false;
  }

  if (const Stmt *Body = Ctor->getBody()) {
    // Only emit the CtorCheck op for non-empty CompoundStmt bodies.
    // For non-CompoundStmts, always assume they are non-empty and emit it.
    if (const auto *CS = dyn_cast<CompoundStmt>(Body)) {
      if (!CS->body_empty() && !this->emitCtorCheck(SourceInfo{}))
        return false;
    } else {
      if (!this->emitCtorCheck(SourceInfo{}))
        return false;
    }

    if (!visitStmt(Body))
      return false;
  }

  return this->emitRetVoid(SourceInfo{});
}

template <class Emitter>
bool Compiler<Emitter>::compileDestructor(const CXXDestructorDecl *Dtor) {
  const RecordDecl *RD = Dtor->getParent();
  const Record *R = this->getRecord(RD);
  if (!R)
    return false;

  if (!Dtor->isTrivial() && Dtor->getBody()) {
    if (!this->visitStmt(Dtor->getBody()))
      return false;
  }

  if (!this->emitThis(Dtor))
    return false;

  if (!this->emitCheckDestruction(Dtor))
    return false;

  assert(R);
  if (!R->isUnion()) {

    LocOverrideScope<Emitter> LOS(this, SourceInfo{});
    // First, destroy all fields.
    for (const Record::Field &Field : llvm::reverse(R->fields())) {
      const Descriptor *D = Field.Desc;
      if (D->hasTrivialDtor())
        continue;
      if (!this->emitGetPtrField(Field.Offset, SourceInfo{}))
        return false;
      if (!this->emitDestructionPop(D, SourceInfo{}))
        return false;
    }
  }

  for (const Record::Base &Base : llvm::reverse(R->bases())) {
    if (Base.R->hasTrivialDtor())
      continue;
    if (!this->emitGetPtrBase(Base.Offset, SourceInfo{}))
      return false;
    if (!this->emitRecordDestructionPop(Base.R, {}))
      return false;
  }

  if (!this->emitMarkDestroyed(Dtor))
    return false;

  // FIXME: Virtual bases.
  return this->emitPopPtr(Dtor) && this->emitRetVoid(Dtor);
}

template <class Emitter>
bool Compiler<Emitter>::compileUnionAssignmentOperator(
    const CXXMethodDecl *MD) {
  if (!this->emitThis(MD))
    return false;

  if (!this->emitGetParam(PT_Ptr, /*ParamIndex=*/0, MD))
    return false;

  return this->emitMemcpy(MD) && this->emitRet(PT_Ptr, MD);
}

template <class Emitter>
bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
  if (F->getReturnType()->isDependentType())
    return false;

  // Classify the return type.
  ReturnType = this->classify(F->getReturnType());

  this->CompilingFunction = F;

  if (const auto *Ctor = dyn_cast<CXXConstructorDecl>(F))
    return this->compileConstructor(Ctor);
  if (const auto *Dtor = dyn_cast<CXXDestructorDecl>(F))
    return this->compileDestructor(Dtor);

  // Emit custom code if this is a lambda static invoker.
  if (const auto *MD = dyn_cast<CXXMethodDecl>(F)) {
    const RecordDecl *RD = MD->getParent();

    if (RD->isUnion() &&
        (MD->isCopyAssignmentOperator() || MD->isMoveAssignmentOperator()))
      return this->compileUnionAssignmentOperator(MD);

    if (MD->isLambdaStaticInvoker())
      return this->emitLambdaStaticInvokerBody(MD);
  }

  // Regular functions.
  if (const auto *Body = F->getBody())
    if (!visitStmt(Body))
      return false;

  // Emit a guard return to protect against a code path missing one.
  if (F->getReturnType()->isVoidType())
    return this->emitRetVoid(SourceInfo{});
  return this->emitNoRet(SourceInfo{});
}

static uint32_t getBitWidth(const Expr *E) {
  assert(E->refersToBitField());
  const auto *ME = cast<MemberExpr>(E);
  const auto *FD = cast<FieldDecl>(ME->getMemberDecl());
  return FD->getBitWidthValue();
}

template <class Emitter>
bool Compiler<Emitter>::VisitUnaryOperator(const UnaryOperator *E) {
  if (E->containsErrors())
    return false;

  const Expr *SubExpr = E->getSubExpr();
  if (SubExpr->getType()->isAnyComplexType())
    return this->VisitComplexUnaryOperator(E);
  if (SubExpr->getType()->isVectorType())
    return this->VisitVectorUnaryOperator(E);
  if (SubExpr->getType()->isFixedPointType())
    return this->VisitFixedPointUnaryOperator(E);
  OptPrimType T = classify(SubExpr->getType());

  switch (E->getOpcode()) {
  case UO_PostInc: { // x++
    if (!Ctx.getLangOpts().CPlusPlus14)
      return this->emitInvalid(E);
    if (!T)
      return this->emitError(E);

    if (!this->visit(SubExpr))
      return false;

    if (T == PT_Ptr) {
      if (!this->emitIncPtr(E))
        return false;

      return DiscardResult ? this->emitPopPtr(E) : true;
    }

    if (T == PT_Float)
      return DiscardResult ? this->emitIncfPop(getFPOptions(E), E)
                           : this->emitIncf(getFPOptions(E), E);

    if (SubExpr->refersToBitField())
      return DiscardResult ? this->emitIncPopBitfield(*T, E->canOverflow(),
                                                      getBitWidth(SubExpr), E)
                           : this->emitIncBitfield(*T, E->canOverflow(),
                                                   getBitWidth(SubExpr), E);

    return DiscardResult ? this->emitIncPop(*T, E->canOverflow(), E)
                         : this->emitInc(*T, E->canOverflow(), E);
  }
  case UO_PostDec: { // x--
    if (!Ctx.getLangOpts().CPlusPlus14)
      return this->emitInvalid(E);
    if (!T)
      return this->emitError(E);

    if (!this->visit(SubExpr))
      return false;

    if (T == PT_Ptr) {
      if (!this->emitDecPtr(E))
        return false;

      return DiscardResult ? this->emitPopPtr(E) : true;
    }

    if (T == PT_Float)
      return DiscardResult ? this->emitDecfPop(getFPOptions(E), E)
                           : this->emitDecf(getFPOptions(E), E);

    if (SubExpr->refersToBitField()) {
      return DiscardResult ? this->emitDecPopBitfield(*T, E->canOverflow(),
                                                      getBitWidth(SubExpr), E)
                           : this->emitDecBitfield(*T, E->canOverflow(),
                                                   getBitWidth(SubExpr), E);
    }

    return DiscardResult ? this->emitDecPop(*T, E->canOverflow(), E)
                         : this->emitDec(*T, E->canOverflow(), E);
  }
  case UO_PreInc: { // ++x
    if (!Ctx.getLangOpts().CPlusPlus14)
      return this->emitInvalid(E);
    if (!T)
      return this->emitError(E);

    if (!this->visit(SubExpr))
      return false;

    if (T == PT_Ptr) {
      if (!this->emitLoadPtr(E))
        return false;
      if (!this->emitConstUint8(1, E))
        return false;
      if (!this->emitAddOffsetUint8(E))
        return false;
      return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
    }

    // Post-inc and pre-inc are the same if the value is to be discarded.
    if (DiscardResult) {
      if (T == PT_Float)
        return this->emitIncfPop(getFPOptions(E), E);
      if (SubExpr->refersToBitField())
        return DiscardResult ? this->emitIncPopBitfield(*T, E->canOverflow(),
                                                        getBitWidth(SubExpr), E)
                             : this->emitIncBitfield(*T, E->canOverflow(),
                                                     getBitWidth(SubExpr), E);
      return this->emitIncPop(*T, E->canOverflow(), E);
    }

    if (T == PT_Float) {
      const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());
      if (!this->emitLoadFloat(E))
        return false;
      APFloat F(TargetSemantics, 1);
      if (!this->emitFloat(F, E))
        return false;

      if (!this->emitAddf(getFPOptions(E), E))
        return false;
      if (!this->emitStoreFloat(E))
        return false;
    } else if (SubExpr->refersToBitField()) {
      assert(isIntegerOrBoolType(*T));
      if (!this->emitPreIncBitfield(*T, E->canOverflow(), getBitWidth(SubExpr),
                                    E))
        return false;
    } else {
      assert(isIntegerOrBoolType(*T));
      if (!this->emitPreInc(*T, E->canOverflow(), E))
        return false;
    }
    return E->isGLValue() || this->emitLoadPop(*T, E);
  }
  case UO_PreDec: { // --x
    if (!Ctx.getLangOpts().CPlusPlus14)
      return this->emitInvalid(E);
    if (!T)
      return this->emitError(E);

    if (!this->visit(SubExpr))
      return false;

    if (T == PT_Ptr) {
      if (!this->emitLoadPtr(E))
        return false;
      if (!this->emitConstUint8(1, E))
        return false;
      if (!this->emitSubOffsetUint8(E))
        return false;
      return DiscardResult ? this->emitStorePopPtr(E) : this->emitStorePtr(E);
    }

    // Post-dec and pre-dec are the same if the value is to be discarded.
    if (DiscardResult) {
      if (T == PT_Float)
        return this->emitDecfPop(getFPOptions(E), E);
      if (SubExpr->refersToBitField())
        return DiscardResult ? this->emitDecPopBitfield(*T, E->canOverflow(),
                                                        getBitWidth(SubExpr), E)
                             : this->emitDecBitfield(*T, E->canOverflow(),
                                                     getBitWidth(SubExpr), E);
      return this->emitDecPop(*T, E->canOverflow(), E);
    }

    if (T == PT_Float) {
      const auto &TargetSemantics = Ctx.getFloatSemantics(E->getType());
      if (!this->emitLoadFloat(E))
        return false;
      APFloat F(TargetSemantics, 1);
      if (!this->emitFloat(F, E))
        return false;

      if (!this->emitSubf(getFPOptions(E), E))
        return false;
      if (!this->emitStoreFloat(E))
        return false;
    } else if (SubExpr->refersToBitField()) {
      assert(isIntegerOrBoolType(*T));
      if (!this->emitPreDecBitfield(*T, E->canOverflow(), getBitWidth(SubExpr),
                                    E))
        return false;
    } else {
      assert(isIntegerOrBoolType(*T));
      if (!this->emitPreDec(*T, E->canOverflow(), E))
        return false;
    }
    return E->isGLValue() || this->emitLoadPop(*T, E);
  }
  case UO_LNot: // !x
    if (!T)
      return this->emitError(E);

    if (DiscardResult)
      return this->discard(SubExpr);

    if (!this->visitBool(SubExpr))
      return false;

    if (!this->emitInv(E))
      return false;

    if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)
      return this->emitCast(PT_Bool, ET, E);
    return true;
  case UO_Minus: // -x
    if (!T)
      return this->emitError(E);

    if (!this->visit(SubExpr))
      return false;
    return DiscardResult ? this->emitPop(*T, E) : this->emitNeg(*T, E);
  case UO_Plus: // +x
    if (!T)
      return this->emitError(E);

    if (!this->visit(SubExpr)) // noop
      return false;
    return DiscardResult ? this->emitPop(*T, E) : true;
  case UO_AddrOf: // &x
    if (E->getType()->isMemberPointerType()) {
      // C++11 [expr.unary.op]p3 has very strict rules on how the address of a
      // member can be formed.
      if (DiscardResult)
        return true;
      return this->emitGetMemberPtr(cast<DeclRefExpr>(SubExpr)->getDecl(), E);
    }
    // [C11 6.5.3.2p3]: if the operand of '&' is the result of a unary '*'
    // operator, neither operator is evaluated and the result is as if both
    // were omitted. So '&*q' is just 'q' with no dereference; delegate to the
    // pointer operand directly instead of to the '*' (which would emit a null
    // check), so that e.g. '&*(int *)0' is not rejected.
    if (!Ctx.getLangOpts().CPlusPlus) {
      const Expr *Sub = SubExpr->IgnoreParens();
      if (const auto *Deref = dyn_cast<UnaryOperator>(Sub);
          Deref && Deref->getOpcode() == UO_Deref)
        return this->delegate(Deref->getSubExpr());
    }
    // We should already have a pointer when we get here.
    return this->delegate(SubExpr);
  case UO_Deref: // *x
    if (DiscardResult)
      return this->discard(SubExpr);

    if (!this->visit(SubExpr))
      return false;

    if (!SubExpr->getType()->isFunctionPointerType() && !this->emitCheckNull(E))
      return false;

    if (classifyPrim(SubExpr) == PT_Ptr)
      return this->emitNarrowPtr(E);
    return true;

  case UO_Not: // ~x
    if (!T)
      return this->emitError(E);

    if (!this->visit(SubExpr))
      return false;
    return DiscardResult ? this->emitPop(*T, E) : this->emitComp(*T, E);
  case UO_Real: // __real x
    if (!T)
      return false;
    return this->delegate(SubExpr);
  case UO_Imag: { // __imag x
    if (!T)
      return false;
    if (!this->discard(SubExpr))
      return false;
    return DiscardResult
               ? true
               : this->visitZeroInitializer(*T, SubExpr->getType(), SubExpr);
  }
  case UO_Extension:
    return this->delegate(SubExpr);
  case UO_Coawait:
    assert(false && "Unhandled opcode");
  }

  return false;
}

template <class Emitter>
bool Compiler<Emitter>::VisitComplexUnaryOperator(const UnaryOperator *E) {
  const Expr *SubExpr = E->getSubExpr();
  assert(SubExpr->getType()->isAnyComplexType());

  if (DiscardResult)
    return this->discard(SubExpr);

  OptPrimType ResT = classify(E);
  auto prepareResult = [=]() -> bool {
    if (!ResT && !Initializing) {
      UnsignedOrNone LocalIndex = allocateLocal(SubExpr);
      if (!LocalIndex)
        return false;
      return this->emitGetPtrLocal(*LocalIndex, E);
    }

    return true;
  };

  // The offset of the temporary, if we created one.
  unsigned SubExprOffset = ~0u;
  auto createTemp = [=, &SubExprOffset]() -> bool {
    SubExprOffset =
        this->allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);
    if (!this->visit(SubExpr))
      return false;
    return this->emitSetLocal(PT_Ptr, SubExprOffset, E);
  };

  PrimType ElemT = classifyComplexElementType(SubExpr->getType());
  auto getElem = [=](unsigned Offset, unsigned Index) -> bool {
    if (!this->emitGetLocal(PT_Ptr, Offset, E))
      return false;
    return this->emitArrayElemPop(ElemT, Index, E);
  };

  switch (E->getOpcode()) {
  case UO_Minus: // -x
    if (!prepareResult())
      return false;
    if (!createTemp())
      return false;
    for (unsigned I = 0; I != 2; ++I) {
      if (!getElem(SubExprOffset, I))
        return false;
      if (!this->emitNeg(ElemT, E))
        return false;
      if (!this->emitInitElem(ElemT, I, E))
        return false;
    }
    break;

  case UO_Plus:   // +x
  case UO_AddrOf: // &x
  case UO_Deref:  // *x
    return this->delegate(SubExpr);

  case UO_LNot:
    if (!this->visit(SubExpr))
      return false;
    if (!this->emitComplexBoolCast(SubExpr))
      return false;
    if (!this->emitInv(E))
      return false;
    if (PrimType ET = classifyPrim(E->getType()); ET != PT_Bool)
      return this->emitCast(PT_Bool, ET, E);
    return true;

  case UO_Real:
    return this->emitComplexReal(SubExpr);

  case UO_Imag:
    if (!this->visit(SubExpr))
      return false;

    if (SubExpr->isLValue()) {
      if (!this->emitConstUint8(1, E))
        return false;
      return this->emitArrayElemPtrPopUint8(E);
    }

    // Since our _Complex implementation does not map to a primitive type,
    // we sometimes have to do the lvalue-to-rvalue conversion here manually.
    return this->emitArrayElemPop(classifyPrim(E->getType()), 1, E);

  case UO_Not: // ~x
    if (!this->delegate(SubExpr))
      return false;
    // Negate the imaginary component.
    if (!this->emitArrayElem(ElemT, 1, E))
      return false;
    if (!this->emitNeg(ElemT, E))
      return false;
    if (!this->emitInitElem(ElemT, 1, E))
      return false;
    return DiscardResult ? this->emitPopPtr(E) : true;

  case UO_Extension:
    return this->delegate(SubExpr);

  default:
    return this->emitInvalid(E);
  }

  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitVectorUnaryOperator(const UnaryOperator *E) {
  const Expr *SubExpr = E->getSubExpr();
  assert(SubExpr->getType()->isVectorType());

  if (DiscardResult)
    return this->discard(SubExpr);

  auto UnaryOp = E->getOpcode();
  if (UnaryOp == UO_Extension)
    return this->delegate(SubExpr);

  if (UnaryOp != UO_Plus && UnaryOp != UO_Minus && UnaryOp != UO_LNot &&
      UnaryOp != UO_Not && UnaryOp != UO_AddrOf)
    return this->emitInvalid(E);

  // Nothing to do here.
  if (UnaryOp == UO_Plus || UnaryOp == UO_AddrOf)
    return this->delegate(SubExpr);

  if (!Initializing) {
    UnsignedOrNone LocalIndex = allocateLocal(SubExpr);
    if (!LocalIndex)
      return false;
    if (!this->emitGetPtrLocal(*LocalIndex, E))
      return false;
  }

  // The offset of the temporary, if we created one.
  unsigned SubExprOffset =
      this->allocateLocalPrimitive(SubExpr, PT_Ptr, /*IsConst=*/true);
  if (!this->visit(SubExpr))
    return false;
  if (!this->emitSetLocal(PT_Ptr, SubExprOffset, E))
    return false;

  const auto *VecTy = SubExpr->getType()->getAs<VectorType>();
  PrimType ElemT = classifyVectorElementType(SubExpr->getType());
  auto getElem = [=](unsigned Offset, unsigned Index) -> bool {
    if (!this->emitGetLocal(PT_Ptr, Offset, E))
      return false;
    return this->emitArrayElemPop(ElemT, Index, E);
  };

  switch (UnaryOp) {
  case UO_Minus:
    for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {
      if (!getElem(SubExprOffset, I))
        return false;
      if (!this->emitNeg(ElemT, E))
        return false;
      if (!this->emitInitElem(ElemT, I, E))
        return false;
    }
    break;
  case UO_LNot: { // !x
    // In C++, the logic operators !, &&, || are available for vectors. !v is
    // equivalent to v == 0.
    //
    // The result of the comparison is a vector of the same width and number of
    // elements as the comparison operands with a signed integral element type.
    //
    // https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
    QualType ResultVecTy = E->getType();
    PrimType ResultVecElemT =
        classifyPrim(ResultVecTy->getAs<VectorType>()->getElementType());
    for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {
      if (!getElem(SubExprOffset, I))
        return false;
      // operator ! on vectors returns -1 for 'truth', so negate it.
      if (!this->emitPrimCast(ElemT, PT_Bool, Ctx.getASTContext().BoolTy, E))
        return false;
      if (!this->emitInv(E))
        return false;
      if (!this->emitPrimCast(PT_Bool, ElemT, VecTy->getElementType(), E))
        return false;
      if (!this->emitNeg(ElemT, E))
        return false;
      if (ElemT != ResultVecElemT &&
          !this->emitPrimCast(ElemT, ResultVecElemT, ResultVecTy, E))
        return false;
      if (!this->emitInitElem(ResultVecElemT, I, E))
        return false;
    }
    break;
  }
  case UO_Not: // ~x
    for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {
      if (!getElem(SubExprOffset, I))
        return false;
      if (ElemT == PT_Bool) {
        if (!this->emitInv(E))
          return false;
      } else {
        if (!this->emitComp(ElemT, E))
          return false;
      }
      if (!this->emitInitElem(ElemT, I, E))
        return false;
    }
    break;
  default:
    llvm_unreachable("Unsupported unary operators should be handled up front");
  }
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::visitDeclRef(const ValueDecl *D, const Expr *E) {
  if (DiscardResult)
    return true;

  if (const auto *ECD = dyn_cast<EnumConstantDecl>(D))
    return this->emitConst(ECD->getInitVal(), E);
  if (const auto *FuncDecl = dyn_cast<FunctionDecl>(D)) {
    const Function *F = getFunction(FuncDecl);
    return F && this->emitGetFnPtr(F, E);
  }
  if (const auto *TPOD = dyn_cast<TemplateParamObjectDecl>(D)) {
    if (UnsignedOrNone Index = P.getOrCreateGlobal(D)) {
      if (OptPrimType T = classify(D->getType())) {
        if (!this->visitAPValue(TPOD->getValue(), *T, E))
          return false;
        return this->emitInitGlobal(*T, *Index, E);
      }

      if (!this->emitGetPtrGlobal(*Index, E))
        return false;
      if (!this->visitAPValueInitializer(TPOD->getValue(), E, TPOD->getType()))
        return false;
      return this->emitFinishInit(E);
    }
    return false;
  }

  // References are implemented via pointers, so when we see a DeclRefExpr
  // pointing to a reference, we need to get its value directly (i.e. the
  // pointer to the actual value) instead of a pointer to the pointer to the
  // value.
  QualType DeclType = D->getType();
  bool IsReference = DeclType->isReferenceType();

  // Function parameters.
  // Note that it's important to check them first since we might have a local
  // variable created for a ParmVarDecl as well.
  if (const auto *PVD = dyn_cast<ParmVarDecl>(D)) {
    if (Ctx.getLangOpts().CPlusPlus && !Ctx.getLangOpts().CPlusPlus11 &&
        !DeclType->isIntegralOrEnumerationType()) {
      return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),
                                      /*InitializerFailed=*/false, E);
    }
    if (auto It = this->Params.find(PVD); It != this->Params.end()) {
      if (IsReference || !It->second.IsPtr)
        return this->emitGetParam(classifyPrim(E), It->second.Index, E);

      return this->emitGetPtrParam(It->second.Index, E);
    }

    if (!Ctx.getLangOpts().CPlusPlus23 && IsReference)
      return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),
                                      /*InitializerFailed=*/false, E);
  }
  // Local variables.
  if (auto It = Locals.find(D); It != Locals.end()) {
    const unsigned Offset = It->second.Offset;
    if (IsReference) {
      assert(classifyPrim(E) == PT_Ptr);
      return this->emitGetRefLocal(Offset, E);
    }
    return this->emitGetPtrLocal(Offset, E);
  }
  // Global variables.
  if (auto GlobalIndex = P.getGlobal(D)) {
    if (IsReference) {
      if (!Ctx.getLangOpts().CPlusPlus11)
        return this->emitGetGlobal(classifyPrim(E), *GlobalIndex, E);
      if (!Ctx.getLangOpts().CPlusPlus23)
        return this->emitGetGlobalUnchecked(classifyPrim(E), *GlobalIndex, E);
      return this->emitGetRefGlobal(*GlobalIndex, E);
    }

    return this->emitGetPtrGlobal(*GlobalIndex, E);
  }

  // In case we need to re-visit a declaration.
  auto revisit = [&](const VarDecl *VD,
                     bool IsConstexprUnknown = true) -> bool {
    llvm::SaveAndRestore CURS(this->VariablesAreConstexprUnknown,
                              IsConstexprUnknown);
    if (!this->emitPushCC(VD->hasConstantInitialization(), E))
      return false;
    auto VarState = this->visitDecl(VD);

    if (!this->emitPopCC(E))
      return false;

    if (VarState.notCreated())
      return true;
    if (!VarState)
      return false;
    // Retry.
    return this->visitDeclRef(D, E);
  };

  if constexpr (!std::is_same_v<Emitter, EvalEmitter>) {
    // Lambda captures.
    if (auto It = this->LambdaCaptures.find(D);
        It != this->LambdaCaptures.end()) {
      auto [Offset, IsPtr] = It->second;

      if (IsPtr)
        return this->emitGetThisFieldPtr(Offset, E);
      return this->emitGetPtrThisField(Offset, E);
    }
  }

  if (const auto *DRE = dyn_cast<DeclRefExpr>(E);
      DRE && DRE->refersToEnclosingVariableOrCapture()) {
    if (const auto *VD = dyn_cast<VarDecl>(D); VD && VD->isInitCapture())
      return revisit(VD);
  }

  if (const auto *BD = dyn_cast<BindingDecl>(D))
    return this->visit(BD->getBinding());

  // Avoid infinite recursion.
  if (D == InitializingDecl)
    return this->emitDummyPtr(D, E);

  // Try to lazily visit (or emit dummy pointers for) declarations
  // we haven't seen yet.
  const auto *VD = dyn_cast<VarDecl>(D);
  if (!VD)
    return this->emitError(E);

  // For C.
  if (!Ctx.getLangOpts().CPlusPlus) {
    if (VD->getInit() && !VD->getInit()->isValueDependent() &&
        DeclType.isConstant(Ctx.getASTContext()) && !VD->isWeak() &&
        VD->evaluateValue())
      return revisit(VD, /*IsConstexprUnknown=*/false);
    return this->emitDummyPtr(D, E);
  }

  // ... and C++.
  const auto typeShouldBeVisited = [&](QualType T) -> bool {
    if (T.isConstant(Ctx.getASTContext()))
      return true;
    return T->isReferenceType();
  };

  if ((VD->hasGlobalStorage() || VD->isStaticDataMember()) &&
      typeShouldBeVisited(DeclType)) {
    if (const Expr *Init = VD->getAnyInitializer();
        Init && !Init->isValueDependent()) {
      // Whether or not the evaluation is successul doesn't really matter
      // here -- we will create a global variable in any case, and that
      // will have the state of initializer evaluation attached.
      APValue V;
      SmallVector<PartialDiagnosticAt> Notes;
      (void)Init->EvaluateAsInitializer(V, Ctx.getASTContext(), VD, Notes,
                                        true);
      return this->visitDeclRef(D, E);
    }
    return revisit(VD, !VD->isConstexpr() && DeclType->isReferenceType());
  }

  // FIXME: The evaluateValue() check here is a little ridiculous, since
  // it will ultimately call into Context::evaluateAsInitializer(). In
  // other words, we're evaluating the initializer, just to know if we can
  // evaluate the initializer.
  if (VD->isLocalVarDecl() && typeShouldBeVisited(DeclType) && VD->getInit() &&
      !VD->getInit()->isValueDependent()) {
    if (VD->evaluateValue()) {
      bool IsConstexprUnknown = !DeclType.isConstant(Ctx.getASTContext()) &&
                                !DeclType->isReferenceType();
      // Revisit the variable declaration, but make sure it's associated with a
      // different evaluation, so e.g. mutable reads don't work on it.
      EvalIDScope _(Ctx);
      return revisit(VD, IsConstexprUnknown);
    } else if (Ctx.getLangOpts().CPlusPlus23 && IsReference)
      return revisit(VD, /*IsConstexprUnknown=*/true);

    if (IsReference)
      return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),
                                      /*InitializerFailed=*/true, E);
  }

  return this->emitDummyPtr(
      D, E, Ctx.getLangOpts().CPlusPlus23 && DeclType->isReferenceType());
}

template <class Emitter>
bool Compiler<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
  const auto *D = E->getDecl();
  return this->visitDeclRef(D, E);
}

template <class Emitter>
bool Compiler<Emitter>::VisitDesignatedInitUpdateExpr(
    const DesignatedInitUpdateExpr *E) {
  if (!this->visitInitializer(E->getBase()))
    return false;
  return this->visitInitializer(E->getUpdater());
}

template <class Emitter> bool Compiler<Emitter>::emitCleanup() {
  for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent()) {
    if (!C->destroyLocals())
      return false;
  }
  return true;
}

template <class Emitter>
unsigned Compiler<Emitter>::collectBaseOffset(const QualType BaseType,
                                              const QualType DerivedType) {
  const auto extractRecordDecl = [](QualType Ty) -> const CXXRecordDecl * {
    if (const auto *R = Ty->getPointeeCXXRecordDecl())
      return R;
    return Ty->getAsCXXRecordDecl();
  };
  const CXXRecordDecl *BaseDecl = extractRecordDecl(BaseType);
  const CXXRecordDecl *DerivedDecl = extractRecordDecl(DerivedType);

  return Ctx.collectBaseOffset(BaseDecl, DerivedDecl);
}

/// Emit casts from a PrimType to another PrimType.
template <class Emitter>
bool Compiler<Emitter>::emitPrimCast(PrimType FromT, PrimType ToT,
                                     QualType ToQT, const Expr *E) {

  if (FromT == PT_Float) {
    // Floating to floating.
    if (ToT == PT_Float) {
      const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);
      return this->emitCastFP(ToSem, getRoundingMode(E), E);
    }

    if (ToT == PT_IntAP)
      return this->emitCastFloatingIntegralAP(Ctx.getBitWidth(ToQT),
                                              getFPOptions(E), E);
    if (ToT == PT_IntAPS)
      return this->emitCastFloatingIntegralAPS(Ctx.getBitWidth(ToQT),
                                               getFPOptions(E), E);

    // Float to integral.
    if (isIntegerOrBoolType(ToT) || ToT == PT_Bool)
      return this->emitCastFloatingIntegral(ToT, getFPOptions(E), E);
  }

  if (isIntegerOrBoolType(FromT) || FromT == PT_Bool) {
    if (ToT == PT_IntAP)
      return this->emitCastAP(FromT, Ctx.getBitWidth(ToQT), E);
    if (ToT == PT_IntAPS)
      return this->emitCastAPS(FromT, Ctx.getBitWidth(ToQT), E);

    // Integral to integral.
    if (isIntegerOrBoolType(ToT) || ToT == PT_Bool)
      return FromT != ToT ? this->emitCast(FromT, ToT, E) : true;

    if (ToT == PT_Float) {
      // Integral to floating.
      const llvm::fltSemantics *ToSem = &Ctx.getFloatSemantics(ToQT);
      return this->emitCastIntegralFloating(FromT, ToSem, getFPOptions(E), E);
    }
  }

  return false;
}

template <class Emitter>
bool Compiler<Emitter>::emitIntegralCast(PrimType FromT, PrimType ToT,
                                         QualType ToQT, const Expr *E) {
  assert(FromT != ToT);

  if (ToT == PT_IntAP)
    return this->emitCastAP(FromT, Ctx.getBitWidth(ToQT), E);
  if (ToT == PT_IntAPS)
    return this->emitCastAPS(FromT, Ctx.getBitWidth(ToQT), E);

  return this->emitCast(FromT, ToT, E);
}

/// Emits __real(SubExpr)
template <class Emitter>
bool Compiler<Emitter>::emitComplexReal(const Expr *SubExpr) {
  assert(SubExpr->getType()->isAnyComplexType());

  if (DiscardResult)
    return this->discard(SubExpr);

  if (!this->visit(SubExpr))
    return false;
  if (SubExpr->isLValue()) {
    if (!this->emitConstUint8(0, SubExpr))
      return false;
    return this->emitArrayElemPtrPopUint8(SubExpr);
  }

  // Rvalue, load the actual element.
  return this->emitArrayElemPop(classifyComplexElementType(SubExpr->getType()),
                                0, SubExpr);
}

template <class Emitter>
bool Compiler<Emitter>::emitComplexBoolCast(const Expr *E) {
  assert(!DiscardResult);
  PrimType ElemT = classifyComplexElementType(E->getType());
  // We emit the expression (__real(E) != 0 || __imag(E) != 0)
  // for us, that means (bool)E[0] || (bool)E[1]
  if (!this->emitArrayElem(ElemT, 0, E))
    return false;
  if (ElemT == PT_Float) {
    if (!this->emitCastFloatingIntegral(PT_Bool, getFPOptions(E), E))
      return false;
  } else {
    if (!this->emitCast(ElemT, PT_Bool, E))
      return false;
  }

  // We now have the bool value of E[0] on the stack.
  LabelTy LabelTrue = this->getLabel();
  if (!this->jumpTrue(LabelTrue, E))
    return false;

  if (!this->emitArrayElemPop(ElemT, 1, E))
    return false;
  if (ElemT == PT_Float) {
    if (!this->emitCastFloatingIntegral(PT_Bool, getFPOptions(E), E))
      return false;
  } else {
    if (!this->emitCast(ElemT, PT_Bool, E))
      return false;
  }
  // Leave the boolean value of E[1] on the stack.
  LabelTy EndLabel = this->getLabel();
  this->jump(EndLabel, E);

  this->emitLabel(LabelTrue);
  if (!this->emitPopPtr(E))
    return false;
  if (!this->emitConstBool(true, E))
    return false;

  this->fallthrough(EndLabel);
  this->emitLabel(EndLabel);

  return true;
}

template <class Emitter>
bool Compiler<Emitter>::emitComplexComparison(const Expr *LHS, const Expr *RHS,
                                              const BinaryOperator *E) {
  assert(E->isComparisonOp());
  assert(!Initializing);
  if (DiscardResult)
    return this->discard(LHS) && this->discard(RHS);

  PrimType ElemT;
  bool LHSIsComplex;
  unsigned LHSOffset;
  if (LHS->getType()->isAnyComplexType()) {
    LHSIsComplex = true;
    ElemT = classifyComplexElementType(LHS->getType());
    LHSOffset = allocateLocalPrimitive(LHS, PT_Ptr, /*IsConst=*/true);
    if (!this->visit(LHS))
      return false;
    if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
      return false;
  } else {
    LHSIsComplex = false;
    PrimType LHST = classifyPrim(LHS->getType());
    LHSOffset = this->allocateLocalPrimitive(LHS, LHST, /*IsConst=*/true);
    if (!this->visit(LHS))
      return false;
    if (!this->emitSetLocal(LHST, LHSOffset, E))
      return false;
  }

  bool RHSIsComplex;
  unsigned RHSOffset;
  if (RHS->getType()->isAnyComplexType()) {
    RHSIsComplex = true;
    ElemT = classifyComplexElementType(RHS->getType());
    RHSOffset = allocateLocalPrimitive(RHS, PT_Ptr, /*IsConst=*/true);
    if (!this->visit(RHS))
      return false;
    if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
      return false;
  } else {
    RHSIsComplex = false;
    PrimType RHST = classifyPrim(RHS->getType());
    RHSOffset = this->allocateLocalPrimitive(RHS, RHST, /*IsConst=*/true);
    if (!this->visit(RHS))
      return false;
    if (!this->emitSetLocal(RHST, RHSOffset, E))
      return false;
  }

  auto getElem = [&](unsigned LocalOffset, unsigned Index,
                     bool IsComplex) -> bool {
    if (IsComplex) {
      if (!this->emitGetLocal(PT_Ptr, LocalOffset, E))
        return false;
      return this->emitArrayElemPop(ElemT, Index, E);
    }
    return this->emitGetLocal(ElemT, LocalOffset, E);
  };

  for (unsigned I = 0; I != 2; ++I) {
    // Get both values.
    if (!getElem(LHSOffset, I, LHSIsComplex))
      return false;
    if (!getElem(RHSOffset, I, RHSIsComplex))
      return false;
    // And compare them.
    if (!this->emitEQ(ElemT, E))
      return false;

    if (!this->emitCastBoolUint8(E))
      return false;
  }

  // We now have two bool values on the stack. Compare those.
  if (!this->emitAddUint8(E))
    return false;
  if (!this->emitConstUint8(2, E))
    return false;

  if (E->getOpcode() == BO_EQ) {
    if (!this->emitEQUint8(E))
      return false;
  } else if (E->getOpcode() == BO_NE) {
    if (!this->emitNEUint8(E))
      return false;
  } else
    return false;

  // In C, this returns an int.
  if (PrimType ResT = classifyPrim(E->getType()); ResT != PT_Bool)
    return this->emitCast(PT_Bool, ResT, E);
  return true;
}

/// When calling this, we have a pointer of the local-to-destroy
/// on the stack.
/// Emit destruction of record types (or arrays of record types).
template <class Emitter>
bool Compiler<Emitter>::emitRecordDestructionPop(const Record *R,
                                                 SourceInfo Loc) {
  assert(R);
  assert(!R->hasTrivialDtor());
  const CXXDestructorDecl *Dtor = R->getDestructor();
  assert(Dtor);
  const Function *DtorFunc = getFunction(Dtor);
  if (!DtorFunc)
    return false;
  assert(DtorFunc->hasThisPointer());
  assert(DtorFunc->getNumParams() == 1);
  return this->emitCall(DtorFunc, 0, Loc);
}
/// When calling this, we have a pointer of the local-to-destroy
/// on the stack.
/// Emit destruction of record types (or arrays of record types).
template <class Emitter>
bool Compiler<Emitter>::emitDestructionPop(const Descriptor *Desc,
                                           SourceInfo Loc) {
  assert(Desc);
  assert(!Desc->hasTrivialDtor());

  // Arrays.
  if (Desc->isArray()) {
    const Descriptor *ElemDesc = Desc->ElemDesc;
    assert(ElemDesc);

    unsigned N = Desc->getNumElems();
    if (N == 0)
      return this->emitPopPtr(Loc);

    for (ssize_t I = N - 1; I >= 1; --I) {
      if (!this->emitConstUint64(I, Loc))
        return false;
      if (!this->emitArrayElemPtrUint64(Loc))
        return false;
      if (!this->emitDestructionPop(ElemDesc, Loc))
        return false;
    }
    // Last iteration, removes the instance pointer from the stack.
    if (!this->emitConstUint64(0, Loc))
      return false;
    if (!this->emitArrayElemPtrPopUint64(Loc))
      return false;
    return this->emitDestructionPop(ElemDesc, Loc);
  }

  assert(Desc->ElemRecord);
  assert(!Desc->ElemRecord->hasTrivialDtor());
  return this->emitRecordDestructionPop(Desc->ElemRecord, Loc);
}

/// Create a dummy pointer for the given decl (or expr) and
/// push a pointer to it on the stack.
template <class Emitter>
bool Compiler<Emitter>::emitDummyPtr(const DeclTy &D, const Expr *E, bool CU) {
  assert(!DiscardResult && "Should've been checked before");
  unsigned DummyID = P.getOrCreateDummy(D, CU);

  if (!this->emitGetPtrGlobal(DummyID, E))
    return false;
  if (E->getType()->isVoidType())
    return true;

  // Convert the dummy pointer to another pointer type if we have to.
  if (PrimType PT = classifyPrim(E); PT != PT_Ptr) {
    if (isPtrType(PT))
      return this->emitDecayPtr(PT_Ptr, PT, E);
    return false;
  }
  return true;
}

template <class Emitter>
bool Compiler<Emitter>::emitFloat(const APFloat &F, const Expr *E) {
  if (Floating::singleWord(F.getSemantics()))
    return this->emitConstFloat(Floating(F), E);

  APInt I = F.bitcastToAPInt();
  return this->emitConstFloat(
      Floating(const_cast<uint64_t *>(I.getRawData()),
               llvm::APFloatBase::SemanticsToEnum(F.getSemantics())),
      E);
}

//  This function is constexpr if and only if To, From, and the types of
//  all subobjects of To and From are types T such that...
//  (3.1) - is_union_v<T> is false;
//  (3.2) - is_pointer_v<T> is false;
//  (3.3) - is_member_pointer_v<T> is false;
//  (3.4) - is_volatile_v<T> is false; and
//  (3.5) - T has no non-static data members of reference type
template <class Emitter>
bool Compiler<Emitter>::emitBuiltinBitCast(const CastExpr *E) {
  const Expr *SubExpr = E->getSubExpr();
  QualType FromType = SubExpr->getType();
  QualType ToType = E->getType();
  OptPrimType ToT = classify(ToType);

  assert(!ToType->isReferenceType());

  // Prepare storage for the result in case we discard.
  if (DiscardResult && !Initializing && !ToT) {
    UnsignedOrNone LocalIndex = allocateLocal(E);
    if (!LocalIndex)
      return false;
    if (!this->emitGetPtrLocal(*LocalIndex, E))
      return false;
  }

  // Get a pointer to the value-to-cast on the stack.
  // For CK_LValueToRValueBitCast, this is always an lvalue and
  // we later assume it to be one (i.e. a PT_Ptr). However,
  // we call this function for other utility methods where
  // a bitcast might be useful, so convert it to a PT_Ptr in that case.
  if (SubExpr->isGLValue() || FromType->isVectorType()) {
    if (!this->visit(SubExpr))
      return false;
  } else if (OptPrimType FromT = classify(SubExpr)) {
    unsigned TempOffset =
        allocateLocalPrimitive(SubExpr, *FromT, /*IsConst=*/true);
    if (!this->visit(SubExpr))
      return false;
    if (!this->emitSetLocal(*FromT, TempOffset, E))
      return false;
    if (!this->emitGetPtrLocal(TempOffset, E))
      return false;
  } else {
    return false;
  }

  if (!ToT) {
    if (!this->emitBitCast(E))
      return false;
    return DiscardResult ? this->emitPopPtr(E) : true;
  }
  assert(ToT);

  const llvm::fltSemantics *TargetSemantics = nullptr;
  if (ToT == PT_Float)
    TargetSemantics = &Ctx.getFloatSemantics(ToType);

  // Conversion to a primitive type. FromType can be another
  // primitive type, or a record/array.
  bool ToTypeIsUChar = (ToType->isSpecificBuiltinType(BuiltinType::UChar) ||
                        ToType->isSpecificBuiltinType(BuiltinType::Char_U));
  uint32_t ResultBitWidth = std::max(Ctx.getBitWidth(ToType), 8u);

  if (!this->emitBitCastPrim(*ToT, ToTypeIsUChar || ToType->isStdByteType(),
                             ResultBitWidth, TargetSemantics,
                             ToType.getTypePtr(), E))
    return false;

  if (DiscardResult)
    return this->emitPop(*ToT, E);

  return true;
}

/// Replicate a scalar value into every scalar element of an aggregate.
/// The scalar is stored in a local at \p SrcOffset and a pointer to the
/// destination must be on top of the interpreter stack. Each element receives
/// the scalar, cast to its own type.
template <class Emitter>
bool Compiler<Emitter>::emitHLSLAggregateSplat(PrimType SrcT,
                                               unsigned SrcOffset,
                                               QualType DestType,
                                               const Expr *E) {
  // Vectors and matrices are treated as flat sequences of elements.
  unsigned NumElems = 0;
  QualType ElemType;
  if (const auto *VT = DestType->getAs<VectorType>()) {
    NumElems = VT->getNumElements();
    ElemType = VT->getElementType();
  } else if (const auto *MT = DestType->getAs<ConstantMatrixType>()) {
    NumElems = MT->getNumElementsFlattened();
    ElemType = MT->getElementType();
  }
  if (NumElems > 0) {
    PrimType ElemT = classifyPrim(ElemType);
    for (unsigned I = 0; I != NumElems; ++I) {
      if (!this->emitGetLocal(SrcT, SrcOffset, E))
        return false;
      if (!this->emitPrimCast(SrcT, ElemT, ElemType, E))
        return false;
      if (!this->emitInitElem(ElemT, I, E))
        return false;
    }
    return true;
  }

  // Arrays: primitive elements are filled directly; composite elements
  // require recursion into each sub-aggregate.
  if (const auto *AT = DestType->getAsArrayTypeUnsafe()) {
    const auto *CAT = cast<ConstantArrayType>(AT);
    QualType ArrElemType = CAT->getElementType();
    unsigned ArrSize = CAT->getZExtSize();

    if (OptPrimType ElemT = classify(ArrElemType)) {
      for (unsigned I = 0; I != ArrSize; ++I) {
        if (!this->emitGetLocal(SrcT, SrcOffset, E))
          return false;
        if (!this->emitPrimCast(SrcT, *ElemT, ArrElemType, E))
          return false;
        if (!this->emitInitElem(*ElemT, I, E))
          return false;
      }
    } else {
      for (unsigned I = 0; I != ArrSize; ++I) {
        if (!this->emitConstUint32(I, E))
          return false;
        if (!this->emitArrayElemPtrUint32(E))
          return false;
        if (!emitHLSLAggregateSplat(SrcT, SrcOffset, ArrElemType, E))
          return false;
        if (!this->emitFinishInitPop(E))
          return false;
      }
    }
    return true;
  }

  // Records: fill base classes first, then named fields in declaration
  // order.
  if (DestType->isRecordType()) {
    const Record *R = getRecord(DestType);
    if (!R)
      return false;

    if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(R->getDecl())) {
      for (const CXXBaseSpecifier &BS : CXXRD->bases()) {
        const Record::Base *B = R->getBase(BS.getType());
        assert(B);
        if (!this->emitGetPtrBase(B->Offset, E))
          return false;
        if (!emitHLSLAggregateSplat(SrcT, SrcOffset, BS.getType(), E))
          return false;
        if (!this->emitFinishInitPop(E))
          return false;
      }
    }

    for (const Record::Field &F : R->fields()) {
      if (F.isUnnamedBitField())
        continue;

      QualType FieldType = F.Decl->getType();
      if (OptPrimType FieldT = classify(FieldType)) {
        if (!this->emitGetLocal(SrcT, SrcOffset, E))
          return false;
        if (!this->emitPrimCast(SrcT, *FieldT, FieldType, E))
          return false;
        if (F.isBitField()) {
          if (!this->emitInitBitField(*FieldT, F.Offset, F.bitWidth(), E))
            return false;
        } else {
          if (!this->emitInitField(*FieldT, F.Offset, E))
            return false;
        }
      } else {
        if (!this->emitGetPtrField(F.Offset, E))
          return false;
        if (!emitHLSLAggregateSplat(SrcT, SrcOffset, FieldType, E))
          return false;
        if (!this->emitPopPtr(E))
          return false;
      }
    }
    return true;
  }

  return false;
}

/// Return the total number of scalar elements in a type. This is used
/// to cap how many source elements are extracted during an elementwise cast,
/// so we never flatten more than the destination can hold.
template <class Emitter>
unsigned Compiler<Emitter>::countHLSLFlatElements(QualType Ty) {
  // Vector and matrix types are treated as flat sequences of elements.
  if (const auto *VT = Ty->getAs<VectorType>())
    return VT->getNumElements();
  if (const auto *MT = Ty->getAs<ConstantMatrixType>())
    return MT->getNumElementsFlattened();
  // Arrays: total count is array size * scalar elements per element.
  if (const auto *AT = Ty->getAsArrayTypeUnsafe()) {
    const auto *CAT = cast<ConstantArrayType>(AT);
    return CAT->getZExtSize() * countHLSLFlatElements(CAT->getElementType());
  }
  // Records: sum scalar element counts of base classes and named fields.
  if (Ty->isRecordType()) {
    const Record *R = getRecord(Ty);
    if (!R)
      return 0;
    unsigned Count = 0;
    if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(R->getDecl())) {
      for (const CXXBaseSpecifier &BS : CXXRD->bases())
        Count += countHLSLFlatElements(BS.getType());
    }
    for (const Record::Field &F : R->fields()) {
      if (F.isUnnamedBitField())
        continue;
      Count += countHLSLFlatElements(F.Decl->getType());
    }
    return Count;
  }
  // Scalar primitive types contribute one element.
  if (canClassify(Ty))
    return 1;
  return 0;
}

/// Walk a source aggregate and extract every scalar element into its own local
/// variable. The results are appended to \p Elements in declaration order,
/// stopping once \p MaxElements have been collected. A pointer to the
/// source aggregate must be stored in the local at \p SrcOffset.
template <class Emitter>
bool Compiler<Emitter>::emitHLSLFlattenAggregate(
    QualType SrcType, unsigned SrcOffset,
    SmallVectorImpl<HLSLFlatElement> &Elements, unsigned MaxElements,
    const Expr *E) {

  // Save a scalar value from the stack into a new local and record it.
  auto saveToLocal = [&](PrimType T) -> bool {
    unsigned Offset = allocateLocalPrimitive(E, T, /*IsConst=*/true);
    if (!this->emitSetLocal(T, Offset, E))
      return false;
    Elements.push_back({Offset, T});
    return true;
  };

  // Save a pointer from the stack into a new local for later use.
  auto savePtrToLocal = [&]() -> UnsignedOrNone {
    unsigned Offset = allocateLocalPrimitive(E, PT_Ptr, /*IsConst=*/true);
    if (!this->emitSetLocal(PT_Ptr, Offset, E))
      return std::nullopt;
    return Offset;
  };

  // Vectors and matrices are flat sequences of elements.
  unsigned NumElems = 0;
  QualType ElemType;
  if (const auto *VT = SrcType->getAs<VectorType>()) {
    NumElems = VT->getNumElements();
    ElemType = VT->getElementType();
  } else if (const auto *MT = SrcType->getAs<ConstantMatrixType>()) {
    NumElems = MT->getNumElementsFlattened();
    ElemType = MT->getElementType();
  }
  if (NumElems > 0) {
    PrimType ElemT = classifyPrim(ElemType);
    for (unsigned I = 0; I != NumElems && Elements.size() < MaxElements; ++I) {
      if (!this->emitGetLocal(PT_Ptr, SrcOffset, E))
        return false;
      if (!this->emitArrayElemPop(ElemT, I, E))
        return false;
      if (!saveToLocal(ElemT))
        return false;
    }
    return true;
  }

  // Arrays: primitive elements are extracted directly; composite elements
  // require recursion into each sub-aggregate.
  if (const auto *AT = SrcType->getAsArrayTypeUnsafe()) {
    const auto *CAT = cast<ConstantArrayType>(AT);
    QualType ArrElemType = CAT->getElementType();
    unsigned ArrSize = CAT->getZExtSize();

    if (OptPrimType ElemT = classify(ArrElemType)) {
      for (unsigned I = 0; I != ArrSize && Elements.size() < MaxElements; ++I) {
        if (!this->emitGetLocal(PT_Ptr, SrcOffset, E))
          return false;
        if (!this->emitArrayElemPop(*ElemT, I, E))
          return false;
        if (!saveToLocal(*ElemT))
          return false;
      }
    } else {
      for (unsigned I = 0; I != ArrSize && Elements.size() < MaxElements; ++I) {
        if (!this->emitGetLocal(PT_Ptr, SrcOffset, E))
          return false;
        if (!this->emitConstUint32(I, E))
          return false;
        if (!this->emitArrayElemPtrPopUint32(E))
          return false;
        UnsignedOrNone ElemPtrOffset = savePtrToLocal();
        if (!ElemPtrOffset)
          return false;
        if (!emitHLSLFlattenAggregate(ArrElemType, *ElemPtrOffset, Elements,
                                      MaxElements, E))
          return false;
      }
    }
    return true;
  }

  // Records: base classes come first, then named fields in declaration
  // order.
  if (SrcType->isRecordType()) {
    const Record *R = getRecord(SrcType);
    if (!R)
      return false;

    if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(R->getDecl())) {
      for (const CXXBaseSpecifier &BS : CXXRD->bases()) {
        if (Elements.size() >= MaxElements)
          break;
        const Record::Base *B = R->getBase(BS.getType());
        assert(B);
        if (!this->emitGetLocal(PT_Ptr, SrcOffset, E))
          return false;
        if (!this->emitGetPtrBasePop(B->Offset, /*NullOK=*/false, E))
          return false;
        UnsignedOrNone BasePtrOffset = savePtrToLocal();
        if (!BasePtrOffset)
          return false;
        if (!emitHLSLFlattenAggregate(BS.getType(), *BasePtrOffset, Elements,
                                      MaxElements, E))
          return false;
      }
    }

    for (const Record::Field &F : R->fields()) {
      if (Elements.size() >= MaxElements)
        break;
      if (F.isUnnamedBitField())
        continue;

      QualType FieldType = F.Decl->getType();
      if (!this->emitGetLocal(PT_Ptr, SrcOffset, E))
        return false;
      if (!this->emitGetPtrFieldPop(F.Offset, E))
        return false;

      if (OptPrimType FieldT = classify(FieldType)) {
        if (!this->emitLoadPop(*FieldT, E))
          return false;
        if (!saveToLocal(*FieldT))
          return false;
      } else {
        UnsignedOrNone FieldPtrOffset = savePtrToLocal();
        if (!FieldPtrOffset)
          return false;
        if (!emitHLSLFlattenAggregate(FieldType, *FieldPtrOffset, Elements,
                                      MaxElements, E))
          return false;
      }
    }
    return true;
  }

  return false;
}

/// Populate an HLSL aggregate from a flat list of previously extracted source
/// elements, casting each to the corresponding destination element type.
/// \p ElemIdx tracks the current position in \p Elements and is advanced as
/// elements are consumed. A pointer to the destination must be on top of the
/// interpreter stack.
template <class Emitter>
bool Compiler<Emitter>::emitHLSLConstructAggregate(
    QualType DestType, ArrayRef<HLSLFlatElement> Elements, unsigned &ElemIdx,
    const Expr *E) {

  // Consume the next source element, cast it, and leave it on the stack.
  auto loadAndCast = [&](PrimType DestT, QualType DestQT) -> bool {
    const auto &Src = Elements[ElemIdx++];
    if (!this->emitGetLocal(Src.Type, Src.LocalOffset, E))
      return false;
    return this->emitPrimCast(Src.Type, DestT, DestQT, E);
  };

  // Vectors and matrices are flat sequences of elements.
  unsigned NumElems = 0;
  QualType ElemType;
  if (const auto *VT = DestType->getAs<VectorType>()) {
    NumElems = VT->getNumElements();
    ElemType = VT->getElementType();
  } else if (const auto *MT = DestType->getAs<ConstantMatrixType>()) {
    NumElems = MT->getNumElementsFlattened();
    ElemType = MT->getElementType();
  }
  if (NumElems > 0) {
    PrimType DestElemT = classifyPrim(ElemType);
    for (unsigned I = 0; I != NumElems; ++I) {
      if (!loadAndCast(DestElemT, ElemType))
        return false;
      if (!this->emitInitElem(DestElemT, I, E))
        return false;
    }
    return true;
  }

  // Arrays: primitive elements are filled directly; composite elements
  // require recursion into each sub-aggregate.
  if (const auto *AT = DestType->getAsArrayTypeUnsafe()) {
    const auto *CAT = cast<ConstantArrayType>(AT);
    QualType ArrElemType = CAT->getElementType();
    unsigned ArrSize = CAT->getZExtSize();

    if (OptPrimType ElemT = classify(ArrElemType)) {
      for (unsigned I = 0; I != ArrSize; ++I) {
        if (!loadAndCast(*ElemT, ArrElemType))
          return false;
        if (!this->emitInitElem(*ElemT, I, E))
          return false;
      }
    } else {
      for (unsigned I = 0; I != ArrSize; ++I) {
        if (!this->emitConstUint32(I, E))
          return false;
        if (!this->emitArrayElemPtrUint32(E))
          return false;
        if (!emitHLSLConstructAggregate(ArrElemType, Elements, ElemIdx, E))
          return false;
        if (!this->emitFinishInitPop(E))
          return false;
      }
    }
    return true;
  }

  // Records: base classes come first, then named fields in declaration
  // order.
  if (DestType->isRecordType()) {
    const Record *R = getRecord(DestType);
    if (!R)
      return false;

    if (const auto *CXXRD = dyn_cast<CXXRecordDecl>(R->getDecl())) {
      for (const CXXBaseSpecifier &BS : CXXRD->bases()) {
        const Record::Base *B = R->getBase(BS.getType());
        assert(B);
        if (!this->emitGetPtrBase(B->Offset, E))
          return false;
        if (!emitHLSLConstructAggregate(BS.getType(), Elements, ElemIdx, E))
          return false;
        if (!this->emitFinishInitPop(E))
          return false;
      }
    }

    for (const Record::Field &F : R->fields()) {
      if (F.isUnnamedBitField())
        continue;

      QualType FieldType = F.Decl->getType();
      if (OptPrimType FieldT = classify(FieldType)) {
        if (!loadAndCast(*FieldT, FieldType))
          return false;
        if (F.isBitField()) {
          if (!this->emitInitBitField(*FieldT, F.Offset, F.bitWidth(), E))
            return false;
        } else {
          if (!this->emitInitField(*FieldT, F.Offset, E))
            return false;
        }
      } else {
        if (!this->emitGetPtrField(F.Offset, E))
          return false;
        if (!emitHLSLConstructAggregate(FieldType, Elements, ElemIdx, E))
          return false;
        if (!this->emitPopPtr(E))
          return false;
      }
    }
    return true;
  }

  return false;
}

namespace clang {
namespace interp {

template class Compiler<ByteCodeEmitter>;
template class Compiler<EvalEmitter>;

} // namespace interp
} // namespace clang
