//===--- Interp.h - Interpreter for the constexpr VM ------------*- 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
//
//===----------------------------------------------------------------------===//
//
// Definition of the interpreter state and entry point.
//
//===----------------------------------------------------------------------===//

#ifndef LLVM_CLANG_AST_INTERP_INTERP_H
#define LLVM_CLANG_AST_INTERP_INTERP_H

#include "../ExprConstShared.h"
#include "BitcastBuffer.h"
#include "Boolean.h"
#include "DynamicAllocator.h"
#include "FixedPoint.h"
#include "Floating.h"
#include "Function.h"
#include "InterpBuiltinBitCast.h"
#include "InterpFrame.h"
#include "InterpStack.h"
#include "InterpState.h"
#include "MemberPointer.h"
#include "PrimType.h"
#include "Program.h"
#include "State.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/Expr.h"
#include "llvm/ADT/APFloat.h"
#include "llvm/ADT/APSInt.h"
#include <type_traits>

namespace clang {
namespace interp {

using APSInt = llvm::APSInt;
using FixedPointSemantics = llvm::FixedPointSemantics;

/// Checks if the variable has externally defined storage.
bool CheckExtern(InterpState &S, CodePtr OpPC, const Pointer &Ptr);

/// Checks if the array is offsetable.
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr);

/// Checks if a pointer is live and accessible.
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
               AccessKinds AK);

/// Checks if a pointer is a dummy pointer.
bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK);

/// Checks if a pointer is null.
bool CheckNull(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
               CheckSubobjectKind CSK);

/// Checks if a pointer is in range.
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                AccessKinds AK);

/// Checks if a field from which a pointer is going to be derived is valid.
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                CheckSubobjectKind CSK);

/// Checks if Ptr is a one-past-the-end pointer.
bool CheckSubobject(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                    CheckSubobjectKind CSK);

/// Checks if the dowcast using the given offset is possible with the given
/// pointer.
bool CheckDowncast(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                   uint32_t Offset);

/// Checks if a pointer points to const storage.
bool CheckConst(InterpState &S, CodePtr OpPC, const Pointer &Ptr);

/// Checks if the Descriptor is of a constexpr or const global variable.
bool CheckConstant(InterpState &S, CodePtr OpPC, const Descriptor *Desc);

/// Checks if a pointer points to a mutable field.
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr);

/// Checks if a value can be loaded from a block.
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
               AccessKinds AK = AK_Read);
bool CheckFinalLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr);

bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                           AccessKinds AK);
bool DiagnoseUninitialized(InterpState &S, CodePtr OpPC, bool Extern,
                           const Descriptor *Desc, AccessKinds AK);

/// Checks a direct load of a primitive value from a global or local variable.
bool CheckGlobalLoad(InterpState &S, CodePtr OpPC, const Block *B);
bool CheckLocalLoad(InterpState &S, CodePtr OpPC, const Block *B);

/// Checks if a value can be stored in a block.
bool CheckStore(InterpState &S, CodePtr OpPC, const Pointer &Ptr);

/// Checks if a value can be initialized.
bool CheckInit(InterpState &S, CodePtr OpPC, const Pointer &Ptr);

/// Checks the 'this' pointer.
bool CheckThis(InterpState &S, CodePtr OpPC, const Pointer &This);

/// Checks if dynamic memory allocation is available in the current
/// language mode.
bool CheckDynamicMemoryAllocation(InterpState &S, CodePtr OpPC);

/// Diagnose mismatched new[]/delete or new/delete[] pairs.
bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC,
                         DynamicAllocator::Form AllocForm,
                         DynamicAllocator::Form DeleteForm, const Descriptor *D,
                         const Expr *NewExpr);

/// Check the source of the pointer passed to delete/delete[] has actually
/// been heap allocated by us.
bool CheckDeleteSource(InterpState &S, CodePtr OpPC, const Expr *Source,
                       const Pointer &Ptr);

bool CheckActive(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                 AccessKinds AK);

/// Sets the given integral value to the pointer, which is of
/// a std::{weak,partial,strong}_ordering type.
bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,
                                const Pointer &Ptr, const APSInt &IntValue);

/// Copy the contents of Src into Dest.
bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest);

bool CallVar(InterpState &S, CodePtr OpPC, const Function *Func,
             uint32_t VarArgSize);
bool Call(InterpState &S, CodePtr OpPC, const Function *Func,
          uint32_t VarArgSize);
bool CallVirt(InterpState &S, CodePtr OpPC, const Function *Func,
              uint32_t VarArgSize);
bool CallBI(InterpState &S, CodePtr OpPC, const CallExpr *CE,
            uint32_t BuiltinID);
bool CallPtr(InterpState &S, CodePtr OpPC, uint32_t ArgSize,
             const CallExpr *CE);
bool CheckLiteralType(InterpState &S, CodePtr OpPC, const Type *T);
bool InvalidShuffleVectorIndex(InterpState &S, CodePtr OpPC, uint32_t Index);
bool CheckBitCast(InterpState &S, CodePtr OpPC, bool HasIndeterminateBits,
                  bool TargetIsUCharOrByte);
bool CheckBCPResult(InterpState &S, const Pointer &Ptr);
bool CheckDestructor(InterpState &S, CodePtr OpPC, const Pointer &Ptr);

template <typename T>
static bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue) {
  const Expr *E = S.Current->getExpr(OpPC);
  S.CCEDiag(E, diag::note_constexpr_overflow) << SrcValue << E->getType();
  return S.noteUndefinedBehavior();
}
bool handleFixedPointOverflow(InterpState &S, CodePtr OpPC,
                              const FixedPoint &FP);

bool isConstexprUnknown(const Pointer &P);

inline bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems);

enum class ShiftDir { Left, Right };

/// Checks if the shift operation is legal.
template <ShiftDir Dir, typename LT, typename RT>
bool CheckShift(InterpState &S, CodePtr OpPC, const LT &LHS, const RT &RHS,
                unsigned Bits) {
  if (RHS.isNegative()) {
    const SourceInfo &Loc = S.Current->getSource(OpPC);
    S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
    if (!S.noteUndefinedBehavior())
      return false;
  }

  // C++11 [expr.shift]p1: Shift width must be less than the bit width of
  // the shifted type.
  if (Bits > 1 && RHS >= Bits) {
    const Expr *E = S.Current->getExpr(OpPC);
    const APSInt Val = RHS.toAPSInt();
    QualType Ty = E->getType();
    S.CCEDiag(E, diag::note_constexpr_large_shift) << Val << Ty << Bits;
    if (!S.noteUndefinedBehavior())
      return false;
  }

  if constexpr (Dir == ShiftDir::Left) {
    if (LHS.isSigned() && !S.getLangOpts().CPlusPlus20) {
      // C++11 [expr.shift]p2: A signed left shift must have a non-negative
      // operand, and must not overflow the corresponding unsigned type.
      if (LHS.isNegative()) {
        const Expr *E = S.Current->getExpr(OpPC);
        S.CCEDiag(E, diag::note_constexpr_lshift_of_negative) << LHS.toAPSInt();
        if (!S.noteUndefinedBehavior())
          return false;
      } else if (LHS.toUnsigned().countLeadingZeros() <
                 static_cast<unsigned>(RHS)) {
        const Expr *E = S.Current->getExpr(OpPC);
        S.CCEDiag(E, diag::note_constexpr_lshift_discards);
        if (!S.noteUndefinedBehavior())
          return false;
      }
    }
  }

  // C++2a [expr.shift]p2: [P0907R4]:
  //    E1 << E2 is the unique value congruent to
  //    E1 x 2^E2 module 2^N.
  return true;
}

/// Checks if Div/Rem operation on LHS and RHS is valid.
template <typename T>
bool CheckDivRem(InterpState &S, CodePtr OpPC, const T &LHS, const T &RHS) {
  if (RHS.isZero()) {
    const auto *Op = cast<BinaryOperator>(S.Current->getExpr(OpPC));
    if constexpr (std::is_same_v<T, Floating>) {
      S.CCEDiag(Op, diag::note_expr_divide_by_zero)
          << Op->getRHS()->getSourceRange();
      return true;
    }

    S.FFDiag(Op, diag::note_expr_divide_by_zero)
        << Op->getRHS()->getSourceRange();
    return false;
  }

  if constexpr (!std::is_same_v<T, FixedPoint>) {
    if (LHS.isSigned() && LHS.isMin() && RHS.isNegative() && RHS.isMinusOne()) {
      APSInt LHSInt = LHS.toAPSInt();
      SmallString<32> Trunc;
      (-LHSInt.extend(LHSInt.getBitWidth() + 1)).toString(Trunc, 10);
      const SourceInfo &Loc = S.Current->getSource(OpPC);
      const Expr *E = S.Current->getExpr(OpPC);
      S.CCEDiag(Loc, diag::note_constexpr_overflow) << Trunc << E->getType();
      return false;
    }
  }
  return true;
}

template <typename SizeT>
bool CheckArraySize(InterpState &S, CodePtr OpPC, SizeT *NumElements,
                    unsigned ElemSize, bool IsNoThrow) {
  // FIXME: Both the SizeT::from() as well as the
  // NumElements.toAPSInt() in this function are rather expensive.

  // Can't be too many elements if the bitwidth of NumElements is lower than
  // that of Descriptor::MaxArrayElemBytes.
  if ((NumElements->bitWidth() - NumElements->isSigned()) <
      (sizeof(Descriptor::MaxArrayElemBytes) * 8))
    return true;

  // FIXME: GH63562
  // APValue stores array extents as unsigned,
  // so anything that is greater that unsigned would overflow when
  // constructing the array, we catch this here.
  SizeT MaxElements = SizeT::from(Descriptor::MaxArrayElemBytes / ElemSize);
  assert(MaxElements.isPositive());
  if (NumElements->toAPSInt().getActiveBits() >
          ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||
      *NumElements > MaxElements) {
    if (!IsNoThrow) {
      const SourceInfo &Loc = S.Current->getSource(OpPC);

      if (NumElements->isSigned() && NumElements->isNegative()) {
        S.FFDiag(Loc, diag::note_constexpr_new_negative)
            << NumElements->toDiagnosticString(S.getASTContext());
      } else {
        S.FFDiag(Loc, diag::note_constexpr_new_too_large)
            << NumElements->toDiagnosticString(S.getASTContext());
      }
    }
    return false;
  }
  return true;
}

/// Checks if the result of a floating-point operation is valid
/// in the current context.
bool CheckFloatResult(InterpState &S, CodePtr OpPC, const Floating &Result,
                      APFloat::opStatus Status, FPOptions FPO);

/// Checks why the given DeclRefExpr is invalid.
bool CheckDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR);

/// Interpreter entry point.
bool Interpret(InterpState &S);

/// Interpret a builtin function.
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
                      uint32_t BuiltinID);

/// Interpret an offsetof operation.
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
                       ArrayRef<int64_t> ArrayIndices, int64_t &Result);

inline bool Invalid(InterpState &S, CodePtr OpPC);

enum class ArithOp { Add, Sub };

//===----------------------------------------------------------------------===//
// Returning values
//===----------------------------------------------------------------------===//

void cleanupAfterFunctionCall(InterpState &S, CodePtr OpPC,
                              const Function *Func);

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Ret(InterpState &S, CodePtr &PC) {
  const T &Ret = S.Stk.pop<T>();

  assert(S.Current);
  assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");
  if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
    cleanupAfterFunctionCall(S, PC, S.Current->getFunction());

  if (InterpFrame *Caller = S.Current->Caller) {
    PC = S.Current->getRetPC();
    InterpFrame::free(S.Current);
    S.Current = Caller;
    S.Stk.push<T>(Ret);
  } else {
    InterpFrame::free(S.Current);
    S.Current = nullptr;
    // The topmost frame should come from an EvalEmitter,
    // which has its own implementation of the Ret<> instruction.
  }
  return true;
}

inline bool RetVoid(InterpState &S, CodePtr &PC) {
  assert(S.Current->getFrameOffset() == S.Stk.size() && "Invalid frame");

  if (!S.checkingPotentialConstantExpression() || S.Current->Caller)
    cleanupAfterFunctionCall(S, PC, S.Current->getFunction());

  if (InterpFrame *Caller = S.Current->Caller) {
    PC = S.Current->getRetPC();
    InterpFrame::free(S.Current);
    S.Current = Caller;
  } else {
    InterpFrame::free(S.Current);
    S.Current = nullptr;
  }
  return true;
}

//===----------------------------------------------------------------------===//
// Add, Sub, Mul
//===----------------------------------------------------------------------===//

template <typename T, bool (*OpFW)(T, T, unsigned, T *),
          template <typename U> class OpAP>
bool AddSubMulHelper(InterpState &S, CodePtr OpPC, unsigned Bits, const T &LHS,
                     const T &RHS) {
  // Fast path - add the numbers with fixed width.
  T Result;
  if constexpr (needsAlloc<T>())
    Result = S.allocAP<T>(LHS.bitWidth());

  if (!OpFW(LHS, RHS, Bits, &Result)) {
    S.Stk.push<T>(Result);
    return true;
  }
  // If for some reason evaluation continues, use the truncated results.
  S.Stk.push<T>(Result);

  // Short-circuit fixed-points here since the error handling is easier.
  if constexpr (std::is_same_v<T, FixedPoint>)
    return handleFixedPointOverflow(S, OpPC, Result);

  // Slow path - compute the result using another bit of precision.
  APSInt Value = OpAP<APSInt>()(LHS.toAPSInt(Bits), RHS.toAPSInt(Bits));

  // Report undefined behaviour, stopping if required.
  if (S.checkingForUndefinedBehavior()) {
    const Expr *E = S.Current->getExpr(OpPC);
    QualType Type = E->getType();
    SmallString<32> Trunc;
    Value.trunc(Result.bitWidth())
        .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
                  /*UpperCase=*/true, /*InsertSeparators=*/true);
    S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
        << Trunc << Type << E->getSourceRange();
  }

  if (!handleOverflow(S, OpPC, Value)) {
    S.Stk.pop<T>();
    return false;
  }
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Add(InterpState &S, CodePtr OpPC) {
  const T &RHS = S.Stk.pop<T>();
  const T &LHS = S.Stk.pop<T>();
  const unsigned Bits = RHS.bitWidth() + 1;

  return AddSubMulHelper<T, T::add, std::plus>(S, OpPC, Bits, LHS, RHS);
}

static inline llvm::RoundingMode getRoundingMode(FPOptions FPO) {
  auto RM = FPO.getRoundingMode();
  if (RM == llvm::RoundingMode::Dynamic)
    return llvm::RoundingMode::NearestTiesToEven;
  return RM;
}

inline bool Addf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
  const Floating &RHS = S.Stk.pop<Floating>();
  const Floating &LHS = S.Stk.pop<Floating>();

  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
  Floating Result = S.allocFloat(LHS.getSemantics());
  auto Status = Floating::add(LHS, RHS, getRoundingMode(FPO), &Result);
  S.Stk.push<Floating>(Result);
  return CheckFloatResult(S, OpPC, Result, Status, FPO);
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Sub(InterpState &S, CodePtr OpPC) {
  const T &RHS = S.Stk.pop<T>();
  const T &LHS = S.Stk.pop<T>();
  const unsigned Bits = RHS.bitWidth() + 1;

  return AddSubMulHelper<T, T::sub, std::minus>(S, OpPC, Bits, LHS, RHS);
}

