//===--- 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"

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, VD), 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 *CE) {
  const Expr *SubExpr = CE->getSubExpr();

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

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

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

    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, CE);
          } else if (auto It = Locals.find(D); It != Locals.end()) {
            return this->emitGetLocal(*SubExprT, It->second.Offset, CE);
          } 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.Offset, CE);
            }
          }
        }
      }
    }

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

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

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

    // 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(CE);
  }

  case CK_DerivedToBaseMemberPointer: {
    assert(classifyPrim(CE->getType()) == PT_MemberPtr);
    assert(classifyPrim(SubExpr->getType()) == PT_MemberPtr);
    const auto *FromMP = SubExpr->getType()->castAs<MemberPointerType>();
    const auto *ToMP = CE->getType()->castAs<MemberPointerType>();

    unsigned DerivedOffset =
        Ctx.collectBaseOffset(ToMP->getMostRecentCXXRecordDecl(),
                              FromMP->getMostRecentCXXRecordDecl());

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

    return this->emitGetMemberPtrBasePop(DerivedOffset, CE);
  }

  case CK_BaseToDerivedMemberPointer: {
    assert(classifyPrim(CE) == PT_MemberPtr);
    assert(classifyPrim(SubExpr) == PT_MemberPtr);
    const auto *FromMP = SubExpr->getType()->castAs<MemberPointerType>();
    const auto *ToMP = CE->getType()->castAs<MemberPointerType>();

    unsigned DerivedOffset =
        Ctx.collectBaseOffset(FromMP->getMostRecentCXXRecordDecl(),
                              ToMP->getMostRecentCXXRecordDecl());

    if (!this->delegate(SubExpr))
      return false;
    return this->emitGetMemberPtrBasePop(-DerivedOffset, CE);
  }

  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 : CE->path()) {
      if (B->isVirtual()) {
        if (!this->emitGetPtrVirtBasePop(extractRecordDecl(B->getType()), CE))
          return false;
        CurType = B->getType();
      } else {
        unsigned DerivedOffset = collectBaseOffset(B->getType(), CurType);
        if (!this->emitGetPtrBasePop(
                DerivedOffset, /*NullOK=*/CE->getType()->isPointerType(), CE))
          return false;
        CurType = B->getType();
      }
    }

    return true;
  }

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

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

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

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

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

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

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

  case CK_NullToPointer:
  case CK_NullToMemberPointer: {
    if (!this->discard(SubExpr))
      return false;
    const Descriptor *Desc = nullptr;
    const QualType PointeeType = CE->getType()->getPointeeType();
    if (!PointeeType.isNull()) {
      if (OptPrimType T = classify(PointeeType))
        Desc = P.createDescriptor(SubExpr, *T);
      else
        Desc = P.createDescriptor(SubExpr, PointeeType.getTypePtr(),
                                  std::nullopt, /*IsConst=*/true);
    }

    uint64_t Val = Ctx.getASTContext().getTargetNullPointerValue(CE->getType());
    return this->emitNull(classifyPrim(CE->getType()), Val, Desc, CE);
  }

  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, CE))
        return false;
    }

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

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

  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);
    QualType PtrType = CE->getType();
    const Descriptor *Desc;
    if (OptPrimType T = classify(PtrType->getPointeeType()))
      Desc = P.createDescriptor(SubExpr, *T);
    else if (PtrType->getPointeeType()->isVoidType())
      Desc = nullptr;
    else
      Desc = P.createDescriptor(CE, PtrType->getPointeeType().getTypePtr(),
                                Descriptor::InlineDescMD, /*IsConst=*/true);

    if (!this->emitGetIntPtr(T, Desc, CE))
      return false;

    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, CE);
  }

  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: {
    QualType CETy = CE->getType();
    // Reject bitcasts to atomic types.
    if (CETy->isAtomicType()) {
      if (!this->discard(SubExpr))
        return false;
      return this->emitInvalidCast(CastKind::Reinterpret, /*Fatal=*/true, CE);
    }
    QualType SubExprTy = SubExpr->getType();
    OptPrimType FromT = classify(SubExprTy);
    // Casts from integer/vector to vector.
    if (CE->getType()->isVectorType())
      return this->emitBuiltinBitCast(CE);

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

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

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

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

    if (!this->visit(SubExpr))
      return false;
    return this->emitDecayPtr(*FromT, *ToT, CE);
  }
  case CK_IntegralToBoolean:
  case CK_FixedPointToBoolean: {
    // 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(), CE);
    if (!this->visit(SubExpr))
      return false;
    return this->emitCast(*FromT, classifyPrim(CE), CE);
  }

  case CK_BooleanToSignedIntegral:
  case CK_IntegralCast: {
    OptPrimType FromT = classify(SubExpr->getType());
    OptPrimType ToT = classify(CE->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 && !CE->getType()->isEnumeralType())
        return this->emitConst(APSInt(IL->getValue(), !isSignedType(*FromT)),
                               CE);
      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 && CE->getType()->isEnumeralType()) {
      const auto *ED = CE->getType()->castAsEnumDecl();
      if (!ED->isFixed()) {
        if (!this->emitCheckEnumValue(*FromT, ED, CE))
          return false;
      }
    }

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

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

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

  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(CE);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, CE))
        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(CE->getType()->isAnyComplexType());
    assert(SubExpr->getType()->isAnyComplexType());
    if (!Initializing) {
      UnsignedOrNone LocalIndex = allocateLocal(CE);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, CE))
        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, CE))
      return false;

    PrimType SourceElemT = classifyComplexElementType(SubExpr->getType());
    QualType DestElemType =
        CE->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, CE))
        return false;
      if (!this->emitArrayElemPop(SourceElemT, I, CE))
        return false;

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

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

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

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

    const auto *VT = CE->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, CE))
      return false;

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

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

    return true;
  }

  case CK_HLSLVectorTruncation: {
    assert(SubExpr->getType()->isVectorType());
    if (OptPrimType ResultT = classify(CE)) {
      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, CE);
    }
    // Otherwise, this truncates from one vector type to another.
    assert(CE->getType()->isVectorType());

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

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

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

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

  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);

  default:
    return this->emitInvalid(CE);
  }
  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 *BO) {
  // Need short-circuiting for these.
  if (BO->isLogicalOp() && !BO->getType()->isVectorType())
    return this->VisitLogicalBinOp(BO);

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

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

    return this->delegate(RHS);
  }

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

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

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

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

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

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

  // Typecheck the args.
  OptPrimType LT = classify(LHS);
  OptPrimType RT = classify(RHS);
  OptPrimType T = classify(BO->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 && BO->getOpcode() == BO_Cmp) {
    if (DiscardResult)
      return true;
    const ComparisonCategoryInfo *CmpInfo =
        Ctx.getASTContext().CompCategories.lookupInfoForType(BO->getType());
    assert(CmpInfo);

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

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

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

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

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

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

  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, BO](bool Result) {
    if (!Result)
      return false;
    if (DiscardResult)
      return this->emitPopBool(BO);
    if (T != PT_Bool)
      return this->emitCast(PT_Bool, *T, BO);
    return true;
  };

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

  switch (BO->getOpcode()) {
  case BO_EQ:
    return MaybeCastToBool(this->emitEQ(*LT, BO));
  case BO_NE:
    return MaybeCastToBool(this->emitNE(*LT, BO));
  case BO_LT:
    return MaybeCastToBool(this->emitLT(*LT, BO));
  case BO_LE:
    return MaybeCastToBool(this->emitLE(*LT, BO));
  case BO_GT:
    return MaybeCastToBool(this->emitGT(*LT, BO));
  case BO_GE:
    return MaybeCastToBool(this->emitGE(*LT, BO));
  case BO_Sub:
    if (BO->getType()->isFloatingType())
      return Discard(this->emitSubf(getFPOptions(BO), BO));
    return Discard(this->emitSub(*T, BO));
  case BO_Add:
    if (BO->getType()->isFloatingType())
      return Discard(this->emitAddf(getFPOptions(BO), BO));
    return Discard(this->emitAdd(*T, BO));
  case BO_Mul:
    if (BO->getType()->isFloatingType())
      return Discard(this->emitMulf(getFPOptions(BO), BO));
    return Discard(this->emitMul(*T, BO));
  case BO_Rem:
    return Discard(this->emitRem(*T, BO));
  case BO_Div:
    if (BO->getType()->isFloatingType())
      return Discard(this->emitDivf(getFPOptions(BO), BO));
    return Discard(this->emitDiv(*T, BO));
  case BO_And:
    return Discard(this->emitBitAnd(*T, BO));
  case BO_Or:
    return Discard(this->emitBitOr(*T, BO));
  case BO_Shl:
    return Discard(this->emitShl(*LT, *RT, BO));
  case BO_Shr:
    return Discard(this->emitShr(*LT, *RT, BO));
  case BO_Xor:
    return Discard(this->emitBitXor(*T, BO));
  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.
  if (Op == BO_Add) {
    if (!this->emitAddOffset(OffsetType, E))
      return false;

    if (classifyPrim(E) != PT_Ptr)
      return this->emitDecayPtr(PT_Ptr, classifyPrim(E), E);
    return true;
  }
  if (Op == BO_Sub) {
    if (!this->emitSubOffset(OffsetType, E))
      return false;

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

  return false;
}

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))
      return false;

    if (!this->visitBool(RHS))
      return false;
    if (!this->jump(LabelEnd))
      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))
      return false;

    if (!this->visitBool(RHS))
      return false;
    if (!this->jump(LabelEnd))
      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;
    return this->emitMulc(ElemT, E);
  }

  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;
    return this->emitDivc(ElemT, E);
  }

  // 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;
    }
  }
  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;
    return this->emitNegFixedPoint(E);
  default:
    return false;
  }

  llvm_unreachable("Unhandled unary opcode");
}

