Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/InterpBuiltin.cpp
213799 views
//===--- InterpBuiltin.cpp - Interpreter for the constexpr VM ---*- C++ -*-===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//7#include "../ExprConstShared.h"8#include "Boolean.h"9#include "Compiler.h"10#include "EvalEmitter.h"11#include "Interp.h"12#include "InterpBuiltinBitCast.h"13#include "PrimType.h"14#include "clang/AST/OSLog.h"15#include "clang/AST/RecordLayout.h"16#include "clang/Basic/Builtins.h"17#include "clang/Basic/TargetBuiltins.h"18#include "clang/Basic/TargetInfo.h"19#include "llvm/ADT/StringExtras.h"20#include "llvm/Support/ErrorHandling.h"21#include "llvm/Support/SipHash.h"2223namespace clang {24namespace interp {2526LLVM_ATTRIBUTE_UNUSED static bool isNoopBuiltin(unsigned ID) {27switch (ID) {28case Builtin::BIas_const:29case Builtin::BIforward:30case Builtin::BIforward_like:31case Builtin::BImove:32case Builtin::BImove_if_noexcept:33case Builtin::BIaddressof:34case Builtin::BI__addressof:35case Builtin::BI__builtin_addressof:36case Builtin::BI__builtin_launder:37return true;38default:39return false;40}41return false;42}4344static void discard(InterpStack &Stk, PrimType T) {45TYPE_SWITCH(T, { Stk.discard<T>(); });46}4748static APSInt popToAPSInt(InterpStack &Stk, PrimType T) {49INT_TYPE_SWITCH(T, return Stk.pop<T>().toAPSInt());50}5152/// Pushes \p Val on the stack as the type given by \p QT.53static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {54assert(QT->isSignedIntegerOrEnumerationType() ||55QT->isUnsignedIntegerOrEnumerationType());56std::optional<PrimType> T = S.getContext().classify(QT);57assert(T);5859unsigned BitWidth = S.getASTContext().getTypeSize(QT);6061if (T == PT_IntAPS) {62auto Result = S.allocAP<IntegralAP<true>>(BitWidth);63Result.copy(Val);64S.Stk.push<IntegralAP<true>>(Result);65return;66}6768if (T == PT_IntAP) {69auto Result = S.allocAP<IntegralAP<false>>(BitWidth);70Result.copy(Val);71S.Stk.push<IntegralAP<false>>(Result);72return;73}7475if (QT->isSignedIntegerOrEnumerationType()) {76int64_t V = Val.getSExtValue();77INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });78} else {79assert(QT->isUnsignedIntegerOrEnumerationType());80uint64_t V = Val.getZExtValue();81INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });82}83}8485template <typename T>86static void pushInteger(InterpState &S, T Val, QualType QT) {87if constexpr (std::is_same_v<T, APInt>)88pushInteger(S, APSInt(Val, !std::is_signed_v<T>), QT);89else if constexpr (std::is_same_v<T, APSInt>)90pushInteger(S, Val, QT);91else92pushInteger(S,93APSInt(APInt(sizeof(T) * 8, static_cast<uint64_t>(Val),94std::is_signed_v<T>),95!std::is_signed_v<T>),96QT);97}9899static void assignInteger(InterpState &S, const Pointer &Dest, PrimType ValueT,100const APSInt &Value) {101102if (ValueT == PT_IntAPS) {103Dest.deref<IntegralAP<true>>() =104S.allocAP<IntegralAP<true>>(Value.getBitWidth());105Dest.deref<IntegralAP<true>>().copy(Value);106} else if (ValueT == PT_IntAP) {107Dest.deref<IntegralAP<false>>() =108S.allocAP<IntegralAP<false>>(Value.getBitWidth());109Dest.deref<IntegralAP<false>>().copy(Value);110} else {111INT_TYPE_SWITCH_NO_BOOL(112ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); });113}114}115116static QualType getElemType(const Pointer &P) {117const Descriptor *Desc = P.getFieldDesc();118QualType T = Desc->getType();119if (Desc->isPrimitive())120return T;121if (T->isPointerType())122return T->getAs<PointerType>()->getPointeeType();123if (Desc->isArray())124return Desc->getElemQualType();125if (const auto *AT = T->getAsArrayTypeUnsafe())126return AT->getElementType();127return T;128}129130static void diagnoseNonConstexprBuiltin(InterpState &S, CodePtr OpPC,131unsigned ID) {132if (!S.diagnosing())133return;134135auto Loc = S.Current->getSource(OpPC);136if (S.getLangOpts().CPlusPlus11)137S.CCEDiag(Loc, diag::note_constexpr_invalid_function)138<< /*isConstexpr=*/0 << /*isConstructor=*/0139<< S.getASTContext().BuiltinInfo.getQuotedName(ID);140else141S.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr);142}143144static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC,145const InterpFrame *Frame,146const CallExpr *Call) {147unsigned Depth = S.Current->getDepth();148auto isStdCall = [](const FunctionDecl *F) -> bool {149return F && F->isInStdNamespace() && F->getIdentifier() &&150F->getIdentifier()->isStr("is_constant_evaluated");151};152const InterpFrame *Caller = Frame->Caller;153// The current frame is the one for __builtin_is_constant_evaluated.154// The one above that, potentially the one for std::is_constant_evaluated().155if (S.inConstantContext() && !S.checkingPotentialConstantExpression() &&156S.getEvalStatus().Diag &&157(Depth == 0 || (Depth == 1 && isStdCall(Frame->getCallee())))) {158if (Caller && isStdCall(Frame->getCallee())) {159const Expr *E = Caller->getExpr(Caller->getRetPC());160S.report(E->getExprLoc(),161diag::warn_is_constant_evaluated_always_true_constexpr)162<< "std::is_constant_evaluated" << E->getSourceRange();163} else {164S.report(Call->getExprLoc(),165diag::warn_is_constant_evaluated_always_true_constexpr)166<< "__builtin_is_constant_evaluated" << Call->getSourceRange();167}168}169170S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));171return true;172}173174// __builtin_assume(int)175static bool interp__builtin_assume(InterpState &S, CodePtr OpPC,176const InterpFrame *Frame,177const CallExpr *Call) {178assert(Call->getNumArgs() == 1);179discard(S.Stk, *S.getContext().classify(Call->getArg(0)));180return true;181}182183static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,184const InterpFrame *Frame,185const CallExpr *Call, unsigned ID) {186uint64_t Limit = ~static_cast<uint64_t>(0);187if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp ||188ID == Builtin::BIwcsncmp || ID == Builtin::BI__builtin_wcsncmp)189Limit = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)))190.getZExtValue();191192const Pointer &B = S.Stk.pop<Pointer>();193const Pointer &A = S.Stk.pop<Pointer>();194if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp ||195ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp)196diagnoseNonConstexprBuiltin(S, OpPC, ID);197198if (Limit == 0) {199pushInteger(S, 0, Call->getType());200return true;201}202203if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))204return false;205206if (A.isDummy() || B.isDummy())207return false;208209bool IsWide = ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp ||210ID == Builtin::BI__builtin_wcscmp ||211ID == Builtin::BI__builtin_wcsncmp;212assert(A.getFieldDesc()->isPrimitiveArray());213assert(B.getFieldDesc()->isPrimitiveArray());214215assert(getElemType(A).getTypePtr() == getElemType(B).getTypePtr());216PrimType ElemT = *S.getContext().classify(getElemType(A));217218auto returnResult = [&](int V) -> bool {219pushInteger(S, V, Call->getType());220return true;221};222223unsigned IndexA = A.getIndex();224unsigned IndexB = B.getIndex();225uint64_t Steps = 0;226for (;; ++IndexA, ++IndexB, ++Steps) {227228if (Steps >= Limit)229break;230const Pointer &PA = A.atIndex(IndexA);231const Pointer &PB = B.atIndex(IndexB);232if (!CheckRange(S, OpPC, PA, AK_Read) ||233!CheckRange(S, OpPC, PB, AK_Read)) {234return false;235}236237if (IsWide) {238INT_TYPE_SWITCH(ElemT, {239T CA = PA.deref<T>();240T CB = PB.deref<T>();241if (CA > CB)242return returnResult(1);243else if (CA < CB)244return returnResult(-1);245else if (CA.isZero() || CB.isZero())246return returnResult(0);247});248continue;249}250251uint8_t CA = PA.deref<uint8_t>();252uint8_t CB = PB.deref<uint8_t>();253254if (CA > CB)255return returnResult(1);256else if (CA < CB)257return returnResult(-1);258if (CA == 0 || CB == 0)259return returnResult(0);260}261262return returnResult(0);263}264265static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,266const InterpFrame *Frame,267const CallExpr *Call, unsigned ID) {268const Pointer &StrPtr = S.Stk.pop<Pointer>();269270if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen)271diagnoseNonConstexprBuiltin(S, OpPC, ID);272273if (!CheckArray(S, OpPC, StrPtr))274return false;275276if (!CheckLive(S, OpPC, StrPtr, AK_Read))277return false;278279if (!CheckDummy(S, OpPC, StrPtr, AK_Read))280return false;281282assert(StrPtr.getFieldDesc()->isPrimitiveArray());283unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize();284285if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) {286[[maybe_unused]] const ASTContext &AC = S.getASTContext();287assert(ElemSize == AC.getTypeSizeInChars(AC.getWCharType()).getQuantity());288}289290size_t Len = 0;291for (size_t I = StrPtr.getIndex();; ++I, ++Len) {292const Pointer &ElemPtr = StrPtr.atIndex(I);293294if (!CheckRange(S, OpPC, ElemPtr, AK_Read))295return false;296297uint32_t Val;298switch (ElemSize) {299case 1:300Val = ElemPtr.deref<uint8_t>();301break;302case 2:303Val = ElemPtr.deref<uint16_t>();304break;305case 4:306Val = ElemPtr.deref<uint32_t>();307break;308default:309llvm_unreachable("Unsupported char size");310}311if (Val == 0)312break;313}314315pushInteger(S, Len, Call->getType());316317return true;318}319320static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,321const InterpFrame *Frame, const CallExpr *Call,322bool Signaling) {323const Pointer &Arg = S.Stk.pop<Pointer>();324325if (!CheckLoad(S, OpPC, Arg))326return false;327328assert(Arg.getFieldDesc()->isPrimitiveArray());329330// Convert the given string to an integer using StringRef's API.331llvm::APInt Fill;332std::string Str;333assert(Arg.getNumElems() >= 1);334for (unsigned I = 0;; ++I) {335const Pointer &Elem = Arg.atIndex(I);336337if (!CheckLoad(S, OpPC, Elem))338return false;339340if (Elem.deref<int8_t>() == 0)341break;342343Str += Elem.deref<char>();344}345346// Treat empty strings as if they were zero.347if (Str.empty())348Fill = llvm::APInt(32, 0);349else if (StringRef(Str).getAsInteger(0, Fill))350return false;351352const llvm::fltSemantics &TargetSemantics =353S.getASTContext().getFloatTypeSemantics(354Call->getDirectCallee()->getReturnType());355356Floating Result = S.allocFloat(TargetSemantics);357if (S.getASTContext().getTargetInfo().isNan2008()) {358if (Signaling)359Result.copy(360llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));361else362Result.copy(363llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));364} else {365// Prior to IEEE 754-2008, architectures were allowed to choose whether366// the first bit of their significand was set for qNaN or sNaN. MIPS chose367// a different encoding to what became a standard in 2008, and for pre-368// 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as369// sNaN. This is now known as "legacy NaN" encoding.370if (Signaling)371Result.copy(372llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));373else374Result.copy(375llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));376}377378S.Stk.push<Floating>(Result);379return true;380}381382static bool interp__builtin_inf(InterpState &S, CodePtr OpPC,383const InterpFrame *Frame,384const CallExpr *Call) {385const llvm::fltSemantics &TargetSemantics =386S.getASTContext().getFloatTypeSemantics(387Call->getDirectCallee()->getReturnType());388389Floating Result = S.allocFloat(TargetSemantics);390Result.copy(APFloat::getInf(TargetSemantics));391S.Stk.push<Floating>(Result);392return true;393}394395static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC,396const InterpFrame *Frame) {397const Floating &Arg2 = S.Stk.pop<Floating>();398const Floating &Arg1 = S.Stk.pop<Floating>();399Floating Result = S.allocFloat(Arg1.getSemantics());400401APFloat Copy = Arg1.getAPFloat();402Copy.copySign(Arg2.getAPFloat());403Result.copy(Copy);404S.Stk.push<Floating>(Result);405406return true;407}408409static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC,410const InterpFrame *Frame, bool IsNumBuiltin) {411const Floating &RHS = S.Stk.pop<Floating>();412const Floating &LHS = S.Stk.pop<Floating>();413Floating Result = S.allocFloat(LHS.getSemantics());414415if (IsNumBuiltin)416Result.copy(llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()));417else418Result.copy(minnum(LHS.getAPFloat(), RHS.getAPFloat()));419S.Stk.push<Floating>(Result);420return true;421}422423static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC,424const InterpFrame *Frame, bool IsNumBuiltin) {425const Floating &RHS = S.Stk.pop<Floating>();426const Floating &LHS = S.Stk.pop<Floating>();427Floating Result = S.allocFloat(LHS.getSemantics());428429if (IsNumBuiltin)430Result.copy(llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()));431else432Result.copy(maxnum(LHS.getAPFloat(), RHS.getAPFloat()));433S.Stk.push<Floating>(Result);434return true;435}436437/// Defined as __builtin_isnan(...), to accommodate the fact that it can438/// take a float, double, long double, etc.439/// But for us, that's all a Floating anyway.440static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC,441const InterpFrame *Frame,442const CallExpr *Call) {443const Floating &Arg = S.Stk.pop<Floating>();444445pushInteger(S, Arg.isNan(), Call->getType());446return true;447}448449static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC,450const InterpFrame *Frame,451const CallExpr *Call) {452const Floating &Arg = S.Stk.pop<Floating>();453454pushInteger(S, Arg.isSignaling(), Call->getType());455return true;456}457458static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC,459const InterpFrame *Frame, bool CheckSign,460const CallExpr *Call) {461const Floating &Arg = S.Stk.pop<Floating>();462bool IsInf = Arg.isInf();463464if (CheckSign)465pushInteger(S, IsInf ? (Arg.isNegative() ? -1 : 1) : 0, Call->getType());466else467pushInteger(S, Arg.isInf(), Call->getType());468return true;469}470471static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC,472const InterpFrame *Frame,473const CallExpr *Call) {474const Floating &Arg = S.Stk.pop<Floating>();475476pushInteger(S, Arg.isFinite(), Call->getType());477return true;478}479480static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC,481const InterpFrame *Frame,482const CallExpr *Call) {483const Floating &Arg = S.Stk.pop<Floating>();484485pushInteger(S, Arg.isNormal(), Call->getType());486return true;487}488489static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC,490const InterpFrame *Frame,491const CallExpr *Call) {492const Floating &Arg = S.Stk.pop<Floating>();493494pushInteger(S, Arg.isDenormal(), Call->getType());495return true;496}497498static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC,499const InterpFrame *Frame,500const CallExpr *Call) {501const Floating &Arg = S.Stk.pop<Floating>();502503pushInteger(S, Arg.isZero(), Call->getType());504return true;505}506507static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC,508const InterpFrame *Frame,509const CallExpr *Call) {510const Floating &Arg = S.Stk.pop<Floating>();511512pushInteger(S, Arg.isNegative(), Call->getType());513return true;514}515516static bool interp_floating_comparison(InterpState &S, CodePtr OpPC,517const CallExpr *Call, unsigned ID) {518const Floating &RHS = S.Stk.pop<Floating>();519const Floating &LHS = S.Stk.pop<Floating>();520521pushInteger(522S,523[&] {524switch (ID) {525case Builtin::BI__builtin_isgreater:526return LHS > RHS;527case Builtin::BI__builtin_isgreaterequal:528return LHS >= RHS;529case Builtin::BI__builtin_isless:530return LHS < RHS;531case Builtin::BI__builtin_islessequal:532return LHS <= RHS;533case Builtin::BI__builtin_islessgreater: {534ComparisonCategoryResult cmp = LHS.compare(RHS);535return cmp == ComparisonCategoryResult::Less ||536cmp == ComparisonCategoryResult::Greater;537}538case Builtin::BI__builtin_isunordered:539return LHS.compare(RHS) == ComparisonCategoryResult::Unordered;540default:541llvm_unreachable("Unexpected builtin ID: Should be a floating point "542"comparison function");543}544}(),545Call->getType());546return true;547}548549/// First parameter to __builtin_isfpclass is the floating value, the550/// second one is an integral value.551static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,552const InterpFrame *Frame,553const CallExpr *Call) {554PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType());555APSInt FPClassArg = popToAPSInt(S.Stk, FPClassArgT);556const Floating &F = S.Stk.pop<Floating>();557558int32_t Result = static_cast<int32_t>(559(F.classify() & std::move(FPClassArg)).getZExtValue());560pushInteger(S, Result, Call->getType());561562return true;563}564565/// Five int values followed by one floating value.566/// __builtin_fpclassify(int, int, int, int, int, float)567static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,568const InterpFrame *Frame,569const CallExpr *Call) {570const Floating &Val = S.Stk.pop<Floating>();571572PrimType IntT = *S.getContext().classify(Call->getArg(0));573APSInt Values[5];574for (unsigned I = 0; I != 5; ++I)575Values[4 - I] = popToAPSInt(S.Stk, IntT);576577unsigned Index;578switch (Val.getCategory()) {579case APFloat::fcNaN:580Index = 0;581break;582case APFloat::fcInfinity:583Index = 1;584break;585case APFloat::fcNormal:586Index = Val.isDenormal() ? 3 : 2;587break;588case APFloat::fcZero:589Index = 4;590break;591}592593// The last argument is first on the stack.594assert(Index <= 4);595596pushInteger(S, Values[Index], Call->getType());597return true;598}599600// The C standard says "fabs raises no floating-point exceptions,601// even if x is a signaling NaN. The returned value is independent of602// the current rounding direction mode." Therefore constant folding can603// proceed without regard to the floating point settings.604// Reference, WG14 N2478 F.10.4.3605static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,606const InterpFrame *Frame) {607const Floating &Val = S.Stk.pop<Floating>();608APFloat F = Val.getAPFloat();609if (!F.isNegative()) {610S.Stk.push<Floating>(Val);611return true;612}613614Floating Result = S.allocFloat(Val.getSemantics());615F.changeSign();616Result.copy(F);617S.Stk.push<Floating>(Result);618return true;619}620621static bool interp__builtin_abs(InterpState &S, CodePtr OpPC,622const InterpFrame *Frame,623const CallExpr *Call) {624PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());625APSInt Val = popToAPSInt(S.Stk, ArgT);626if (Val ==627APSInt(APInt::getSignedMinValue(Val.getBitWidth()), /*IsUnsigned=*/false))628return false;629if (Val.isNegative())630Val.negate();631pushInteger(S, Val, Call->getType());632return true;633}634635static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,636const InterpFrame *Frame,637const CallExpr *Call) {638PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());639APSInt Val = popToAPSInt(S.Stk, ArgT);640pushInteger(S, Val.popcount(), Call->getType());641return true;642}643644static bool interp__builtin_parity(InterpState &S, CodePtr OpPC,645const InterpFrame *Frame,646const CallExpr *Call) {647PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());648APSInt Val = popToAPSInt(S.Stk, ArgT);649pushInteger(S, Val.popcount() % 2, Call->getType());650return true;651}652653static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC,654const InterpFrame *Frame,655const CallExpr *Call) {656PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());657APSInt Val = popToAPSInt(S.Stk, ArgT);658pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType());659return true;660}661662static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC,663const InterpFrame *Frame,664const CallExpr *Call) {665PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());666APSInt Val = popToAPSInt(S.Stk, ArgT);667pushInteger(S, Val.reverseBits(), Call->getType());668return true;669}670671static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC,672const InterpFrame *Frame,673const CallExpr *Call) {674// This is an unevaluated call, so there are no arguments on the stack.675assert(Call->getNumArgs() == 1);676const Expr *Arg = Call->getArg(0);677678GCCTypeClass ResultClass =679EvaluateBuiltinClassifyType(Arg->getType(), S.getLangOpts());680int32_t ReturnVal = static_cast<int32_t>(ResultClass);681pushInteger(S, ReturnVal, Call->getType());682return true;683}684685// __builtin_expect(long, long)686// __builtin_expect_with_probability(long, long, double)687static bool interp__builtin_expect(InterpState &S, CodePtr OpPC,688const InterpFrame *Frame,689const CallExpr *Call) {690// The return value is simply the value of the first parameter.691// We ignore the probability.692unsigned NumArgs = Call->getNumArgs();693assert(NumArgs == 2 || NumArgs == 3);694695PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());696if (NumArgs == 3)697S.Stk.discard<Floating>();698discard(S.Stk, ArgT);699700APSInt Val = popToAPSInt(S.Stk, ArgT);701pushInteger(S, Val, Call->getType());702return true;703}704705/// rotateleft(value, amount)706static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC,707const InterpFrame *Frame,708const CallExpr *Call, bool Right) {709PrimType AmountT = *S.getContext().classify(Call->getArg(1)->getType());710PrimType ValueT = *S.getContext().classify(Call->getArg(0)->getType());711712APSInt Amount = popToAPSInt(S.Stk, AmountT);713APSInt Value = popToAPSInt(S.Stk, ValueT);714715APSInt Result;716if (Right)717Result = APSInt(Value.rotr(Amount.urem(Value.getBitWidth())),718/*IsUnsigned=*/true);719else // Left.720Result = APSInt(Value.rotl(Amount.urem(Value.getBitWidth())),721/*IsUnsigned=*/true);722723pushInteger(S, Result, Call->getType());724return true;725}726727static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC,728const InterpFrame *Frame,729const CallExpr *Call) {730PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());731APSInt Value = popToAPSInt(S.Stk, ArgT);732733uint64_t N = Value.countr_zero();734pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType());735return true;736}737738static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC,739const InterpFrame *Frame,740const CallExpr *Call) {741#ifndef NDEBUG742assert(Call->getArg(0)->isLValue());743PrimType PtrT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr);744assert(PtrT == PT_Ptr &&745"Unsupported pointer type passed to __builtin_addressof()");746#endif747return true;748}749750static bool interp__builtin_move(InterpState &S, CodePtr OpPC,751const InterpFrame *Frame,752const CallExpr *Call) {753return Call->getDirectCallee()->isConstexpr();754}755756static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC,757const InterpFrame *Frame,758const CallExpr *Call) {759PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());760APSInt Arg = popToAPSInt(S.Stk, ArgT);761762int Result = S.getASTContext().getTargetInfo().getEHDataRegisterNumber(763Arg.getZExtValue());764pushInteger(S, Result, Call->getType());765return true;766}767768// Two integral values followed by a pointer (lhs, rhs, resultOut)769static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC,770const CallExpr *Call,771unsigned BuiltinOp) {772const Pointer &ResultPtr = S.Stk.pop<Pointer>();773if (ResultPtr.isDummy())774return false;775776PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());777PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());778APSInt RHS = popToAPSInt(S.Stk, RHST);779APSInt LHS = popToAPSInt(S.Stk, LHST);780QualType ResultType = Call->getArg(2)->getType()->getPointeeType();781PrimType ResultT = *S.getContext().classify(ResultType);782bool Overflow;783784APSInt Result;785if (BuiltinOp == Builtin::BI__builtin_add_overflow ||786BuiltinOp == Builtin::BI__builtin_sub_overflow ||787BuiltinOp == Builtin::BI__builtin_mul_overflow) {788bool IsSigned = LHS.isSigned() || RHS.isSigned() ||789ResultType->isSignedIntegerOrEnumerationType();790bool AllSigned = LHS.isSigned() && RHS.isSigned() &&791ResultType->isSignedIntegerOrEnumerationType();792uint64_t LHSSize = LHS.getBitWidth();793uint64_t RHSSize = RHS.getBitWidth();794uint64_t ResultSize = S.getASTContext().getTypeSize(ResultType);795uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize);796797// Add an additional bit if the signedness isn't uniformly agreed to. We798// could do this ONLY if there is a signed and an unsigned that both have799// MaxBits, but the code to check that is pretty nasty. The issue will be800// caught in the shrink-to-result later anyway.801if (IsSigned && !AllSigned)802++MaxBits;803804LHS = APSInt(LHS.extOrTrunc(MaxBits), !IsSigned);805RHS = APSInt(RHS.extOrTrunc(MaxBits), !IsSigned);806Result = APSInt(MaxBits, !IsSigned);807}808809// Find largest int.810switch (BuiltinOp) {811default:812llvm_unreachable("Invalid value for BuiltinOp");813case Builtin::BI__builtin_add_overflow:814case Builtin::BI__builtin_sadd_overflow:815case Builtin::BI__builtin_saddl_overflow:816case Builtin::BI__builtin_saddll_overflow:817case Builtin::BI__builtin_uadd_overflow:818case Builtin::BI__builtin_uaddl_overflow:819case Builtin::BI__builtin_uaddll_overflow:820Result = LHS.isSigned() ? LHS.sadd_ov(RHS, Overflow)821: LHS.uadd_ov(RHS, Overflow);822break;823case Builtin::BI__builtin_sub_overflow:824case Builtin::BI__builtin_ssub_overflow:825case Builtin::BI__builtin_ssubl_overflow:826case Builtin::BI__builtin_ssubll_overflow:827case Builtin::BI__builtin_usub_overflow:828case Builtin::BI__builtin_usubl_overflow:829case Builtin::BI__builtin_usubll_overflow:830Result = LHS.isSigned() ? LHS.ssub_ov(RHS, Overflow)831: LHS.usub_ov(RHS, Overflow);832break;833case Builtin::BI__builtin_mul_overflow:834case Builtin::BI__builtin_smul_overflow:835case Builtin::BI__builtin_smull_overflow:836case Builtin::BI__builtin_smulll_overflow:837case Builtin::BI__builtin_umul_overflow:838case Builtin::BI__builtin_umull_overflow:839case Builtin::BI__builtin_umulll_overflow:840Result = LHS.isSigned() ? LHS.smul_ov(RHS, Overflow)841: LHS.umul_ov(RHS, Overflow);842break;843}844845// In the case where multiple sizes are allowed, truncate and see if846// the values are the same.847if (BuiltinOp == Builtin::BI__builtin_add_overflow ||848BuiltinOp == Builtin::BI__builtin_sub_overflow ||849BuiltinOp == Builtin::BI__builtin_mul_overflow) {850// APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead,851// since it will give us the behavior of a TruncOrSelf in the case where852// its parameter <= its size. We previously set Result to be at least the853// type-size of the result, so getTypeSize(ResultType) <= Resu854APSInt Temp = Result.extOrTrunc(S.getASTContext().getTypeSize(ResultType));855Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType());856857if (!APSInt::isSameValue(Temp, Result))858Overflow = true;859Result = std::move(Temp);860}861862// Write Result to ResultPtr and put Overflow on the stack.863assignInteger(S, ResultPtr, ResultT, Result);864if (ResultPtr.canBeInitialized())865ResultPtr.initialize();866867assert(Call->getDirectCallee()->getReturnType()->isBooleanType());868S.Stk.push<Boolean>(Overflow);869return true;870}871872/// Three integral values followed by a pointer (lhs, rhs, carry, carryOut).873static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,874const InterpFrame *Frame,875const CallExpr *Call, unsigned BuiltinOp) {876const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();877PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());878PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());879APSInt CarryIn = popToAPSInt(S.Stk, LHST);880APSInt RHS = popToAPSInt(S.Stk, RHST);881APSInt LHS = popToAPSInt(S.Stk, LHST);882883APSInt CarryOut;884885APSInt Result;886// Copy the number of bits and sign.887Result = LHS;888CarryOut = LHS;889890bool FirstOverflowed = false;891bool SecondOverflowed = false;892switch (BuiltinOp) {893default:894llvm_unreachable("Invalid value for BuiltinOp");895case Builtin::BI__builtin_addcb:896case Builtin::BI__builtin_addcs:897case Builtin::BI__builtin_addc:898case Builtin::BI__builtin_addcl:899case Builtin::BI__builtin_addcll:900Result =901LHS.uadd_ov(RHS, FirstOverflowed).uadd_ov(CarryIn, SecondOverflowed);902break;903case Builtin::BI__builtin_subcb:904case Builtin::BI__builtin_subcs:905case Builtin::BI__builtin_subc:906case Builtin::BI__builtin_subcl:907case Builtin::BI__builtin_subcll:908Result =909LHS.usub_ov(RHS, FirstOverflowed).usub_ov(CarryIn, SecondOverflowed);910break;911}912// It is possible for both overflows to happen but CGBuiltin uses an OR so913// this is consistent.914CarryOut = (uint64_t)(FirstOverflowed | SecondOverflowed);915916QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();917PrimType CarryOutT = *S.getContext().classify(CarryOutType);918assignInteger(S, CarryOutPtr, CarryOutT, CarryOut);919CarryOutPtr.initialize();920921assert(Call->getType() == Call->getArg(0)->getType());922pushInteger(S, Result, Call->getType());923return true;924}925926static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,927const InterpFrame *Frame, const CallExpr *Call,928unsigned BuiltinOp) {929930std::optional<APSInt> Fallback;931if (BuiltinOp == Builtin::BI__builtin_clzg && Call->getNumArgs() == 2) {932PrimType FallbackT = *S.getContext().classify(Call->getArg(1));933Fallback = popToAPSInt(S.Stk, FallbackT);934}935PrimType ValT = *S.getContext().classify(Call->getArg(0));936const APSInt &Val = popToAPSInt(S.Stk, ValT);937938// When the argument is 0, the result of GCC builtins is undefined, whereas939// for Microsoft intrinsics, the result is the bit-width of the argument.940bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&941BuiltinOp != Builtin::BI__lzcnt &&942BuiltinOp != Builtin::BI__lzcnt64;943944if (Val == 0) {945if (Fallback) {946pushInteger(S, *Fallback, Call->getType());947return true;948}949950if (ZeroIsUndefined)951return false;952}953954pushInteger(S, Val.countl_zero(), Call->getType());955return true;956}957958static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC,959const InterpFrame *Frame, const CallExpr *Call,960unsigned BuiltinID) {961std::optional<APSInt> Fallback;962if (BuiltinID == Builtin::BI__builtin_ctzg && Call->getNumArgs() == 2) {963PrimType FallbackT = *S.getContext().classify(Call->getArg(1));964Fallback = popToAPSInt(S.Stk, FallbackT);965}966PrimType ValT = *S.getContext().classify(Call->getArg(0));967const APSInt &Val = popToAPSInt(S.Stk, ValT);968969if (Val == 0) {970if (Fallback) {971pushInteger(S, *Fallback, Call->getType());972return true;973}974return false;975}976977pushInteger(S, Val.countr_zero(), Call->getType());978return true;979}980981static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC,982const InterpFrame *Frame,983const CallExpr *Call) {984PrimType ReturnT = *S.getContext().classify(Call->getType());985PrimType ValT = *S.getContext().classify(Call->getArg(0));986const APSInt &Val = popToAPSInt(S.Stk, ValT);987assert(Val.getActiveBits() <= 64);988989INT_TYPE_SWITCH(ReturnT,990{ S.Stk.push<T>(T::from(Val.byteSwap().getZExtValue())); });991return true;992}993994/// bool __atomic_always_lock_free(size_t, void const volatile*)995/// bool __atomic_is_lock_free(size_t, void const volatile*)996static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,997const InterpFrame *Frame,998const CallExpr *Call,999unsigned BuiltinOp) {1000auto returnBool = [&S](bool Value) -> bool {1001S.Stk.push<Boolean>(Value);1002return true;1003};10041005PrimType ValT = *S.getContext().classify(Call->getArg(0));1006const Pointer &Ptr = S.Stk.pop<Pointer>();1007const APSInt &SizeVal = popToAPSInt(S.Stk, ValT);10081009// For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power1010// of two less than or equal to the maximum inline atomic width, we know it1011// is lock-free. If the size isn't a power of two, or greater than the1012// maximum alignment where we promote atomics, we know it is not lock-free1013// (at least not in the sense of atomic_is_lock_free). Otherwise,1014// the answer can only be determined at runtime; for example, 16-byte1015// atomics have lock-free implementations on some, but not all,1016// x86-64 processors.10171018// Check power-of-two.1019CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());1020if (Size.isPowerOfTwo()) {1021// Check against inlining width.1022unsigned InlineWidthBits =1023S.getASTContext().getTargetInfo().getMaxAtomicInlineWidth();1024if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits)) {10251026// OK, we will inline appropriately-aligned operations of this size,1027// and _Atomic(T) is appropriately-aligned.1028if (Size == CharUnits::One())1029return returnBool(true);10301031// Same for null pointers.1032assert(BuiltinOp != Builtin::BI__c11_atomic_is_lock_free);1033if (Ptr.isZero())1034return returnBool(true);10351036if (Ptr.isIntegralPointer()) {1037uint64_t IntVal = Ptr.getIntegerRepresentation();1038if (APSInt(APInt(64, IntVal, false), true).isAligned(Size.getAsAlign()))1039return returnBool(true);1040}10411042const Expr *PtrArg = Call->getArg(1);1043// Otherwise, check if the type's alignment against Size.1044if (const auto *ICE = dyn_cast<ImplicitCastExpr>(PtrArg)) {1045// Drop the potential implicit-cast to 'const volatile void*', getting1046// the underlying type.1047if (ICE->getCastKind() == CK_BitCast)1048PtrArg = ICE->getSubExpr();1049}10501051if (auto PtrTy = PtrArg->getType()->getAs<PointerType>()) {1052QualType PointeeType = PtrTy->getPointeeType();1053if (!PointeeType->isIncompleteType() &&1054S.getASTContext().getTypeAlignInChars(PointeeType) >= Size) {1055// OK, we will inline operations on this object.1056return returnBool(true);1057}1058}1059}1060}10611062if (BuiltinOp == Builtin::BI__atomic_always_lock_free)1063return returnBool(false);10641065return false;1066}10671068/// bool __c11_atomic_is_lock_free(size_t)1069static bool interp__builtin_c11_atomic_is_lock_free(InterpState &S,1070CodePtr OpPC,1071const InterpFrame *Frame,1072const CallExpr *Call) {1073PrimType ValT = *S.getContext().classify(Call->getArg(0));1074const APSInt &SizeVal = popToAPSInt(S.Stk, ValT);10751076auto returnBool = [&S](bool Value) -> bool {1077S.Stk.push<Boolean>(Value);1078return true;1079};10801081CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());1082if (Size.isPowerOfTwo()) {1083// Check against inlining width.1084unsigned InlineWidthBits =1085S.getASTContext().getTargetInfo().getMaxAtomicInlineWidth();1086if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits))1087return returnBool(true);1088}10891090return false; // returnBool(false);1091}10921093/// __builtin_complex(Float A, float B);1094static bool interp__builtin_complex(InterpState &S, CodePtr OpPC,1095const InterpFrame *Frame,1096const CallExpr *Call) {1097const Floating &Arg2 = S.Stk.pop<Floating>();1098const Floating &Arg1 = S.Stk.pop<Floating>();1099Pointer &Result = S.Stk.peek<Pointer>();11001101Result.atIndex(0).deref<Floating>() = Arg1;1102Result.atIndex(0).initialize();1103Result.atIndex(1).deref<Floating>() = Arg2;1104Result.atIndex(1).initialize();1105Result.initialize();11061107return true;1108}11091110/// __builtin_is_aligned()1111/// __builtin_align_up()1112/// __builtin_align_down()1113/// The first parameter is either an integer or a pointer.1114/// The second parameter is the requested alignment as an integer.1115static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,1116const InterpFrame *Frame,1117const CallExpr *Call,1118unsigned BuiltinOp) {1119PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1));1120const APSInt &Alignment = popToAPSInt(S.Stk, AlignmentT);11211122if (Alignment < 0 || !Alignment.isPowerOf2()) {1123S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment;1124return false;1125}1126unsigned SrcWidth = S.getASTContext().getIntWidth(Call->getArg(0)->getType());1127APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1));1128if (APSInt::compareValues(Alignment, MaxValue) > 0) {1129S.FFDiag(Call, diag::note_constexpr_alignment_too_big)1130<< MaxValue << Call->getArg(0)->getType() << Alignment;1131return false;1132}11331134// The first parameter is either an integer or a pointer (but not a function1135// pointer).1136PrimType FirstArgT = *S.Ctx.classify(Call->getArg(0));11371138if (isIntegralType(FirstArgT)) {1139const APSInt &Src = popToAPSInt(S.Stk, FirstArgT);1140APInt AlignMinusOne = Alignment.extOrTrunc(Src.getBitWidth()) - 1;1141if (BuiltinOp == Builtin::BI__builtin_align_up) {1142APSInt AlignedVal =1143APSInt((Src + AlignMinusOne) & ~AlignMinusOne, Src.isUnsigned());1144pushInteger(S, AlignedVal, Call->getType());1145} else if (BuiltinOp == Builtin::BI__builtin_align_down) {1146APSInt AlignedVal = APSInt(Src & ~AlignMinusOne, Src.isUnsigned());1147pushInteger(S, AlignedVal, Call->getType());1148} else {1149assert(*S.Ctx.classify(Call->getType()) == PT_Bool);1150S.Stk.push<Boolean>((Src & AlignMinusOne) == 0);1151}1152return true;1153}11541155assert(FirstArgT == PT_Ptr);1156const Pointer &Ptr = S.Stk.pop<Pointer>();11571158unsigned PtrOffset = Ptr.getByteOffset();1159PtrOffset = Ptr.getIndex();1160CharUnits BaseAlignment =1161S.getASTContext().getDeclAlign(Ptr.getDeclDesc()->asValueDecl());1162CharUnits PtrAlign =1163BaseAlignment.alignmentAtOffset(CharUnits::fromQuantity(PtrOffset));11641165if (BuiltinOp == Builtin::BI__builtin_is_aligned) {1166if (PtrAlign.getQuantity() >= Alignment) {1167S.Stk.push<Boolean>(true);1168return true;1169}1170// If the alignment is not known to be sufficient, some cases could still1171// be aligned at run time. However, if the requested alignment is less or1172// equal to the base alignment and the offset is not aligned, we know that1173// the run-time value can never be aligned.1174if (BaseAlignment.getQuantity() >= Alignment &&1175PtrAlign.getQuantity() < Alignment) {1176S.Stk.push<Boolean>(false);1177return true;1178}11791180S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_compute)1181<< Alignment;1182return false;1183}11841185assert(BuiltinOp == Builtin::BI__builtin_align_down ||1186BuiltinOp == Builtin::BI__builtin_align_up);11871188// For align_up/align_down, we can return the same value if the alignment1189// is known to be greater or equal to the requested value.1190if (PtrAlign.getQuantity() >= Alignment) {1191S.Stk.push<Pointer>(Ptr);1192return true;1193}11941195// The alignment could be greater than the minimum at run-time, so we cannot1196// infer much about the resulting pointer value. One case is possible:1197// For `_Alignas(32) char buf[N]; __builtin_align_down(&buf[idx], 32)` we1198// can infer the correct index if the requested alignment is smaller than1199// the base alignment so we can perform the computation on the offset.1200if (BaseAlignment.getQuantity() >= Alignment) {1201assert(Alignment.getBitWidth() <= 64 &&1202"Cannot handle > 64-bit address-space");1203uint64_t Alignment64 = Alignment.getZExtValue();1204CharUnits NewOffset =1205CharUnits::fromQuantity(BuiltinOp == Builtin::BI__builtin_align_down1206? llvm::alignDown(PtrOffset, Alignment64)1207: llvm::alignTo(PtrOffset, Alignment64));12081209S.Stk.push<Pointer>(Ptr.atIndex(NewOffset.getQuantity()));1210return true;1211}12121213// Otherwise, we cannot constant-evaluate the result.1214S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_adjust) << Alignment;1215return false;1216}12171218/// __builtin_assume_aligned(Ptr, Alignment[, ExtraOffset])1219static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC,1220const InterpFrame *Frame,1221const CallExpr *Call) {1222assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3);12231224std::optional<APSInt> ExtraOffset;1225if (Call->getNumArgs() == 3)1226ExtraOffset = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(2)));12271228APSInt Alignment = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)));1229const Pointer &Ptr = S.Stk.pop<Pointer>();12301231CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue());12321233// If there is a base object, then it must have the correct alignment.1234if (Ptr.isBlockPointer()) {1235CharUnits BaseAlignment;1236if (const auto *VD = Ptr.getDeclDesc()->asValueDecl())1237BaseAlignment = S.getASTContext().getDeclAlign(VD);1238else if (const auto *E = Ptr.getDeclDesc()->asExpr())1239BaseAlignment = GetAlignOfExpr(S.getASTContext(), E, UETT_AlignOf);12401241if (BaseAlignment < Align) {1242S.CCEDiag(Call->getArg(0),1243diag::note_constexpr_baa_insufficient_alignment)1244<< 0 << BaseAlignment.getQuantity() << Align.getQuantity();1245return false;1246}1247}12481249APValue AV = Ptr.toAPValue(S.getASTContext());1250CharUnits AVOffset = AV.getLValueOffset();1251if (ExtraOffset)1252AVOffset -= CharUnits::fromQuantity(ExtraOffset->getZExtValue());1253if (AVOffset.alignTo(Align) != AVOffset) {1254if (Ptr.isBlockPointer())1255S.CCEDiag(Call->getArg(0),1256diag::note_constexpr_baa_insufficient_alignment)1257<< 1 << AVOffset.getQuantity() << Align.getQuantity();1258else1259S.CCEDiag(Call->getArg(0),1260diag::note_constexpr_baa_value_insufficient_alignment)1261<< AVOffset.getQuantity() << Align.getQuantity();1262return false;1263}12641265S.Stk.push<Pointer>(Ptr);1266return true;1267}12681269static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC,1270const InterpFrame *Frame,1271const CallExpr *Call) {1272if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||1273!Call->getArg(1)->getType()->isIntegerType())1274return false;12751276PrimType ValT = *S.Ctx.classify(Call->getArg(0));1277PrimType IndexT = *S.Ctx.classify(Call->getArg(1));1278APSInt Index = popToAPSInt(S.Stk, IndexT);1279APSInt Val = popToAPSInt(S.Stk, ValT);12801281unsigned BitWidth = Val.getBitWidth();1282uint64_t Shift = Index.extractBitsAsZExtValue(8, 0);1283uint64_t Length = Index.extractBitsAsZExtValue(8, 8);1284Length = Length > BitWidth ? BitWidth : Length;12851286// Handle out of bounds cases.1287if (Length == 0 || Shift >= BitWidth) {1288pushInteger(S, 0, Call->getType());1289return true;1290}12911292uint64_t Result = Val.getZExtValue() >> Shift;1293Result &= llvm::maskTrailingOnes<uint64_t>(Length);1294pushInteger(S, Result, Call->getType());1295return true;1296}12971298static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC,1299const InterpFrame *Frame,1300const CallExpr *Call) {1301QualType CallType = Call->getType();1302if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||1303!Call->getArg(1)->getType()->isIntegerType() ||1304!CallType->isIntegerType())1305return false;13061307PrimType ValT = *S.Ctx.classify(Call->getArg(0));1308PrimType IndexT = *S.Ctx.classify(Call->getArg(1));13091310APSInt Idx = popToAPSInt(S.Stk, IndexT);1311APSInt Val = popToAPSInt(S.Stk, ValT);13121313unsigned BitWidth = Val.getBitWidth();1314uint64_t Index = Idx.extractBitsAsZExtValue(8, 0);13151316if (Index < BitWidth)1317Val.clearHighBits(BitWidth - Index);13181319pushInteger(S, Val, CallType);1320return true;1321}13221323static bool interp__builtin_ia32_lzcnt(InterpState &S, CodePtr OpPC,1324const InterpFrame *Frame,1325const CallExpr *Call) {1326QualType CallType = Call->getType();1327if (!CallType->isIntegerType() ||1328!Call->getArg(0)->getType()->isIntegerType())1329return false;13301331APSInt Val = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));1332pushInteger(S, Val.countLeadingZeros(), CallType);1333return true;1334}13351336static bool interp__builtin_ia32_tzcnt(InterpState &S, CodePtr OpPC,1337const InterpFrame *Frame,1338const CallExpr *Call) {1339QualType CallType = Call->getType();1340if (!CallType->isIntegerType() ||1341!Call->getArg(0)->getType()->isIntegerType())1342return false;13431344APSInt Val = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));1345pushInteger(S, Val.countTrailingZeros(), CallType);1346return true;1347}13481349static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC,1350const InterpFrame *Frame,1351const CallExpr *Call) {1352if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||1353!Call->getArg(1)->getType()->isIntegerType())1354return false;13551356PrimType ValT = *S.Ctx.classify(Call->getArg(0));1357PrimType MaskT = *S.Ctx.classify(Call->getArg(1));13581359APSInt Mask = popToAPSInt(S.Stk, MaskT);1360APSInt Val = popToAPSInt(S.Stk, ValT);13611362unsigned BitWidth = Val.getBitWidth();1363APInt Result = APInt::getZero(BitWidth);1364for (unsigned I = 0, P = 0; I != BitWidth; ++I) {1365if (Mask[I])1366Result.setBitVal(I, Val[P++]);1367}1368pushInteger(S, std::move(Result), Call->getType());1369return true;1370}13711372static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC,1373const InterpFrame *Frame,1374const CallExpr *Call) {1375if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||1376!Call->getArg(1)->getType()->isIntegerType())1377return false;13781379PrimType ValT = *S.Ctx.classify(Call->getArg(0));1380PrimType MaskT = *S.Ctx.classify(Call->getArg(1));13811382APSInt Mask = popToAPSInt(S.Stk, MaskT);1383APSInt Val = popToAPSInt(S.Stk, ValT);13841385unsigned BitWidth = Val.getBitWidth();1386APInt Result = APInt::getZero(BitWidth);1387for (unsigned I = 0, P = 0; I != BitWidth; ++I) {1388if (Mask[I])1389Result.setBitVal(P++, Val[I]);1390}1391pushInteger(S, std::move(Result), Call->getType());1392return true;1393}13941395/// (CarryIn, LHS, RHS, Result)1396static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S,1397CodePtr OpPC,1398const InterpFrame *Frame,1399const CallExpr *Call,1400unsigned BuiltinOp) {1401if (Call->getNumArgs() != 4 || !Call->getArg(0)->getType()->isIntegerType() ||1402!Call->getArg(1)->getType()->isIntegerType() ||1403!Call->getArg(2)->getType()->isIntegerType())1404return false;14051406const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();14071408PrimType CarryInT = *S.getContext().classify(Call->getArg(0));1409PrimType LHST = *S.getContext().classify(Call->getArg(1));1410PrimType RHST = *S.getContext().classify(Call->getArg(2));1411APSInt RHS = popToAPSInt(S.Stk, RHST);1412APSInt LHS = popToAPSInt(S.Stk, LHST);1413APSInt CarryIn = popToAPSInt(S.Stk, CarryInT);14141415bool IsAdd = BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u32 ||1416BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u64;14171418unsigned BitWidth = LHS.getBitWidth();1419unsigned CarryInBit = CarryIn.ugt(0) ? 1 : 0;1420APInt ExResult =1421IsAdd ? (LHS.zext(BitWidth + 1) + (RHS.zext(BitWidth + 1) + CarryInBit))1422: (LHS.zext(BitWidth + 1) - (RHS.zext(BitWidth + 1) + CarryInBit));14231424APInt Result = ExResult.extractBits(BitWidth, 0);1425APSInt CarryOut =1426APSInt(ExResult.extractBits(1, BitWidth), /*IsUnsigned=*/true);14271428QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();1429PrimType CarryOutT = *S.getContext().classify(CarryOutType);1430assignInteger(S, CarryOutPtr, CarryOutT, APSInt(std::move(Result), true));14311432pushInteger(S, CarryOut, Call->getType());14331434return true;1435}14361437static bool interp__builtin_os_log_format_buffer_size(InterpState &S,1438CodePtr OpPC,1439const InterpFrame *Frame,1440const CallExpr *Call) {1441analyze_os_log::OSLogBufferLayout Layout;1442analyze_os_log::computeOSLogBufferLayout(S.getASTContext(), Call, Layout);1443pushInteger(S, Layout.size().getQuantity(), Call->getType());1444return true;1445}14461447static bool1448interp__builtin_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC,1449const InterpFrame *Frame,1450const CallExpr *Call) {1451const auto &Ptr = S.Stk.pop<Pointer>();1452assert(Ptr.getFieldDesc()->isPrimitiveArray());14531454// This should be created for a StringLiteral, so should alway shold at least1455// one array element.1456assert(Ptr.getFieldDesc()->getNumElems() >= 1);1457StringRef R(&Ptr.deref<char>(), Ptr.getFieldDesc()->getNumElems() - 1);1458uint64_t Result = getPointerAuthStableSipHash(R);1459pushInteger(S, Result, Call->getType());1460return true;1461}14621463static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,1464const InterpFrame *Frame,1465const CallExpr *Call) {1466// A call to __operator_new is only valid within std::allocate<>::allocate.1467// Walk up the call stack to find the appropriate caller and get the1468// element type from it.1469auto [NewCall, ElemType] = S.getStdAllocatorCaller("allocate");14701471if (ElemType.isNull()) {1472S.FFDiag(Call, S.getLangOpts().CPlusPlus201473? diag::note_constexpr_new_untyped1474: diag::note_constexpr_new);1475return false;1476}1477assert(NewCall);14781479if (ElemType->isIncompleteType() || ElemType->isFunctionType()) {1480S.FFDiag(Call, diag::note_constexpr_new_not_complete_object_type)1481<< (ElemType->isIncompleteType() ? 0 : 1) << ElemType;1482return false;1483}14841485// We only care about the first parameter (the size), so discard all the1486// others.1487{1488unsigned NumArgs = Call->getNumArgs();1489assert(NumArgs >= 1);14901491// The std::nothrow_t arg never gets put on the stack.1492if (Call->getArg(NumArgs - 1)->getType()->isNothrowT())1493--NumArgs;1494auto Args = ArrayRef(Call->getArgs(), Call->getNumArgs());1495// First arg is needed.1496Args = Args.drop_front();14971498// Discard the rest.1499for (const Expr *Arg : Args)1500discard(S.Stk, *S.getContext().classify(Arg));1501}15021503APSInt Bytes = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(0)));1504CharUnits ElemSize = S.getASTContext().getTypeSizeInChars(ElemType);1505assert(!ElemSize.isZero());1506// Divide the number of bytes by sizeof(ElemType), so we get the number of1507// elements we should allocate.1508APInt NumElems, Remainder;1509APInt ElemSizeAP(Bytes.getBitWidth(), ElemSize.getQuantity());1510APInt::udivrem(Bytes, ElemSizeAP, NumElems, Remainder);1511if (Remainder != 0) {1512// This likely indicates a bug in the implementation of 'std::allocator'.1513S.FFDiag(Call, diag::note_constexpr_operator_new_bad_size)1514<< Bytes << APSInt(ElemSizeAP, true) << ElemType;1515return false;1516}15171518// NB: The same check we're using in CheckArraySize()1519if (NumElems.getActiveBits() >1520ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||1521NumElems.ugt(Descriptor::MaxArrayElemBytes / ElemSize.getQuantity())) {1522// FIXME: NoThrow check?1523const SourceInfo &Loc = S.Current->getSource(OpPC);1524S.FFDiag(Loc, diag::note_constexpr_new_too_large)1525<< NumElems.getZExtValue();1526return false;1527}15281529if (!CheckArraySize(S, OpPC, NumElems.getZExtValue()))1530return false;15311532bool IsArray = NumElems.ugt(1);1533std::optional<PrimType> ElemT = S.getContext().classify(ElemType);1534DynamicAllocator &Allocator = S.getAllocator();1535if (ElemT) {1536Block *B =1537Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(),1538S.Ctx.getEvalID(), DynamicAllocator::Form::Operator);1539assert(B);1540S.Stk.push<Pointer>(Pointer(B).atIndex(0));1541return true;1542}15431544assert(!ElemT);15451546// Composite arrays1547if (IsArray) {1548const Descriptor *Desc =1549S.P.createDescriptor(NewCall, ElemType.getTypePtr(),1550IsArray ? std::nullopt : Descriptor::InlineDescMD);1551Block *B =1552Allocator.allocate(Desc, NumElems.getZExtValue(), S.Ctx.getEvalID(),1553DynamicAllocator::Form::Operator);1554assert(B);1555S.Stk.push<Pointer>(Pointer(B).atIndex(0));1556return true;1557}15581559// Records. Still allocate them as single-element arrays.1560QualType AllocType = S.getASTContext().getConstantArrayType(1561ElemType, NumElems, nullptr, ArraySizeModifier::Normal, 0);15621563const Descriptor *Desc =1564S.P.createDescriptor(NewCall, AllocType.getTypePtr(),1565IsArray ? std::nullopt : Descriptor::InlineDescMD);1566Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(),1567DynamicAllocator::Form::Operator);1568assert(B);1569S.Stk.push<Pointer>(Pointer(B).atIndex(0).narrow());1570return true;1571}15721573static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC,1574const InterpFrame *Frame,1575const CallExpr *Call) {1576const Expr *Source = nullptr;1577const Block *BlockToDelete = nullptr;15781579if (S.checkingPotentialConstantExpression()) {1580S.Stk.discard<Pointer>();1581return false;1582}15831584// This is permitted only within a call to std::allocator<T>::deallocate.1585if (!S.getStdAllocatorCaller("deallocate")) {1586S.FFDiag(Call);1587S.Stk.discard<Pointer>();1588return true;1589}15901591{1592const Pointer &Ptr = S.Stk.pop<Pointer>();15931594if (Ptr.isZero()) {1595S.CCEDiag(Call, diag::note_constexpr_deallocate_null);1596return true;1597}15981599Source = Ptr.getDeclDesc()->asExpr();1600BlockToDelete = Ptr.block();16011602if (!BlockToDelete->isDynamic()) {1603S.FFDiag(Call, diag::note_constexpr_delete_not_heap_alloc)1604<< Ptr.toDiagnosticString(S.getASTContext());1605if (const auto *D = Ptr.getFieldDesc()->asDecl())1606S.Note(D->getLocation(), diag::note_declared_at);1607}1608}1609assert(BlockToDelete);16101611DynamicAllocator &Allocator = S.getAllocator();1612const Descriptor *BlockDesc = BlockToDelete->getDescriptor();1613std::optional<DynamicAllocator::Form> AllocForm =1614Allocator.getAllocationForm(Source);16151616if (!Allocator.deallocate(Source, BlockToDelete, S)) {1617// Nothing has been deallocated, this must be a double-delete.1618const SourceInfo &Loc = S.Current->getSource(OpPC);1619S.FFDiag(Loc, diag::note_constexpr_double_delete);1620return false;1621}1622assert(AllocForm);16231624return CheckNewDeleteForms(1625S, OpPC, *AllocForm, DynamicAllocator::Form::Operator, BlockDesc, Source);1626}16271628static bool interp__builtin_arithmetic_fence(InterpState &S, CodePtr OpPC,1629const InterpFrame *Frame,1630const CallExpr *Call) {1631const Floating &Arg0 = S.Stk.pop<Floating>();1632S.Stk.push<Floating>(Arg0);1633return true;1634}16351636static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,1637const CallExpr *Call, unsigned ID) {1638const Pointer &Arg = S.Stk.pop<Pointer>();1639assert(Arg.getFieldDesc()->isPrimitiveArray());16401641QualType ElemType = Arg.getFieldDesc()->getElemQualType();1642assert(Call->getType() == ElemType);1643PrimType ElemT = *S.getContext().classify(ElemType);1644unsigned NumElems = Arg.getNumElems();16451646INT_TYPE_SWITCH_NO_BOOL(ElemT, {1647T Result = Arg.atIndex(0).deref<T>();1648unsigned BitWidth = Result.bitWidth();1649for (unsigned I = 1; I != NumElems; ++I) {1650T Elem = Arg.atIndex(I).deref<T>();1651T PrevResult = Result;16521653if (ID == Builtin::BI__builtin_reduce_add) {1654if (T::add(Result, Elem, BitWidth, &Result)) {1655unsigned OverflowBits = BitWidth + 1;1656(void)handleOverflow(S, OpPC,1657(PrevResult.toAPSInt(OverflowBits) +1658Elem.toAPSInt(OverflowBits)));1659return false;1660}1661} else if (ID == Builtin::BI__builtin_reduce_mul) {1662if (T::mul(Result, Elem, BitWidth, &Result)) {1663unsigned OverflowBits = BitWidth * 2;1664(void)handleOverflow(S, OpPC,1665(PrevResult.toAPSInt(OverflowBits) *1666Elem.toAPSInt(OverflowBits)));1667return false;1668}16691670} else if (ID == Builtin::BI__builtin_reduce_and) {1671(void)T::bitAnd(Result, Elem, BitWidth, &Result);1672} else if (ID == Builtin::BI__builtin_reduce_or) {1673(void)T::bitOr(Result, Elem, BitWidth, &Result);1674} else if (ID == Builtin::BI__builtin_reduce_xor) {1675(void)T::bitXor(Result, Elem, BitWidth, &Result);1676} else if (ID == Builtin::BI__builtin_reduce_min) {1677if (Elem < Result)1678Result = Elem;1679} else if (ID == Builtin::BI__builtin_reduce_max) {1680if (Elem > Result)1681Result = Elem;1682} else {1683llvm_unreachable("Unhandled vector reduce builtin");1684}1685}1686pushInteger(S, Result.toAPSInt(), Call->getType());1687});16881689return true;1690}16911692/// Can be called with an integer or vector as the first and only parameter.1693static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC,1694const InterpFrame *Frame,1695const CallExpr *Call,1696unsigned BuiltinID) {1697assert(Call->getNumArgs() == 1);1698if (Call->getArg(0)->getType()->isIntegerType()) {1699PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());1700APSInt Val = popToAPSInt(S.Stk, ArgT);17011702if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) {1703pushInteger(S, Val.popcount(), Call->getType());1704} else {1705pushInteger(S, Val.reverseBits(), Call->getType());1706}1707return true;1708}1709// Otherwise, the argument must be a vector.1710assert(Call->getArg(0)->getType()->isVectorType());1711const Pointer &Arg = S.Stk.pop<Pointer>();1712assert(Arg.getFieldDesc()->isPrimitiveArray());1713const Pointer &Dst = S.Stk.peek<Pointer>();1714assert(Dst.getFieldDesc()->isPrimitiveArray());1715assert(Arg.getFieldDesc()->getNumElems() ==1716Dst.getFieldDesc()->getNumElems());17171718QualType ElemType = Arg.getFieldDesc()->getElemQualType();1719PrimType ElemT = *S.getContext().classify(ElemType);1720unsigned NumElems = Arg.getNumElems();17211722// FIXME: Reading from uninitialized vector elements?1723for (unsigned I = 0; I != NumElems; ++I) {1724INT_TYPE_SWITCH_NO_BOOL(ElemT, {1725if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) {1726Dst.atIndex(I).deref<T>() =1727T::from(Arg.atIndex(I).deref<T>().toAPSInt().popcount());1728} else {1729Dst.atIndex(I).deref<T>() = T::from(1730Arg.atIndex(I).deref<T>().toAPSInt().reverseBits().getZExtValue());1731}1732Dst.atIndex(I).initialize();1733});1734}17351736return true;1737}17381739static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,1740const InterpFrame *Frame,1741const CallExpr *Call, unsigned ID) {1742assert(Call->getNumArgs() == 3);1743const ASTContext &ASTCtx = S.getASTContext();1744PrimType SizeT = *S.getContext().classify(Call->getArg(2));1745APSInt Size = popToAPSInt(S.Stk, SizeT);1746const Pointer SrcPtr = S.Stk.pop<Pointer>();1747const Pointer DestPtr = S.Stk.pop<Pointer>();17481749assert(!Size.isSigned() && "memcpy and friends take an unsigned size");17501751if (ID == Builtin::BImemcpy || ID == Builtin::BImemmove)1752diagnoseNonConstexprBuiltin(S, OpPC, ID);17531754bool Move =1755(ID == Builtin::BI__builtin_memmove || ID == Builtin::BImemmove ||1756ID == Builtin::BI__builtin_wmemmove || ID == Builtin::BIwmemmove);1757bool WChar = ID == Builtin::BIwmemcpy || ID == Builtin::BIwmemmove ||1758ID == Builtin::BI__builtin_wmemcpy ||1759ID == Builtin::BI__builtin_wmemmove;17601761// If the size is zero, we treat this as always being a valid no-op.1762if (Size.isZero()) {1763S.Stk.push<Pointer>(DestPtr);1764return true;1765}17661767if (SrcPtr.isZero() || DestPtr.isZero()) {1768Pointer DiagPtr = (SrcPtr.isZero() ? SrcPtr : DestPtr);1769S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)1770<< /*IsMove=*/Move << /*IsWchar=*/WChar << !SrcPtr.isZero()1771<< DiagPtr.toDiagnosticString(ASTCtx);1772return false;1773}17741775// Diagnose integral src/dest pointers specially.1776if (SrcPtr.isIntegralPointer() || DestPtr.isIntegralPointer()) {1777std::string DiagVal = "(void *)";1778DiagVal += SrcPtr.isIntegralPointer()1779? std::to_string(SrcPtr.getIntegerRepresentation())1780: std::to_string(DestPtr.getIntegerRepresentation());1781S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)1782<< Move << WChar << DestPtr.isIntegralPointer() << DiagVal;1783return false;1784}17851786// Can't read from dummy pointers.1787if (DestPtr.isDummy() || SrcPtr.isDummy())1788return false;17891790QualType DestElemType = getElemType(DestPtr);1791size_t RemainingDestElems;1792if (DestPtr.getFieldDesc()->isArray()) {1793RemainingDestElems = DestPtr.isUnknownSizeArray()1794? 01795: (DestPtr.getNumElems() - DestPtr.getIndex());1796} else {1797RemainingDestElems = 1;1798}1799unsigned DestElemSize = ASTCtx.getTypeSizeInChars(DestElemType).getQuantity();18001801if (WChar) {1802uint64_t WCharSize =1803ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();1804Size *= APSInt(APInt(Size.getBitWidth(), WCharSize, /*IsSigned=*/false),1805/*IsUnsigend=*/true);1806}18071808if (Size.urem(DestElemSize) != 0) {1809S.FFDiag(S.Current->getSource(OpPC),1810diag::note_constexpr_memcpy_unsupported)1811<< Move << WChar << 0 << DestElemType << Size << DestElemSize;1812return false;1813}18141815QualType SrcElemType = getElemType(SrcPtr);1816size_t RemainingSrcElems;1817if (SrcPtr.getFieldDesc()->isArray()) {1818RemainingSrcElems = SrcPtr.isUnknownSizeArray()1819? 01820: (SrcPtr.getNumElems() - SrcPtr.getIndex());1821} else {1822RemainingSrcElems = 1;1823}1824unsigned SrcElemSize = ASTCtx.getTypeSizeInChars(SrcElemType).getQuantity();18251826if (!ASTCtx.hasSameUnqualifiedType(DestElemType, SrcElemType)) {1827S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_type_pun)1828<< Move << SrcElemType << DestElemType;1829return false;1830}18311832if (DestElemType->isIncompleteType() ||1833DestPtr.getType()->isIncompleteType()) {1834QualType DiagType =1835DestElemType->isIncompleteType() ? DestElemType : DestPtr.getType();1836S.FFDiag(S.Current->getSource(OpPC),1837diag::note_constexpr_memcpy_incomplete_type)1838<< Move << DiagType;1839return false;1840}18411842if (!DestElemType.isTriviallyCopyableType(ASTCtx)) {1843S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_nontrivial)1844<< Move << DestElemType;1845return false;1846}18471848// Check if we have enough elements to read from and write to.1849size_t RemainingDestBytes = RemainingDestElems * DestElemSize;1850size_t RemainingSrcBytes = RemainingSrcElems * SrcElemSize;1851if (Size.ugt(RemainingDestBytes) || Size.ugt(RemainingSrcBytes)) {1852APInt N = Size.udiv(DestElemSize);1853S.FFDiag(S.Current->getSource(OpPC),1854diag::note_constexpr_memcpy_unsupported)1855<< Move << WChar << (Size.ugt(RemainingSrcBytes) ? 1 : 2)1856<< DestElemType << toString(N, 10, /*Signed=*/false);1857return false;1858}18591860// Check for overlapping memory regions.1861if (!Move && Pointer::pointToSameBlock(SrcPtr, DestPtr)) {1862// Remove base casts.1863Pointer SrcP = SrcPtr;1864while (SrcP.isBaseClass())1865SrcP = SrcP.getBase();18661867Pointer DestP = DestPtr;1868while (DestP.isBaseClass())1869DestP = DestP.getBase();18701871unsigned SrcIndex = SrcP.expand().getIndex() * SrcP.elemSize();1872unsigned DstIndex = DestP.expand().getIndex() * DestP.elemSize();1873unsigned N = Size.getZExtValue();18741875if ((SrcIndex <= DstIndex && (SrcIndex + N) > DstIndex) ||1876(DstIndex <= SrcIndex && (DstIndex + N) > SrcIndex)) {1877S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_overlap)1878<< /*IsWChar=*/false;1879return false;1880}1881}18821883assert(Size.getZExtValue() % DestElemSize == 0);1884if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size.getZExtValue()).toBits()))1885return false;18861887S.Stk.push<Pointer>(DestPtr);1888return true;1889}18901891/// Determine if T is a character type for which we guarantee that1892/// sizeof(T) == 1.1893static bool isOneByteCharacterType(QualType T) {1894return T->isCharType() || T->isChar8Type();1895}18961897static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,1898const InterpFrame *Frame,1899const CallExpr *Call, unsigned ID) {1900assert(Call->getNumArgs() == 3);1901PrimType SizeT = *S.getContext().classify(Call->getArg(2));1902const APSInt &Size = popToAPSInt(S.Stk, SizeT);1903const Pointer &PtrB = S.Stk.pop<Pointer>();1904const Pointer &PtrA = S.Stk.pop<Pointer>();19051906if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp ||1907ID == Builtin::BIwmemcmp)1908diagnoseNonConstexprBuiltin(S, OpPC, ID);19091910if (Size.isZero()) {1911pushInteger(S, 0, Call->getType());1912return true;1913}19141915bool IsWide =1916(ID == Builtin::BIwmemcmp || ID == Builtin::BI__builtin_wmemcmp);19171918const ASTContext &ASTCtx = S.getASTContext();1919QualType ElemTypeA = getElemType(PtrA);1920QualType ElemTypeB = getElemType(PtrB);1921// FIXME: This is an arbitrary limitation the current constant interpreter1922// had. We could remove this.1923if (!IsWide && (!isOneByteCharacterType(ElemTypeA) ||1924!isOneByteCharacterType(ElemTypeB))) {1925S.FFDiag(S.Current->getSource(OpPC),1926diag::note_constexpr_memcmp_unsupported)1927<< ASTCtx.BuiltinInfo.getQuotedName(ID) << PtrA.getType()1928<< PtrB.getType();1929return false;1930}19311932if (PtrA.isDummy() || PtrB.isDummy())1933return false;19341935// Now, read both pointers to a buffer and compare those.1936BitcastBuffer BufferA(1937Bits(ASTCtx.getTypeSize(ElemTypeA) * PtrA.getNumElems()));1938readPointerToBuffer(S.getContext(), PtrA, BufferA, false);1939// FIXME: The swapping here is UNDOING something we do when reading the1940// data into the buffer.1941if (ASTCtx.getTargetInfo().isBigEndian())1942swapBytes(BufferA.Data.get(), BufferA.byteSize().getQuantity());19431944BitcastBuffer BufferB(1945Bits(ASTCtx.getTypeSize(ElemTypeB) * PtrB.getNumElems()));1946readPointerToBuffer(S.getContext(), PtrB, BufferB, false);1947// FIXME: The swapping here is UNDOING something we do when reading the1948// data into the buffer.1949if (ASTCtx.getTargetInfo().isBigEndian())1950swapBytes(BufferB.Data.get(), BufferB.byteSize().getQuantity());19511952size_t MinBufferSize = std::min(BufferA.byteSize().getQuantity(),1953BufferB.byteSize().getQuantity());19541955unsigned ElemSize = 1;1956if (IsWide)1957ElemSize = ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();1958// The Size given for the wide variants is in wide-char units. Convert it1959// to bytes.1960size_t ByteSize = Size.getZExtValue() * ElemSize;1961size_t CmpSize = std::min(MinBufferSize, ByteSize);19621963for (size_t I = 0; I != CmpSize; I += ElemSize) {1964if (IsWide) {1965INT_TYPE_SWITCH(*S.getContext().classify(ASTCtx.getWCharType()), {1966T A = *reinterpret_cast<T *>(BufferA.Data.get() + I);1967T B = *reinterpret_cast<T *>(BufferB.Data.get() + I);1968if (A < B) {1969pushInteger(S, -1, Call->getType());1970return true;1971} else if (A > B) {1972pushInteger(S, 1, Call->getType());1973return true;1974}1975});1976} else {1977std::byte A = BufferA.Data[I];1978std::byte B = BufferB.Data[I];19791980if (A < B) {1981pushInteger(S, -1, Call->getType());1982return true;1983} else if (A > B) {1984pushInteger(S, 1, Call->getType());1985return true;1986}1987}1988}19891990// We compared CmpSize bytes above. If the limiting factor was the Size1991// passed, we're done and the result is equality (0).1992if (ByteSize <= CmpSize) {1993pushInteger(S, 0, Call->getType());1994return true;1995}19961997// However, if we read all the available bytes but were instructed to read1998// even more, diagnose this as a "read of dereferenced one-past-the-end1999// pointer". This is what would happen if we called CheckLoad() on every array2000// element.2001S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)2002<< AK_Read << S.Current->getRange(OpPC);2003return false;2004}20052006// __builtin_memchr(ptr, int, int)2007// __builtin_strchr(ptr, int)2008static bool interp__builtin_memchr(InterpState &S, CodePtr OpPC,2009const CallExpr *Call, unsigned ID) {2010if (ID == Builtin::BImemchr || ID == Builtin::BIwcschr ||2011ID == Builtin::BIstrchr || ID == Builtin::BIwmemchr)2012diagnoseNonConstexprBuiltin(S, OpPC, ID);20132014std::optional<APSInt> MaxLength;2015PrimType DesiredT = *S.getContext().classify(Call->getArg(1));2016if (Call->getNumArgs() == 3) {2017PrimType MaxT = *S.getContext().classify(Call->getArg(2));2018MaxLength = popToAPSInt(S.Stk, MaxT);2019}2020APSInt Desired = popToAPSInt(S.Stk, DesiredT);2021const Pointer &Ptr = S.Stk.pop<Pointer>();20222023if (MaxLength && MaxLength->isZero()) {2024S.Stk.push<Pointer>();2025return true;2026}20272028if (Ptr.isDummy())2029return false;20302031// Null is only okay if the given size is 0.2032if (Ptr.isZero()) {2033S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)2034<< AK_Read;2035return false;2036}20372038QualType ElemTy = Ptr.getFieldDesc()->isArray()2039? Ptr.getFieldDesc()->getElemQualType()2040: Ptr.getFieldDesc()->getType();2041bool IsRawByte = ID == Builtin::BImemchr || ID == Builtin::BI__builtin_memchr;20422043// Give up on byte-oriented matching against multibyte elements.2044if (IsRawByte && !isOneByteCharacterType(ElemTy)) {2045S.FFDiag(S.Current->getSource(OpPC),2046diag::note_constexpr_memchr_unsupported)2047<< S.getASTContext().BuiltinInfo.getQuotedName(ID) << ElemTy;2048return false;2049}20502051if (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr) {2052// strchr compares directly to the passed integer, and therefore2053// always fails if given an int that is not a char.2054if (Desired !=2055Desired.trunc(S.getASTContext().getCharWidth()).getSExtValue()) {2056S.Stk.push<Pointer>();2057return true;2058}2059}20602061uint64_t DesiredVal;2062if (ID == Builtin::BIwmemchr || ID == Builtin::BI__builtin_wmemchr ||2063ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr) {2064// wcschr and wmemchr are given a wchar_t to look for. Just use it.2065DesiredVal = Desired.getZExtValue();2066} else {2067DesiredVal = Desired.trunc(S.getASTContext().getCharWidth()).getZExtValue();2068}20692070bool StopAtZero =2071(ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr ||2072ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr);20732074PrimType ElemT =2075IsRawByte ? PT_Sint8 : *S.getContext().classify(getElemType(Ptr));20762077size_t Index = Ptr.getIndex();2078size_t Step = 0;2079for (;;) {2080const Pointer &ElemPtr =2081(Index + Step) > 0 ? Ptr.atIndex(Index + Step) : Ptr;20822083if (!CheckLoad(S, OpPC, ElemPtr))2084return false;20852086uint64_t V;2087INT_TYPE_SWITCH_NO_BOOL(2088ElemT, { V = static_cast<uint64_t>(ElemPtr.deref<T>().toUnsigned()); });20892090if (V == DesiredVal) {2091S.Stk.push<Pointer>(ElemPtr);2092return true;2093}20942095if (StopAtZero && V == 0)2096break;20972098++Step;2099if (MaxLength && Step == MaxLength->getZExtValue())2100break;2101}21022103S.Stk.push<Pointer>();2104return true;2105}21062107static unsigned computeFullDescSize(const ASTContext &ASTCtx,2108const Descriptor *Desc) {21092110if (Desc->isPrimitive())2111return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();21122113if (Desc->isArray())2114return ASTCtx.getTypeSizeInChars(Desc->getElemQualType()).getQuantity() *2115Desc->getNumElems();21162117if (Desc->isRecord())2118return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();21192120llvm_unreachable("Unhandled descriptor type");2121return 0;2122}21232124static unsigned computePointerOffset(const ASTContext &ASTCtx,2125const Pointer &Ptr) {2126unsigned Result = 0;21272128Pointer P = Ptr;2129while (P.isArrayElement() || P.isField()) {2130P = P.expand();2131const Descriptor *D = P.getFieldDesc();21322133if (P.isArrayElement()) {2134unsigned ElemSize =2135ASTCtx.getTypeSizeInChars(D->getElemQualType()).getQuantity();2136if (P.isOnePastEnd())2137Result += ElemSize * P.getNumElems();2138else2139Result += ElemSize * P.getIndex();2140P = P.expand().getArray();2141} else if (P.isBaseClass()) {21422143const auto *RD = cast<CXXRecordDecl>(D->asDecl());2144bool IsVirtual = Ptr.isVirtualBaseClass();2145P = P.getBase();2146const Record *BaseRecord = P.getRecord();21472148const ASTRecordLayout &Layout =2149ASTCtx.getASTRecordLayout(cast<CXXRecordDecl>(BaseRecord->getDecl()));2150if (IsVirtual)2151Result += Layout.getVBaseClassOffset(RD).getQuantity();2152else2153Result += Layout.getBaseClassOffset(RD).getQuantity();2154} else if (P.isField()) {2155const FieldDecl *FD = P.getField();2156const ASTRecordLayout &Layout =2157ASTCtx.getASTRecordLayout(FD->getParent());2158unsigned FieldIndex = FD->getFieldIndex();2159uint64_t FieldOffset =2160ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex))2161.getQuantity();2162Result += FieldOffset;2163P = P.getBase();2164} else2165llvm_unreachable("Unhandled descriptor type");2166}21672168return Result;2169}21702171static bool interp__builtin_object_size(InterpState &S, CodePtr OpPC,2172const InterpFrame *Frame,2173const CallExpr *Call) {2174PrimType KindT = *S.getContext().classify(Call->getArg(1));2175[[maybe_unused]] unsigned Kind = popToAPSInt(S.Stk, KindT).getZExtValue();21762177assert(Kind <= 3 && "unexpected kind");21782179const Pointer &Ptr = S.Stk.pop<Pointer>();21802181if (Ptr.isZero())2182return false;21832184const Descriptor *DeclDesc = Ptr.getDeclDesc();2185if (!DeclDesc)2186return false;21872188const ASTContext &ASTCtx = S.getASTContext();21892190unsigned ByteOffset = computePointerOffset(ASTCtx, Ptr);2191unsigned FullSize = computeFullDescSize(ASTCtx, DeclDesc);21922193pushInteger(S, FullSize - ByteOffset, Call->getType());21942195return true;2196}21972198static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,2199const CallExpr *Call) {22002201if (!S.inConstantContext())2202return false;22032204const Pointer &Ptr = S.Stk.pop<Pointer>();22052206auto Error = [&](int Diag) {2207bool CalledFromStd = false;2208const auto *Callee = S.Current->getCallee();2209if (Callee && Callee->isInStdNamespace()) {2210const IdentifierInfo *Identifier = Callee->getIdentifier();2211CalledFromStd = Identifier && Identifier->isStr("is_within_lifetime");2212}2213S.CCEDiag(CalledFromStd2214? S.Current->Caller->getSource(S.Current->getRetPC())2215: S.Current->getSource(OpPC),2216diag::err_invalid_is_within_lifetime)2217<< (CalledFromStd ? "std::is_within_lifetime"2218: "__builtin_is_within_lifetime")2219<< Diag;2220return false;2221};22222223if (Ptr.isZero())2224return Error(0);2225if (Ptr.isOnePastEnd())2226return Error(1);22272228bool Result = Ptr.getLifetime() != Lifetime::Ended;2229if (!Ptr.isActive()) {2230Result = false;2231} else {2232if (!CheckLive(S, OpPC, Ptr, AK_Read))2233return false;2234if (!CheckMutable(S, OpPC, Ptr))2235return false;2236if (!CheckDummy(S, OpPC, Ptr, AK_Read))2237return false;2238}22392240// Check if we're currently running an initializer.2241for (InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) {2242if (const Function *F = Frame->getFunction();2243F && F->isConstructor() && Frame->getThis().block() == Ptr.block()) {2244return Error(2);2245}2246}2247if (S.EvaluatingDecl && Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl)2248return Error(2);22492250pushInteger(S, Result, Call->getType());2251return true;2252}22532254static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC,2255const CallExpr *Call,2256unsigned BuiltinID) {2257Call->dumpColor();2258assert(Call->getNumArgs() == 2);22592260// Single integer case.2261if (!Call->getArg(0)->getType()->isVectorType()) {2262assert(!Call->getArg(1)->getType()->isVectorType());2263APSInt RHS = popToAPSInt(2264S.Stk, *S.getContext().classify(Call->getArg(1)->getType()));2265APSInt LHS = popToAPSInt(2266S.Stk, *S.getContext().classify(Call->getArg(0)->getType()));2267APInt Result;2268if (BuiltinID == Builtin::BI__builtin_elementwise_add_sat) {2269Result = LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS);2270} else if (BuiltinID == Builtin::BI__builtin_elementwise_sub_sat) {2271Result = LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS);2272} else {2273llvm_unreachable("Wrong builtin ID");2274}22752276pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType());2277return true;2278}22792280// Vector case.2281assert(Call->getArg(0)->getType()->isVectorType() &&2282Call->getArg(1)->getType()->isVectorType());2283const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();2284assert(VT->getElementType() ==2285Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());2286assert(VT->getNumElements() ==2287Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());2288assert(VT->getElementType()->isIntegralOrEnumerationType());22892290const Pointer &RHS = S.Stk.pop<Pointer>();2291const Pointer &LHS = S.Stk.pop<Pointer>();2292const Pointer &Dst = S.Stk.peek<Pointer>();2293PrimType ElemT = *S.getContext().classify(VT->getElementType());2294unsigned NumElems = VT->getNumElements();2295for (unsigned I = 0; I != NumElems; ++I) {2296APSInt Elem1;2297APSInt Elem2;2298INT_TYPE_SWITCH_NO_BOOL(ElemT, {2299Elem1 = LHS.atIndex(I).deref<T>().toAPSInt();2300Elem2 = RHS.atIndex(I).deref<T>().toAPSInt();2301});23022303APSInt Result;2304if (BuiltinID == Builtin::BI__builtin_elementwise_add_sat) {2305Result = APSInt(Elem1.isSigned() ? Elem1.sadd_sat(Elem2)2306: Elem1.uadd_sat(Elem2),2307Call->getType()->isUnsignedIntegerOrEnumerationType());2308} else if (BuiltinID == Builtin::BI__builtin_elementwise_sub_sat) {2309Result = APSInt(Elem1.isSigned() ? Elem1.ssub_sat(Elem2)2310: Elem1.usub_sat(Elem2),2311Call->getType()->isUnsignedIntegerOrEnumerationType());2312} else {2313llvm_unreachable("Wrong builtin ID");2314}23152316INT_TYPE_SWITCH_NO_BOOL(ElemT, {2317const Pointer &E = Dst.atIndex(I);2318E.deref<T>() = static_cast<T>(Result);2319E.initialize();2320});2321}23222323return true;2324}23252326bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,2327uint32_t BuiltinID) {2328if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID))2329return Invalid(S, OpPC);23302331const InterpFrame *Frame = S.Current;2332switch (BuiltinID) {2333case Builtin::BI__builtin_is_constant_evaluated:2334return interp__builtin_is_constant_evaluated(S, OpPC, Frame, Call);23352336case Builtin::BI__builtin_assume:2337case Builtin::BI__assume:2338return interp__builtin_assume(S, OpPC, Frame, Call);23392340case Builtin::BI__builtin_strcmp:2341case Builtin::BIstrcmp:2342case Builtin::BI__builtin_strncmp:2343case Builtin::BIstrncmp:2344case Builtin::BI__builtin_wcsncmp:2345case Builtin::BIwcsncmp:2346case Builtin::BI__builtin_wcscmp:2347case Builtin::BIwcscmp:2348return interp__builtin_strcmp(S, OpPC, Frame, Call, BuiltinID);23492350case Builtin::BI__builtin_strlen:2351case Builtin::BIstrlen:2352case Builtin::BI__builtin_wcslen:2353case Builtin::BIwcslen:2354return interp__builtin_strlen(S, OpPC, Frame, Call, BuiltinID);23552356case Builtin::BI__builtin_nan:2357case Builtin::BI__builtin_nanf:2358case Builtin::BI__builtin_nanl:2359case Builtin::BI__builtin_nanf16:2360case Builtin::BI__builtin_nanf128:2361return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/false);23622363case Builtin::BI__builtin_nans:2364case Builtin::BI__builtin_nansf:2365case Builtin::BI__builtin_nansl:2366case Builtin::BI__builtin_nansf16:2367case Builtin::BI__builtin_nansf128:2368return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/true);23692370case Builtin::BI__builtin_huge_val:2371case Builtin::BI__builtin_huge_valf:2372case Builtin::BI__builtin_huge_vall:2373case Builtin::BI__builtin_huge_valf16:2374case Builtin::BI__builtin_huge_valf128:2375case Builtin::BI__builtin_inf:2376case Builtin::BI__builtin_inff:2377case Builtin::BI__builtin_infl:2378case Builtin::BI__builtin_inff16:2379case Builtin::BI__builtin_inff128:2380return interp__builtin_inf(S, OpPC, Frame, Call);23812382case Builtin::BI__builtin_copysign:2383case Builtin::BI__builtin_copysignf:2384case Builtin::BI__builtin_copysignl:2385case Builtin::BI__builtin_copysignf128:2386return interp__builtin_copysign(S, OpPC, Frame);23872388case Builtin::BI__builtin_fmin:2389case Builtin::BI__builtin_fminf:2390case Builtin::BI__builtin_fminl:2391case Builtin::BI__builtin_fminf16:2392case Builtin::BI__builtin_fminf128:2393return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/false);23942395case Builtin::BI__builtin_fminimum_num:2396case Builtin::BI__builtin_fminimum_numf:2397case Builtin::BI__builtin_fminimum_numl:2398case Builtin::BI__builtin_fminimum_numf16:2399case Builtin::BI__builtin_fminimum_numf128:2400return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/true);24012402case Builtin::BI__builtin_fmax:2403case Builtin::BI__builtin_fmaxf:2404case Builtin::BI__builtin_fmaxl:2405case Builtin::BI__builtin_fmaxf16:2406case Builtin::BI__builtin_fmaxf128:2407return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/false);24082409case Builtin::BI__builtin_fmaximum_num:2410case Builtin::BI__builtin_fmaximum_numf:2411case Builtin::BI__builtin_fmaximum_numl:2412case Builtin::BI__builtin_fmaximum_numf16:2413case Builtin::BI__builtin_fmaximum_numf128:2414return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/true);24152416case Builtin::BI__builtin_isnan:2417return interp__builtin_isnan(S, OpPC, Frame, Call);24182419case Builtin::BI__builtin_issignaling:2420return interp__builtin_issignaling(S, OpPC, Frame, Call);24212422case Builtin::BI__builtin_isinf:2423return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/false, Call);24242425case Builtin::BI__builtin_isinf_sign:2426return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/true, Call);24272428case Builtin::BI__builtin_isfinite:2429return interp__builtin_isfinite(S, OpPC, Frame, Call);24302431case Builtin::BI__builtin_isnormal:2432return interp__builtin_isnormal(S, OpPC, Frame, Call);24332434case Builtin::BI__builtin_issubnormal:2435return interp__builtin_issubnormal(S, OpPC, Frame, Call);24362437case Builtin::BI__builtin_iszero:2438return interp__builtin_iszero(S, OpPC, Frame, Call);24392440case Builtin::BI__builtin_signbit:2441case Builtin::BI__builtin_signbitf:2442case Builtin::BI__builtin_signbitl:2443return interp__builtin_signbit(S, OpPC, Frame, Call);24442445case Builtin::BI__builtin_isgreater:2446case Builtin::BI__builtin_isgreaterequal:2447case Builtin::BI__builtin_isless:2448case Builtin::BI__builtin_islessequal:2449case Builtin::BI__builtin_islessgreater:2450case Builtin::BI__builtin_isunordered:2451return interp_floating_comparison(S, OpPC, Call, BuiltinID);24522453case Builtin::BI__builtin_isfpclass:2454return interp__builtin_isfpclass(S, OpPC, Frame, Call);24552456case Builtin::BI__builtin_fpclassify:2457return interp__builtin_fpclassify(S, OpPC, Frame, Call);24582459case Builtin::BI__builtin_fabs:2460case Builtin::BI__builtin_fabsf:2461case Builtin::BI__builtin_fabsl:2462case Builtin::BI__builtin_fabsf128:2463return interp__builtin_fabs(S, OpPC, Frame);24642465case Builtin::BI__builtin_abs:2466case Builtin::BI__builtin_labs:2467case Builtin::BI__builtin_llabs:2468return interp__builtin_abs(S, OpPC, Frame, Call);24692470case Builtin::BI__builtin_popcount:2471case Builtin::BI__builtin_popcountl:2472case Builtin::BI__builtin_popcountll:2473case Builtin::BI__builtin_popcountg:2474case Builtin::BI__popcnt16: // Microsoft variants of popcount2475case Builtin::BI__popcnt:2476case Builtin::BI__popcnt64:2477return interp__builtin_popcount(S, OpPC, Frame, Call);24782479case Builtin::BI__builtin_parity:2480case Builtin::BI__builtin_parityl:2481case Builtin::BI__builtin_parityll:2482return interp__builtin_parity(S, OpPC, Frame, Call);24832484case Builtin::BI__builtin_clrsb:2485case Builtin::BI__builtin_clrsbl:2486case Builtin::BI__builtin_clrsbll:2487return interp__builtin_clrsb(S, OpPC, Frame, Call);24882489case Builtin::BI__builtin_bitreverse8:2490case Builtin::BI__builtin_bitreverse16:2491case Builtin::BI__builtin_bitreverse32:2492case Builtin::BI__builtin_bitreverse64:2493return interp__builtin_bitreverse(S, OpPC, Frame, Call);24942495case Builtin::BI__builtin_classify_type:2496return interp__builtin_classify_type(S, OpPC, Frame, Call);24972498case Builtin::BI__builtin_expect:2499case Builtin::BI__builtin_expect_with_probability:2500return interp__builtin_expect(S, OpPC, Frame, Call);25012502case Builtin::BI__builtin_rotateleft8:2503case Builtin::BI__builtin_rotateleft16:2504case Builtin::BI__builtin_rotateleft32:2505case Builtin::BI__builtin_rotateleft64:2506case Builtin::BI_rotl8: // Microsoft variants of rotate left2507case Builtin::BI_rotl16:2508case Builtin::BI_rotl:2509case Builtin::BI_lrotl:2510case Builtin::BI_rotl64:2511return interp__builtin_rotate(S, OpPC, Frame, Call, /*Right=*/false);25122513case Builtin::BI__builtin_rotateright8:2514case Builtin::BI__builtin_rotateright16:2515case Builtin::BI__builtin_rotateright32:2516case Builtin::BI__builtin_rotateright64:2517case Builtin::BI_rotr8: // Microsoft variants of rotate right2518case Builtin::BI_rotr16:2519case Builtin::BI_rotr:2520case Builtin::BI_lrotr:2521case Builtin::BI_rotr64:2522return interp__builtin_rotate(S, OpPC, Frame, Call, /*Right=*/true);25232524case Builtin::BI__builtin_ffs:2525case Builtin::BI__builtin_ffsl:2526case Builtin::BI__builtin_ffsll:2527return interp__builtin_ffs(S, OpPC, Frame, Call);25282529case Builtin::BIaddressof:2530case Builtin::BI__addressof:2531case Builtin::BI__builtin_addressof:2532assert(isNoopBuiltin(BuiltinID));2533return interp__builtin_addressof(S, OpPC, Frame, Call);25342535case Builtin::BIas_const:2536case Builtin::BIforward:2537case Builtin::BIforward_like:2538case Builtin::BImove:2539case Builtin::BImove_if_noexcept:2540assert(isNoopBuiltin(BuiltinID));2541return interp__builtin_move(S, OpPC, Frame, Call);25422543case Builtin::BI__builtin_eh_return_data_regno:2544return interp__builtin_eh_return_data_regno(S, OpPC, Frame, Call);25452546case Builtin::BI__builtin_launder:2547assert(isNoopBuiltin(BuiltinID));2548return true;25492550case Builtin::BI__builtin_add_overflow:2551case Builtin::BI__builtin_sub_overflow:2552case Builtin::BI__builtin_mul_overflow:2553case Builtin::BI__builtin_sadd_overflow:2554case Builtin::BI__builtin_uadd_overflow:2555case Builtin::BI__builtin_uaddl_overflow:2556case Builtin::BI__builtin_uaddll_overflow:2557case Builtin::BI__builtin_usub_overflow:2558case Builtin::BI__builtin_usubl_overflow:2559case Builtin::BI__builtin_usubll_overflow:2560case Builtin::BI__builtin_umul_overflow:2561case Builtin::BI__builtin_umull_overflow:2562case Builtin::BI__builtin_umulll_overflow:2563case Builtin::BI__builtin_saddl_overflow:2564case Builtin::BI__builtin_saddll_overflow:2565case Builtin::BI__builtin_ssub_overflow:2566case Builtin::BI__builtin_ssubl_overflow:2567case Builtin::BI__builtin_ssubll_overflow:2568case Builtin::BI__builtin_smul_overflow:2569case Builtin::BI__builtin_smull_overflow:2570case Builtin::BI__builtin_smulll_overflow:2571return interp__builtin_overflowop(S, OpPC, Call, BuiltinID);25722573case Builtin::BI__builtin_addcb:2574case Builtin::BI__builtin_addcs:2575case Builtin::BI__builtin_addc:2576case Builtin::BI__builtin_addcl:2577case Builtin::BI__builtin_addcll:2578case Builtin::BI__builtin_subcb:2579case Builtin::BI__builtin_subcs:2580case Builtin::BI__builtin_subc:2581case Builtin::BI__builtin_subcl:2582case Builtin::BI__builtin_subcll:2583return interp__builtin_carryop(S, OpPC, Frame, Call, BuiltinID);25842585case Builtin::BI__builtin_clz:2586case Builtin::BI__builtin_clzl:2587case Builtin::BI__builtin_clzll:2588case Builtin::BI__builtin_clzs:2589case Builtin::BI__builtin_clzg:2590case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes2591case Builtin::BI__lzcnt:2592case Builtin::BI__lzcnt64:2593return interp__builtin_clz(S, OpPC, Frame, Call, BuiltinID);25942595case Builtin::BI__builtin_ctz:2596case Builtin::BI__builtin_ctzl:2597case Builtin::BI__builtin_ctzll:2598case Builtin::BI__builtin_ctzs:2599case Builtin::BI__builtin_ctzg:2600return interp__builtin_ctz(S, OpPC, Frame, Call, BuiltinID);26012602case Builtin::BI__builtin_bswap16:2603case Builtin::BI__builtin_bswap32:2604case Builtin::BI__builtin_bswap64:2605return interp__builtin_bswap(S, OpPC, Frame, Call);26062607case Builtin::BI__atomic_always_lock_free:2608case Builtin::BI__atomic_is_lock_free:2609return interp__builtin_atomic_lock_free(S, OpPC, Frame, Call, BuiltinID);26102611case Builtin::BI__c11_atomic_is_lock_free:2612return interp__builtin_c11_atomic_is_lock_free(S, OpPC, Frame, Call);26132614case Builtin::BI__builtin_complex:2615return interp__builtin_complex(S, OpPC, Frame, Call);26162617case Builtin::BI__builtin_is_aligned:2618case Builtin::BI__builtin_align_up:2619case Builtin::BI__builtin_align_down:2620return interp__builtin_is_aligned_up_down(S, OpPC, Frame, Call, BuiltinID);26212622case Builtin::BI__builtin_assume_aligned:2623return interp__builtin_assume_aligned(S, OpPC, Frame, Call);26242625case clang::X86::BI__builtin_ia32_bextr_u32:2626case clang::X86::BI__builtin_ia32_bextr_u64:2627case clang::X86::BI__builtin_ia32_bextri_u32:2628case clang::X86::BI__builtin_ia32_bextri_u64:2629return interp__builtin_ia32_bextr(S, OpPC, Frame, Call);26302631case clang::X86::BI__builtin_ia32_bzhi_si:2632case clang::X86::BI__builtin_ia32_bzhi_di:2633return interp__builtin_ia32_bzhi(S, OpPC, Frame, Call);26342635case clang::X86::BI__builtin_ia32_lzcnt_u16:2636case clang::X86::BI__builtin_ia32_lzcnt_u32:2637case clang::X86::BI__builtin_ia32_lzcnt_u64:2638return interp__builtin_ia32_lzcnt(S, OpPC, Frame, Call);26392640case clang::X86::BI__builtin_ia32_tzcnt_u16:2641case clang::X86::BI__builtin_ia32_tzcnt_u32:2642case clang::X86::BI__builtin_ia32_tzcnt_u64:2643return interp__builtin_ia32_tzcnt(S, OpPC, Frame, Call);26442645case clang::X86::BI__builtin_ia32_pdep_si:2646case clang::X86::BI__builtin_ia32_pdep_di:2647return interp__builtin_ia32_pdep(S, OpPC, Frame, Call);26482649case clang::X86::BI__builtin_ia32_pext_si:2650case clang::X86::BI__builtin_ia32_pext_di:2651return interp__builtin_ia32_pext(S, OpPC, Frame, Call);26522653case clang::X86::BI__builtin_ia32_addcarryx_u32:2654case clang::X86::BI__builtin_ia32_addcarryx_u64:2655case clang::X86::BI__builtin_ia32_subborrow_u32:2656case clang::X86::BI__builtin_ia32_subborrow_u64:2657return interp__builtin_ia32_addcarry_subborrow(S, OpPC, Frame, Call,2658BuiltinID);26592660case Builtin::BI__builtin_os_log_format_buffer_size:2661return interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, Call);26622663case Builtin::BI__builtin_ptrauth_string_discriminator:2664return interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, Call);26652666case Builtin::BI__noop:2667pushInteger(S, 0, Call->getType());2668return true;26692670case Builtin::BI__builtin_operator_new:2671return interp__builtin_operator_new(S, OpPC, Frame, Call);26722673case Builtin::BI__builtin_operator_delete:2674return interp__builtin_operator_delete(S, OpPC, Frame, Call);26752676case Builtin::BI__arithmetic_fence:2677return interp__builtin_arithmetic_fence(S, OpPC, Frame, Call);26782679case Builtin::BI__builtin_reduce_add:2680case Builtin::BI__builtin_reduce_mul:2681case Builtin::BI__builtin_reduce_and:2682case Builtin::BI__builtin_reduce_or:2683case Builtin::BI__builtin_reduce_xor:2684case Builtin::BI__builtin_reduce_min:2685case Builtin::BI__builtin_reduce_max:2686return interp__builtin_vector_reduce(S, OpPC, Call, BuiltinID);26872688case Builtin::BI__builtin_elementwise_popcount:2689case Builtin::BI__builtin_elementwise_bitreverse:2690return interp__builtin_elementwise_popcount(S, OpPC, Frame, Call,2691BuiltinID);26922693case Builtin::BI__builtin_memcpy:2694case Builtin::BImemcpy:2695case Builtin::BI__builtin_wmemcpy:2696case Builtin::BIwmemcpy:2697case Builtin::BI__builtin_memmove:2698case Builtin::BImemmove:2699case Builtin::BI__builtin_wmemmove:2700case Builtin::BIwmemmove:2701return interp__builtin_memcpy(S, OpPC, Frame, Call, BuiltinID);27022703case Builtin::BI__builtin_memcmp:2704case Builtin::BImemcmp:2705case Builtin::BI__builtin_bcmp:2706case Builtin::BIbcmp:2707case Builtin::BI__builtin_wmemcmp:2708case Builtin::BIwmemcmp:2709return interp__builtin_memcmp(S, OpPC, Frame, Call, BuiltinID);27102711case Builtin::BImemchr:2712case Builtin::BI__builtin_memchr:2713case Builtin::BIstrchr:2714case Builtin::BI__builtin_strchr:2715case Builtin::BIwmemchr:2716case Builtin::BI__builtin_wmemchr:2717case Builtin::BIwcschr:2718case Builtin::BI__builtin_wcschr:2719case Builtin::BI__builtin_char_memchr:2720return interp__builtin_memchr(S, OpPC, Call, BuiltinID);27212722case Builtin::BI__builtin_object_size:2723case Builtin::BI__builtin_dynamic_object_size:2724return interp__builtin_object_size(S, OpPC, Frame, Call);27252726case Builtin::BI__builtin_is_within_lifetime:2727return interp__builtin_is_within_lifetime(S, OpPC, Call);27282729case Builtin::BI__builtin_elementwise_add_sat:2730case Builtin::BI__builtin_elementwise_sub_sat:2731return interp__builtin_elementwise_sat(S, OpPC, Call, BuiltinID);27322733default:2734S.FFDiag(S.Current->getLocation(OpPC),2735diag::note_invalid_subexpr_in_const_expr)2736<< S.Current->getRange(OpPC);27372738return false;2739}27402741llvm_unreachable("Unhandled builtin ID");2742}27432744bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,2745ArrayRef<int64_t> ArrayIndices, int64_t &IntResult) {2746CharUnits Result;2747unsigned N = E->getNumComponents();2748assert(N > 0);27492750unsigned ArrayIndex = 0;2751QualType CurrentType = E->getTypeSourceInfo()->getType();2752for (unsigned I = 0; I != N; ++I) {2753const OffsetOfNode &Node = E->getComponent(I);2754switch (Node.getKind()) {2755case OffsetOfNode::Field: {2756const FieldDecl *MemberDecl = Node.getField();2757const RecordType *RT = CurrentType->getAs<RecordType>();2758if (!RT)2759return false;2760const RecordDecl *RD = RT->getDecl();2761if (RD->isInvalidDecl())2762return false;2763const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD);2764unsigned FieldIndex = MemberDecl->getFieldIndex();2765assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");2766Result +=2767S.getASTContext().toCharUnitsFromBits(RL.getFieldOffset(FieldIndex));2768CurrentType = MemberDecl->getType().getNonReferenceType();2769break;2770}2771case OffsetOfNode::Array: {2772// When generating bytecode, we put all the index expressions as Sint64 on2773// the stack.2774int64_t Index = ArrayIndices[ArrayIndex];2775const ArrayType *AT = S.getASTContext().getAsArrayType(CurrentType);2776if (!AT)2777return false;2778CurrentType = AT->getElementType();2779CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType);2780Result += Index * ElementSize;2781++ArrayIndex;2782break;2783}2784case OffsetOfNode::Base: {2785const CXXBaseSpecifier *BaseSpec = Node.getBase();2786if (BaseSpec->isVirtual())2787return false;27882789// Find the layout of the class whose base we are looking into.2790const RecordType *RT = CurrentType->getAs<RecordType>();2791if (!RT)2792return false;2793const RecordDecl *RD = RT->getDecl();2794if (RD->isInvalidDecl())2795return false;2796const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD);27972798// Find the base class itself.2799CurrentType = BaseSpec->getType();2800const RecordType *BaseRT = CurrentType->getAs<RecordType>();2801if (!BaseRT)2802return false;28032804// Add the offset to the base.2805Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));2806break;2807}2808case OffsetOfNode::Identifier:2809llvm_unreachable("Dependent OffsetOfExpr?");2810}2811}28122813IntResult = Result.getQuantity();28142815return true;2816}28172818bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,2819const Pointer &Ptr, const APSInt &IntValue) {28202821const Record *R = Ptr.getRecord();2822assert(R);2823assert(R->getNumFields() == 1);28242825unsigned FieldOffset = R->getField(0u)->Offset;2826const Pointer &FieldPtr = Ptr.atField(FieldOffset);2827PrimType FieldT = *S.getContext().classify(FieldPtr.getType());28282829INT_TYPE_SWITCH(FieldT,2830FieldPtr.deref<T>() = T::from(IntValue.getSExtValue()));2831FieldPtr.initialize();2832return true;2833}28342835static void zeroAll(Pointer &Dest) {2836const Descriptor *Desc = Dest.getFieldDesc();28372838if (Desc->isPrimitive()) {2839TYPE_SWITCH(Desc->getPrimType(), {2840Dest.deref<T>().~T();2841new (&Dest.deref<T>()) T();2842});2843return;2844}28452846if (Desc->isRecord()) {2847const Record *R = Desc->ElemRecord;2848for (const Record::Field &F : R->fields()) {2849Pointer FieldPtr = Dest.atField(F.Offset);2850zeroAll(FieldPtr);2851}2852return;2853}28542855if (Desc->isPrimitiveArray()) {2856for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {2857TYPE_SWITCH(Desc->getPrimType(), {2858Dest.deref<T>().~T();2859new (&Dest.deref<T>()) T();2860});2861}2862return;2863}28642865if (Desc->isCompositeArray()) {2866for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {2867Pointer ElemPtr = Dest.atIndex(I).narrow();2868zeroAll(ElemPtr);2869}2870return;2871}2872}28732874static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,2875Pointer &Dest, bool Activate);2876static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,2877Pointer &Dest, bool Activate = false) {2878[[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();2879const Descriptor *DestDesc = Dest.getFieldDesc();28802881auto copyField = [&](const Record::Field &F, bool Activate) -> bool {2882Pointer DestField = Dest.atField(F.Offset);2883if (std::optional<PrimType> FT = S.Ctx.classify(F.Decl->getType())) {2884TYPE_SWITCH(*FT, {2885DestField.deref<T>() = Src.atField(F.Offset).deref<T>();2886if (Src.atField(F.Offset).isInitialized())2887DestField.initialize();2888if (Activate)2889DestField.activate();2890});2891return true;2892}2893// Composite field.2894return copyComposite(S, OpPC, Src.atField(F.Offset), DestField, Activate);2895};28962897assert(SrcDesc->isRecord());2898assert(SrcDesc->ElemRecord == DestDesc->ElemRecord);2899const Record *R = DestDesc->ElemRecord;2900for (const Record::Field &F : R->fields()) {2901if (R->isUnion()) {2902// For unions, only copy the active field. Zero all others.2903const Pointer &SrcField = Src.atField(F.Offset);2904if (SrcField.isActive()) {2905if (!copyField(F, /*Activate=*/true))2906return false;2907} else {2908Pointer DestField = Dest.atField(F.Offset);2909zeroAll(DestField);2910}2911} else {2912if (!copyField(F, Activate))2913return false;2914}2915}29162917for (const Record::Base &B : R->bases()) {2918Pointer DestBase = Dest.atField(B.Offset);2919if (!copyRecord(S, OpPC, Src.atField(B.Offset), DestBase, Activate))2920return false;2921}29222923Dest.initialize();2924return true;2925}29262927static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,2928Pointer &Dest, bool Activate = false) {2929assert(Src.isLive() && Dest.isLive());29302931[[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();2932const Descriptor *DestDesc = Dest.getFieldDesc();29332934assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive());29352936if (DestDesc->isPrimitiveArray()) {2937assert(SrcDesc->isPrimitiveArray());2938assert(SrcDesc->getNumElems() == DestDesc->getNumElems());2939PrimType ET = DestDesc->getPrimType();2940for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {2941Pointer DestElem = Dest.atIndex(I);2942TYPE_SWITCH(ET, {2943DestElem.deref<T>() = Src.atIndex(I).deref<T>();2944DestElem.initialize();2945});2946}2947return true;2948}29492950if (DestDesc->isCompositeArray()) {2951assert(SrcDesc->isCompositeArray());2952assert(SrcDesc->getNumElems() == DestDesc->getNumElems());2953for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {2954const Pointer &SrcElem = Src.atIndex(I).narrow();2955Pointer DestElem = Dest.atIndex(I).narrow();2956if (!copyComposite(S, OpPC, SrcElem, DestElem, Activate))2957return false;2958}2959return true;2960}29612962if (DestDesc->isRecord())2963return copyRecord(S, OpPC, Src, Dest, Activate);2964return Invalid(S, OpPC);2965}29662967bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {2968return copyComposite(S, OpPC, Src, Dest);2969}29702971} // namespace interp2972} // namespace clang297329742975