inline bool Subf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
  const Floating &RHS = S.Stk.pop<Floating>();
  const Floating &LHS = S.Stk.pop<Floating>();

  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
  Floating Result = S.allocFloat(LHS.getSemantics());
  auto Status = Floating::sub(LHS, RHS, getRoundingMode(FPO), &Result);
  S.Stk.push<Floating>(Result);
  return CheckFloatResult(S, OpPC, Result, Status, FPO);
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Mul(InterpState &S, CodePtr OpPC) {
  const T &RHS = S.Stk.pop<T>();
  const T &LHS = S.Stk.pop<T>();
  const unsigned Bits = RHS.bitWidth() * 2;

  return AddSubMulHelper<T, T::mul, std::multiplies>(S, OpPC, Bits, LHS, RHS);
}

inline bool Mulf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
  const Floating &RHS = S.Stk.pop<Floating>();
  const Floating &LHS = S.Stk.pop<Floating>();

  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
  Floating Result = S.allocFloat(LHS.getSemantics());

  auto Status = Floating::mul(LHS, RHS, getRoundingMode(FPO), &Result);

  S.Stk.push<Floating>(Result);
  return CheckFloatResult(S, OpPC, Result, Status, FPO);
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool Mulc(InterpState &S, CodePtr OpPC) {
  const Pointer &RHS = S.Stk.pop<Pointer>();
  const Pointer &LHS = S.Stk.pop<Pointer>();
  const Pointer &Result = S.Stk.peek<Pointer>();

  if constexpr (std::is_same_v<T, Floating>) {
    APFloat A = LHS.elem<Floating>(0).getAPFloat();
    APFloat B = LHS.elem<Floating>(1).getAPFloat();
    APFloat C = RHS.elem<Floating>(0).getAPFloat();
    APFloat D = RHS.elem<Floating>(1).getAPFloat();

    APFloat ResR(A.getSemantics());
    APFloat ResI(A.getSemantics());
    HandleComplexComplexMul(A, B, C, D, ResR, ResI);

    // Copy into the result.
    Floating RA = S.allocFloat(A.getSemantics());
    RA.copy(ResR);
    Result.elem<Floating>(0) = RA; // Floating(ResR);

    Floating RI = S.allocFloat(A.getSemantics());
    RI.copy(ResI);
    Result.elem<Floating>(1) = RI; // Floating(ResI);
    Result.initializeAllElements();
  } else {
    // Integer element type.
    const T &LHSR = LHS.elem<T>(0);
    const T &LHSI = LHS.elem<T>(1);
    const T &RHSR = RHS.elem<T>(0);
    const T &RHSI = RHS.elem<T>(1);
    unsigned Bits = LHSR.bitWidth();

    // real(Result) = (real(LHS) * real(RHS)) - (imag(LHS) * imag(RHS))
    T A;
    if (T::mul(LHSR, RHSR, Bits, &A))
      return false;
    T B;
    if (T::mul(LHSI, RHSI, Bits, &B))
      return false;
    if (T::sub(A, B, Bits, &Result.elem<T>(0)))
      return false;

    // imag(Result) = (real(LHS) * imag(RHS)) + (imag(LHS) * real(RHS))
    if (T::mul(LHSR, RHSI, Bits, &A))
      return false;
    if (T::mul(LHSI, RHSR, Bits, &B))
      return false;
    if (T::add(A, B, Bits, &Result.elem<T>(1)))
      return false;
    Result.initialize();
    Result.initializeAllElements();
  }

  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool Divc(InterpState &S, CodePtr OpPC) {
  const Pointer &RHS = S.Stk.pop<Pointer>();
  const Pointer &LHS = S.Stk.pop<Pointer>();
  const Pointer &Result = S.Stk.peek<Pointer>();

  if constexpr (std::is_same_v<T, Floating>) {
    APFloat A = LHS.elem<Floating>(0).getAPFloat();
    APFloat B = LHS.elem<Floating>(1).getAPFloat();
    APFloat C = RHS.elem<Floating>(0).getAPFloat();
    APFloat D = RHS.elem<Floating>(1).getAPFloat();

    APFloat ResR(A.getSemantics());
    APFloat ResI(A.getSemantics());
    HandleComplexComplexDiv(A, B, C, D, ResR, ResI);

    // Copy into the result.
    Floating RA = S.allocFloat(A.getSemantics());
    RA.copy(ResR);
    Result.elem<Floating>(0) = RA; // Floating(ResR);

    Floating RI = S.allocFloat(A.getSemantics());
    RI.copy(ResI);
    Result.elem<Floating>(1) = RI; // Floating(ResI);

    Result.initializeAllElements();
  } else {
    // Integer element type.
    const T &LHSR = LHS.elem<T>(0);
    const T &LHSI = LHS.elem<T>(1);
    const T &RHSR = RHS.elem<T>(0);
    const T &RHSI = RHS.elem<T>(1);
    unsigned Bits = LHSR.bitWidth();
    const T Zero = T::from(0, Bits);

    if (Compare(RHSR, Zero) == ComparisonCategoryResult::Equal &&
        Compare(RHSI, Zero) == ComparisonCategoryResult::Equal) {
      const SourceInfo &E = S.Current->getSource(OpPC);
      S.FFDiag(E, diag::note_expr_divide_by_zero);
      return false;
    }

    // Den = real(RHS)² + imag(RHS)²
    T A, B;
    if (T::mul(RHSR, RHSR, Bits, &A) || T::mul(RHSI, RHSI, Bits, &B)) {
      // Ignore overflow here, because that's what the current interpeter does.
    }
    T Den;
    if (T::add(A, B, Bits, &Den))
      return false;

    if (Compare(Den, Zero) == ComparisonCategoryResult::Equal) {
      const SourceInfo &E = S.Current->getSource(OpPC);
      S.FFDiag(E, diag::note_expr_divide_by_zero);
      return false;
    }

    // real(Result) = ((real(LHS) * real(RHS)) + (imag(LHS) * imag(RHS))) / Den
    T &ResultR = Result.elem<T>(0);
    T &ResultI = Result.elem<T>(1);

    if (T::mul(LHSR, RHSR, Bits, &A) || T::mul(LHSI, RHSI, Bits, &B))
      return false;
    if (T::add(A, B, Bits, &ResultR))
      return false;
    if (T::div(ResultR, Den, Bits, &ResultR))
      return false;

    // imag(Result) = ((imag(LHS) * real(RHS)) - (real(LHS) * imag(RHS))) / Den
    if (T::mul(LHSI, RHSR, Bits, &A) || T::mul(LHSR, RHSI, Bits, &B))
      return false;
    if (T::sub(A, B, Bits, &ResultI))
      return false;
    if (T::div(ResultI, Den, Bits, &ResultI))
      return false;
    Result.initializeAllElements();
  }

  return true;
}

/// 1) Pops the RHS from the stack.
/// 2) Pops the LHS from the stack.
/// 3) Pushes 'LHS & RHS' on the stack
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool BitAnd(InterpState &S, CodePtr OpPC) {
  const T &RHS = S.Stk.pop<T>();
  const T &LHS = S.Stk.pop<T>();
  unsigned Bits = RHS.bitWidth();

  T Result;
  if constexpr (needsAlloc<T>())
    Result = S.allocAP<T>(Bits);

  if (!T::bitAnd(LHS, RHS, Bits, &Result)) {
    S.Stk.push<T>(Result);
    return true;
  }
  return false;
}

/// 1) Pops the RHS from the stack.
/// 2) Pops the LHS from the stack.
/// 3) Pushes 'LHS | RHS' on the stack
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool BitOr(InterpState &S, CodePtr OpPC) {
  const T &RHS = S.Stk.pop<T>();
  const T &LHS = S.Stk.pop<T>();
  unsigned Bits = RHS.bitWidth();

  T Result;
  if constexpr (needsAlloc<T>())
    Result = S.allocAP<T>(Bits);

  if (!T::bitOr(LHS, RHS, Bits, &Result)) {
    S.Stk.push<T>(Result);
    return true;
  }
  return false;
}

/// 1) Pops the RHS from the stack.
/// 2) Pops the LHS from the stack.
/// 3) Pushes 'LHS ^ RHS' on the stack
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool BitXor(InterpState &S, CodePtr OpPC) {
  const T &RHS = S.Stk.pop<T>();
  const T &LHS = S.Stk.pop<T>();

  unsigned Bits = RHS.bitWidth();

  T Result;
  if constexpr (needsAlloc<T>())
    Result = S.allocAP<T>(Bits);

  if (!T::bitXor(LHS, RHS, Bits, &Result)) {
    S.Stk.push<T>(Result);
    return true;
  }
  return false;
}

/// 1) Pops the RHS from the stack.
/// 2) Pops the LHS from the stack.
/// 3) Pushes 'LHS % RHS' on the stack (the remainder of dividing LHS by RHS).
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Rem(InterpState &S, CodePtr OpPC) {
  const T &RHS = S.Stk.pop<T>();
  const T &LHS = S.Stk.pop<T>();
  const unsigned Bits = RHS.bitWidth() * 2;

  if (!CheckDivRem(S, OpPC, LHS, RHS))
    return false;

  T Result;
  if constexpr (needsAlloc<T>())
    Result = S.allocAP<T>(LHS.bitWidth());

  if (!T::rem(LHS, RHS, Bits, &Result)) {
    S.Stk.push<T>(Result);
    return true;
  }
  return false;
}

/// 1) Pops the RHS from the stack.
/// 2) Pops the LHS from the stack.
/// 3) Pushes 'LHS / RHS' on the stack
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Div(InterpState &S, CodePtr OpPC) {
  const T &RHS = S.Stk.pop<T>();
  const T &LHS = S.Stk.pop<T>();
  const unsigned Bits = RHS.bitWidth() * 2;

  if (!CheckDivRem(S, OpPC, LHS, RHS))
    return false;

  T Result;
  if constexpr (needsAlloc<T>())
    Result = S.allocAP<T>(LHS.bitWidth());

  if (!T::div(LHS, RHS, Bits, &Result)) {
    S.Stk.push<T>(Result);
    return true;
  }

  if constexpr (std::is_same_v<T, FixedPoint>) {
    if (handleFixedPointOverflow(S, OpPC, Result)) {
      S.Stk.push<T>(Result);
      return true;
    }
  }
  return false;
}

inline bool Divf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
  const Floating &RHS = S.Stk.pop<Floating>();
  const Floating &LHS = S.Stk.pop<Floating>();

  if (!CheckDivRem(S, OpPC, LHS, RHS))
    return false;

  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);

  Floating Result = S.allocFloat(LHS.getSemantics());
  auto Status = Floating::div(LHS, RHS, getRoundingMode(FPO), &Result);

  S.Stk.push<Floating>(Result);
  return CheckFloatResult(S, OpPC, Result, Status, FPO);
}

//===----------------------------------------------------------------------===//
// Inv
//===----------------------------------------------------------------------===//

inline bool Inv(InterpState &S, CodePtr OpPC) {
  const auto &Val = S.Stk.pop<Boolean>();
  S.Stk.push<Boolean>(!Val);
  return true;
}

//===----------------------------------------------------------------------===//
// Neg
//===----------------------------------------------------------------------===//

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Neg(InterpState &S, CodePtr OpPC) {
  const T &Value = S.Stk.pop<T>();

  if constexpr (std::is_same_v<T, Floating>) {
    T Result = S.allocFloat(Value.getSemantics());

    if (!T::neg(Value, &Result)) {
      S.Stk.push<T>(Result);
      return true;
    }
    return false;
  } else {
    T Result;
    if constexpr (needsAlloc<T>())
      Result = S.allocAP<T>(Value.bitWidth());

    if (!T::neg(Value, &Result)) {
      S.Stk.push<T>(Result);
      return true;
    }

    assert(isIntegralType(Name) &&
           "don't expect other types to fail at constexpr negation");
    S.Stk.push<T>(Result);

    APSInt NegatedValue = -Value.toAPSInt(Value.bitWidth() + 1);
    if (S.checkingForUndefinedBehavior()) {
      const Expr *E = S.Current->getExpr(OpPC);
      QualType Type = E->getType();
      SmallString<32> Trunc;
      NegatedValue.trunc(Result.bitWidth())
          .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
                    /*UpperCase=*/true, /*InsertSeparators=*/true);
      S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
          << Trunc << Type << E->getSourceRange();
      return true;
    }

    return handleOverflow(S, OpPC, NegatedValue);
  }
}

enum class PushVal : bool {
  No,
  Yes,
};
enum class IncDecOp {
  Inc,
  Dec,
};

template <typename T, IncDecOp Op, PushVal DoPush>
bool IncDecHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                  bool CanOverflow) {
  assert(!Ptr.isDummy());

  if (!S.inConstantContext()) {
    if (isConstexprUnknown(Ptr))
      return false;
  }

  if constexpr (std::is_same_v<T, Boolean>) {
    if (!S.getLangOpts().CPlusPlus14)
      return Invalid(S, OpPC);
  }

  const T &Value = Ptr.deref<T>();
  T Result;
  if constexpr (needsAlloc<T>())
    Result = S.allocAP<T>(Value.bitWidth());

  if constexpr (DoPush == PushVal::Yes)
    S.Stk.push<T>(Value);

  if constexpr (Op == IncDecOp::Inc) {
    if (!T::increment(Value, &Result) || !CanOverflow) {
      Ptr.deref<T>() = Result;
      return true;
    }
  } else {
    if (!T::decrement(Value, &Result) || !CanOverflow) {
      Ptr.deref<T>() = Result;
      return true;
    }
  }
  assert(CanOverflow);

  // Something went wrong with the previous operation. Compute the
  // result with another bit of precision.
  unsigned Bits = Value.bitWidth() + 1;
  APSInt APResult;
  if constexpr (Op == IncDecOp::Inc)
    APResult = ++Value.toAPSInt(Bits);
  else
    APResult = --Value.toAPSInt(Bits);

  // Report undefined behaviour, stopping if required.
  if (S.checkingForUndefinedBehavior()) {
    const Expr *E = S.Current->getExpr(OpPC);
    QualType Type = E->getType();
    SmallString<32> Trunc;
    APResult.trunc(Result.bitWidth())
        .toString(Trunc, 10, Result.isSigned(), /*formatAsCLiteral=*/false,
                  /*UpperCase=*/true, /*InsertSeparators=*/true);
    S.report(E->getExprLoc(), diag::warn_integer_constant_overflow)
        << Trunc << Type << E->getSourceRange();
    return true;
  }
  return handleOverflow(S, OpPC, APResult);
}

/// 1) Pops a pointer from the stack
/// 2) Load the value from the pointer
/// 3) Writes the value increased by one back to the pointer
/// 4) Pushes the original (pre-inc) value on the stack.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Inc(InterpState &S, CodePtr OpPC, bool CanOverflow) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
    return false;

  return IncDecHelper<T, IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr,
                                                      CanOverflow);
}

/// 1) Pops a pointer from the stack
/// 2) Load the value from the pointer
/// 3) Writes the value increased by one back to the pointer
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool IncPop(InterpState &S, CodePtr OpPC, bool CanOverflow) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
    return false;

  return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow);
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool PreInc(InterpState &S, CodePtr OpPC, bool CanOverflow) {
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
    return false;

  return IncDecHelper<T, IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, CanOverflow);
}

/// 1) Pops a pointer from the stack
/// 2) Load the value from the pointer
/// 3) Writes the value decreased by one back to the pointer
/// 4) Pushes the original (pre-dec) value on the stack.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Dec(InterpState &S, CodePtr OpPC, bool CanOverflow) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
    return false;

  return IncDecHelper<T, IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr,
                                                      CanOverflow);
}