template <class Emitter>
bool Compiler<Emitter>::VisitImplicitValueInitExpr(
    const ImplicitValueInitExpr *E) {
  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;
  }

  return false;
}

template <class Emitter>
bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) {
  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, E);
      if (BitField)
        return this->emitInitBitField(T, FieldToInit, 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;

      if (!this->visitInitializer(Init))
        return false;
      return this->emitPopPtr(E);
    };

    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 (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->visitInitializer(Init))
            return false;

          if (!this->emitFinishInitPop(E))
            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()) {
    if (Inits.size() == 1 && QT == Inits[0]->getType())
      return this->delegate(Inits[0]);

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

    if (!this->emitCheckArraySize(NumElems, E))
      return false;

    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 (!this->visitArrayElemInit(ElementIndex, Init, InitT))
          return false;
        ++ElementIndex;
      }
    }

    // Expand the filler expression.
    // FIXME: This should go away.
    if (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;
  }

  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;
  if (!this->visitInitializer(Init))
    return false;
  return this->emitFinishInitPop(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(),
                        /*ExtendingDecl=*/nullptr, 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) {
  OptPrimType T = classify(E->getType());
  if (T && E->hasAPValueResult()) {
    // 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;

    if (this->visitAPValue(E->getAPValueResult(), *T, E))
      return true;
  }
  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().getClangABICompat() <= 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();

      // 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 (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) {
    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);

  // 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;
  };

  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. But this will probably
    // turn out to be wrong some time in the future, as always.
    if (auto GlobalIndex = P.getGlobal(VD))
      return this->emitGetPtrGlobal(*GlobalIndex, E) && maybeLoadValue();
    return false;
  }

  if (!isa<FieldDecl>(Member)) {
    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);
  // 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) {
  // 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);

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

  // TODO: This compiles to quite a lot of bytecode if the array is larger.
  //   Investigate compiling this to a loop.
  const Expr *SubExpr = E->getSubExpr();
  size_t Size = E->getArraySize().getZExtValue();
  OptPrimType SubExprT = classify(SubExpr);

  // 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);

    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)
    return this->visitInitializer(SourceExpr);

  PrimType SubExprT = classify(SourceExpr).value_or(PT_Ptr);
  if (auto It = OpaqueExprs.find(E); It != OpaqueExprs.end())
    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;

  // 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) {
    if (!this->emitGetLocal(SubExprT, LocalIndex, E))
      return false;
  }

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

  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();

  auto visitChildExpr = [&](const Expr *E) -> bool {
    LocalScope<Emitter> S(this);
    if (!this->delegate(E))
      return false;
    return S.destroyLocals();
  };

  if (std::optional<bool> BoolValue = getBoolValue(Condition)) {
    if (*BoolValue)
      return visitChildExpr(TrueExpr);
    return visitChildExpr(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->emitStartSpeculation(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;
  }

  if (!this->jumpFalse(LabelFalse))
    return false;
  if (!visitChildExpr(TrueExpr))
    return false;
  if (!this->jump(LabelEnd))
    return false;
  this->emitLabel(LabelFalse);
  if (!visitChildExpr(FalseExpr))
    return false;
  this->fallthrough(LabelEnd);
  this->emitLabel(LabelEnd);

  if (IsBcpCall)
    return this->emitEndSpeculation(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) {
    if (!this->emitCast(*LT, *LHSComputationT, 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) {
    if (!this->emitCast(*LHSComputationT, *ResultT, 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);
  const Expr *SubExpr = E->getSubExpr();

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

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

  if (Initializing) {
    // We already have a value, just initialize that.
    return this->delegate(SubExpr);
  }
  // If we don't end up using the materialized temporary anyway, don't
  // bother creating it.
  if (DiscardResult)
    return this->discard(SubExpr);

  // When we're initializing a global variable *or* the storage duration of
  // the temporary is explicitly static, create a global variable.
  OptPrimType SubExprT = classify(SubExpr);
  bool IsStatic = E->getStorageDuration() == SD_Static;
  if (IsStatic) {

    UnsignedOrNone GlobalIndex = P.createGlobal(E);
    if (!GlobalIndex)
      return false;

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

    if (SubExprT) {
      if (!this->visit(SubExpr))
        return false;
      if (!this->emitInitGlobalTemp(*SubExprT, *GlobalIndex, TempDecl, E))
        return false;
      return this->emitGetPtrGlobal(*GlobalIndex, E);
    }

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

  // For everyhing else, use local variables.
  if (SubExprT) {
    bool IsConst = SubExpr->getType().isConstQualified();
    bool IsVolatile = SubExpr->getType().isVolatileQualified();
    unsigned LocalIndex = allocateLocalPrimitive(
        E, *SubExprT, IsConst, IsVolatile, E->getExtendingDecl());
    if (!this->visit(SubExpr))
      return false;
    if (!this->emitSetLocal(*SubExprT, LocalIndex, E))
      return false;
    return this->emitGetPtrLocal(LocalIndex, E);
  }

  if (!this->checkLiteralType(SubExpr))
    return false;
  const Expr *Inner = E->getSubExpr()->skipRValueSubobjectAdjustments();
  if (UnsignedOrNone LocalIndex =
          allocateLocal(E, Inner->getType(), E->getExtendingDecl())) {
    InitLinkScope<Emitter> ILS(this, InitLink::Temp(*LocalIndex));
    if (!this->emitGetPtrLocal(*LocalIndex, E))
      return false;
    return this->visitInitializer(SubExpr) && this->emitFinishInit(E);
  }
  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) && this->emitFinishInit(E);
  }

  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);
    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) && this->emitFinishInit(E);
  }

  // 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) && this->emitFinishInit(E);
}

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->visitInitializer(Init))
        return false;

      if (!this->emitPopPtr(E))
        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 (isIntegralType(*PointeeFromT) && isIntegralType(*PointeeToT))
        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);
}

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 (!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 this->emitFinishInit(E);
  }

  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 (const auto *CT = Ty->getAs<ComplexType>()) {
    if (!Initializing) {
      UnsignedOrNone LocalIndex = allocateLocal(E);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }

    // Initialize both fields to 0.
    QualType ElemQT = CT->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 *VT = Ty->getAs<VectorType>()) {
    // FIXME: Code duplication with the _Complex case above.
    if (!Initializing) {
      UnsignedOrNone LocalIndex = allocateLocal(E);
      if (!LocalIndex)
        return false;
      if (!this->emitGetPtrLocal(*LocalIndex, E))
        return false;
    }

    // Initialize all fields to 0.
    QualType ElemQT = VT->getElementType();
    PrimType ElemT = classifyPrim(ElemQT);

    for (unsigned I = 0, N = VT->getNumElements(); 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 Offset = align(primSize(PT_Ptr)); // instance pointer.
  for (const ParmVarDecl *PD : Ctor->parameters()) {
    PrimType PT = this->classify(PD->getType()).value_or(PT_Ptr);

    if (!this->emitGetParam(PT, Offset, E))
      return false;
    Offset += align(primSize(PT));
  }

  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 (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;
      if (const ConstantArrayType *CAT =
              Ctx.getASTContext().getAsConstantArrayType(InitType)) {
        StaticInitElems = CAT->getZExtSize();
        if (!this->visitInitializer(Init))
          return false;

        if (const auto *ILE = dyn_cast<InitListExpr>(Init);
            ILE && ILE->hasArrayFiller())
          DynamicInit = ILE->getArrayFiller();
      }

      // 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 to 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.

      if (DynamicInit || 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)
          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))
            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))
          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->visitInitializer(DynamicInit))
              return false;
            if (!this->emitPopPtr(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))
          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) {
  const Expr *Arg = E->getArgument();

  const FunctionDecl *OperatorDelete = E->getOperatorDelete();

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

  // Arg must be an lvalue.
  if (!this->visit(Arg))
    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>::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>::VisitConvertVectorExpr(const ConvertVectorExpr *E) {
  assert(Initializing);
  const auto *VT = E->getType()->castAs<VectorType>();
  QualType ElemType = VT->getElementType();
  PrimType ElemT = classifyPrim(ElemType);
  const Expr *Src = E->getSrcExpr();
  QualType SrcType = Src->getType();
  PrimType SrcElemT = classifyVectorElementType(SrcType);

  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>::VisitShuffleVectorExpr(const ShuffleVectorExpr *E) {
  // FIXME: Unary shuffle with mask not currently supported.
  if (E->getNumSubExprs() == 2)
    return this->emitInvalid(E);

  assert(Initializing);
  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);

  // 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;
  }

  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 (isIntegralType(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));
    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);
}

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) {
  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(E->getType());
    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 = classifyPrim(D->getType());
      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 = classifyPrim(ET);
      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);

    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,
    const ValueDecl *ExtendingDecl, ScopeKind SC, bool IsConstexprUnknown) {
  // 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 = IsConstexprUnknown;
  Scope::Local Local = this->createLocal(D);
  if (auto *VD = dyn_cast_if_present<ValueDecl>(Src.dyn_cast<const Decl *>()))
    Locals.insert({VD, Local});
  if (ExtendingDecl)
    VarScope->addExtended(Local, ExtendingDecl);
  else
    VarScope->addForScopeKind(Local, SC);
  return Local.Offset;
}

