Path: blob/main/contrib/llvm-project/clang/lib/AST/Interp/InterpBuiltin.cpp
35291 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 "Interp.h"10#include "PrimType.h"11#include "clang/AST/OSLog.h"12#include "clang/AST/RecordLayout.h"13#include "clang/Basic/Builtins.h"14#include "clang/Basic/TargetInfo.h"15#include "llvm/Support/SipHash.h"1617namespace clang {18namespace interp {1920static unsigned callArgSize(const InterpState &S, const CallExpr *C) {21unsigned O = 0;2223for (const Expr *E : C->arguments()) {24O += align(primSize(*S.getContext().classify(E)));25}2627return O;28}2930template <typename T>31static T getParam(const InterpFrame *Frame, unsigned Index) {32assert(Frame->getFunction()->getNumParams() > Index);33unsigned Offset = Frame->getFunction()->getParamOffset(Index);34return Frame->getParam<T>(Offset);35}3637PrimType getIntPrimType(const InterpState &S) {38const TargetInfo &TI = S.getCtx().getTargetInfo();39unsigned IntWidth = TI.getIntWidth();4041if (IntWidth == 32)42return PT_Sint32;43else if (IntWidth == 16)44return PT_Sint16;45llvm_unreachable("Int isn't 16 or 32 bit?");46}4748PrimType getLongPrimType(const InterpState &S) {49const TargetInfo &TI = S.getCtx().getTargetInfo();50unsigned LongWidth = TI.getLongWidth();5152if (LongWidth == 64)53return PT_Sint64;54else if (LongWidth == 32)55return PT_Sint32;56else if (LongWidth == 16)57return PT_Sint16;58llvm_unreachable("long isn't 16, 32 or 64 bit?");59}6061/// Peek an integer value from the stack into an APSInt.62static APSInt peekToAPSInt(InterpStack &Stk, PrimType T, size_t Offset = 0) {63if (Offset == 0)64Offset = align(primSize(T));6566APSInt R;67INT_TYPE_SWITCH(T, R = Stk.peek<T>(Offset).toAPSInt());6869return R;70}7172/// Pushes \p Val on the stack as the type given by \p QT.73static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {74assert(QT->isSignedIntegerOrEnumerationType() ||75QT->isUnsignedIntegerOrEnumerationType());76std::optional<PrimType> T = S.getContext().classify(QT);77assert(T);7879if (QT->isSignedIntegerOrEnumerationType()) {80int64_t V = Val.getSExtValue();81INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V)); });82} else {83assert(QT->isUnsignedIntegerOrEnumerationType());84uint64_t V = Val.getZExtValue();85INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V)); });86}87}8889template <typename T>90static void pushInteger(InterpState &S, T Val, QualType QT) {91if constexpr (std::is_same_v<T, APInt>)92pushInteger(S, APSInt(Val, !std::is_signed_v<T>), QT);93else94pushInteger(S,95APSInt(APInt(sizeof(T) * 8, static_cast<uint64_t>(Val),96std::is_signed_v<T>),97!std::is_signed_v<T>),98QT);99}100101static void assignInteger(Pointer &Dest, PrimType ValueT, const APSInt &Value) {102INT_TYPE_SWITCH_NO_BOOL(103ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); });104}105106static bool retPrimValue(InterpState &S, CodePtr OpPC, APValue &Result,107std::optional<PrimType> &T) {108if (!T)109return RetVoid(S, OpPC, Result);110111#define RET_CASE(X) \112case X: \113return Ret<X>(S, OpPC, Result);114switch (*T) {115RET_CASE(PT_Ptr);116RET_CASE(PT_FnPtr);117RET_CASE(PT_Float);118RET_CASE(PT_Bool);119RET_CASE(PT_Sint8);120RET_CASE(PT_Uint8);121RET_CASE(PT_Sint16);122RET_CASE(PT_Uint16);123RET_CASE(PT_Sint32);124RET_CASE(PT_Uint32);125RET_CASE(PT_Sint64);126RET_CASE(PT_Uint64);127default:128llvm_unreachable("Unsupported return type for builtin function");129}130#undef RET_CASE131}132133static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC,134const InterpFrame *Frame,135const CallExpr *Call) {136// The current frame is the one for __builtin_is_constant_evaluated.137// The one above that, potentially the one for std::is_constant_evaluated().138if (S.inConstantContext() && !S.checkingPotentialConstantExpression() &&139Frame->Caller && S.getEvalStatus().Diag) {140auto isStdCall = [](const FunctionDecl *F) -> bool {141return F && F->isInStdNamespace() && F->getIdentifier() &&142F->getIdentifier()->isStr("is_constant_evaluated");143};144const InterpFrame *Caller = Frame->Caller;145146if (Caller->Caller && isStdCall(Caller->getCallee())) {147const Expr *E = Caller->Caller->getExpr(Caller->getRetPC());148S.report(E->getExprLoc(),149diag::warn_is_constant_evaluated_always_true_constexpr)150<< "std::is_constant_evaluated" << E->getSourceRange();151} else {152const Expr *E = Frame->Caller->getExpr(Frame->getRetPC());153S.report(E->getExprLoc(),154diag::warn_is_constant_evaluated_always_true_constexpr)155<< "__builtin_is_constant_evaluated" << E->getSourceRange();156}157}158159S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));160return true;161}162163static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,164const InterpFrame *Frame,165const CallExpr *Call) {166const Pointer &A = getParam<Pointer>(Frame, 0);167const Pointer &B = getParam<Pointer>(Frame, 1);168169if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))170return false;171172if (A.isDummy() || B.isDummy())173return false;174175assert(A.getFieldDesc()->isPrimitiveArray());176assert(B.getFieldDesc()->isPrimitiveArray());177178unsigned IndexA = A.getIndex();179unsigned IndexB = B.getIndex();180int32_t Result = 0;181for (;; ++IndexA, ++IndexB) {182const Pointer &PA = A.atIndex(IndexA);183const Pointer &PB = B.atIndex(IndexB);184if (!CheckRange(S, OpPC, PA, AK_Read) ||185!CheckRange(S, OpPC, PB, AK_Read)) {186return false;187}188uint8_t CA = PA.deref<uint8_t>();189uint8_t CB = PB.deref<uint8_t>();190191if (CA > CB) {192Result = 1;193break;194} else if (CA < CB) {195Result = -1;196break;197}198if (CA == 0 || CB == 0)199break;200}201202pushInteger(S, Result, Call->getType());203return true;204}205206static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,207const InterpFrame *Frame,208const CallExpr *Call) {209const Pointer &StrPtr = getParam<Pointer>(Frame, 0);210211if (!CheckArray(S, OpPC, StrPtr))212return false;213214if (!CheckLive(S, OpPC, StrPtr, AK_Read))215return false;216217if (!CheckDummy(S, OpPC, StrPtr, AK_Read))218return false;219220assert(StrPtr.getFieldDesc()->isPrimitiveArray());221222size_t Len = 0;223for (size_t I = StrPtr.getIndex();; ++I, ++Len) {224const Pointer &ElemPtr = StrPtr.atIndex(I);225226if (!CheckRange(S, OpPC, ElemPtr, AK_Read))227return false;228229uint8_t Val = ElemPtr.deref<uint8_t>();230if (Val == 0)231break;232}233234pushInteger(S, Len, Call->getType());235236return true;237}238239static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,240const InterpFrame *Frame, const Function *F,241bool Signaling) {242const Pointer &Arg = getParam<Pointer>(Frame, 0);243244if (!CheckLoad(S, OpPC, Arg))245return false;246247assert(Arg.getFieldDesc()->isPrimitiveArray());248249// Convert the given string to an integer using StringRef's API.250llvm::APInt Fill;251std::string Str;252assert(Arg.getNumElems() >= 1);253for (unsigned I = 0;; ++I) {254const Pointer &Elem = Arg.atIndex(I);255256if (!CheckLoad(S, OpPC, Elem))257return false;258259if (Elem.deref<int8_t>() == 0)260break;261262Str += Elem.deref<char>();263}264265// Treat empty strings as if they were zero.266if (Str.empty())267Fill = llvm::APInt(32, 0);268else if (StringRef(Str).getAsInteger(0, Fill))269return false;270271const llvm::fltSemantics &TargetSemantics =272S.getCtx().getFloatTypeSemantics(F->getDecl()->getReturnType());273274Floating Result;275if (S.getCtx().getTargetInfo().isNan2008()) {276if (Signaling)277Result = Floating(278llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));279else280Result = Floating(281llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));282} else {283// Prior to IEEE 754-2008, architectures were allowed to choose whether284// the first bit of their significand was set for qNaN or sNaN. MIPS chose285// a different encoding to what became a standard in 2008, and for pre-286// 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as287// sNaN. This is now known as "legacy NaN" encoding.288if (Signaling)289Result = Floating(290llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));291else292Result = Floating(293llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));294}295296S.Stk.push<Floating>(Result);297return true;298}299300static bool interp__builtin_inf(InterpState &S, CodePtr OpPC,301const InterpFrame *Frame, const Function *F) {302const llvm::fltSemantics &TargetSemantics =303S.getCtx().getFloatTypeSemantics(F->getDecl()->getReturnType());304305S.Stk.push<Floating>(Floating::getInf(TargetSemantics));306return true;307}308309static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC,310const InterpFrame *Frame,311const Function *F) {312const Floating &Arg1 = getParam<Floating>(Frame, 0);313const Floating &Arg2 = getParam<Floating>(Frame, 1);314315APFloat Copy = Arg1.getAPFloat();316Copy.copySign(Arg2.getAPFloat());317S.Stk.push<Floating>(Floating(Copy));318319return true;320}321322static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC,323const InterpFrame *Frame, const Function *F) {324const Floating &LHS = getParam<Floating>(Frame, 0);325const Floating &RHS = getParam<Floating>(Frame, 1);326327Floating Result;328329// When comparing zeroes, return -0.0 if one of the zeroes is negative.330if (LHS.isZero() && RHS.isZero() && RHS.isNegative())331Result = RHS;332else if (LHS.isNan() || RHS < LHS)333Result = RHS;334else335Result = LHS;336337S.Stk.push<Floating>(Result);338return true;339}340341static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC,342const InterpFrame *Frame,343const Function *Func) {344const Floating &LHS = getParam<Floating>(Frame, 0);345const Floating &RHS = getParam<Floating>(Frame, 1);346347Floating Result;348349// When comparing zeroes, return +0.0 if one of the zeroes is positive.350if (LHS.isZero() && RHS.isZero() && LHS.isNegative())351Result = RHS;352else if (LHS.isNan() || RHS > LHS)353Result = RHS;354else355Result = LHS;356357S.Stk.push<Floating>(Result);358return true;359}360361/// Defined as __builtin_isnan(...), to accommodate the fact that it can362/// take a float, double, long double, etc.363/// But for us, that's all a Floating anyway.364static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC,365const InterpFrame *Frame, const Function *F,366const CallExpr *Call) {367const Floating &Arg = S.Stk.peek<Floating>();368369pushInteger(S, Arg.isNan(), Call->getType());370return true;371}372373static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC,374const InterpFrame *Frame,375const Function *F,376const CallExpr *Call) {377const Floating &Arg = S.Stk.peek<Floating>();378379pushInteger(S, Arg.isSignaling(), Call->getType());380return true;381}382383static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC,384const InterpFrame *Frame, const Function *F,385bool CheckSign, const CallExpr *Call) {386const Floating &Arg = S.Stk.peek<Floating>();387bool IsInf = Arg.isInf();388389if (CheckSign)390pushInteger(S, IsInf ? (Arg.isNegative() ? -1 : 1) : 0, Call->getType());391else392pushInteger(S, Arg.isInf(), Call->getType());393return true;394}395396static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC,397const InterpFrame *Frame,398const Function *F, const CallExpr *Call) {399const Floating &Arg = S.Stk.peek<Floating>();400401pushInteger(S, Arg.isFinite(), Call->getType());402return true;403}404405static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC,406const InterpFrame *Frame,407const Function *F, const CallExpr *Call) {408const Floating &Arg = S.Stk.peek<Floating>();409410pushInteger(S, Arg.isNormal(), Call->getType());411return true;412}413414static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC,415const InterpFrame *Frame,416const Function *F,417const CallExpr *Call) {418const Floating &Arg = S.Stk.peek<Floating>();419420pushInteger(S, Arg.isDenormal(), Call->getType());421return true;422}423424static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC,425const InterpFrame *Frame, const Function *F,426const CallExpr *Call) {427const Floating &Arg = S.Stk.peek<Floating>();428429pushInteger(S, Arg.isZero(), Call->getType());430return true;431}432433/// First parameter to __builtin_isfpclass is the floating value, the434/// second one is an integral value.435static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,436const InterpFrame *Frame,437const Function *Func,438const CallExpr *Call) {439PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType());440APSInt FPClassArg = peekToAPSInt(S.Stk, FPClassArgT);441const Floating &F =442S.Stk.peek<Floating>(align(primSize(FPClassArgT) + primSize(PT_Float)));443444int32_t Result =445static_cast<int32_t>((F.classify() & FPClassArg).getZExtValue());446pushInteger(S, Result, Call->getType());447448return true;449}450451/// Five int values followed by one floating value.452static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,453const InterpFrame *Frame,454const Function *Func,455const CallExpr *Call) {456const Floating &Val = S.Stk.peek<Floating>();457458unsigned Index;459switch (Val.getCategory()) {460case APFloat::fcNaN:461Index = 0;462break;463case APFloat::fcInfinity:464Index = 1;465break;466case APFloat::fcNormal:467Index = Val.isDenormal() ? 3 : 2;468break;469case APFloat::fcZero:470Index = 4;471break;472}473474// The last argument is first on the stack.475assert(Index <= 4);476unsigned IntSize = primSize(getIntPrimType(S));477unsigned Offset =478align(primSize(PT_Float)) + ((1 + (4 - Index)) * align(IntSize));479480APSInt I = peekToAPSInt(S.Stk, getIntPrimType(S), Offset);481pushInteger(S, I, Call->getType());482return true;483}484485// The C standard says "fabs raises no floating-point exceptions,486// even if x is a signaling NaN. The returned value is independent of487// the current rounding direction mode." Therefore constant folding can488// proceed without regard to the floating point settings.489// Reference, WG14 N2478 F.10.4.3490static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,491const InterpFrame *Frame,492const Function *Func) {493const Floating &Val = getParam<Floating>(Frame, 0);494495S.Stk.push<Floating>(Floating::abs(Val));496return true;497}498499static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,500const InterpFrame *Frame,501const Function *Func,502const CallExpr *Call) {503PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());504APSInt Val = peekToAPSInt(S.Stk, ArgT);505pushInteger(S, Val.popcount(), Call->getType());506return true;507}508509static bool interp__builtin_parity(InterpState &S, CodePtr OpPC,510const InterpFrame *Frame,511const Function *Func, const CallExpr *Call) {512PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());513APSInt Val = peekToAPSInt(S.Stk, ArgT);514pushInteger(S, Val.popcount() % 2, Call->getType());515return true;516}517518static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC,519const InterpFrame *Frame,520const Function *Func, const CallExpr *Call) {521PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());522APSInt Val = peekToAPSInt(S.Stk, ArgT);523pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType());524return true;525}526527static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC,528const InterpFrame *Frame,529const Function *Func,530const CallExpr *Call) {531PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());532APSInt Val = peekToAPSInt(S.Stk, ArgT);533pushInteger(S, Val.reverseBits(), Call->getType());534return true;535}536537static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC,538const InterpFrame *Frame,539const Function *Func,540const CallExpr *Call) {541// This is an unevaluated call, so there are no arguments on the stack.542assert(Call->getNumArgs() == 1);543const Expr *Arg = Call->getArg(0);544545GCCTypeClass ResultClass =546EvaluateBuiltinClassifyType(Arg->getType(), S.getLangOpts());547int32_t ReturnVal = static_cast<int32_t>(ResultClass);548pushInteger(S, ReturnVal, Call->getType());549return true;550}551552// __builtin_expect(long, long)553// __builtin_expect_with_probability(long, long, double)554static bool interp__builtin_expect(InterpState &S, CodePtr OpPC,555const InterpFrame *Frame,556const Function *Func, const CallExpr *Call) {557// The return value is simply the value of the first parameter.558// We ignore the probability.559unsigned NumArgs = Call->getNumArgs();560assert(NumArgs == 2 || NumArgs == 3);561562PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());563unsigned Offset = align(primSize(getLongPrimType(S))) * 2;564if (NumArgs == 3)565Offset += align(primSize(PT_Float));566567APSInt Val = peekToAPSInt(S.Stk, ArgT, Offset);568pushInteger(S, Val, Call->getType());569return true;570}571572/// rotateleft(value, amount)573static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC,574const InterpFrame *Frame,575const Function *Func, const CallExpr *Call,576bool Right) {577PrimType AmountT = *S.getContext().classify(Call->getArg(1)->getType());578PrimType ValueT = *S.getContext().classify(Call->getArg(0)->getType());579580APSInt Amount = peekToAPSInt(S.Stk, AmountT);581APSInt Value = peekToAPSInt(582S.Stk, ValueT, align(primSize(AmountT)) + align(primSize(ValueT)));583584APSInt Result;585if (Right)586Result = APSInt(Value.rotr(Amount.urem(Value.getBitWidth())),587/*IsUnsigned=*/true);588else // Left.589Result = APSInt(Value.rotl(Amount.urem(Value.getBitWidth())),590/*IsUnsigned=*/true);591592pushInteger(S, Result, Call->getType());593return true;594}595596static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC,597const InterpFrame *Frame, const Function *Func,598const CallExpr *Call) {599PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());600APSInt Value = peekToAPSInt(S.Stk, ArgT);601602uint64_t N = Value.countr_zero();603pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType());604return true;605}606607static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC,608const InterpFrame *Frame,609const Function *Func,610const CallExpr *Call) {611assert(Call->getArg(0)->isLValue());612PrimType PtrT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr);613614if (PtrT == PT_FnPtr) {615const FunctionPointer &Arg = S.Stk.peek<FunctionPointer>();616S.Stk.push<FunctionPointer>(Arg);617} else if (PtrT == PT_Ptr) {618const Pointer &Arg = S.Stk.peek<Pointer>();619S.Stk.push<Pointer>(Arg);620} else {621assert(false && "Unsupported pointer type passed to __builtin_addressof()");622}623return true;624}625626static bool interp__builtin_move(InterpState &S, CodePtr OpPC,627const InterpFrame *Frame, const Function *Func,628const CallExpr *Call) {629630PrimType ArgT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr);631632TYPE_SWITCH(ArgT, const T &Arg = S.Stk.peek<T>(); S.Stk.push<T>(Arg););633634return Func->getDecl()->isConstexpr();635}636637static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC,638const InterpFrame *Frame,639const Function *Func,640const CallExpr *Call) {641PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());642APSInt Arg = peekToAPSInt(S.Stk, ArgT);643644int Result =645S.getCtx().getTargetInfo().getEHDataRegisterNumber(Arg.getZExtValue());646pushInteger(S, Result, Call->getType());647return true;648}649650/// Just takes the first Argument to the call and puts it on the stack.651static bool noopPointer(InterpState &S, CodePtr OpPC, const InterpFrame *Frame,652const Function *Func, const CallExpr *Call) {653const Pointer &Arg = S.Stk.peek<Pointer>();654S.Stk.push<Pointer>(Arg);655return true;656}657658// Two integral values followed by a pointer (lhs, rhs, resultOut)659static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC,660const InterpFrame *Frame,661const Function *Func,662const CallExpr *Call) {663Pointer &ResultPtr = S.Stk.peek<Pointer>();664if (ResultPtr.isDummy())665return false;666667unsigned BuiltinOp = Func->getBuiltinID();668PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());669PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());670APSInt RHS = peekToAPSInt(S.Stk, RHST,671align(primSize(PT_Ptr)) + align(primSize(RHST)));672APSInt LHS = peekToAPSInt(S.Stk, LHST,673align(primSize(PT_Ptr)) + align(primSize(RHST)) +674align(primSize(LHST)));675QualType ResultType = Call->getArg(2)->getType()->getPointeeType();676PrimType ResultT = *S.getContext().classify(ResultType);677bool Overflow;678679APSInt Result;680if (BuiltinOp == Builtin::BI__builtin_add_overflow ||681BuiltinOp == Builtin::BI__builtin_sub_overflow ||682BuiltinOp == Builtin::BI__builtin_mul_overflow) {683bool IsSigned = LHS.isSigned() || RHS.isSigned() ||684ResultType->isSignedIntegerOrEnumerationType();685bool AllSigned = LHS.isSigned() && RHS.isSigned() &&686ResultType->isSignedIntegerOrEnumerationType();687uint64_t LHSSize = LHS.getBitWidth();688uint64_t RHSSize = RHS.getBitWidth();689uint64_t ResultSize = S.getCtx().getTypeSize(ResultType);690uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize);691692// Add an additional bit if the signedness isn't uniformly agreed to. We693// could do this ONLY if there is a signed and an unsigned that both have694// MaxBits, but the code to check that is pretty nasty. The issue will be695// caught in the shrink-to-result later anyway.696if (IsSigned && !AllSigned)697++MaxBits;698699LHS = APSInt(LHS.extOrTrunc(MaxBits), !IsSigned);700RHS = APSInt(RHS.extOrTrunc(MaxBits), !IsSigned);701Result = APSInt(MaxBits, !IsSigned);702}703704// Find largest int.705switch (BuiltinOp) {706default:707llvm_unreachable("Invalid value for BuiltinOp");708case Builtin::BI__builtin_add_overflow:709case Builtin::BI__builtin_sadd_overflow:710case Builtin::BI__builtin_saddl_overflow:711case Builtin::BI__builtin_saddll_overflow:712case Builtin::BI__builtin_uadd_overflow:713case Builtin::BI__builtin_uaddl_overflow:714case Builtin::BI__builtin_uaddll_overflow:715Result = LHS.isSigned() ? LHS.sadd_ov(RHS, Overflow)716: LHS.uadd_ov(RHS, Overflow);717break;718case Builtin::BI__builtin_sub_overflow:719case Builtin::BI__builtin_ssub_overflow:720case Builtin::BI__builtin_ssubl_overflow:721case Builtin::BI__builtin_ssubll_overflow:722case Builtin::BI__builtin_usub_overflow:723case Builtin::BI__builtin_usubl_overflow:724case Builtin::BI__builtin_usubll_overflow:725Result = LHS.isSigned() ? LHS.ssub_ov(RHS, Overflow)726: LHS.usub_ov(RHS, Overflow);727break;728case Builtin::BI__builtin_mul_overflow:729case Builtin::BI__builtin_smul_overflow:730case Builtin::BI__builtin_smull_overflow:731case Builtin::BI__builtin_smulll_overflow:732case Builtin::BI__builtin_umul_overflow:733case Builtin::BI__builtin_umull_overflow:734case Builtin::BI__builtin_umulll_overflow:735Result = LHS.isSigned() ? LHS.smul_ov(RHS, Overflow)736: LHS.umul_ov(RHS, Overflow);737break;738}739740// In the case where multiple sizes are allowed, truncate and see if741// the values are the same.742if (BuiltinOp == Builtin::BI__builtin_add_overflow ||743BuiltinOp == Builtin::BI__builtin_sub_overflow ||744BuiltinOp == Builtin::BI__builtin_mul_overflow) {745// APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead,746// since it will give us the behavior of a TruncOrSelf in the case where747// its parameter <= its size. We previously set Result to be at least the748// type-size of the result, so getTypeSize(ResultType) <= Resu749APSInt Temp = Result.extOrTrunc(S.getCtx().getTypeSize(ResultType));750Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType());751752if (!APSInt::isSameValue(Temp, Result))753Overflow = true;754Result = Temp;755}756757// Write Result to ResultPtr and put Overflow on the stacl.758assignInteger(ResultPtr, ResultT, Result);759ResultPtr.initialize();760assert(Func->getDecl()->getReturnType()->isBooleanType());761S.Stk.push<Boolean>(Overflow);762return true;763}764765/// Three integral values followed by a pointer (lhs, rhs, carry, carryOut).766static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,767const InterpFrame *Frame,768const Function *Func,769const CallExpr *Call) {770unsigned BuiltinOp = Func->getBuiltinID();771PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());772PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());773PrimType CarryT = *S.getContext().classify(Call->getArg(2)->getType());774APSInt RHS = peekToAPSInt(S.Stk, RHST,775align(primSize(PT_Ptr)) + align(primSize(CarryT)) +776align(primSize(RHST)));777APSInt LHS =778peekToAPSInt(S.Stk, LHST,779align(primSize(PT_Ptr)) + align(primSize(RHST)) +780align(primSize(CarryT)) + align(primSize(LHST)));781APSInt CarryIn = peekToAPSInt(782S.Stk, LHST, align(primSize(PT_Ptr)) + align(primSize(CarryT)));783APSInt CarryOut;784785APSInt Result;786// Copy the number of bits and sign.787Result = LHS;788CarryOut = LHS;789790bool FirstOverflowed = false;791bool SecondOverflowed = false;792switch (BuiltinOp) {793default:794llvm_unreachable("Invalid value for BuiltinOp");795case Builtin::BI__builtin_addcb:796case Builtin::BI__builtin_addcs:797case Builtin::BI__builtin_addc:798case Builtin::BI__builtin_addcl:799case Builtin::BI__builtin_addcll:800Result =801LHS.uadd_ov(RHS, FirstOverflowed).uadd_ov(CarryIn, SecondOverflowed);802break;803case Builtin::BI__builtin_subcb:804case Builtin::BI__builtin_subcs:805case Builtin::BI__builtin_subc:806case Builtin::BI__builtin_subcl:807case Builtin::BI__builtin_subcll:808Result =809LHS.usub_ov(RHS, FirstOverflowed).usub_ov(CarryIn, SecondOverflowed);810break;811}812// It is possible for both overflows to happen but CGBuiltin uses an OR so813// this is consistent.814CarryOut = (uint64_t)(FirstOverflowed | SecondOverflowed);815816Pointer &CarryOutPtr = S.Stk.peek<Pointer>();817QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();818PrimType CarryOutT = *S.getContext().classify(CarryOutType);819assignInteger(CarryOutPtr, CarryOutT, CarryOut);820CarryOutPtr.initialize();821822assert(Call->getType() == Call->getArg(0)->getType());823pushInteger(S, Result, Call->getType());824return true;825}826827static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,828const InterpFrame *Frame, const Function *Func,829const CallExpr *Call) {830unsigned CallSize = callArgSize(S, Call);831unsigned BuiltinOp = Func->getBuiltinID();832PrimType ValT = *S.getContext().classify(Call->getArg(0));833const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize);834835// When the argument is 0, the result of GCC builtins is undefined, whereas836// for Microsoft intrinsics, the result is the bit-width of the argument.837bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&838BuiltinOp != Builtin::BI__lzcnt &&839BuiltinOp != Builtin::BI__lzcnt64;840841if (Val == 0) {842if (Func->getBuiltinID() == Builtin::BI__builtin_clzg &&843Call->getNumArgs() == 2) {844// We have a fallback parameter.845PrimType FallbackT = *S.getContext().classify(Call->getArg(1));846const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT);847pushInteger(S, Fallback, Call->getType());848return true;849}850851if (ZeroIsUndefined)852return false;853}854855pushInteger(S, Val.countl_zero(), Call->getType());856return true;857}858859static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC,860const InterpFrame *Frame, const Function *Func,861const CallExpr *Call) {862unsigned CallSize = callArgSize(S, Call);863PrimType ValT = *S.getContext().classify(Call->getArg(0));864const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize);865866if (Val == 0) {867if (Func->getBuiltinID() == Builtin::BI__builtin_ctzg &&868Call->getNumArgs() == 2) {869// We have a fallback parameter.870PrimType FallbackT = *S.getContext().classify(Call->getArg(1));871const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT);872pushInteger(S, Fallback, Call->getType());873return true;874}875return false;876}877878pushInteger(S, Val.countr_zero(), Call->getType());879return true;880}881882static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC,883const InterpFrame *Frame,884const Function *Func, const CallExpr *Call) {885PrimType ReturnT = *S.getContext().classify(Call->getType());886PrimType ValT = *S.getContext().classify(Call->getArg(0));887const APSInt &Val = peekToAPSInt(S.Stk, ValT);888assert(Val.getActiveBits() <= 64);889890INT_TYPE_SWITCH(ReturnT,891{ S.Stk.push<T>(T::from(Val.byteSwap().getZExtValue())); });892return true;893}894895/// bool __atomic_always_lock_free(size_t, void const volatile*)896/// bool __atomic_is_lock_free(size_t, void const volatile*)897/// bool __c11_atomic_is_lock_free(size_t)898static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,899const InterpFrame *Frame,900const Function *Func,901const CallExpr *Call) {902unsigned BuiltinOp = Func->getBuiltinID();903904PrimType ValT = *S.getContext().classify(Call->getArg(0));905unsigned SizeValOffset = 0;906if (BuiltinOp != Builtin::BI__c11_atomic_is_lock_free)907SizeValOffset = align(primSize(ValT)) + align(primSize(PT_Ptr));908const APSInt &SizeVal = peekToAPSInt(S.Stk, ValT, SizeValOffset);909910auto returnBool = [&S](bool Value) -> bool {911S.Stk.push<Boolean>(Value);912return true;913};914915// For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power916// of two less than or equal to the maximum inline atomic width, we know it917// is lock-free. If the size isn't a power of two, or greater than the918// maximum alignment where we promote atomics, we know it is not lock-free919// (at least not in the sense of atomic_is_lock_free). Otherwise,920// the answer can only be determined at runtime; for example, 16-byte921// atomics have lock-free implementations on some, but not all,922// x86-64 processors.923924// Check power-of-two.925CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());926if (Size.isPowerOfTwo()) {927// Check against inlining width.928unsigned InlineWidthBits =929S.getCtx().getTargetInfo().getMaxAtomicInlineWidth();930if (Size <= S.getCtx().toCharUnitsFromBits(InlineWidthBits)) {931932// OK, we will inline appropriately-aligned operations of this size,933// and _Atomic(T) is appropriately-aligned.934if (BuiltinOp == Builtin::BI__c11_atomic_is_lock_free ||935Size == CharUnits::One())936return returnBool(true);937938// Same for null pointers.939assert(BuiltinOp != Builtin::BI__c11_atomic_is_lock_free);940const Pointer &Ptr = S.Stk.peek<Pointer>();941if (Ptr.isZero())942return returnBool(true);943944QualType PointeeType = Call->getArg(1)945->IgnoreImpCasts()946->getType()947->castAs<PointerType>()948->getPointeeType();949// OK, we will inline operations on this object.950if (!PointeeType->isIncompleteType() &&951S.getCtx().getTypeAlignInChars(PointeeType) >= Size)952return returnBool(true);953}954}955956if (BuiltinOp == Builtin::BI__atomic_always_lock_free)957return returnBool(false);958959return false;960}961962/// __builtin_complex(Float A, float B);963static bool interp__builtin_complex(InterpState &S, CodePtr OpPC,964const InterpFrame *Frame,965const Function *Func,966const CallExpr *Call) {967const Floating &Arg2 = S.Stk.peek<Floating>();968const Floating &Arg1 = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2);969Pointer &Result = S.Stk.peek<Pointer>(align(primSize(PT_Float)) * 2 +970align(primSize(PT_Ptr)));971972Result.atIndex(0).deref<Floating>() = Arg1;973Result.atIndex(0).initialize();974Result.atIndex(1).deref<Floating>() = Arg2;975Result.atIndex(1).initialize();976Result.initialize();977978return true;979}980981/// __builtin_is_aligned()982/// __builtin_align_up()983/// __builtin_align_down()984/// The first parameter is either an integer or a pointer.985/// The second parameter is the requested alignment as an integer.986static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,987const InterpFrame *Frame,988const Function *Func,989const CallExpr *Call) {990unsigned BuiltinOp = Func->getBuiltinID();991unsigned CallSize = callArgSize(S, Call);992993PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1));994const APSInt &Alignment = peekToAPSInt(S.Stk, AlignmentT);995996if (Alignment < 0 || !Alignment.isPowerOf2()) {997S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment;998return false;999}1000unsigned SrcWidth = S.getCtx().getIntWidth(Call->getArg(0)->getType());1001APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1));1002if (APSInt::compareValues(Alignment, MaxValue) > 0) {1003S.FFDiag(Call, diag::note_constexpr_alignment_too_big)1004<< MaxValue << Call->getArg(0)->getType() << Alignment;1005return false;1006}10071008// The first parameter is either an integer or a pointer (but not a function1009// pointer).1010PrimType FirstArgT = *S.Ctx.classify(Call->getArg(0));10111012if (isIntegralType(FirstArgT)) {1013const APSInt &Src = peekToAPSInt(S.Stk, FirstArgT, CallSize);1014APSInt Align = Alignment.extOrTrunc(Src.getBitWidth());1015if (BuiltinOp == Builtin::BI__builtin_align_up) {1016APSInt AlignedVal =1017APSInt((Src + (Align - 1)) & ~(Align - 1), Src.isUnsigned());1018pushInteger(S, AlignedVal, Call->getType());1019} else if (BuiltinOp == Builtin::BI__builtin_align_down) {1020APSInt AlignedVal = APSInt(Src & ~(Align - 1), Src.isUnsigned());1021pushInteger(S, AlignedVal, Call->getType());1022} else {1023assert(*S.Ctx.classify(Call->getType()) == PT_Bool);1024S.Stk.push<Boolean>((Src & (Align - 1)) == 0);1025}1026return true;1027}10281029assert(FirstArgT == PT_Ptr);1030const Pointer &Ptr = S.Stk.peek<Pointer>(CallSize);10311032unsigned PtrOffset = Ptr.getByteOffset();1033PtrOffset = Ptr.getIndex();1034CharUnits BaseAlignment =1035S.getCtx().getDeclAlign(Ptr.getDeclDesc()->asValueDecl());1036CharUnits PtrAlign =1037BaseAlignment.alignmentAtOffset(CharUnits::fromQuantity(PtrOffset));10381039if (BuiltinOp == Builtin::BI__builtin_is_aligned) {1040if (PtrAlign.getQuantity() >= Alignment) {1041S.Stk.push<Boolean>(true);1042return true;1043}1044// If the alignment is not known to be sufficient, some cases could still1045// be aligned at run time. However, if the requested alignment is less or1046// equal to the base alignment and the offset is not aligned, we know that1047// the run-time value can never be aligned.1048if (BaseAlignment.getQuantity() >= Alignment &&1049PtrAlign.getQuantity() < Alignment) {1050S.Stk.push<Boolean>(false);1051return true;1052}10531054S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_compute)1055<< Alignment;1056return false;1057}10581059assert(BuiltinOp == Builtin::BI__builtin_align_down ||1060BuiltinOp == Builtin::BI__builtin_align_up);10611062// For align_up/align_down, we can return the same value if the alignment1063// is known to be greater or equal to the requested value.1064if (PtrAlign.getQuantity() >= Alignment) {1065S.Stk.push<Pointer>(Ptr);1066return true;1067}10681069// The alignment could be greater than the minimum at run-time, so we cannot1070// infer much about the resulting pointer value. One case is possible:1071// For `_Alignas(32) char buf[N]; __builtin_align_down(&buf[idx], 32)` we1072// can infer the correct index if the requested alignment is smaller than1073// the base alignment so we can perform the computation on the offset.1074if (BaseAlignment.getQuantity() >= Alignment) {1075assert(Alignment.getBitWidth() <= 64 &&1076"Cannot handle > 64-bit address-space");1077uint64_t Alignment64 = Alignment.getZExtValue();1078CharUnits NewOffset =1079CharUnits::fromQuantity(BuiltinOp == Builtin::BI__builtin_align_down1080? llvm::alignDown(PtrOffset, Alignment64)1081: llvm::alignTo(PtrOffset, Alignment64));10821083S.Stk.push<Pointer>(Ptr.atIndex(NewOffset.getQuantity()));1084return true;1085}10861087// Otherwise, we cannot constant-evaluate the result.1088S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_adjust) << Alignment;1089return false;1090}10911092static bool interp__builtin_os_log_format_buffer_size(InterpState &S,1093CodePtr OpPC,1094const InterpFrame *Frame,1095const Function *Func,1096const CallExpr *Call) {1097analyze_os_log::OSLogBufferLayout Layout;1098analyze_os_log::computeOSLogBufferLayout(S.getCtx(), Call, Layout);1099pushInteger(S, Layout.size().getQuantity(), Call->getType());1100return true;1101}11021103static bool interp__builtin_ptrauth_string_discriminator(1104InterpState &S, CodePtr OpPC, const InterpFrame *Frame,1105const Function *Func, const CallExpr *Call) {1106const auto &Ptr = S.Stk.peek<Pointer>();1107assert(Ptr.getFieldDesc()->isPrimitiveArray());11081109StringRef R(&Ptr.deref<char>(), Ptr.getFieldDesc()->getNumElems() - 1);1110uint64_t Result = getPointerAuthStableSipHash(R);1111pushInteger(S, Result, Call->getType());1112return true;1113}11141115bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,1116const CallExpr *Call) {1117const InterpFrame *Frame = S.Current;1118APValue Dummy;11191120std::optional<PrimType> ReturnT = S.getContext().classify(Call);11211122switch (F->getBuiltinID()) {1123case Builtin::BI__builtin_is_constant_evaluated:1124if (!interp__builtin_is_constant_evaluated(S, OpPC, Frame, Call))1125return false;1126break;1127case Builtin::BI__builtin_assume:1128case Builtin::BI__assume:1129break;1130case Builtin::BI__builtin_strcmp:1131if (!interp__builtin_strcmp(S, OpPC, Frame, Call))1132return false;1133break;1134case Builtin::BI__builtin_strlen:1135if (!interp__builtin_strlen(S, OpPC, Frame, Call))1136return false;1137break;1138case Builtin::BI__builtin_nan:1139case Builtin::BI__builtin_nanf:1140case Builtin::BI__builtin_nanl:1141case Builtin::BI__builtin_nanf16:1142case Builtin::BI__builtin_nanf128:1143if (!interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/false))1144return false;1145break;1146case Builtin::BI__builtin_nans:1147case Builtin::BI__builtin_nansf:1148case Builtin::BI__builtin_nansl:1149case Builtin::BI__builtin_nansf16:1150case Builtin::BI__builtin_nansf128:1151if (!interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/true))1152return false;1153break;11541155case Builtin::BI__builtin_huge_val:1156case Builtin::BI__builtin_huge_valf:1157case Builtin::BI__builtin_huge_vall:1158case Builtin::BI__builtin_huge_valf16:1159case Builtin::BI__builtin_huge_valf128:1160case Builtin::BI__builtin_inf:1161case Builtin::BI__builtin_inff:1162case Builtin::BI__builtin_infl:1163case Builtin::BI__builtin_inff16:1164case Builtin::BI__builtin_inff128:1165if (!interp__builtin_inf(S, OpPC, Frame, F))1166return false;1167break;1168case Builtin::BI__builtin_copysign:1169case Builtin::BI__builtin_copysignf:1170case Builtin::BI__builtin_copysignl:1171case Builtin::BI__builtin_copysignf128:1172if (!interp__builtin_copysign(S, OpPC, Frame, F))1173return false;1174break;11751176case Builtin::BI__builtin_fmin:1177case Builtin::BI__builtin_fminf:1178case Builtin::BI__builtin_fminl:1179case Builtin::BI__builtin_fminf16:1180case Builtin::BI__builtin_fminf128:1181if (!interp__builtin_fmin(S, OpPC, Frame, F))1182return false;1183break;11841185case Builtin::BI__builtin_fmax:1186case Builtin::BI__builtin_fmaxf:1187case Builtin::BI__builtin_fmaxl:1188case Builtin::BI__builtin_fmaxf16:1189case Builtin::BI__builtin_fmaxf128:1190if (!interp__builtin_fmax(S, OpPC, Frame, F))1191return false;1192break;11931194case Builtin::BI__builtin_isnan:1195if (!interp__builtin_isnan(S, OpPC, Frame, F, Call))1196return false;1197break;1198case Builtin::BI__builtin_issignaling:1199if (!interp__builtin_issignaling(S, OpPC, Frame, F, Call))1200return false;1201break;12021203case Builtin::BI__builtin_isinf:1204if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false, Call))1205return false;1206break;12071208case Builtin::BI__builtin_isinf_sign:1209if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true, Call))1210return false;1211break;12121213case Builtin::BI__builtin_isfinite:1214if (!interp__builtin_isfinite(S, OpPC, Frame, F, Call))1215return false;1216break;1217case Builtin::BI__builtin_isnormal:1218if (!interp__builtin_isnormal(S, OpPC, Frame, F, Call))1219return false;1220break;1221case Builtin::BI__builtin_issubnormal:1222if (!interp__builtin_issubnormal(S, OpPC, Frame, F, Call))1223return false;1224break;1225case Builtin::BI__builtin_iszero:1226if (!interp__builtin_iszero(S, OpPC, Frame, F, Call))1227return false;1228break;1229case Builtin::BI__builtin_isfpclass:1230if (!interp__builtin_isfpclass(S, OpPC, Frame, F, Call))1231return false;1232break;1233case Builtin::BI__builtin_fpclassify:1234if (!interp__builtin_fpclassify(S, OpPC, Frame, F, Call))1235return false;1236break;12371238case Builtin::BI__builtin_fabs:1239case Builtin::BI__builtin_fabsf:1240case Builtin::BI__builtin_fabsl:1241case Builtin::BI__builtin_fabsf128:1242if (!interp__builtin_fabs(S, OpPC, Frame, F))1243return false;1244break;12451246case Builtin::BI__builtin_popcount:1247case Builtin::BI__builtin_popcountl:1248case Builtin::BI__builtin_popcountll:1249case Builtin::BI__builtin_popcountg:1250case Builtin::BI__popcnt16: // Microsoft variants of popcount1251case Builtin::BI__popcnt:1252case Builtin::BI__popcnt64:1253if (!interp__builtin_popcount(S, OpPC, Frame, F, Call))1254return false;1255break;12561257case Builtin::BI__builtin_parity:1258case Builtin::BI__builtin_parityl:1259case Builtin::BI__builtin_parityll:1260if (!interp__builtin_parity(S, OpPC, Frame, F, Call))1261return false;1262break;12631264case Builtin::BI__builtin_clrsb:1265case Builtin::BI__builtin_clrsbl:1266case Builtin::BI__builtin_clrsbll:1267if (!interp__builtin_clrsb(S, OpPC, Frame, F, Call))1268return false;1269break;12701271case Builtin::BI__builtin_bitreverse8:1272case Builtin::BI__builtin_bitreverse16:1273case Builtin::BI__builtin_bitreverse32:1274case Builtin::BI__builtin_bitreverse64:1275if (!interp__builtin_bitreverse(S, OpPC, Frame, F, Call))1276return false;1277break;12781279case Builtin::BI__builtin_classify_type:1280if (!interp__builtin_classify_type(S, OpPC, Frame, F, Call))1281return false;1282break;12831284case Builtin::BI__builtin_expect:1285case Builtin::BI__builtin_expect_with_probability:1286if (!interp__builtin_expect(S, OpPC, Frame, F, Call))1287return false;1288break;12891290case Builtin::BI__builtin_rotateleft8:1291case Builtin::BI__builtin_rotateleft16:1292case Builtin::BI__builtin_rotateleft32:1293case Builtin::BI__builtin_rotateleft64:1294case Builtin::BI_rotl8: // Microsoft variants of rotate left1295case Builtin::BI_rotl16:1296case Builtin::BI_rotl:1297case Builtin::BI_lrotl:1298case Builtin::BI_rotl64:1299if (!interp__builtin_rotate(S, OpPC, Frame, F, Call, /*Right=*/false))1300return false;1301break;13021303case Builtin::BI__builtin_rotateright8:1304case Builtin::BI__builtin_rotateright16:1305case Builtin::BI__builtin_rotateright32:1306case Builtin::BI__builtin_rotateright64:1307case Builtin::BI_rotr8: // Microsoft variants of rotate right1308case Builtin::BI_rotr16:1309case Builtin::BI_rotr:1310case Builtin::BI_lrotr:1311case Builtin::BI_rotr64:1312if (!interp__builtin_rotate(S, OpPC, Frame, F, Call, /*Right=*/true))1313return false;1314break;13151316case Builtin::BI__builtin_ffs:1317case Builtin::BI__builtin_ffsl:1318case Builtin::BI__builtin_ffsll:1319if (!interp__builtin_ffs(S, OpPC, Frame, F, Call))1320return false;1321break;1322case Builtin::BIaddressof:1323case Builtin::BI__addressof:1324case Builtin::BI__builtin_addressof:1325if (!interp__builtin_addressof(S, OpPC, Frame, F, Call))1326return false;1327break;13281329case Builtin::BIas_const:1330case Builtin::BIforward:1331case Builtin::BIforward_like:1332case Builtin::BImove:1333case Builtin::BImove_if_noexcept:1334if (!interp__builtin_move(S, OpPC, Frame, F, Call))1335return false;1336break;13371338case Builtin::BI__builtin_eh_return_data_regno:1339if (!interp__builtin_eh_return_data_regno(S, OpPC, Frame, F, Call))1340return false;1341break;13421343case Builtin::BI__builtin_launder:1344if (!noopPointer(S, OpPC, Frame, F, Call))1345return false;1346break;13471348case Builtin::BI__builtin_add_overflow:1349case Builtin::BI__builtin_sub_overflow:1350case Builtin::BI__builtin_mul_overflow:1351case Builtin::BI__builtin_sadd_overflow:1352case Builtin::BI__builtin_uadd_overflow:1353case Builtin::BI__builtin_uaddl_overflow:1354case Builtin::BI__builtin_uaddll_overflow:1355case Builtin::BI__builtin_usub_overflow:1356case Builtin::BI__builtin_usubl_overflow:1357case Builtin::BI__builtin_usubll_overflow:1358case Builtin::BI__builtin_umul_overflow:1359case Builtin::BI__builtin_umull_overflow:1360case Builtin::BI__builtin_umulll_overflow:1361case Builtin::BI__builtin_saddl_overflow:1362case Builtin::BI__builtin_saddll_overflow:1363case Builtin::BI__builtin_ssub_overflow:1364case Builtin::BI__builtin_ssubl_overflow:1365case Builtin::BI__builtin_ssubll_overflow:1366case Builtin::BI__builtin_smul_overflow:1367case Builtin::BI__builtin_smull_overflow:1368case Builtin::BI__builtin_smulll_overflow:1369if (!interp__builtin_overflowop(S, OpPC, Frame, F, Call))1370return false;1371break;13721373case Builtin::BI__builtin_addcb:1374case Builtin::BI__builtin_addcs:1375case Builtin::BI__builtin_addc:1376case Builtin::BI__builtin_addcl:1377case Builtin::BI__builtin_addcll:1378case Builtin::BI__builtin_subcb:1379case Builtin::BI__builtin_subcs:1380case Builtin::BI__builtin_subc:1381case Builtin::BI__builtin_subcl:1382case Builtin::BI__builtin_subcll:1383if (!interp__builtin_carryop(S, OpPC, Frame, F, Call))1384return false;1385break;13861387case Builtin::BI__builtin_clz:1388case Builtin::BI__builtin_clzl:1389case Builtin::BI__builtin_clzll:1390case Builtin::BI__builtin_clzs:1391case Builtin::BI__builtin_clzg:1392case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes1393case Builtin::BI__lzcnt:1394case Builtin::BI__lzcnt64:1395if (!interp__builtin_clz(S, OpPC, Frame, F, Call))1396return false;1397break;13981399case Builtin::BI__builtin_ctz:1400case Builtin::BI__builtin_ctzl:1401case Builtin::BI__builtin_ctzll:1402case Builtin::BI__builtin_ctzs:1403case Builtin::BI__builtin_ctzg:1404if (!interp__builtin_ctz(S, OpPC, Frame, F, Call))1405return false;1406break;14071408case Builtin::BI__builtin_bswap16:1409case Builtin::BI__builtin_bswap32:1410case Builtin::BI__builtin_bswap64:1411if (!interp__builtin_bswap(S, OpPC, Frame, F, Call))1412return false;1413break;14141415case Builtin::BI__atomic_always_lock_free:1416case Builtin::BI__atomic_is_lock_free:1417case Builtin::BI__c11_atomic_is_lock_free:1418if (!interp__builtin_atomic_lock_free(S, OpPC, Frame, F, Call))1419return false;1420break;14211422case Builtin::BI__builtin_complex:1423if (!interp__builtin_complex(S, OpPC, Frame, F, Call))1424return false;1425break;14261427case Builtin::BI__builtin_is_aligned:1428case Builtin::BI__builtin_align_up:1429case Builtin::BI__builtin_align_down:1430if (!interp__builtin_is_aligned_up_down(S, OpPC, Frame, F, Call))1431return false;1432break;14331434case Builtin::BI__builtin_os_log_format_buffer_size:1435if (!interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, F, Call))1436return false;1437break;14381439case Builtin::BI__builtin_ptrauth_string_discriminator:1440if (!interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, F, Call))1441return false;1442break;14431444default:1445S.FFDiag(S.Current->getLocation(OpPC),1446diag::note_invalid_subexpr_in_const_expr)1447<< S.Current->getRange(OpPC);14481449return false;1450}14511452return retPrimValue(S, OpPC, Dummy, ReturnT);1453}14541455bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,1456llvm::ArrayRef<int64_t> ArrayIndices,1457int64_t &IntResult) {1458CharUnits Result;1459unsigned N = E->getNumComponents();1460assert(N > 0);14611462unsigned ArrayIndex = 0;1463QualType CurrentType = E->getTypeSourceInfo()->getType();1464for (unsigned I = 0; I != N; ++I) {1465const OffsetOfNode &Node = E->getComponent(I);1466switch (Node.getKind()) {1467case OffsetOfNode::Field: {1468const FieldDecl *MemberDecl = Node.getField();1469const RecordType *RT = CurrentType->getAs<RecordType>();1470if (!RT)1471return false;1472const RecordDecl *RD = RT->getDecl();1473if (RD->isInvalidDecl())1474return false;1475const ASTRecordLayout &RL = S.getCtx().getASTRecordLayout(RD);1476unsigned FieldIndex = MemberDecl->getFieldIndex();1477assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");1478Result += S.getCtx().toCharUnitsFromBits(RL.getFieldOffset(FieldIndex));1479CurrentType = MemberDecl->getType().getNonReferenceType();1480break;1481}1482case OffsetOfNode::Array: {1483// When generating bytecode, we put all the index expressions as Sint64 on1484// the stack.1485int64_t Index = ArrayIndices[ArrayIndex];1486const ArrayType *AT = S.getCtx().getAsArrayType(CurrentType);1487if (!AT)1488return false;1489CurrentType = AT->getElementType();1490CharUnits ElementSize = S.getCtx().getTypeSizeInChars(CurrentType);1491Result += Index * ElementSize;1492++ArrayIndex;1493break;1494}1495case OffsetOfNode::Base: {1496const CXXBaseSpecifier *BaseSpec = Node.getBase();1497if (BaseSpec->isVirtual())1498return false;14991500// Find the layout of the class whose base we are looking into.1501const RecordType *RT = CurrentType->getAs<RecordType>();1502if (!RT)1503return false;1504const RecordDecl *RD = RT->getDecl();1505if (RD->isInvalidDecl())1506return false;1507const ASTRecordLayout &RL = S.getCtx().getASTRecordLayout(RD);15081509// Find the base class itself.1510CurrentType = BaseSpec->getType();1511const RecordType *BaseRT = CurrentType->getAs<RecordType>();1512if (!BaseRT)1513return false;15141515// Add the offset to the base.1516Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));1517break;1518}1519case OffsetOfNode::Identifier:1520llvm_unreachable("Dependent OffsetOfExpr?");1521}1522}15231524IntResult = Result.getQuantity();15251526return true;1527}15281529bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,1530const Pointer &Ptr, const APSInt &IntValue) {15311532const Record *R = Ptr.getRecord();1533assert(R);1534assert(R->getNumFields() == 1);15351536unsigned FieldOffset = R->getField(0u)->Offset;1537const Pointer &FieldPtr = Ptr.atField(FieldOffset);1538PrimType FieldT = *S.getContext().classify(FieldPtr.getType());15391540INT_TYPE_SWITCH(FieldT,1541FieldPtr.deref<T>() = T::from(IntValue.getSExtValue()));1542FieldPtr.initialize();1543return true;1544}15451546bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {1547assert(Src.isLive() && Dest.isLive());15481549[[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();1550const Descriptor *DestDesc = Dest.getFieldDesc();15511552assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive());15531554if (DestDesc->isPrimitiveArray()) {1555assert(SrcDesc->isPrimitiveArray());1556assert(SrcDesc->getNumElems() == DestDesc->getNumElems());1557PrimType ET = DestDesc->getPrimType();1558for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {1559Pointer DestElem = Dest.atIndex(I);1560TYPE_SWITCH(ET, {1561DestElem.deref<T>() = Src.atIndex(I).deref<T>();1562DestElem.initialize();1563});1564}1565return true;1566}15671568if (DestDesc->isRecord()) {1569assert(SrcDesc->isRecord());1570assert(SrcDesc->ElemRecord == DestDesc->ElemRecord);1571const Record *R = DestDesc->ElemRecord;1572for (const Record::Field &F : R->fields()) {1573Pointer DestField = Dest.atField(F.Offset);1574if (std::optional<PrimType> FT = S.Ctx.classify(F.Decl->getType())) {1575TYPE_SWITCH(*FT, {1576DestField.deref<T>() = Src.atField(F.Offset).deref<T>();1577DestField.initialize();1578});1579} else {1580return Invalid(S, OpPC);1581}1582}1583return true;1584}15851586// FIXME: Composite types.15871588return Invalid(S, OpPC);1589}15901591} // namespace interp1592} // namespace clang159315941595