/// 1) Pops a pointer from the stack
/// 2) Load the value from the pointer
/// 3) Writes the value decreased by one back to the pointer
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool DecPop(InterpState &S, CodePtr OpPC, bool CanOverflow) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
    return false;

  return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow);
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool PreDec(InterpState &S, CodePtr OpPC, bool CanOverflow) {
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
    return false;
  return IncDecHelper<T, IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, CanOverflow);
}

template <IncDecOp Op, PushVal DoPush>
bool IncDecFloatHelper(InterpState &S, CodePtr OpPC, const Pointer &Ptr,
                       uint32_t FPOI) {
  Floating Value = Ptr.deref<Floating>();
  Floating Result = S.allocFloat(Value.getSemantics());

  if constexpr (DoPush == PushVal::Yes)
    S.Stk.push<Floating>(Value);

  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
  llvm::APFloat::opStatus Status;
  if constexpr (Op == IncDecOp::Inc)
    Status = Floating::increment(Value, getRoundingMode(FPO), &Result);
  else
    Status = Floating::decrement(Value, getRoundingMode(FPO), &Result);

  Ptr.deref<Floating>() = Result;

  return CheckFloatResult(S, OpPC, Result, Status, FPO);
}

inline bool Incf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
    return false;

  return IncDecFloatHelper<IncDecOp::Inc, PushVal::Yes>(S, OpPC, Ptr, FPOI);
}

inline bool IncfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckLoad(S, OpPC, Ptr, AK_Increment))
    return false;

  return IncDecFloatHelper<IncDecOp::Inc, PushVal::No>(S, OpPC, Ptr, FPOI);
}

inline bool Decf(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
    return false;

  return IncDecFloatHelper<IncDecOp::Dec, PushVal::Yes>(S, OpPC, Ptr, FPOI);
}

inline bool DecfPop(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckLoad(S, OpPC, Ptr, AK_Decrement))
    return false;

  return IncDecFloatHelper<IncDecOp::Dec, PushVal::No>(S, OpPC, Ptr, FPOI);
}

/// 1) Pops the value from the stack.
/// 2) Pushes the bitwise complemented value on the stack (~V).
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Comp(InterpState &S, CodePtr OpPC) {
  const T &Val = S.Stk.pop<T>();

  T Result;
  if constexpr (needsAlloc<T>())
    Result = S.allocAP<T>(Val.bitWidth());

  if (!T::comp(Val, &Result)) {
    S.Stk.push<T>(Result);
    return true;
  }
  return false;
}

//===----------------------------------------------------------------------===//
// EQ, NE, GT, GE, LT, LE
//===----------------------------------------------------------------------===//

using CompareFn = llvm::function_ref<bool(ComparisonCategoryResult)>;

template <typename T>
bool CmpHelper(InterpState &S, CodePtr OpPC, CompareFn Fn) {
  assert((!std::is_same_v<T, MemberPointer>) &&
         "Non-equality comparisons on member pointer types should already be "
         "rejected in Sema.");
  using BoolT = PrimConv<PT_Bool>::T;
  const T &RHS = S.Stk.pop<T>();
  const T &LHS = S.Stk.pop<T>();
  S.Stk.push<BoolT>(BoolT::from(Fn(LHS.compare(RHS))));
  return true;
}

template <typename T>
bool CmpHelperEQ(InterpState &S, CodePtr OpPC, CompareFn Fn) {
  return CmpHelper<T>(S, OpPC, Fn);
}

template <>
inline bool CmpHelper<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
  using BoolT = PrimConv<PT_Bool>::T;
  const Pointer &RHS = S.Stk.pop<Pointer>();
  const Pointer &LHS = S.Stk.pop<Pointer>();

  // Function pointers cannot be compared in an ordered way.
  if (LHS.isFunctionPointer() || RHS.isFunctionPointer() ||
      LHS.isTypeidPointer() || RHS.isTypeidPointer()) {
    const SourceInfo &Loc = S.Current->getSource(OpPC);
    S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
        << LHS.toDiagnosticString(S.getASTContext())
        << RHS.toDiagnosticString(S.getASTContext());
    return false;
  }

  if (!Pointer::hasSameBase(LHS, RHS)) {
    const SourceInfo &Loc = S.Current->getSource(OpPC);
    S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
        << LHS.toDiagnosticString(S.getASTContext())
        << RHS.toDiagnosticString(S.getASTContext());
    return false;
  }

  // Diagnose comparisons between fields with different access specifiers.
  if (std::optional<std::pair<Pointer, Pointer>> Split =
          Pointer::computeSplitPoint(LHS, RHS)) {
    const FieldDecl *LF = Split->first.getField();
    const FieldDecl *RF = Split->second.getField();
    if (LF && RF && !LF->getParent()->isUnion() &&
        LF->getAccess() != RF->getAccess()) {
      S.CCEDiag(S.Current->getSource(OpPC),
                diag::note_constexpr_pointer_comparison_differing_access)
          << LF << LF->getAccess() << RF << RF->getAccess() << LF->getParent();
    }
  }

  unsigned VL = LHS.getByteOffset();
  unsigned VR = RHS.getByteOffset();
  S.Stk.push<BoolT>(BoolT::from(Fn(Compare(VL, VR))));
  return true;
}

static inline bool IsOpaqueConstantCall(const CallExpr *E) {
  unsigned Builtin = E->getBuiltinCallee();
  return (Builtin == Builtin::BI__builtin___CFStringMakeConstantString ||
          Builtin == Builtin::BI__builtin___NSStringMakeConstantString ||
          Builtin == Builtin::BI__builtin_ptrauth_sign_constant ||
          Builtin == Builtin::BI__builtin_function_start);
}

bool arePotentiallyOverlappingStringLiterals(const Pointer &LHS,
                                             const Pointer &RHS);

template <>
inline bool CmpHelperEQ<Pointer>(InterpState &S, CodePtr OpPC, CompareFn Fn) {
  using BoolT = PrimConv<PT_Bool>::T;
  const Pointer &RHS = S.Stk.pop<Pointer>();
  const Pointer &LHS = S.Stk.pop<Pointer>();

  if (LHS.isZero() && RHS.isZero()) {
    S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Equal)));
    return true;
  }

  // Reject comparisons to weak pointers.
  for (const auto &P : {LHS, RHS}) {
    if (P.isZero())
      continue;
    if (P.isWeak()) {
      const SourceInfo &Loc = S.Current->getSource(OpPC);
      S.FFDiag(Loc, diag::note_constexpr_pointer_weak_comparison)
          << P.toDiagnosticString(S.getASTContext());
      return false;
    }
  }

  if (!S.inConstantContext()) {
    if (isConstexprUnknown(LHS) || isConstexprUnknown(RHS))
      return false;
  }

  if (LHS.isFunctionPointer() && RHS.isFunctionPointer()) {
    S.Stk.push<BoolT>(BoolT::from(Fn(Compare(LHS.getIntegerRepresentation(),
                                             RHS.getIntegerRepresentation()))));
    return true;
  }

  // FIXME: The source check here isn't entirely correct.
  if (LHS.pointsToStringLiteral() && RHS.pointsToStringLiteral() &&
      LHS.getFieldDesc()->asExpr() != RHS.getFieldDesc()->asExpr()) {
    if (arePotentiallyOverlappingStringLiterals(LHS, RHS)) {
      const SourceInfo &Loc = S.Current->getSource(OpPC);
      S.FFDiag(Loc, diag::note_constexpr_literal_comparison)
          << LHS.toDiagnosticString(S.getASTContext())
          << RHS.toDiagnosticString(S.getASTContext());
      return false;
    }
  }

  if (Pointer::hasSameBase(LHS, RHS)) {
    size_t A = LHS.computeOffsetForComparison();
    size_t B = RHS.computeOffsetForComparison();
    S.Stk.push<BoolT>(BoolT::from(Fn(Compare(A, B))));
    return true;
  }

  // Otherwise we need to do a bunch of extra checks before returning Unordered.
  if (LHS.isOnePastEnd() && !RHS.isOnePastEnd() && !RHS.isZero() &&
      RHS.getOffset() == 0) {
    const SourceInfo &Loc = S.Current->getSource(OpPC);
    S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
        << LHS.toDiagnosticString(S.getASTContext());
    return false;
  }
  if (RHS.isOnePastEnd() && !LHS.isOnePastEnd() && !LHS.isZero() &&
      LHS.getOffset() == 0) {
    const SourceInfo &Loc = S.Current->getSource(OpPC);
    S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_past_end)
        << RHS.toDiagnosticString(S.getASTContext());
    return false;
  }

  bool BothNonNull = !LHS.isZero() && !RHS.isZero();
  // Reject comparisons to literals.
  for (const auto &P : {LHS, RHS}) {
    if (P.isZero())
      continue;
    if (BothNonNull && P.pointsToLiteral()) {
      const Expr *E = P.getDeclDesc()->asExpr();
      if (isa<StringLiteral>(E)) {
        const SourceInfo &Loc = S.Current->getSource(OpPC);
        S.FFDiag(Loc, diag::note_constexpr_literal_comparison);
        return false;
      }
      if (const auto *CE = dyn_cast<CallExpr>(E);
          CE && IsOpaqueConstantCall(CE)) {
        const SourceInfo &Loc = S.Current->getSource(OpPC);
        S.FFDiag(Loc, diag::note_constexpr_opaque_call_comparison)
            << P.toDiagnosticString(S.getASTContext());
        return false;
      }
    } else if (BothNonNull && P.isIntegralPointer()) {
      const SourceInfo &Loc = S.Current->getSource(OpPC);
      S.FFDiag(Loc, diag::note_constexpr_pointer_constant_comparison)
          << LHS.toDiagnosticString(S.getASTContext())
          << RHS.toDiagnosticString(S.getASTContext());
      return false;
    }
  }

  if (LHS.isUnknownSizeArray() && RHS.isUnknownSizeArray()) {
    const SourceInfo &Loc = S.Current->getSource(OpPC);
    S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_zero_sized)
        << LHS.toDiagnosticString(S.getASTContext())
        << RHS.toDiagnosticString(S.getASTContext());
    return false;
  }

  S.Stk.push<BoolT>(BoolT::from(Fn(ComparisonCategoryResult::Unordered)));
  return true;
}