template <class Emitter>
UnsignedOrNone Compiler<Emitter>::allocateLocal(DeclTy &&Src, QualType Ty,
                                                const ValueDecl *ExtendingDecl,
                                                ScopeKind SC,
                                                bool IsConstexprUnknown) {
  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=*/false, Init);
  if (!D)
    return std::nullopt;
  D->IsConstexprUnknown = IsConstexprUnknown;

  Scope::Local Local = this->createLocal(D);
  if (Key)
    Locals.insert({Key, Local});
  if (ExtendingDecl)
    VarScope->addExtended(Local, ExtendingDecl);
  else
    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);

  // If we won't destroy the toplevel scope, check for memory leaks first.
  if (!DestroyToplevelScope) {
    if (!this->emitCheckAllocations(E))
      return false;
  }

  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;

    if (!this->emitFinishInit(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() && this->emitCheckAllocations(E) && false;
}

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

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

  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);
      GlobalInlineDescriptor &GD =
          *reinterpret_cast<GlobalInlineDescriptor *>(GlobalBlock->rawData());

      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, VD);
  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);
      GlobalInlineDescriptor &GD =
          *reinterpret_cast<GlobalInlineDescriptor *>(GlobalBlock->rawData());

      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, bool IsConstexprUnknown) {
  // We don't know what to do with these, so just return false.
  if (VD->getType().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) {
      // We've already seen and initialized this global.
      if (P.getPtrGlobal(*GlobalIndex).isInitialized())
        return checkDecl();
      // The previous attempt at initialization might've been unsuccessful,
      // so let's try this one.
    } else if ((GlobalIndex = P.createGlobal(VD, Init))) {
    } 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 (!visitInitializer(Init))
      return false;

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

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

    if (!Init)
      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;
    return this->emitSetLocal(*VarT, Offset, VD);
  }
  // Local composite variables.
  if (UnsignedOrNone Offset = this->allocateLocal(
          VD, VD->getType(), nullptr, ScopeKind::Block, IsConstexprUnknown)) {
    if (!Init)
      return true;

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

    if (!visitInitializer(Init))
      return false;

    return this->emitFinishInitPop(Init);
  }
  return false;
}

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.isLValue()) {
    if (Val.isNullPointer())
      return this->emitNull(ValType, 0, nullptr, E);
    APValue::LValueBase Base = Val.getLValueBase();
    if (const Expr *BaseExpr = Base.dyn_cast<const Expr *>())
      return this->visit(BaseExpr);
    if (const auto *VD = Base.dyn_cast<const ValueDecl *>())
      return this->visitDeclRef(VD, E);
  } else if (Val.isMemberPointer()) {
    if (const ValueDecl *MemberDecl = Val.getMemberPointerDecl())
      return this->emitGetMemberPtr(MemberDecl, E);
    return this->emitNullMemberPtr(0, nullptr, E);
  }

  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();

      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->emitPopPtr(E))
          return false;
      }
    }
    return true;
  }
  if (Val.isUnion()) {
    const FieldDecl *UnionField = Val.getUnionField();
    const Record *R = this->getRecord(UnionField->getParent());
    assert(R);
    const APValue &F = Val.getUnionValue();
    const Record::Field *RF = R->getField(UnionField);
    PrimType T = classifyPrim(RF->Decl->getType());
    if (!this->visitAPValue(F, T, E))
      return false;
    return this->emitInitField(T, RF->Offset, E);
  }
  if (Val.isArray()) {
    const auto *ArrType = T->getAsArrayTypeUnsafe();
    QualType ElemType = ArrType->getElementType();
    for (unsigned A = 0, AN = Val.getArraySize(); A != AN; ++A) {
      const APValue &Elem = Val.getArrayInitializedElt(A);
      if (OptPrimType ElemT = classify(ElemType)) {
        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;
    this->fallthrough(EndLabel);
    if (!this->emitEndSpeculation(E))
      return false;
    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;
  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()) {
    assert(ReturnT);
    return this->emitPop(*ReturnT, E);
  }

  return true;
}

template <class Emitter>
bool Compiler<Emitter>::VisitCallExpr(const CallExpr *E) {
  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);
      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;
  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);
    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, IsAssignmentOperatorCall,
                           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);
      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);
      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 (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 auto *CXXRD = dyn_cast<CXXRecordDecl>(FD->getParent());
  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 {
      InitLinkScope<Emitter> ILS(this, InitLink::RVO());
      // RVO - construct the value in the return location.
      if (!this->emitRVOPtr(RE))
        return false;
      if (!this->visitInitializer(RE))
        return false;
      if (!this->emitPopPtr(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) {
  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 {
    if (!this->visitBool(IS->getCond()))
      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))
      return false;
    if (!visitChildStmt(IS->getThen()))
      return false;
    if (!this->jump(LabelEnd))
      return false;
    this->emitLabel(LabelElse);
    if (!visitChildStmt(Else))
      return false;
    this->emitLabel(LabelEnd);
  } else {
    LabelTy LabelEnd = this->getLabel();
    if (!this->jumpFalse(LabelEnd))
      return false;
    if (!visitChildStmt(IS->getThen()))
      return false;
    this->emitLabel(LabelEnd);
  }

  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);

  {
    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))
      return false;

    if (!this->visitStmt(Body))
      return false;

    if (!CondScope.destroyLocals())
      return false;
  }
  if (!this->jump(CondLabel))
    return false;
  this->fallthrough(EndLabel);
  this->emitLabel(EndLabel);
  return 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))
    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))
      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))
    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))
    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))
    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;
      }
    }
  }

  assert(TargetLabel);

  for (VariableScope<Emitter> *C = this->VarScope; C != BreakScope;
       C = C->getParent())
    C->emitDestruction();

  return this->jump(*TargetLabel);
}

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())
    C->emitDestruction();

  return this->jump(*TargetLabel);
}

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)) {
      // FIXME: Implement ranges.
      if (CS->caseStmtIsGNURange())
        return false;
      CaseLabels[SC] = this->getLabel();

      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]))
        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))
      return false;
  } else {
    if (!this->jump(EndLabel))
      return false;
  }

  SwitchScope<Emitter> SS(this, S, std::move(CaseLabels), EndLabel,
                          DefaultLabel);
  if (!this->visitStmt(S->getBody()))
    return false;
  this->emitLabel(EndLabel);

  return LS.destroyLocals();
}

