brintos

brintos / llvm-project-archived public Read only

0
0
Text · 198.2 KiB · 61043f2 Raw
5534 lines · cpp
1//===--- InterpBuiltin.cpp - Interpreter for the constexpr VM ---*- C++ -*-===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8#include "../ExprConstShared.h"9#include "Boolean.h"10#include "EvalEmitter.h"11#include "InterpBuiltinBitCast.h"12#include "InterpHelpers.h"13#include "PrimType.h"14#include "Program.h"15#include "clang/AST/InferAlloc.h"16#include "clang/AST/OSLog.h"17#include "clang/AST/RecordLayout.h"18#include "clang/Basic/Builtins.h"19#include "clang/Basic/TargetBuiltins.h"20#include "clang/Basic/TargetInfo.h"21#include "llvm/ADT/StringExtras.h"22#include "llvm/Support/AllocToken.h"23#include "llvm/Support/ErrorHandling.h"24#include "llvm/Support/SipHash.h"25 26namespace clang {27namespace interp {28 29[[maybe_unused]] static bool isNoopBuiltin(unsigned ID) {30  switch (ID) {31  case Builtin::BIas_const:32  case Builtin::BIforward:33  case Builtin::BIforward_like:34  case Builtin::BImove:35  case Builtin::BImove_if_noexcept:36  case Builtin::BIaddressof:37  case Builtin::BI__addressof:38  case Builtin::BI__builtin_addressof:39  case Builtin::BI__builtin_launder:40    return true;41  default:42    return false;43  }44  return false;45}46 47static void discard(InterpStack &Stk, PrimType T) {48  TYPE_SWITCH(T, { Stk.discard<T>(); });49}50 51static APSInt popToAPSInt(InterpStack &Stk, PrimType T) {52  INT_TYPE_SWITCH(T, return Stk.pop<T>().toAPSInt());53}54 55static APSInt popToAPSInt(InterpState &S, const Expr *E) {56  return popToAPSInt(S.Stk, *S.getContext().classify(E->getType()));57}58static APSInt popToAPSInt(InterpState &S, QualType T) {59  return popToAPSInt(S.Stk, *S.getContext().classify(T));60}61 62/// Pushes \p Val on the stack as the type given by \p QT.63static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {64  assert(QT->isSignedIntegerOrEnumerationType() ||65         QT->isUnsignedIntegerOrEnumerationType());66  OptPrimType T = S.getContext().classify(QT);67  assert(T);68 69  unsigned BitWidth = S.getASTContext().getTypeSize(QT);70 71  if (T == PT_IntAPS) {72    auto Result = S.allocAP<IntegralAP<true>>(BitWidth);73    Result.copy(Val);74    S.Stk.push<IntegralAP<true>>(Result);75    return;76  }77 78  if (T == PT_IntAP) {79    auto Result = S.allocAP<IntegralAP<false>>(BitWidth);80    Result.copy(Val);81    S.Stk.push<IntegralAP<false>>(Result);82    return;83  }84 85  if (QT->isSignedIntegerOrEnumerationType()) {86    int64_t V = Val.getSExtValue();87    INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });88  } else {89    assert(QT->isUnsignedIntegerOrEnumerationType());90    uint64_t V = Val.getZExtValue();91    INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });92  }93}94 95template <typename T>96static void pushInteger(InterpState &S, T Val, QualType QT) {97  if constexpr (std::is_same_v<T, APInt>)98    pushInteger(S, APSInt(Val, !std::is_signed_v<T>), QT);99  else if constexpr (std::is_same_v<T, APSInt>)100    pushInteger(S, Val, QT);101  else102    pushInteger(S,103                APSInt(APInt(sizeof(T) * 8, static_cast<uint64_t>(Val),104                             std::is_signed_v<T>),105                       !std::is_signed_v<T>),106                QT);107}108 109static void assignInteger(InterpState &S, const Pointer &Dest, PrimType ValueT,110                          const APSInt &Value) {111 112  if (ValueT == PT_IntAPS) {113    Dest.deref<IntegralAP<true>>() =114        S.allocAP<IntegralAP<true>>(Value.getBitWidth());115    Dest.deref<IntegralAP<true>>().copy(Value);116  } else if (ValueT == PT_IntAP) {117    Dest.deref<IntegralAP<false>>() =118        S.allocAP<IntegralAP<false>>(Value.getBitWidth());119    Dest.deref<IntegralAP<false>>().copy(Value);120  } else {121    INT_TYPE_SWITCH_NO_BOOL(122        ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); });123  }124}125 126static QualType getElemType(const Pointer &P) {127  const Descriptor *Desc = P.getFieldDesc();128  QualType T = Desc->getType();129  if (Desc->isPrimitive())130    return T;131  if (T->isPointerType())132    return T->getAs<PointerType>()->getPointeeType();133  if (Desc->isArray())134    return Desc->getElemQualType();135  if (const auto *AT = T->getAsArrayTypeUnsafe())136    return AT->getElementType();137  return T;138}139 140static void diagnoseNonConstexprBuiltin(InterpState &S, CodePtr OpPC,141                                        unsigned ID) {142  if (!S.diagnosing())143    return;144 145  auto Loc = S.Current->getSource(OpPC);146  if (S.getLangOpts().CPlusPlus11)147    S.CCEDiag(Loc, diag::note_constexpr_invalid_function)148        << /*isConstexpr=*/0 << /*isConstructor=*/0149        << S.getASTContext().BuiltinInfo.getQuotedName(ID);150  else151    S.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr);152}153 154static llvm::APSInt convertBoolVectorToInt(const Pointer &Val) {155  assert(Val.getFieldDesc()->isPrimitiveArray() &&156         Val.getFieldDesc()->getElemQualType()->isBooleanType() &&157         "Not a boolean vector");158  unsigned NumElems = Val.getNumElems();159 160  // Each element is one bit, so create an integer with NumElts bits.161  llvm::APSInt Result(NumElems, 0);162  for (unsigned I = 0; I != NumElems; ++I) {163    if (Val.elem<bool>(I))164      Result.setBit(I);165  }166 167  return Result;168}169 170static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC,171                                                  const InterpFrame *Frame,172                                                  const CallExpr *Call) {173  unsigned Depth = S.Current->getDepth();174  auto isStdCall = [](const FunctionDecl *F) -> bool {175    return F && F->isInStdNamespace() && F->getIdentifier() &&176           F->getIdentifier()->isStr("is_constant_evaluated");177  };178  const InterpFrame *Caller = Frame->Caller;179  // The current frame is the one for __builtin_is_constant_evaluated.180  // The one above that, potentially the one for std::is_constant_evaluated().181  if (S.inConstantContext() && !S.checkingPotentialConstantExpression() &&182      S.getEvalStatus().Diag &&183      (Depth == 0 || (Depth == 1 && isStdCall(Frame->getCallee())))) {184    if (Caller && isStdCall(Frame->getCallee())) {185      const Expr *E = Caller->getExpr(Caller->getRetPC());186      S.report(E->getExprLoc(),187               diag::warn_is_constant_evaluated_always_true_constexpr)188          << "std::is_constant_evaluated" << E->getSourceRange();189    } else {190      S.report(Call->getExprLoc(),191               diag::warn_is_constant_evaluated_always_true_constexpr)192          << "__builtin_is_constant_evaluated" << Call->getSourceRange();193    }194  }195 196  S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));197  return true;198}199 200// __builtin_assume(int)201static bool interp__builtin_assume(InterpState &S, CodePtr OpPC,202                                   const InterpFrame *Frame,203                                   const CallExpr *Call) {204  assert(Call->getNumArgs() == 1);205  discard(S.Stk, *S.getContext().classify(Call->getArg(0)));206  return true;207}208 209static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,210                                   const InterpFrame *Frame,211                                   const CallExpr *Call, unsigned ID) {212  uint64_t Limit = ~static_cast<uint64_t>(0);213  if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp ||214      ID == Builtin::BIwcsncmp || ID == Builtin::BI__builtin_wcsncmp)215    Limit = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)))216                .getZExtValue();217 218  const Pointer &B = S.Stk.pop<Pointer>();219  const Pointer &A = S.Stk.pop<Pointer>();220  if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp ||221      ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp)222    diagnoseNonConstexprBuiltin(S, OpPC, ID);223 224  if (Limit == 0) {225    pushInteger(S, 0, Call->getType());226    return true;227  }228 229  if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))230    return false;231 232  if (A.isDummy() || B.isDummy())233    return false;234  if (!A.isBlockPointer() || !B.isBlockPointer())235    return false;236 237  bool IsWide = ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp ||238                ID == Builtin::BI__builtin_wcscmp ||239                ID == Builtin::BI__builtin_wcsncmp;240  assert(A.getFieldDesc()->isPrimitiveArray());241  assert(B.getFieldDesc()->isPrimitiveArray());242 243  // Different element types shouldn't happen, but with casts they can.244  if (!S.getASTContext().hasSameUnqualifiedType(getElemType(A), getElemType(B)))245    return false;246 247  PrimType ElemT = *S.getContext().classify(getElemType(A));248 249  auto returnResult = [&](int V) -> bool {250    pushInteger(S, V, Call->getType());251    return true;252  };253 254  unsigned IndexA = A.getIndex();255  unsigned IndexB = B.getIndex();256  uint64_t Steps = 0;257  for (;; ++IndexA, ++IndexB, ++Steps) {258 259    if (Steps >= Limit)260      break;261    const Pointer &PA = A.atIndex(IndexA);262    const Pointer &PB = B.atIndex(IndexB);263    if (!CheckRange(S, OpPC, PA, AK_Read) ||264        !CheckRange(S, OpPC, PB, AK_Read)) {265      return false;266    }267 268    if (IsWide) {269      INT_TYPE_SWITCH(ElemT, {270        T CA = PA.deref<T>();271        T CB = PB.deref<T>();272        if (CA > CB)273          return returnResult(1);274        if (CA < CB)275          return returnResult(-1);276        if (CA.isZero() || CB.isZero())277          return returnResult(0);278      });279      continue;280    }281 282    uint8_t CA = PA.deref<uint8_t>();283    uint8_t CB = PB.deref<uint8_t>();284 285    if (CA > CB)286      return returnResult(1);287    if (CA < CB)288      return returnResult(-1);289    if (CA == 0 || CB == 0)290      return returnResult(0);291  }292 293  return returnResult(0);294}295 296static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,297                                   const InterpFrame *Frame,298                                   const CallExpr *Call, unsigned ID) {299  const Pointer &StrPtr = S.Stk.pop<Pointer>().expand();300 301  if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen)302    diagnoseNonConstexprBuiltin(S, OpPC, ID);303 304  if (!CheckArray(S, OpPC, StrPtr))305    return false;306 307  if (!CheckLive(S, OpPC, StrPtr, AK_Read))308    return false;309 310  if (!CheckDummy(S, OpPC, StrPtr.block(), AK_Read))311    return false;312 313  if (!StrPtr.getFieldDesc()->isPrimitiveArray())314    return false;315 316  assert(StrPtr.getFieldDesc()->isPrimitiveArray());317  unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize();318 319  if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) {320    [[maybe_unused]] const ASTContext &AC = S.getASTContext();321    assert(ElemSize == AC.getTypeSizeInChars(AC.getWCharType()).getQuantity());322  }323 324  size_t Len = 0;325  for (size_t I = StrPtr.getIndex();; ++I, ++Len) {326    const Pointer &ElemPtr = StrPtr.atIndex(I);327 328    if (!CheckRange(S, OpPC, ElemPtr, AK_Read))329      return false;330 331    uint32_t Val;332    switch (ElemSize) {333    case 1:334      Val = ElemPtr.deref<uint8_t>();335      break;336    case 2:337      Val = ElemPtr.deref<uint16_t>();338      break;339    case 4:340      Val = ElemPtr.deref<uint32_t>();341      break;342    default:343      llvm_unreachable("Unsupported char size");344    }345    if (Val == 0)346      break;347  }348 349  pushInteger(S, Len, Call->getType());350 351  return true;352}353 354static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,355                                const InterpFrame *Frame, const CallExpr *Call,356                                bool Signaling) {357  const Pointer &Arg = S.Stk.pop<Pointer>();358 359  if (!CheckLoad(S, OpPC, Arg))360    return false;361 362  assert(Arg.getFieldDesc()->isPrimitiveArray());363 364  // Convert the given string to an integer using StringRef's API.365  llvm::APInt Fill;366  std::string Str;367  assert(Arg.getNumElems() >= 1);368  for (unsigned I = 0;; ++I) {369    const Pointer &Elem = Arg.atIndex(I);370 371    if (!CheckLoad(S, OpPC, Elem))372      return false;373 374    if (Elem.deref<int8_t>() == 0)375      break;376 377    Str += Elem.deref<char>();378  }379 380  // Treat empty strings as if they were zero.381  if (Str.empty())382    Fill = llvm::APInt(32, 0);383  else if (StringRef(Str).getAsInteger(0, Fill))384    return false;385 386  const llvm::fltSemantics &TargetSemantics =387      S.getASTContext().getFloatTypeSemantics(388          Call->getDirectCallee()->getReturnType());389 390  Floating Result = S.allocFloat(TargetSemantics);391  if (S.getASTContext().getTargetInfo().isNan2008()) {392    if (Signaling)393      Result.copy(394          llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));395    else396      Result.copy(397          llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));398  } else {399    // Prior to IEEE 754-2008, architectures were allowed to choose whether400    // the first bit of their significand was set for qNaN or sNaN. MIPS chose401    // a different encoding to what became a standard in 2008, and for pre-402    // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as403    // sNaN. This is now known as "legacy NaN" encoding.404    if (Signaling)405      Result.copy(406          llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));407    else408      Result.copy(409          llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));410  }411 412  S.Stk.push<Floating>(Result);413  return true;414}415 416static bool interp__builtin_inf(InterpState &S, CodePtr OpPC,417                                const InterpFrame *Frame,418                                const CallExpr *Call) {419  const llvm::fltSemantics &TargetSemantics =420      S.getASTContext().getFloatTypeSemantics(421          Call->getDirectCallee()->getReturnType());422 423  Floating Result = S.allocFloat(TargetSemantics);424  Result.copy(APFloat::getInf(TargetSemantics));425  S.Stk.push<Floating>(Result);426  return true;427}428 429static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC,430                                     const InterpFrame *Frame) {431  const Floating &Arg2 = S.Stk.pop<Floating>();432  const Floating &Arg1 = S.Stk.pop<Floating>();433  Floating Result = S.allocFloat(Arg1.getSemantics());434 435  APFloat Copy = Arg1.getAPFloat();436  Copy.copySign(Arg2.getAPFloat());437  Result.copy(Copy);438  S.Stk.push<Floating>(Result);439 440  return true;441}442 443static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC,444                                 const InterpFrame *Frame, bool IsNumBuiltin) {445  const Floating &RHS = S.Stk.pop<Floating>();446  const Floating &LHS = S.Stk.pop<Floating>();447  Floating Result = S.allocFloat(LHS.getSemantics());448 449  if (IsNumBuiltin)450    Result.copy(llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()));451  else452    Result.copy(minnum(LHS.getAPFloat(), RHS.getAPFloat()));453  S.Stk.push<Floating>(Result);454  return true;455}456 457static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC,458                                 const InterpFrame *Frame, bool IsNumBuiltin) {459  const Floating &RHS = S.Stk.pop<Floating>();460  const Floating &LHS = S.Stk.pop<Floating>();461  Floating Result = S.allocFloat(LHS.getSemantics());462 463  if (IsNumBuiltin)464    Result.copy(llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()));465  else466    Result.copy(maxnum(LHS.getAPFloat(), RHS.getAPFloat()));467  S.Stk.push<Floating>(Result);468  return true;469}470 471/// Defined as __builtin_isnan(...), to accommodate the fact that it can472/// take a float, double, long double, etc.473/// But for us, that's all a Floating anyway.474static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC,475                                  const InterpFrame *Frame,476                                  const CallExpr *Call) {477  const Floating &Arg = S.Stk.pop<Floating>();478 479  pushInteger(S, Arg.isNan(), Call->getType());480  return true;481}482 483static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC,484                                        const InterpFrame *Frame,485                                        const CallExpr *Call) {486  const Floating &Arg = S.Stk.pop<Floating>();487 488  pushInteger(S, Arg.isSignaling(), Call->getType());489  return true;490}491 492static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC,493                                  const InterpFrame *Frame, bool CheckSign,494                                  const CallExpr *Call) {495  const Floating &Arg = S.Stk.pop<Floating>();496  APFloat F = Arg.getAPFloat();497  bool IsInf = F.isInfinity();498 499  if (CheckSign)500    pushInteger(S, IsInf ? (F.isNegative() ? -1 : 1) : 0, Call->getType());501  else502    pushInteger(S, IsInf, Call->getType());503  return true;504}505 506static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC,507                                     const InterpFrame *Frame,508                                     const CallExpr *Call) {509  const Floating &Arg = S.Stk.pop<Floating>();510 511  pushInteger(S, Arg.isFinite(), Call->getType());512  return true;513}514 515static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC,516                                     const InterpFrame *Frame,517                                     const CallExpr *Call) {518  const Floating &Arg = S.Stk.pop<Floating>();519 520  pushInteger(S, Arg.isNormal(), Call->getType());521  return true;522}523 524static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC,525                                        const InterpFrame *Frame,526                                        const CallExpr *Call) {527  const Floating &Arg = S.Stk.pop<Floating>();528 529  pushInteger(S, Arg.isDenormal(), Call->getType());530  return true;531}532 533static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC,534                                   const InterpFrame *Frame,535                                   const CallExpr *Call) {536  const Floating &Arg = S.Stk.pop<Floating>();537 538  pushInteger(S, Arg.isZero(), Call->getType());539  return true;540}541 542static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC,543                                    const InterpFrame *Frame,544                                    const CallExpr *Call) {545  const Floating &Arg = S.Stk.pop<Floating>();546 547  pushInteger(S, Arg.isNegative(), Call->getType());548  return true;549}550 551static bool interp_floating_comparison(InterpState &S, CodePtr OpPC,552                                       const CallExpr *Call, unsigned ID) {553  const Floating &RHS = S.Stk.pop<Floating>();554  const Floating &LHS = S.Stk.pop<Floating>();555 556  pushInteger(557      S,558      [&] {559        switch (ID) {560        case Builtin::BI__builtin_isgreater:561          return LHS > RHS;562        case Builtin::BI__builtin_isgreaterequal:563          return LHS >= RHS;564        case Builtin::BI__builtin_isless:565          return LHS < RHS;566        case Builtin::BI__builtin_islessequal:567          return LHS <= RHS;568        case Builtin::BI__builtin_islessgreater: {569          ComparisonCategoryResult Cmp = LHS.compare(RHS);570          return Cmp == ComparisonCategoryResult::Less ||571                 Cmp == ComparisonCategoryResult::Greater;572        }573        case Builtin::BI__builtin_isunordered:574          return LHS.compare(RHS) == ComparisonCategoryResult::Unordered;575        default:576          llvm_unreachable("Unexpected builtin ID: Should be a floating point "577                           "comparison function");578        }579      }(),580      Call->getType());581  return true;582}583 584/// First parameter to __builtin_isfpclass is the floating value, the585/// second one is an integral value.586static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,587                                      const InterpFrame *Frame,588                                      const CallExpr *Call) {589  APSInt FPClassArg = popToAPSInt(S, Call->getArg(1));590  const Floating &F = S.Stk.pop<Floating>();591 592  int32_t Result = static_cast<int32_t>(593      (F.classify() & std::move(FPClassArg)).getZExtValue());594  pushInteger(S, Result, Call->getType());595 596  return true;597}598 599/// Five int values followed by one floating value.600/// __builtin_fpclassify(int, int, int, int, int, float)601static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,602                                       const InterpFrame *Frame,603                                       const CallExpr *Call) {604  const Floating &Val = S.Stk.pop<Floating>();605 606  PrimType IntT = *S.getContext().classify(Call->getArg(0));607  APSInt Values[5];608  for (unsigned I = 0; I != 5; ++I)609    Values[4 - I] = popToAPSInt(S.Stk, IntT);610 611  unsigned Index;612  switch (Val.getCategory()) {613  case APFloat::fcNaN:614    Index = 0;615    break;616  case APFloat::fcInfinity:617    Index = 1;618    break;619  case APFloat::fcNormal:620    Index = Val.isDenormal() ? 3 : 2;621    break;622  case APFloat::fcZero:623    Index = 4;624    break;625  }626 627  // The last argument is first on the stack.628  assert(Index <= 4);629 630  pushInteger(S, Values[Index], Call->getType());631  return true;632}633 634static inline Floating abs(InterpState &S, const Floating &In) {635  if (!In.isNegative())636    return In;637 638  Floating Output = S.allocFloat(In.getSemantics());639  APFloat New = In.getAPFloat();640  New.changeSign();641  Output.copy(New);642  return Output;643}644 645// The C standard says "fabs raises no floating-point exceptions,646// even if x is a signaling NaN. The returned value is independent of647// the current rounding direction mode."  Therefore constant folding can648// proceed without regard to the floating point settings.649// Reference, WG14 N2478 F.10.4.3650static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,651                                 const InterpFrame *Frame) {652  const Floating &Val = S.Stk.pop<Floating>();653  S.Stk.push<Floating>(abs(S, Val));654  return true;655}656 657static bool interp__builtin_abs(InterpState &S, CodePtr OpPC,658                                const InterpFrame *Frame,659                                const CallExpr *Call) {660  APSInt Val = popToAPSInt(S, Call->getArg(0));661  if (Val ==662      APSInt(APInt::getSignedMinValue(Val.getBitWidth()), /*IsUnsigned=*/false))663    return false;664  if (Val.isNegative())665    Val.negate();666  pushInteger(S, Val, Call->getType());667  return true;668}669 670static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,671                                     const InterpFrame *Frame,672                                     const CallExpr *Call) {673  APSInt Val;674  if (Call->getArg(0)->getType()->isExtVectorBoolType()) {675    const Pointer &Arg = S.Stk.pop<Pointer>();676    Val = convertBoolVectorToInt(Arg);677  } else {678    Val = popToAPSInt(S, Call->getArg(0));679  }680  pushInteger(S, Val.popcount(), Call->getType());681  return true;682}683 684static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC,685                                          const InterpFrame *Frame,686                                          const CallExpr *Call) {687  // This is an unevaluated call, so there are no arguments on the stack.688  assert(Call->getNumArgs() == 1);689  const Expr *Arg = Call->getArg(0);690 691  GCCTypeClass ResultClass =692      EvaluateBuiltinClassifyType(Arg->getType(), S.getLangOpts());693  int32_t ReturnVal = static_cast<int32_t>(ResultClass);694  pushInteger(S, ReturnVal, Call->getType());695  return true;696}697 698// __builtin_expect(long, long)699// __builtin_expect_with_probability(long, long, double)700static bool interp__builtin_expect(InterpState &S, CodePtr OpPC,701                                   const InterpFrame *Frame,702                                   const CallExpr *Call) {703  // The return value is simply the value of the first parameter.704  // We ignore the probability.705  unsigned NumArgs = Call->getNumArgs();706  assert(NumArgs == 2 || NumArgs == 3);707 708  PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());709  if (NumArgs == 3)710    S.Stk.discard<Floating>();711  discard(S.Stk, ArgT);712 713  APSInt Val = popToAPSInt(S.Stk, ArgT);714  pushInteger(S, Val, Call->getType());715  return true;716}717 718static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC,719                                      const InterpFrame *Frame,720                                      const CallExpr *Call) {721#ifndef NDEBUG722  assert(Call->getArg(0)->isLValue());723  PrimType PtrT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr);724  assert(PtrT == PT_Ptr &&725         "Unsupported pointer type passed to __builtin_addressof()");726#endif727  return true;728}729 730static bool interp__builtin_move(InterpState &S, CodePtr OpPC,731                                 const InterpFrame *Frame,732                                 const CallExpr *Call) {733  return Call->getDirectCallee()->isConstexpr();734}735 736static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC,737                                                 const InterpFrame *Frame,738                                                 const CallExpr *Call) {739  APSInt Arg = popToAPSInt(S, Call->getArg(0));740 741  int Result = S.getASTContext().getTargetInfo().getEHDataRegisterNumber(742      Arg.getZExtValue());743  pushInteger(S, Result, Call->getType());744  return true;745}746 747// Two integral values followed by a pointer (lhs, rhs, resultOut)748static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC,749                                       const CallExpr *Call,750                                       unsigned BuiltinOp) {751  const Pointer &ResultPtr = S.Stk.pop<Pointer>();752  if (ResultPtr.isDummy() || !ResultPtr.isBlockPointer())753    return false;754 755  PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());756  PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());757  APSInt RHS = popToAPSInt(S.Stk, RHST);758  APSInt LHS = popToAPSInt(S.Stk, LHST);759  QualType ResultType = Call->getArg(2)->getType()->getPointeeType();760  PrimType ResultT = *S.getContext().classify(ResultType);761  bool Overflow;762 763  APSInt Result;764  if (BuiltinOp == Builtin::BI__builtin_add_overflow ||765      BuiltinOp == Builtin::BI__builtin_sub_overflow ||766      BuiltinOp == Builtin::BI__builtin_mul_overflow) {767    bool IsSigned = LHS.isSigned() || RHS.isSigned() ||768                    ResultType->isSignedIntegerOrEnumerationType();769    bool AllSigned = LHS.isSigned() && RHS.isSigned() &&770                     ResultType->isSignedIntegerOrEnumerationType();771    uint64_t LHSSize = LHS.getBitWidth();772    uint64_t RHSSize = RHS.getBitWidth();773    uint64_t ResultSize = S.getASTContext().getTypeSize(ResultType);774    uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize);775 776    // Add an additional bit if the signedness isn't uniformly agreed to. We777    // could do this ONLY if there is a signed and an unsigned that both have778    // MaxBits, but the code to check that is pretty nasty.  The issue will be779    // caught in the shrink-to-result later anyway.780    if (IsSigned && !AllSigned)781      ++MaxBits;782 783    LHS = APSInt(LHS.extOrTrunc(MaxBits), !IsSigned);784    RHS = APSInt(RHS.extOrTrunc(MaxBits), !IsSigned);785    Result = APSInt(MaxBits, !IsSigned);786  }787 788  // Find largest int.789  switch (BuiltinOp) {790  default:791    llvm_unreachable("Invalid value for BuiltinOp");792  case Builtin::BI__builtin_add_overflow:793  case Builtin::BI__builtin_sadd_overflow:794  case Builtin::BI__builtin_saddl_overflow:795  case Builtin::BI__builtin_saddll_overflow:796  case Builtin::BI__builtin_uadd_overflow:797  case Builtin::BI__builtin_uaddl_overflow:798  case Builtin::BI__builtin_uaddll_overflow:799    Result = LHS.isSigned() ? LHS.sadd_ov(RHS, Overflow)800                            : LHS.uadd_ov(RHS, Overflow);801    break;802  case Builtin::BI__builtin_sub_overflow:803  case Builtin::BI__builtin_ssub_overflow:804  case Builtin::BI__builtin_ssubl_overflow:805  case Builtin::BI__builtin_ssubll_overflow:806  case Builtin::BI__builtin_usub_overflow:807  case Builtin::BI__builtin_usubl_overflow:808  case Builtin::BI__builtin_usubll_overflow:809    Result = LHS.isSigned() ? LHS.ssub_ov(RHS, Overflow)810                            : LHS.usub_ov(RHS, Overflow);811    break;812  case Builtin::BI__builtin_mul_overflow:813  case Builtin::BI__builtin_smul_overflow:814  case Builtin::BI__builtin_smull_overflow:815  case Builtin::BI__builtin_smulll_overflow:816  case Builtin::BI__builtin_umul_overflow:817  case Builtin::BI__builtin_umull_overflow:818  case Builtin::BI__builtin_umulll_overflow:819    Result = LHS.isSigned() ? LHS.smul_ov(RHS, Overflow)820                            : LHS.umul_ov(RHS, Overflow);821    break;822  }823 824  // In the case where multiple sizes are allowed, truncate and see if825  // the values are the same.826  if (BuiltinOp == Builtin::BI__builtin_add_overflow ||827      BuiltinOp == Builtin::BI__builtin_sub_overflow ||828      BuiltinOp == Builtin::BI__builtin_mul_overflow) {829    // APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead,830    // since it will give us the behavior of a TruncOrSelf in the case where831    // its parameter <= its size.  We previously set Result to be at least the832    // type-size of the result, so getTypeSize(ResultType) <= Resu833    APSInt Temp = Result.extOrTrunc(S.getASTContext().getTypeSize(ResultType));834    Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType());835 836    if (!APSInt::isSameValue(Temp, Result))837      Overflow = true;838    Result = std::move(Temp);839  }840 841  // Write Result to ResultPtr and put Overflow on the stack.842  assignInteger(S, ResultPtr, ResultT, Result);843  if (ResultPtr.canBeInitialized())844    ResultPtr.initialize();845 846  assert(Call->getDirectCallee()->getReturnType()->isBooleanType());847  S.Stk.push<Boolean>(Overflow);848  return true;849}850 851/// Three integral values followed by a pointer (lhs, rhs, carry, carryOut).852static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,853                                    const InterpFrame *Frame,854                                    const CallExpr *Call, unsigned BuiltinOp) {855  const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();856  PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());857  PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());858  APSInt CarryIn = popToAPSInt(S.Stk, LHST);859  APSInt RHS = popToAPSInt(S.Stk, RHST);860  APSInt LHS = popToAPSInt(S.Stk, LHST);861 862  if (CarryOutPtr.isDummy() || !CarryOutPtr.isBlockPointer())863    return false;864 865  APSInt CarryOut;866 867  APSInt Result;868  // Copy the number of bits and sign.869  Result = LHS;870  CarryOut = LHS;871 872  bool FirstOverflowed = false;873  bool SecondOverflowed = false;874  switch (BuiltinOp) {875  default:876    llvm_unreachable("Invalid value for BuiltinOp");877  case Builtin::BI__builtin_addcb:878  case Builtin::BI__builtin_addcs:879  case Builtin::BI__builtin_addc:880  case Builtin::BI__builtin_addcl:881  case Builtin::BI__builtin_addcll:882    Result =883        LHS.uadd_ov(RHS, FirstOverflowed).uadd_ov(CarryIn, SecondOverflowed);884    break;885  case Builtin::BI__builtin_subcb:886  case Builtin::BI__builtin_subcs:887  case Builtin::BI__builtin_subc:888  case Builtin::BI__builtin_subcl:889  case Builtin::BI__builtin_subcll:890    Result =891        LHS.usub_ov(RHS, FirstOverflowed).usub_ov(CarryIn, SecondOverflowed);892    break;893  }894  // It is possible for both overflows to happen but CGBuiltin uses an OR so895  // this is consistent.896  CarryOut = (uint64_t)(FirstOverflowed | SecondOverflowed);897 898  QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();899  PrimType CarryOutT = *S.getContext().classify(CarryOutType);900  assignInteger(S, CarryOutPtr, CarryOutT, CarryOut);901  CarryOutPtr.initialize();902 903  assert(Call->getType() == Call->getArg(0)->getType());904  pushInteger(S, Result, Call->getType());905  return true;906}907 908static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,909                                const InterpFrame *Frame, const CallExpr *Call,910                                unsigned BuiltinOp) {911 912  std::optional<APSInt> Fallback;913  if (BuiltinOp == Builtin::BI__builtin_clzg && Call->getNumArgs() == 2)914    Fallback = popToAPSInt(S, Call->getArg(1));915 916  APSInt Val;917  if (Call->getArg(0)->getType()->isExtVectorBoolType()) {918    const Pointer &Arg = S.Stk.pop<Pointer>();919    Val = convertBoolVectorToInt(Arg);920  } else {921    Val = popToAPSInt(S, Call->getArg(0));922  }923 924  // When the argument is 0, the result of GCC builtins is undefined, whereas925  // for Microsoft intrinsics, the result is the bit-width of the argument.926  bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&927                         BuiltinOp != Builtin::BI__lzcnt &&928                         BuiltinOp != Builtin::BI__lzcnt64;929 930  if (Val == 0) {931    if (Fallback) {932      pushInteger(S, *Fallback, Call->getType());933      return true;934    }935 936    if (ZeroIsUndefined)937      return false;938  }939 940  pushInteger(S, Val.countl_zero(), Call->getType());941  return true;942}943 944static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC,945                                const InterpFrame *Frame, const CallExpr *Call,946                                unsigned BuiltinID) {947  std::optional<APSInt> Fallback;948  if (BuiltinID == Builtin::BI__builtin_ctzg && Call->getNumArgs() == 2)949    Fallback = popToAPSInt(S, Call->getArg(1));950 951  APSInt Val;952  if (Call->getArg(0)->getType()->isExtVectorBoolType()) {953    const Pointer &Arg = S.Stk.pop<Pointer>();954    Val = convertBoolVectorToInt(Arg);955  } else {956    Val = popToAPSInt(S, Call->getArg(0));957  }958 959  if (Val == 0) {960    if (Fallback) {961      pushInteger(S, *Fallback, Call->getType());962      return true;963    }964    return false;965  }966 967  pushInteger(S, Val.countr_zero(), Call->getType());968  return true;969}970 971static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC,972                                  const InterpFrame *Frame,973                                  const CallExpr *Call) {974  const APSInt &Val = popToAPSInt(S, Call->getArg(0));975  if (Val.getBitWidth() == 8)976    pushInteger(S, Val, Call->getType());977  else978    pushInteger(S, Val.byteSwap(), Call->getType());979  return true;980}981 982/// bool __atomic_always_lock_free(size_t, void const volatile*)983/// bool __atomic_is_lock_free(size_t, void const volatile*)984static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,985                                             const InterpFrame *Frame,986                                             const CallExpr *Call,987                                             unsigned BuiltinOp) {988  auto returnBool = [&S](bool Value) -> bool {989    S.Stk.push<Boolean>(Value);990    return true;991  };992 993  const Pointer &Ptr = S.Stk.pop<Pointer>();994  const APSInt &SizeVal = popToAPSInt(S, Call->getArg(0));995 996  // For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power997  // of two less than or equal to the maximum inline atomic width, we know it998  // is lock-free.  If the size isn't a power of two, or greater than the999  // maximum alignment where we promote atomics, we know it is not lock-free1000  // (at least not in the sense of atomic_is_lock_free).  Otherwise,1001  // the answer can only be determined at runtime; for example, 16-byte1002  // atomics have lock-free implementations on some, but not all,1003  // x86-64 processors.1004 1005  // Check power-of-two.1006  CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());1007  if (Size.isPowerOfTwo()) {1008    // Check against inlining width.1009    unsigned InlineWidthBits =1010        S.getASTContext().getTargetInfo().getMaxAtomicInlineWidth();1011    if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits)) {1012 1013      // OK, we will inline appropriately-aligned operations of this size,1014      // and _Atomic(T) is appropriately-aligned.1015      if (Size == CharUnits::One())1016        return returnBool(true);1017 1018      // Same for null pointers.1019      assert(BuiltinOp != Builtin::BI__c11_atomic_is_lock_free);1020      if (Ptr.isZero())1021        return returnBool(true);1022 1023      if (Ptr.isIntegralPointer()) {1024        uint64_t IntVal = Ptr.getIntegerRepresentation();1025        if (APSInt(APInt(64, IntVal, false), true).isAligned(Size.getAsAlign()))1026          return returnBool(true);1027      }1028 1029      const Expr *PtrArg = Call->getArg(1);1030      // Otherwise, check if the type's alignment against Size.1031      if (const auto *ICE = dyn_cast<ImplicitCastExpr>(PtrArg)) {1032        // Drop the potential implicit-cast to 'const volatile void*', getting1033        // the underlying type.1034        if (ICE->getCastKind() == CK_BitCast)1035          PtrArg = ICE->getSubExpr();1036      }1037 1038      if (const auto *PtrTy = PtrArg->getType()->getAs<PointerType>()) {1039        QualType PointeeType = PtrTy->getPointeeType();1040        if (!PointeeType->isIncompleteType() &&1041            S.getASTContext().getTypeAlignInChars(PointeeType) >= Size) {1042          // OK, we will inline operations on this object.1043          return returnBool(true);1044        }1045      }1046    }1047  }1048 1049  if (BuiltinOp == Builtin::BI__atomic_always_lock_free)1050    return returnBool(false);1051 1052  return false;1053}1054 1055/// bool __c11_atomic_is_lock_free(size_t)1056static bool interp__builtin_c11_atomic_is_lock_free(InterpState &S,1057                                                    CodePtr OpPC,1058                                                    const InterpFrame *Frame,1059                                                    const CallExpr *Call) {1060  const APSInt &SizeVal = popToAPSInt(S, Call->getArg(0));1061 1062  CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());1063  if (Size.isPowerOfTwo()) {1064    // Check against inlining width.1065    unsigned InlineWidthBits =1066        S.getASTContext().getTargetInfo().getMaxAtomicInlineWidth();1067    if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits)) {1068      S.Stk.push<Boolean>(true);1069      return true;1070    }1071  }1072 1073  return false; // returnBool(false);1074}1075 1076/// __builtin_complex(Float A, float B);1077static bool interp__builtin_complex(InterpState &S, CodePtr OpPC,1078                                    const InterpFrame *Frame,1079                                    const CallExpr *Call) {1080  const Floating &Arg2 = S.Stk.pop<Floating>();1081  const Floating &Arg1 = S.Stk.pop<Floating>();1082  Pointer &Result = S.Stk.peek<Pointer>();1083 1084  Result.elem<Floating>(0) = Arg1;1085  Result.elem<Floating>(1) = Arg2;1086  Result.initializeAllElements();1087 1088  return true;1089}1090 1091/// __builtin_is_aligned()1092/// __builtin_align_up()1093/// __builtin_align_down()1094/// The first parameter is either an integer or a pointer.1095/// The second parameter is the requested alignment as an integer.1096static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,1097                                               const InterpFrame *Frame,1098                                               const CallExpr *Call,1099                                               unsigned BuiltinOp) {1100  const APSInt &Alignment = popToAPSInt(S, Call->getArg(1));1101 1102  if (Alignment < 0 || !Alignment.isPowerOf2()) {1103    S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment;1104    return false;1105  }1106  unsigned SrcWidth = S.getASTContext().getIntWidth(Call->getArg(0)->getType());1107  APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1));1108  if (APSInt::compareValues(Alignment, MaxValue) > 0) {1109    S.FFDiag(Call, diag::note_constexpr_alignment_too_big)1110        << MaxValue << Call->getArg(0)->getType() << Alignment;1111    return false;1112  }1113 1114  // The first parameter is either an integer or a pointer.1115  PrimType FirstArgT = *S.Ctx.classify(Call->getArg(0));1116 1117  if (isIntegralType(FirstArgT)) {1118    const APSInt &Src = popToAPSInt(S.Stk, FirstArgT);1119    APInt AlignMinusOne = Alignment.extOrTrunc(Src.getBitWidth()) - 1;1120    if (BuiltinOp == Builtin::BI__builtin_align_up) {1121      APSInt AlignedVal =1122          APSInt((Src + AlignMinusOne) & ~AlignMinusOne, Src.isUnsigned());1123      pushInteger(S, AlignedVal, Call->getType());1124    } else if (BuiltinOp == Builtin::BI__builtin_align_down) {1125      APSInt AlignedVal = APSInt(Src & ~AlignMinusOne, Src.isUnsigned());1126      pushInteger(S, AlignedVal, Call->getType());1127    } else {1128      assert(*S.Ctx.classify(Call->getType()) == PT_Bool);1129      S.Stk.push<Boolean>((Src & AlignMinusOne) == 0);1130    }1131    return true;1132  }1133  assert(FirstArgT == PT_Ptr);1134  const Pointer &Ptr = S.Stk.pop<Pointer>();1135  if (!Ptr.isBlockPointer())1136    return false;1137 1138  unsigned PtrOffset = Ptr.getIndex();1139  CharUnits BaseAlignment =1140      S.getASTContext().getDeclAlign(Ptr.getDeclDesc()->asValueDecl());1141  CharUnits PtrAlign =1142      BaseAlignment.alignmentAtOffset(CharUnits::fromQuantity(PtrOffset));1143 1144  if (BuiltinOp == Builtin::BI__builtin_is_aligned) {1145    if (PtrAlign.getQuantity() >= Alignment) {1146      S.Stk.push<Boolean>(true);1147      return true;1148    }1149    // If the alignment is not known to be sufficient, some cases could still1150    // be aligned at run time. However, if the requested alignment is less or1151    // equal to the base alignment and the offset is not aligned, we know that1152    // the run-time value can never be aligned.1153    if (BaseAlignment.getQuantity() >= Alignment &&1154        PtrAlign.getQuantity() < Alignment) {1155      S.Stk.push<Boolean>(false);1156      return true;1157    }1158 1159    S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_compute)1160        << Alignment;1161    return false;1162  }1163 1164  assert(BuiltinOp == Builtin::BI__builtin_align_down ||1165         BuiltinOp == Builtin::BI__builtin_align_up);1166 1167  // For align_up/align_down, we can return the same value if the alignment1168  // is known to be greater or equal to the requested value.1169  if (PtrAlign.getQuantity() >= Alignment) {1170    S.Stk.push<Pointer>(Ptr);1171    return true;1172  }1173 1174  // The alignment could be greater than the minimum at run-time, so we cannot1175  // infer much about the resulting pointer value. One case is possible:1176  // For `_Alignas(32) char buf[N]; __builtin_align_down(&buf[idx], 32)` we1177  // can infer the correct index if the requested alignment is smaller than1178  // the base alignment so we can perform the computation on the offset.1179  if (BaseAlignment.getQuantity() >= Alignment) {1180    assert(Alignment.getBitWidth() <= 64 &&1181           "Cannot handle > 64-bit address-space");1182    uint64_t Alignment64 = Alignment.getZExtValue();1183    CharUnits NewOffset =1184        CharUnits::fromQuantity(BuiltinOp == Builtin::BI__builtin_align_down1185                                    ? llvm::alignDown(PtrOffset, Alignment64)1186                                    : llvm::alignTo(PtrOffset, Alignment64));1187 1188    S.Stk.push<Pointer>(Ptr.atIndex(NewOffset.getQuantity()));1189    return true;1190  }1191 1192  // Otherwise, we cannot constant-evaluate the result.1193  S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_adjust) << Alignment;1194  return false;1195}1196 1197/// __builtin_assume_aligned(Ptr, Alignment[, ExtraOffset])1198static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC,1199                                           const InterpFrame *Frame,1200                                           const CallExpr *Call) {1201  assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3);1202 1203  std::optional<APSInt> ExtraOffset;1204  if (Call->getNumArgs() == 3)1205    ExtraOffset = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(2)));1206 1207  APSInt Alignment = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)));1208  const Pointer &Ptr = S.Stk.pop<Pointer>();1209 1210  CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue());1211 1212  // If there is a base object, then it must have the correct alignment.1213  if (Ptr.isBlockPointer()) {1214    CharUnits BaseAlignment;1215    if (const auto *VD = Ptr.getDeclDesc()->asValueDecl())1216      BaseAlignment = S.getASTContext().getDeclAlign(VD);1217    else if (const auto *E = Ptr.getDeclDesc()->asExpr())1218      BaseAlignment = GetAlignOfExpr(S.getASTContext(), E, UETT_AlignOf);1219 1220    if (BaseAlignment < Align) {1221      S.CCEDiag(Call->getArg(0),1222                diag::note_constexpr_baa_insufficient_alignment)1223          << 0 << BaseAlignment.getQuantity() << Align.getQuantity();1224      return false;1225    }1226  }1227 1228  APValue AV = Ptr.toAPValue(S.getASTContext());1229  CharUnits AVOffset = AV.getLValueOffset();1230  if (ExtraOffset)1231    AVOffset -= CharUnits::fromQuantity(ExtraOffset->getZExtValue());1232  if (AVOffset.alignTo(Align) != AVOffset) {1233    if (Ptr.isBlockPointer())1234      S.CCEDiag(Call->getArg(0),1235                diag::note_constexpr_baa_insufficient_alignment)1236          << 1 << AVOffset.getQuantity() << Align.getQuantity();1237    else1238      S.CCEDiag(Call->getArg(0),1239                diag::note_constexpr_baa_value_insufficient_alignment)1240          << AVOffset.getQuantity() << Align.getQuantity();1241    return false;1242  }1243 1244  S.Stk.push<Pointer>(Ptr);1245  return true;1246}1247 1248/// (CarryIn, LHS, RHS, Result)1249static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S,1250                                                    CodePtr OpPC,1251                                                    const InterpFrame *Frame,1252                                                    const CallExpr *Call,1253                                                    unsigned BuiltinOp) {1254  if (Call->getNumArgs() != 4 || !Call->getArg(0)->getType()->isIntegerType() ||1255      !Call->getArg(1)->getType()->isIntegerType() ||1256      !Call->getArg(2)->getType()->isIntegerType())1257    return false;1258 1259  const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();1260 1261  APSInt RHS = popToAPSInt(S, Call->getArg(2));1262  APSInt LHS = popToAPSInt(S, Call->getArg(1));1263  APSInt CarryIn = popToAPSInt(S, Call->getArg(0));1264 1265  bool IsAdd = BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u32 ||1266               BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u64;1267 1268  unsigned BitWidth = LHS.getBitWidth();1269  unsigned CarryInBit = CarryIn.ugt(0) ? 1 : 0;1270  APInt ExResult =1271      IsAdd ? (LHS.zext(BitWidth + 1) + (RHS.zext(BitWidth + 1) + CarryInBit))1272            : (LHS.zext(BitWidth + 1) - (RHS.zext(BitWidth + 1) + CarryInBit));1273 1274  APInt Result = ExResult.extractBits(BitWidth, 0);1275  APSInt CarryOut =1276      APSInt(ExResult.extractBits(1, BitWidth), /*IsUnsigned=*/true);1277 1278  QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();1279  PrimType CarryOutT = *S.getContext().classify(CarryOutType);1280  assignInteger(S, CarryOutPtr, CarryOutT, APSInt(std::move(Result), true));1281 1282  pushInteger(S, CarryOut, Call->getType());1283 1284  return true;1285}1286 1287static bool interp__builtin_os_log_format_buffer_size(InterpState &S,1288                                                      CodePtr OpPC,1289                                                      const InterpFrame *Frame,1290                                                      const CallExpr *Call) {1291  analyze_os_log::OSLogBufferLayout Layout;1292  analyze_os_log::computeOSLogBufferLayout(S.getASTContext(), Call, Layout);1293  pushInteger(S, Layout.size().getQuantity(), Call->getType());1294  return true;1295}1296 1297static bool1298interp__builtin_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC,1299                                             const InterpFrame *Frame,1300                                             const CallExpr *Call) {1301  const auto &Ptr = S.Stk.pop<Pointer>();1302  assert(Ptr.getFieldDesc()->isPrimitiveArray());1303 1304  // This should be created for a StringLiteral, so should alway shold at least1305  // one array element.1306  assert(Ptr.getFieldDesc()->getNumElems() >= 1);1307  StringRef R(&Ptr.deref<char>(), Ptr.getFieldDesc()->getNumElems() - 1);1308  uint64_t Result = getPointerAuthStableSipHash(R);1309  pushInteger(S, Result, Call->getType());1310  return true;1311}1312 1313static bool interp__builtin_infer_alloc_token(InterpState &S, CodePtr OpPC,1314                                              const InterpFrame *Frame,1315                                              const CallExpr *Call) {1316  const ASTContext &ASTCtx = S.getASTContext();1317  uint64_t BitWidth = ASTCtx.getTypeSize(ASTCtx.getSizeType());1318  auto Mode =1319      ASTCtx.getLangOpts().AllocTokenMode.value_or(llvm::DefaultAllocTokenMode);1320  auto MaxTokensOpt = ASTCtx.getLangOpts().AllocTokenMax;1321  uint64_t MaxTokens =1322      MaxTokensOpt.value_or(0) ? *MaxTokensOpt : (~0ULL >> (64 - BitWidth));1323 1324  // We do not read any of the arguments; discard them.1325  for (int I = Call->getNumArgs() - 1; I >= 0; --I)1326    discard(S.Stk, *S.getContext().classify(Call->getArg(I)));1327 1328  // Note: Type inference from a surrounding cast is not supported in1329  // constexpr evaluation.1330  QualType AllocType = infer_alloc::inferPossibleType(Call, ASTCtx, nullptr);1331  if (AllocType.isNull()) {1332    S.CCEDiag(Call,1333              diag::note_constexpr_infer_alloc_token_type_inference_failed);1334    return false;1335  }1336 1337  auto ATMD = infer_alloc::getAllocTokenMetadata(AllocType, ASTCtx);1338  if (!ATMD) {1339    S.CCEDiag(Call, diag::note_constexpr_infer_alloc_token_no_metadata);1340    return false;1341  }1342 1343  auto MaybeToken = llvm::getAllocToken(Mode, *ATMD, MaxTokens);1344  if (!MaybeToken) {1345    S.CCEDiag(Call, diag::note_constexpr_infer_alloc_token_stateful_mode);1346    return false;1347  }1348 1349  pushInteger(S, llvm::APInt(BitWidth, *MaybeToken), ASTCtx.getSizeType());1350  return true;1351}1352 1353static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,1354                                         const InterpFrame *Frame,1355                                         const CallExpr *Call) {1356  // A call to __operator_new is only valid within std::allocate<>::allocate.1357  // Walk up the call stack to find the appropriate caller and get the1358  // element type from it.1359  auto [NewCall, ElemType] = S.getStdAllocatorCaller("allocate");1360 1361  if (ElemType.isNull()) {1362    S.FFDiag(Call, S.getLangOpts().CPlusPlus201363                       ? diag::note_constexpr_new_untyped1364                       : diag::note_constexpr_new);1365    return false;1366  }1367  assert(NewCall);1368 1369  if (ElemType->isIncompleteType() || ElemType->isFunctionType()) {1370    S.FFDiag(Call, diag::note_constexpr_new_not_complete_object_type)1371        << (ElemType->isIncompleteType() ? 0 : 1) << ElemType;1372    return false;1373  }1374 1375  // We only care about the first parameter (the size), so discard all the1376  // others.1377  {1378    unsigned NumArgs = Call->getNumArgs();1379    assert(NumArgs >= 1);1380 1381    // The std::nothrow_t arg never gets put on the stack.1382    if (Call->getArg(NumArgs - 1)->getType()->isNothrowT())1383      --NumArgs;1384    auto Args = ArrayRef(Call->getArgs(), Call->getNumArgs());1385    // First arg is needed.1386    Args = Args.drop_front();1387 1388    // Discard the rest.1389    for (const Expr *Arg : Args)1390      discard(S.Stk, *S.getContext().classify(Arg));1391  }1392 1393  APSInt Bytes = popToAPSInt(S, Call->getArg(0));1394  CharUnits ElemSize = S.getASTContext().getTypeSizeInChars(ElemType);1395  assert(!ElemSize.isZero());1396  // Divide the number of bytes by sizeof(ElemType), so we get the number of1397  // elements we should allocate.1398  APInt NumElems, Remainder;1399  APInt ElemSizeAP(Bytes.getBitWidth(), ElemSize.getQuantity());1400  APInt::udivrem(Bytes, ElemSizeAP, NumElems, Remainder);1401  if (Remainder != 0) {1402    // This likely indicates a bug in the implementation of 'std::allocator'.1403    S.FFDiag(Call, diag::note_constexpr_operator_new_bad_size)1404        << Bytes << APSInt(ElemSizeAP, true) << ElemType;1405    return false;1406  }1407 1408  // NB: The same check we're using in CheckArraySize()1409  if (NumElems.getActiveBits() >1410          ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||1411      NumElems.ugt(Descriptor::MaxArrayElemBytes / ElemSize.getQuantity())) {1412    // FIXME: NoThrow check?1413    const SourceInfo &Loc = S.Current->getSource(OpPC);1414    S.FFDiag(Loc, diag::note_constexpr_new_too_large)1415        << NumElems.getZExtValue();1416    return false;1417  }1418 1419  if (!CheckArraySize(S, OpPC, NumElems.getZExtValue()))1420    return false;1421 1422  bool IsArray = NumElems.ugt(1);1423  OptPrimType ElemT = S.getContext().classify(ElemType);1424  DynamicAllocator &Allocator = S.getAllocator();1425  if (ElemT) {1426    Block *B =1427        Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(),1428                           S.Ctx.getEvalID(), DynamicAllocator::Form::Operator);1429    assert(B);1430    S.Stk.push<Pointer>(Pointer(B).atIndex(0));1431    return true;1432  }1433 1434  assert(!ElemT);1435 1436  // Composite arrays1437  if (IsArray) {1438    const Descriptor *Desc =1439        S.P.createDescriptor(NewCall, ElemType.getTypePtr(), std::nullopt);1440    Block *B =1441        Allocator.allocate(Desc, NumElems.getZExtValue(), S.Ctx.getEvalID(),1442                           DynamicAllocator::Form::Operator);1443    assert(B);1444    S.Stk.push<Pointer>(Pointer(B).atIndex(0).narrow());1445    return true;1446  }1447 1448  // Records. Still allocate them as single-element arrays.1449  QualType AllocType = S.getASTContext().getConstantArrayType(1450      ElemType, NumElems, nullptr, ArraySizeModifier::Normal, 0);1451 1452  const Descriptor *Desc = S.P.createDescriptor(NewCall, AllocType.getTypePtr(),1453                                                Descriptor::InlineDescMD);1454  Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(),1455                                DynamicAllocator::Form::Operator);1456  assert(B);1457  S.Stk.push<Pointer>(Pointer(B).atIndex(0).narrow());1458  return true;1459}1460 1461static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC,1462                                            const InterpFrame *Frame,1463                                            const CallExpr *Call) {1464  const Expr *Source = nullptr;1465  const Block *BlockToDelete = nullptr;1466 1467  if (S.checkingPotentialConstantExpression()) {1468    S.Stk.discard<Pointer>();1469    return false;1470  }1471 1472  // This is permitted only within a call to std::allocator<T>::deallocate.1473  if (!S.getStdAllocatorCaller("deallocate")) {1474    S.FFDiag(Call);1475    S.Stk.discard<Pointer>();1476    return true;1477  }1478 1479  {1480    const Pointer &Ptr = S.Stk.pop<Pointer>();1481 1482    if (Ptr.isZero()) {1483      S.CCEDiag(Call, diag::note_constexpr_deallocate_null);1484      return true;1485    }1486 1487    Source = Ptr.getDeclDesc()->asExpr();1488    BlockToDelete = Ptr.block();1489 1490    if (!BlockToDelete->isDynamic()) {1491      S.FFDiag(Call, diag::note_constexpr_delete_not_heap_alloc)1492          << Ptr.toDiagnosticString(S.getASTContext());1493      if (const auto *D = Ptr.getFieldDesc()->asDecl())1494        S.Note(D->getLocation(), diag::note_declared_at);1495    }1496  }1497  assert(BlockToDelete);1498 1499  DynamicAllocator &Allocator = S.getAllocator();1500  const Descriptor *BlockDesc = BlockToDelete->getDescriptor();1501  std::optional<DynamicAllocator::Form> AllocForm =1502      Allocator.getAllocationForm(Source);1503 1504  if (!Allocator.deallocate(Source, BlockToDelete, S)) {1505    // Nothing has been deallocated, this must be a double-delete.1506    const SourceInfo &Loc = S.Current->getSource(OpPC);1507    S.FFDiag(Loc, diag::note_constexpr_double_delete);1508    return false;1509  }1510  assert(AllocForm);1511 1512  return CheckNewDeleteForms(1513      S, OpPC, *AllocForm, DynamicAllocator::Form::Operator, BlockDesc, Source);1514}1515 1516static bool interp__builtin_arithmetic_fence(InterpState &S, CodePtr OpPC,1517                                             const InterpFrame *Frame,1518                                             const CallExpr *Call) {1519  const Floating &Arg0 = S.Stk.pop<Floating>();1520  S.Stk.push<Floating>(Arg0);1521  return true;1522}1523 1524static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,1525                                          const CallExpr *Call, unsigned ID) {1526  const Pointer &Arg = S.Stk.pop<Pointer>();1527  assert(Arg.getFieldDesc()->isPrimitiveArray());1528 1529  QualType ElemType = Arg.getFieldDesc()->getElemQualType();1530  assert(Call->getType() == ElemType);1531  PrimType ElemT = *S.getContext().classify(ElemType);1532  unsigned NumElems = Arg.getNumElems();1533 1534  INT_TYPE_SWITCH_NO_BOOL(ElemT, {1535    T Result = Arg.elem<T>(0);1536    unsigned BitWidth = Result.bitWidth();1537    for (unsigned I = 1; I != NumElems; ++I) {1538      T Elem = Arg.elem<T>(I);1539      T PrevResult = Result;1540 1541      if (ID == Builtin::BI__builtin_reduce_add) {1542        if (T::add(Result, Elem, BitWidth, &Result)) {1543          unsigned OverflowBits = BitWidth + 1;1544          (void)handleOverflow(S, OpPC,1545                               (PrevResult.toAPSInt(OverflowBits) +1546                                Elem.toAPSInt(OverflowBits)));1547          return false;1548        }1549      } else if (ID == Builtin::BI__builtin_reduce_mul) {1550        if (T::mul(Result, Elem, BitWidth, &Result)) {1551          unsigned OverflowBits = BitWidth * 2;1552          (void)handleOverflow(S, OpPC,1553                               (PrevResult.toAPSInt(OverflowBits) *1554                                Elem.toAPSInt(OverflowBits)));1555          return false;1556        }1557 1558      } else if (ID == Builtin::BI__builtin_reduce_and) {1559        (void)T::bitAnd(Result, Elem, BitWidth, &Result);1560      } else if (ID == Builtin::BI__builtin_reduce_or) {1561        (void)T::bitOr(Result, Elem, BitWidth, &Result);1562      } else if (ID == Builtin::BI__builtin_reduce_xor) {1563        (void)T::bitXor(Result, Elem, BitWidth, &Result);1564      } else if (ID == Builtin::BI__builtin_reduce_min) {1565        if (Elem < Result)1566          Result = Elem;1567      } else if (ID == Builtin::BI__builtin_reduce_max) {1568        if (Elem > Result)1569          Result = Elem;1570      } else {1571        llvm_unreachable("Unhandled vector reduce builtin");1572      }1573    }1574    pushInteger(S, Result.toAPSInt(), Call->getType());1575  });1576 1577  return true;1578}1579 1580static bool interp__builtin_elementwise_abs(InterpState &S, CodePtr OpPC,1581                                            const InterpFrame *Frame,1582                                            const CallExpr *Call,1583                                            unsigned BuiltinID) {1584  assert(Call->getNumArgs() == 1);1585  QualType Ty = Call->getArg(0)->getType();1586  if (Ty->isIntegerType()) {1587    APSInt Val = popToAPSInt(S, Call->getArg(0));1588    pushInteger(S, Val.abs(), Call->getType());1589    return true;1590  }1591 1592  if (Ty->isFloatingType()) {1593    Floating Val = S.Stk.pop<Floating>();1594    Floating Result = abs(S, Val);1595    S.Stk.push<Floating>(Result);1596    return true;1597  }1598 1599  // Otherwise, the argument must be a vector.1600  assert(Call->getArg(0)->getType()->isVectorType());1601  const Pointer &Arg = S.Stk.pop<Pointer>();1602  assert(Arg.getFieldDesc()->isPrimitiveArray());1603  const Pointer &Dst = S.Stk.peek<Pointer>();1604  assert(Dst.getFieldDesc()->isPrimitiveArray());1605  assert(Arg.getFieldDesc()->getNumElems() ==1606         Dst.getFieldDesc()->getNumElems());1607 1608  QualType ElemType = Arg.getFieldDesc()->getElemQualType();1609  PrimType ElemT = *S.getContext().classify(ElemType);1610  unsigned NumElems = Arg.getNumElems();1611  // we can either have a vector of integer or a vector of floating point1612  for (unsigned I = 0; I != NumElems; ++I) {1613    if (ElemType->isIntegerType()) {1614      INT_TYPE_SWITCH_NO_BOOL(ElemT, {1615        Dst.elem<T>(I) = T::from(static_cast<T>(1616            APSInt(Arg.elem<T>(I).toAPSInt().abs(),1617                   ElemType->isUnsignedIntegerOrEnumerationType())));1618      });1619    } else {1620      Floating Val = Arg.elem<Floating>(I);1621      Dst.elem<Floating>(I) = abs(S, Val);1622    }1623  }1624  Dst.initializeAllElements();1625 1626  return true;1627}1628 1629/// Can be called with an integer or vector as the first and only parameter.1630static bool interp__builtin_elementwise_countzeroes(InterpState &S,1631                                                    CodePtr OpPC,1632                                                    const InterpFrame *Frame,1633                                                    const CallExpr *Call,1634                                                    unsigned BuiltinID) {1635  bool HasZeroArg = Call->getNumArgs() == 2;1636  bool IsCTTZ = BuiltinID == Builtin::BI__builtin_elementwise_ctzg;1637  assert(Call->getNumArgs() == 1 || HasZeroArg);1638  if (Call->getArg(0)->getType()->isIntegerType()) {1639    PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());1640    APSInt Val = popToAPSInt(S.Stk, ArgT);1641    std::optional<APSInt> ZeroVal;1642    if (HasZeroArg) {1643      ZeroVal = Val;1644      Val = popToAPSInt(S.Stk, ArgT);1645    }1646 1647    if (Val.isZero()) {1648      if (ZeroVal) {1649        pushInteger(S, *ZeroVal, Call->getType());1650        return true;1651      }1652      // If we haven't been provided the second argument, the result is1653      // undefined1654      S.FFDiag(S.Current->getSource(OpPC),1655               diag::note_constexpr_countzeroes_zero)1656          << /*IsTrailing=*/IsCTTZ;1657      return false;1658    }1659 1660    if (BuiltinID == Builtin::BI__builtin_elementwise_clzg) {1661      pushInteger(S, Val.countLeadingZeros(), Call->getType());1662    } else {1663      pushInteger(S, Val.countTrailingZeros(), Call->getType());1664    }1665    return true;1666  }1667  // Otherwise, the argument must be a vector.1668  const ASTContext &ASTCtx = S.getASTContext();1669  Pointer ZeroArg;1670  if (HasZeroArg) {1671    assert(Call->getArg(1)->getType()->isVectorType() &&1672           ASTCtx.hasSameUnqualifiedType(Call->getArg(0)->getType(),1673                                         Call->getArg(1)->getType()));1674    (void)ASTCtx;1675    ZeroArg = S.Stk.pop<Pointer>();1676    assert(ZeroArg.getFieldDesc()->isPrimitiveArray());1677  }1678  assert(Call->getArg(0)->getType()->isVectorType());1679  const Pointer &Arg = S.Stk.pop<Pointer>();1680  assert(Arg.getFieldDesc()->isPrimitiveArray());1681  const Pointer &Dst = S.Stk.peek<Pointer>();1682  assert(Dst.getFieldDesc()->isPrimitiveArray());1683  assert(Arg.getFieldDesc()->getNumElems() ==1684         Dst.getFieldDesc()->getNumElems());1685 1686  QualType ElemType = Arg.getFieldDesc()->getElemQualType();1687  PrimType ElemT = *S.getContext().classify(ElemType);1688  unsigned NumElems = Arg.getNumElems();1689 1690  // FIXME: Reading from uninitialized vector elements?1691  for (unsigned I = 0; I != NumElems; ++I) {1692    INT_TYPE_SWITCH_NO_BOOL(ElemT, {1693      APInt EltVal = Arg.atIndex(I).deref<T>().toAPSInt();1694      if (EltVal.isZero()) {1695        if (HasZeroArg) {1696          Dst.atIndex(I).deref<T>() = ZeroArg.atIndex(I).deref<T>();1697        } else {1698          // If we haven't been provided the second argument, the result is1699          // undefined1700          S.FFDiag(S.Current->getSource(OpPC),1701                   diag::note_constexpr_countzeroes_zero)1702              << /*IsTrailing=*/IsCTTZ;1703          return false;1704        }1705      } else if (IsCTTZ) {1706        Dst.atIndex(I).deref<T>() = T::from(EltVal.countTrailingZeros());1707      } else {1708        Dst.atIndex(I).deref<T>() = T::from(EltVal.countLeadingZeros());1709      }1710      Dst.atIndex(I).initialize();1711    });1712  }1713 1714  return true;1715}1716 1717static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,1718                                   const InterpFrame *Frame,1719                                   const CallExpr *Call, unsigned ID) {1720  assert(Call->getNumArgs() == 3);1721  const ASTContext &ASTCtx = S.getASTContext();1722  APSInt Size = popToAPSInt(S, Call->getArg(2));1723  Pointer SrcPtr = S.Stk.pop<Pointer>().expand();1724  Pointer DestPtr = S.Stk.pop<Pointer>().expand();1725 1726  assert(!Size.isSigned() && "memcpy and friends take an unsigned size");1727 1728  if (ID == Builtin::BImemcpy || ID == Builtin::BImemmove)1729    diagnoseNonConstexprBuiltin(S, OpPC, ID);1730 1731  bool Move =1732      (ID == Builtin::BI__builtin_memmove || ID == Builtin::BImemmove ||1733       ID == Builtin::BI__builtin_wmemmove || ID == Builtin::BIwmemmove);1734  bool WChar = ID == Builtin::BIwmemcpy || ID == Builtin::BIwmemmove ||1735               ID == Builtin::BI__builtin_wmemcpy ||1736               ID == Builtin::BI__builtin_wmemmove;1737 1738  // If the size is zero, we treat this as always being a valid no-op.1739  if (Size.isZero()) {1740    S.Stk.push<Pointer>(DestPtr);1741    return true;1742  }1743 1744  if (SrcPtr.isZero() || DestPtr.isZero()) {1745    Pointer DiagPtr = (SrcPtr.isZero() ? SrcPtr : DestPtr);1746    S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)1747        << /*IsMove=*/Move << /*IsWchar=*/WChar << !SrcPtr.isZero()1748        << DiagPtr.toDiagnosticString(ASTCtx);1749    return false;1750  }1751 1752  // Diagnose integral src/dest pointers specially.1753  if (SrcPtr.isIntegralPointer() || DestPtr.isIntegralPointer()) {1754    std::string DiagVal = "(void *)";1755    DiagVal += SrcPtr.isIntegralPointer()1756                   ? std::to_string(SrcPtr.getIntegerRepresentation())1757                   : std::to_string(DestPtr.getIntegerRepresentation());1758    S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)1759        << Move << WChar << DestPtr.isIntegralPointer() << DiagVal;1760    return false;1761  }1762 1763  // Can't read from dummy pointers.1764  if (DestPtr.isDummy() || SrcPtr.isDummy())1765    return false;1766 1767  if (DestPtr.getType()->isIncompleteType()) {1768    S.FFDiag(S.Current->getSource(OpPC),1769             diag::note_constexpr_memcpy_incomplete_type)1770        << Move << DestPtr.getType();1771    return false;1772  }1773  if (SrcPtr.getType()->isIncompleteType()) {1774    S.FFDiag(S.Current->getSource(OpPC),1775             diag::note_constexpr_memcpy_incomplete_type)1776        << Move << SrcPtr.getType();1777    return false;1778  }1779 1780  QualType DestElemType = getElemType(DestPtr);1781  if (DestElemType->isIncompleteType()) {1782    S.FFDiag(S.Current->getSource(OpPC),1783             diag::note_constexpr_memcpy_incomplete_type)1784        << Move << DestElemType;1785    return false;1786  }1787 1788  size_t RemainingDestElems;1789  if (DestPtr.getFieldDesc()->isArray()) {1790    RemainingDestElems = DestPtr.isUnknownSizeArray()1791                             ? 01792                             : (DestPtr.getNumElems() - DestPtr.getIndex());1793  } else {1794    RemainingDestElems = 1;1795  }1796  unsigned DestElemSize = ASTCtx.getTypeSizeInChars(DestElemType).getQuantity();1797 1798  if (WChar) {1799    uint64_t WCharSize =1800        ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();1801    Size *= APSInt(APInt(Size.getBitWidth(), WCharSize, /*IsSigned=*/false),1802                   /*IsUnsigend=*/true);1803  }1804 1805  if (Size.urem(DestElemSize) != 0) {1806    S.FFDiag(S.Current->getSource(OpPC),1807             diag::note_constexpr_memcpy_unsupported)1808        << Move << WChar << 0 << DestElemType << Size << DestElemSize;1809    return false;1810  }1811 1812  QualType SrcElemType = getElemType(SrcPtr);1813  size_t RemainingSrcElems;1814  if (SrcPtr.getFieldDesc()->isArray()) {1815    RemainingSrcElems = SrcPtr.isUnknownSizeArray()1816                            ? 01817                            : (SrcPtr.getNumElems() - SrcPtr.getIndex());1818  } else {1819    RemainingSrcElems = 1;1820  }1821  unsigned SrcElemSize = ASTCtx.getTypeSizeInChars(SrcElemType).getQuantity();1822 1823  if (!ASTCtx.hasSameUnqualifiedType(DestElemType, SrcElemType)) {1824    S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_type_pun)1825        << Move << SrcElemType << DestElemType;1826    return false;1827  }1828 1829  if (!DestElemType.isTriviallyCopyableType(ASTCtx)) {1830    S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_nontrivial)1831        << Move << DestElemType;1832    return false;1833  }1834 1835  // Check if we have enough elements to read from and write to.1836  size_t RemainingDestBytes = RemainingDestElems * DestElemSize;1837  size_t RemainingSrcBytes = RemainingSrcElems * SrcElemSize;1838  if (Size.ugt(RemainingDestBytes) || Size.ugt(RemainingSrcBytes)) {1839    APInt N = Size.udiv(DestElemSize);1840    S.FFDiag(S.Current->getSource(OpPC),1841             diag::note_constexpr_memcpy_unsupported)1842        << Move << WChar << (Size.ugt(RemainingSrcBytes) ? 1 : 2)1843        << DestElemType << toString(N, 10, /*Signed=*/false);1844    return false;1845  }1846 1847  // Check for overlapping memory regions.1848  if (!Move && Pointer::pointToSameBlock(SrcPtr, DestPtr)) {1849    // Remove base casts.1850    Pointer SrcP = SrcPtr;1851    while (SrcP.isBaseClass())1852      SrcP = SrcP.getBase();1853 1854    Pointer DestP = DestPtr;1855    while (DestP.isBaseClass())1856      DestP = DestP.getBase();1857 1858    unsigned SrcIndex = SrcP.expand().getIndex() * SrcP.elemSize();1859    unsigned DstIndex = DestP.expand().getIndex() * DestP.elemSize();1860    unsigned N = Size.getZExtValue();1861 1862    if ((SrcIndex <= DstIndex && (SrcIndex + N) > DstIndex) ||1863        (DstIndex <= SrcIndex && (DstIndex + N) > SrcIndex)) {1864      S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_overlap)1865          << /*IsWChar=*/false;1866      return false;1867    }1868  }1869 1870  assert(Size.getZExtValue() % DestElemSize == 0);1871  if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size.getZExtValue()).toBits()))1872    return false;1873 1874  S.Stk.push<Pointer>(DestPtr);1875  return true;1876}1877 1878/// Determine if T is a character type for which we guarantee that1879/// sizeof(T) == 1.1880static bool isOneByteCharacterType(QualType T) {1881  return T->isCharType() || T->isChar8Type();1882}1883 1884static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,1885                                   const InterpFrame *Frame,1886                                   const CallExpr *Call, unsigned ID) {1887  assert(Call->getNumArgs() == 3);1888  const APSInt &Size = popToAPSInt(S, Call->getArg(2));1889  const Pointer &PtrB = S.Stk.pop<Pointer>();1890  const Pointer &PtrA = S.Stk.pop<Pointer>();1891 1892  if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp ||1893      ID == Builtin::BIwmemcmp)1894    diagnoseNonConstexprBuiltin(S, OpPC, ID);1895 1896  if (Size.isZero()) {1897    pushInteger(S, 0, Call->getType());1898    return true;1899  }1900 1901  if (!PtrA.isBlockPointer() || !PtrB.isBlockPointer())1902    return false;1903 1904  bool IsWide =1905      (ID == Builtin::BIwmemcmp || ID == Builtin::BI__builtin_wmemcmp);1906 1907  const ASTContext &ASTCtx = S.getASTContext();1908  QualType ElemTypeA = getElemType(PtrA);1909  QualType ElemTypeB = getElemType(PtrB);1910  // FIXME: This is an arbitrary limitation the current constant interpreter1911  // had. We could remove this.1912  if (!IsWide && (!isOneByteCharacterType(ElemTypeA) ||1913                  !isOneByteCharacterType(ElemTypeB))) {1914    S.FFDiag(S.Current->getSource(OpPC),1915             diag::note_constexpr_memcmp_unsupported)1916        << ASTCtx.BuiltinInfo.getQuotedName(ID) << PtrA.getType()1917        << PtrB.getType();1918    return false;1919  }1920 1921  if (PtrA.isDummy() || PtrB.isDummy())1922    return false;1923 1924  if (!CheckRange(S, OpPC, PtrA, AK_Read) ||1925      !CheckRange(S, OpPC, PtrB, AK_Read))1926    return false;1927 1928  // Now, read both pointers to a buffer and compare those.1929  BitcastBuffer BufferA(1930      Bits(ASTCtx.getTypeSize(ElemTypeA) * PtrA.getNumElems()));1931  readPointerToBuffer(S.getContext(), PtrA, BufferA, false);1932  // FIXME: The swapping here is UNDOING something we do when reading the1933  // data into the buffer.1934  if (ASTCtx.getTargetInfo().isBigEndian())1935    swapBytes(BufferA.Data.get(), BufferA.byteSize().getQuantity());1936 1937  BitcastBuffer BufferB(1938      Bits(ASTCtx.getTypeSize(ElemTypeB) * PtrB.getNumElems()));1939  readPointerToBuffer(S.getContext(), PtrB, BufferB, false);1940  // FIXME: The swapping here is UNDOING something we do when reading the1941  // data into the buffer.1942  if (ASTCtx.getTargetInfo().isBigEndian())1943    swapBytes(BufferB.Data.get(), BufferB.byteSize().getQuantity());1944 1945  size_t MinBufferSize = std::min(BufferA.byteSize().getQuantity(),1946                                  BufferB.byteSize().getQuantity());1947 1948  unsigned ElemSize = 1;1949  if (IsWide)1950    ElemSize = ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();1951  // The Size given for the wide variants is in wide-char units. Convert it1952  // to bytes.1953  size_t ByteSize = Size.getZExtValue() * ElemSize;1954  size_t CmpSize = std::min(MinBufferSize, ByteSize);1955 1956  for (size_t I = 0; I != CmpSize; I += ElemSize) {1957    if (IsWide) {1958      INT_TYPE_SWITCH(*S.getContext().classify(ASTCtx.getWCharType()), {1959        T A = *reinterpret_cast<T *>(BufferA.atByte(I));1960        T B = *reinterpret_cast<T *>(BufferB.atByte(I));1961        if (A < B) {1962          pushInteger(S, -1, Call->getType());1963          return true;1964        }1965        if (A > B) {1966          pushInteger(S, 1, Call->getType());1967          return true;1968        }1969      });1970    } else {1971      std::byte A = BufferA.deref<std::byte>(Bytes(I));1972      std::byte B = BufferB.deref<std::byte>(Bytes(I));1973 1974      if (A < B) {1975        pushInteger(S, -1, Call->getType());1976        return true;1977      }1978      if (A > B) {1979        pushInteger(S, 1, Call->getType());1980        return true;1981      }1982    }1983  }1984 1985  // We compared CmpSize bytes above. If the limiting factor was the Size1986  // passed, we're done and the result is equality (0).1987  if (ByteSize <= CmpSize) {1988    pushInteger(S, 0, Call->getType());1989    return true;1990  }1991 1992  // However, if we read all the available bytes but were instructed to read1993  // even more, diagnose this as a "read of dereferenced one-past-the-end1994  // pointer". This is what would happen if we called CheckLoad() on every array1995  // element.1996  S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)1997      << AK_Read << S.Current->getRange(OpPC);1998  return false;1999}2000 2001// __builtin_memchr(ptr, int, int)2002// __builtin_strchr(ptr, int)2003static bool interp__builtin_memchr(InterpState &S, CodePtr OpPC,2004                                   const CallExpr *Call, unsigned ID) {2005  if (ID == Builtin::BImemchr || ID == Builtin::BIwcschr ||2006      ID == Builtin::BIstrchr || ID == Builtin::BIwmemchr)2007    diagnoseNonConstexprBuiltin(S, OpPC, ID);2008 2009  std::optional<APSInt> MaxLength;2010  if (Call->getNumArgs() == 3)2011    MaxLength = popToAPSInt(S, Call->getArg(2));2012 2013  APSInt Desired = popToAPSInt(S, Call->getArg(1));2014  const Pointer &Ptr = S.Stk.pop<Pointer>();2015 2016  if (MaxLength && MaxLength->isZero()) {2017    S.Stk.push<Pointer>();2018    return true;2019  }2020 2021  if (Ptr.isDummy()) {2022    if (Ptr.getType()->isIncompleteType())2023      S.FFDiag(S.Current->getSource(OpPC),2024               diag::note_constexpr_ltor_incomplete_type)2025          << Ptr.getType();2026    return false;2027  }2028 2029  // Null is only okay if the given size is 0.2030  if (Ptr.isZero()) {2031    S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)2032        << AK_Read;2033    return false;2034  }2035 2036  QualType ElemTy = Ptr.getFieldDesc()->isArray()2037                        ? Ptr.getFieldDesc()->getElemQualType()2038                        : Ptr.getFieldDesc()->getType();2039  bool IsRawByte = ID == Builtin::BImemchr || ID == Builtin::BI__builtin_memchr;2040 2041  // Give up on byte-oriented matching against multibyte elements.2042  if (IsRawByte && !isOneByteCharacterType(ElemTy)) {2043    S.FFDiag(S.Current->getSource(OpPC),2044             diag::note_constexpr_memchr_unsupported)2045        << S.getASTContext().BuiltinInfo.getQuotedName(ID) << ElemTy;2046    return false;2047  }2048 2049  if (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr) {2050    int64_t DesiredTrunc;2051    if (S.getASTContext().CharTy->isSignedIntegerType())2052      DesiredTrunc =2053          Desired.trunc(S.getASTContext().getCharWidth()).getSExtValue();2054    else2055      DesiredTrunc =2056          Desired.trunc(S.getASTContext().getCharWidth()).getZExtValue();2057    // strchr compares directly to the passed integer, and therefore2058    // always fails if given an int that is not a char.2059    if (Desired != DesiredTrunc) {2060      S.Stk.push<Pointer>();2061      return true;2062    }2063  }2064 2065  uint64_t DesiredVal;2066  if (ID == Builtin::BIwmemchr || ID == Builtin::BI__builtin_wmemchr ||2067      ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr) {2068    // wcschr and wmemchr are given a wchar_t to look for. Just use it.2069    DesiredVal = Desired.getZExtValue();2070  } else {2071    DesiredVal = Desired.trunc(S.getASTContext().getCharWidth()).getZExtValue();2072  }2073 2074  bool StopAtZero =2075      (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr ||2076       ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr);2077 2078  PrimType ElemT =2079      IsRawByte ? PT_Sint8 : *S.getContext().classify(getElemType(Ptr));2080 2081  size_t Index = Ptr.getIndex();2082  size_t Step = 0;2083  for (;;) {2084    const Pointer &ElemPtr =2085        (Index + Step) > 0 ? Ptr.atIndex(Index + Step) : Ptr;2086 2087    if (!CheckLoad(S, OpPC, ElemPtr))2088      return false;2089 2090    uint64_t V;2091    INT_TYPE_SWITCH_NO_BOOL(2092        ElemT, { V = static_cast<uint64_t>(ElemPtr.deref<T>().toUnsigned()); });2093 2094    if (V == DesiredVal) {2095      S.Stk.push<Pointer>(ElemPtr);2096      return true;2097    }2098 2099    if (StopAtZero && V == 0)2100      break;2101 2102    ++Step;2103    if (MaxLength && Step == MaxLength->getZExtValue())2104      break;2105  }2106 2107  S.Stk.push<Pointer>();2108  return true;2109}2110 2111static std::optional<unsigned> computeFullDescSize(const ASTContext &ASTCtx,2112                                                   const Descriptor *Desc) {2113  if (Desc->isPrimitive())2114    return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();2115  if (Desc->isArray())2116    return ASTCtx.getTypeSizeInChars(Desc->getElemQualType()).getQuantity() *2117           Desc->getNumElems();2118  if (Desc->isRecord()) {2119    // Can't use Descriptor::getType() as that may return a pointer type. Look2120    // at the decl directly.2121    return ASTCtx2122        .getTypeSizeInChars(2123            ASTCtx.getCanonicalTagType(Desc->ElemRecord->getDecl()))2124        .getQuantity();2125  }2126 2127  return std::nullopt;2128}2129 2130/// Compute the byte offset of \p Ptr in the full declaration.2131static unsigned computePointerOffset(const ASTContext &ASTCtx,2132                                     const Pointer &Ptr) {2133  unsigned Result = 0;2134 2135  Pointer P = Ptr;2136  while (P.isField() || P.isArrayElement()) {2137    P = P.expand();2138    const Descriptor *D = P.getFieldDesc();2139 2140    if (P.isArrayElement()) {2141      unsigned ElemSize =2142          ASTCtx.getTypeSizeInChars(D->getElemQualType()).getQuantity();2143      if (P.isOnePastEnd())2144        Result += ElemSize * P.getNumElems();2145      else2146        Result += ElemSize * P.getIndex();2147      P = P.expand().getArray();2148    } else if (P.isBaseClass()) {2149      const auto *RD = cast<CXXRecordDecl>(D->asDecl());2150      bool IsVirtual = Ptr.isVirtualBaseClass();2151      P = P.getBase();2152      const Record *BaseRecord = P.getRecord();2153 2154      const ASTRecordLayout &Layout =2155          ASTCtx.getASTRecordLayout(cast<CXXRecordDecl>(BaseRecord->getDecl()));2156      if (IsVirtual)2157        Result += Layout.getVBaseClassOffset(RD).getQuantity();2158      else2159        Result += Layout.getBaseClassOffset(RD).getQuantity();2160    } else if (P.isField()) {2161      const FieldDecl *FD = P.getField();2162      const ASTRecordLayout &Layout =2163          ASTCtx.getASTRecordLayout(FD->getParent());2164      unsigned FieldIndex = FD->getFieldIndex();2165      uint64_t FieldOffset =2166          ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex))2167              .getQuantity();2168      Result += FieldOffset;2169      P = P.getBase();2170    } else2171      llvm_unreachable("Unhandled descriptor type");2172  }2173 2174  return Result;2175}2176 2177/// Does Ptr point to the last subobject?2178static bool pointsToLastObject(const Pointer &Ptr) {2179  Pointer P = Ptr;2180  while (!P.isRoot()) {2181 2182    if (P.isArrayElement()) {2183      P = P.expand().getArray();2184      continue;2185    }2186    if (P.isBaseClass()) {2187      if (P.getRecord()->getNumFields() > 0)2188        return false;2189      P = P.getBase();2190      continue;2191    }2192 2193    Pointer Base = P.getBase();2194    if (const Record *R = Base.getRecord()) {2195      assert(P.getField());2196      if (P.getField()->getFieldIndex() != R->getNumFields() - 1)2197        return false;2198    }2199    P = Base;2200  }2201 2202  return true;2203}2204 2205/// Does Ptr point to the last object AND to a flexible array member?2206static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const Pointer &Ptr) {2207  auto isFlexibleArrayMember = [&](const Descriptor *FieldDesc) {2208    using FAMKind = LangOptions::StrictFlexArraysLevelKind;2209    FAMKind StrictFlexArraysLevel =2210        Ctx.getLangOpts().getStrictFlexArraysLevel();2211 2212    if (StrictFlexArraysLevel == FAMKind::Default)2213      return true;2214 2215    unsigned NumElems = FieldDesc->getNumElems();2216    if (NumElems == 0 && StrictFlexArraysLevel != FAMKind::IncompleteOnly)2217      return true;2218 2219    if (NumElems == 1 && StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)2220      return true;2221    return false;2222  };2223 2224  const Descriptor *FieldDesc = Ptr.getFieldDesc();2225  if (!FieldDesc->isArray())2226    return false;2227 2228  return Ptr.isDummy() && pointsToLastObject(Ptr) &&2229         isFlexibleArrayMember(FieldDesc);2230}2231 2232static bool interp__builtin_object_size(InterpState &S, CodePtr OpPC,2233                                        const InterpFrame *Frame,2234                                        const CallExpr *Call) {2235  const ASTContext &ASTCtx = S.getASTContext();2236  // From the GCC docs:2237  // Kind is an integer constant from 0 to 3. If the least significant bit is2238  // clear, objects are whole variables. If it is set, a closest surrounding2239  // subobject is considered the object a pointer points to. The second bit2240  // determines if maximum or minimum of remaining bytes is computed.2241  unsigned Kind = popToAPSInt(S, Call->getArg(1)).getZExtValue();2242  assert(Kind <= 3 && "unexpected kind");2243  bool UseFieldDesc = (Kind & 1u);2244  bool ReportMinimum = (Kind & 2u);2245  const Pointer &Ptr = S.Stk.pop<Pointer>();2246 2247  if (Call->getArg(0)->HasSideEffects(ASTCtx)) {2248    // "If there are any side effects in them, it returns (size_t) -12249    // for type 0 or 1 and (size_t) 0 for type 2 or 3."2250    pushInteger(S, Kind <= 1 ? -1 : 0, Call->getType());2251    return true;2252  }2253 2254  if (Ptr.isZero() || !Ptr.isBlockPointer())2255    return false;2256 2257  // We can't load through pointers.2258  if (Ptr.isDummy() && Ptr.getType()->isPointerType())2259    return false;2260 2261  bool DetermineForCompleteObject = Ptr.getFieldDesc() == Ptr.getDeclDesc();2262  const Descriptor *DeclDesc = Ptr.getDeclDesc();2263  assert(DeclDesc);2264 2265  if (!UseFieldDesc || DetermineForCompleteObject) {2266    // Lower bound, so we can't fall back to this.2267    if (ReportMinimum && !DetermineForCompleteObject)2268      return false;2269 2270    // Can't read beyond the pointer decl desc.2271    if (!UseFieldDesc && !ReportMinimum && DeclDesc->getType()->isPointerType())2272      return false;2273  } else {2274    if (isUserWritingOffTheEnd(ASTCtx, Ptr.expand())) {2275      // If we cannot determine the size of the initial allocation, then we2276      // can't given an accurate upper-bound. However, we are still able to give2277      // conservative lower-bounds for Type=3.2278      if (Kind == 1)2279        return false;2280    }2281  }2282 2283  const Descriptor *Desc = UseFieldDesc ? Ptr.getFieldDesc() : DeclDesc;2284  assert(Desc);2285 2286  std::optional<unsigned> FullSize = computeFullDescSize(ASTCtx, Desc);2287  if (!FullSize)2288    return false;2289 2290  unsigned ByteOffset;2291  if (UseFieldDesc) {2292    if (Ptr.isBaseClass())2293      ByteOffset = computePointerOffset(ASTCtx, Ptr.getBase()) -2294                   computePointerOffset(ASTCtx, Ptr);2295    else {2296      if (Ptr.inArray())2297        ByteOffset =2298            computePointerOffset(ASTCtx, Ptr) -2299            computePointerOffset(ASTCtx, Ptr.expand().atIndex(0).narrow());2300      else2301        ByteOffset = 0;2302    }2303  } else2304    ByteOffset = computePointerOffset(ASTCtx, Ptr);2305 2306  assert(ByteOffset <= *FullSize);2307  unsigned Result = *FullSize - ByteOffset;2308 2309  pushInteger(S, Result, Call->getType());2310  return true;2311}2312 2313static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,2314                                               const CallExpr *Call) {2315 2316  if (!S.inConstantContext())2317    return false;2318 2319  const Pointer &Ptr = S.Stk.pop<Pointer>();2320 2321  auto Error = [&](int Diag) {2322    bool CalledFromStd = false;2323    const auto *Callee = S.Current->getCallee();2324    if (Callee && Callee->isInStdNamespace()) {2325      const IdentifierInfo *Identifier = Callee->getIdentifier();2326      CalledFromStd = Identifier && Identifier->isStr("is_within_lifetime");2327    }2328    S.CCEDiag(CalledFromStd2329                  ? S.Current->Caller->getSource(S.Current->getRetPC())2330                  : S.Current->getSource(OpPC),2331              diag::err_invalid_is_within_lifetime)2332        << (CalledFromStd ? "std::is_within_lifetime"2333                          : "__builtin_is_within_lifetime")2334        << Diag;2335    return false;2336  };2337 2338  if (Ptr.isZero())2339    return Error(0);2340  if (Ptr.isOnePastEnd())2341    return Error(1);2342 2343  bool Result = Ptr.getLifetime() != Lifetime::Ended;2344  if (!Ptr.isActive()) {2345    Result = false;2346  } else {2347    if (!CheckLive(S, OpPC, Ptr, AK_Read))2348      return false;2349    if (!CheckMutable(S, OpPC, Ptr))2350      return false;2351    if (!CheckDummy(S, OpPC, Ptr.block(), AK_Read))2352      return false;2353  }2354 2355  // Check if we're currently running an initializer.2356  if (llvm::is_contained(S.InitializingBlocks, Ptr.block()))2357    return Error(2);2358  if (S.EvaluatingDecl && Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl)2359    return Error(2);2360 2361  pushInteger(S, Result, Call->getType());2362  return true;2363}2364 2365static bool interp__builtin_elementwise_int_unaryop(2366    InterpState &S, CodePtr OpPC, const CallExpr *Call,2367    llvm::function_ref<APInt(const APSInt &)> Fn) {2368  assert(Call->getNumArgs() == 1);2369 2370  // Single integer case.2371  if (!Call->getArg(0)->getType()->isVectorType()) {2372    assert(Call->getType()->isIntegerType());2373    APSInt Src = popToAPSInt(S, Call->getArg(0));2374    APInt Result = Fn(Src);2375    pushInteger(S, APSInt(std::move(Result), !Src.isSigned()), Call->getType());2376    return true;2377  }2378 2379  // Vector case.2380  const Pointer &Arg = S.Stk.pop<Pointer>();2381  assert(Arg.getFieldDesc()->isPrimitiveArray());2382  const Pointer &Dst = S.Stk.peek<Pointer>();2383  assert(Dst.getFieldDesc()->isPrimitiveArray());2384  assert(Arg.getFieldDesc()->getNumElems() ==2385         Dst.getFieldDesc()->getNumElems());2386 2387  QualType ElemType = Arg.getFieldDesc()->getElemQualType();2388  PrimType ElemT = *S.getContext().classify(ElemType);2389  unsigned NumElems = Arg.getNumElems();2390  bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();2391 2392  for (unsigned I = 0; I != NumElems; ++I) {2393    INT_TYPE_SWITCH_NO_BOOL(ElemT, {2394      APSInt Src = Arg.elem<T>(I).toAPSInt();2395      APInt Result = Fn(Src);2396      Dst.elem<T>(I) = static_cast<T>(APSInt(std::move(Result), DestUnsigned));2397    });2398  }2399  Dst.initializeAllElements();2400 2401  return true;2402}2403 2404static bool interp__builtin_elementwise_int_binop(2405    InterpState &S, CodePtr OpPC, const CallExpr *Call,2406    llvm::function_ref<APInt(const APSInt &, const APSInt &)> Fn) {2407  assert(Call->getNumArgs() == 2);2408 2409  // Single integer case.2410  if (!Call->getArg(0)->getType()->isVectorType()) {2411    assert(!Call->getArg(1)->getType()->isVectorType());2412    APSInt RHS = popToAPSInt(S, Call->getArg(1));2413    APSInt LHS = popToAPSInt(S, Call->getArg(0));2414    APInt Result = Fn(LHS, RHS);2415    pushInteger(S, APSInt(std::move(Result), !LHS.isSigned()), Call->getType());2416    return true;2417  }2418 2419  const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();2420  assert(VT->getElementType()->isIntegralOrEnumerationType());2421  PrimType ElemT = *S.getContext().classify(VT->getElementType());2422  unsigned NumElems = VT->getNumElements();2423  bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();2424 2425  // Vector + Scalar case.2426  if (!Call->getArg(1)->getType()->isVectorType()) {2427    assert(Call->getArg(1)->getType()->isIntegralOrEnumerationType());2428 2429    APSInt RHS = popToAPSInt(S, Call->getArg(1));2430    const Pointer &LHS = S.Stk.pop<Pointer>();2431    const Pointer &Dst = S.Stk.peek<Pointer>();2432 2433    for (unsigned I = 0; I != NumElems; ++I) {2434      INT_TYPE_SWITCH_NO_BOOL(ElemT, {2435        Dst.elem<T>(I) = static_cast<T>(2436            APSInt(Fn(LHS.elem<T>(I).toAPSInt(), RHS), DestUnsigned));2437      });2438    }2439    Dst.initializeAllElements();2440    return true;2441  }2442 2443  // Vector case.2444  assert(Call->getArg(0)->getType()->isVectorType() &&2445         Call->getArg(1)->getType()->isVectorType());2446  assert(VT->getElementType() ==2447         Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());2448  assert(VT->getNumElements() ==2449         Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());2450  assert(VT->getElementType()->isIntegralOrEnumerationType());2451 2452  const Pointer &RHS = S.Stk.pop<Pointer>();2453  const Pointer &LHS = S.Stk.pop<Pointer>();2454  const Pointer &Dst = S.Stk.peek<Pointer>();2455  for (unsigned I = 0; I != NumElems; ++I) {2456    INT_TYPE_SWITCH_NO_BOOL(ElemT, {2457      APSInt Elem1 = LHS.elem<T>(I).toAPSInt();2458      APSInt Elem2 = RHS.elem<T>(I).toAPSInt();2459      Dst.elem<T>(I) = static_cast<T>(APSInt(Fn(Elem1, Elem2), DestUnsigned));2460    });2461  }2462  Dst.initializeAllElements();2463 2464  return true;2465}2466 2467static bool2468interp__builtin_x86_pack(InterpState &S, CodePtr, const CallExpr *E,2469                         llvm::function_ref<APInt(const APSInt &)> PackFn) {2470  const auto *VT0 = E->getArg(0)->getType()->castAs<VectorType>();2471  [[maybe_unused]] const auto *VT1 =2472      E->getArg(1)->getType()->castAs<VectorType>();2473  assert(VT0 && VT1 && "pack builtin VT0 and VT1 must be VectorType");2474  assert(VT0->getElementType() == VT1->getElementType() &&2475         VT0->getNumElements() == VT1->getNumElements() &&2476         "pack builtin VT0 and VT1 ElementType must be same");2477 2478  const Pointer &RHS = S.Stk.pop<Pointer>();2479  const Pointer &LHS = S.Stk.pop<Pointer>();2480  const Pointer &Dst = S.Stk.peek<Pointer>();2481 2482  const ASTContext &ASTCtx = S.getASTContext();2483  unsigned SrcBits = ASTCtx.getIntWidth(VT0->getElementType());2484  unsigned LHSVecLen = VT0->getNumElements();2485  unsigned SrcPerLane = 128 / SrcBits;2486  unsigned Lanes = LHSVecLen * SrcBits / 128;2487 2488  PrimType SrcT = *S.getContext().classify(VT0->getElementType());2489  PrimType DstT = *S.getContext().classify(getElemType(Dst));2490  bool IsUnsigend = getElemType(Dst)->isUnsignedIntegerType();2491 2492  for (unsigned Lane = 0; Lane != Lanes; ++Lane) {2493    unsigned BaseSrc = Lane * SrcPerLane;2494    unsigned BaseDst = Lane * (2 * SrcPerLane);2495 2496    for (unsigned I = 0; I != SrcPerLane; ++I) {2497      INT_TYPE_SWITCH_NO_BOOL(SrcT, {2498        APSInt A = LHS.elem<T>(BaseSrc + I).toAPSInt();2499        APSInt B = RHS.elem<T>(BaseSrc + I).toAPSInt();2500 2501        assignInteger(S, Dst.atIndex(BaseDst + I), DstT,2502                      APSInt(PackFn(A), IsUnsigend));2503        assignInteger(S, Dst.atIndex(BaseDst + SrcPerLane + I), DstT,2504                      APSInt(PackFn(B), IsUnsigend));2505      });2506    }2507  }2508 2509  Dst.initializeAllElements();2510  return true;2511}2512 2513static bool interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC,2514                                               const CallExpr *Call,2515                                               unsigned BuiltinID) {2516  assert(Call->getNumArgs() == 2);2517 2518  QualType Arg0Type = Call->getArg(0)->getType();2519 2520  // TODO: Support floating-point types.2521  if (!(Arg0Type->isIntegerType() ||2522        (Arg0Type->isVectorType() &&2523         Arg0Type->castAs<VectorType>()->getElementType()->isIntegerType())))2524    return false;2525 2526  if (!Arg0Type->isVectorType()) {2527    assert(!Call->getArg(1)->getType()->isVectorType());2528    APSInt RHS = popToAPSInt(S, Call->getArg(1));2529    APSInt LHS = popToAPSInt(S, Arg0Type);2530    APInt Result;2531    if (BuiltinID == Builtin::BI__builtin_elementwise_max) {2532      Result = std::max(LHS, RHS);2533    } else if (BuiltinID == Builtin::BI__builtin_elementwise_min) {2534      Result = std::min(LHS, RHS);2535    } else {2536      llvm_unreachable("Wrong builtin ID");2537    }2538 2539    pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType());2540    return true;2541  }2542 2543  // Vector case.2544  assert(Call->getArg(0)->getType()->isVectorType() &&2545         Call->getArg(1)->getType()->isVectorType());2546  const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();2547  assert(VT->getElementType() ==2548         Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());2549  assert(VT->getNumElements() ==2550         Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());2551  assert(VT->getElementType()->isIntegralOrEnumerationType());2552 2553  const Pointer &RHS = S.Stk.pop<Pointer>();2554  const Pointer &LHS = S.Stk.pop<Pointer>();2555  const Pointer &Dst = S.Stk.peek<Pointer>();2556  PrimType ElemT = *S.getContext().classify(VT->getElementType());2557  unsigned NumElems = VT->getNumElements();2558  for (unsigned I = 0; I != NumElems; ++I) {2559    APSInt Elem1;2560    APSInt Elem2;2561    INT_TYPE_SWITCH_NO_BOOL(ElemT, {2562      Elem1 = LHS.elem<T>(I).toAPSInt();2563      Elem2 = RHS.elem<T>(I).toAPSInt();2564    });2565 2566    APSInt Result;2567    if (BuiltinID == Builtin::BI__builtin_elementwise_max) {2568      Result = APSInt(std::max(Elem1, Elem2),2569                      Call->getType()->isUnsignedIntegerOrEnumerationType());2570    } else if (BuiltinID == Builtin::BI__builtin_elementwise_min) {2571      Result = APSInt(std::min(Elem1, Elem2),2572                      Call->getType()->isUnsignedIntegerOrEnumerationType());2573    } else {2574      llvm_unreachable("Wrong builtin ID");2575    }2576 2577    INT_TYPE_SWITCH_NO_BOOL(ElemT,2578                            { Dst.elem<T>(I) = static_cast<T>(Result); });2579  }2580  Dst.initializeAllElements();2581 2582  return true;2583}2584 2585static bool interp__builtin_ia32_pmul(2586    InterpState &S, CodePtr OpPC, const CallExpr *Call,2587    llvm::function_ref<APInt(const APSInt &, const APSInt &, const APSInt &,2588                             const APSInt &)>2589        Fn) {2590  assert(Call->getArg(0)->getType()->isVectorType() &&2591         Call->getArg(1)->getType()->isVectorType());2592  const Pointer &RHS = S.Stk.pop<Pointer>();2593  const Pointer &LHS = S.Stk.pop<Pointer>();2594  const Pointer &Dst = S.Stk.peek<Pointer>();2595 2596  const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();2597  PrimType ElemT = *S.getContext().classify(VT->getElementType());2598  unsigned NumElems = VT->getNumElements();2599  const auto *DestVT = Call->getType()->castAs<VectorType>();2600  PrimType DestElemT = *S.getContext().classify(DestVT->getElementType());2601  bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();2602 2603  unsigned DstElem = 0;2604  for (unsigned I = 0; I != NumElems; I += 2) {2605    APSInt Result;2606    INT_TYPE_SWITCH_NO_BOOL(ElemT, {2607      APSInt LoLHS = LHS.elem<T>(I).toAPSInt();2608      APSInt HiLHS = LHS.elem<T>(I + 1).toAPSInt();2609      APSInt LoRHS = RHS.elem<T>(I).toAPSInt();2610      APSInt HiRHS = RHS.elem<T>(I + 1).toAPSInt();2611      Result = APSInt(Fn(LoLHS, HiLHS, LoRHS, HiRHS), DestUnsigned);2612    });2613 2614    INT_TYPE_SWITCH_NO_BOOL(DestElemT,2615                            { Dst.elem<T>(DstElem) = static_cast<T>(Result); });2616    ++DstElem;2617  }2618 2619  Dst.initializeAllElements();2620  return true;2621}2622 2623static bool interp_builtin_horizontal_int_binop(2624    InterpState &S, CodePtr OpPC, const CallExpr *Call,2625    llvm::function_ref<APInt(const APSInt &, const APSInt &)> Fn) {2626  const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();2627  PrimType ElemT = *S.getContext().classify(VT->getElementType());2628  bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();2629 2630  const Pointer &RHS = S.Stk.pop<Pointer>();2631  const Pointer &LHS = S.Stk.pop<Pointer>();2632  const Pointer &Dst = S.Stk.peek<Pointer>();2633  unsigned NumElts = VT->getNumElements();2634  unsigned EltBits = S.getASTContext().getIntWidth(VT->getElementType());2635  unsigned EltsPerLane = 128 / EltBits;2636  unsigned Lanes = NumElts * EltBits / 128;2637  unsigned DestIndex = 0;2638 2639  for (unsigned Lane = 0; Lane < Lanes; ++Lane) {2640    unsigned LaneStart = Lane * EltsPerLane;2641    for (unsigned I = 0; I < EltsPerLane; I += 2) {2642      INT_TYPE_SWITCH_NO_BOOL(ElemT, {2643        APSInt Elem1 = LHS.elem<T>(LaneStart + I).toAPSInt();2644        APSInt Elem2 = LHS.elem<T>(LaneStart + I + 1).toAPSInt();2645        APSInt ResL = APSInt(Fn(Elem1, Elem2), DestUnsigned);2646        Dst.elem<T>(DestIndex++) = static_cast<T>(ResL);2647      });2648    }2649 2650    for (unsigned I = 0; I < EltsPerLane; I += 2) {2651      INT_TYPE_SWITCH_NO_BOOL(ElemT, {2652        APSInt Elem1 = RHS.elem<T>(LaneStart + I).toAPSInt();2653        APSInt Elem2 = RHS.elem<T>(LaneStart + I + 1).toAPSInt();2654        APSInt ResR = APSInt(Fn(Elem1, Elem2), DestUnsigned);2655        Dst.elem<T>(DestIndex++) = static_cast<T>(ResR);2656      });2657    }2658  }2659  Dst.initializeAllElements();2660  return true;2661}2662 2663static bool interp_builtin_horizontal_fp_binop(2664    InterpState &S, CodePtr OpPC, const CallExpr *Call,2665    llvm::function_ref<APFloat(const APFloat &, const APFloat &,2666                               llvm::RoundingMode)>2667        Fn) {2668  const Pointer &RHS = S.Stk.pop<Pointer>();2669  const Pointer &LHS = S.Stk.pop<Pointer>();2670  const Pointer &Dst = S.Stk.peek<Pointer>();2671  FPOptions FPO = Call->getFPFeaturesInEffect(S.Ctx.getLangOpts());2672  llvm::RoundingMode RM = getRoundingMode(FPO);2673  const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();2674 2675  unsigned NumElts = VT->getNumElements();2676  unsigned EltBits = S.getASTContext().getTypeSize(VT->getElementType());2677  unsigned NumLanes = NumElts * EltBits / 128;2678  unsigned NumElemsPerLane = NumElts / NumLanes;2679  unsigned HalfElemsPerLane = NumElemsPerLane / 2;2680 2681  for (unsigned L = 0; L != NumElts; L += NumElemsPerLane) {2682    using T = PrimConv<PT_Float>::T;2683    for (unsigned E = 0; E != HalfElemsPerLane; ++E) {2684      APFloat Elem1 = LHS.elem<T>(L + (2 * E) + 0).getAPFloat();2685      APFloat Elem2 = LHS.elem<T>(L + (2 * E) + 1).getAPFloat();2686      Dst.elem<T>(L + E) = static_cast<T>(Fn(Elem1, Elem2, RM));2687    }2688    for (unsigned E = 0; E != HalfElemsPerLane; ++E) {2689      APFloat Elem1 = RHS.elem<T>(L + (2 * E) + 0).getAPFloat();2690      APFloat Elem2 = RHS.elem<T>(L + (2 * E) + 1).getAPFloat();2691      Dst.elem<T>(L + E + HalfElemsPerLane) =2692          static_cast<T>(Fn(Elem1, Elem2, RM));2693    }2694  }2695  Dst.initializeAllElements();2696  return true;2697}2698 2699static bool interp__builtin_ia32_addsub(InterpState &S, CodePtr OpPC,2700                                        const CallExpr *Call) {2701  // Addsub: alternates between subtraction and addition2702  // Result[i] = (i % 2 == 0) ? (a[i] - b[i]) : (a[i] + b[i])2703  const Pointer &RHS = S.Stk.pop<Pointer>();2704  const Pointer &LHS = S.Stk.pop<Pointer>();2705  const Pointer &Dst = S.Stk.peek<Pointer>();2706  FPOptions FPO = Call->getFPFeaturesInEffect(S.Ctx.getLangOpts());2707  llvm::RoundingMode RM = getRoundingMode(FPO);2708  const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();2709  unsigned NumElems = VT->getNumElements();2710 2711  using T = PrimConv<PT_Float>::T;2712  for (unsigned I = 0; I != NumElems; ++I) {2713    APFloat LElem = LHS.elem<T>(I).getAPFloat();2714    APFloat RElem = RHS.elem<T>(I).getAPFloat();2715    if (I % 2 == 0) {2716      // Even indices: subtract2717      LElem.subtract(RElem, RM);2718    } else {2719      // Odd indices: add2720      LElem.add(RElem, RM);2721    }2722    Dst.elem<T>(I) = static_cast<T>(LElem);2723  }2724  Dst.initializeAllElements();2725  return true;2726}2727 2728static bool interp__builtin_elementwise_triop_fp(2729    InterpState &S, CodePtr OpPC, const CallExpr *Call,2730    llvm::function_ref<APFloat(const APFloat &, const APFloat &,2731                               const APFloat &, llvm::RoundingMode)>2732        Fn) {2733  assert(Call->getNumArgs() == 3);2734 2735  FPOptions FPO = Call->getFPFeaturesInEffect(S.Ctx.getLangOpts());2736  llvm::RoundingMode RM = getRoundingMode(FPO);2737  QualType Arg1Type = Call->getArg(0)->getType();2738  QualType Arg2Type = Call->getArg(1)->getType();2739  QualType Arg3Type = Call->getArg(2)->getType();2740 2741  // Non-vector floating point types.2742  if (!Arg1Type->isVectorType()) {2743    assert(!Arg2Type->isVectorType());2744    assert(!Arg3Type->isVectorType());2745    (void)Arg2Type;2746    (void)Arg3Type;2747 2748    const Floating &Z = S.Stk.pop<Floating>();2749    const Floating &Y = S.Stk.pop<Floating>();2750    const Floating &X = S.Stk.pop<Floating>();2751    APFloat F = Fn(X.getAPFloat(), Y.getAPFloat(), Z.getAPFloat(), RM);2752    Floating Result = S.allocFloat(X.getSemantics());2753    Result.copy(F);2754    S.Stk.push<Floating>(Result);2755    return true;2756  }2757 2758  // Vector type.2759  assert(Arg1Type->isVectorType() && Arg2Type->isVectorType() &&2760         Arg3Type->isVectorType());2761 2762  const VectorType *VecTy = Arg1Type->castAs<VectorType>();2763  QualType ElemQT = VecTy->getElementType();2764  unsigned NumElems = VecTy->getNumElements();2765 2766  assert(ElemQT == Arg2Type->castAs<VectorType>()->getElementType() &&2767         ElemQT == Arg3Type->castAs<VectorType>()->getElementType());2768  assert(NumElems == Arg2Type->castAs<VectorType>()->getNumElements() &&2769         NumElems == Arg3Type->castAs<VectorType>()->getNumElements());2770  assert(ElemQT->isRealFloatingType());2771  (void)ElemQT;2772 2773  const Pointer &VZ = S.Stk.pop<Pointer>();2774  const Pointer &VY = S.Stk.pop<Pointer>();2775  const Pointer &VX = S.Stk.pop<Pointer>();2776  const Pointer &Dst = S.Stk.peek<Pointer>();2777  for (unsigned I = 0; I != NumElems; ++I) {2778    using T = PrimConv<PT_Float>::T;2779    APFloat X = VX.elem<T>(I).getAPFloat();2780    APFloat Y = VY.elem<T>(I).getAPFloat();2781    APFloat Z = VZ.elem<T>(I).getAPFloat();2782    APFloat F = Fn(X, Y, Z, RM);2783    Dst.elem<Floating>(I) = Floating(F);2784  }2785  Dst.initializeAllElements();2786  return true;2787}2788 2789/// AVX512 predicated move: "Result = Mask[] ? LHS[] : RHS[]".2790static bool interp__builtin_select(InterpState &S, CodePtr OpPC,2791                                   const CallExpr *Call) {2792  const Pointer &RHS = S.Stk.pop<Pointer>();2793  const Pointer &LHS = S.Stk.pop<Pointer>();2794  APSInt Mask = popToAPSInt(S, Call->getArg(0));2795  const Pointer &Dst = S.Stk.peek<Pointer>();2796 2797  assert(LHS.getNumElems() == RHS.getNumElems());2798  assert(LHS.getNumElems() == Dst.getNumElems());2799  unsigned NumElems = LHS.getNumElems();2800  PrimType ElemT = LHS.getFieldDesc()->getPrimType();2801  PrimType DstElemT = Dst.getFieldDesc()->getPrimType();2802 2803  for (unsigned I = 0; I != NumElems; ++I) {2804    if (ElemT == PT_Float) {2805      assert(DstElemT == PT_Float);2806      Dst.elem<Floating>(I) =2807          Mask[I] ? LHS.elem<Floating>(I) : RHS.elem<Floating>(I);2808    } else {2809      APSInt Elem;2810      INT_TYPE_SWITCH(ElemT, {2811        Elem = Mask[I] ? LHS.elem<T>(I).toAPSInt() : RHS.elem<T>(I).toAPSInt();2812      });2813      INT_TYPE_SWITCH_NO_BOOL(DstElemT,2814                              { Dst.elem<T>(I) = static_cast<T>(Elem); });2815    }2816  }2817  Dst.initializeAllElements();2818 2819  return true;2820}2821 2822/// Scalar variant of AVX512 predicated select:2823/// Result[i] = (Mask bit 0) ? LHS[i] : RHS[i], but only element 0 may change.2824/// All other elements are taken from RHS.2825static bool interp__builtin_select_scalar(InterpState &S,2826                                          const CallExpr *Call) {2827  unsigned N =2828      Call->getArg(1)->getType()->getAs<VectorType>()->getNumElements();2829 2830  const Pointer &W = S.Stk.pop<Pointer>();2831  const Pointer &A = S.Stk.pop<Pointer>();2832  APSInt U = popToAPSInt(S, Call->getArg(0));2833  const Pointer &Dst = S.Stk.peek<Pointer>();2834 2835  bool TakeA0 = U.getZExtValue() & 1ULL;2836 2837  for (unsigned I = TakeA0; I != N; ++I)2838    Dst.elem<Floating>(I) = W.elem<Floating>(I);2839  if (TakeA0)2840    Dst.elem<Floating>(0) = A.elem<Floating>(0);2841 2842  Dst.initializeAllElements();2843  return true;2844}2845 2846static bool interp__builtin_blend(InterpState &S, CodePtr OpPC,2847                                  const CallExpr *Call) {2848  APSInt Mask = popToAPSInt(S, Call->getArg(2));2849  const Pointer &TrueVec = S.Stk.pop<Pointer>();2850  const Pointer &FalseVec = S.Stk.pop<Pointer>();2851  const Pointer &Dst = S.Stk.peek<Pointer>();2852 2853  assert(FalseVec.getNumElems() == TrueVec.getNumElems());2854  assert(FalseVec.getNumElems() == Dst.getNumElems());2855  unsigned NumElems = FalseVec.getNumElems();2856  PrimType ElemT = FalseVec.getFieldDesc()->getPrimType();2857  PrimType DstElemT = Dst.getFieldDesc()->getPrimType();2858 2859  for (unsigned I = 0; I != NumElems; ++I) {2860    bool MaskBit = Mask[I % 8];2861    if (ElemT == PT_Float) {2862      assert(DstElemT == PT_Float);2863      Dst.elem<Floating>(I) =2864          MaskBit ? TrueVec.elem<Floating>(I) : FalseVec.elem<Floating>(I);2865    } else {2866      assert(DstElemT == ElemT);2867      INT_TYPE_SWITCH_NO_BOOL(DstElemT, {2868        Dst.elem<T>(I) =2869            static_cast<T>(MaskBit ? TrueVec.elem<T>(I).toAPSInt()2870                                   : FalseVec.elem<T>(I).toAPSInt());2871      });2872    }2873  }2874  Dst.initializeAllElements();2875 2876  return true;2877}2878 2879static bool interp__builtin_ia32_test_op(2880    InterpState &S, CodePtr OpPC, const CallExpr *Call,2881    llvm::function_ref<bool(const APInt &A, const APInt &B)> Fn) {2882  const Pointer &RHS = S.Stk.pop<Pointer>();2883  const Pointer &LHS = S.Stk.pop<Pointer>();2884 2885  assert(LHS.getNumElems() == RHS.getNumElems());2886 2887  unsigned SourceLen = LHS.getNumElems();2888  QualType ElemQT = getElemType(LHS);2889  OptPrimType ElemPT = S.getContext().classify(ElemQT);2890  unsigned LaneWidth = S.getASTContext().getTypeSize(ElemQT);2891 2892  APInt AWide(LaneWidth * SourceLen, 0);2893  APInt BWide(LaneWidth * SourceLen, 0);2894 2895  for (unsigned I = 0; I != SourceLen; ++I) {2896    APInt ALane;2897    APInt BLane;2898 2899    if (ElemQT->isIntegerType()) { // Get value.2900      INT_TYPE_SWITCH_NO_BOOL(*ElemPT, {2901        ALane = LHS.elem<T>(I).toAPSInt();2902        BLane = RHS.elem<T>(I).toAPSInt();2903      });2904    } else if (ElemQT->isFloatingType()) { // Get only sign bit.2905      using T = PrimConv<PT_Float>::T;2906      ALane = LHS.elem<T>(I).getAPFloat().bitcastToAPInt().isNegative();2907      BLane = RHS.elem<T>(I).getAPFloat().bitcastToAPInt().isNegative();2908    } else { // Must be integer or floating type.2909      return false;2910    }2911    AWide.insertBits(ALane, I * LaneWidth);2912    BWide.insertBits(BLane, I * LaneWidth);2913  }2914  pushInteger(S, Fn(AWide, BWide), Call->getType());2915  return true;2916}2917 2918static bool interp__builtin_ia32_movmsk_op(InterpState &S, CodePtr OpPC,2919                                           const CallExpr *Call) {2920  assert(Call->getNumArgs() == 1);2921 2922  const Pointer &Source = S.Stk.pop<Pointer>();2923 2924  unsigned SourceLen = Source.getNumElems();2925  QualType ElemQT = getElemType(Source);2926  OptPrimType ElemT = S.getContext().classify(ElemQT);2927  unsigned ResultLen =2928      S.getASTContext().getTypeSize(Call->getType()); // Always 32-bit integer.2929  APInt Result(ResultLen, 0);2930 2931  for (unsigned I = 0; I != SourceLen; ++I) {2932    APInt Elem;2933    if (ElemQT->isIntegerType()) {2934      INT_TYPE_SWITCH_NO_BOOL(*ElemT, { Elem = Source.elem<T>(I).toAPSInt(); });2935    } else if (ElemQT->isRealFloatingType()) {2936      using T = PrimConv<PT_Float>::T;2937      Elem = Source.elem<T>(I).getAPFloat().bitcastToAPInt();2938    } else {2939      return false;2940    }2941    Result.setBitVal(I, Elem.isNegative());2942  }2943  pushInteger(S, Result, Call->getType());2944  return true;2945}2946 2947static bool interp__builtin_elementwise_triop(2948    InterpState &S, CodePtr OpPC, const CallExpr *Call,2949    llvm::function_ref<APInt(const APSInt &, const APSInt &, const APSInt &)>2950        Fn) {2951  assert(Call->getNumArgs() == 3);2952 2953  QualType Arg0Type = Call->getArg(0)->getType();2954  QualType Arg2Type = Call->getArg(2)->getType();2955  // Non-vector integer types.2956  if (!Arg0Type->isVectorType()) {2957    const APSInt &Op2 = popToAPSInt(S, Arg2Type);2958    const APSInt &Op1 = popToAPSInt(S, Call->getArg(1));2959    const APSInt &Op0 = popToAPSInt(S, Arg0Type);2960    APSInt Result = APSInt(Fn(Op0, Op1, Op2), Op0.isUnsigned());2961    pushInteger(S, Result, Call->getType());2962    return true;2963  }2964 2965  const auto *VecT = Arg0Type->castAs<VectorType>();2966  PrimType ElemT = *S.getContext().classify(VecT->getElementType());2967  unsigned NumElems = VecT->getNumElements();2968  bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();2969 2970  // Vector + Vector + Scalar case.2971  if (!Arg2Type->isVectorType()) {2972    APSInt Op2 = popToAPSInt(S, Arg2Type);2973 2974    const Pointer &Op1 = S.Stk.pop<Pointer>();2975    const Pointer &Op0 = S.Stk.pop<Pointer>();2976    const Pointer &Dst = S.Stk.peek<Pointer>();2977    for (unsigned I = 0; I != NumElems; ++I) {2978      INT_TYPE_SWITCH_NO_BOOL(ElemT, {2979        Dst.elem<T>(I) = static_cast<T>(APSInt(2980            Fn(Op0.elem<T>(I).toAPSInt(), Op1.elem<T>(I).toAPSInt(), Op2),2981            DestUnsigned));2982      });2983    }2984    Dst.initializeAllElements();2985 2986    return true;2987  }2988 2989  // Vector type.2990  const Pointer &Op2 = S.Stk.pop<Pointer>();2991  const Pointer &Op1 = S.Stk.pop<Pointer>();2992  const Pointer &Op0 = S.Stk.pop<Pointer>();2993  const Pointer &Dst = S.Stk.peek<Pointer>();2994  for (unsigned I = 0; I != NumElems; ++I) {2995    APSInt Val0, Val1, Val2;2996    INT_TYPE_SWITCH_NO_BOOL(ElemT, {2997      Val0 = Op0.elem<T>(I).toAPSInt();2998      Val1 = Op1.elem<T>(I).toAPSInt();2999      Val2 = Op2.elem<T>(I).toAPSInt();3000    });3001    APSInt Result = APSInt(Fn(Val0, Val1, Val2), Val0.isUnsigned());3002    INT_TYPE_SWITCH_NO_BOOL(ElemT,3003                            { Dst.elem<T>(I) = static_cast<T>(Result); });3004  }3005  Dst.initializeAllElements();3006 3007  return true;3008}3009 3010static bool interp__builtin_x86_extract_vector(InterpState &S, CodePtr OpPC,3011                                               const CallExpr *Call,3012                                               unsigned ID) {3013  assert(Call->getNumArgs() == 2);3014 3015  APSInt ImmAPS = popToAPSInt(S, Call->getArg(1));3016  uint64_t Index = ImmAPS.getZExtValue();3017 3018  const Pointer &Src = S.Stk.pop<Pointer>();3019  if (!Src.getFieldDesc()->isPrimitiveArray())3020    return false;3021 3022  const Pointer &Dst = S.Stk.peek<Pointer>();3023  if (!Dst.getFieldDesc()->isPrimitiveArray())3024    return false;3025 3026  unsigned SrcElems = Src.getNumElems();3027  unsigned DstElems = Dst.getNumElems();3028 3029  unsigned NumLanes = SrcElems / DstElems;3030  unsigned Lane = static_cast<unsigned>(Index % NumLanes);3031  unsigned ExtractPos = Lane * DstElems;3032 3033  PrimType ElemT = Src.getFieldDesc()->getPrimType();3034 3035  TYPE_SWITCH(ElemT, {3036    for (unsigned I = 0; I != DstElems; ++I) {3037      Dst.elem<T>(I) = Src.elem<T>(ExtractPos + I);3038    }3039  });3040 3041  Dst.initializeAllElements();3042  return true;3043}3044 3045static bool interp__builtin_x86_extract_vector_masked(InterpState &S,3046                                                      CodePtr OpPC,3047                                                      const CallExpr *Call,3048                                                      unsigned ID) {3049  assert(Call->getNumArgs() == 4);3050 3051  APSInt MaskAPS = popToAPSInt(S, Call->getArg(3));3052  const Pointer &Merge = S.Stk.pop<Pointer>();3053  APSInt ImmAPS = popToAPSInt(S, Call->getArg(1));3054  const Pointer &Src = S.Stk.pop<Pointer>();3055 3056  if (!Src.getFieldDesc()->isPrimitiveArray() ||3057      !Merge.getFieldDesc()->isPrimitiveArray())3058    return false;3059 3060  const Pointer &Dst = S.Stk.peek<Pointer>();3061  if (!Dst.getFieldDesc()->isPrimitiveArray())3062    return false;3063 3064  unsigned SrcElems = Src.getNumElems();3065  unsigned DstElems = Dst.getNumElems();3066 3067  unsigned NumLanes = SrcElems / DstElems;3068  unsigned Lane = static_cast<unsigned>(ImmAPS.getZExtValue() % NumLanes);3069  unsigned Base = Lane * DstElems;3070 3071  PrimType ElemT = Src.getFieldDesc()->getPrimType();3072 3073  TYPE_SWITCH(ElemT, {3074    for (unsigned I = 0; I != DstElems; ++I) {3075      if (MaskAPS[I])3076        Dst.elem<T>(I) = Src.elem<T>(Base + I);3077      else3078        Dst.elem<T>(I) = Merge.elem<T>(I);3079    }3080  });3081 3082  Dst.initializeAllElements();3083  return true;3084}3085 3086static bool interp__builtin_x86_insert_subvector(InterpState &S, CodePtr OpPC,3087                                                 const CallExpr *Call,3088                                                 unsigned ID) {3089  assert(Call->getNumArgs() == 3);3090 3091  APSInt ImmAPS = popToAPSInt(S, Call->getArg(2));3092  uint64_t Index = ImmAPS.getZExtValue();3093 3094  const Pointer &SubVec = S.Stk.pop<Pointer>();3095  if (!SubVec.getFieldDesc()->isPrimitiveArray())3096    return false;3097 3098  const Pointer &BaseVec = S.Stk.pop<Pointer>();3099  if (!BaseVec.getFieldDesc()->isPrimitiveArray())3100    return false;3101 3102  const Pointer &Dst = S.Stk.peek<Pointer>();3103 3104  unsigned BaseElements = BaseVec.getNumElems();3105  unsigned SubElements = SubVec.getNumElems();3106 3107  assert(SubElements != 0 && BaseElements != 0 &&3108         (BaseElements % SubElements) == 0);3109 3110  unsigned NumLanes = BaseElements / SubElements;3111  unsigned Lane = static_cast<unsigned>(Index % NumLanes);3112  unsigned InsertPos = Lane * SubElements;3113 3114  PrimType ElemT = BaseVec.getFieldDesc()->getPrimType();3115 3116  TYPE_SWITCH(ElemT, {3117    for (unsigned I = 0; I != BaseElements; ++I)3118      Dst.elem<T>(I) = BaseVec.elem<T>(I);3119    for (unsigned I = 0; I != SubElements; ++I)3120      Dst.elem<T>(InsertPos + I) = SubVec.elem<T>(I);3121  });3122 3123  Dst.initializeAllElements();3124  return true;3125}3126 3127static bool interp__builtin_ia32_phminposuw(InterpState &S, CodePtr OpPC,3128                                            const CallExpr *Call) {3129  assert(Call->getNumArgs() == 1);3130 3131  const Pointer &Source = S.Stk.pop<Pointer>();3132  const Pointer &Dest = S.Stk.peek<Pointer>();3133 3134  unsigned SourceLen = Source.getNumElems();3135  QualType ElemQT = getElemType(Source);3136  OptPrimType ElemT = S.getContext().classify(ElemQT);3137  unsigned ElemBitWidth = S.getASTContext().getTypeSize(ElemQT);3138 3139  bool DestUnsigned = Call->getCallReturnType(S.getASTContext())3140                          ->castAs<VectorType>()3141                          ->getElementType()3142                          ->isUnsignedIntegerOrEnumerationType();3143 3144  INT_TYPE_SWITCH_NO_BOOL(*ElemT, {3145    APSInt MinIndex(ElemBitWidth, DestUnsigned);3146    APSInt MinVal = Source.elem<T>(0).toAPSInt();3147 3148    for (unsigned I = 1; I != SourceLen; ++I) {3149      APSInt Val = Source.elem<T>(I).toAPSInt();3150      if (MinVal.ugt(Val)) {3151        MinVal = Val;3152        MinIndex = I;3153      }3154    }3155 3156    Dest.elem<T>(0) = static_cast<T>(MinVal);3157    Dest.elem<T>(1) = static_cast<T>(MinIndex);3158    for (unsigned I = 2; I != SourceLen; ++I) {3159      Dest.elem<T>(I) = static_cast<T>(APSInt(ElemBitWidth, DestUnsigned));3160    }3161  });3162  Dest.initializeAllElements();3163  return true;3164}3165 3166static bool interp__builtin_ia32_pternlog(InterpState &S, CodePtr OpPC,3167                                          const CallExpr *Call, bool MaskZ) {3168  assert(Call->getNumArgs() == 5);3169 3170  APInt U = popToAPSInt(S, Call->getArg(4));   // Lane mask3171  APInt Imm = popToAPSInt(S, Call->getArg(3)); // Ternary truth table3172  const Pointer &C = S.Stk.pop<Pointer>();3173  const Pointer &B = S.Stk.pop<Pointer>();3174  const Pointer &A = S.Stk.pop<Pointer>();3175  const Pointer &Dst = S.Stk.peek<Pointer>();3176 3177  unsigned DstLen = A.getNumElems();3178  QualType ElemQT = getElemType(A);3179  OptPrimType ElemT = S.getContext().classify(ElemQT);3180  unsigned LaneWidth = S.getASTContext().getTypeSize(ElemQT);3181  bool DstUnsigned = ElemQT->isUnsignedIntegerOrEnumerationType();3182 3183  INT_TYPE_SWITCH_NO_BOOL(*ElemT, {3184    for (unsigned I = 0; I != DstLen; ++I) {3185      APInt ALane = A.elem<T>(I).toAPSInt();3186      APInt BLane = B.elem<T>(I).toAPSInt();3187      APInt CLane = C.elem<T>(I).toAPSInt();3188      APInt RLane(LaneWidth, 0);3189      if (U[I]) { // If lane not masked, compute ternary logic.3190        for (unsigned Bit = 0; Bit != LaneWidth; ++Bit) {3191          unsigned ABit = ALane[Bit];3192          unsigned BBit = BLane[Bit];3193          unsigned CBit = CLane[Bit];3194          unsigned Idx = (ABit << 2) | (BBit << 1) | (CBit);3195          RLane.setBitVal(Bit, Imm[Idx]);3196        }3197        Dst.elem<T>(I) = static_cast<T>(APSInt(RLane, DstUnsigned));3198      } else if (MaskZ) { // If zero masked, zero the lane.3199        Dst.elem<T>(I) = static_cast<T>(APSInt(RLane, DstUnsigned));3200      } else { // Just masked, put in A lane.3201        Dst.elem<T>(I) = static_cast<T>(APSInt(ALane, DstUnsigned));3202      }3203    }3204  });3205  Dst.initializeAllElements();3206  return true;3207}3208 3209static bool interp__builtin_vec_ext(InterpState &S, CodePtr OpPC,3210                                    const CallExpr *Call, unsigned ID) {3211  assert(Call->getNumArgs() == 2);3212 3213  APSInt ImmAPS = popToAPSInt(S, Call->getArg(1));3214  const Pointer &Vec = S.Stk.pop<Pointer>();3215  if (!Vec.getFieldDesc()->isPrimitiveArray())3216    return false;3217 3218  unsigned NumElems = Vec.getNumElems();3219  unsigned Index =3220      static_cast<unsigned>(ImmAPS.getZExtValue() & (NumElems - 1));3221 3222  PrimType ElemT = Vec.getFieldDesc()->getPrimType();3223  // FIXME(#161685): Replace float+int split with a numeric-only type switch3224  if (ElemT == PT_Float) {3225    S.Stk.push<Floating>(Vec.elem<Floating>(Index));3226    return true;3227  }3228  INT_TYPE_SWITCH_NO_BOOL(ElemT, {3229    APSInt V = Vec.elem<T>(Index).toAPSInt();3230    pushInteger(S, V, Call->getType());3231  });3232 3233  return true;3234}3235 3236static bool interp__builtin_vec_set(InterpState &S, CodePtr OpPC,3237                                    const CallExpr *Call, unsigned ID) {3238  assert(Call->getNumArgs() == 3);3239 3240  APSInt ImmAPS = popToAPSInt(S, Call->getArg(2));3241  APSInt ValAPS = popToAPSInt(S, Call->getArg(1));3242 3243  const Pointer &Base = S.Stk.pop<Pointer>();3244  if (!Base.getFieldDesc()->isPrimitiveArray())3245    return false;3246 3247  const Pointer &Dst = S.Stk.peek<Pointer>();3248 3249  unsigned NumElems = Base.getNumElems();3250  unsigned Index =3251      static_cast<unsigned>(ImmAPS.getZExtValue() & (NumElems - 1));3252 3253  PrimType ElemT = Base.getFieldDesc()->getPrimType();3254  INT_TYPE_SWITCH_NO_BOOL(ElemT, {3255    for (unsigned I = 0; I != NumElems; ++I)3256      Dst.elem<T>(I) = Base.elem<T>(I);3257    Dst.elem<T>(Index) = static_cast<T>(ValAPS);3258  });3259 3260  Dst.initializeAllElements();3261  return true;3262}3263 3264static bool evalICmpImm(uint8_t Imm, const APSInt &A, const APSInt &B,3265                        bool IsUnsigned) {3266  switch (Imm & 0x7) {3267  case 0x00: // _MM_CMPINT_EQ3268    return (A == B);3269  case 0x01: // _MM_CMPINT_LT3270    return IsUnsigned ? A.ult(B) : A.slt(B);3271  case 0x02: // _MM_CMPINT_LE3272    return IsUnsigned ? A.ule(B) : A.sle(B);3273  case 0x03: // _MM_CMPINT_FALSE3274    return false;3275  case 0x04: // _MM_CMPINT_NE3276    return (A != B);3277  case 0x05: // _MM_CMPINT_NLT3278    return IsUnsigned ? A.ugt(B) : A.sgt(B);3279  case 0x06: // _MM_CMPINT_NLE3280    return IsUnsigned ? A.uge(B) : A.sge(B);3281  case 0x07: // _MM_CMPINT_TRUE3282    return true;3283  default:3284    llvm_unreachable("Invalid Op");3285  }3286}3287 3288static bool interp__builtin_ia32_cmp_mask(InterpState &S, CodePtr OpPC,3289                                          const CallExpr *Call, unsigned ID,3290                                          bool IsUnsigned) {3291  assert(Call->getNumArgs() == 4);3292 3293  APSInt Mask = popToAPSInt(S, Call->getArg(3));3294  APSInt Opcode = popToAPSInt(S, Call->getArg(2));3295  unsigned CmpOp = static_cast<unsigned>(Opcode.getZExtValue());3296  const Pointer &RHS = S.Stk.pop<Pointer>();3297  const Pointer &LHS = S.Stk.pop<Pointer>();3298 3299  assert(LHS.getNumElems() == RHS.getNumElems());3300 3301  APInt RetMask = APInt::getZero(LHS.getNumElems());3302  unsigned VectorLen = LHS.getNumElems();3303  PrimType ElemT = LHS.getFieldDesc()->getPrimType();3304 3305  for (unsigned ElemNum = 0; ElemNum < VectorLen; ++ElemNum) {3306    APSInt A, B;3307    INT_TYPE_SWITCH_NO_BOOL(ElemT, {3308      A = LHS.elem<T>(ElemNum).toAPSInt();3309      B = RHS.elem<T>(ElemNum).toAPSInt();3310    });3311    RetMask.setBitVal(ElemNum,3312                      Mask[ElemNum] && evalICmpImm(CmpOp, A, B, IsUnsigned));3313  }3314  pushInteger(S, RetMask, Call->getType());3315  return true;3316}3317 3318static bool interp__builtin_ia32_vpconflict(InterpState &S, CodePtr OpPC,3319                                            const CallExpr *Call) {3320  assert(Call->getNumArgs() == 1);3321 3322  QualType Arg0Type = Call->getArg(0)->getType();3323  const auto *VecT = Arg0Type->castAs<VectorType>();3324  PrimType ElemT = *S.getContext().classify(VecT->getElementType());3325  unsigned NumElems = VecT->getNumElements();3326  bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();3327  const Pointer &Src = S.Stk.pop<Pointer>();3328  const Pointer &Dst = S.Stk.peek<Pointer>();3329 3330  for (unsigned I = 0; I != NumElems; ++I) {3331    INT_TYPE_SWITCH_NO_BOOL(ElemT, {3332      APSInt ElemI = Src.elem<T>(I).toAPSInt();3333      APInt ConflictMask(ElemI.getBitWidth(), 0);3334      for (unsigned J = 0; J != I; ++J) {3335        APSInt ElemJ = Src.elem<T>(J).toAPSInt();3336        ConflictMask.setBitVal(J, ElemI == ElemJ);3337      }3338      Dst.elem<T>(I) = static_cast<T>(APSInt(ConflictMask, DestUnsigned));3339    });3340  }3341  Dst.initializeAllElements();3342  return true;3343}3344 3345static bool interp__builtin_ia32_cvt_vec2mask(InterpState &S, CodePtr OpPC,3346                                              const CallExpr *Call,3347                                              unsigned ID) {3348  assert(Call->getNumArgs() == 1);3349 3350  const Pointer &Vec = S.Stk.pop<Pointer>();3351  unsigned RetWidth = S.getASTContext().getIntWidth(Call->getType());3352  APInt RetMask(RetWidth, 0);3353 3354  unsigned VectorLen = Vec.getNumElems();3355  PrimType ElemT = Vec.getFieldDesc()->getPrimType();3356 3357  for (unsigned ElemNum = 0; ElemNum != VectorLen; ++ElemNum) {3358    APSInt A;3359    INT_TYPE_SWITCH_NO_BOOL(ElemT, { A = Vec.elem<T>(ElemNum).toAPSInt(); });3360    unsigned MSB = A[A.getBitWidth() - 1];3361    RetMask.setBitVal(ElemNum, MSB);3362  }3363  pushInteger(S, RetMask, Call->getType());3364  return true;3365}3366 3367static bool interp__builtin_ia32_shuffle_generic(3368    InterpState &S, CodePtr OpPC, const CallExpr *Call,3369    llvm::function_ref<std::pair<unsigned, int>(unsigned, unsigned)>3370        GetSourceIndex) {3371 3372  assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3);3373 3374  unsigned ShuffleMask = 0;3375  Pointer A, MaskVector, B;3376  bool IsVectorMask = false;3377  bool IsSingleOperand = (Call->getNumArgs() == 2);3378 3379  if (IsSingleOperand) {3380    QualType MaskType = Call->getArg(1)->getType();3381    if (MaskType->isVectorType()) {3382      IsVectorMask = true;3383      MaskVector = S.Stk.pop<Pointer>();3384      A = S.Stk.pop<Pointer>();3385      B = A;3386    } else if (MaskType->isIntegerType()) {3387      ShuffleMask = popToAPSInt(S, Call->getArg(1)).getZExtValue();3388      A = S.Stk.pop<Pointer>();3389      B = A;3390    } else {3391      return false;3392    }3393  } else {3394    QualType Arg2Type = Call->getArg(2)->getType();3395    if (Arg2Type->isVectorType()) {3396      IsVectorMask = true;3397      B = S.Stk.pop<Pointer>();3398      MaskVector = S.Stk.pop<Pointer>();3399      A = S.Stk.pop<Pointer>();3400    } else if (Arg2Type->isIntegerType()) {3401      ShuffleMask = popToAPSInt(S, Call->getArg(2)).getZExtValue();3402      B = S.Stk.pop<Pointer>();3403      A = S.Stk.pop<Pointer>();3404    } else {3405      return false;3406    }3407  }3408 3409  QualType Arg0Type = Call->getArg(0)->getType();3410  const auto *VecT = Arg0Type->castAs<VectorType>();3411  PrimType ElemT = *S.getContext().classify(VecT->getElementType());3412  unsigned NumElems = VecT->getNumElements();3413 3414  const Pointer &Dst = S.Stk.peek<Pointer>();3415 3416  PrimType MaskElemT = PT_Uint32;3417  if (IsVectorMask) {3418    QualType Arg1Type = Call->getArg(1)->getType();3419    const auto *MaskVecT = Arg1Type->castAs<VectorType>();3420    QualType MaskElemType = MaskVecT->getElementType();3421    MaskElemT = *S.getContext().classify(MaskElemType);3422  }3423 3424  for (unsigned DstIdx = 0; DstIdx != NumElems; ++DstIdx) {3425    if (IsVectorMask) {3426      INT_TYPE_SWITCH(MaskElemT, {3427        ShuffleMask = static_cast<unsigned>(MaskVector.elem<T>(DstIdx));3428      });3429    }3430 3431    auto [SrcVecIdx, SrcIdx] = GetSourceIndex(DstIdx, ShuffleMask);3432 3433    if (SrcIdx < 0) {3434      // Zero out this element3435      if (ElemT == PT_Float) {3436        Dst.elem<Floating>(DstIdx) = Floating(3437            S.getASTContext().getFloatTypeSemantics(VecT->getElementType()));3438      } else {3439        INT_TYPE_SWITCH_NO_BOOL(ElemT, { Dst.elem<T>(DstIdx) = T::from(0); });3440      }3441    } else {3442      const Pointer &Src = (SrcVecIdx == 0) ? A : B;3443      TYPE_SWITCH(ElemT, { Dst.elem<T>(DstIdx) = Src.elem<T>(SrcIdx); });3444    }3445  }3446  Dst.initializeAllElements();3447 3448  return true;3449}3450 3451static bool interp__builtin_ia32_shift_with_count(3452    InterpState &S, CodePtr OpPC, const CallExpr *Call,3453    llvm::function_ref<APInt(const APInt &, uint64_t)> ShiftOp,3454    llvm::function_ref<APInt(const APInt &, unsigned)> OverflowOp) {3455 3456  assert(Call->getNumArgs() == 2);3457 3458  const Pointer &Count = S.Stk.pop<Pointer>();3459  const Pointer &Source = S.Stk.pop<Pointer>();3460 3461  QualType SourceType = Call->getArg(0)->getType();3462  QualType CountType = Call->getArg(1)->getType();3463  assert(SourceType->isVectorType() && CountType->isVectorType());3464 3465  const auto *SourceVecT = SourceType->castAs<VectorType>();3466  const auto *CountVecT = CountType->castAs<VectorType>();3467  PrimType SourceElemT = *S.getContext().classify(SourceVecT->getElementType());3468  PrimType CountElemT = *S.getContext().classify(CountVecT->getElementType());3469 3470  const Pointer &Dst = S.Stk.peek<Pointer>();3471 3472  unsigned DestEltWidth =3473      S.getASTContext().getTypeSize(SourceVecT->getElementType());3474  bool IsDestUnsigned = SourceVecT->getElementType()->isUnsignedIntegerType();3475  unsigned DestLen = SourceVecT->getNumElements();3476  unsigned CountEltWidth =3477      S.getASTContext().getTypeSize(CountVecT->getElementType());3478  unsigned NumBitsInQWord = 64;3479  unsigned NumCountElts = NumBitsInQWord / CountEltWidth;3480 3481  uint64_t CountLQWord = 0;3482  for (unsigned EltIdx = 0; EltIdx != NumCountElts; ++EltIdx) {3483    uint64_t Elt = 0;3484    INT_TYPE_SWITCH(CountElemT,3485                    { Elt = static_cast<uint64_t>(Count.elem<T>(EltIdx)); });3486    CountLQWord |= (Elt << (EltIdx * CountEltWidth));3487  }3488 3489  for (unsigned EltIdx = 0; EltIdx != DestLen; ++EltIdx) {3490    APSInt Elt;3491    INT_TYPE_SWITCH(SourceElemT, { Elt = Source.elem<T>(EltIdx).toAPSInt(); });3492 3493    APInt Result;3494    if (CountLQWord < DestEltWidth) {3495      Result = ShiftOp(Elt, CountLQWord);3496    } else {3497      Result = OverflowOp(Elt, DestEltWidth);3498    }3499    if (IsDestUnsigned) {3500      INT_TYPE_SWITCH(SourceElemT, {3501        Dst.elem<T>(EltIdx) = T::from(Result.getZExtValue());3502      });3503    } else {3504      INT_TYPE_SWITCH(SourceElemT, {3505        Dst.elem<T>(EltIdx) = T::from(Result.getSExtValue());3506      });3507    }3508  }3509 3510  Dst.initializeAllElements();3511  return true;3512}3513 3514static bool interp__builtin_ia32_shufbitqmb_mask(InterpState &S, CodePtr OpPC,3515                                                 const CallExpr *Call) {3516 3517  assert(Call->getNumArgs() == 3);3518 3519  QualType SourceType = Call->getArg(0)->getType();3520  QualType ShuffleMaskType = Call->getArg(1)->getType();3521  QualType ZeroMaskType = Call->getArg(2)->getType();3522  if (!SourceType->isVectorType() || !ShuffleMaskType->isVectorType() ||3523      !ZeroMaskType->isIntegerType()) {3524    return false;3525  }3526 3527  Pointer Source, ShuffleMask;3528  APSInt ZeroMask = popToAPSInt(S, Call->getArg(2));3529  ShuffleMask = S.Stk.pop<Pointer>();3530  Source = S.Stk.pop<Pointer>();3531 3532  const auto *SourceVecT = SourceType->castAs<VectorType>();3533  const auto *ShuffleMaskVecT = ShuffleMaskType->castAs<VectorType>();3534  assert(SourceVecT->getNumElements() == ShuffleMaskVecT->getNumElements());3535  assert(ZeroMask.getBitWidth() == SourceVecT->getNumElements());3536 3537  PrimType SourceElemT = *S.getContext().classify(SourceVecT->getElementType());3538  PrimType ShuffleMaskElemT =3539      *S.getContext().classify(ShuffleMaskVecT->getElementType());3540 3541  unsigned NumBytesInQWord = 8;3542  unsigned NumBitsInByte = 8;3543  unsigned NumBytes = SourceVecT->getNumElements();3544  unsigned NumQWords = NumBytes / NumBytesInQWord;3545  unsigned RetWidth = ZeroMask.getBitWidth();3546  APSInt RetMask(llvm::APInt(RetWidth, 0), /*isUnsigned=*/true);3547 3548  for (unsigned QWordId = 0; QWordId != NumQWords; ++QWordId) {3549    APInt SourceQWord(64, 0);3550    for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {3551      uint64_t Byte = 0;3552      INT_TYPE_SWITCH(SourceElemT, {3553        Byte = static_cast<uint64_t>(3554            Source.elem<T>(QWordId * NumBytesInQWord + ByteIdx));3555      });3556      SourceQWord.insertBits(APInt(8, Byte & 0xFF), ByteIdx * NumBitsInByte);3557    }3558 3559    for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {3560      unsigned SelIdx = QWordId * NumBytesInQWord + ByteIdx;3561      unsigned M = 0;3562      INT_TYPE_SWITCH(ShuffleMaskElemT, {3563        M = static_cast<unsigned>(ShuffleMask.elem<T>(SelIdx)) & 0x3F;3564      });3565 3566      if (ZeroMask[SelIdx]) {3567        RetMask.setBitVal(SelIdx, SourceQWord[M]);3568      }3569    }3570  }3571 3572  pushInteger(S, RetMask, Call->getType());3573  return true;3574}3575 3576static bool interp__builtin_ia32_vcvtps2ph(InterpState &S, CodePtr OpPC,3577                                           const CallExpr *Call) {3578  // Arguments are: vector of floats, rounding immediate3579  assert(Call->getNumArgs() == 2);3580 3581  APSInt Imm = popToAPSInt(S, Call->getArg(1));3582  const Pointer &Src = S.Stk.pop<Pointer>();3583  const Pointer &Dst = S.Stk.peek<Pointer>();3584 3585  assert(Src.getFieldDesc()->isPrimitiveArray());3586  assert(Dst.getFieldDesc()->isPrimitiveArray());3587 3588  const auto *SrcVTy = Call->getArg(0)->getType()->castAs<VectorType>();3589  unsigned SrcNumElems = SrcVTy->getNumElements();3590  const auto *DstVTy = Call->getType()->castAs<VectorType>();3591  unsigned DstNumElems = DstVTy->getNumElements();3592 3593  const llvm::fltSemantics &HalfSem =3594      S.getASTContext().getFloatTypeSemantics(S.getASTContext().HalfTy);3595 3596  // imm[2] == 1 means use MXCSR rounding mode.3597  // In that case, we can only evaluate if the conversion is exact.3598  int ImmVal = Imm.getZExtValue();3599  bool UseMXCSR = (ImmVal & 4) != 0;3600  bool IsFPConstrained =3601      Call->getFPFeaturesInEffect(S.getASTContext().getLangOpts())3602          .isFPConstrained();3603 3604  llvm::RoundingMode RM;3605  if (!UseMXCSR) {3606    switch (ImmVal & 3) {3607    case 0:3608      RM = llvm::RoundingMode::NearestTiesToEven;3609      break;3610    case 1:3611      RM = llvm::RoundingMode::TowardNegative;3612      break;3613    case 2:3614      RM = llvm::RoundingMode::TowardPositive;3615      break;3616    case 3:3617      RM = llvm::RoundingMode::TowardZero;3618      break;3619    default:3620      llvm_unreachable("Invalid immediate rounding mode");3621    }3622  } else {3623    // For MXCSR, we must check for exactness. We can use any rounding mode3624    // for the trial conversion since the result is the same if it's exact.3625    RM = llvm::RoundingMode::NearestTiesToEven;3626  }3627 3628  QualType DstElemQT = Dst.getFieldDesc()->getElemQualType();3629  PrimType DstElemT = *S.getContext().classify(DstElemQT);3630 3631  for (unsigned I = 0; I != SrcNumElems; ++I) {3632    Floating SrcVal = Src.elem<Floating>(I);3633    APFloat DstVal = SrcVal.getAPFloat();3634 3635    bool LostInfo;3636    APFloat::opStatus St = DstVal.convert(HalfSem, RM, &LostInfo);3637 3638    if (UseMXCSR && IsFPConstrained && St != APFloat::opOK) {3639      S.FFDiag(S.Current->getSource(OpPC),3640               diag::note_constexpr_dynamic_rounding);3641      return false;3642    }3643 3644    INT_TYPE_SWITCH_NO_BOOL(DstElemT, {3645      // Convert the destination value's bit pattern to an unsigned integer,3646      // then reconstruct the element using the target type's 'from' method.3647      uint64_t RawBits = DstVal.bitcastToAPInt().getZExtValue();3648      Dst.elem<T>(I) = T::from(RawBits);3649    });3650  }3651 3652  // Zero out remaining elements if the destination has more elements3653  // (e.g., vcvtps2ph converting 4 floats to 8 shorts).3654  if (DstNumElems > SrcNumElems) {3655    for (unsigned I = SrcNumElems; I != DstNumElems; ++I) {3656      INT_TYPE_SWITCH_NO_BOOL(DstElemT, { Dst.elem<T>(I) = T::from(0); });3657    }3658  }3659 3660  Dst.initializeAllElements();3661  return true;3662}3663 3664static bool interp__builtin_ia32_multishiftqb(InterpState &S, CodePtr OpPC,3665                                              const CallExpr *Call) {3666  assert(Call->getNumArgs() == 2);3667 3668  QualType ATy = Call->getArg(0)->getType();3669  QualType BTy = Call->getArg(1)->getType();3670  if (!ATy->isVectorType() || !BTy->isVectorType()) {3671    return false;3672  }3673 3674  const Pointer &BPtr = S.Stk.pop<Pointer>();3675  const Pointer &APtr = S.Stk.pop<Pointer>();3676  const auto *AVecT = ATy->castAs<VectorType>();3677  assert(AVecT->getNumElements() ==3678         BTy->castAs<VectorType>()->getNumElements());3679 3680  PrimType ElemT = *S.getContext().classify(AVecT->getElementType());3681 3682  unsigned NumBytesInQWord = 8;3683  unsigned NumBitsInByte = 8;3684  unsigned NumBytes = AVecT->getNumElements();3685  unsigned NumQWords = NumBytes / NumBytesInQWord;3686  const Pointer &Dst = S.Stk.peek<Pointer>();3687 3688  for (unsigned QWordId = 0; QWordId != NumQWords; ++QWordId) {3689    APInt BQWord(64, 0);3690    for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {3691      unsigned Idx = QWordId * NumBytesInQWord + ByteIdx;3692      INT_TYPE_SWITCH(ElemT, {3693        uint64_t Byte = static_cast<uint64_t>(BPtr.elem<T>(Idx));3694        BQWord.insertBits(APInt(8, Byte & 0xFF), ByteIdx * NumBitsInByte);3695      });3696    }3697 3698    for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {3699      unsigned Idx = QWordId * NumBytesInQWord + ByteIdx;3700      uint64_t Ctrl = 0;3701      INT_TYPE_SWITCH(3702          ElemT, { Ctrl = static_cast<uint64_t>(APtr.elem<T>(Idx)) & 0x3F; });3703 3704      APInt Byte(8, 0);3705      for (unsigned BitIdx = 0; BitIdx != NumBitsInByte; ++BitIdx) {3706        Byte.setBitVal(BitIdx, BQWord[(Ctrl + BitIdx) & 0x3F]);3707      }3708      INT_TYPE_SWITCH(ElemT,3709                      { Dst.elem<T>(Idx) = T::from(Byte.getZExtValue()); });3710    }3711  }3712 3713  Dst.initializeAllElements();3714 3715  return true;3716}3717 3718bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,3719                      uint32_t BuiltinID) {3720  if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID))3721    return Invalid(S, OpPC);3722 3723  const InterpFrame *Frame = S.Current;3724  switch (BuiltinID) {3725  case Builtin::BI__builtin_is_constant_evaluated:3726    return interp__builtin_is_constant_evaluated(S, OpPC, Frame, Call);3727 3728  case Builtin::BI__builtin_assume:3729  case Builtin::BI__assume:3730    return interp__builtin_assume(S, OpPC, Frame, Call);3731 3732  case Builtin::BI__builtin_strcmp:3733  case Builtin::BIstrcmp:3734  case Builtin::BI__builtin_strncmp:3735  case Builtin::BIstrncmp:3736  case Builtin::BI__builtin_wcsncmp:3737  case Builtin::BIwcsncmp:3738  case Builtin::BI__builtin_wcscmp:3739  case Builtin::BIwcscmp:3740    return interp__builtin_strcmp(S, OpPC, Frame, Call, BuiltinID);3741 3742  case Builtin::BI__builtin_strlen:3743  case Builtin::BIstrlen:3744  case Builtin::BI__builtin_wcslen:3745  case Builtin::BIwcslen:3746    return interp__builtin_strlen(S, OpPC, Frame, Call, BuiltinID);3747 3748  case Builtin::BI__builtin_nan:3749  case Builtin::BI__builtin_nanf:3750  case Builtin::BI__builtin_nanl:3751  case Builtin::BI__builtin_nanf16:3752  case Builtin::BI__builtin_nanf128:3753    return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/false);3754 3755  case Builtin::BI__builtin_nans:3756  case Builtin::BI__builtin_nansf:3757  case Builtin::BI__builtin_nansl:3758  case Builtin::BI__builtin_nansf16:3759  case Builtin::BI__builtin_nansf128:3760    return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/true);3761 3762  case Builtin::BI__builtin_huge_val:3763  case Builtin::BI__builtin_huge_valf:3764  case Builtin::BI__builtin_huge_vall:3765  case Builtin::BI__builtin_huge_valf16:3766  case Builtin::BI__builtin_huge_valf128:3767  case Builtin::BI__builtin_inf:3768  case Builtin::BI__builtin_inff:3769  case Builtin::BI__builtin_infl:3770  case Builtin::BI__builtin_inff16:3771  case Builtin::BI__builtin_inff128:3772    return interp__builtin_inf(S, OpPC, Frame, Call);3773 3774  case Builtin::BI__builtin_copysign:3775  case Builtin::BI__builtin_copysignf:3776  case Builtin::BI__builtin_copysignl:3777  case Builtin::BI__builtin_copysignf128:3778    return interp__builtin_copysign(S, OpPC, Frame);3779 3780  case Builtin::BI__builtin_fmin:3781  case Builtin::BI__builtin_fminf:3782  case Builtin::BI__builtin_fminl:3783  case Builtin::BI__builtin_fminf16:3784  case Builtin::BI__builtin_fminf128:3785    return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/false);3786 3787  case Builtin::BI__builtin_fminimum_num:3788  case Builtin::BI__builtin_fminimum_numf:3789  case Builtin::BI__builtin_fminimum_numl:3790  case Builtin::BI__builtin_fminimum_numf16:3791  case Builtin::BI__builtin_fminimum_numf128:3792    return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/true);3793 3794  case Builtin::BI__builtin_fmax:3795  case Builtin::BI__builtin_fmaxf:3796  case Builtin::BI__builtin_fmaxl:3797  case Builtin::BI__builtin_fmaxf16:3798  case Builtin::BI__builtin_fmaxf128:3799    return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/false);3800 3801  case Builtin::BI__builtin_fmaximum_num:3802  case Builtin::BI__builtin_fmaximum_numf:3803  case Builtin::BI__builtin_fmaximum_numl:3804  case Builtin::BI__builtin_fmaximum_numf16:3805  case Builtin::BI__builtin_fmaximum_numf128:3806    return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/true);3807 3808  case Builtin::BI__builtin_isnan:3809    return interp__builtin_isnan(S, OpPC, Frame, Call);3810 3811  case Builtin::BI__builtin_issignaling:3812    return interp__builtin_issignaling(S, OpPC, Frame, Call);3813 3814  case Builtin::BI__builtin_isinf:3815    return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/false, Call);3816 3817  case Builtin::BI__builtin_isinf_sign:3818    return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/true, Call);3819 3820  case Builtin::BI__builtin_isfinite:3821    return interp__builtin_isfinite(S, OpPC, Frame, Call);3822 3823  case Builtin::BI__builtin_isnormal:3824    return interp__builtin_isnormal(S, OpPC, Frame, Call);3825 3826  case Builtin::BI__builtin_issubnormal:3827    return interp__builtin_issubnormal(S, OpPC, Frame, Call);3828 3829  case Builtin::BI__builtin_iszero:3830    return interp__builtin_iszero(S, OpPC, Frame, Call);3831 3832  case Builtin::BI__builtin_signbit:3833  case Builtin::BI__builtin_signbitf:3834  case Builtin::BI__builtin_signbitl:3835    return interp__builtin_signbit(S, OpPC, Frame, Call);3836 3837  case Builtin::BI__builtin_isgreater:3838  case Builtin::BI__builtin_isgreaterequal:3839  case Builtin::BI__builtin_isless:3840  case Builtin::BI__builtin_islessequal:3841  case Builtin::BI__builtin_islessgreater:3842  case Builtin::BI__builtin_isunordered:3843    return interp_floating_comparison(S, OpPC, Call, BuiltinID);3844 3845  case Builtin::BI__builtin_isfpclass:3846    return interp__builtin_isfpclass(S, OpPC, Frame, Call);3847 3848  case Builtin::BI__builtin_fpclassify:3849    return interp__builtin_fpclassify(S, OpPC, Frame, Call);3850 3851  case Builtin::BI__builtin_fabs:3852  case Builtin::BI__builtin_fabsf:3853  case Builtin::BI__builtin_fabsl:3854  case Builtin::BI__builtin_fabsf128:3855    return interp__builtin_fabs(S, OpPC, Frame);3856 3857  case Builtin::BI__builtin_abs:3858  case Builtin::BI__builtin_labs:3859  case Builtin::BI__builtin_llabs:3860    return interp__builtin_abs(S, OpPC, Frame, Call);3861 3862  case Builtin::BI__builtin_popcount:3863  case Builtin::BI__builtin_popcountl:3864  case Builtin::BI__builtin_popcountll:3865  case Builtin::BI__builtin_popcountg:3866  case Builtin::BI__popcnt16: // Microsoft variants of popcount3867  case Builtin::BI__popcnt:3868  case Builtin::BI__popcnt64:3869    return interp__builtin_popcount(S, OpPC, Frame, Call);3870 3871  case Builtin::BI__builtin_parity:3872  case Builtin::BI__builtin_parityl:3873  case Builtin::BI__builtin_parityll:3874    return interp__builtin_elementwise_int_unaryop(3875        S, OpPC, Call, [](const APSInt &Val) {3876          return APInt(Val.getBitWidth(), Val.popcount() % 2);3877        });3878  case Builtin::BI__builtin_clrsb:3879  case Builtin::BI__builtin_clrsbl:3880  case Builtin::BI__builtin_clrsbll:3881    return interp__builtin_elementwise_int_unaryop(3882        S, OpPC, Call, [](const APSInt &Val) {3883          return APInt(Val.getBitWidth(),3884                       Val.getBitWidth() - Val.getSignificantBits());3885        });3886  case Builtin::BI__builtin_bitreverse8:3887  case Builtin::BI__builtin_bitreverse16:3888  case Builtin::BI__builtin_bitreverse32:3889  case Builtin::BI__builtin_bitreverse64:3890    return interp__builtin_elementwise_int_unaryop(3891        S, OpPC, Call, [](const APSInt &Val) { return Val.reverseBits(); });3892 3893  case Builtin::BI__builtin_classify_type:3894    return interp__builtin_classify_type(S, OpPC, Frame, Call);3895 3896  case Builtin::BI__builtin_expect:3897  case Builtin::BI__builtin_expect_with_probability:3898    return interp__builtin_expect(S, OpPC, Frame, Call);3899 3900  case Builtin::BI__builtin_rotateleft8:3901  case Builtin::BI__builtin_rotateleft16:3902  case Builtin::BI__builtin_rotateleft32:3903  case Builtin::BI__builtin_rotateleft64:3904  case Builtin::BI_rotl8: // Microsoft variants of rotate left3905  case Builtin::BI_rotl16:3906  case Builtin::BI_rotl:3907  case Builtin::BI_lrotl:3908  case Builtin::BI_rotl64:3909    return interp__builtin_elementwise_int_binop(3910        S, OpPC, Call, [](const APSInt &Value, const APSInt &Amount) {3911          return Value.rotl(Amount);3912        });3913 3914  case Builtin::BI__builtin_rotateright8:3915  case Builtin::BI__builtin_rotateright16:3916  case Builtin::BI__builtin_rotateright32:3917  case Builtin::BI__builtin_rotateright64:3918  case Builtin::BI_rotr8: // Microsoft variants of rotate right3919  case Builtin::BI_rotr16:3920  case Builtin::BI_rotr:3921  case Builtin::BI_lrotr:3922  case Builtin::BI_rotr64:3923    return interp__builtin_elementwise_int_binop(3924        S, OpPC, Call, [](const APSInt &Value, const APSInt &Amount) {3925          return Value.rotr(Amount);3926        });3927 3928  case Builtin::BI__builtin_ffs:3929  case Builtin::BI__builtin_ffsl:3930  case Builtin::BI__builtin_ffsll:3931    return interp__builtin_elementwise_int_unaryop(3932        S, OpPC, Call, [](const APSInt &Val) {3933          return APInt(Val.getBitWidth(),3934                       Val.isZero() ? 0u : Val.countTrailingZeros() + 1u);3935        });3936 3937  case Builtin::BIaddressof:3938  case Builtin::BI__addressof:3939  case Builtin::BI__builtin_addressof:3940    assert(isNoopBuiltin(BuiltinID));3941    return interp__builtin_addressof(S, OpPC, Frame, Call);3942 3943  case Builtin::BIas_const:3944  case Builtin::BIforward:3945  case Builtin::BIforward_like:3946  case Builtin::BImove:3947  case Builtin::BImove_if_noexcept:3948    assert(isNoopBuiltin(BuiltinID));3949    return interp__builtin_move(S, OpPC, Frame, Call);3950 3951  case Builtin::BI__builtin_eh_return_data_regno:3952    return interp__builtin_eh_return_data_regno(S, OpPC, Frame, Call);3953 3954  case Builtin::BI__builtin_launder:3955    assert(isNoopBuiltin(BuiltinID));3956    return true;3957 3958  case Builtin::BI__builtin_add_overflow:3959  case Builtin::BI__builtin_sub_overflow:3960  case Builtin::BI__builtin_mul_overflow:3961  case Builtin::BI__builtin_sadd_overflow:3962  case Builtin::BI__builtin_uadd_overflow:3963  case Builtin::BI__builtin_uaddl_overflow:3964  case Builtin::BI__builtin_uaddll_overflow:3965  case Builtin::BI__builtin_usub_overflow:3966  case Builtin::BI__builtin_usubl_overflow:3967  case Builtin::BI__builtin_usubll_overflow:3968  case Builtin::BI__builtin_umul_overflow:3969  case Builtin::BI__builtin_umull_overflow:3970  case Builtin::BI__builtin_umulll_overflow:3971  case Builtin::BI__builtin_saddl_overflow:3972  case Builtin::BI__builtin_saddll_overflow:3973  case Builtin::BI__builtin_ssub_overflow:3974  case Builtin::BI__builtin_ssubl_overflow:3975  case Builtin::BI__builtin_ssubll_overflow:3976  case Builtin::BI__builtin_smul_overflow:3977  case Builtin::BI__builtin_smull_overflow:3978  case Builtin::BI__builtin_smulll_overflow:3979    return interp__builtin_overflowop(S, OpPC, Call, BuiltinID);3980 3981  case Builtin::BI__builtin_addcb:3982  case Builtin::BI__builtin_addcs:3983  case Builtin::BI__builtin_addc:3984  case Builtin::BI__builtin_addcl:3985  case Builtin::BI__builtin_addcll:3986  case Builtin::BI__builtin_subcb:3987  case Builtin::BI__builtin_subcs:3988  case Builtin::BI__builtin_subc:3989  case Builtin::BI__builtin_subcl:3990  case Builtin::BI__builtin_subcll:3991    return interp__builtin_carryop(S, OpPC, Frame, Call, BuiltinID);3992 3993  case Builtin::BI__builtin_clz:3994  case Builtin::BI__builtin_clzl:3995  case Builtin::BI__builtin_clzll:3996  case Builtin::BI__builtin_clzs:3997  case Builtin::BI__builtin_clzg:3998  case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes3999  case Builtin::BI__lzcnt:4000  case Builtin::BI__lzcnt64:4001    return interp__builtin_clz(S, OpPC, Frame, Call, BuiltinID);4002 4003  case Builtin::BI__builtin_ctz:4004  case Builtin::BI__builtin_ctzl:4005  case Builtin::BI__builtin_ctzll:4006  case Builtin::BI__builtin_ctzs:4007  case Builtin::BI__builtin_ctzg:4008    return interp__builtin_ctz(S, OpPC, Frame, Call, BuiltinID);4009 4010  case Builtin::BI__builtin_elementwise_clzg:4011  case Builtin::BI__builtin_elementwise_ctzg:4012    return interp__builtin_elementwise_countzeroes(S, OpPC, Frame, Call,4013                                                   BuiltinID);4014  case Builtin::BI__builtin_bswapg:4015  case Builtin::BI__builtin_bswap16:4016  case Builtin::BI__builtin_bswap32:4017  case Builtin::BI__builtin_bswap64:4018    return interp__builtin_bswap(S, OpPC, Frame, Call);4019 4020  case Builtin::BI__atomic_always_lock_free:4021  case Builtin::BI__atomic_is_lock_free:4022    return interp__builtin_atomic_lock_free(S, OpPC, Frame, Call, BuiltinID);4023 4024  case Builtin::BI__c11_atomic_is_lock_free:4025    return interp__builtin_c11_atomic_is_lock_free(S, OpPC, Frame, Call);4026 4027  case Builtin::BI__builtin_complex:4028    return interp__builtin_complex(S, OpPC, Frame, Call);4029 4030  case Builtin::BI__builtin_is_aligned:4031  case Builtin::BI__builtin_align_up:4032  case Builtin::BI__builtin_align_down:4033    return interp__builtin_is_aligned_up_down(S, OpPC, Frame, Call, BuiltinID);4034 4035  case Builtin::BI__builtin_assume_aligned:4036    return interp__builtin_assume_aligned(S, OpPC, Frame, Call);4037 4038  case clang::X86::BI__builtin_ia32_bextr_u32:4039  case clang::X86::BI__builtin_ia32_bextr_u64:4040  case clang::X86::BI__builtin_ia32_bextri_u32:4041  case clang::X86::BI__builtin_ia32_bextri_u64:4042    return interp__builtin_elementwise_int_binop(4043        S, OpPC, Call, [](const APSInt &Val, const APSInt &Idx) {4044          unsigned BitWidth = Val.getBitWidth();4045          uint64_t Shift = Idx.extractBitsAsZExtValue(8, 0);4046          uint64_t Length = Idx.extractBitsAsZExtValue(8, 8);4047          if (Length > BitWidth) {4048            Length = BitWidth;4049          }4050 4051          // Handle out of bounds cases.4052          if (Length == 0 || Shift >= BitWidth)4053            return APInt(BitWidth, 0);4054 4055          uint64_t Result = Val.getZExtValue() >> Shift;4056          Result &= llvm::maskTrailingOnes<uint64_t>(Length);4057          return APInt(BitWidth, Result);4058        });4059 4060  case clang::X86::BI__builtin_ia32_bzhi_si:4061  case clang::X86::BI__builtin_ia32_bzhi_di:4062    return interp__builtin_elementwise_int_binop(4063        S, OpPC, Call, [](const APSInt &Val, const APSInt &Idx) {4064          unsigned BitWidth = Val.getBitWidth();4065          uint64_t Index = Idx.extractBitsAsZExtValue(8, 0);4066          APSInt Result = Val;4067 4068          if (Index < BitWidth)4069            Result.clearHighBits(BitWidth - Index);4070 4071          return Result;4072        });4073 4074  case clang::X86::BI__builtin_ia32_ktestcqi:4075  case clang::X86::BI__builtin_ia32_ktestchi:4076  case clang::X86::BI__builtin_ia32_ktestcsi:4077  case clang::X86::BI__builtin_ia32_ktestcdi:4078    return interp__builtin_elementwise_int_binop(4079        S, OpPC, Call, [](const APSInt &A, const APSInt &B) {4080          return APInt(sizeof(unsigned char) * 8, (~A & B) == 0);4081        });4082 4083  case clang::X86::BI__builtin_ia32_ktestzqi:4084  case clang::X86::BI__builtin_ia32_ktestzhi:4085  case clang::X86::BI__builtin_ia32_ktestzsi:4086  case clang::X86::BI__builtin_ia32_ktestzdi:4087    return interp__builtin_elementwise_int_binop(4088        S, OpPC, Call, [](const APSInt &A, const APSInt &B) {4089          return APInt(sizeof(unsigned char) * 8, (A & B) == 0);4090        });4091 4092  case clang::X86::BI__builtin_ia32_kortestcqi:4093  case clang::X86::BI__builtin_ia32_kortestchi:4094  case clang::X86::BI__builtin_ia32_kortestcsi:4095  case clang::X86::BI__builtin_ia32_kortestcdi:4096    return interp__builtin_elementwise_int_binop(4097        S, OpPC, Call, [](const APSInt &A, const APSInt &B) {4098          return APInt(sizeof(unsigned char) * 8, ~(A | B) == 0);4099        });4100 4101  case clang::X86::BI__builtin_ia32_kortestzqi:4102  case clang::X86::BI__builtin_ia32_kortestzhi:4103  case clang::X86::BI__builtin_ia32_kortestzsi:4104  case clang::X86::BI__builtin_ia32_kortestzdi:4105    return interp__builtin_elementwise_int_binop(4106        S, OpPC, Call, [](const APSInt &A, const APSInt &B) {4107          return APInt(sizeof(unsigned char) * 8, (A | B) == 0);4108        });4109 4110  case clang::X86::BI__builtin_ia32_lzcnt_u16:4111  case clang::X86::BI__builtin_ia32_lzcnt_u32:4112  case clang::X86::BI__builtin_ia32_lzcnt_u64:4113    return interp__builtin_elementwise_int_unaryop(4114        S, OpPC, Call, [](const APSInt &Src) {4115          return APInt(Src.getBitWidth(), Src.countLeadingZeros());4116        });4117 4118  case clang::X86::BI__builtin_ia32_tzcnt_u16:4119  case clang::X86::BI__builtin_ia32_tzcnt_u32:4120  case clang::X86::BI__builtin_ia32_tzcnt_u64:4121    return interp__builtin_elementwise_int_unaryop(4122        S, OpPC, Call, [](const APSInt &Src) {4123          return APInt(Src.getBitWidth(), Src.countTrailingZeros());4124        });4125 4126  case clang::X86::BI__builtin_ia32_pdep_si:4127  case clang::X86::BI__builtin_ia32_pdep_di:4128    return interp__builtin_elementwise_int_binop(4129        S, OpPC, Call, [](const APSInt &Val, const APSInt &Mask) {4130          unsigned BitWidth = Val.getBitWidth();4131          APInt Result = APInt::getZero(BitWidth);4132 4133          for (unsigned I = 0, P = 0; I != BitWidth; ++I) {4134            if (Mask[I])4135              Result.setBitVal(I, Val[P++]);4136          }4137 4138          return Result;4139        });4140 4141  case clang::X86::BI__builtin_ia32_pext_si:4142  case clang::X86::BI__builtin_ia32_pext_di:4143    return interp__builtin_elementwise_int_binop(4144        S, OpPC, Call, [](const APSInt &Val, const APSInt &Mask) {4145          unsigned BitWidth = Val.getBitWidth();4146          APInt Result = APInt::getZero(BitWidth);4147 4148          for (unsigned I = 0, P = 0; I != BitWidth; ++I) {4149            if (Mask[I])4150              Result.setBitVal(P++, Val[I]);4151          }4152 4153          return Result;4154        });4155 4156  case clang::X86::BI__builtin_ia32_addcarryx_u32:4157  case clang::X86::BI__builtin_ia32_addcarryx_u64:4158  case clang::X86::BI__builtin_ia32_subborrow_u32:4159  case clang::X86::BI__builtin_ia32_subborrow_u64:4160    return interp__builtin_ia32_addcarry_subborrow(S, OpPC, Frame, Call,4161                                                   BuiltinID);4162 4163  case Builtin::BI__builtin_os_log_format_buffer_size:4164    return interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, Call);4165 4166  case Builtin::BI__builtin_ptrauth_string_discriminator:4167    return interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, Call);4168 4169  case Builtin::BI__builtin_infer_alloc_token:4170    return interp__builtin_infer_alloc_token(S, OpPC, Frame, Call);4171 4172  case Builtin::BI__noop:4173    pushInteger(S, 0, Call->getType());4174    return true;4175 4176  case Builtin::BI__builtin_operator_new:4177    return interp__builtin_operator_new(S, OpPC, Frame, Call);4178 4179  case Builtin::BI__builtin_operator_delete:4180    return interp__builtin_operator_delete(S, OpPC, Frame, Call);4181 4182  case Builtin::BI__arithmetic_fence:4183    return interp__builtin_arithmetic_fence(S, OpPC, Frame, Call);4184 4185  case Builtin::BI__builtin_reduce_add:4186  case Builtin::BI__builtin_reduce_mul:4187  case Builtin::BI__builtin_reduce_and:4188  case Builtin::BI__builtin_reduce_or:4189  case Builtin::BI__builtin_reduce_xor:4190  case Builtin::BI__builtin_reduce_min:4191  case Builtin::BI__builtin_reduce_max:4192    return interp__builtin_vector_reduce(S, OpPC, Call, BuiltinID);4193 4194  case Builtin::BI__builtin_elementwise_popcount:4195    return interp__builtin_elementwise_int_unaryop(4196        S, OpPC, Call, [](const APSInt &Src) {4197          return APInt(Src.getBitWidth(), Src.popcount());4198        });4199  case Builtin::BI__builtin_elementwise_bitreverse:4200    return interp__builtin_elementwise_int_unaryop(4201        S, OpPC, Call, [](const APSInt &Src) { return Src.reverseBits(); });4202 4203  case Builtin::BI__builtin_elementwise_abs:4204    return interp__builtin_elementwise_abs(S, OpPC, Frame, Call, BuiltinID);4205 4206  case Builtin::BI__builtin_memcpy:4207  case Builtin::BImemcpy:4208  case Builtin::BI__builtin_wmemcpy:4209  case Builtin::BIwmemcpy:4210  case Builtin::BI__builtin_memmove:4211  case Builtin::BImemmove:4212  case Builtin::BI__builtin_wmemmove:4213  case Builtin::BIwmemmove:4214    return interp__builtin_memcpy(S, OpPC, Frame, Call, BuiltinID);4215 4216  case Builtin::BI__builtin_memcmp:4217  case Builtin::BImemcmp:4218  case Builtin::BI__builtin_bcmp:4219  case Builtin::BIbcmp:4220  case Builtin::BI__builtin_wmemcmp:4221  case Builtin::BIwmemcmp:4222    return interp__builtin_memcmp(S, OpPC, Frame, Call, BuiltinID);4223 4224  case Builtin::BImemchr:4225  case Builtin::BI__builtin_memchr:4226  case Builtin::BIstrchr:4227  case Builtin::BI__builtin_strchr:4228  case Builtin::BIwmemchr:4229  case Builtin::BI__builtin_wmemchr:4230  case Builtin::BIwcschr:4231  case Builtin::BI__builtin_wcschr:4232  case Builtin::BI__builtin_char_memchr:4233    return interp__builtin_memchr(S, OpPC, Call, BuiltinID);4234 4235  case Builtin::BI__builtin_object_size:4236  case Builtin::BI__builtin_dynamic_object_size:4237    return interp__builtin_object_size(S, OpPC, Frame, Call);4238 4239  case Builtin::BI__builtin_is_within_lifetime:4240    return interp__builtin_is_within_lifetime(S, OpPC, Call);4241 4242  case Builtin::BI__builtin_elementwise_add_sat:4243    return interp__builtin_elementwise_int_binop(4244        S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {4245          return LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS);4246        });4247 4248  case Builtin::BI__builtin_elementwise_sub_sat:4249    return interp__builtin_elementwise_int_binop(4250        S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {4251          return LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS);4252        });4253  case X86::BI__builtin_ia32_extract128i256:4254  case X86::BI__builtin_ia32_vextractf128_pd256:4255  case X86::BI__builtin_ia32_vextractf128_ps256:4256  case X86::BI__builtin_ia32_vextractf128_si256:4257    return interp__builtin_x86_extract_vector(S, OpPC, Call, BuiltinID);4258 4259  case X86::BI__builtin_ia32_extractf32x4_256_mask:4260  case X86::BI__builtin_ia32_extractf32x4_mask:4261  case X86::BI__builtin_ia32_extractf32x8_mask:4262  case X86::BI__builtin_ia32_extractf64x2_256_mask:4263  case X86::BI__builtin_ia32_extractf64x2_512_mask:4264  case X86::BI__builtin_ia32_extractf64x4_mask:4265  case X86::BI__builtin_ia32_extracti32x4_256_mask:4266  case X86::BI__builtin_ia32_extracti32x4_mask:4267  case X86::BI__builtin_ia32_extracti32x8_mask:4268  case X86::BI__builtin_ia32_extracti64x2_256_mask:4269  case X86::BI__builtin_ia32_extracti64x2_512_mask:4270  case X86::BI__builtin_ia32_extracti64x4_mask:4271    return interp__builtin_x86_extract_vector_masked(S, OpPC, Call, BuiltinID);4272 4273  case clang::X86::BI__builtin_ia32_pmulhrsw128:4274  case clang::X86::BI__builtin_ia32_pmulhrsw256:4275  case clang::X86::BI__builtin_ia32_pmulhrsw512:4276    return interp__builtin_elementwise_int_binop(4277        S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {4278          return (llvm::APIntOps::mulsExtended(LHS, RHS).ashr(14) + 1)4279              .extractBits(16, 1);4280        });4281 4282  case clang::X86::BI__builtin_ia32_movmskps:4283  case clang::X86::BI__builtin_ia32_movmskpd:4284  case clang::X86::BI__builtin_ia32_pmovmskb128:4285  case clang::X86::BI__builtin_ia32_pmovmskb256:4286  case clang::X86::BI__builtin_ia32_movmskps256:4287  case clang::X86::BI__builtin_ia32_movmskpd256: {4288    return interp__builtin_ia32_movmsk_op(S, OpPC, Call);4289  }4290 4291  case X86::BI__builtin_ia32_psignb128:4292  case X86::BI__builtin_ia32_psignb256:4293  case X86::BI__builtin_ia32_psignw128:4294  case X86::BI__builtin_ia32_psignw256:4295  case X86::BI__builtin_ia32_psignd128:4296  case X86::BI__builtin_ia32_psignd256:4297    return interp__builtin_elementwise_int_binop(4298        S, OpPC, Call, [](const APInt &AElem, const APInt &BElem) {4299          if (BElem.isZero())4300            return APInt::getZero(AElem.getBitWidth());4301          if (BElem.isNegative())4302            return -AElem;4303          return AElem;4304        });4305 4306  case clang::X86::BI__builtin_ia32_pavgb128:4307  case clang::X86::BI__builtin_ia32_pavgw128:4308  case clang::X86::BI__builtin_ia32_pavgb256:4309  case clang::X86::BI__builtin_ia32_pavgw256:4310  case clang::X86::BI__builtin_ia32_pavgb512:4311  case clang::X86::BI__builtin_ia32_pavgw512:4312    return interp__builtin_elementwise_int_binop(S, OpPC, Call,4313                                                 llvm::APIntOps::avgCeilU);4314 4315  case clang::X86::BI__builtin_ia32_pmaddubsw128:4316  case clang::X86::BI__builtin_ia32_pmaddubsw256:4317  case clang::X86::BI__builtin_ia32_pmaddubsw512:4318    return interp__builtin_ia32_pmul(4319        S, OpPC, Call,4320        [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,4321           const APSInt &HiRHS) {4322          unsigned BitWidth = 2 * LoLHS.getBitWidth();4323          return (LoLHS.zext(BitWidth) * LoRHS.sext(BitWidth))4324              .sadd_sat((HiLHS.zext(BitWidth) * HiRHS.sext(BitWidth)));4325        });4326 4327  case clang::X86::BI__builtin_ia32_pmaddwd128:4328  case clang::X86::BI__builtin_ia32_pmaddwd256:4329  case clang::X86::BI__builtin_ia32_pmaddwd512:4330    return interp__builtin_ia32_pmul(4331        S, OpPC, Call,4332        [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,4333           const APSInt &HiRHS) {4334          unsigned BitWidth = 2 * LoLHS.getBitWidth();4335          return (LoLHS.sext(BitWidth) * LoRHS.sext(BitWidth)) +4336                 (HiLHS.sext(BitWidth) * HiRHS.sext(BitWidth));4337        });4338 4339  case clang::X86::BI__builtin_ia32_pmulhuw128:4340  case clang::X86::BI__builtin_ia32_pmulhuw256:4341  case clang::X86::BI__builtin_ia32_pmulhuw512:4342    return interp__builtin_elementwise_int_binop(S, OpPC, Call,4343                                                 llvm::APIntOps::mulhu);4344 4345  case clang::X86::BI__builtin_ia32_pmulhw128:4346  case clang::X86::BI__builtin_ia32_pmulhw256:4347  case clang::X86::BI__builtin_ia32_pmulhw512:4348    return interp__builtin_elementwise_int_binop(S, OpPC, Call,4349                                                 llvm::APIntOps::mulhs);4350 4351  case clang::X86::BI__builtin_ia32_psllv2di:4352  case clang::X86::BI__builtin_ia32_psllv4di:4353  case clang::X86::BI__builtin_ia32_psllv4si:4354  case clang::X86::BI__builtin_ia32_psllv8di:4355  case clang::X86::BI__builtin_ia32_psllv8hi:4356  case clang::X86::BI__builtin_ia32_psllv8si:4357  case clang::X86::BI__builtin_ia32_psllv16hi:4358  case clang::X86::BI__builtin_ia32_psllv16si:4359  case clang::X86::BI__builtin_ia32_psllv32hi:4360  case clang::X86::BI__builtin_ia32_psllwi128:4361  case clang::X86::BI__builtin_ia32_psllwi256:4362  case clang::X86::BI__builtin_ia32_psllwi512:4363  case clang::X86::BI__builtin_ia32_pslldi128:4364  case clang::X86::BI__builtin_ia32_pslldi256:4365  case clang::X86::BI__builtin_ia32_pslldi512:4366  case clang::X86::BI__builtin_ia32_psllqi128:4367  case clang::X86::BI__builtin_ia32_psllqi256:4368  case clang::X86::BI__builtin_ia32_psllqi512:4369    return interp__builtin_elementwise_int_binop(4370        S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {4371          if (RHS.uge(LHS.getBitWidth())) {4372            return APInt::getZero(LHS.getBitWidth());4373          }4374          return LHS.shl(RHS.getZExtValue());4375        });4376 4377  case clang::X86::BI__builtin_ia32_psrav4si:4378  case clang::X86::BI__builtin_ia32_psrav8di:4379  case clang::X86::BI__builtin_ia32_psrav8hi:4380  case clang::X86::BI__builtin_ia32_psrav8si:4381  case clang::X86::BI__builtin_ia32_psrav16hi:4382  case clang::X86::BI__builtin_ia32_psrav16si:4383  case clang::X86::BI__builtin_ia32_psrav32hi:4384  case clang::X86::BI__builtin_ia32_psravq128:4385  case clang::X86::BI__builtin_ia32_psravq256:4386  case clang::X86::BI__builtin_ia32_psrawi128:4387  case clang::X86::BI__builtin_ia32_psrawi256:4388  case clang::X86::BI__builtin_ia32_psrawi512:4389  case clang::X86::BI__builtin_ia32_psradi128:4390  case clang::X86::BI__builtin_ia32_psradi256:4391  case clang::X86::BI__builtin_ia32_psradi512:4392  case clang::X86::BI__builtin_ia32_psraqi128:4393  case clang::X86::BI__builtin_ia32_psraqi256:4394  case clang::X86::BI__builtin_ia32_psraqi512:4395    return interp__builtin_elementwise_int_binop(4396        S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {4397          if (RHS.uge(LHS.getBitWidth())) {4398            return LHS.ashr(LHS.getBitWidth() - 1);4399          }4400          return LHS.ashr(RHS.getZExtValue());4401        });4402 4403  case clang::X86::BI__builtin_ia32_psrlv2di:4404  case clang::X86::BI__builtin_ia32_psrlv4di:4405  case clang::X86::BI__builtin_ia32_psrlv4si:4406  case clang::X86::BI__builtin_ia32_psrlv8di:4407  case clang::X86::BI__builtin_ia32_psrlv8hi:4408  case clang::X86::BI__builtin_ia32_psrlv8si:4409  case clang::X86::BI__builtin_ia32_psrlv16hi:4410  case clang::X86::BI__builtin_ia32_psrlv16si:4411  case clang::X86::BI__builtin_ia32_psrlv32hi:4412  case clang::X86::BI__builtin_ia32_psrlwi128:4413  case clang::X86::BI__builtin_ia32_psrlwi256:4414  case clang::X86::BI__builtin_ia32_psrlwi512:4415  case clang::X86::BI__builtin_ia32_psrldi128:4416  case clang::X86::BI__builtin_ia32_psrldi256:4417  case clang::X86::BI__builtin_ia32_psrldi512:4418  case clang::X86::BI__builtin_ia32_psrlqi128:4419  case clang::X86::BI__builtin_ia32_psrlqi256:4420  case clang::X86::BI__builtin_ia32_psrlqi512:4421    return interp__builtin_elementwise_int_binop(4422        S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {4423          if (RHS.uge(LHS.getBitWidth())) {4424            return APInt::getZero(LHS.getBitWidth());4425          }4426          return LHS.lshr(RHS.getZExtValue());4427        });4428  case clang::X86::BI__builtin_ia32_packsswb128:4429  case clang::X86::BI__builtin_ia32_packsswb256:4430  case clang::X86::BI__builtin_ia32_packsswb512:4431  case clang::X86::BI__builtin_ia32_packssdw128:4432  case clang::X86::BI__builtin_ia32_packssdw256:4433  case clang::X86::BI__builtin_ia32_packssdw512:4434    return interp__builtin_x86_pack(S, OpPC, Call, [](const APSInt &Src) {4435      return APInt(Src).truncSSat(Src.getBitWidth() / 2);4436    });4437  case clang::X86::BI__builtin_ia32_packusdw128:4438  case clang::X86::BI__builtin_ia32_packusdw256:4439  case clang::X86::BI__builtin_ia32_packusdw512:4440  case clang::X86::BI__builtin_ia32_packuswb128:4441  case clang::X86::BI__builtin_ia32_packuswb256:4442  case clang::X86::BI__builtin_ia32_packuswb512:4443    return interp__builtin_x86_pack(S, OpPC, Call, [](const APSInt &Src) {4444      unsigned DstBits = Src.getBitWidth() / 2;4445      if (Src.isNegative())4446        return APInt::getZero(DstBits);4447      if (Src.isIntN(DstBits))4448        return APInt(Src).trunc(DstBits);4449      return APInt::getAllOnes(DstBits);4450    });4451 4452  case clang::X86::BI__builtin_ia32_selectss_128:4453  case clang::X86::BI__builtin_ia32_selectsd_128:4454  case clang::X86::BI__builtin_ia32_selectsh_128:4455  case clang::X86::BI__builtin_ia32_selectsbf_128:4456    return interp__builtin_select_scalar(S, Call);4457  case clang::X86::BI__builtin_ia32_vprotbi:4458  case clang::X86::BI__builtin_ia32_vprotdi:4459  case clang::X86::BI__builtin_ia32_vprotqi:4460  case clang::X86::BI__builtin_ia32_vprotwi:4461  case clang::X86::BI__builtin_ia32_prold128:4462  case clang::X86::BI__builtin_ia32_prold256:4463  case clang::X86::BI__builtin_ia32_prold512:4464  case clang::X86::BI__builtin_ia32_prolq128:4465  case clang::X86::BI__builtin_ia32_prolq256:4466  case clang::X86::BI__builtin_ia32_prolq512:4467    return interp__builtin_elementwise_int_binop(4468        S, OpPC, Call,4469        [](const APSInt &LHS, const APSInt &RHS) { return LHS.rotl(RHS); });4470 4471  case clang::X86::BI__builtin_ia32_prord128:4472  case clang::X86::BI__builtin_ia32_prord256:4473  case clang::X86::BI__builtin_ia32_prord512:4474  case clang::X86::BI__builtin_ia32_prorq128:4475  case clang::X86::BI__builtin_ia32_prorq256:4476  case clang::X86::BI__builtin_ia32_prorq512:4477    return interp__builtin_elementwise_int_binop(4478        S, OpPC, Call,4479        [](const APSInt &LHS, const APSInt &RHS) { return LHS.rotr(RHS); });4480 4481  case Builtin::BI__builtin_elementwise_max:4482  case Builtin::BI__builtin_elementwise_min:4483    return interp__builtin_elementwise_maxmin(S, OpPC, Call, BuiltinID);4484 4485  case clang::X86::BI__builtin_ia32_phaddw128:4486  case clang::X86::BI__builtin_ia32_phaddw256:4487  case clang::X86::BI__builtin_ia32_phaddd128:4488  case clang::X86::BI__builtin_ia32_phaddd256:4489    return interp_builtin_horizontal_int_binop(4490        S, OpPC, Call,4491        [](const APSInt &LHS, const APSInt &RHS) { return LHS + RHS; });4492  case clang::X86::BI__builtin_ia32_phaddsw128:4493  case clang::X86::BI__builtin_ia32_phaddsw256:4494    return interp_builtin_horizontal_int_binop(4495        S, OpPC, Call,4496        [](const APSInt &LHS, const APSInt &RHS) { return LHS.sadd_sat(RHS); });4497  case clang::X86::BI__builtin_ia32_phsubw128:4498  case clang::X86::BI__builtin_ia32_phsubw256:4499  case clang::X86::BI__builtin_ia32_phsubd128:4500  case clang::X86::BI__builtin_ia32_phsubd256:4501    return interp_builtin_horizontal_int_binop(4502        S, OpPC, Call,4503        [](const APSInt &LHS, const APSInt &RHS) { return LHS - RHS; });4504  case clang::X86::BI__builtin_ia32_phsubsw128:4505  case clang::X86::BI__builtin_ia32_phsubsw256:4506    return interp_builtin_horizontal_int_binop(4507        S, OpPC, Call,4508        [](const APSInt &LHS, const APSInt &RHS) { return LHS.ssub_sat(RHS); });4509  case clang::X86::BI__builtin_ia32_haddpd:4510  case clang::X86::BI__builtin_ia32_haddps:4511  case clang::X86::BI__builtin_ia32_haddpd256:4512  case clang::X86::BI__builtin_ia32_haddps256:4513    return interp_builtin_horizontal_fp_binop(4514        S, OpPC, Call,4515        [](const APFloat &LHS, const APFloat &RHS, llvm::RoundingMode RM) {4516          APFloat F = LHS;4517          F.add(RHS, RM);4518          return F;4519        });4520  case clang::X86::BI__builtin_ia32_hsubpd:4521  case clang::X86::BI__builtin_ia32_hsubps:4522  case clang::X86::BI__builtin_ia32_hsubpd256:4523  case clang::X86::BI__builtin_ia32_hsubps256:4524    return interp_builtin_horizontal_fp_binop(4525        S, OpPC, Call,4526        [](const APFloat &LHS, const APFloat &RHS, llvm::RoundingMode RM) {4527          APFloat F = LHS;4528          F.subtract(RHS, RM);4529          return F;4530        });4531  case clang::X86::BI__builtin_ia32_addsubpd:4532  case clang::X86::BI__builtin_ia32_addsubps:4533  case clang::X86::BI__builtin_ia32_addsubpd256:4534  case clang::X86::BI__builtin_ia32_addsubps256:4535    return interp__builtin_ia32_addsub(S, OpPC, Call);4536 4537  case clang::X86::BI__builtin_ia32_pmuldq128:4538  case clang::X86::BI__builtin_ia32_pmuldq256:4539  case clang::X86::BI__builtin_ia32_pmuldq512:4540    return interp__builtin_ia32_pmul(4541        S, OpPC, Call,4542        [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,4543           const APSInt &HiRHS) {4544          return llvm::APIntOps::mulsExtended(LoLHS, LoRHS);4545        });4546 4547  case clang::X86::BI__builtin_ia32_pmuludq128:4548  case clang::X86::BI__builtin_ia32_pmuludq256:4549  case clang::X86::BI__builtin_ia32_pmuludq512:4550    return interp__builtin_ia32_pmul(4551        S, OpPC, Call,4552        [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,4553           const APSInt &HiRHS) {4554          return llvm::APIntOps::muluExtended(LoLHS, LoRHS);4555        });4556 4557  case Builtin::BI__builtin_elementwise_fma:4558    return interp__builtin_elementwise_triop_fp(4559        S, OpPC, Call,4560        [](const APFloat &X, const APFloat &Y, const APFloat &Z,4561           llvm::RoundingMode RM) {4562          APFloat F = X;4563          F.fusedMultiplyAdd(Y, Z, RM);4564          return F;4565        });4566 4567  case X86::BI__builtin_ia32_vpmadd52luq128:4568  case X86::BI__builtin_ia32_vpmadd52luq256:4569  case X86::BI__builtin_ia32_vpmadd52luq512:4570    return interp__builtin_elementwise_triop(4571        S, OpPC, Call, [](const APSInt &A, const APSInt &B, const APSInt &C) {4572          return A + (B.trunc(52) * C.trunc(52)).zext(64);4573        });4574  case X86::BI__builtin_ia32_vpmadd52huq128:4575  case X86::BI__builtin_ia32_vpmadd52huq256:4576  case X86::BI__builtin_ia32_vpmadd52huq512:4577    return interp__builtin_elementwise_triop(4578        S, OpPC, Call, [](const APSInt &A, const APSInt &B, const APSInt &C) {4579          return A + llvm::APIntOps::mulhu(B.trunc(52), C.trunc(52)).zext(64);4580        });4581 4582  case X86::BI__builtin_ia32_vpshldd128:4583  case X86::BI__builtin_ia32_vpshldd256:4584  case X86::BI__builtin_ia32_vpshldd512:4585  case X86::BI__builtin_ia32_vpshldq128:4586  case X86::BI__builtin_ia32_vpshldq256:4587  case X86::BI__builtin_ia32_vpshldq512:4588  case X86::BI__builtin_ia32_vpshldw128:4589  case X86::BI__builtin_ia32_vpshldw256:4590  case X86::BI__builtin_ia32_vpshldw512:4591    return interp__builtin_elementwise_triop(4592        S, OpPC, Call,4593        [](const APSInt &Hi, const APSInt &Lo, const APSInt &Amt) {4594          return llvm::APIntOps::fshl(Hi, Lo, Amt);4595        });4596 4597  case X86::BI__builtin_ia32_vpshrdd128:4598  case X86::BI__builtin_ia32_vpshrdd256:4599  case X86::BI__builtin_ia32_vpshrdd512:4600  case X86::BI__builtin_ia32_vpshrdq128:4601  case X86::BI__builtin_ia32_vpshrdq256:4602  case X86::BI__builtin_ia32_vpshrdq512:4603  case X86::BI__builtin_ia32_vpshrdw128:4604  case X86::BI__builtin_ia32_vpshrdw256:4605  case X86::BI__builtin_ia32_vpshrdw512:4606    // NOTE: Reversed Hi/Lo operands.4607    return interp__builtin_elementwise_triop(4608        S, OpPC, Call,4609        [](const APSInt &Lo, const APSInt &Hi, const APSInt &Amt) {4610          return llvm::APIntOps::fshr(Hi, Lo, Amt);4611        });4612  case X86::BI__builtin_ia32_vpconflictsi_128:4613  case X86::BI__builtin_ia32_vpconflictsi_256:4614  case X86::BI__builtin_ia32_vpconflictsi_512:4615  case X86::BI__builtin_ia32_vpconflictdi_128:4616  case X86::BI__builtin_ia32_vpconflictdi_256:4617  case X86::BI__builtin_ia32_vpconflictdi_512:4618    return interp__builtin_ia32_vpconflict(S, OpPC, Call);4619  case clang::X86::BI__builtin_ia32_blendpd:4620  case clang::X86::BI__builtin_ia32_blendpd256:4621  case clang::X86::BI__builtin_ia32_blendps:4622  case clang::X86::BI__builtin_ia32_blendps256:4623  case clang::X86::BI__builtin_ia32_pblendw128:4624  case clang::X86::BI__builtin_ia32_pblendw256:4625  case clang::X86::BI__builtin_ia32_pblendd128:4626  case clang::X86::BI__builtin_ia32_pblendd256:4627    return interp__builtin_blend(S, OpPC, Call);4628 4629  case clang::X86::BI__builtin_ia32_blendvpd:4630  case clang::X86::BI__builtin_ia32_blendvpd256:4631  case clang::X86::BI__builtin_ia32_blendvps:4632  case clang::X86::BI__builtin_ia32_blendvps256:4633    return interp__builtin_elementwise_triop_fp(4634        S, OpPC, Call,4635        [](const APFloat &F, const APFloat &T, const APFloat &C,4636           llvm::RoundingMode) { return C.isNegative() ? T : F; });4637 4638  case clang::X86::BI__builtin_ia32_pblendvb128:4639  case clang::X86::BI__builtin_ia32_pblendvb256:4640    return interp__builtin_elementwise_triop(4641        S, OpPC, Call, [](const APSInt &F, const APSInt &T, const APSInt &C) {4642          return ((APInt)C).isNegative() ? T : F;4643        });4644  case X86::BI__builtin_ia32_ptestz128:4645  case X86::BI__builtin_ia32_ptestz256:4646  case X86::BI__builtin_ia32_vtestzps:4647  case X86::BI__builtin_ia32_vtestzps256:4648  case X86::BI__builtin_ia32_vtestzpd:4649  case X86::BI__builtin_ia32_vtestzpd256:4650    return interp__builtin_ia32_test_op(4651        S, OpPC, Call,4652        [](const APInt &A, const APInt &B) { return (A & B) == 0; });4653  case X86::BI__builtin_ia32_ptestc128:4654  case X86::BI__builtin_ia32_ptestc256:4655  case X86::BI__builtin_ia32_vtestcps:4656  case X86::BI__builtin_ia32_vtestcps256:4657  case X86::BI__builtin_ia32_vtestcpd:4658  case X86::BI__builtin_ia32_vtestcpd256:4659    return interp__builtin_ia32_test_op(4660        S, OpPC, Call,4661        [](const APInt &A, const APInt &B) { return (~A & B) == 0; });4662  case X86::BI__builtin_ia32_ptestnzc128:4663  case X86::BI__builtin_ia32_ptestnzc256:4664  case X86::BI__builtin_ia32_vtestnzcps:4665  case X86::BI__builtin_ia32_vtestnzcps256:4666  case X86::BI__builtin_ia32_vtestnzcpd:4667  case X86::BI__builtin_ia32_vtestnzcpd256:4668    return interp__builtin_ia32_test_op(4669        S, OpPC, Call, [](const APInt &A, const APInt &B) {4670          return ((A & B) != 0) && ((~A & B) != 0);4671        });4672  case X86::BI__builtin_ia32_selectb_128:4673  case X86::BI__builtin_ia32_selectb_256:4674  case X86::BI__builtin_ia32_selectb_512:4675  case X86::BI__builtin_ia32_selectw_128:4676  case X86::BI__builtin_ia32_selectw_256:4677  case X86::BI__builtin_ia32_selectw_512:4678  case X86::BI__builtin_ia32_selectd_128:4679  case X86::BI__builtin_ia32_selectd_256:4680  case X86::BI__builtin_ia32_selectd_512:4681  case X86::BI__builtin_ia32_selectq_128:4682  case X86::BI__builtin_ia32_selectq_256:4683  case X86::BI__builtin_ia32_selectq_512:4684  case X86::BI__builtin_ia32_selectph_128:4685  case X86::BI__builtin_ia32_selectph_256:4686  case X86::BI__builtin_ia32_selectph_512:4687  case X86::BI__builtin_ia32_selectpbf_128:4688  case X86::BI__builtin_ia32_selectpbf_256:4689  case X86::BI__builtin_ia32_selectpbf_512:4690  case X86::BI__builtin_ia32_selectps_128:4691  case X86::BI__builtin_ia32_selectps_256:4692  case X86::BI__builtin_ia32_selectps_512:4693  case X86::BI__builtin_ia32_selectpd_128:4694  case X86::BI__builtin_ia32_selectpd_256:4695  case X86::BI__builtin_ia32_selectpd_512:4696    return interp__builtin_select(S, OpPC, Call);4697 4698  case X86::BI__builtin_ia32_shufps:4699  case X86::BI__builtin_ia32_shufps256:4700  case X86::BI__builtin_ia32_shufps512:4701    return interp__builtin_ia32_shuffle_generic(4702        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4703          unsigned NumElemPerLane = 4;4704          unsigned NumSelectableElems = NumElemPerLane / 2;4705          unsigned BitsPerElem = 2;4706          unsigned IndexMask = 0x3;4707          unsigned MaskBits = 8;4708          unsigned Lane = DstIdx / NumElemPerLane;4709          unsigned ElemInLane = DstIdx % NumElemPerLane;4710          unsigned LaneOffset = Lane * NumElemPerLane;4711          unsigned SrcIdx = ElemInLane >= NumSelectableElems ? 1 : 0;4712          unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;4713          unsigned Index = (ShuffleMask >> BitIndex) & IndexMask;4714          return std::pair<unsigned, int>{SrcIdx,4715                                          static_cast<int>(LaneOffset + Index)};4716        });4717  case X86::BI__builtin_ia32_shufpd:4718  case X86::BI__builtin_ia32_shufpd256:4719  case X86::BI__builtin_ia32_shufpd512:4720    return interp__builtin_ia32_shuffle_generic(4721        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4722          unsigned NumElemPerLane = 2;4723          unsigned NumSelectableElems = NumElemPerLane / 2;4724          unsigned BitsPerElem = 1;4725          unsigned IndexMask = 0x1;4726          unsigned MaskBits = 8;4727          unsigned Lane = DstIdx / NumElemPerLane;4728          unsigned ElemInLane = DstIdx % NumElemPerLane;4729          unsigned LaneOffset = Lane * NumElemPerLane;4730          unsigned SrcIdx = ElemInLane >= NumSelectableElems ? 1 : 0;4731          unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;4732          unsigned Index = (ShuffleMask >> BitIndex) & IndexMask;4733          return std::pair<unsigned, int>{SrcIdx,4734                                          static_cast<int>(LaneOffset + Index)};4735        });4736  case X86::BI__builtin_ia32_insertps128:4737    return interp__builtin_ia32_shuffle_generic(4738        S, OpPC, Call, [](unsigned DstIdx, unsigned Mask) {4739          // Bits [3:0]: zero mask - if bit is set, zero this element4740          if ((Mask & (1 << DstIdx)) != 0) {4741            return std::pair<unsigned, int>{0, -1};4742          }4743          // Bits [7:6]: select element from source vector Y (0-3)4744          // Bits [5:4]: select destination position (0-3)4745          unsigned SrcElem = (Mask >> 6) & 0x3;4746          unsigned DstElem = (Mask >> 4) & 0x3;4747          if (DstIdx == DstElem) {4748            // Insert element from source vector (B) at this position4749            return std::pair<unsigned, int>{1, static_cast<int>(SrcElem)};4750          } else {4751            // Copy from destination vector (A)4752            return std::pair<unsigned, int>{0, static_cast<int>(DstIdx)};4753          }4754        });4755  case X86::BI__builtin_ia32_permvarsi256:4756  case X86::BI__builtin_ia32_permvarsf256:4757  case X86::BI__builtin_ia32_permvardf512:4758  case X86::BI__builtin_ia32_permvardi512:4759  case X86::BI__builtin_ia32_permvarhi128:4760    return interp__builtin_ia32_shuffle_generic(4761        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4762          int Offset = ShuffleMask & 0x7;4763          return std::pair<unsigned, int>{0, Offset};4764        });4765  case X86::BI__builtin_ia32_permvarqi128:4766  case X86::BI__builtin_ia32_permvarhi256:4767  case X86::BI__builtin_ia32_permvarsi512:4768  case X86::BI__builtin_ia32_permvarsf512:4769    return interp__builtin_ia32_shuffle_generic(4770        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4771          int Offset = ShuffleMask & 0xF;4772          return std::pair<unsigned, int>{0, Offset};4773        });4774  case X86::BI__builtin_ia32_permvardi256:4775  case X86::BI__builtin_ia32_permvardf256:4776    return interp__builtin_ia32_shuffle_generic(4777        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4778          int Offset = ShuffleMask & 0x3;4779          return std::pair<unsigned, int>{0, Offset};4780        });4781  case X86::BI__builtin_ia32_permvarqi256:4782  case X86::BI__builtin_ia32_permvarhi512:4783    return interp__builtin_ia32_shuffle_generic(4784        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4785          int Offset = ShuffleMask & 0x1F;4786          return std::pair<unsigned, int>{0, Offset};4787        });4788  case X86::BI__builtin_ia32_permvarqi512:4789    return interp__builtin_ia32_shuffle_generic(4790        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4791          int Offset = ShuffleMask & 0x3F;4792          return std::pair<unsigned, int>{0, Offset};4793        });4794  case X86::BI__builtin_ia32_vpermi2varq128:4795  case X86::BI__builtin_ia32_vpermi2varpd128:4796    return interp__builtin_ia32_shuffle_generic(4797        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4798          int Offset = ShuffleMask & 0x1;4799          unsigned SrcIdx = (ShuffleMask >> 1) & 0x1;4800          return std::pair<unsigned, int>{SrcIdx, Offset};4801        });4802  case X86::BI__builtin_ia32_vpermi2vard128:4803  case X86::BI__builtin_ia32_vpermi2varps128:4804  case X86::BI__builtin_ia32_vpermi2varq256:4805  case X86::BI__builtin_ia32_vpermi2varpd256:4806    return interp__builtin_ia32_shuffle_generic(4807        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4808          int Offset = ShuffleMask & 0x3;4809          unsigned SrcIdx = (ShuffleMask >> 2) & 0x1;4810          return std::pair<unsigned, int>{SrcIdx, Offset};4811        });4812  case X86::BI__builtin_ia32_vpermi2varhi128:4813  case X86::BI__builtin_ia32_vpermi2vard256:4814  case X86::BI__builtin_ia32_vpermi2varps256:4815  case X86::BI__builtin_ia32_vpermi2varq512:4816  case X86::BI__builtin_ia32_vpermi2varpd512:4817    return interp__builtin_ia32_shuffle_generic(4818        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4819          int Offset = ShuffleMask & 0x7;4820          unsigned SrcIdx = (ShuffleMask >> 3) & 0x1;4821          return std::pair<unsigned, int>{SrcIdx, Offset};4822        });4823  case X86::BI__builtin_ia32_vpermi2varqi128:4824  case X86::BI__builtin_ia32_vpermi2varhi256:4825  case X86::BI__builtin_ia32_vpermi2vard512:4826  case X86::BI__builtin_ia32_vpermi2varps512:4827    return interp__builtin_ia32_shuffle_generic(4828        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4829          int Offset = ShuffleMask & 0xF;4830          unsigned SrcIdx = (ShuffleMask >> 4) & 0x1;4831          return std::pair<unsigned, int>{SrcIdx, Offset};4832        });4833  case X86::BI__builtin_ia32_vpermi2varqi256:4834  case X86::BI__builtin_ia32_vpermi2varhi512:4835    return interp__builtin_ia32_shuffle_generic(4836        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4837          int Offset = ShuffleMask & 0x1F;4838          unsigned SrcIdx = (ShuffleMask >> 5) & 0x1;4839          return std::pair<unsigned, int>{SrcIdx, Offset};4840        });4841  case X86::BI__builtin_ia32_vpermi2varqi512:4842    return interp__builtin_ia32_shuffle_generic(4843        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4844          int Offset = ShuffleMask & 0x3F;4845          unsigned SrcIdx = (ShuffleMask >> 6) & 0x1;4846          return std::pair<unsigned, int>{SrcIdx, Offset};4847        });4848  case X86::BI__builtin_ia32_pshufb128:4849  case X86::BI__builtin_ia32_pshufb256:4850  case X86::BI__builtin_ia32_pshufb512:4851    return interp__builtin_ia32_shuffle_generic(4852        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4853          uint8_t Ctlb = static_cast<uint8_t>(ShuffleMask);4854          if (Ctlb & 0x80)4855            return std::make_pair(0, -1);4856 4857          unsigned LaneBase = (DstIdx / 16) * 16;4858          unsigned SrcOffset = Ctlb & 0x0F;4859          unsigned SrcIdx = LaneBase + SrcOffset;4860          return std::make_pair(0, static_cast<int>(SrcIdx));4861        });4862 4863  case X86::BI__builtin_ia32_pshuflw:4864  case X86::BI__builtin_ia32_pshuflw256:4865  case X86::BI__builtin_ia32_pshuflw512:4866    return interp__builtin_ia32_shuffle_generic(4867        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4868          unsigned LaneBase = (DstIdx / 8) * 8;4869          unsigned LaneIdx = DstIdx % 8;4870          if (LaneIdx < 4) {4871            unsigned Sel = (ShuffleMask >> (2 * LaneIdx)) & 0x3;4872            return std::make_pair(0, static_cast<int>(LaneBase + Sel));4873          }4874 4875          return std::make_pair(0, static_cast<int>(DstIdx));4876        });4877 4878  case X86::BI__builtin_ia32_pshufhw:4879  case X86::BI__builtin_ia32_pshufhw256:4880  case X86::BI__builtin_ia32_pshufhw512:4881    return interp__builtin_ia32_shuffle_generic(4882        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4883          unsigned LaneBase = (DstIdx / 8) * 8;4884          unsigned LaneIdx = DstIdx % 8;4885          if (LaneIdx >= 4) {4886            unsigned Sel = (ShuffleMask >> (2 * (LaneIdx - 4))) & 0x3;4887            return std::make_pair(0, static_cast<int>(LaneBase + 4 + Sel));4888          }4889 4890          return std::make_pair(0, static_cast<int>(DstIdx));4891        });4892 4893  case X86::BI__builtin_ia32_pshufd:4894  case X86::BI__builtin_ia32_pshufd256:4895  case X86::BI__builtin_ia32_pshufd512:4896  case X86::BI__builtin_ia32_vpermilps:4897  case X86::BI__builtin_ia32_vpermilps256:4898  case X86::BI__builtin_ia32_vpermilps512:4899    return interp__builtin_ia32_shuffle_generic(4900        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4901          unsigned LaneBase = (DstIdx / 4) * 4;4902          unsigned LaneIdx = DstIdx % 4;4903          unsigned Sel = (ShuffleMask >> (2 * LaneIdx)) & 0x3;4904          return std::make_pair(0, static_cast<int>(LaneBase + Sel));4905        });4906 4907  case X86::BI__builtin_ia32_vpermilvarpd:4908  case X86::BI__builtin_ia32_vpermilvarpd256:4909  case X86::BI__builtin_ia32_vpermilvarpd512:4910    return interp__builtin_ia32_shuffle_generic(4911        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4912          unsigned NumElemPerLane = 2;4913          unsigned Lane = DstIdx / NumElemPerLane;4914          unsigned Offset = ShuffleMask & 0b10 ? 1 : 0;4915          return std::make_pair(4916              0, static_cast<int>(Lane * NumElemPerLane + Offset));4917        });4918 4919  case X86::BI__builtin_ia32_vpermilvarps:4920  case X86::BI__builtin_ia32_vpermilvarps256:4921  case X86::BI__builtin_ia32_vpermilvarps512:4922    return interp__builtin_ia32_shuffle_generic(4923        S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {4924          unsigned NumElemPerLane = 4;4925          unsigned Lane = DstIdx / NumElemPerLane;4926          unsigned Offset = ShuffleMask & 0b11;4927          return std::make_pair(4928              0, static_cast<int>(Lane * NumElemPerLane + Offset));4929        });4930 4931  case X86::BI__builtin_ia32_vpermilpd:4932  case X86::BI__builtin_ia32_vpermilpd256:4933  case X86::BI__builtin_ia32_vpermilpd512:4934    return interp__builtin_ia32_shuffle_generic(4935        S, OpPC, Call, [](unsigned DstIdx, unsigned Control) {4936          unsigned NumElemPerLane = 2;4937          unsigned BitsPerElem = 1;4938          unsigned MaskBits = 8;4939          unsigned IndexMask = 0x1;4940          unsigned Lane = DstIdx / NumElemPerLane;4941          unsigned LaneOffset = Lane * NumElemPerLane;4942          unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;4943          unsigned Index = (Control >> BitIndex) & IndexMask;4944          return std::make_pair(0, static_cast<int>(LaneOffset + Index));4945        });4946 4947  case X86::BI__builtin_ia32_vpmultishiftqb128:4948  case X86::BI__builtin_ia32_vpmultishiftqb256:4949  case X86::BI__builtin_ia32_vpmultishiftqb512:4950    return interp__builtin_ia32_multishiftqb(S, OpPC, Call);4951  case X86::BI__builtin_ia32_kandqi:4952  case X86::BI__builtin_ia32_kandhi:4953  case X86::BI__builtin_ia32_kandsi:4954  case X86::BI__builtin_ia32_kanddi:4955    return interp__builtin_elementwise_int_binop(4956        S, OpPC, Call,4957        [](const APSInt &LHS, const APSInt &RHS) { return LHS & RHS; });4958 4959  case X86::BI__builtin_ia32_kandnqi:4960  case X86::BI__builtin_ia32_kandnhi:4961  case X86::BI__builtin_ia32_kandnsi:4962  case X86::BI__builtin_ia32_kandndi:4963    return interp__builtin_elementwise_int_binop(4964        S, OpPC, Call,4965        [](const APSInt &LHS, const APSInt &RHS) { return ~LHS & RHS; });4966 4967  case X86::BI__builtin_ia32_korqi:4968  case X86::BI__builtin_ia32_korhi:4969  case X86::BI__builtin_ia32_korsi:4970  case X86::BI__builtin_ia32_kordi:4971    return interp__builtin_elementwise_int_binop(4972        S, OpPC, Call,4973        [](const APSInt &LHS, const APSInt &RHS) { return LHS | RHS; });4974 4975  case X86::BI__builtin_ia32_kxnorqi:4976  case X86::BI__builtin_ia32_kxnorhi:4977  case X86::BI__builtin_ia32_kxnorsi:4978  case X86::BI__builtin_ia32_kxnordi:4979    return interp__builtin_elementwise_int_binop(4980        S, OpPC, Call,4981        [](const APSInt &LHS, const APSInt &RHS) { return ~(LHS ^ RHS); });4982 4983  case X86::BI__builtin_ia32_kxorqi:4984  case X86::BI__builtin_ia32_kxorhi:4985  case X86::BI__builtin_ia32_kxorsi:4986  case X86::BI__builtin_ia32_kxordi:4987    return interp__builtin_elementwise_int_binop(4988        S, OpPC, Call,4989        [](const APSInt &LHS, const APSInt &RHS) { return LHS ^ RHS; });4990 4991  case X86::BI__builtin_ia32_knotqi:4992  case X86::BI__builtin_ia32_knothi:4993  case X86::BI__builtin_ia32_knotsi:4994  case X86::BI__builtin_ia32_knotdi:4995    return interp__builtin_elementwise_int_unaryop(4996        S, OpPC, Call, [](const APSInt &Src) { return ~Src; });4997 4998  case X86::BI__builtin_ia32_kaddqi:4999  case X86::BI__builtin_ia32_kaddhi:5000  case X86::BI__builtin_ia32_kaddsi:5001  case X86::BI__builtin_ia32_kadddi:5002    return interp__builtin_elementwise_int_binop(5003        S, OpPC, Call,5004        [](const APSInt &LHS, const APSInt &RHS) { return LHS + RHS; });5005 5006  case X86::BI__builtin_ia32_kmovb:5007  case X86::BI__builtin_ia32_kmovw:5008  case X86::BI__builtin_ia32_kmovd:5009  case X86::BI__builtin_ia32_kmovq:5010    return interp__builtin_elementwise_int_unaryop(5011        S, OpPC, Call, [](const APSInt &Src) { return Src; });5012 5013  case X86::BI__builtin_ia32_kunpckhi:5014  case X86::BI__builtin_ia32_kunpckdi:5015  case X86::BI__builtin_ia32_kunpcksi:5016    return interp__builtin_elementwise_int_binop(5017        S, OpPC, Call, [](const APSInt &A, const APSInt &B) {5018          // Generic kunpack: extract lower half of each operand and concatenate5019          // Result = A[HalfWidth-1:0] concat B[HalfWidth-1:0]5020          unsigned BW = A.getBitWidth();5021          return APSInt(A.trunc(BW / 2).concat(B.trunc(BW / 2)),5022                        A.isUnsigned());5023        });5024 5025  case X86::BI__builtin_ia32_phminposuw128:5026    return interp__builtin_ia32_phminposuw(S, OpPC, Call);5027 5028  case X86::BI__builtin_ia32_psraq128:5029  case X86::BI__builtin_ia32_psraq256:5030  case X86::BI__builtin_ia32_psraq512:5031  case X86::BI__builtin_ia32_psrad128:5032  case X86::BI__builtin_ia32_psrad256:5033  case X86::BI__builtin_ia32_psrad512:5034  case X86::BI__builtin_ia32_psraw128:5035  case X86::BI__builtin_ia32_psraw256:5036  case X86::BI__builtin_ia32_psraw512:5037    return interp__builtin_ia32_shift_with_count(5038        S, OpPC, Call,5039        [](const APInt &Elt, uint64_t Count) { return Elt.ashr(Count); },5040        [](const APInt &Elt, unsigned Width) { return Elt.ashr(Width - 1); });5041 5042  case X86::BI__builtin_ia32_psllq128:5043  case X86::BI__builtin_ia32_psllq256:5044  case X86::BI__builtin_ia32_psllq512:5045  case X86::BI__builtin_ia32_pslld128:5046  case X86::BI__builtin_ia32_pslld256:5047  case X86::BI__builtin_ia32_pslld512:5048  case X86::BI__builtin_ia32_psllw128:5049  case X86::BI__builtin_ia32_psllw256:5050  case X86::BI__builtin_ia32_psllw512:5051    return interp__builtin_ia32_shift_with_count(5052        S, OpPC, Call,5053        [](const APInt &Elt, uint64_t Count) { return Elt.shl(Count); },5054        [](const APInt &Elt, unsigned Width) { return APInt::getZero(Width); });5055 5056  case X86::BI__builtin_ia32_psrlq128:5057  case X86::BI__builtin_ia32_psrlq256:5058  case X86::BI__builtin_ia32_psrlq512:5059  case X86::BI__builtin_ia32_psrld128:5060  case X86::BI__builtin_ia32_psrld256:5061  case X86::BI__builtin_ia32_psrld512:5062  case X86::BI__builtin_ia32_psrlw128:5063  case X86::BI__builtin_ia32_psrlw256:5064  case X86::BI__builtin_ia32_psrlw512:5065    return interp__builtin_ia32_shift_with_count(5066        S, OpPC, Call,5067        [](const APInt &Elt, uint64_t Count) { return Elt.lshr(Count); },5068        [](const APInt &Elt, unsigned Width) { return APInt::getZero(Width); });5069 5070  case X86::BI__builtin_ia32_pternlogd128_mask:5071  case X86::BI__builtin_ia32_pternlogd256_mask:5072  case X86::BI__builtin_ia32_pternlogd512_mask:5073  case X86::BI__builtin_ia32_pternlogq128_mask:5074  case X86::BI__builtin_ia32_pternlogq256_mask:5075  case X86::BI__builtin_ia32_pternlogq512_mask:5076    return interp__builtin_ia32_pternlog(S, OpPC, Call, /*MaskZ=*/false);5077  case X86::BI__builtin_ia32_pternlogd128_maskz:5078  case X86::BI__builtin_ia32_pternlogd256_maskz:5079  case X86::BI__builtin_ia32_pternlogd512_maskz:5080  case X86::BI__builtin_ia32_pternlogq128_maskz:5081  case X86::BI__builtin_ia32_pternlogq256_maskz:5082  case X86::BI__builtin_ia32_pternlogq512_maskz:5083    return interp__builtin_ia32_pternlog(S, OpPC, Call, /*MaskZ=*/true);5084  case Builtin::BI__builtin_elementwise_fshl:5085    return interp__builtin_elementwise_triop(S, OpPC, Call,5086                                             llvm::APIntOps::fshl);5087  case Builtin::BI__builtin_elementwise_fshr:5088    return interp__builtin_elementwise_triop(S, OpPC, Call,5089                                             llvm::APIntOps::fshr);5090 5091  case X86::BI__builtin_ia32_shuf_f32x4_256:5092  case X86::BI__builtin_ia32_shuf_i32x4_256:5093  case X86::BI__builtin_ia32_shuf_f64x2_256:5094  case X86::BI__builtin_ia32_shuf_i64x2_256:5095  case X86::BI__builtin_ia32_shuf_f32x4:5096  case X86::BI__builtin_ia32_shuf_i32x4:5097  case X86::BI__builtin_ia32_shuf_f64x2:5098  case X86::BI__builtin_ia32_shuf_i64x2: {5099    // Destination and sources A, B all have the same type.5100    QualType VecQT = Call->getArg(0)->getType();5101    const auto *VecT = VecQT->castAs<VectorType>();5102    unsigned NumElems = VecT->getNumElements();5103    unsigned ElemBits = S.getASTContext().getTypeSize(VecT->getElementType());5104    unsigned LaneBits = 128u;5105    unsigned NumLanes = (NumElems * ElemBits) / LaneBits;5106    unsigned NumElemsPerLane = LaneBits / ElemBits;5107 5108    return interp__builtin_ia32_shuffle_generic(5109        S, OpPC, Call,5110        [NumLanes, NumElemsPerLane](unsigned DstIdx, unsigned ShuffleMask) {5111          // DstIdx determines source. ShuffleMask selects lane in source.5112          unsigned BitsPerElem = NumLanes / 2;5113          unsigned IndexMask = (1u << BitsPerElem) - 1;5114          unsigned Lane = DstIdx / NumElemsPerLane;5115          unsigned SrcIdx = (Lane < NumLanes / 2) ? 0 : 1;5116          unsigned BitIdx = BitsPerElem * Lane;5117          unsigned SrcLaneIdx = (ShuffleMask >> BitIdx) & IndexMask;5118          unsigned ElemInLane = DstIdx % NumElemsPerLane;5119          unsigned IdxToPick = SrcLaneIdx * NumElemsPerLane + ElemInLane;5120          return std::pair<unsigned, int>{SrcIdx, IdxToPick};5121        });5122  }5123 5124  case X86::BI__builtin_ia32_insertf32x4_256:5125  case X86::BI__builtin_ia32_inserti32x4_256:5126  case X86::BI__builtin_ia32_insertf64x2_256:5127  case X86::BI__builtin_ia32_inserti64x2_256:5128  case X86::BI__builtin_ia32_insertf32x4:5129  case X86::BI__builtin_ia32_inserti32x4:5130  case X86::BI__builtin_ia32_insertf64x2_512:5131  case X86::BI__builtin_ia32_inserti64x2_512:5132  case X86::BI__builtin_ia32_insertf32x8:5133  case X86::BI__builtin_ia32_inserti32x8:5134  case X86::BI__builtin_ia32_insertf64x4:5135  case X86::BI__builtin_ia32_inserti64x4:5136  case X86::BI__builtin_ia32_vinsertf128_ps256:5137  case X86::BI__builtin_ia32_vinsertf128_pd256:5138  case X86::BI__builtin_ia32_vinsertf128_si256:5139  case X86::BI__builtin_ia32_insert128i256:5140    return interp__builtin_x86_insert_subvector(S, OpPC, Call, BuiltinID);5141 5142  case clang::X86::BI__builtin_ia32_vcvtps2ph:5143  case clang::X86::BI__builtin_ia32_vcvtps2ph256:5144    return interp__builtin_ia32_vcvtps2ph(S, OpPC, Call);5145 5146  case X86::BI__builtin_ia32_vec_ext_v4hi:5147  case X86::BI__builtin_ia32_vec_ext_v16qi:5148  case X86::BI__builtin_ia32_vec_ext_v8hi:5149  case X86::BI__builtin_ia32_vec_ext_v4si:5150  case X86::BI__builtin_ia32_vec_ext_v2di:5151  case X86::BI__builtin_ia32_vec_ext_v32qi:5152  case X86::BI__builtin_ia32_vec_ext_v16hi:5153  case X86::BI__builtin_ia32_vec_ext_v8si:5154  case X86::BI__builtin_ia32_vec_ext_v4di:5155  case X86::BI__builtin_ia32_vec_ext_v4sf:5156    return interp__builtin_vec_ext(S, OpPC, Call, BuiltinID);5157 5158  case X86::BI__builtin_ia32_vec_set_v4hi:5159  case X86::BI__builtin_ia32_vec_set_v16qi:5160  case X86::BI__builtin_ia32_vec_set_v8hi:5161  case X86::BI__builtin_ia32_vec_set_v4si:5162  case X86::BI__builtin_ia32_vec_set_v2di:5163  case X86::BI__builtin_ia32_vec_set_v32qi:5164  case X86::BI__builtin_ia32_vec_set_v16hi:5165  case X86::BI__builtin_ia32_vec_set_v8si:5166  case X86::BI__builtin_ia32_vec_set_v4di:5167    return interp__builtin_vec_set(S, OpPC, Call, BuiltinID);5168 5169  case X86::BI__builtin_ia32_cvtb2mask128:5170  case X86::BI__builtin_ia32_cvtb2mask256:5171  case X86::BI__builtin_ia32_cvtb2mask512:5172  case X86::BI__builtin_ia32_cvtw2mask128:5173  case X86::BI__builtin_ia32_cvtw2mask256:5174  case X86::BI__builtin_ia32_cvtw2mask512:5175  case X86::BI__builtin_ia32_cvtd2mask128:5176  case X86::BI__builtin_ia32_cvtd2mask256:5177  case X86::BI__builtin_ia32_cvtd2mask512:5178  case X86::BI__builtin_ia32_cvtq2mask128:5179  case X86::BI__builtin_ia32_cvtq2mask256:5180  case X86::BI__builtin_ia32_cvtq2mask512:5181    return interp__builtin_ia32_cvt_vec2mask(S, OpPC, Call, BuiltinID);5182 5183  case X86::BI__builtin_ia32_cmpb128_mask:5184  case X86::BI__builtin_ia32_cmpw128_mask:5185  case X86::BI__builtin_ia32_cmpd128_mask:5186  case X86::BI__builtin_ia32_cmpq128_mask:5187  case X86::BI__builtin_ia32_cmpb256_mask:5188  case X86::BI__builtin_ia32_cmpw256_mask:5189  case X86::BI__builtin_ia32_cmpd256_mask:5190  case X86::BI__builtin_ia32_cmpq256_mask:5191  case X86::BI__builtin_ia32_cmpb512_mask:5192  case X86::BI__builtin_ia32_cmpw512_mask:5193  case X86::BI__builtin_ia32_cmpd512_mask:5194  case X86::BI__builtin_ia32_cmpq512_mask:5195    return interp__builtin_ia32_cmp_mask(S, OpPC, Call, BuiltinID,5196                                         /*IsUnsigned=*/false);5197 5198  case X86::BI__builtin_ia32_ucmpb128_mask:5199  case X86::BI__builtin_ia32_ucmpw128_mask:5200  case X86::BI__builtin_ia32_ucmpd128_mask:5201  case X86::BI__builtin_ia32_ucmpq128_mask:5202  case X86::BI__builtin_ia32_ucmpb256_mask:5203  case X86::BI__builtin_ia32_ucmpw256_mask:5204  case X86::BI__builtin_ia32_ucmpd256_mask:5205  case X86::BI__builtin_ia32_ucmpq256_mask:5206  case X86::BI__builtin_ia32_ucmpb512_mask:5207  case X86::BI__builtin_ia32_ucmpw512_mask:5208  case X86::BI__builtin_ia32_ucmpd512_mask:5209  case X86::BI__builtin_ia32_ucmpq512_mask:5210    return interp__builtin_ia32_cmp_mask(S, OpPC, Call, BuiltinID,5211                                         /*IsUnsigned=*/true);5212 5213  case X86::BI__builtin_ia32_vpshufbitqmb128_mask:5214  case X86::BI__builtin_ia32_vpshufbitqmb256_mask:5215  case X86::BI__builtin_ia32_vpshufbitqmb512_mask:5216    return interp__builtin_ia32_shufbitqmb_mask(S, OpPC, Call);5217 5218  case X86::BI__builtin_ia32_pslldqi128_byteshift:5219  case X86::BI__builtin_ia32_pslldqi256_byteshift:5220  case X86::BI__builtin_ia32_pslldqi512_byteshift:5221    // These SLLDQ intrinsics always operate on byte elements (8 bits).5222    // The lane width is hardcoded to 16 to match the SIMD register size,5223    // but the algorithm processes one byte per iteration,5224    // so APInt(8, ...) is correct and intentional.5225    return interp__builtin_ia32_shuffle_generic(5226        S, OpPC, Call,5227        [](unsigned DstIdx, unsigned Shift) -> std::pair<unsigned, int> {5228          unsigned LaneBase = (DstIdx / 16) * 16;5229          unsigned LaneIdx = DstIdx % 16;5230          if (LaneIdx < Shift)5231            return std::make_pair(0, -1);5232 5233          return std::make_pair(0,5234                                static_cast<int>(LaneBase + LaneIdx - Shift));5235        });5236 5237  case X86::BI__builtin_ia32_psrldqi128_byteshift:5238  case X86::BI__builtin_ia32_psrldqi256_byteshift:5239  case X86::BI__builtin_ia32_psrldqi512_byteshift:5240    // These SRLDQ intrinsics always operate on byte elements (8 bits).5241    // The lane width is hardcoded to 16 to match the SIMD register size,5242    // but the algorithm processes one byte per iteration,5243    // so APInt(8, ...) is correct and intentional.5244    return interp__builtin_ia32_shuffle_generic(5245        S, OpPC, Call,5246        [](unsigned DstIdx, unsigned Shift) -> std::pair<unsigned, int> {5247          unsigned LaneBase = (DstIdx / 16) * 16;5248          unsigned LaneIdx = DstIdx % 16;5249          if (LaneIdx + Shift < 16)5250            return std::make_pair(0,5251                                  static_cast<int>(LaneBase + LaneIdx + Shift));5252 5253          return std::make_pair(0, -1);5254        });5255 5256  case X86::BI__builtin_ia32_palignr128:5257  case X86::BI__builtin_ia32_palignr256:5258  case X86::BI__builtin_ia32_palignr512:5259    return interp__builtin_ia32_shuffle_generic(5260        S, OpPC, Call, [](unsigned DstIdx, unsigned Shift) {5261          // Default to -1 → zero-fill this destination element5262          unsigned VecIdx = 1;5263          int ElemIdx = -1;5264 5265          int Lane = DstIdx / 16;5266          int Offset = DstIdx % 16;5267 5268          // Elements come from VecB first, then VecA after the shift boundary5269          unsigned ShiftedIdx = Offset + (Shift & 0xFF);5270          if (ShiftedIdx < 16) { // from VecB5271            ElemIdx = ShiftedIdx + (Lane * 16);5272          } else if (ShiftedIdx < 32) { // from VecA5273            VecIdx = 0;5274            ElemIdx = (ShiftedIdx - 16) + (Lane * 16);5275          }5276 5277          return std::pair<unsigned, int>{VecIdx, ElemIdx};5278        });5279 5280  case X86::BI__builtin_ia32_alignd128:5281  case X86::BI__builtin_ia32_alignd256:5282  case X86::BI__builtin_ia32_alignd512:5283  case X86::BI__builtin_ia32_alignq128:5284  case X86::BI__builtin_ia32_alignq256:5285  case X86::BI__builtin_ia32_alignq512: {5286    unsigned NumElems = Call->getType()->castAs<VectorType>()->getNumElements();5287    return interp__builtin_ia32_shuffle_generic(5288        S, OpPC, Call, [NumElems](unsigned DstIdx, unsigned Shift) {5289          unsigned Imm = Shift & 0xFF;5290          unsigned EffectiveShift = Imm & (NumElems - 1);5291          unsigned SourcePos = DstIdx + EffectiveShift;5292          unsigned VecIdx = SourcePos < NumElems ? 1u : 0u;5293          unsigned ElemIdx = SourcePos & (NumElems - 1);5294          return std::pair<unsigned, int>{VecIdx, static_cast<int>(ElemIdx)};5295        });5296  }5297 5298  default:5299    S.FFDiag(S.Current->getLocation(OpPC),5300             diag::note_invalid_subexpr_in_const_expr)5301        << S.Current->getRange(OpPC);5302 5303    return false;5304  }5305 5306  llvm_unreachable("Unhandled builtin ID");5307}5308 5309bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,5310                       ArrayRef<int64_t> ArrayIndices, int64_t &IntResult) {5311  CharUnits Result;5312  unsigned N = E->getNumComponents();5313  assert(N > 0);5314 5315  unsigned ArrayIndex = 0;5316  QualType CurrentType = E->getTypeSourceInfo()->getType();5317  for (unsigned I = 0; I != N; ++I) {5318    const OffsetOfNode &Node = E->getComponent(I);5319    switch (Node.getKind()) {5320    case OffsetOfNode::Field: {5321      const FieldDecl *MemberDecl = Node.getField();5322      const auto *RD = CurrentType->getAsRecordDecl();5323      if (!RD || RD->isInvalidDecl())5324        return false;5325      const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD);5326      unsigned FieldIndex = MemberDecl->getFieldIndex();5327      assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");5328      Result +=5329          S.getASTContext().toCharUnitsFromBits(RL.getFieldOffset(FieldIndex));5330      CurrentType = MemberDecl->getType().getNonReferenceType();5331      break;5332    }5333    case OffsetOfNode::Array: {5334      // When generating bytecode, we put all the index expressions as Sint64 on5335      // the stack.5336      int64_t Index = ArrayIndices[ArrayIndex];5337      const ArrayType *AT = S.getASTContext().getAsArrayType(CurrentType);5338      if (!AT)5339        return false;5340      CurrentType = AT->getElementType();5341      CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType);5342      Result += Index * ElementSize;5343      ++ArrayIndex;5344      break;5345    }5346    case OffsetOfNode::Base: {5347      const CXXBaseSpecifier *BaseSpec = Node.getBase();5348      if (BaseSpec->isVirtual())5349        return false;5350 5351      // Find the layout of the class whose base we are looking into.5352      const auto *RD = CurrentType->getAsCXXRecordDecl();5353      if (!RD || RD->isInvalidDecl())5354        return false;5355      const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD);5356 5357      // Find the base class itself.5358      CurrentType = BaseSpec->getType();5359      const auto *BaseRD = CurrentType->getAsCXXRecordDecl();5360      if (!BaseRD)5361        return false;5362 5363      // Add the offset to the base.5364      Result += RL.getBaseClassOffset(BaseRD);5365      break;5366    }5367    case OffsetOfNode::Identifier:5368      llvm_unreachable("Dependent OffsetOfExpr?");5369    }5370  }5371 5372  IntResult = Result.getQuantity();5373 5374  return true;5375}5376 5377bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,5378                                const Pointer &Ptr, const APSInt &IntValue) {5379 5380  const Record *R = Ptr.getRecord();5381  assert(R);5382  assert(R->getNumFields() == 1);5383 5384  unsigned FieldOffset = R->getField(0u)->Offset;5385  const Pointer &FieldPtr = Ptr.atField(FieldOffset);5386  PrimType FieldT = *S.getContext().classify(FieldPtr.getType());5387 5388  INT_TYPE_SWITCH(FieldT,5389                  FieldPtr.deref<T>() = T::from(IntValue.getSExtValue()));5390  FieldPtr.initialize();5391  return true;5392}5393 5394static void zeroAll(Pointer &Dest) {5395  const Descriptor *Desc = Dest.getFieldDesc();5396 5397  if (Desc->isPrimitive()) {5398    TYPE_SWITCH(Desc->getPrimType(), {5399      Dest.deref<T>().~T();5400      new (&Dest.deref<T>()) T();5401    });5402    return;5403  }5404 5405  if (Desc->isRecord()) {5406    const Record *R = Desc->ElemRecord;5407    for (const Record::Field &F : R->fields()) {5408      Pointer FieldPtr = Dest.atField(F.Offset);5409      zeroAll(FieldPtr);5410    }5411    return;5412  }5413 5414  if (Desc->isPrimitiveArray()) {5415    for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {5416      TYPE_SWITCH(Desc->getPrimType(), {5417        Dest.deref<T>().~T();5418        new (&Dest.deref<T>()) T();5419      });5420    }5421    return;5422  }5423 5424  if (Desc->isCompositeArray()) {5425    for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {5426      Pointer ElemPtr = Dest.atIndex(I).narrow();5427      zeroAll(ElemPtr);5428    }5429    return;5430  }5431}5432 5433static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,5434                          Pointer &Dest, bool Activate);5435static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,5436                       Pointer &Dest, bool Activate = false) {5437  [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();5438  const Descriptor *DestDesc = Dest.getFieldDesc();5439 5440  auto copyField = [&](const Record::Field &F, bool Activate) -> bool {5441    Pointer DestField = Dest.atField(F.Offset);5442    if (OptPrimType FT = S.Ctx.classify(F.Decl->getType())) {5443      TYPE_SWITCH(*FT, {5444        DestField.deref<T>() = Src.atField(F.Offset).deref<T>();5445        if (Src.atField(F.Offset).isInitialized())5446          DestField.initialize();5447        if (Activate)5448          DestField.activate();5449      });5450      return true;5451    }5452    // Composite field.5453    return copyComposite(S, OpPC, Src.atField(F.Offset), DestField, Activate);5454  };5455 5456  assert(SrcDesc->isRecord());5457  assert(SrcDesc->ElemRecord == DestDesc->ElemRecord);5458  const Record *R = DestDesc->ElemRecord;5459  for (const Record::Field &F : R->fields()) {5460    if (R->isUnion()) {5461      // For unions, only copy the active field. Zero all others.5462      const Pointer &SrcField = Src.atField(F.Offset);5463      if (SrcField.isActive()) {5464        if (!copyField(F, /*Activate=*/true))5465          return false;5466      } else {5467        if (!CheckMutable(S, OpPC, Src.atField(F.Offset)))5468          return false;5469        Pointer DestField = Dest.atField(F.Offset);5470        zeroAll(DestField);5471      }5472    } else {5473      if (!copyField(F, Activate))5474        return false;5475    }5476  }5477 5478  for (const Record::Base &B : R->bases()) {5479    Pointer DestBase = Dest.atField(B.Offset);5480    if (!copyRecord(S, OpPC, Src.atField(B.Offset), DestBase, Activate))5481      return false;5482  }5483 5484  Dest.initialize();5485  return true;5486}5487 5488static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,5489                          Pointer &Dest, bool Activate = false) {5490  assert(Src.isLive() && Dest.isLive());5491 5492  [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();5493  const Descriptor *DestDesc = Dest.getFieldDesc();5494 5495  assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive());5496 5497  if (DestDesc->isPrimitiveArray()) {5498    assert(SrcDesc->isPrimitiveArray());5499    assert(SrcDesc->getNumElems() == DestDesc->getNumElems());5500    PrimType ET = DestDesc->getPrimType();5501    for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {5502      Pointer DestElem = Dest.atIndex(I);5503      TYPE_SWITCH(ET, {5504        DestElem.deref<T>() = Src.elem<T>(I);5505        DestElem.initialize();5506      });5507    }5508    return true;5509  }5510 5511  if (DestDesc->isCompositeArray()) {5512    assert(SrcDesc->isCompositeArray());5513    assert(SrcDesc->getNumElems() == DestDesc->getNumElems());5514    for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {5515      const Pointer &SrcElem = Src.atIndex(I).narrow();5516      Pointer DestElem = Dest.atIndex(I).narrow();5517      if (!copyComposite(S, OpPC, SrcElem, DestElem, Activate))5518        return false;5519    }5520    return true;5521  }5522 5523  if (DestDesc->isRecord())5524    return copyRecord(S, OpPC, Src, Dest, Activate);5525  return Invalid(S, OpPC);5526}5527 5528bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {5529  return copyComposite(S, OpPC, Src, Dest);5530}5531 5532} // namespace interp5533} // namespace clang5534