template <>
inline bool CmpHelperEQ<MemberPointer>(InterpState &S, CodePtr OpPC,
                                       CompareFn Fn) {
  const auto &RHS = S.Stk.pop<MemberPointer>();
  const auto &LHS = S.Stk.pop<MemberPointer>();

  // If either operand is a pointer to a weak function, the comparison is not
  // constant.
  for (const auto &MP : {LHS, RHS}) {
    if (MP.isWeak()) {
      const SourceInfo &Loc = S.Current->getSource(OpPC);
      S.FFDiag(Loc, diag::note_constexpr_mem_pointer_weak_comparison)
          << MP.getMemberFunction();
      return false;
    }
  }

  // C++11 [expr.eq]p2:
  //   If both operands are null, they compare equal. Otherwise if only one is
  //   null, they compare unequal.
  if (LHS.isZero() && RHS.isZero()) {
    S.Stk.push<Boolean>(Fn(ComparisonCategoryResult::Equal));
    return true;
  }
  if (LHS.isZero() || RHS.isZero()) {
    S.Stk.push<Boolean>(Fn(ComparisonCategoryResult::Unordered));
    return true;
  }

  // We cannot compare against virtual declarations at compile time.
  for (const auto &MP : {LHS, RHS}) {
    if (const CXXMethodDecl *MD = MP.getMemberFunction();
        MD && MD->isVirtual()) {
      const SourceInfo &Loc = S.Current->getSource(OpPC);
      S.CCEDiag(Loc, diag::note_constexpr_compare_virtual_mem_ptr) << MD;
    }
  }

  S.Stk.push<Boolean>(Boolean::from(Fn(LHS.compare(RHS))));
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool EQ(InterpState &S, CodePtr OpPC) {
  return CmpHelperEQ<T>(S, OpPC, [](ComparisonCategoryResult R) {
    return R == ComparisonCategoryResult::Equal;
  });
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CMP3(InterpState &S, CodePtr OpPC, const ComparisonCategoryInfo *CmpInfo) {
  const T &RHS = S.Stk.pop<T>();
  const T &LHS = S.Stk.pop<T>();
  const Pointer &P = S.Stk.peek<Pointer>();

  ComparisonCategoryResult CmpResult = LHS.compare(RHS);
  if constexpr (std::is_same_v<T, Pointer>) {
    if (CmpResult == ComparisonCategoryResult::Unordered) {
      const SourceInfo &Loc = S.Current->getSource(OpPC);
      S.FFDiag(Loc, diag::note_constexpr_pointer_comparison_unspecified)
          << LHS.toDiagnosticString(S.getASTContext())
          << RHS.toDiagnosticString(S.getASTContext());
      return false;
    }
  }

  assert(CmpInfo);
  const auto *CmpValueInfo =
      CmpInfo->getValueInfo(CmpInfo->makeWeakResult(CmpResult));
  assert(CmpValueInfo);
  assert(CmpValueInfo->hasValidIntValue());
  return SetThreeWayComparisonField(S, OpPC, P, CmpValueInfo->getIntValue());
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool NE(InterpState &S, CodePtr OpPC) {
  return CmpHelperEQ<T>(S, OpPC, [](ComparisonCategoryResult R) {
    return R != ComparisonCategoryResult::Equal;
  });
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool LT(InterpState &S, CodePtr OpPC) {
  return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
    return R == ComparisonCategoryResult::Less;
  });
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool LE(InterpState &S, CodePtr OpPC) {
  return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
    return R == ComparisonCategoryResult::Less ||
           R == ComparisonCategoryResult::Equal;
  });
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GT(InterpState &S, CodePtr OpPC) {
  return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
    return R == ComparisonCategoryResult::Greater;
  });
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GE(InterpState &S, CodePtr OpPC) {
  return CmpHelper<T>(S, OpPC, [](ComparisonCategoryResult R) {
    return R == ComparisonCategoryResult::Greater ||
           R == ComparisonCategoryResult::Equal;
  });
}

//===----------------------------------------------------------------------===//
// Dup, Pop, Test
//===----------------------------------------------------------------------===//

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Dup(InterpState &S, CodePtr OpPC) {
  S.Stk.push<T>(S.Stk.peek<T>());
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Pop(InterpState &S, CodePtr OpPC) {
  S.Stk.discard<T>();
  return true;
}

/// [Value1, Value2] -> [Value2, Value1]
template <PrimType TopName, PrimType BottomName>
bool Flip(InterpState &S, CodePtr OpPC) {
  using TopT = typename PrimConv<TopName>::T;
  using BottomT = typename PrimConv<BottomName>::T;

  const auto &Top = S.Stk.pop<TopT>();
  const auto &Bottom = S.Stk.pop<BottomT>();

  S.Stk.push<TopT>(Top);
  S.Stk.push<BottomT>(Bottom);

  return true;
}

//===----------------------------------------------------------------------===//
// Const
//===----------------------------------------------------------------------===//

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Const(InterpState &S, CodePtr OpPC, const T &Arg) {
  if constexpr (needsAlloc<T>()) {
    T Result = S.allocAP<T>(Arg.bitWidth());
    Result.copy(Arg.toAPSInt());
    S.Stk.push<T>(Result);
    return true;
  }
  S.Stk.push<T>(Arg);
  return true;
}

inline bool ConstFloat(InterpState &S, CodePtr OpPC, const Floating &F) {
  Floating Result = S.allocFloat(F.getSemantics());
  Result.copy(F.getAPFloat());
  S.Stk.push<Floating>(Result);
  return true;
}

//===----------------------------------------------------------------------===//
// Get/Set Local/Param/Global/This
//===----------------------------------------------------------------------===//

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
  const Block *B = S.Current->getLocalBlock(I);
  if (!CheckLocalLoad(S, OpPC, B))
    return false;
  S.Stk.push<T>(B->deref<T>());
  return true;
}

bool EndLifetime(InterpState &S, CodePtr OpPC);
bool EndLifetimePop(InterpState &S, CodePtr OpPC);
bool StartLifetime(InterpState &S, CodePtr OpPC);

/// 1) Pops the value from the stack.
/// 2) Writes the value to the local variable with the
///    given offset.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool SetLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
  S.Current->setLocal<T>(I, S.Stk.pop<T>());
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetParam(InterpState &S, CodePtr OpPC, uint32_t I) {
  if (S.checkingPotentialConstantExpression()) {
    return false;
  }
  S.Stk.push<T>(S.Current->getParam<T>(I));
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool SetParam(InterpState &S, CodePtr OpPC, uint32_t I) {
  S.Current->setParam<T>(I, S.Stk.pop<T>());
  return true;
}

/// 1) Peeks a pointer on the stack
/// 2) Pushes the value of the pointer's field on the stack
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetField(InterpState &S, CodePtr OpPC, uint32_t I) {
  const Pointer &Obj = S.Stk.peek<Pointer>();
  if (!CheckNull(S, OpPC, Obj, CSK_Field))
    return false;
  if (!CheckRange(S, OpPC, Obj, CSK_Field))
    return false;
  const Pointer &Field = Obj.atField(I);
  if (!CheckLoad(S, OpPC, Field))
    return false;
  S.Stk.push<T>(Field.deref<T>());
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool SetField(InterpState &S, CodePtr OpPC, uint32_t I) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Obj = S.Stk.peek<Pointer>();
  if (!CheckNull(S, OpPC, Obj, CSK_Field))
    return false;
  if (!CheckRange(S, OpPC, Obj, CSK_Field))
    return false;
  const Pointer &Field = Obj.atField(I);
  if (!CheckStore(S, OpPC, Field))
    return false;
  Field.initialize();
  Field.deref<T>() = Value;
  return true;
}

/// 1) Pops a pointer from the stack
/// 2) Pushes the value of the pointer's field on the stack
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetFieldPop(InterpState &S, CodePtr OpPC, uint32_t I) {
  const Pointer &Obj = S.Stk.pop<Pointer>();
  if (!CheckNull(S, OpPC, Obj, CSK_Field))
    return false;
  if (!CheckRange(S, OpPC, Obj, CSK_Field))
    return false;
  const Pointer &Field = Obj.atField(I);
  if (!CheckLoad(S, OpPC, Field))
    return false;
  S.Stk.push<T>(Field.deref<T>());
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
  if (S.checkingPotentialConstantExpression())
    return false;
  const Pointer &This = S.Current->getThis();
  if (!CheckThis(S, OpPC, This))
    return false;
  const Pointer &Field = This.atField(I);
  if (!CheckLoad(S, OpPC, Field))
    return false;
  S.Stk.push<T>(Field.deref<T>());
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool SetThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
  if (S.checkingPotentialConstantExpression())
    return false;
  const T &Value = S.Stk.pop<T>();
  const Pointer &This = S.Current->getThis();
  if (!CheckThis(S, OpPC, This))
    return false;
  const Pointer &Field = This.atField(I);
  if (!CheckStore(S, OpPC, Field))
    return false;
  Field.deref<T>() = Value;
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
  const Block *B = S.P.getGlobal(I);

  if (!CheckGlobalLoad(S, OpPC, B))
    return false;

  S.Stk.push<T>(B->deref<T>());
  return true;
}

/// Same as GetGlobal, but without the checks.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool GetGlobalUnchecked(InterpState &S, CodePtr OpPC, uint32_t I) {
  const Block *B = S.P.getGlobal(I);
  const auto &Desc =
      *reinterpret_cast<const GlobalInlineDescriptor *>(B->rawData());
  if (Desc.InitState != GlobalInitState::Initialized)
    return DiagnoseUninitialized(S, OpPC, B->isExtern(), B->getDescriptor(),
                                 AK_Read);

  S.Stk.push<T>(B->deref<T>());
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool SetGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
  // TODO: emit warning.
  return false;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
  const Pointer &P = S.P.getGlobal(I);

  P.deref<T>() = S.Stk.pop<T>();

  if constexpr (std::is_same_v<T, Floating>) {
    auto &Val = P.deref<Floating>();
    if (!Val.singleWord()) {
      uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
      Val.take(NewMemory);
    }

  } else if constexpr (needsAlloc<T>()) {
    auto &Val = P.deref<T>();
    if (!Val.singleWord()) {
      uint64_t *NewMemory = new (S.P) uint64_t[Val.numWords()];
      Val.take(NewMemory);
    }
  }

  P.initialize();
  return true;
}

/// 1) Converts the value on top of the stack to an APValue
/// 2) Sets that APValue on \Temp
/// 3) Initializes global with index \I with that
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitGlobalTemp(InterpState &S, CodePtr OpPC, uint32_t I,
                    const LifetimeExtendedTemporaryDecl *Temp) {
  if (S.EvalMode == EvaluationMode::ConstantFold)
    return false;
  assert(Temp);

  const Pointer &Ptr = S.P.getGlobal(I);
  assert(Ptr.getDeclDesc()->asExpr());
  S.SeenGlobalTemporaries.push_back(
      std::make_pair(Ptr.getDeclDesc()->asExpr(), Temp));

  Ptr.deref<T>() = S.Stk.pop<T>();
  Ptr.initialize();
  return true;
}

/// 1) Converts the value on top of the stack to an APValue
/// 2) Sets that APValue on \Temp
/// 3) Initialized global with index \I with that
inline bool InitGlobalTempComp(InterpState &S, CodePtr OpPC,
                               const LifetimeExtendedTemporaryDecl *Temp) {
  if (S.EvalMode == EvaluationMode::ConstantFold)
    return false;
  assert(Temp);

  const Pointer &Ptr = S.Stk.peek<Pointer>();
  S.SeenGlobalTemporaries.push_back(
      std::make_pair(Ptr.getDeclDesc()->asExpr(), Temp));
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
  if (S.checkingPotentialConstantExpression() && S.Current->getDepth() == 0)
    return false;
  const Pointer &This = S.Current->getThis();
  if (!CheckThis(S, OpPC, This))
    return false;
  const Pointer &Field = This.atField(I);
  assert(Field.canBeInitialized());
  Field.deref<T>() = S.Stk.pop<T>();
  Field.initialize();
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitThisFieldActivate(InterpState &S, CodePtr OpPC, uint32_t I) {
  if (S.checkingPotentialConstantExpression() && S.Current->getDepth() == 0)
    return false;
  const Pointer &This = S.Current->getThis();
  if (!CheckThis(S, OpPC, This))
    return false;
  const Pointer &Field = This.atField(I);
  assert(Field.canBeInitialized());
  Field.deref<T>() = S.Stk.pop<T>();
  Field.activate();
  Field.initialize();
  return true;
}

// FIXME: The Field pointer here is too much IMO and we could instead just
// pass an Offset + BitWidth pair.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitThisBitField(InterpState &S, CodePtr OpPC, const Record::Field *F,
                      uint32_t FieldOffset) {
  assert(F->isBitField());
  if (S.checkingPotentialConstantExpression() && S.Current->getDepth() == 0)
    return false;
  const Pointer &This = S.Current->getThis();
  if (!CheckThis(S, OpPC, This))
    return false;
  const Pointer &Field = This.atField(FieldOffset);
  assert(Field.canBeInitialized());
  const auto &Value = S.Stk.pop<T>();
  Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
  Field.initialize();
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitThisBitFieldActivate(InterpState &S, CodePtr OpPC,
                              const Record::Field *F, uint32_t FieldOffset) {
  assert(F->isBitField());
  if (S.checkingPotentialConstantExpression() && S.Current->getDepth() == 0)
    return false;
  const Pointer &This = S.Current->getThis();
  if (!CheckThis(S, OpPC, This))
    return false;
  const Pointer &Field = This.atField(FieldOffset);
  assert(Field.canBeInitialized());
  const auto &Value = S.Stk.pop<T>();
  Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
  Field.initialize();
  Field.activate();
  return true;
}

/// 1) Pops the value from the stack
/// 2) Peeks a pointer from the stack
/// 3) Pushes the value to field I of the pointer on the stack
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitField(InterpState &S, CodePtr OpPC, uint32_t I) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (!CheckRange(S, OpPC, Ptr, CSK_Field))
    return false;
  if (!CheckArray(S, OpPC, Ptr))
    return false;

  const Pointer &Field = Ptr.atField(I);
  Field.deref<T>() = Value;
  Field.initialize();
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitFieldActivate(InterpState &S, CodePtr OpPC, uint32_t I) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (!CheckRange(S, OpPC, Ptr, CSK_Field))
    return false;
  if (!CheckArray(S, OpPC, Ptr))
    return false;

  const Pointer &Field = Ptr.atField(I);
  Field.deref<T>() = Value;
  Field.activate();
  Field.initialize();
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitBitField(InterpState &S, CodePtr OpPC, const Record::Field *F) {
  assert(F->isBitField());
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (!CheckRange(S, OpPC, Ptr, CSK_Field))
    return false;
  if (!CheckArray(S, OpPC, Ptr))
    return false;

  const Pointer &Field = Ptr.atField(F->Offset);

  if constexpr (needsAlloc<T>()) {
    T Result = S.allocAP<T>(Value.bitWidth());
    if (T::isSigned())
      Result.copy(Value.toAPSInt()
                      .trunc(F->Decl->getBitWidthValue())
                      .sextOrTrunc(Value.bitWidth()));
    else
      Result.copy(Value.toAPSInt()
                      .trunc(F->Decl->getBitWidthValue())
                      .zextOrTrunc(Value.bitWidth()));

    Field.deref<T>() = Result;
  } else {
    Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
  }
  Field.initialize();
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitBitFieldActivate(InterpState &S, CodePtr OpPC,
                          const Record::Field *F) {
  assert(F->isBitField());
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (!CheckRange(S, OpPC, Ptr, CSK_Field))
    return false;
  if (!CheckArray(S, OpPC, Ptr))
    return false;

  const Pointer &Field = Ptr.atField(F->Offset);

  if constexpr (needsAlloc<T>()) {
    T Result = S.allocAP<T>(Value.bitWidth());
    if (T::isSigned())
      Result.copy(Value.toAPSInt()
                      .trunc(F->Decl->getBitWidthValue())
                      .sextOrTrunc(Value.bitWidth()));
    else
      Result.copy(Value.toAPSInt()
                      .trunc(F->Decl->getBitWidthValue())
                      .zextOrTrunc(Value.bitWidth()));

    Field.deref<T>() = Result;
  } else {
    Field.deref<T>() = Value.truncate(F->Decl->getBitWidthValue());
  }
  Field.activate();
  Field.initialize();
  return true;
}

//===----------------------------------------------------------------------===//
// GetPtr Local/Param/Global/Field/This
//===----------------------------------------------------------------------===//

inline bool GetPtrLocal(InterpState &S, CodePtr OpPC, uint32_t I) {
  S.Stk.push<Pointer>(S.Current->getLocalPointer(I));
  return true;
}

inline bool GetPtrParam(InterpState &S, CodePtr OpPC, uint32_t I) {
  if (S.checkingPotentialConstantExpression()) {
    return false;
  }
  S.Stk.push<Pointer>(S.Current->getParamPointer(I));
  return true;
}

inline bool GetPtrGlobal(InterpState &S, CodePtr OpPC, uint32_t I) {
  S.Stk.push<Pointer>(S.P.getPtrGlobal(I));
  return true;
}

/// 1) Peeks a Pointer
/// 2) Pushes Pointer.atField(Off) on the stack
bool GetPtrField(InterpState &S, CodePtr OpPC, uint32_t Off);
bool GetPtrFieldPop(InterpState &S, CodePtr OpPC, uint32_t Off);

inline bool GetPtrThisField(InterpState &S, CodePtr OpPC, uint32_t Off) {
  if (S.checkingPotentialConstantExpression() && S.Current->getDepth() == 0)
    return false;
  const Pointer &This = S.Current->getThis();
  if (!CheckThis(S, OpPC, This))
    return false;
  S.Stk.push<Pointer>(This.atField(Off));
  return true;
}

inline bool GetPtrDerivedPop(InterpState &S, CodePtr OpPC, uint32_t Off,
                             bool NullOK, const Type *TargetType) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!NullOK && !CheckNull(S, OpPC, Ptr, CSK_Derived))
    return false;

  if (!Ptr.isBlockPointer()) {
    // FIXME: We don't have the necessary information in integral pointers.
    // The Descriptor only has a record, but that does of course not include
    // the potential derived classes of said record.
    S.Stk.push<Pointer>(Ptr);
    return true;
  }

  if (!CheckSubobject(S, OpPC, Ptr, CSK_Derived))
    return false;
  if (!CheckDowncast(S, OpPC, Ptr, Off))
    return false;

  const Record *TargetRecord = Ptr.atFieldSub(Off).getRecord();
  assert(TargetRecord);

  if (TargetRecord->getDecl()->getCanonicalDecl() !=
      TargetType->getAsCXXRecordDecl()->getCanonicalDecl()) {
    QualType MostDerivedType = Ptr.getDeclDesc()->getType();
    S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_downcast)
        << MostDerivedType << QualType(TargetType, 0);
    return false;
  }

  S.Stk.push<Pointer>(Ptr.atFieldSub(Off));
  return true;
}

inline bool GetPtrBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (!CheckNull(S, OpPC, Ptr, CSK_Base))
    return false;

  if (!Ptr.isBlockPointer()) {
    if (!Ptr.isIntegralPointer())
      return false;
    S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.getASTContext(), Off));
    return true;
  }

  if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
    return false;
  const Pointer &Result = Ptr.atField(Off);
  if (Result.isPastEnd() || !Result.isBaseClass())
    return false;
  S.Stk.push<Pointer>(Result);
  return true;
}

inline bool GetPtrBasePop(InterpState &S, CodePtr OpPC, uint32_t Off,
                          bool NullOK) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();

  if (!NullOK && !CheckNull(S, OpPC, Ptr, CSK_Base))
    return false;

  if (!Ptr.isBlockPointer()) {
    if (!Ptr.isIntegralPointer())
      return false;
    S.Stk.push<Pointer>(Ptr.asIntPointer().baseCast(S.getASTContext(), Off));
    return true;
  }

  if (!CheckSubobject(S, OpPC, Ptr, CSK_Base))
    return false;
  const Pointer &Result = Ptr.atField(Off);
  if (Result.isPastEnd() || !Result.isBaseClass())
    return false;
  S.Stk.push<Pointer>(Result);
  return true;
}

inline bool GetMemberPtrBasePop(InterpState &S, CodePtr OpPC, int32_t Off) {
  const auto &Ptr = S.Stk.pop<MemberPointer>();
  S.Stk.push<MemberPointer>(Ptr.atInstanceBase(Off));
  return true;
}

inline bool GetPtrThisBase(InterpState &S, CodePtr OpPC, uint32_t Off) {
  if (S.checkingPotentialConstantExpression())
    return false;
  const Pointer &This = S.Current->getThis();
  if (!CheckThis(S, OpPC, This))
    return false;
  S.Stk.push<Pointer>(This.atField(Off));
  return true;
}

inline bool FinishInitPop(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (Ptr.canBeInitialized())
    Ptr.initialize();
  return true;
}

inline bool FinishInit(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (Ptr.canBeInitialized())
    Ptr.initialize();
  return true;
}