template <class Emitter>
bool Compiler<Emitter>::visitCaseStmt(const CaseStmt *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) {
  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>(S->getSubStmt()));

      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.
  return this->visitStmt(S->getSubStmt());
}

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.Offset, 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);

  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;

      bool BitField = F->isBitField();
      if (BitField)
        return this->emitInitThisBitField(*T, F, FieldOffset, 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;

    if (!this->visitInitializer(InitExpr))
      return false;

    return this->emitFinishInitPop(InitExpr);
  };

  const RecordDecl *RD = Ctor->getParent();
  const Record *R = this->getRecord(RD);
  if (!R)
    return false;
  bool IsUnion = R->isUnion();

  if (IsUnion && Ctor->isCopyOrMoveConstructor()) {
    LocOverrideScope<Emitter> LOS(this, SourceInfo{});

    if (R->getNumFields() == 0)
      return this->emitRetVoid(Ctor);
    // union copy and move ctors are special.
    assert(cast<CompoundStmt>(Ctor->getBody())->body_empty());
    if (!this->emitThis(Ctor))
      return false;

    const ParmVarDecl *PVD = Ctor->getParamDecl(0);
    ParamOffset PO = this->Params[PVD]; // Must exist.

    if (!this->emitGetParam(PT_Ptr, PO.Offset, Ctor))
      return false;

    return this->emitMemcpy(Ctor) && this->emitPopPtr(Ctor) &&
           this->emitRetVoid(Ctor);
  }

  InitLinkScope<Emitter> InitScope(this, InitLink::This());
  for (const auto *Init : Ctor->inits()) {
    // Scope needed for the initializers.
    LocalScope<Emitter> Scope(this);

    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;
    } 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->visitInitializer(InitExpr))
        return false;
      if (!this->emitFinishInitPop(InitExpr))
        return false;
    } else if (const IndirectFieldDecl *IFD = Init->getIndirectMember()) {
      LocOverrideScope<Emitter> LOS(this, SourceInfo{},
                                    initNeedsOverridenLoc(Init));
      assert(IFD->getChainingSize() >= 2);

      unsigned NestedFieldOffset = 0;
      const Record::Field *NestedField = nullptr;
      for (const NamedDecl *ND : IFD->chain()) {
        const auto *FD = cast<FieldDecl>(ND);
        const Record *FieldRecord = this->P.getOrCreateRecord(FD->getParent());
        assert(FieldRecord);

        NestedField = FieldRecord->getField(FD);
        assert(NestedField);
        IsUnion = IsUnion || FieldRecord->isUnion();

        NestedFieldOffset += NestedField->Offset;
      }
      assert(NestedField);

      unsigned FirstLinkOffset =
          R->getField(cast<FieldDecl>(IFD->chain()[0]))->Offset;
      InitLinkScope<Emitter> ILS(this, InitLink::Field(FirstLinkOffset));
      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;
      }

    } else {
      assert(Init->isDelegatingInitializer());
      if (!this->emitThis(InitExpr))
        return false;
      if (!this->visitInitializer(Init->getInit()))
        return false;
      if (!this->emitPopPtr(InitExpr))
        return false;
    }

    if (!Scope.destroyLocals())
      return false;
  }

  if (const auto *Body = Ctor->getBody())
    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;
  }

  // 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;

  const ParmVarDecl *PVD = MD->getParamDecl(0);
  ParamOffset PO = this->Params[PVD]; // Must exist.

  if (!this->emitGetParam(PT_Ptr, PO.Offset, MD))
    return false;

  return this->emitMemcpy(MD) && this->emitRet(PT_Ptr, MD);
}

template <class Emitter>
bool Compiler<Emitter>::visitFunc(const FunctionDecl *F) {
  // 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) {
  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(isIntegralType(*T));
      if (!this->emitPreIncBitfield(*T, E->canOverflow(), getBitWidth(SubExpr),
                                    E))
        return false;
    } else {
      assert(isIntegralType(*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(isIntegralType(*T));
      if (!this->emitPreDecBitfield(*T, E->canOverflow(), getBitWidth(SubExpr),
                                    E))
        return false;
    } else {
      assert(isIntegralType(*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.
      return this->emitGetMemberPtr(cast<DeclRefExpr>(SubExpr)->getDecl(), E);
    }
    // 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
    assert(T);
    return this->delegate(SubExpr);
  case UO_Imag: { // __imag x
    assert(T);
    if (!this->discard(SubExpr))
      return false;
    return 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:
    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->visit(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 (!this->emitGetPtrGlobal(*Index, E))
        return false;
      if (OptPrimType T = classify(E->getType())) {
        if (!this->visitAPValue(TPOD->getValue(), *T, E))
          return false;
        return this->emitInitGlobal(*T, *Index, E);
      }
      return this->visitAPValueInitializer(TPOD->getValue(), E,
                                           TPOD->getType());
    }
    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.
  bool IsReference = D->getType()->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 &&
        !D->getType()->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.Offset, E);

      return this->emitGetPtrParam(It->second.Offset, E);
    }
  }
  // Local variables.
  if (auto It = Locals.find(D); It != Locals.end()) {
    const unsigned Offset = It->second.Offset;
    if (IsReference)
      return this->emitGetLocal(classifyPrim(E), 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);
      return this->emitGetGlobalUnchecked(classifyPrim(E), *GlobalIndex, E);
    }

    return this->emitGetPtrGlobal(*GlobalIndex, E);
  }

  // In case we need to re-visit a declaration.
  auto revisit = [&](const VarDecl *VD) -> bool {
    if (!this->emitPushCC(VD->hasConstantInitialization(), E))
      return false;
    auto VarState = this->visitDecl(VD, /*IsConstexprUnknown=*/true);

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

    if (VarState.notCreated())
      return true;
    if (!VarState)
      return false;
    // Retry.
    return this->visitDeclRef(D, E);
  };

  // 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.
  // For C.
  if (!Ctx.getLangOpts().CPlusPlus) {
    if (const auto *VD = dyn_cast<VarDecl>(D);
        VD && VD->getAnyInitializer() &&
        VD->getType().isConstant(Ctx.getASTContext()) && !VD->isWeak())
      return revisit(VD);
    return this->emitDummyPtr(D, E);
  }

  // ... and C++.
  const auto *VD = dyn_cast<VarDecl>(D);
  if (!VD)
    return this->emitDummyPtr(D, E);

  const auto typeShouldBeVisited = [&](QualType T) -> bool {
    if (T.isConstant(Ctx.getASTContext()))
      return true;
    return T->isReferenceType();
  };

  if ((VD->hasGlobalStorage() || VD->isStaticDataMember()) &&
      typeShouldBeVisited(VD->getType())) {
    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);
  }

  // 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(VD->getType()) &&
      VD->getInit() && !VD->getInit()->isValueDependent()) {

    if (VD->evaluateValue())
      return revisit(VD);

    if (!IsReference)
      return this->emitDummyPtr(D, E);

    return this->emitInvalidDeclRef(cast<DeclRefExpr>(E),
                                    /*InitializerFailed=*/true, E);
  }

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

template <class Emitter>
bool Compiler<Emitter>::VisitDeclRefExpr(const DeclRefExpr *E) {
  const auto *D = E->getDecl();
  return this->visitDeclRef(D, E);
}

template <class Emitter> void Compiler<Emitter>::emitCleanup() {
  for (VariableScope<Emitter> *C = VarScope; C; C = C->getParent())
    C->emitDestruction();
}

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 (isIntegralType(ToT) || ToT == PT_Bool)
      return this->emitCastFloatingIntegral(ToT, getFPOptions(E), E);
  }

  if (isIntegralType(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 (isIntegralType(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;
}

/// 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))
    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);

  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);
  assert(!DiscardResult);

  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) {
  assert(!DiscardResult && "Should've been checked before");

  unsigned DummyID = P.getOrCreateDummy(D);

  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) {
  assert(!DiscardResult && "Should've been checked before");

  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;
}

namespace clang {
namespace interp {

template class Compiler<ByteCodeEmitter>;
template class Compiler<EvalEmitter>;

} // namespace interp
} // namespace clang