inline bool FinishInitActivate(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (Ptr.canBeInitialized()) {
    Ptr.initialize();
    Ptr.activate();
  }
  return true;
}

inline bool FinishInitActivatePop(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (Ptr.canBeInitialized()) {
    Ptr.initialize();
    Ptr.activate();
  }
  return true;
}

bool FinishInitGlobal(InterpState &S, CodePtr OpPC);

inline bool Dump(InterpState &S, CodePtr OpPC) {
  S.Stk.dump();
  return true;
}

inline bool CheckNull(InterpState &S, CodePtr OpPC) {
  const auto &Ptr = S.Stk.peek<Pointer>();
  if (Ptr.isZero()) {
    S.FFDiag(S.Current->getSource(OpPC),
             diag::note_constexpr_dereferencing_null);
    return S.noteUndefinedBehavior();
  }
  return true;
}

inline bool VirtBaseHelper(InterpState &S, CodePtr OpPC, const RecordDecl *Decl,
                           const Pointer &Ptr) {
  Pointer Base = Ptr;
  while (Base.isBaseClass())
    Base = Base.getBase();

  const Record::Base *VirtBase = Base.getRecord()->getVirtualBase(Decl);
  S.Stk.push<Pointer>(Base.atField(VirtBase->Offset));
  return true;
}

inline bool GetPtrVirtBasePop(InterpState &S, CodePtr OpPC,
                              const RecordDecl *D) {
  assert(D);
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckNull(S, OpPC, Ptr, CSK_Base))
    return false;
  return VirtBaseHelper(S, OpPC, D, Ptr);
}

inline bool GetPtrThisVirtBase(InterpState &S, CodePtr OpPC,
                               const RecordDecl *D) {
  assert(D);
  if (S.checkingPotentialConstantExpression())
    return false;
  const Pointer &This = S.Current->getThis();
  if (!CheckThis(S, OpPC, This))
    return false;
  return VirtBaseHelper(S, OpPC, D, S.Current->getThis());
}

//===----------------------------------------------------------------------===//
// Load, Store, Init
//===----------------------------------------------------------------------===//

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Load(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (!CheckLoad(S, OpPC, Ptr))
    return false;
  if (!Ptr.isBlockPointer())
    return false;
  S.Stk.push<T>(Ptr.deref<T>());
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool LoadPop(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckLoad(S, OpPC, Ptr))
    return false;
  if (!Ptr.isBlockPointer())
    return false;
  S.Stk.push<T>(Ptr.deref<T>());
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Store(InterpState &S, CodePtr OpPC) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (!CheckStore(S, OpPC, Ptr))
    return false;
  if (Ptr.canBeInitialized())
    Ptr.initialize();
  Ptr.deref<T>() = Value;
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StorePop(InterpState &S, CodePtr OpPC) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckStore(S, OpPC, Ptr))
    return false;
  if (Ptr.canBeInitialized())
    Ptr.initialize();
  Ptr.deref<T>() = Value;
  return true;
}

static inline bool Activate(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (Ptr.canBeInitialized())
    Ptr.activate();
  return true;
}

static inline bool ActivateThisField(InterpState &S, CodePtr OpPC, uint32_t I) {
  if (S.checkingPotentialConstantExpression())
    return false;

  const Pointer &Ptr = S.Current->getThis();
  assert(Ptr.atField(I).canBeInitialized());
  Ptr.atField(I).activate();
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StoreActivate(InterpState &S, CodePtr OpPC) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.peek<Pointer>();

  if (Ptr.canBeInitialized()) {
    Ptr.initialize();
    Ptr.activate();
  }

  if (!CheckStore(S, OpPC, Ptr))
    return false;
  Ptr.deref<T>() = Value;
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StoreActivatePop(InterpState &S, CodePtr OpPC) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.pop<Pointer>();

  if (Ptr.canBeInitialized()) {
    Ptr.initialize();
    Ptr.activate();
  }
  if (!CheckStore(S, OpPC, Ptr))
    return false;
  Ptr.deref<T>() = Value;
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StoreBitField(InterpState &S, CodePtr OpPC) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (!CheckStore(S, OpPC, Ptr))
    return false;
  if (Ptr.canBeInitialized())
    Ptr.initialize();
  if (const auto *FD = Ptr.getField())
    Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
  else
    Ptr.deref<T>() = Value;
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StoreBitFieldPop(InterpState &S, CodePtr OpPC) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckStore(S, OpPC, Ptr))
    return false;
  if (Ptr.canBeInitialized())
    Ptr.initialize();
  if (const auto *FD = Ptr.getField())
    Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
  else
    Ptr.deref<T>() = Value;
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StoreBitFieldActivate(InterpState &S, CodePtr OpPC) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (Ptr.canBeInitialized()) {
    Ptr.initialize();
    Ptr.activate();
  }
  if (!CheckStore(S, OpPC, Ptr))
    return false;
  if (const auto *FD = Ptr.getField())
    Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
  else
    Ptr.deref<T>() = Value;
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool StoreBitFieldActivatePop(InterpState &S, CodePtr OpPC) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.pop<Pointer>();

  if (Ptr.canBeInitialized()) {
    Ptr.initialize();
    Ptr.activate();
  }
  if (!CheckStore(S, OpPC, Ptr))
    return false;
  if (const auto *FD = Ptr.getField())
    Ptr.deref<T>() = Value.truncate(FD->getBitWidthValue());
  else
    Ptr.deref<T>() = Value;
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Init(InterpState &S, CodePtr OpPC) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.peek<Pointer>();
  if (!CheckInit(S, OpPC, Ptr))
    return false;
  Ptr.initialize();
  new (&Ptr.deref<T>()) T(Value);
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitPop(InterpState &S, CodePtr OpPC) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (!CheckInit(S, OpPC, Ptr))
    return false;
  Ptr.initialize();
  new (&Ptr.deref<T>()) T(Value);
  return true;
}

/// 1) Pops the value from the stack
/// 2) Peeks a pointer and gets its index \Idx
/// 3) Sets the value on the pointer, leaving the pointer on the stack.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitElem(InterpState &S, CodePtr OpPC, uint32_t Idx) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.peek<Pointer>();

  if (Ptr.isUnknownSizeArray())
    return false;

  // In the unlikely event that we're initializing the first item of
  // a non-array, skip the atIndex().
  if (Idx == 0 && !Ptr.getFieldDesc()->isArray()) {
    Ptr.initialize();
    new (&Ptr.deref<T>()) T(Value);
    return true;
  }

  const Pointer &ElemPtr = Ptr.atIndex(Idx);
  if (!CheckInit(S, OpPC, ElemPtr))
    return false;
  ElemPtr.initialize();
  new (&ElemPtr.deref<T>()) T(Value);
  return true;
}

/// The same as InitElem, but pops the pointer as well.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool InitElemPop(InterpState &S, CodePtr OpPC, uint32_t Idx) {
  const T &Value = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (Ptr.isUnknownSizeArray())
    return false;

  // In the unlikely event that we're initializing the first item of
  // a non-array, skip the atIndex().
  if (Idx == 0 && !Ptr.getFieldDesc()->isArray()) {
    Ptr.initialize();
    new (&Ptr.deref<T>()) T(Value);
    return true;
  }

  const Pointer &ElemPtr = Ptr.atIndex(Idx);
  if (!CheckInit(S, OpPC, ElemPtr))
    return false;
  ElemPtr.initialize();
  new (&ElemPtr.deref<T>()) T(Value);
  return true;
}

inline bool Memcpy(InterpState &S, CodePtr OpPC) {
  const Pointer &Src = S.Stk.pop<Pointer>();
  Pointer &Dest = S.Stk.peek<Pointer>();

  if (!CheckLoad(S, OpPC, Src))
    return false;

  return DoMemcpy(S, OpPC, Src, Dest);
}

inline bool ToMemberPtr(InterpState &S, CodePtr OpPC) {
  const auto &Member = S.Stk.pop<MemberPointer>();
  const auto &Base = S.Stk.pop<Pointer>();

  S.Stk.push<MemberPointer>(Member.takeInstance(Base));
  return true;
}

inline bool CastMemberPtrPtr(InterpState &S, CodePtr OpPC) {
  const auto &MP = S.Stk.pop<MemberPointer>();

  if (std::optional<Pointer> Ptr = MP.toPointer(S.Ctx)) {
    S.Stk.push<Pointer>(*Ptr);
    return true;
  }
  return Invalid(S, OpPC);
}

//===----------------------------------------------------------------------===//
// AddOffset, SubOffset
//===----------------------------------------------------------------------===//

template <class T, ArithOp Op>
std::optional<Pointer> OffsetHelper(InterpState &S, CodePtr OpPC,
                                    const T &Offset, const Pointer &Ptr,
                                    bool IsPointerArith = false) {
  // A zero offset does not change the pointer.
  if (Offset.isZero())
    return Ptr;

  if (IsPointerArith && !CheckNull(S, OpPC, Ptr, CSK_ArrayIndex)) {
    // The CheckNull will have emitted a note already, but we only
    // abort in C++, since this is fine in C.
    if (S.getLangOpts().CPlusPlus)
      return std::nullopt;
  }

  // Arrays of unknown bounds cannot have pointers into them.
  if (!CheckArray(S, OpPC, Ptr))
    return std::nullopt;

  // This is much simpler for integral pointers, so handle them first.
  if (Ptr.isIntegralPointer()) {
    uint64_t V = Ptr.getIntegerRepresentation();
    uint64_t O = static_cast<uint64_t>(Offset) * Ptr.elemSize();
    if constexpr (Op == ArithOp::Add)
      return Pointer(V + O, Ptr.asIntPointer().Desc);
    else
      return Pointer(V - O, Ptr.asIntPointer().Desc);
  } else if (Ptr.isFunctionPointer()) {
    uint64_t O = static_cast<uint64_t>(Offset);
    uint64_t N;
    if constexpr (Op == ArithOp::Add)
      N = Ptr.getByteOffset() + O;
    else
      N = Ptr.getByteOffset() - O;

    if (N > 1)
      S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
          << N << /*non-array*/ true << 0;
    return Pointer(Ptr.asFunctionPointer().getFunction(), N);
  }

  assert(Ptr.isBlockPointer());

  uint64_t MaxIndex = static_cast<uint64_t>(Ptr.getNumElems());
  uint64_t Index;
  if (Ptr.isOnePastEnd())
    Index = MaxIndex;
  else
    Index = Ptr.getIndex();

  bool Invalid = false;
  // Helper to report an invalid offset, computed as APSInt.
  auto DiagInvalidOffset = [&]() -> void {
    const unsigned Bits = Offset.bitWidth();
    APSInt APOffset(Offset.toAPSInt().extend(Bits + 2), /*IsUnsigend=*/false);
    APSInt APIndex(APInt(Bits + 2, Index, /*IsSigned=*/true),
                   /*IsUnsigned=*/false);
    APSInt NewIndex =
        (Op == ArithOp::Add) ? (APIndex + APOffset) : (APIndex - APOffset);
    S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_array_index)
        << NewIndex << /*array*/ static_cast<int>(!Ptr.inArray()) << MaxIndex;
    Invalid = true;
  };

  if (Ptr.isBlockPointer()) {
    uint64_t IOffset = static_cast<uint64_t>(Offset);
    uint64_t MaxOffset = MaxIndex - Index;

    if constexpr (Op == ArithOp::Add) {
      // If the new offset would be negative, bail out.
      if (Offset.isNegative() && (Offset.isMin() || -IOffset > Index))
        DiagInvalidOffset();

      // If the new offset would be out of bounds, bail out.
      if (Offset.isPositive() && IOffset > MaxOffset)
        DiagInvalidOffset();
    } else {
      // If the new offset would be negative, bail out.
      if (Offset.isPositive() && Index < IOffset)
        DiagInvalidOffset();

      // If the new offset would be out of bounds, bail out.
      if (Offset.isNegative() && (Offset.isMin() || -IOffset > MaxOffset))
        DiagInvalidOffset();
    }
  }

  if (Invalid && S.getLangOpts().CPlusPlus)
    return std::nullopt;

  // Offset is valid - compute it on unsigned.
  int64_t WideIndex = static_cast<int64_t>(Index);
  int64_t WideOffset = static_cast<int64_t>(Offset);
  int64_t Result;
  if constexpr (Op == ArithOp::Add)
    Result = WideIndex + WideOffset;
  else
    Result = WideIndex - WideOffset;

  // When the pointer is one-past-end, going back to index 0 is the only
  // useful thing we can do. Any other index has been diagnosed before and
  // we don't get here.
  if (Result == 0 && Ptr.isOnePastEnd()) {
    if (Ptr.getFieldDesc()->isArray())
      return Ptr.atIndex(0);
    return Pointer(Ptr.asBlockPointer().Pointee, Ptr.asBlockPointer().Base);
  }

  return Ptr.atIndex(static_cast<uint64_t>(Result));
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool AddOffset(InterpState &S, CodePtr OpPC) {
  const T &Offset = S.Stk.pop<T>();
  Pointer Ptr = S.Stk.pop<Pointer>();
  if (Ptr.isBlockPointer())
    Ptr = Ptr.expand();

  if (std::optional<Pointer> Result = OffsetHelper<T, ArithOp::Add>(
          S, OpPC, Offset, Ptr, /*IsPointerArith=*/true)) {
    S.Stk.push<Pointer>(*Result);
    return true;
  }
  return false;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool SubOffset(InterpState &S, CodePtr OpPC) {
  const T &Offset = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.pop<Pointer>();

  if (std::optional<Pointer> Result = OffsetHelper<T, ArithOp::Sub>(
          S, OpPC, Offset, Ptr, /*IsPointerArith=*/true)) {
    S.Stk.push<Pointer>(*Result);
    return true;
  }
  return false;
}

template <ArithOp Op>
static inline bool IncDecPtrHelper(InterpState &S, CodePtr OpPC,
                                   const Pointer &Ptr) {
  if (Ptr.isDummy())
    return false;

  using OneT = Integral<8, false>;

  const Pointer &P = Ptr.deref<Pointer>();
  if (!CheckNull(S, OpPC, P, CSK_ArrayIndex))
    return false;

  // Get the current value on the stack.
  S.Stk.push<Pointer>(P);

  // Now the current Ptr again and a constant 1.
  OneT One = OneT::from(1);
  if (std::optional<Pointer> Result =
          OffsetHelper<OneT, Op>(S, OpPC, One, P, /*IsPointerArith=*/true)) {
    // Store the new value.
    Ptr.deref<Pointer>() = *Result;
    return true;
  }
  return false;
}

static inline bool IncPtr(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();

  if (!Ptr.isInitialized())
    return DiagnoseUninitialized(S, OpPC, Ptr, AK_Increment);

  return IncDecPtrHelper<ArithOp::Add>(S, OpPC, Ptr);
}

static inline bool DecPtr(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();

  if (!Ptr.isInitialized())
    return DiagnoseUninitialized(S, OpPC, Ptr, AK_Decrement);

  return IncDecPtrHelper<ArithOp::Sub>(S, OpPC, Ptr);
}

/// 1) Pops a Pointer from the stack.
/// 2) Pops another Pointer from the stack.
/// 3) Pushes the difference of the indices of the two pointers on the stack.
template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool SubPtr(InterpState &S, CodePtr OpPC) {
  const Pointer &LHS = S.Stk.pop<Pointer>();
  const Pointer &RHS = S.Stk.pop<Pointer>();

  if (!Pointer::hasSameBase(LHS, RHS) && S.getLangOpts().CPlusPlus) {
    S.FFDiag(S.Current->getSource(OpPC),
             diag::note_constexpr_pointer_arith_unspecified)
        << LHS.toDiagnosticString(S.getASTContext())
        << RHS.toDiagnosticString(S.getASTContext());
    return false;
  }

  if (LHS == RHS) {
    S.Stk.push<T>();
    return true;
  }

  for (const Pointer &P : {LHS, RHS}) {
    if (P.isZeroSizeArray()) {
      QualType PtrT = P.getType();
      while (auto *AT = dyn_cast<ArrayType>(PtrT))
        PtrT = AT->getElementType();

      QualType ArrayTy = S.getASTContext().getConstantArrayType(
          PtrT, APInt::getZero(1), nullptr, ArraySizeModifier::Normal, 0);
      S.FFDiag(S.Current->getSource(OpPC),
               diag::note_constexpr_pointer_subtraction_zero_size)
          << ArrayTy;

      return false;
    }
  }

  int64_t A64 =
      LHS.isBlockPointer()
          ? (LHS.isElementPastEnd() ? LHS.getNumElems() : LHS.getIndex())
          : LHS.getIntegerRepresentation();

  int64_t B64 =
      RHS.isBlockPointer()
          ? (RHS.isElementPastEnd() ? RHS.getNumElems() : RHS.getIndex())
          : RHS.getIntegerRepresentation();

  int64_t R64 = A64 - B64;
  if (static_cast<int64_t>(T::from(R64)) != R64)
    return handleOverflow(S, OpPC, R64);

  S.Stk.push<T>(T::from(R64));
  return true;
}

//===----------------------------------------------------------------------===//
// Destroy
//===----------------------------------------------------------------------===//

inline bool Destroy(InterpState &S, CodePtr OpPC, uint32_t I) {
  assert(S.Current->getFunction());

  // FIXME: We iterate the scope once here and then again in the destroy() call
  // below.
  for (auto &Local : S.Current->getFunction()->getScope(I).locals_reverse()) {
    const Pointer &Ptr = S.Current->getLocalPointer(Local.Offset);

    if (Ptr.getLifetime() == Lifetime::Ended) {
      // Try to use the declaration for better diagnostics
      if (const Decl *D = Ptr.getDeclDesc()->asDecl()) {
        auto *ND = cast<NamedDecl>(D);
        S.FFDiag(ND->getLocation(),
                 diag::note_constexpr_destroy_out_of_lifetime)
            << ND->getNameAsString();
      } else {
        S.FFDiag(Ptr.getDeclDesc()->getLocation(),
                 diag::note_constexpr_destroy_out_of_lifetime)
            << Ptr.toDiagnosticString(S.getASTContext());
      }
      return false;
    }
  }

  S.Current->destroy(I);
  return true;
}

inline bool InitScope(InterpState &S, CodePtr OpPC, uint32_t I) {
  S.Current->initScope(I);
  return true;
}

//===----------------------------------------------------------------------===//
// Cast, CastFP
//===----------------------------------------------------------------------===//

template <PrimType TIn, PrimType TOut> bool Cast(InterpState &S, CodePtr OpPC) {
  using T = typename PrimConv<TIn>::T;
  using U = typename PrimConv<TOut>::T;
  S.Stk.push<U>(U::from(S.Stk.pop<T>()));
  return true;
}

/// 1) Pops a Floating from the stack.
/// 2) Pushes a new floating on the stack that uses the given semantics.
inline bool CastFP(InterpState &S, CodePtr OpPC, const llvm::fltSemantics *Sem,
                   llvm::RoundingMode RM) {
  Floating F = S.Stk.pop<Floating>();
  Floating Result = S.allocFloat(*Sem);
  F.toSemantics(Sem, RM, &Result);
  S.Stk.push<Floating>(Result);
  return true;
}

inline bool CastFixedPoint(InterpState &S, CodePtr OpPC, uint32_t FPS) {
  FixedPointSemantics TargetSemantics =
      FixedPointSemantics::getFromOpaqueInt(FPS);
  const auto &Source = S.Stk.pop<FixedPoint>();

  bool Overflow;
  FixedPoint Result = Source.toSemantics(TargetSemantics, &Overflow);

  if (Overflow && !handleFixedPointOverflow(S, OpPC, Result))
    return false;

  S.Stk.push<FixedPoint>(Result);
  return true;
}

/// Like Cast(), but we cast to an arbitrary-bitwidth integral, so we need
/// to know what bitwidth the result should be.
template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CastAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
  auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
  // Copy data.
  {
    APInt Source = S.Stk.pop<T>().toAPSInt().extOrTrunc(BitWidth);
    Result.copy(Source);
  }
  S.Stk.push<IntegralAP<false>>(Result);
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CastAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
  auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
  // Copy data.
  {
    APInt Source = S.Stk.pop<T>().toAPSInt().extOrTrunc(BitWidth);
    Result.copy(Source);
  }
  S.Stk.push<IntegralAP<true>>(Result);
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CastIntegralFloating(InterpState &S, CodePtr OpPC,
                          const llvm::fltSemantics *Sem, uint32_t FPOI) {
  const T &From = S.Stk.pop<T>();
  APSInt FromAP = From.toAPSInt();

  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
  Floating Result = S.allocFloat(*Sem);
  auto Status =
      Floating::fromIntegral(FromAP, *Sem, getRoundingMode(FPO), &Result);
  S.Stk.push<Floating>(Result);

  return CheckFloatResult(S, OpPC, Result, Status, FPO);
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CastFloatingIntegral(InterpState &S, CodePtr OpPC, uint32_t FPOI) {
  const Floating &F = S.Stk.pop<Floating>();

  if constexpr (std::is_same_v<T, Boolean>) {
    S.Stk.push<T>(T(F.isNonZero()));
    return true;
  } else {
    APSInt Result(std::max(8u, T::bitWidth()),
                  /*IsUnsigned=*/!T::isSigned());
    auto Status = F.convertToInteger(Result);

    // Float-to-Integral overflow check.
    if ((Status & APFloat::opStatus::opInvalidOp)) {
      const Expr *E = S.Current->getExpr(OpPC);
      QualType Type = E->getType();

      S.CCEDiag(E, diag::note_constexpr_overflow) << F.getAPFloat() << Type;
      if (S.noteUndefinedBehavior()) {
        S.Stk.push<T>(T(Result));
        return true;
      }
      return false;
    }

    FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);
    S.Stk.push<T>(T(Result));
    return CheckFloatResult(S, OpPC, F, Status, FPO);
  }
}

static inline bool CastFloatingIntegralAP(InterpState &S, CodePtr OpPC,
                                          uint32_t BitWidth, uint32_t FPOI) {
  const Floating &F = S.Stk.pop<Floating>();

  APSInt Result(BitWidth, /*IsUnsigned=*/true);
  auto Status = F.convertToInteger(Result);

  // Float-to-Integral overflow check.
  if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite())
    return handleOverflow(S, OpPC, F.getAPFloat());

  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);

  auto ResultAP = S.allocAP<IntegralAP<false>>(BitWidth);
  ResultAP.copy(Result);

  S.Stk.push<IntegralAP<false>>(ResultAP);

  return CheckFloatResult(S, OpPC, F, Status, FPO);
}

static inline bool CastFloatingIntegralAPS(InterpState &S, CodePtr OpPC,
                                           uint32_t BitWidth, uint32_t FPOI) {
  const Floating &F = S.Stk.pop<Floating>();

  APSInt Result(BitWidth, /*IsUnsigned=*/false);
  auto Status = F.convertToInteger(Result);

  // Float-to-Integral overflow check.
  if ((Status & APFloat::opStatus::opInvalidOp) && F.isFinite())
    return handleOverflow(S, OpPC, F.getAPFloat());

  FPOptions FPO = FPOptions::getFromOpaqueInt(FPOI);

  auto ResultAP = S.allocAP<IntegralAP<true>>(BitWidth);
  ResultAP.copy(Result);

  S.Stk.push<IntegralAP<true>>(ResultAP);

  return CheckFloatResult(S, OpPC, F, Status, FPO);
}

bool CheckPointerToIntegralCast(InterpState &S, CodePtr OpPC,
                                const Pointer &Ptr, unsigned BitWidth);
bool CastPointerIntegralAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth);
bool CastPointerIntegralAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth);

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CastPointerIntegral(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();

  S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast)
      << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
      << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);

  if (!CheckPointerToIntegralCast(S, OpPC, Ptr, T::bitWidth()))
    return Invalid(S, OpPC);

  S.Stk.push<T>(T::from(Ptr.getIntegerRepresentation()));
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
static inline bool CastIntegralFixedPoint(InterpState &S, CodePtr OpPC,
                                          uint32_t FPS) {
  const T &Int = S.Stk.pop<T>();

  FixedPointSemantics Sem = FixedPointSemantics::getFromOpaqueInt(FPS);

  bool Overflow;
  FixedPoint Result = FixedPoint::from(Int.toAPSInt(), Sem, &Overflow);

  if (Overflow && !handleFixedPointOverflow(S, OpPC, Result))
    return false;

  S.Stk.push<FixedPoint>(Result);
  return true;
}

static inline bool CastFloatingFixedPoint(InterpState &S, CodePtr OpPC,
                                          uint32_t FPS) {
  const auto &Float = S.Stk.pop<Floating>();

  FixedPointSemantics Sem = FixedPointSemantics::getFromOpaqueInt(FPS);

  bool Overflow;
  FixedPoint Result = FixedPoint::from(Float.getAPFloat(), Sem, &Overflow);

  if (Overflow && !handleFixedPointOverflow(S, OpPC, Result))
    return false;

  S.Stk.push<FixedPoint>(Result);
  return true;
}

static inline bool CastFixedPointFloating(InterpState &S, CodePtr OpPC,
                                          const llvm::fltSemantics *Sem) {
  const auto &Fixed = S.Stk.pop<FixedPoint>();
  Floating Result = S.allocFloat(*Sem);
  Result.copy(Fixed.toFloat(Sem));
  S.Stk.push<Floating>(Result);
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
static inline bool CastFixedPointIntegral(InterpState &S, CodePtr OpPC) {
  const auto &Fixed = S.Stk.pop<FixedPoint>();

  bool Overflow;
  APSInt Int = Fixed.toInt(T::bitWidth(), T::isSigned(), &Overflow);

  if (Overflow && !handleOverflow(S, OpPC, Int))
    return false;

  S.Stk.push<T>(Int);
  return true;
}

static inline bool FnPtrCast(InterpState &S, CodePtr OpPC) {
  const SourceInfo &E = S.Current->getSource(OpPC);
  S.CCEDiag(E, diag::note_constexpr_invalid_cast)
      << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
      << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
  return true;
}

static inline bool PtrPtrCast(InterpState &S, CodePtr OpPC, bool SrcIsVoidPtr) {
  const auto &Ptr = S.Stk.peek<Pointer>();

  if (SrcIsVoidPtr && S.getLangOpts().CPlusPlus) {
    bool HasValidResult = !Ptr.isZero();

    if (HasValidResult) {
      if (S.getStdAllocatorCaller("allocate"))
        return true;

      const auto &E = cast<CastExpr>(S.Current->getExpr(OpPC));
      if (S.getLangOpts().CPlusPlus26 &&
          S.getASTContext().hasSimilarType(Ptr.getType(),
                                           E->getType()->getPointeeType()))
        return true;

      S.CCEDiag(E, diag::note_constexpr_invalid_void_star_cast)
          << E->getSubExpr()->getType() << S.getLangOpts().CPlusPlus26
          << Ptr.getType().getCanonicalType() << E->getType()->getPointeeType();
    } else if (!S.getLangOpts().CPlusPlus26) {
      const SourceInfo &E = S.Current->getSource(OpPC);
      S.CCEDiag(E, diag::note_constexpr_invalid_cast)
          << diag::ConstexprInvalidCastKind::CastFrom << "'void *'"
          << S.Current->getRange(OpPC);
    }
  } else {
    const SourceInfo &E = S.Current->getSource(OpPC);
    S.CCEDiag(E, diag::note_constexpr_invalid_cast)
        << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
        << S.getLangOpts().CPlusPlus << S.Current->getRange(OpPC);
  }

  return true;
}

//===----------------------------------------------------------------------===//
// Zero, Nullptr
//===----------------------------------------------------------------------===//

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool Zero(InterpState &S, CodePtr OpPC) {
  S.Stk.push<T>(T::zero());
  return true;
}

static inline bool ZeroIntAP(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
  auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
  if (!Result.singleWord())
    std::memset(Result.Memory, 0, Result.numWords() * sizeof(uint64_t));
  S.Stk.push<IntegralAP<false>>(Result);
  return true;
}

static inline bool ZeroIntAPS(InterpState &S, CodePtr OpPC, uint32_t BitWidth) {
  auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
  if (!Result.singleWord())
    std::memset(Result.Memory, 0, Result.numWords() * sizeof(uint64_t));
  S.Stk.push<IntegralAP<true>>(Result);
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool Null(InterpState &S, CodePtr OpPC, uint64_t Value,
                 const Descriptor *Desc) {
  // FIXME(perf): This is a somewhat often-used function and the value of a
  // null pointer is almost always 0.
  S.Stk.push<T>(Value, Desc);
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool IsNonNull(InterpState &S, CodePtr OpPC) {
  const auto &P = S.Stk.pop<T>();
  if (P.isWeak())
    return false;
  S.Stk.push<Boolean>(Boolean::from(!P.isZero()));
  return true;
}

//===----------------------------------------------------------------------===//
// This, ImplicitThis
//===----------------------------------------------------------------------===//

inline bool This(InterpState &S, CodePtr OpPC) {
  // Cannot read 'this' in this mode.
  if (S.checkingPotentialConstantExpression()) {
    return false;
  }

  const Pointer &This = S.Current->getThis();
  if (!CheckThis(S, OpPC, This))
    return false;

  // Ensure the This pointer has been cast to the correct base.
  if (!This.isDummy()) {
    assert(isa<CXXMethodDecl>(S.Current->getFunction()->getDecl()));
    if (!This.isTypeidPointer()) {
      [[maybe_unused]] const Record *R = This.getRecord();
      if (!R)
        R = This.narrow().getRecord();
      assert(R);
      assert(R->getDecl() ==
             cast<CXXMethodDecl>(S.Current->getFunction()->getDecl())
                 ->getParent());
    }
  }

  S.Stk.push<Pointer>(This);
  return true;
}

inline bool RVOPtr(InterpState &S, CodePtr OpPC) {
  assert(S.Current->getFunction()->hasRVO());
  if (S.checkingPotentialConstantExpression())
    return false;
  S.Stk.push<Pointer>(S.Current->getRVOPtr());
  return true;
}

//===----------------------------------------------------------------------===//
// Shr, Shl
//===----------------------------------------------------------------------===//

template <class LT, class RT, ShiftDir Dir>
inline bool DoShift(InterpState &S, CodePtr OpPC, LT &LHS, RT &RHS,
                    LT *Result) {
  static_assert(!needsAlloc<LT>());
  const unsigned Bits = LHS.bitWidth();

  // OpenCL 6.3j: shift values are effectively % word size of LHS.
  if (S.getLangOpts().OpenCL)
    RT::bitAnd(RHS, RT::from(LHS.bitWidth() - 1, RHS.bitWidth()),
               RHS.bitWidth(), &RHS);

  if (RHS.isNegative()) {
    // During constant-folding, a negative shift is an opposite shift. Such a
    // shift is not a constant expression.
    const SourceInfo &Loc = S.Current->getSource(OpPC);
    S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS.toAPSInt();
    if (!S.noteUndefinedBehavior())
      return false;
    RHS = -RHS;
    return DoShift<LT, RT,
                   Dir == ShiftDir::Left ? ShiftDir::Right : ShiftDir::Left>(
        S, OpPC, LHS, RHS, Result);
  }

  if (!CheckShift<Dir>(S, OpPC, LHS, RHS, Bits))
    return false;

  // Limit the shift amount to Bits - 1. If this happened,
  // it has already been diagnosed by CheckShift() above,
  // but we still need to handle it.
  // Note that we have to be extra careful here since we're doing the shift in
  // any case, but we need to adjust the shift amount or the way we do the shift
  // for the potential error cases.
  typename LT::AsUnsigned R;
  unsigned MaxShiftAmount = LHS.bitWidth() - 1;
  if constexpr (Dir == ShiftDir::Left) {
    if (Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
        ComparisonCategoryResult::Greater) {
      if (LHS.isNegative())
        R = LT::AsUnsigned::zero(LHS.bitWidth());
      else {
        RHS = RT::from(LHS.countLeadingZeros(), RHS.bitWidth());
        LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
                                  LT::AsUnsigned::from(RHS, Bits), Bits, &R);
      }
    } else if (LHS.isNegative()) {
      if (LHS.isMin()) {
        R = LT::AsUnsigned::zero(LHS.bitWidth());
      } else {
        // If the LHS is negative, perform the cast and invert the result.
        typename LT::AsUnsigned LHSU = LT::AsUnsigned::from(-LHS);
        LT::AsUnsigned::shiftLeft(LHSU, LT::AsUnsigned::from(RHS, Bits), Bits,
                                  &R);
        R = -R;
      }
    } else {
      // The good case, a simple left shift.
      LT::AsUnsigned::shiftLeft(LT::AsUnsigned::from(LHS),
                                LT::AsUnsigned::from(RHS, Bits), Bits, &R);
    }
    S.Stk.push<LT>(LT::from(R));
    return true;
  }

    // Right shift.
    if (Compare(RHS, RT::from(MaxShiftAmount, RHS.bitWidth())) ==
        ComparisonCategoryResult::Greater) {
      R = LT::AsUnsigned::from(-1);
    } else {
      // Do the shift on potentially signed LT, then convert to unsigned type.
      LT A;
      LT::shiftRight(LHS, LT::from(RHS, Bits), Bits, &A);
      R = LT::AsUnsigned::from(A);
    }

  S.Stk.push<LT>(LT::from(R));
  return true;
}

/// A version of DoShift that works on IntegralAP.
template <class LT, class RT, ShiftDir Dir>
inline bool DoShiftAP(InterpState &S, CodePtr OpPC, const APSInt &LHS,
                      APSInt RHS, LT *Result) {
  const unsigned Bits = LHS.getBitWidth();

  // OpenCL 6.3j: shift values are effectively % word size of LHS.
  if (S.getLangOpts().OpenCL)
    RHS &=
        APSInt(llvm::APInt(RHS.getBitWidth(), static_cast<uint64_t>(Bits - 1)),
               RHS.isUnsigned());

  if (RHS.isNegative()) {
    // During constant-folding, a negative shift is an opposite shift. Such a
    // shift is not a constant expression.
    const SourceInfo &Loc = S.Current->getSource(OpPC);
    S.CCEDiag(Loc, diag::note_constexpr_negative_shift) << RHS; //.toAPSInt();
    if (!S.noteUndefinedBehavior())
      return false;
    return DoShiftAP<LT, RT,
                     Dir == ShiftDir::Left ? ShiftDir::Right : ShiftDir::Left>(
        S, OpPC, LHS, -RHS, Result);
  }

  if (!CheckShift<Dir>(S, OpPC, static_cast<LT>(LHS), static_cast<RT>(RHS),
                       Bits))
    return false;

  unsigned SA = (unsigned)RHS.getLimitedValue(Bits - 1);
  if constexpr (Dir == ShiftDir::Left) {
    if constexpr (needsAlloc<LT>())
      Result->copy(LHS << SA);
    else
      *Result = LT(LHS << SA);
  } else {
    if constexpr (needsAlloc<LT>())
      Result->copy(LHS >> SA);
    else
      *Result = LT(LHS >> SA);
  }

  S.Stk.push<LT>(*Result);
  return true;
}

template <PrimType NameL, PrimType NameR>
inline bool Shr(InterpState &S, CodePtr OpPC) {
  using LT = typename PrimConv<NameL>::T;
  using RT = typename PrimConv<NameR>::T;
  auto RHS = S.Stk.pop<RT>();
  auto LHS = S.Stk.pop<LT>();

  if constexpr (needsAlloc<LT>() || needsAlloc<RT>()) {
    LT Result;
    if constexpr (needsAlloc<LT>())
      Result = S.allocAP<LT>(LHS.bitWidth());
    return DoShiftAP<LT, RT, ShiftDir::Right>(S, OpPC, LHS.toAPSInt(),
                                              RHS.toAPSInt(), &Result);
  } else {
    LT Result;
    return DoShift<LT, RT, ShiftDir::Right>(S, OpPC, LHS, RHS, &Result);
  }
}

template <PrimType NameL, PrimType NameR>
inline bool Shl(InterpState &S, CodePtr OpPC) {
  using LT = typename PrimConv<NameL>::T;
  using RT = typename PrimConv<NameR>::T;
  auto RHS = S.Stk.pop<RT>();
  auto LHS = S.Stk.pop<LT>();

  if constexpr (needsAlloc<LT>() || needsAlloc<RT>()) {
    LT Result;
    if constexpr (needsAlloc<LT>())
      Result = S.allocAP<LT>(LHS.bitWidth());
    return DoShiftAP<LT, RT, ShiftDir::Left>(S, OpPC, LHS.toAPSInt(),
                                             RHS.toAPSInt(), &Result);
  } else {
    LT Result;
    return DoShift<LT, RT, ShiftDir::Left>(S, OpPC, LHS, RHS, &Result);
  }
}

static inline bool ShiftFixedPoint(InterpState &S, CodePtr OpPC, bool Left) {
  const auto &RHS = S.Stk.pop<FixedPoint>();
  const auto &LHS = S.Stk.pop<FixedPoint>();
  llvm::FixedPointSemantics LHSSema = LHS.getSemantics();

  unsigned ShiftBitWidth =
      LHSSema.getWidth() - (unsigned)LHSSema.hasUnsignedPadding() - 1;

  // Embedded-C 4.1.6.2.2:
  //   The right operand must be nonnegative and less than the total number
  //   of (nonpadding) bits of the fixed-point operand ...
  if (RHS.isNegative()) {
    S.CCEDiag(S.Current->getLocation(OpPC), diag::note_constexpr_negative_shift)
        << RHS.toAPSInt();
  } else if (static_cast<unsigned>(RHS.toAPSInt().getLimitedValue(
                 ShiftBitWidth)) != RHS.toAPSInt()) {
    const Expr *E = S.Current->getExpr(OpPC);
    S.CCEDiag(E, diag::note_constexpr_large_shift)
        << RHS.toAPSInt() << E->getType() << ShiftBitWidth;
  }

  FixedPoint Result;
  if (Left) {
    if (FixedPoint::shiftLeft(LHS, RHS, ShiftBitWidth, &Result) &&
        !handleFixedPointOverflow(S, OpPC, Result))
      return false;
  } else {
    if (FixedPoint::shiftRight(LHS, RHS, ShiftBitWidth, &Result) &&
        !handleFixedPointOverflow(S, OpPC, Result))
      return false;
  }

  S.Stk.push<FixedPoint>(Result);
  return true;
}

//===----------------------------------------------------------------------===//
// NoRet
//===----------------------------------------------------------------------===//

inline bool NoRet(InterpState &S, CodePtr OpPC) {
  SourceLocation EndLoc = S.Current->getCallee()->getEndLoc();
  S.FFDiag(EndLoc, diag::note_constexpr_no_return);
  return false;
}

//===----------------------------------------------------------------------===//
// NarrowPtr, ExpandPtr
//===----------------------------------------------------------------------===//

inline bool NarrowPtr(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  S.Stk.push<Pointer>(Ptr.narrow());
  return true;
}

inline bool ExpandPtr(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();
  if (Ptr.isBlockPointer())
    S.Stk.push<Pointer>(Ptr.expand());
  else
    S.Stk.push<Pointer>(Ptr);
  return true;
}

// 1) Pops an integral value from the stack
// 2) Peeks a pointer
// 3) Pushes a new pointer that's a narrowed array
//   element of the peeked pointer with the value
//   from 1) added as offset.
//
// This leaves the original pointer on the stack and pushes a new one
// with the offset applied and narrowed.
template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool ArrayElemPtr(InterpState &S, CodePtr OpPC) {
  const T &Offset = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.peek<Pointer>();

  if (!Ptr.isZero() && !Offset.isZero()) {
    if (!CheckArray(S, OpPC, Ptr))
      return false;
  }

  if (Offset.isZero()) {
    if (Ptr.getFieldDesc()->isArray() && Ptr.getIndex() == 0) {
      S.Stk.push<Pointer>(Ptr.atIndex(0).narrow());
      return true;
    }
    S.Stk.push<Pointer>(Ptr);
    return true;
  }

  assert(!Offset.isZero());

  if (std::optional<Pointer> Result =
          OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr)) {
    S.Stk.push<Pointer>(Result->narrow());
    return true;
  }

  return false;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool ArrayElemPtrPop(InterpState &S, CodePtr OpPC) {
  const T &Offset = S.Stk.pop<T>();
  const Pointer &Ptr = S.Stk.pop<Pointer>();

  if (!Ptr.isZero() && !Offset.isZero()) {
    if (!CheckArray(S, OpPC, Ptr))
      return false;
  }

  if (Offset.isZero()) {
    if (Ptr.getFieldDesc()->isArray() && Ptr.getIndex() == 0) {
      S.Stk.push<Pointer>(Ptr.atIndex(0).narrow());
      return true;
    }
    S.Stk.push<Pointer>(Ptr);
    return true;
  }

  assert(!Offset.isZero());

  if (std::optional<Pointer> Result =
          OffsetHelper<T, ArithOp::Add>(S, OpPC, Offset, Ptr)) {
    S.Stk.push<Pointer>(Result->narrow());
    return true;
  }
  return false;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool ArrayElem(InterpState &S, CodePtr OpPC, uint32_t Index) {
  const Pointer &Ptr = S.Stk.peek<Pointer>();

  if (!CheckLoad(S, OpPC, Ptr))
    return false;

  assert(Ptr.atIndex(Index).getFieldDesc()->getPrimType() == Name);
  S.Stk.push<T>(Ptr.elem<T>(Index));
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool ArrayElemPop(InterpState &S, CodePtr OpPC, uint32_t Index) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();

  if (!CheckLoad(S, OpPC, Ptr))
    return false;

  assert(Ptr.atIndex(Index).getFieldDesc()->getPrimType() == Name);
  S.Stk.push<T>(Ptr.elem<T>(Index));
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool CopyArray(InterpState &S, CodePtr OpPC, uint32_t SrcIndex,
                      uint32_t DestIndex, uint32_t Size) {
  const auto &SrcPtr = S.Stk.pop<Pointer>();
  const auto &DestPtr = S.Stk.peek<Pointer>();

  if (SrcPtr.isDummy() || DestPtr.isDummy())
    return false;

  for (uint32_t I = 0; I != Size; ++I) {
    const Pointer &SP = SrcPtr.atIndex(SrcIndex + I);

    if (!CheckLoad(S, OpPC, SP))
      return false;

    const Pointer &DP = DestPtr.atIndex(DestIndex + I);
    DP.deref<T>() = SP.deref<T>();
    DP.initialize();
  }
  return true;
}

/// Just takes a pointer and checks if it's an incomplete
/// array type.
inline bool ArrayDecay(InterpState &S, CodePtr OpPC) {
  const Pointer &Ptr = S.Stk.pop<Pointer>();

  if (Ptr.isZero()) {
    S.Stk.push<Pointer>(Ptr);
    return true;
  }

  if (!Ptr.isZeroSizeArray()) {
    if (!CheckRange(S, OpPC, Ptr, CSK_ArrayToPointer))
      return false;
  }

  if (Ptr.isRoot() || !Ptr.isUnknownSizeArray()) {
    S.Stk.push<Pointer>(Ptr.atIndex(0));
    return true;
  }

  const SourceInfo &E = S.Current->getSource(OpPC);
  S.FFDiag(E, diag::note_constexpr_unsupported_unsized_array);

  return false;
}

inline bool GetFnPtr(InterpState &S, CodePtr OpPC, const Function *Func) {
  assert(Func);
  S.Stk.push<Pointer>(Func);
  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool GetIntPtr(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
  const T &IntVal = S.Stk.pop<T>();

  S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast)
      << diag::ConstexprInvalidCastKind::ThisConversionOrReinterpret
      << S.getLangOpts().CPlusPlus;

  S.Stk.push<Pointer>(static_cast<uint64_t>(IntVal), Desc);
  return true;
}

inline bool GetMemberPtr(InterpState &S, CodePtr OpPC, const ValueDecl *D) {
  S.Stk.push<MemberPointer>(D);
  return true;
}

inline bool GetMemberPtrBase(InterpState &S, CodePtr OpPC) {
  const auto &MP = S.Stk.pop<MemberPointer>();

  if (!MP.isBaseCastPossible())
    return false;

  S.Stk.push<Pointer>(MP.getBase());
  return true;
}

inline bool GetMemberPtrDecl(InterpState &S, CodePtr OpPC) {
  const auto &MP = S.Stk.pop<MemberPointer>();

  const auto *FD = cast<FunctionDecl>(MP.getDecl());
  const auto *Func = S.getContext().getOrCreateFunction(FD);

  S.Stk.push<Pointer>(Func);
  return true;
}

/// Just emit a diagnostic. The expression that caused emission of this
/// op is not valid in a constant context.
inline bool Invalid(InterpState &S, CodePtr OpPC) {
  const SourceLocation &Loc = S.Current->getLocation(OpPC);
  S.FFDiag(Loc, diag::note_invalid_subexpr_in_const_expr)
      << S.Current->getRange(OpPC);
  return false;
}

inline bool Unsupported(InterpState &S, CodePtr OpPC) {
  const SourceLocation &Loc = S.Current->getLocation(OpPC);
  S.FFDiag(Loc, diag::note_constexpr_stmt_expr_unsupported)
      << S.Current->getRange(OpPC);
  return false;
}

inline bool StartSpeculation(InterpState &S, CodePtr OpPC) {
  ++S.SpeculationDepth;
  if (S.SpeculationDepth != 1)
    return true;

  assert(S.PrevDiags == nullptr);
  S.PrevDiags = S.getEvalStatus().Diag;
  S.getEvalStatus().Diag = nullptr;
  return true;
}
inline bool EndSpeculation(InterpState &S, CodePtr OpPC) {
  assert(S.SpeculationDepth != 0);
  --S.SpeculationDepth;
  if (S.SpeculationDepth == 0) {
    S.getEvalStatus().Diag = S.PrevDiags;
    S.PrevDiags = nullptr;
  }
  return true;
}

inline bool PushCC(InterpState &S, CodePtr OpPC, bool Value) {
  S.ConstantContextOverride = Value;
  return true;
}
inline bool PopCC(InterpState &S, CodePtr OpPC) {
  S.ConstantContextOverride = std::nullopt;
  return true;
}

/// Do nothing and just abort execution.
inline bool Error(InterpState &S, CodePtr OpPC) { return false; }

inline bool SideEffect(InterpState &S, CodePtr OpPC) {
  return S.noteSideEffect();
}

/// Same here, but only for casts.
inline bool InvalidCast(InterpState &S, CodePtr OpPC, CastKind Kind,
                        bool Fatal) {
  const SourceLocation &Loc = S.Current->getLocation(OpPC);

  if (Kind == CastKind::Reinterpret) {
    S.CCEDiag(Loc, diag::note_constexpr_invalid_cast)
        << static_cast<unsigned>(Kind) << S.Current->getRange(OpPC);
    return !Fatal;
  }
  if (Kind == CastKind::Volatile) {
    if (!S.checkingPotentialConstantExpression()) {
      const auto *E = cast<CastExpr>(S.Current->getExpr(OpPC));
      if (S.getLangOpts().CPlusPlus)
        S.FFDiag(E, diag::note_constexpr_access_volatile_type)
            << AK_Read << E->getSubExpr()->getType();
      else
        S.FFDiag(E);
    }

    return false;
  }
  if (Kind == CastKind::Dynamic) {
    assert(!S.getLangOpts().CPlusPlus20);
    S.CCEDiag(S.Current->getSource(OpPC), diag::note_constexpr_invalid_cast)
        << diag::ConstexprInvalidCastKind::Dynamic;
    return true;
  }

  return false;
}

inline bool InvalidDeclRef(InterpState &S, CodePtr OpPC, const DeclRefExpr *DR,
                           bool InitializerFailed) {
  assert(DR);

  if (InitializerFailed) {
    const SourceInfo &Loc = S.Current->getSource(OpPC);
    const auto *VD = cast<VarDecl>(DR->getDecl());
    S.FFDiag(Loc, diag::note_constexpr_var_init_non_constant, 1) << VD;
    S.Note(VD->getLocation(), diag::note_declared_at);
    return false;
  }

  return CheckDeclRef(S, OpPC, DR);
}

inline bool SizelessVectorElementSize(InterpState &S, CodePtr OpPC) {
  if (S.inConstantContext()) {
    const SourceRange &ArgRange = S.Current->getRange(OpPC);
    const Expr *E = S.Current->getExpr(OpPC);
    S.CCEDiag(E, diag::note_constexpr_non_const_vectorelements) << ArgRange;
  }
  return false;
}

inline bool CheckPseudoDtor(InterpState &S, CodePtr OpPC) {
  if (!S.getLangOpts().CPlusPlus20)
    S.CCEDiag(S.Current->getSource(OpPC),
              diag::note_constexpr_pseudo_destructor);
  return true;
}

inline bool Assume(InterpState &S, CodePtr OpPC) {
  const auto Val = S.Stk.pop<Boolean>();

  if (Val)
    return true;

  // Else, diagnose.
  const SourceLocation &Loc = S.Current->getLocation(OpPC);
  S.CCEDiag(Loc, diag::note_constexpr_assumption_failed);
  return false;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool OffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E) {
  llvm::SmallVector<int64_t> ArrayIndices;
  for (size_t I = 0; I != E->getNumExpressions(); ++I)
    ArrayIndices.emplace_back(S.Stk.pop<int64_t>());

  int64_t Result;
  if (!InterpretOffsetOf(S, OpPC, E, ArrayIndices, Result))
    return false;

  S.Stk.push<T>(T::from(Result));

  return true;
}

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool CheckNonNullArg(InterpState &S, CodePtr OpPC) {
  const T &Arg = S.Stk.peek<T>();
  if (!Arg.isZero())
    return true;

  const SourceLocation &Loc = S.Current->getLocation(OpPC);
  S.CCEDiag(Loc, diag::note_non_null_attribute_failed);

  return false;
}

void diagnoseEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED,
                       const APSInt &Value);

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool CheckEnumValue(InterpState &S, CodePtr OpPC, const EnumDecl *ED) {
  assert(ED);
  assert(!ED->isFixed());

  if (S.inConstantContext()) {
    const APSInt Val = S.Stk.peek<T>().toAPSInt();
    diagnoseEnumValue(S, OpPC, ED, Val);
  }
  return true;
}

/// OldPtr -> Integer -> NewPtr.
template <PrimType TIn, PrimType TOut>
inline bool DecayPtr(InterpState &S, CodePtr OpPC) {
  static_assert(isPtrType(TIn) && isPtrType(TOut));
  using FromT = typename PrimConv<TIn>::T;
  using ToT = typename PrimConv<TOut>::T;

  const FromT &OldPtr = S.Stk.pop<FromT>();

  if constexpr (std::is_same_v<FromT, FunctionPointer> &&
                std::is_same_v<ToT, Pointer>) {
    S.Stk.push<Pointer>(OldPtr.getFunction(), OldPtr.getOffset());
    return true;
  } else if constexpr (std::is_same_v<FromT, Pointer> &&
                       std::is_same_v<ToT, FunctionPointer>) {
    if (OldPtr.isFunctionPointer()) {
      S.Stk.push<FunctionPointer>(OldPtr.asFunctionPointer().getFunction(),
                                  OldPtr.getByteOffset());
      return true;
    }
  }

  S.Stk.push<ToT>(ToT(OldPtr.getIntegerRepresentation(), nullptr));
  return true;
}

inline bool CheckDecl(InterpState &S, CodePtr OpPC, const VarDecl *VD) {
  // An expression E is a core constant expression unless the evaluation of E
  // would evaluate one of the following: [C++23] - a control flow that passes
  // through a declaration of a variable with static or thread storage duration
  // unless that variable is usable in constant expressions.
  assert(VD->isLocalVarDecl() &&
         VD->isStaticLocal()); // Checked before emitting this.

  if (VD == S.EvaluatingDecl)
    return true;

  if (!VD->isUsableInConstantExpressions(S.getASTContext())) {
    S.CCEDiag(VD->getLocation(), diag::note_constexpr_static_local)
        << (VD->getTSCSpec() == TSCS_unspecified ? 0 : 1) << VD;
    return false;
  }
  return true;
}

inline bool Alloc(InterpState &S, CodePtr OpPC, const Descriptor *Desc) {
  assert(Desc);

  if (!CheckDynamicMemoryAllocation(S, OpPC))
    return false;

  DynamicAllocator &Allocator = S.getAllocator();
  Block *B = Allocator.allocate(Desc, S.Ctx.getEvalID(),
                                DynamicAllocator::Form::NonArray);
  assert(B);
  S.Stk.push<Pointer>(B);
  return true;
}

template <PrimType Name, class SizeT = typename PrimConv<Name>::T>
inline bool AllocN(InterpState &S, CodePtr OpPC, PrimType T, const Expr *Source,
                   bool IsNoThrow) {
  if (!CheckDynamicMemoryAllocation(S, OpPC))
    return false;

  SizeT NumElements = S.Stk.pop<SizeT>();
  if (!CheckArraySize(S, OpPC, &NumElements, primSize(T), IsNoThrow)) {
    if (!IsNoThrow)
      return false;

    // If this failed and is nothrow, just return a null ptr.
    S.Stk.push<Pointer>(0, nullptr);
    return true;
  }
  if (NumElements.isNegative()) {
    if (!IsNoThrow) {
      S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_new_negative)
          << NumElements.toDiagnosticString(S.getASTContext());
      return false;
    }
    S.Stk.push<Pointer>(0, nullptr);
    return true;
  }

  if (!CheckArraySize(S, OpPC, static_cast<uint64_t>(NumElements)))
    return false;

  DynamicAllocator &Allocator = S.getAllocator();
  Block *B =
      Allocator.allocate(Source, T, static_cast<size_t>(NumElements),
                         S.Ctx.getEvalID(), DynamicAllocator::Form::Array);
  assert(B);
  if (NumElements.isZero())
    S.Stk.push<Pointer>(B);
  else
    S.Stk.push<Pointer>(Pointer(B).atIndex(0));
  return true;
}

template <PrimType Name, class SizeT = typename PrimConv<Name>::T>
inline bool AllocCN(InterpState &S, CodePtr OpPC, const Descriptor *ElementDesc,
                    bool IsNoThrow) {
  if (!CheckDynamicMemoryAllocation(S, OpPC))
    return false;

  SizeT NumElements = S.Stk.pop<SizeT>();
  if (!CheckArraySize(S, OpPC, &NumElements, ElementDesc->getSize(),
                      IsNoThrow)) {
    if (!IsNoThrow)
      return false;

    // If this failed and is nothrow, just return a null ptr.
    S.Stk.push<Pointer>(0, ElementDesc);
    return true;
  }
  assert(NumElements.isPositive());

  if (!CheckArraySize(S, OpPC, static_cast<uint64_t>(NumElements)))
    return false;

  DynamicAllocator &Allocator = S.getAllocator();
  Block *B =
      Allocator.allocate(ElementDesc, static_cast<size_t>(NumElements),
                         S.Ctx.getEvalID(), DynamicAllocator::Form::Array);
  assert(B);
  if (NumElements.isZero())
    S.Stk.push<Pointer>(B);
  else
    S.Stk.push<Pointer>(Pointer(B).atIndex(0));

  return true;
}

bool Free(InterpState &S, CodePtr OpPC, bool DeleteIsArrayForm,
          bool IsGlobalDelete);

static inline bool IsConstantContext(InterpState &S, CodePtr OpPC) {
  S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
  return true;
}

static inline bool CheckAllocations(InterpState &S, CodePtr OpPC) {
  return S.maybeDiagnoseDanglingAllocations();
}

/// Check if the initializer and storage types of a placement-new expression
/// match.
bool CheckNewTypeMismatch(InterpState &S, CodePtr OpPC, const Expr *E,
                          std::optional<uint64_t> ArraySize = std::nullopt);

template <PrimType Name, class T = typename PrimConv<Name>::T>
bool CheckNewTypeMismatchArray(InterpState &S, CodePtr OpPC, const Expr *E) {
  const auto &Size = S.Stk.pop<T>();
  return CheckNewTypeMismatch(S, OpPC, E, static_cast<uint64_t>(Size));
}
bool InvalidNewDeleteExpr(InterpState &S, CodePtr OpPC, const Expr *E);

template <PrimType Name, class T = typename PrimConv<Name>::T>
inline bool BitCastPrim(InterpState &S, CodePtr OpPC, bool TargetIsUCharOrByte,
                        uint32_t ResultBitWidth,
                        const llvm::fltSemantics *Sem) {
  const Pointer &FromPtr = S.Stk.pop<Pointer>();

  if (!CheckLoad(S, OpPC, FromPtr))
    return false;

  if constexpr (std::is_same_v<T, Pointer>) {
    // The only pointer type we can validly bitcast to is nullptr_t.
    S.Stk.push<Pointer>();
    return true;
  } else {

    size_t BuffSize = ResultBitWidth / 8;
    llvm::SmallVector<std::byte> Buff(BuffSize);
    bool HasIndeterminateBits = false;

    Bits FullBitWidth(ResultBitWidth);
    Bits BitWidth = FullBitWidth;

    if constexpr (std::is_same_v<T, Floating>) {
      assert(Sem);
      BitWidth = Bits(llvm::APFloatBase::getSizeInBits(*Sem));
    }

    if (!DoBitCast(S, OpPC, FromPtr, Buff.data(), BitWidth, FullBitWidth,
                   HasIndeterminateBits))
      return false;

    if (!CheckBitCast(S, OpPC, HasIndeterminateBits, TargetIsUCharOrByte))
      return false;

    if constexpr (std::is_same_v<T, Floating>) {
      assert(Sem);
      Floating Result = S.allocFloat(*Sem);
      Floating::bitcastFromMemory(Buff.data(), *Sem, &Result);
      S.Stk.push<Floating>(Result);
    } else if constexpr (needsAlloc<T>()) {
      T Result = S.allocAP<T>(ResultBitWidth);
      T::bitcastFromMemory(Buff.data(), ResultBitWidth, &Result);
      S.Stk.push<T>(Result);
    } else if constexpr (std::is_same_v<T, Boolean>) {
      // Only allow to cast single-byte integers to bool if they are either 0
      // or 1.
      assert(FullBitWidth.getQuantity() == 8);
      auto Val = static_cast<unsigned int>(Buff[0]);
      if (Val > 1) {
        S.FFDiag(S.Current->getSource(OpPC),
                 diag::note_constexpr_bit_cast_unrepresentable_value)
            << S.getASTContext().BoolTy << Val;
        return false;
      }
      S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
    } else {
      assert(!Sem);
      S.Stk.push<T>(T::bitcastFromMemory(Buff.data(), ResultBitWidth));
    }
    return true;
  }
}

inline bool BitCast(InterpState &S, CodePtr OpPC) {
  const Pointer &FromPtr = S.Stk.pop<Pointer>();
  Pointer &ToPtr = S.Stk.peek<Pointer>();

  if (!CheckLoad(S, OpPC, FromPtr))
    return false;

  if (!DoBitCastPtr(S, OpPC, FromPtr, ToPtr))
    return false;

  return true;
}

/// Typeid support.
bool GetTypeid(InterpState &S, CodePtr OpPC, const Type *TypePtr,
               const Type *TypeInfoType);
bool GetTypeidPtr(InterpState &S, CodePtr OpPC, const Type *TypeInfoType);
bool DiagTypeid(InterpState &S, CodePtr OpPC);

inline bool CheckDestruction(InterpState &S, CodePtr OpPC) {
  const auto &Ptr = S.Stk.peek<Pointer>();
  return CheckDestructor(S, OpPC, Ptr);
}

inline bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems) {
  uint64_t Limit = S.getLangOpts().ConstexprStepLimit;
  if (NumElems > Limit) {
    S.FFDiag(S.Current->getSource(OpPC),
             diag::note_constexpr_new_exceeds_limits)
        << NumElems << Limit;
    return false;
  }
  return true;
}

//===----------------------------------------------------------------------===//
// Read opcode arguments
//===----------------------------------------------------------------------===//

template <typename T> inline T ReadArg(InterpState &S, CodePtr &OpPC) {
  if constexpr (std::is_pointer<T>::value) {
    uint32_t ID = OpPC.read<uint32_t>();
    return reinterpret_cast<T>(S.P.getNativePointer(ID));
  } else {
    return OpPC.read<T>();
  }
}

template <> inline Floating ReadArg<Floating>(InterpState &S, CodePtr &OpPC) {
  auto &Semantics =
      llvm::APFloatBase::EnumToSemantics(Floating::deserializeSemantics(*OpPC));

  auto F = S.allocFloat(Semantics);
  Floating::deserialize(*OpPC, &F);
  OpPC += align(F.bytesToSerialize());
  return F;
}

template <>
inline IntegralAP<false> ReadArg<IntegralAP<false>>(InterpState &S,
                                                    CodePtr &OpPC) {
  uint32_t BitWidth = IntegralAP<false>::deserializeSize(*OpPC);
  auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
  assert(Result.bitWidth() == BitWidth);

  IntegralAP<false>::deserialize(*OpPC, &Result);
  OpPC += align(Result.bytesToSerialize());
  return Result;
}

template <>
inline IntegralAP<true> ReadArg<IntegralAP<true>>(InterpState &S,
                                                  CodePtr &OpPC) {
  uint32_t BitWidth = IntegralAP<true>::deserializeSize(*OpPC);
  auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
  assert(Result.bitWidth() == BitWidth);

  IntegralAP<true>::deserialize(*OpPC, &Result);
  OpPC += align(Result.bytesToSerialize());
  return Result;
}

template <>
inline FixedPoint ReadArg<FixedPoint>(InterpState &S, CodePtr &OpPC) {
  FixedPoint FP = FixedPoint::deserialize(*OpPC);
  OpPC += align(FP.bytesToSerialize());
  return FP;
}

} // namespace interp
} // namespace clang

#endif
