1a07aba5dSTimm Baeder //===--- InterpBuiltin.cpp - Interpreter for the constexpr VM ---*- C++ -*-===// 2a07aba5dSTimm Baeder // 3a07aba5dSTimm Baeder // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4a07aba5dSTimm Baeder // See https://llvm.org/LICENSE.txt for license information. 5a07aba5dSTimm Baeder // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6a07aba5dSTimm Baeder // 7a07aba5dSTimm Baeder //===----------------------------------------------------------------------===// 8a07aba5dSTimm Baeder #include "../ExprConstShared.h" 9a07aba5dSTimm Baeder #include "Boolean.h" 10a07aba5dSTimm Baeder #include "Compiler.h" 11a07aba5dSTimm Baeder #include "EvalEmitter.h" 12a07aba5dSTimm Baeder #include "Interp.h" 13ef2a104cSTimm Baeder #include "InterpBuiltinBitCast.h" 14a07aba5dSTimm Baeder #include "PrimType.h" 15a07aba5dSTimm Baeder #include "clang/AST/OSLog.h" 16a07aba5dSTimm Baeder #include "clang/AST/RecordLayout.h" 17a07aba5dSTimm Baeder #include "clang/Basic/Builtins.h" 1885181788STimm Baeder #include "clang/Basic/TargetBuiltins.h" 19a07aba5dSTimm Baeder #include "clang/Basic/TargetInfo.h" 20f0d60170STimm Baeder #include "llvm/ADT/StringExtras.h" 21a07aba5dSTimm Baeder #include "llvm/Support/SipHash.h" 22a07aba5dSTimm Baeder 23a07aba5dSTimm Baeder namespace clang { 24a07aba5dSTimm Baeder namespace interp { 25a07aba5dSTimm Baeder 26a07aba5dSTimm Baeder static unsigned callArgSize(const InterpState &S, const CallExpr *C) { 27a07aba5dSTimm Baeder unsigned O = 0; 28a07aba5dSTimm Baeder 29a07aba5dSTimm Baeder for (const Expr *E : C->arguments()) { 30a07aba5dSTimm Baeder O += align(primSize(*S.getContext().classify(E))); 31a07aba5dSTimm Baeder } 32a07aba5dSTimm Baeder 33a07aba5dSTimm Baeder return O; 34a07aba5dSTimm Baeder } 35a07aba5dSTimm Baeder 36a07aba5dSTimm Baeder template <typename T> 37a07aba5dSTimm Baeder static T getParam(const InterpFrame *Frame, unsigned Index) { 38a07aba5dSTimm Baeder assert(Frame->getFunction()->getNumParams() > Index); 39a07aba5dSTimm Baeder unsigned Offset = Frame->getFunction()->getParamOffset(Index); 40a07aba5dSTimm Baeder return Frame->getParam<T>(Offset); 41a07aba5dSTimm Baeder } 42a07aba5dSTimm Baeder 436f8e8551STimm Baeder static APSInt getAPSIntParam(const InterpFrame *Frame, unsigned Index) { 446f8e8551STimm Baeder APSInt R; 456f8e8551STimm Baeder unsigned Offset = Frame->getFunction()->getParamOffset(Index); 466f8e8551STimm Baeder INT_TYPE_SWITCH(Frame->getFunction()->getParamType(Index), 476f8e8551STimm Baeder R = Frame->getParam<T>(Offset).toAPSInt()); 486f8e8551STimm Baeder return R; 496f8e8551STimm Baeder } 506f8e8551STimm Baeder 51cbdd14eeSCongcong Cai static PrimType getIntPrimType(const InterpState &S) { 52d9e72860Syronglin const TargetInfo &TI = S.getASTContext().getTargetInfo(); 53a07aba5dSTimm Baeder unsigned IntWidth = TI.getIntWidth(); 54a07aba5dSTimm Baeder 55a07aba5dSTimm Baeder if (IntWidth == 32) 56a07aba5dSTimm Baeder return PT_Sint32; 57a07aba5dSTimm Baeder else if (IntWidth == 16) 58a07aba5dSTimm Baeder return PT_Sint16; 59a07aba5dSTimm Baeder llvm_unreachable("Int isn't 16 or 32 bit?"); 60a07aba5dSTimm Baeder } 61a07aba5dSTimm Baeder 62cbdd14eeSCongcong Cai static PrimType getLongPrimType(const InterpState &S) { 63d9e72860Syronglin const TargetInfo &TI = S.getASTContext().getTargetInfo(); 64a07aba5dSTimm Baeder unsigned LongWidth = TI.getLongWidth(); 65a07aba5dSTimm Baeder 66a07aba5dSTimm Baeder if (LongWidth == 64) 67a07aba5dSTimm Baeder return PT_Sint64; 68a07aba5dSTimm Baeder else if (LongWidth == 32) 69a07aba5dSTimm Baeder return PT_Sint32; 70a07aba5dSTimm Baeder else if (LongWidth == 16) 71a07aba5dSTimm Baeder return PT_Sint16; 72a07aba5dSTimm Baeder llvm_unreachable("long isn't 16, 32 or 64 bit?"); 73a07aba5dSTimm Baeder } 74a07aba5dSTimm Baeder 75a07aba5dSTimm Baeder /// Peek an integer value from the stack into an APSInt. 76a07aba5dSTimm Baeder static APSInt peekToAPSInt(InterpStack &Stk, PrimType T, size_t Offset = 0) { 77a07aba5dSTimm Baeder if (Offset == 0) 78a07aba5dSTimm Baeder Offset = align(primSize(T)); 79a07aba5dSTimm Baeder 80a07aba5dSTimm Baeder APSInt R; 81a07aba5dSTimm Baeder INT_TYPE_SWITCH(T, R = Stk.peek<T>(Offset).toAPSInt()); 82a07aba5dSTimm Baeder 83a07aba5dSTimm Baeder return R; 84a07aba5dSTimm Baeder } 85a07aba5dSTimm Baeder 86a07aba5dSTimm Baeder /// Pushes \p Val on the stack as the type given by \p QT. 87a07aba5dSTimm Baeder static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) { 88a07aba5dSTimm Baeder assert(QT->isSignedIntegerOrEnumerationType() || 89a07aba5dSTimm Baeder QT->isUnsignedIntegerOrEnumerationType()); 90a07aba5dSTimm Baeder std::optional<PrimType> T = S.getContext().classify(QT); 91a07aba5dSTimm Baeder assert(T); 92a07aba5dSTimm Baeder 9331bde711STimm Baeder unsigned BitWidth = S.getASTContext().getTypeSize(QT); 94a07aba5dSTimm Baeder if (QT->isSignedIntegerOrEnumerationType()) { 95a07aba5dSTimm Baeder int64_t V = Val.getSExtValue(); 9631bde711STimm Baeder INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); }); 97a07aba5dSTimm Baeder } else { 98a07aba5dSTimm Baeder assert(QT->isUnsignedIntegerOrEnumerationType()); 99a07aba5dSTimm Baeder uint64_t V = Val.getZExtValue(); 10031bde711STimm Baeder INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); }); 101a07aba5dSTimm Baeder } 102a07aba5dSTimm Baeder } 103a07aba5dSTimm Baeder 104a07aba5dSTimm Baeder template <typename T> 105a07aba5dSTimm Baeder static void pushInteger(InterpState &S, T Val, QualType QT) { 106a07aba5dSTimm Baeder if constexpr (std::is_same_v<T, APInt>) 107a07aba5dSTimm Baeder pushInteger(S, APSInt(Val, !std::is_signed_v<T>), QT); 1081288f6d4STimm Baeder else if constexpr (std::is_same_v<T, APSInt>) 1091288f6d4STimm Baeder pushInteger(S, Val, QT); 110a07aba5dSTimm Baeder else 111a07aba5dSTimm Baeder pushInteger(S, 112a07aba5dSTimm Baeder APSInt(APInt(sizeof(T) * 8, static_cast<uint64_t>(Val), 113a07aba5dSTimm Baeder std::is_signed_v<T>), 114a07aba5dSTimm Baeder !std::is_signed_v<T>), 115a07aba5dSTimm Baeder QT); 116a07aba5dSTimm Baeder } 117a07aba5dSTimm Baeder 118a07aba5dSTimm Baeder static void assignInteger(Pointer &Dest, PrimType ValueT, const APSInt &Value) { 119a07aba5dSTimm Baeder INT_TYPE_SWITCH_NO_BOOL( 120a07aba5dSTimm Baeder ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); }); 121a07aba5dSTimm Baeder } 122a07aba5dSTimm Baeder 12382ed9c03STimm Baeder static bool retPrimValue(InterpState &S, CodePtr OpPC, 124a07aba5dSTimm Baeder std::optional<PrimType> &T) { 125a07aba5dSTimm Baeder if (!T) 12682ed9c03STimm Baeder return RetVoid(S, OpPC); 127a07aba5dSTimm Baeder 128a07aba5dSTimm Baeder #define RET_CASE(X) \ 129a07aba5dSTimm Baeder case X: \ 13082ed9c03STimm Baeder return Ret<X>(S, OpPC); 131a07aba5dSTimm Baeder switch (*T) { 132a07aba5dSTimm Baeder RET_CASE(PT_Ptr); 133a07aba5dSTimm Baeder RET_CASE(PT_FnPtr); 134a07aba5dSTimm Baeder RET_CASE(PT_Float); 135a07aba5dSTimm Baeder RET_CASE(PT_Bool); 136a07aba5dSTimm Baeder RET_CASE(PT_Sint8); 137a07aba5dSTimm Baeder RET_CASE(PT_Uint8); 138a07aba5dSTimm Baeder RET_CASE(PT_Sint16); 139a07aba5dSTimm Baeder RET_CASE(PT_Uint16); 140a07aba5dSTimm Baeder RET_CASE(PT_Sint32); 141a07aba5dSTimm Baeder RET_CASE(PT_Uint32); 142a07aba5dSTimm Baeder RET_CASE(PT_Sint64); 143a07aba5dSTimm Baeder RET_CASE(PT_Uint64); 14431bde711STimm Baeder RET_CASE(PT_IntAP); 14531bde711STimm Baeder RET_CASE(PT_IntAPS); 146a07aba5dSTimm Baeder default: 147a07aba5dSTimm Baeder llvm_unreachable("Unsupported return type for builtin function"); 148a07aba5dSTimm Baeder } 149a07aba5dSTimm Baeder #undef RET_CASE 150a07aba5dSTimm Baeder } 151a07aba5dSTimm Baeder 15246446bb2STimm Baeder static void diagnoseNonConstexprBuiltin(InterpState &S, CodePtr OpPC, 15346446bb2STimm Baeder unsigned ID) { 15446446bb2STimm Baeder auto Loc = S.Current->getSource(OpPC); 15546446bb2STimm Baeder if (S.getLangOpts().CPlusPlus11) 15646446bb2STimm Baeder S.CCEDiag(Loc, diag::note_constexpr_invalid_function) 15746446bb2STimm Baeder << /*isConstexpr=*/0 << /*isConstructor=*/0 158dc3cd2e9SChandler Carruth << S.getASTContext().BuiltinInfo.getQuotedName(ID); 15946446bb2STimm Baeder else 16046446bb2STimm Baeder S.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr); 16146446bb2STimm Baeder } 16246446bb2STimm Baeder 163a07aba5dSTimm Baeder static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC, 164a07aba5dSTimm Baeder const InterpFrame *Frame, 165a07aba5dSTimm Baeder const CallExpr *Call) { 166a024a0ceSTimm Baeder unsigned Depth = S.Current->getDepth(); 167a07aba5dSTimm Baeder auto isStdCall = [](const FunctionDecl *F) -> bool { 168a07aba5dSTimm Baeder return F && F->isInStdNamespace() && F->getIdentifier() && 169a07aba5dSTimm Baeder F->getIdentifier()->isStr("is_constant_evaluated"); 170a07aba5dSTimm Baeder }; 171a07aba5dSTimm Baeder const InterpFrame *Caller = Frame->Caller; 172a024a0ceSTimm Baeder // The current frame is the one for __builtin_is_constant_evaluated. 173a024a0ceSTimm Baeder // The one above that, potentially the one for std::is_constant_evaluated(). 174a024a0ceSTimm Baeder if (S.inConstantContext() && !S.checkingPotentialConstantExpression() && 175a024a0ceSTimm Baeder S.getEvalStatus().Diag && 176a024a0ceSTimm Baeder (Depth == 1 || (Depth == 2 && isStdCall(Caller->getCallee())))) { 177a07aba5dSTimm Baeder if (Caller->Caller && isStdCall(Caller->getCallee())) { 178a07aba5dSTimm Baeder const Expr *E = Caller->Caller->getExpr(Caller->getRetPC()); 179a07aba5dSTimm Baeder S.report(E->getExprLoc(), 180a07aba5dSTimm Baeder diag::warn_is_constant_evaluated_always_true_constexpr) 181a07aba5dSTimm Baeder << "std::is_constant_evaluated" << E->getSourceRange(); 182a07aba5dSTimm Baeder } else { 183a07aba5dSTimm Baeder const Expr *E = Frame->Caller->getExpr(Frame->getRetPC()); 184a07aba5dSTimm Baeder S.report(E->getExprLoc(), 185a07aba5dSTimm Baeder diag::warn_is_constant_evaluated_always_true_constexpr) 186a07aba5dSTimm Baeder << "__builtin_is_constant_evaluated" << E->getSourceRange(); 187a07aba5dSTimm Baeder } 188a07aba5dSTimm Baeder } 189a07aba5dSTimm Baeder 190a07aba5dSTimm Baeder S.Stk.push<Boolean>(Boolean::from(S.inConstantContext())); 191a07aba5dSTimm Baeder return true; 192a07aba5dSTimm Baeder } 193a07aba5dSTimm Baeder 194a07aba5dSTimm Baeder static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, 195a07aba5dSTimm Baeder const InterpFrame *Frame, 19646446bb2STimm Baeder const Function *Func, const CallExpr *Call) { 19746446bb2STimm Baeder unsigned ID = Func->getBuiltinID(); 198a07aba5dSTimm Baeder const Pointer &A = getParam<Pointer>(Frame, 0); 199a07aba5dSTimm Baeder const Pointer &B = getParam<Pointer>(Frame, 1); 200a07aba5dSTimm Baeder 201d17e51f3STimm Baeder if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp) 20246446bb2STimm Baeder diagnoseNonConstexprBuiltin(S, OpPC, ID); 20346446bb2STimm Baeder 204d17e51f3STimm Baeder uint64_t Limit = ~static_cast<uint64_t>(0); 205d17e51f3STimm Baeder if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp) 206d17e51f3STimm Baeder Limit = peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2))) 207d17e51f3STimm Baeder .getZExtValue(); 208d17e51f3STimm Baeder 209d17e51f3STimm Baeder if (Limit == 0) { 210d17e51f3STimm Baeder pushInteger(S, 0, Call->getType()); 211d17e51f3STimm Baeder return true; 212d17e51f3STimm Baeder } 213d17e51f3STimm Baeder 214a07aba5dSTimm Baeder if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read)) 215a07aba5dSTimm Baeder return false; 216a07aba5dSTimm Baeder 217a07aba5dSTimm Baeder if (A.isDummy() || B.isDummy()) 218a07aba5dSTimm Baeder return false; 219a07aba5dSTimm Baeder 220a07aba5dSTimm Baeder assert(A.getFieldDesc()->isPrimitiveArray()); 221a07aba5dSTimm Baeder assert(B.getFieldDesc()->isPrimitiveArray()); 222a07aba5dSTimm Baeder 223a07aba5dSTimm Baeder unsigned IndexA = A.getIndex(); 224a07aba5dSTimm Baeder unsigned IndexB = B.getIndex(); 225a07aba5dSTimm Baeder int32_t Result = 0; 226d17e51f3STimm Baeder uint64_t Steps = 0; 227d17e51f3STimm Baeder for (;; ++IndexA, ++IndexB, ++Steps) { 228d17e51f3STimm Baeder 229d17e51f3STimm Baeder if (Steps >= Limit) 230d17e51f3STimm Baeder break; 231a07aba5dSTimm Baeder const Pointer &PA = A.atIndex(IndexA); 232a07aba5dSTimm Baeder const Pointer &PB = B.atIndex(IndexB); 233a07aba5dSTimm Baeder if (!CheckRange(S, OpPC, PA, AK_Read) || 234a07aba5dSTimm Baeder !CheckRange(S, OpPC, PB, AK_Read)) { 235a07aba5dSTimm Baeder return false; 236a07aba5dSTimm Baeder } 237a07aba5dSTimm Baeder uint8_t CA = PA.deref<uint8_t>(); 238a07aba5dSTimm Baeder uint8_t CB = PB.deref<uint8_t>(); 239a07aba5dSTimm Baeder 240a07aba5dSTimm Baeder if (CA > CB) { 241a07aba5dSTimm Baeder Result = 1; 242a07aba5dSTimm Baeder break; 243a07aba5dSTimm Baeder } else if (CA < CB) { 244a07aba5dSTimm Baeder Result = -1; 245a07aba5dSTimm Baeder break; 246a07aba5dSTimm Baeder } 247a07aba5dSTimm Baeder if (CA == 0 || CB == 0) 248a07aba5dSTimm Baeder break; 249a07aba5dSTimm Baeder } 250a07aba5dSTimm Baeder 251a07aba5dSTimm Baeder pushInteger(S, Result, Call->getType()); 252a07aba5dSTimm Baeder return true; 253a07aba5dSTimm Baeder } 254a07aba5dSTimm Baeder 255a07aba5dSTimm Baeder static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, 256a07aba5dSTimm Baeder const InterpFrame *Frame, 257dac9736dSTimm Baeder const Function *Func, const CallExpr *Call) { 258dac9736dSTimm Baeder unsigned ID = Func->getBuiltinID(); 259a07aba5dSTimm Baeder const Pointer &StrPtr = getParam<Pointer>(Frame, 0); 260a07aba5dSTimm Baeder 26100b50c91STimm Baeder if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen) 262dac9736dSTimm Baeder diagnoseNonConstexprBuiltin(S, OpPC, ID); 263dac9736dSTimm Baeder 264a07aba5dSTimm Baeder if (!CheckArray(S, OpPC, StrPtr)) 265a07aba5dSTimm Baeder return false; 266a07aba5dSTimm Baeder 267a07aba5dSTimm Baeder if (!CheckLive(S, OpPC, StrPtr, AK_Read)) 268a07aba5dSTimm Baeder return false; 269a07aba5dSTimm Baeder 270a07aba5dSTimm Baeder if (!CheckDummy(S, OpPC, StrPtr, AK_Read)) 271a07aba5dSTimm Baeder return false; 272a07aba5dSTimm Baeder 273a07aba5dSTimm Baeder assert(StrPtr.getFieldDesc()->isPrimitiveArray()); 27400b50c91STimm Baeder unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize(); 27500b50c91STimm Baeder 27600b50c91STimm Baeder if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) { 2774f08fa1aSJie Fu [[maybe_unused]] const ASTContext &AC = S.getASTContext(); 27800b50c91STimm Baeder assert(ElemSize == AC.getTypeSizeInChars(AC.getWCharType()).getQuantity()); 27900b50c91STimm Baeder } 280a07aba5dSTimm Baeder 281a07aba5dSTimm Baeder size_t Len = 0; 282a07aba5dSTimm Baeder for (size_t I = StrPtr.getIndex();; ++I, ++Len) { 283a07aba5dSTimm Baeder const Pointer &ElemPtr = StrPtr.atIndex(I); 284a07aba5dSTimm Baeder 285a07aba5dSTimm Baeder if (!CheckRange(S, OpPC, ElemPtr, AK_Read)) 286a07aba5dSTimm Baeder return false; 287a07aba5dSTimm Baeder 28800b50c91STimm Baeder uint32_t Val; 28900b50c91STimm Baeder switch (ElemSize) { 29000b50c91STimm Baeder case 1: 29100b50c91STimm Baeder Val = ElemPtr.deref<uint8_t>(); 29200b50c91STimm Baeder break; 29300b50c91STimm Baeder case 2: 29400b50c91STimm Baeder Val = ElemPtr.deref<uint16_t>(); 29500b50c91STimm Baeder break; 29600b50c91STimm Baeder case 4: 29700b50c91STimm Baeder Val = ElemPtr.deref<uint32_t>(); 29800b50c91STimm Baeder break; 29900b50c91STimm Baeder default: 30000b50c91STimm Baeder llvm_unreachable("Unsupported char size"); 30100b50c91STimm Baeder } 302a07aba5dSTimm Baeder if (Val == 0) 303a07aba5dSTimm Baeder break; 304a07aba5dSTimm Baeder } 305a07aba5dSTimm Baeder 306a07aba5dSTimm Baeder pushInteger(S, Len, Call->getType()); 307a07aba5dSTimm Baeder 308a07aba5dSTimm Baeder return true; 309a07aba5dSTimm Baeder } 310a07aba5dSTimm Baeder 311a07aba5dSTimm Baeder static bool interp__builtin_nan(InterpState &S, CodePtr OpPC, 312a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *F, 313a07aba5dSTimm Baeder bool Signaling) { 314a07aba5dSTimm Baeder const Pointer &Arg = getParam<Pointer>(Frame, 0); 315a07aba5dSTimm Baeder 316a07aba5dSTimm Baeder if (!CheckLoad(S, OpPC, Arg)) 317a07aba5dSTimm Baeder return false; 318a07aba5dSTimm Baeder 319a07aba5dSTimm Baeder assert(Arg.getFieldDesc()->isPrimitiveArray()); 320a07aba5dSTimm Baeder 321a07aba5dSTimm Baeder // Convert the given string to an integer using StringRef's API. 322a07aba5dSTimm Baeder llvm::APInt Fill; 323a07aba5dSTimm Baeder std::string Str; 324a07aba5dSTimm Baeder assert(Arg.getNumElems() >= 1); 325a07aba5dSTimm Baeder for (unsigned I = 0;; ++I) { 326a07aba5dSTimm Baeder const Pointer &Elem = Arg.atIndex(I); 327a07aba5dSTimm Baeder 328a07aba5dSTimm Baeder if (!CheckLoad(S, OpPC, Elem)) 329a07aba5dSTimm Baeder return false; 330a07aba5dSTimm Baeder 331a07aba5dSTimm Baeder if (Elem.deref<int8_t>() == 0) 332a07aba5dSTimm Baeder break; 333a07aba5dSTimm Baeder 334a07aba5dSTimm Baeder Str += Elem.deref<char>(); 335a07aba5dSTimm Baeder } 336a07aba5dSTimm Baeder 337a07aba5dSTimm Baeder // Treat empty strings as if they were zero. 338a07aba5dSTimm Baeder if (Str.empty()) 339a07aba5dSTimm Baeder Fill = llvm::APInt(32, 0); 340a07aba5dSTimm Baeder else if (StringRef(Str).getAsInteger(0, Fill)) 341a07aba5dSTimm Baeder return false; 342a07aba5dSTimm Baeder 343a07aba5dSTimm Baeder const llvm::fltSemantics &TargetSemantics = 344d9e72860Syronglin S.getASTContext().getFloatTypeSemantics(F->getDecl()->getReturnType()); 345a07aba5dSTimm Baeder 346a07aba5dSTimm Baeder Floating Result; 347d9e72860Syronglin if (S.getASTContext().getTargetInfo().isNan2008()) { 348a07aba5dSTimm Baeder if (Signaling) 349a07aba5dSTimm Baeder Result = Floating( 350a07aba5dSTimm Baeder llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill)); 351a07aba5dSTimm Baeder else 352a07aba5dSTimm Baeder Result = Floating( 353a07aba5dSTimm Baeder llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill)); 354a07aba5dSTimm Baeder } else { 355a07aba5dSTimm Baeder // Prior to IEEE 754-2008, architectures were allowed to choose whether 356a07aba5dSTimm Baeder // the first bit of their significand was set for qNaN or sNaN. MIPS chose 357a07aba5dSTimm Baeder // a different encoding to what became a standard in 2008, and for pre- 358a07aba5dSTimm Baeder // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as 359a07aba5dSTimm Baeder // sNaN. This is now known as "legacy NaN" encoding. 360a07aba5dSTimm Baeder if (Signaling) 361a07aba5dSTimm Baeder Result = Floating( 362a07aba5dSTimm Baeder llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill)); 363a07aba5dSTimm Baeder else 364a07aba5dSTimm Baeder Result = Floating( 365a07aba5dSTimm Baeder llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill)); 366a07aba5dSTimm Baeder } 367a07aba5dSTimm Baeder 368a07aba5dSTimm Baeder S.Stk.push<Floating>(Result); 369a07aba5dSTimm Baeder return true; 370a07aba5dSTimm Baeder } 371a07aba5dSTimm Baeder 372a07aba5dSTimm Baeder static bool interp__builtin_inf(InterpState &S, CodePtr OpPC, 373a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *F) { 374a07aba5dSTimm Baeder const llvm::fltSemantics &TargetSemantics = 375d9e72860Syronglin S.getASTContext().getFloatTypeSemantics(F->getDecl()->getReturnType()); 376a07aba5dSTimm Baeder 377a07aba5dSTimm Baeder S.Stk.push<Floating>(Floating::getInf(TargetSemantics)); 378a07aba5dSTimm Baeder return true; 379a07aba5dSTimm Baeder } 380a07aba5dSTimm Baeder 381a07aba5dSTimm Baeder static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC, 382a07aba5dSTimm Baeder const InterpFrame *Frame, 383a07aba5dSTimm Baeder const Function *F) { 384a07aba5dSTimm Baeder const Floating &Arg1 = getParam<Floating>(Frame, 0); 385a07aba5dSTimm Baeder const Floating &Arg2 = getParam<Floating>(Frame, 1); 386a07aba5dSTimm Baeder 387a07aba5dSTimm Baeder APFloat Copy = Arg1.getAPFloat(); 388a07aba5dSTimm Baeder Copy.copySign(Arg2.getAPFloat()); 389a07aba5dSTimm Baeder S.Stk.push<Floating>(Floating(Copy)); 390a07aba5dSTimm Baeder 391a07aba5dSTimm Baeder return true; 392a07aba5dSTimm Baeder } 393a07aba5dSTimm Baeder 394a07aba5dSTimm Baeder static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC, 395790d9869STimm Baeder const InterpFrame *Frame, const Function *F, 396790d9869STimm Baeder bool IsNumBuiltin) { 397a07aba5dSTimm Baeder const Floating &LHS = getParam<Floating>(Frame, 0); 398a07aba5dSTimm Baeder const Floating &RHS = getParam<Floating>(Frame, 1); 399a07aba5dSTimm Baeder 400a07aba5dSTimm Baeder Floating Result; 401a07aba5dSTimm Baeder 402790d9869STimm Baeder if (IsNumBuiltin) { 403790d9869STimm Baeder Result = llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()); 404790d9869STimm Baeder } else { 405a07aba5dSTimm Baeder // When comparing zeroes, return -0.0 if one of the zeroes is negative. 406a07aba5dSTimm Baeder if (LHS.isZero() && RHS.isZero() && RHS.isNegative()) 407a07aba5dSTimm Baeder Result = RHS; 408a07aba5dSTimm Baeder else if (LHS.isNan() || RHS < LHS) 409a07aba5dSTimm Baeder Result = RHS; 410a07aba5dSTimm Baeder else 411a07aba5dSTimm Baeder Result = LHS; 412790d9869STimm Baeder } 413a07aba5dSTimm Baeder 414a07aba5dSTimm Baeder S.Stk.push<Floating>(Result); 415a07aba5dSTimm Baeder return true; 416a07aba5dSTimm Baeder } 417a07aba5dSTimm Baeder 418a07aba5dSTimm Baeder static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC, 419790d9869STimm Baeder const InterpFrame *Frame, const Function *Func, 420790d9869STimm Baeder bool IsNumBuiltin) { 421a07aba5dSTimm Baeder const Floating &LHS = getParam<Floating>(Frame, 0); 422a07aba5dSTimm Baeder const Floating &RHS = getParam<Floating>(Frame, 1); 423a07aba5dSTimm Baeder 424a07aba5dSTimm Baeder Floating Result; 425a07aba5dSTimm Baeder 426790d9869STimm Baeder if (IsNumBuiltin) { 427790d9869STimm Baeder Result = llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()); 428790d9869STimm Baeder } else { 429a07aba5dSTimm Baeder // When comparing zeroes, return +0.0 if one of the zeroes is positive. 430a07aba5dSTimm Baeder if (LHS.isZero() && RHS.isZero() && LHS.isNegative()) 431a07aba5dSTimm Baeder Result = RHS; 432a07aba5dSTimm Baeder else if (LHS.isNan() || RHS > LHS) 433a07aba5dSTimm Baeder Result = RHS; 434a07aba5dSTimm Baeder else 435a07aba5dSTimm Baeder Result = LHS; 436790d9869STimm Baeder } 437a07aba5dSTimm Baeder 438a07aba5dSTimm Baeder S.Stk.push<Floating>(Result); 439a07aba5dSTimm Baeder return true; 440a07aba5dSTimm Baeder } 441a07aba5dSTimm Baeder 442a07aba5dSTimm Baeder /// Defined as __builtin_isnan(...), to accommodate the fact that it can 443a07aba5dSTimm Baeder /// take a float, double, long double, etc. 444a07aba5dSTimm Baeder /// But for us, that's all a Floating anyway. 445a07aba5dSTimm Baeder static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC, 446a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *F, 447a07aba5dSTimm Baeder const CallExpr *Call) { 448a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 449a07aba5dSTimm Baeder 450a07aba5dSTimm Baeder pushInteger(S, Arg.isNan(), Call->getType()); 451a07aba5dSTimm Baeder return true; 452a07aba5dSTimm Baeder } 453a07aba5dSTimm Baeder 454a07aba5dSTimm Baeder static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC, 455a07aba5dSTimm Baeder const InterpFrame *Frame, 456a07aba5dSTimm Baeder const Function *F, 457a07aba5dSTimm Baeder const CallExpr *Call) { 458a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 459a07aba5dSTimm Baeder 460a07aba5dSTimm Baeder pushInteger(S, Arg.isSignaling(), Call->getType()); 461a07aba5dSTimm Baeder return true; 462a07aba5dSTimm Baeder } 463a07aba5dSTimm Baeder 464a07aba5dSTimm Baeder static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC, 465a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *F, 466a07aba5dSTimm Baeder bool CheckSign, const CallExpr *Call) { 467a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 468a07aba5dSTimm Baeder bool IsInf = Arg.isInf(); 469a07aba5dSTimm Baeder 470a07aba5dSTimm Baeder if (CheckSign) 471a07aba5dSTimm Baeder pushInteger(S, IsInf ? (Arg.isNegative() ? -1 : 1) : 0, Call->getType()); 472a07aba5dSTimm Baeder else 473a07aba5dSTimm Baeder pushInteger(S, Arg.isInf(), Call->getType()); 474a07aba5dSTimm Baeder return true; 475a07aba5dSTimm Baeder } 476a07aba5dSTimm Baeder 477a07aba5dSTimm Baeder static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC, 478a07aba5dSTimm Baeder const InterpFrame *Frame, 479a07aba5dSTimm Baeder const Function *F, const CallExpr *Call) { 480a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 481a07aba5dSTimm Baeder 482a07aba5dSTimm Baeder pushInteger(S, Arg.isFinite(), Call->getType()); 483a07aba5dSTimm Baeder return true; 484a07aba5dSTimm Baeder } 485a07aba5dSTimm Baeder 486a07aba5dSTimm Baeder static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC, 487a07aba5dSTimm Baeder const InterpFrame *Frame, 488a07aba5dSTimm Baeder const Function *F, const CallExpr *Call) { 489a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 490a07aba5dSTimm Baeder 491a07aba5dSTimm Baeder pushInteger(S, Arg.isNormal(), Call->getType()); 492a07aba5dSTimm Baeder return true; 493a07aba5dSTimm Baeder } 494a07aba5dSTimm Baeder 495a07aba5dSTimm Baeder static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC, 496a07aba5dSTimm Baeder const InterpFrame *Frame, 497a07aba5dSTimm Baeder const Function *F, 498a07aba5dSTimm Baeder const CallExpr *Call) { 499a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 500a07aba5dSTimm Baeder 501a07aba5dSTimm Baeder pushInteger(S, Arg.isDenormal(), Call->getType()); 502a07aba5dSTimm Baeder return true; 503a07aba5dSTimm Baeder } 504a07aba5dSTimm Baeder 505a07aba5dSTimm Baeder static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC, 506a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *F, 507a07aba5dSTimm Baeder const CallExpr *Call) { 508a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 509a07aba5dSTimm Baeder 510a07aba5dSTimm Baeder pushInteger(S, Arg.isZero(), Call->getType()); 511a07aba5dSTimm Baeder return true; 512a07aba5dSTimm Baeder } 513a07aba5dSTimm Baeder 51411259343SMital Ashok static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC, 51511259343SMital Ashok const InterpFrame *Frame, const Function *F, 51611259343SMital Ashok const CallExpr *Call) { 51711259343SMital Ashok const Floating &Arg = S.Stk.peek<Floating>(); 51811259343SMital Ashok 51911259343SMital Ashok pushInteger(S, Arg.isNegative(), Call->getType()); 52011259343SMital Ashok return true; 52111259343SMital Ashok } 52211259343SMital Ashok 52311259343SMital Ashok static bool interp_floating_comparison(InterpState &S, CodePtr OpPC, 52411259343SMital Ashok const InterpFrame *Frame, 52511259343SMital Ashok const Function *F, 52611259343SMital Ashok const CallExpr *Call) { 52711259343SMital Ashok const Floating &RHS = S.Stk.peek<Floating>(); 52811259343SMital Ashok const Floating &LHS = S.Stk.peek<Floating>(align(2u * primSize(PT_Float))); 52911259343SMital Ashok unsigned ID = F->getBuiltinID(); 53011259343SMital Ashok 53111259343SMital Ashok pushInteger( 53211259343SMital Ashok S, 53311259343SMital Ashok [&] { 53411259343SMital Ashok switch (ID) { 53511259343SMital Ashok case Builtin::BI__builtin_isgreater: 53611259343SMital Ashok return LHS > RHS; 53711259343SMital Ashok case Builtin::BI__builtin_isgreaterequal: 53811259343SMital Ashok return LHS >= RHS; 53911259343SMital Ashok case Builtin::BI__builtin_isless: 54011259343SMital Ashok return LHS < RHS; 54111259343SMital Ashok case Builtin::BI__builtin_islessequal: 54211259343SMital Ashok return LHS <= RHS; 54311259343SMital Ashok case Builtin::BI__builtin_islessgreater: { 54411259343SMital Ashok ComparisonCategoryResult cmp = LHS.compare(RHS); 54511259343SMital Ashok return cmp == ComparisonCategoryResult::Less || 54611259343SMital Ashok cmp == ComparisonCategoryResult::Greater; 54711259343SMital Ashok } 54811259343SMital Ashok case Builtin::BI__builtin_isunordered: 54911259343SMital Ashok return LHS.compare(RHS) == ComparisonCategoryResult::Unordered; 55011259343SMital Ashok default: 55111259343SMital Ashok llvm_unreachable("Unexpected builtin ID: Should be a floating point " 55211259343SMital Ashok "comparison function"); 55311259343SMital Ashok } 55411259343SMital Ashok }(), 55511259343SMital Ashok Call->getType()); 55611259343SMital Ashok return true; 55711259343SMital Ashok } 55811259343SMital Ashok 559a07aba5dSTimm Baeder /// First parameter to __builtin_isfpclass is the floating value, the 560a07aba5dSTimm Baeder /// second one is an integral value. 561a07aba5dSTimm Baeder static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC, 562a07aba5dSTimm Baeder const InterpFrame *Frame, 563a07aba5dSTimm Baeder const Function *Func, 564a07aba5dSTimm Baeder const CallExpr *Call) { 565a07aba5dSTimm Baeder PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType()); 566a07aba5dSTimm Baeder APSInt FPClassArg = peekToAPSInt(S.Stk, FPClassArgT); 567a07aba5dSTimm Baeder const Floating &F = 568a07aba5dSTimm Baeder S.Stk.peek<Floating>(align(primSize(FPClassArgT) + primSize(PT_Float))); 569a07aba5dSTimm Baeder 570a07aba5dSTimm Baeder int32_t Result = 571a07aba5dSTimm Baeder static_cast<int32_t>((F.classify() & FPClassArg).getZExtValue()); 572a07aba5dSTimm Baeder pushInteger(S, Result, Call->getType()); 573a07aba5dSTimm Baeder 574a07aba5dSTimm Baeder return true; 575a07aba5dSTimm Baeder } 576a07aba5dSTimm Baeder 577a07aba5dSTimm Baeder /// Five int values followed by one floating value. 578a07aba5dSTimm Baeder static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC, 579a07aba5dSTimm Baeder const InterpFrame *Frame, 580a07aba5dSTimm Baeder const Function *Func, 581a07aba5dSTimm Baeder const CallExpr *Call) { 582a07aba5dSTimm Baeder const Floating &Val = S.Stk.peek<Floating>(); 583a07aba5dSTimm Baeder 584a07aba5dSTimm Baeder unsigned Index; 585a07aba5dSTimm Baeder switch (Val.getCategory()) { 586a07aba5dSTimm Baeder case APFloat::fcNaN: 587a07aba5dSTimm Baeder Index = 0; 588a07aba5dSTimm Baeder break; 589a07aba5dSTimm Baeder case APFloat::fcInfinity: 590a07aba5dSTimm Baeder Index = 1; 591a07aba5dSTimm Baeder break; 592a07aba5dSTimm Baeder case APFloat::fcNormal: 593a07aba5dSTimm Baeder Index = Val.isDenormal() ? 3 : 2; 594a07aba5dSTimm Baeder break; 595a07aba5dSTimm Baeder case APFloat::fcZero: 596a07aba5dSTimm Baeder Index = 4; 597a07aba5dSTimm Baeder break; 598a07aba5dSTimm Baeder } 599a07aba5dSTimm Baeder 600a07aba5dSTimm Baeder // The last argument is first on the stack. 601a07aba5dSTimm Baeder assert(Index <= 4); 602a07aba5dSTimm Baeder unsigned IntSize = primSize(getIntPrimType(S)); 603a07aba5dSTimm Baeder unsigned Offset = 604a07aba5dSTimm Baeder align(primSize(PT_Float)) + ((1 + (4 - Index)) * align(IntSize)); 605a07aba5dSTimm Baeder 606a07aba5dSTimm Baeder APSInt I = peekToAPSInt(S.Stk, getIntPrimType(S), Offset); 607a07aba5dSTimm Baeder pushInteger(S, I, Call->getType()); 608a07aba5dSTimm Baeder return true; 609a07aba5dSTimm Baeder } 610a07aba5dSTimm Baeder 611a07aba5dSTimm Baeder // The C standard says "fabs raises no floating-point exceptions, 612a07aba5dSTimm Baeder // even if x is a signaling NaN. The returned value is independent of 613a07aba5dSTimm Baeder // the current rounding direction mode." Therefore constant folding can 614a07aba5dSTimm Baeder // proceed without regard to the floating point settings. 615a07aba5dSTimm Baeder // Reference, WG14 N2478 F.10.4.3 616a07aba5dSTimm Baeder static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC, 617a07aba5dSTimm Baeder const InterpFrame *Frame, 618a07aba5dSTimm Baeder const Function *Func) { 619a07aba5dSTimm Baeder const Floating &Val = getParam<Floating>(Frame, 0); 620a07aba5dSTimm Baeder 621a07aba5dSTimm Baeder S.Stk.push<Floating>(Floating::abs(Val)); 622a07aba5dSTimm Baeder return true; 623a07aba5dSTimm Baeder } 624a07aba5dSTimm Baeder 625332ac18eSc8ef static bool interp__builtin_abs(InterpState &S, CodePtr OpPC, 626332ac18eSc8ef const InterpFrame *Frame, const Function *Func, 627332ac18eSc8ef const CallExpr *Call) { 628332ac18eSc8ef PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 629332ac18eSc8ef APSInt Val = peekToAPSInt(S.Stk, ArgT); 630332ac18eSc8ef if (Val == 631332ac18eSc8ef APSInt(APInt::getSignedMinValue(Val.getBitWidth()), /*IsUnsigned=*/false)) 632332ac18eSc8ef return false; 633332ac18eSc8ef if (Val.isNegative()) 634332ac18eSc8ef Val.negate(); 635332ac18eSc8ef pushInteger(S, Val, Call->getType()); 636332ac18eSc8ef return true; 637332ac18eSc8ef } 638332ac18eSc8ef 639a07aba5dSTimm Baeder static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC, 640a07aba5dSTimm Baeder const InterpFrame *Frame, 641a07aba5dSTimm Baeder const Function *Func, 642a07aba5dSTimm Baeder const CallExpr *Call) { 643a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 644a07aba5dSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, ArgT); 645a07aba5dSTimm Baeder pushInteger(S, Val.popcount(), Call->getType()); 646a07aba5dSTimm Baeder return true; 647a07aba5dSTimm Baeder } 648a07aba5dSTimm Baeder 649a07aba5dSTimm Baeder static bool interp__builtin_parity(InterpState &S, CodePtr OpPC, 650a07aba5dSTimm Baeder const InterpFrame *Frame, 651a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call) { 652a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 653a07aba5dSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, ArgT); 654a07aba5dSTimm Baeder pushInteger(S, Val.popcount() % 2, Call->getType()); 655a07aba5dSTimm Baeder return true; 656a07aba5dSTimm Baeder } 657a07aba5dSTimm Baeder 658a07aba5dSTimm Baeder static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC, 659a07aba5dSTimm Baeder const InterpFrame *Frame, 660a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call) { 661a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 662a07aba5dSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, ArgT); 663a07aba5dSTimm Baeder pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType()); 664a07aba5dSTimm Baeder return true; 665a07aba5dSTimm Baeder } 666a07aba5dSTimm Baeder 667a07aba5dSTimm Baeder static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC, 668a07aba5dSTimm Baeder const InterpFrame *Frame, 669a07aba5dSTimm Baeder const Function *Func, 670a07aba5dSTimm Baeder const CallExpr *Call) { 671a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 672a07aba5dSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, ArgT); 673a07aba5dSTimm Baeder pushInteger(S, Val.reverseBits(), Call->getType()); 674a07aba5dSTimm Baeder return true; 675a07aba5dSTimm Baeder } 676a07aba5dSTimm Baeder 677a07aba5dSTimm Baeder static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC, 678a07aba5dSTimm Baeder const InterpFrame *Frame, 679a07aba5dSTimm Baeder const Function *Func, 680a07aba5dSTimm Baeder const CallExpr *Call) { 681a07aba5dSTimm Baeder // This is an unevaluated call, so there are no arguments on the stack. 682a07aba5dSTimm Baeder assert(Call->getNumArgs() == 1); 683a07aba5dSTimm Baeder const Expr *Arg = Call->getArg(0); 684a07aba5dSTimm Baeder 685a07aba5dSTimm Baeder GCCTypeClass ResultClass = 686a07aba5dSTimm Baeder EvaluateBuiltinClassifyType(Arg->getType(), S.getLangOpts()); 687a07aba5dSTimm Baeder int32_t ReturnVal = static_cast<int32_t>(ResultClass); 688a07aba5dSTimm Baeder pushInteger(S, ReturnVal, Call->getType()); 689a07aba5dSTimm Baeder return true; 690a07aba5dSTimm Baeder } 691a07aba5dSTimm Baeder 692a07aba5dSTimm Baeder // __builtin_expect(long, long) 693a07aba5dSTimm Baeder // __builtin_expect_with_probability(long, long, double) 694a07aba5dSTimm Baeder static bool interp__builtin_expect(InterpState &S, CodePtr OpPC, 695a07aba5dSTimm Baeder const InterpFrame *Frame, 696a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call) { 697a07aba5dSTimm Baeder // The return value is simply the value of the first parameter. 698a07aba5dSTimm Baeder // We ignore the probability. 699a07aba5dSTimm Baeder unsigned NumArgs = Call->getNumArgs(); 700a07aba5dSTimm Baeder assert(NumArgs == 2 || NumArgs == 3); 701a07aba5dSTimm Baeder 702a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 703a07aba5dSTimm Baeder unsigned Offset = align(primSize(getLongPrimType(S))) * 2; 704a07aba5dSTimm Baeder if (NumArgs == 3) 705a07aba5dSTimm Baeder Offset += align(primSize(PT_Float)); 706a07aba5dSTimm Baeder 707a07aba5dSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, ArgT, Offset); 708a07aba5dSTimm Baeder pushInteger(S, Val, Call->getType()); 709a07aba5dSTimm Baeder return true; 710a07aba5dSTimm Baeder } 711a07aba5dSTimm Baeder 712a07aba5dSTimm Baeder /// rotateleft(value, amount) 713a07aba5dSTimm Baeder static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC, 714a07aba5dSTimm Baeder const InterpFrame *Frame, 715a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call, 716a07aba5dSTimm Baeder bool Right) { 717a07aba5dSTimm Baeder PrimType AmountT = *S.getContext().classify(Call->getArg(1)->getType()); 718a07aba5dSTimm Baeder PrimType ValueT = *S.getContext().classify(Call->getArg(0)->getType()); 719a07aba5dSTimm Baeder 720a07aba5dSTimm Baeder APSInt Amount = peekToAPSInt(S.Stk, AmountT); 721a07aba5dSTimm Baeder APSInt Value = peekToAPSInt( 722a07aba5dSTimm Baeder S.Stk, ValueT, align(primSize(AmountT)) + align(primSize(ValueT))); 723a07aba5dSTimm Baeder 724a07aba5dSTimm Baeder APSInt Result; 725a07aba5dSTimm Baeder if (Right) 726a07aba5dSTimm Baeder Result = APSInt(Value.rotr(Amount.urem(Value.getBitWidth())), 727a07aba5dSTimm Baeder /*IsUnsigned=*/true); 728a07aba5dSTimm Baeder else // Left. 729a07aba5dSTimm Baeder Result = APSInt(Value.rotl(Amount.urem(Value.getBitWidth())), 730a07aba5dSTimm Baeder /*IsUnsigned=*/true); 731a07aba5dSTimm Baeder 732a07aba5dSTimm Baeder pushInteger(S, Result, Call->getType()); 733a07aba5dSTimm Baeder return true; 734a07aba5dSTimm Baeder } 735a07aba5dSTimm Baeder 736a07aba5dSTimm Baeder static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC, 737a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *Func, 738a07aba5dSTimm Baeder const CallExpr *Call) { 739a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 740a07aba5dSTimm Baeder APSInt Value = peekToAPSInt(S.Stk, ArgT); 741a07aba5dSTimm Baeder 742a07aba5dSTimm Baeder uint64_t N = Value.countr_zero(); 743a07aba5dSTimm Baeder pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType()); 744a07aba5dSTimm Baeder return true; 745a07aba5dSTimm Baeder } 746a07aba5dSTimm Baeder 747a07aba5dSTimm Baeder static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC, 748a07aba5dSTimm Baeder const InterpFrame *Frame, 749a07aba5dSTimm Baeder const Function *Func, 750a07aba5dSTimm Baeder const CallExpr *Call) { 751a07aba5dSTimm Baeder assert(Call->getArg(0)->isLValue()); 752a07aba5dSTimm Baeder PrimType PtrT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr); 753a07aba5dSTimm Baeder 754a07aba5dSTimm Baeder if (PtrT == PT_FnPtr) { 755a07aba5dSTimm Baeder const FunctionPointer &Arg = S.Stk.peek<FunctionPointer>(); 756a07aba5dSTimm Baeder S.Stk.push<FunctionPointer>(Arg); 757a07aba5dSTimm Baeder } else if (PtrT == PT_Ptr) { 758a07aba5dSTimm Baeder const Pointer &Arg = S.Stk.peek<Pointer>(); 759a07aba5dSTimm Baeder S.Stk.push<Pointer>(Arg); 760a07aba5dSTimm Baeder } else { 761a07aba5dSTimm Baeder assert(false && "Unsupported pointer type passed to __builtin_addressof()"); 762a07aba5dSTimm Baeder } 763a07aba5dSTimm Baeder return true; 764a07aba5dSTimm Baeder } 765a07aba5dSTimm Baeder 766a07aba5dSTimm Baeder static bool interp__builtin_move(InterpState &S, CodePtr OpPC, 767a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *Func, 768a07aba5dSTimm Baeder const CallExpr *Call) { 769a07aba5dSTimm Baeder 770a07aba5dSTimm Baeder PrimType ArgT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr); 771a07aba5dSTimm Baeder 772a07aba5dSTimm Baeder TYPE_SWITCH(ArgT, const T &Arg = S.Stk.peek<T>(); S.Stk.push<T>(Arg);); 773a07aba5dSTimm Baeder 774a07aba5dSTimm Baeder return Func->getDecl()->isConstexpr(); 775a07aba5dSTimm Baeder } 776a07aba5dSTimm Baeder 777a07aba5dSTimm Baeder static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC, 778a07aba5dSTimm Baeder const InterpFrame *Frame, 779a07aba5dSTimm Baeder const Function *Func, 780a07aba5dSTimm Baeder const CallExpr *Call) { 781a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 782a07aba5dSTimm Baeder APSInt Arg = peekToAPSInt(S.Stk, ArgT); 783a07aba5dSTimm Baeder 784d9e72860Syronglin int Result = S.getASTContext().getTargetInfo().getEHDataRegisterNumber( 785d9e72860Syronglin Arg.getZExtValue()); 786a07aba5dSTimm Baeder pushInteger(S, Result, Call->getType()); 787a07aba5dSTimm Baeder return true; 788a07aba5dSTimm Baeder } 789a07aba5dSTimm Baeder 790a07aba5dSTimm Baeder /// Just takes the first Argument to the call and puts it on the stack. 791a07aba5dSTimm Baeder static bool noopPointer(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, 792a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call) { 793a07aba5dSTimm Baeder const Pointer &Arg = S.Stk.peek<Pointer>(); 794a07aba5dSTimm Baeder S.Stk.push<Pointer>(Arg); 795a07aba5dSTimm Baeder return true; 796a07aba5dSTimm Baeder } 797a07aba5dSTimm Baeder 798a07aba5dSTimm Baeder // Two integral values followed by a pointer (lhs, rhs, resultOut) 799a07aba5dSTimm Baeder static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC, 800a07aba5dSTimm Baeder const InterpFrame *Frame, 801a07aba5dSTimm Baeder const Function *Func, 802a07aba5dSTimm Baeder const CallExpr *Call) { 803a07aba5dSTimm Baeder Pointer &ResultPtr = S.Stk.peek<Pointer>(); 804a07aba5dSTimm Baeder if (ResultPtr.isDummy()) 805a07aba5dSTimm Baeder return false; 806a07aba5dSTimm Baeder 807a07aba5dSTimm Baeder unsigned BuiltinOp = Func->getBuiltinID(); 808a07aba5dSTimm Baeder PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType()); 809a07aba5dSTimm Baeder PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType()); 810a07aba5dSTimm Baeder APSInt RHS = peekToAPSInt(S.Stk, RHST, 811a07aba5dSTimm Baeder align(primSize(PT_Ptr)) + align(primSize(RHST))); 812a07aba5dSTimm Baeder APSInt LHS = peekToAPSInt(S.Stk, LHST, 813a07aba5dSTimm Baeder align(primSize(PT_Ptr)) + align(primSize(RHST)) + 814a07aba5dSTimm Baeder align(primSize(LHST))); 815a07aba5dSTimm Baeder QualType ResultType = Call->getArg(2)->getType()->getPointeeType(); 816a07aba5dSTimm Baeder PrimType ResultT = *S.getContext().classify(ResultType); 817a07aba5dSTimm Baeder bool Overflow; 818a07aba5dSTimm Baeder 819a07aba5dSTimm Baeder APSInt Result; 820a07aba5dSTimm Baeder if (BuiltinOp == Builtin::BI__builtin_add_overflow || 821a07aba5dSTimm Baeder BuiltinOp == Builtin::BI__builtin_sub_overflow || 822a07aba5dSTimm Baeder BuiltinOp == Builtin::BI__builtin_mul_overflow) { 823a07aba5dSTimm Baeder bool IsSigned = LHS.isSigned() || RHS.isSigned() || 824a07aba5dSTimm Baeder ResultType->isSignedIntegerOrEnumerationType(); 825a07aba5dSTimm Baeder bool AllSigned = LHS.isSigned() && RHS.isSigned() && 826a07aba5dSTimm Baeder ResultType->isSignedIntegerOrEnumerationType(); 827a07aba5dSTimm Baeder uint64_t LHSSize = LHS.getBitWidth(); 828a07aba5dSTimm Baeder uint64_t RHSSize = RHS.getBitWidth(); 829d9e72860Syronglin uint64_t ResultSize = S.getASTContext().getTypeSize(ResultType); 830a07aba5dSTimm Baeder uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize); 831a07aba5dSTimm Baeder 832a07aba5dSTimm Baeder // Add an additional bit if the signedness isn't uniformly agreed to. We 833a07aba5dSTimm Baeder // could do this ONLY if there is a signed and an unsigned that both have 834a07aba5dSTimm Baeder // MaxBits, but the code to check that is pretty nasty. The issue will be 835a07aba5dSTimm Baeder // caught in the shrink-to-result later anyway. 836a07aba5dSTimm Baeder if (IsSigned && !AllSigned) 837a07aba5dSTimm Baeder ++MaxBits; 838a07aba5dSTimm Baeder 839a07aba5dSTimm Baeder LHS = APSInt(LHS.extOrTrunc(MaxBits), !IsSigned); 840a07aba5dSTimm Baeder RHS = APSInt(RHS.extOrTrunc(MaxBits), !IsSigned); 841a07aba5dSTimm Baeder Result = APSInt(MaxBits, !IsSigned); 842a07aba5dSTimm Baeder } 843a07aba5dSTimm Baeder 844a07aba5dSTimm Baeder // Find largest int. 845a07aba5dSTimm Baeder switch (BuiltinOp) { 846a07aba5dSTimm Baeder default: 847a07aba5dSTimm Baeder llvm_unreachable("Invalid value for BuiltinOp"); 848a07aba5dSTimm Baeder case Builtin::BI__builtin_add_overflow: 849a07aba5dSTimm Baeder case Builtin::BI__builtin_sadd_overflow: 850a07aba5dSTimm Baeder case Builtin::BI__builtin_saddl_overflow: 851a07aba5dSTimm Baeder case Builtin::BI__builtin_saddll_overflow: 852a07aba5dSTimm Baeder case Builtin::BI__builtin_uadd_overflow: 853a07aba5dSTimm Baeder case Builtin::BI__builtin_uaddl_overflow: 854a07aba5dSTimm Baeder case Builtin::BI__builtin_uaddll_overflow: 855a07aba5dSTimm Baeder Result = LHS.isSigned() ? LHS.sadd_ov(RHS, Overflow) 856a07aba5dSTimm Baeder : LHS.uadd_ov(RHS, Overflow); 857a07aba5dSTimm Baeder break; 858a07aba5dSTimm Baeder case Builtin::BI__builtin_sub_overflow: 859a07aba5dSTimm Baeder case Builtin::BI__builtin_ssub_overflow: 860a07aba5dSTimm Baeder case Builtin::BI__builtin_ssubl_overflow: 861a07aba5dSTimm Baeder case Builtin::BI__builtin_ssubll_overflow: 862a07aba5dSTimm Baeder case Builtin::BI__builtin_usub_overflow: 863a07aba5dSTimm Baeder case Builtin::BI__builtin_usubl_overflow: 864a07aba5dSTimm Baeder case Builtin::BI__builtin_usubll_overflow: 865a07aba5dSTimm Baeder Result = LHS.isSigned() ? LHS.ssub_ov(RHS, Overflow) 866a07aba5dSTimm Baeder : LHS.usub_ov(RHS, Overflow); 867a07aba5dSTimm Baeder break; 868a07aba5dSTimm Baeder case Builtin::BI__builtin_mul_overflow: 869a07aba5dSTimm Baeder case Builtin::BI__builtin_smul_overflow: 870a07aba5dSTimm Baeder case Builtin::BI__builtin_smull_overflow: 871a07aba5dSTimm Baeder case Builtin::BI__builtin_smulll_overflow: 872a07aba5dSTimm Baeder case Builtin::BI__builtin_umul_overflow: 873a07aba5dSTimm Baeder case Builtin::BI__builtin_umull_overflow: 874a07aba5dSTimm Baeder case Builtin::BI__builtin_umulll_overflow: 875a07aba5dSTimm Baeder Result = LHS.isSigned() ? LHS.smul_ov(RHS, Overflow) 876a07aba5dSTimm Baeder : LHS.umul_ov(RHS, Overflow); 877a07aba5dSTimm Baeder break; 878a07aba5dSTimm Baeder } 879a07aba5dSTimm Baeder 880a07aba5dSTimm Baeder // In the case where multiple sizes are allowed, truncate and see if 881a07aba5dSTimm Baeder // the values are the same. 882a07aba5dSTimm Baeder if (BuiltinOp == Builtin::BI__builtin_add_overflow || 883a07aba5dSTimm Baeder BuiltinOp == Builtin::BI__builtin_sub_overflow || 884a07aba5dSTimm Baeder BuiltinOp == Builtin::BI__builtin_mul_overflow) { 885a07aba5dSTimm Baeder // APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead, 886a07aba5dSTimm Baeder // since it will give us the behavior of a TruncOrSelf in the case where 887a07aba5dSTimm Baeder // its parameter <= its size. We previously set Result to be at least the 888a07aba5dSTimm Baeder // type-size of the result, so getTypeSize(ResultType) <= Resu 889d9e72860Syronglin APSInt Temp = Result.extOrTrunc(S.getASTContext().getTypeSize(ResultType)); 890a07aba5dSTimm Baeder Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType()); 891a07aba5dSTimm Baeder 892a07aba5dSTimm Baeder if (!APSInt::isSameValue(Temp, Result)) 893a07aba5dSTimm Baeder Overflow = true; 894a07aba5dSTimm Baeder Result = Temp; 895a07aba5dSTimm Baeder } 896a07aba5dSTimm Baeder 897a07aba5dSTimm Baeder // Write Result to ResultPtr and put Overflow on the stacl. 898a07aba5dSTimm Baeder assignInteger(ResultPtr, ResultT, Result); 899a07aba5dSTimm Baeder ResultPtr.initialize(); 900a07aba5dSTimm Baeder assert(Func->getDecl()->getReturnType()->isBooleanType()); 901a07aba5dSTimm Baeder S.Stk.push<Boolean>(Overflow); 902a07aba5dSTimm Baeder return true; 903a07aba5dSTimm Baeder } 904a07aba5dSTimm Baeder 905a07aba5dSTimm Baeder /// Three integral values followed by a pointer (lhs, rhs, carry, carryOut). 906a07aba5dSTimm Baeder static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC, 907a07aba5dSTimm Baeder const InterpFrame *Frame, 908a07aba5dSTimm Baeder const Function *Func, 909a07aba5dSTimm Baeder const CallExpr *Call) { 910a07aba5dSTimm Baeder unsigned BuiltinOp = Func->getBuiltinID(); 911a07aba5dSTimm Baeder PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType()); 912a07aba5dSTimm Baeder PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType()); 913a07aba5dSTimm Baeder PrimType CarryT = *S.getContext().classify(Call->getArg(2)->getType()); 914a07aba5dSTimm Baeder APSInt RHS = peekToAPSInt(S.Stk, RHST, 915a07aba5dSTimm Baeder align(primSize(PT_Ptr)) + align(primSize(CarryT)) + 916a07aba5dSTimm Baeder align(primSize(RHST))); 917a07aba5dSTimm Baeder APSInt LHS = 918a07aba5dSTimm Baeder peekToAPSInt(S.Stk, LHST, 919a07aba5dSTimm Baeder align(primSize(PT_Ptr)) + align(primSize(RHST)) + 920a07aba5dSTimm Baeder align(primSize(CarryT)) + align(primSize(LHST))); 921a07aba5dSTimm Baeder APSInt CarryIn = peekToAPSInt( 922a07aba5dSTimm Baeder S.Stk, LHST, align(primSize(PT_Ptr)) + align(primSize(CarryT))); 923a07aba5dSTimm Baeder APSInt CarryOut; 924a07aba5dSTimm Baeder 925a07aba5dSTimm Baeder APSInt Result; 926a07aba5dSTimm Baeder // Copy the number of bits and sign. 927a07aba5dSTimm Baeder Result = LHS; 928a07aba5dSTimm Baeder CarryOut = LHS; 929a07aba5dSTimm Baeder 930a07aba5dSTimm Baeder bool FirstOverflowed = false; 931a07aba5dSTimm Baeder bool SecondOverflowed = false; 932a07aba5dSTimm Baeder switch (BuiltinOp) { 933a07aba5dSTimm Baeder default: 934a07aba5dSTimm Baeder llvm_unreachable("Invalid value for BuiltinOp"); 935a07aba5dSTimm Baeder case Builtin::BI__builtin_addcb: 936a07aba5dSTimm Baeder case Builtin::BI__builtin_addcs: 937a07aba5dSTimm Baeder case Builtin::BI__builtin_addc: 938a07aba5dSTimm Baeder case Builtin::BI__builtin_addcl: 939a07aba5dSTimm Baeder case Builtin::BI__builtin_addcll: 940a07aba5dSTimm Baeder Result = 941a07aba5dSTimm Baeder LHS.uadd_ov(RHS, FirstOverflowed).uadd_ov(CarryIn, SecondOverflowed); 942a07aba5dSTimm Baeder break; 943a07aba5dSTimm Baeder case Builtin::BI__builtin_subcb: 944a07aba5dSTimm Baeder case Builtin::BI__builtin_subcs: 945a07aba5dSTimm Baeder case Builtin::BI__builtin_subc: 946a07aba5dSTimm Baeder case Builtin::BI__builtin_subcl: 947a07aba5dSTimm Baeder case Builtin::BI__builtin_subcll: 948a07aba5dSTimm Baeder Result = 949a07aba5dSTimm Baeder LHS.usub_ov(RHS, FirstOverflowed).usub_ov(CarryIn, SecondOverflowed); 950a07aba5dSTimm Baeder break; 951a07aba5dSTimm Baeder } 952a07aba5dSTimm Baeder // It is possible for both overflows to happen but CGBuiltin uses an OR so 953a07aba5dSTimm Baeder // this is consistent. 954a07aba5dSTimm Baeder CarryOut = (uint64_t)(FirstOverflowed | SecondOverflowed); 955a07aba5dSTimm Baeder 956a07aba5dSTimm Baeder Pointer &CarryOutPtr = S.Stk.peek<Pointer>(); 957a07aba5dSTimm Baeder QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType(); 958a07aba5dSTimm Baeder PrimType CarryOutT = *S.getContext().classify(CarryOutType); 959a07aba5dSTimm Baeder assignInteger(CarryOutPtr, CarryOutT, CarryOut); 960a07aba5dSTimm Baeder CarryOutPtr.initialize(); 961a07aba5dSTimm Baeder 962a07aba5dSTimm Baeder assert(Call->getType() == Call->getArg(0)->getType()); 963a07aba5dSTimm Baeder pushInteger(S, Result, Call->getType()); 964a07aba5dSTimm Baeder return true; 965a07aba5dSTimm Baeder } 966a07aba5dSTimm Baeder 967a07aba5dSTimm Baeder static bool interp__builtin_clz(InterpState &S, CodePtr OpPC, 968a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *Func, 969a07aba5dSTimm Baeder const CallExpr *Call) { 970a07aba5dSTimm Baeder unsigned CallSize = callArgSize(S, Call); 971a07aba5dSTimm Baeder unsigned BuiltinOp = Func->getBuiltinID(); 972a07aba5dSTimm Baeder PrimType ValT = *S.getContext().classify(Call->getArg(0)); 973a07aba5dSTimm Baeder const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize); 974a07aba5dSTimm Baeder 975a07aba5dSTimm Baeder // When the argument is 0, the result of GCC builtins is undefined, whereas 976a07aba5dSTimm Baeder // for Microsoft intrinsics, the result is the bit-width of the argument. 977a07aba5dSTimm Baeder bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 && 978a07aba5dSTimm Baeder BuiltinOp != Builtin::BI__lzcnt && 979a07aba5dSTimm Baeder BuiltinOp != Builtin::BI__lzcnt64; 980a07aba5dSTimm Baeder 981a07aba5dSTimm Baeder if (Val == 0) { 982a07aba5dSTimm Baeder if (Func->getBuiltinID() == Builtin::BI__builtin_clzg && 983a07aba5dSTimm Baeder Call->getNumArgs() == 2) { 984a07aba5dSTimm Baeder // We have a fallback parameter. 985a07aba5dSTimm Baeder PrimType FallbackT = *S.getContext().classify(Call->getArg(1)); 986a07aba5dSTimm Baeder const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT); 987a07aba5dSTimm Baeder pushInteger(S, Fallback, Call->getType()); 988a07aba5dSTimm Baeder return true; 989a07aba5dSTimm Baeder } 990a07aba5dSTimm Baeder 991a07aba5dSTimm Baeder if (ZeroIsUndefined) 992a07aba5dSTimm Baeder return false; 993a07aba5dSTimm Baeder } 994a07aba5dSTimm Baeder 995a07aba5dSTimm Baeder pushInteger(S, Val.countl_zero(), Call->getType()); 996a07aba5dSTimm Baeder return true; 997a07aba5dSTimm Baeder } 998a07aba5dSTimm Baeder 999a07aba5dSTimm Baeder static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC, 1000a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *Func, 1001a07aba5dSTimm Baeder const CallExpr *Call) { 1002a07aba5dSTimm Baeder unsigned CallSize = callArgSize(S, Call); 1003a07aba5dSTimm Baeder PrimType ValT = *S.getContext().classify(Call->getArg(0)); 1004a07aba5dSTimm Baeder const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize); 1005a07aba5dSTimm Baeder 1006a07aba5dSTimm Baeder if (Val == 0) { 1007a07aba5dSTimm Baeder if (Func->getBuiltinID() == Builtin::BI__builtin_ctzg && 1008a07aba5dSTimm Baeder Call->getNumArgs() == 2) { 1009a07aba5dSTimm Baeder // We have a fallback parameter. 1010a07aba5dSTimm Baeder PrimType FallbackT = *S.getContext().classify(Call->getArg(1)); 1011a07aba5dSTimm Baeder const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT); 1012a07aba5dSTimm Baeder pushInteger(S, Fallback, Call->getType()); 1013a07aba5dSTimm Baeder return true; 1014a07aba5dSTimm Baeder } 1015a07aba5dSTimm Baeder return false; 1016a07aba5dSTimm Baeder } 1017a07aba5dSTimm Baeder 1018a07aba5dSTimm Baeder pushInteger(S, Val.countr_zero(), Call->getType()); 1019a07aba5dSTimm Baeder return true; 1020a07aba5dSTimm Baeder } 1021a07aba5dSTimm Baeder 1022a07aba5dSTimm Baeder static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC, 1023a07aba5dSTimm Baeder const InterpFrame *Frame, 1024a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call) { 1025a07aba5dSTimm Baeder PrimType ReturnT = *S.getContext().classify(Call->getType()); 1026a07aba5dSTimm Baeder PrimType ValT = *S.getContext().classify(Call->getArg(0)); 1027a07aba5dSTimm Baeder const APSInt &Val = peekToAPSInt(S.Stk, ValT); 1028a07aba5dSTimm Baeder assert(Val.getActiveBits() <= 64); 1029a07aba5dSTimm Baeder 1030a07aba5dSTimm Baeder INT_TYPE_SWITCH(ReturnT, 1031a07aba5dSTimm Baeder { S.Stk.push<T>(T::from(Val.byteSwap().getZExtValue())); }); 1032a07aba5dSTimm Baeder return true; 1033a07aba5dSTimm Baeder } 1034a07aba5dSTimm Baeder 1035a07aba5dSTimm Baeder /// bool __atomic_always_lock_free(size_t, void const volatile*) 1036a07aba5dSTimm Baeder /// bool __atomic_is_lock_free(size_t, void const volatile*) 1037a07aba5dSTimm Baeder /// bool __c11_atomic_is_lock_free(size_t) 1038a07aba5dSTimm Baeder static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC, 1039a07aba5dSTimm Baeder const InterpFrame *Frame, 1040a07aba5dSTimm Baeder const Function *Func, 1041a07aba5dSTimm Baeder const CallExpr *Call) { 1042a07aba5dSTimm Baeder unsigned BuiltinOp = Func->getBuiltinID(); 1043a07aba5dSTimm Baeder 1044a07aba5dSTimm Baeder PrimType ValT = *S.getContext().classify(Call->getArg(0)); 1045a07aba5dSTimm Baeder unsigned SizeValOffset = 0; 1046a07aba5dSTimm Baeder if (BuiltinOp != Builtin::BI__c11_atomic_is_lock_free) 1047a07aba5dSTimm Baeder SizeValOffset = align(primSize(ValT)) + align(primSize(PT_Ptr)); 1048a07aba5dSTimm Baeder const APSInt &SizeVal = peekToAPSInt(S.Stk, ValT, SizeValOffset); 1049a07aba5dSTimm Baeder 1050a07aba5dSTimm Baeder auto returnBool = [&S](bool Value) -> bool { 1051a07aba5dSTimm Baeder S.Stk.push<Boolean>(Value); 1052a07aba5dSTimm Baeder return true; 1053a07aba5dSTimm Baeder }; 1054a07aba5dSTimm Baeder 1055a07aba5dSTimm Baeder // For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power 1056a07aba5dSTimm Baeder // of two less than or equal to the maximum inline atomic width, we know it 1057a07aba5dSTimm Baeder // is lock-free. If the size isn't a power of two, or greater than the 1058a07aba5dSTimm Baeder // maximum alignment where we promote atomics, we know it is not lock-free 1059a07aba5dSTimm Baeder // (at least not in the sense of atomic_is_lock_free). Otherwise, 1060a07aba5dSTimm Baeder // the answer can only be determined at runtime; for example, 16-byte 1061a07aba5dSTimm Baeder // atomics have lock-free implementations on some, but not all, 1062a07aba5dSTimm Baeder // x86-64 processors. 1063a07aba5dSTimm Baeder 1064a07aba5dSTimm Baeder // Check power-of-two. 1065a07aba5dSTimm Baeder CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue()); 1066a07aba5dSTimm Baeder if (Size.isPowerOfTwo()) { 1067a07aba5dSTimm Baeder // Check against inlining width. 1068a07aba5dSTimm Baeder unsigned InlineWidthBits = 1069d9e72860Syronglin S.getASTContext().getTargetInfo().getMaxAtomicInlineWidth(); 1070d9e72860Syronglin if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits)) { 1071a07aba5dSTimm Baeder 1072a07aba5dSTimm Baeder // OK, we will inline appropriately-aligned operations of this size, 1073a07aba5dSTimm Baeder // and _Atomic(T) is appropriately-aligned. 1074a07aba5dSTimm Baeder if (BuiltinOp == Builtin::BI__c11_atomic_is_lock_free || 1075a07aba5dSTimm Baeder Size == CharUnits::One()) 1076a07aba5dSTimm Baeder return returnBool(true); 1077a07aba5dSTimm Baeder 1078a07aba5dSTimm Baeder // Same for null pointers. 1079a07aba5dSTimm Baeder assert(BuiltinOp != Builtin::BI__c11_atomic_is_lock_free); 1080a07aba5dSTimm Baeder const Pointer &Ptr = S.Stk.peek<Pointer>(); 1081a07aba5dSTimm Baeder if (Ptr.isZero()) 1082a07aba5dSTimm Baeder return returnBool(true); 1083a07aba5dSTimm Baeder 1084a07aba5dSTimm Baeder if (Ptr.isIntegralPointer()) { 1085a07aba5dSTimm Baeder uint64_t IntVal = Ptr.getIntegerRepresentation(); 1086a07aba5dSTimm Baeder if (APSInt(APInt(64, IntVal, false), true).isAligned(Size.getAsAlign())) 1087a07aba5dSTimm Baeder return returnBool(true); 1088a07aba5dSTimm Baeder } 1089a07aba5dSTimm Baeder 1090a07aba5dSTimm Baeder const Expr *PtrArg = Call->getArg(1); 1091a07aba5dSTimm Baeder // Otherwise, check if the type's alignment against Size. 1092a07aba5dSTimm Baeder if (const auto *ICE = dyn_cast<ImplicitCastExpr>(PtrArg)) { 1093a07aba5dSTimm Baeder // Drop the potential implicit-cast to 'const volatile void*', getting 1094a07aba5dSTimm Baeder // the underlying type. 1095a07aba5dSTimm Baeder if (ICE->getCastKind() == CK_BitCast) 1096a07aba5dSTimm Baeder PtrArg = ICE->getSubExpr(); 1097a07aba5dSTimm Baeder } 1098a07aba5dSTimm Baeder 1099a07aba5dSTimm Baeder if (auto PtrTy = PtrArg->getType()->getAs<PointerType>()) { 1100a07aba5dSTimm Baeder QualType PointeeType = PtrTy->getPointeeType(); 1101a07aba5dSTimm Baeder if (!PointeeType->isIncompleteType() && 1102d9e72860Syronglin S.getASTContext().getTypeAlignInChars(PointeeType) >= Size) { 1103a07aba5dSTimm Baeder // OK, we will inline operations on this object. 1104a07aba5dSTimm Baeder return returnBool(true); 1105a07aba5dSTimm Baeder } 1106a07aba5dSTimm Baeder } 1107a07aba5dSTimm Baeder } 1108a07aba5dSTimm Baeder } 1109a07aba5dSTimm Baeder 1110a07aba5dSTimm Baeder if (BuiltinOp == Builtin::BI__atomic_always_lock_free) 1111a07aba5dSTimm Baeder return returnBool(false); 1112a07aba5dSTimm Baeder 1113a07aba5dSTimm Baeder return false; 1114a07aba5dSTimm Baeder } 1115a07aba5dSTimm Baeder 1116a07aba5dSTimm Baeder /// __builtin_complex(Float A, float B); 1117a07aba5dSTimm Baeder static bool interp__builtin_complex(InterpState &S, CodePtr OpPC, 1118a07aba5dSTimm Baeder const InterpFrame *Frame, 1119a07aba5dSTimm Baeder const Function *Func, 1120a07aba5dSTimm Baeder const CallExpr *Call) { 1121a07aba5dSTimm Baeder const Floating &Arg2 = S.Stk.peek<Floating>(); 1122a07aba5dSTimm Baeder const Floating &Arg1 = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2); 1123a07aba5dSTimm Baeder Pointer &Result = S.Stk.peek<Pointer>(align(primSize(PT_Float)) * 2 + 1124a07aba5dSTimm Baeder align(primSize(PT_Ptr))); 1125a07aba5dSTimm Baeder 1126a07aba5dSTimm Baeder Result.atIndex(0).deref<Floating>() = Arg1; 1127a07aba5dSTimm Baeder Result.atIndex(0).initialize(); 1128a07aba5dSTimm Baeder Result.atIndex(1).deref<Floating>() = Arg2; 1129a07aba5dSTimm Baeder Result.atIndex(1).initialize(); 1130a07aba5dSTimm Baeder Result.initialize(); 1131a07aba5dSTimm Baeder 1132a07aba5dSTimm Baeder return true; 1133a07aba5dSTimm Baeder } 1134a07aba5dSTimm Baeder 1135a07aba5dSTimm Baeder /// __builtin_is_aligned() 1136a07aba5dSTimm Baeder /// __builtin_align_up() 1137a07aba5dSTimm Baeder /// __builtin_align_down() 1138a07aba5dSTimm Baeder /// The first parameter is either an integer or a pointer. 1139a07aba5dSTimm Baeder /// The second parameter is the requested alignment as an integer. 1140a07aba5dSTimm Baeder static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC, 1141a07aba5dSTimm Baeder const InterpFrame *Frame, 1142a07aba5dSTimm Baeder const Function *Func, 1143a07aba5dSTimm Baeder const CallExpr *Call) { 1144a07aba5dSTimm Baeder unsigned BuiltinOp = Func->getBuiltinID(); 1145a07aba5dSTimm Baeder unsigned CallSize = callArgSize(S, Call); 1146a07aba5dSTimm Baeder 1147a07aba5dSTimm Baeder PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1)); 1148a07aba5dSTimm Baeder const APSInt &Alignment = peekToAPSInt(S.Stk, AlignmentT); 1149a07aba5dSTimm Baeder 1150a07aba5dSTimm Baeder if (Alignment < 0 || !Alignment.isPowerOf2()) { 1151a07aba5dSTimm Baeder S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment; 1152a07aba5dSTimm Baeder return false; 1153a07aba5dSTimm Baeder } 1154d9e72860Syronglin unsigned SrcWidth = S.getASTContext().getIntWidth(Call->getArg(0)->getType()); 1155a07aba5dSTimm Baeder APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1)); 1156a07aba5dSTimm Baeder if (APSInt::compareValues(Alignment, MaxValue) > 0) { 1157a07aba5dSTimm Baeder S.FFDiag(Call, diag::note_constexpr_alignment_too_big) 1158a07aba5dSTimm Baeder << MaxValue << Call->getArg(0)->getType() << Alignment; 1159a07aba5dSTimm Baeder return false; 1160a07aba5dSTimm Baeder } 1161a07aba5dSTimm Baeder 1162a07aba5dSTimm Baeder // The first parameter is either an integer or a pointer (but not a function 1163a07aba5dSTimm Baeder // pointer). 1164a07aba5dSTimm Baeder PrimType FirstArgT = *S.Ctx.classify(Call->getArg(0)); 1165a07aba5dSTimm Baeder 1166a07aba5dSTimm Baeder if (isIntegralType(FirstArgT)) { 1167a07aba5dSTimm Baeder const APSInt &Src = peekToAPSInt(S.Stk, FirstArgT, CallSize); 1168a07aba5dSTimm Baeder APSInt Align = Alignment.extOrTrunc(Src.getBitWidth()); 1169a07aba5dSTimm Baeder if (BuiltinOp == Builtin::BI__builtin_align_up) { 1170a07aba5dSTimm Baeder APSInt AlignedVal = 1171a07aba5dSTimm Baeder APSInt((Src + (Align - 1)) & ~(Align - 1), Src.isUnsigned()); 1172a07aba5dSTimm Baeder pushInteger(S, AlignedVal, Call->getType()); 1173a07aba5dSTimm Baeder } else if (BuiltinOp == Builtin::BI__builtin_align_down) { 1174a07aba5dSTimm Baeder APSInt AlignedVal = APSInt(Src & ~(Align - 1), Src.isUnsigned()); 1175a07aba5dSTimm Baeder pushInteger(S, AlignedVal, Call->getType()); 1176a07aba5dSTimm Baeder } else { 1177a07aba5dSTimm Baeder assert(*S.Ctx.classify(Call->getType()) == PT_Bool); 1178a07aba5dSTimm Baeder S.Stk.push<Boolean>((Src & (Align - 1)) == 0); 1179a07aba5dSTimm Baeder } 1180a07aba5dSTimm Baeder return true; 1181a07aba5dSTimm Baeder } 1182a07aba5dSTimm Baeder 1183a07aba5dSTimm Baeder assert(FirstArgT == PT_Ptr); 1184a07aba5dSTimm Baeder const Pointer &Ptr = S.Stk.peek<Pointer>(CallSize); 1185a07aba5dSTimm Baeder 1186a07aba5dSTimm Baeder unsigned PtrOffset = Ptr.getByteOffset(); 1187a07aba5dSTimm Baeder PtrOffset = Ptr.getIndex(); 1188a07aba5dSTimm Baeder CharUnits BaseAlignment = 1189d9e72860Syronglin S.getASTContext().getDeclAlign(Ptr.getDeclDesc()->asValueDecl()); 1190a07aba5dSTimm Baeder CharUnits PtrAlign = 1191a07aba5dSTimm Baeder BaseAlignment.alignmentAtOffset(CharUnits::fromQuantity(PtrOffset)); 1192a07aba5dSTimm Baeder 1193a07aba5dSTimm Baeder if (BuiltinOp == Builtin::BI__builtin_is_aligned) { 1194a07aba5dSTimm Baeder if (PtrAlign.getQuantity() >= Alignment) { 1195a07aba5dSTimm Baeder S.Stk.push<Boolean>(true); 1196a07aba5dSTimm Baeder return true; 1197a07aba5dSTimm Baeder } 1198a07aba5dSTimm Baeder // If the alignment is not known to be sufficient, some cases could still 1199a07aba5dSTimm Baeder // be aligned at run time. However, if the requested alignment is less or 1200a07aba5dSTimm Baeder // equal to the base alignment and the offset is not aligned, we know that 1201a07aba5dSTimm Baeder // the run-time value can never be aligned. 1202a07aba5dSTimm Baeder if (BaseAlignment.getQuantity() >= Alignment && 1203a07aba5dSTimm Baeder PtrAlign.getQuantity() < Alignment) { 1204a07aba5dSTimm Baeder S.Stk.push<Boolean>(false); 1205a07aba5dSTimm Baeder return true; 1206a07aba5dSTimm Baeder } 1207a07aba5dSTimm Baeder 1208a07aba5dSTimm Baeder S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_compute) 1209a07aba5dSTimm Baeder << Alignment; 1210a07aba5dSTimm Baeder return false; 1211a07aba5dSTimm Baeder } 1212a07aba5dSTimm Baeder 1213a07aba5dSTimm Baeder assert(BuiltinOp == Builtin::BI__builtin_align_down || 1214a07aba5dSTimm Baeder BuiltinOp == Builtin::BI__builtin_align_up); 1215a07aba5dSTimm Baeder 1216a07aba5dSTimm Baeder // For align_up/align_down, we can return the same value if the alignment 1217a07aba5dSTimm Baeder // is known to be greater or equal to the requested value. 1218a07aba5dSTimm Baeder if (PtrAlign.getQuantity() >= Alignment) { 1219a07aba5dSTimm Baeder S.Stk.push<Pointer>(Ptr); 1220a07aba5dSTimm Baeder return true; 1221a07aba5dSTimm Baeder } 1222a07aba5dSTimm Baeder 1223a07aba5dSTimm Baeder // The alignment could be greater than the minimum at run-time, so we cannot 1224a07aba5dSTimm Baeder // infer much about the resulting pointer value. One case is possible: 1225a07aba5dSTimm Baeder // For `_Alignas(32) char buf[N]; __builtin_align_down(&buf[idx], 32)` we 1226a07aba5dSTimm Baeder // can infer the correct index if the requested alignment is smaller than 1227a07aba5dSTimm Baeder // the base alignment so we can perform the computation on the offset. 1228a07aba5dSTimm Baeder if (BaseAlignment.getQuantity() >= Alignment) { 1229a07aba5dSTimm Baeder assert(Alignment.getBitWidth() <= 64 && 1230a07aba5dSTimm Baeder "Cannot handle > 64-bit address-space"); 1231a07aba5dSTimm Baeder uint64_t Alignment64 = Alignment.getZExtValue(); 1232a07aba5dSTimm Baeder CharUnits NewOffset = 1233a07aba5dSTimm Baeder CharUnits::fromQuantity(BuiltinOp == Builtin::BI__builtin_align_down 1234a07aba5dSTimm Baeder ? llvm::alignDown(PtrOffset, Alignment64) 1235a07aba5dSTimm Baeder : llvm::alignTo(PtrOffset, Alignment64)); 1236a07aba5dSTimm Baeder 1237a07aba5dSTimm Baeder S.Stk.push<Pointer>(Ptr.atIndex(NewOffset.getQuantity())); 1238a07aba5dSTimm Baeder return true; 1239a07aba5dSTimm Baeder } 1240a07aba5dSTimm Baeder 1241a07aba5dSTimm Baeder // Otherwise, we cannot constant-evaluate the result. 1242a07aba5dSTimm Baeder S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_adjust) << Alignment; 1243a07aba5dSTimm Baeder return false; 1244a07aba5dSTimm Baeder } 1245a07aba5dSTimm Baeder 124680c15c48STimm Baeder /// __builtin_assume_aligned(Ptr, Alignment[, ExtraOffset]) 124780c15c48STimm Baeder static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC, 124880c15c48STimm Baeder const InterpFrame *Frame, 124980c15c48STimm Baeder const Function *Func, 125080c15c48STimm Baeder const CallExpr *Call) { 125180c15c48STimm Baeder assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3); 125280c15c48STimm Baeder 125380c15c48STimm Baeder // Might be called with function pointers in C. 125480c15c48STimm Baeder std::optional<PrimType> PtrT = S.Ctx.classify(Call->getArg(0)); 125580c15c48STimm Baeder if (PtrT != PT_Ptr) 125680c15c48STimm Baeder return false; 125780c15c48STimm Baeder 125880c15c48STimm Baeder unsigned ArgSize = callArgSize(S, Call); 125980c15c48STimm Baeder const Pointer &Ptr = S.Stk.peek<Pointer>(ArgSize); 126080c15c48STimm Baeder std::optional<APSInt> ExtraOffset; 126180c15c48STimm Baeder APSInt Alignment; 126280c15c48STimm Baeder if (Call->getNumArgs() == 2) { 126380c15c48STimm Baeder Alignment = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1))); 126480c15c48STimm Baeder } else { 126580c15c48STimm Baeder PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1)); 126680c15c48STimm Baeder PrimType ExtraOffsetT = *S.Ctx.classify(Call->getArg(2)); 126780c15c48STimm Baeder Alignment = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)), 126880c15c48STimm Baeder align(primSize(AlignmentT)) + 126980c15c48STimm Baeder align(primSize(ExtraOffsetT))); 127080c15c48STimm Baeder ExtraOffset = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(2))); 127180c15c48STimm Baeder } 127280c15c48STimm Baeder 127380c15c48STimm Baeder CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue()); 127480c15c48STimm Baeder 127580c15c48STimm Baeder // If there is a base object, then it must have the correct alignment. 127680c15c48STimm Baeder if (Ptr.isBlockPointer()) { 127780c15c48STimm Baeder CharUnits BaseAlignment; 127880c15c48STimm Baeder if (const auto *VD = Ptr.getDeclDesc()->asValueDecl()) 127980c15c48STimm Baeder BaseAlignment = S.getASTContext().getDeclAlign(VD); 128080c15c48STimm Baeder else if (const auto *E = Ptr.getDeclDesc()->asExpr()) 128180c15c48STimm Baeder BaseAlignment = GetAlignOfExpr(S.getASTContext(), E, UETT_AlignOf); 128280c15c48STimm Baeder 128380c15c48STimm Baeder if (BaseAlignment < Align) { 128480c15c48STimm Baeder S.CCEDiag(Call->getArg(0), 128580c15c48STimm Baeder diag::note_constexpr_baa_insufficient_alignment) 128680c15c48STimm Baeder << 0 << BaseAlignment.getQuantity() << Align.getQuantity(); 128780c15c48STimm Baeder return false; 128880c15c48STimm Baeder } 128980c15c48STimm Baeder } 129080c15c48STimm Baeder 129180c15c48STimm Baeder APValue AV = Ptr.toAPValue(S.getASTContext()); 129280c15c48STimm Baeder CharUnits AVOffset = AV.getLValueOffset(); 129380c15c48STimm Baeder if (ExtraOffset) 129480c15c48STimm Baeder AVOffset -= CharUnits::fromQuantity(ExtraOffset->getZExtValue()); 129580c15c48STimm Baeder if (AVOffset.alignTo(Align) != AVOffset) { 129680c15c48STimm Baeder if (Ptr.isBlockPointer()) 129780c15c48STimm Baeder S.CCEDiag(Call->getArg(0), 129880c15c48STimm Baeder diag::note_constexpr_baa_insufficient_alignment) 129980c15c48STimm Baeder << 1 << AVOffset.getQuantity() << Align.getQuantity(); 130080c15c48STimm Baeder else 130180c15c48STimm Baeder S.CCEDiag(Call->getArg(0), 130280c15c48STimm Baeder diag::note_constexpr_baa_value_insufficient_alignment) 130380c15c48STimm Baeder << AVOffset.getQuantity() << Align.getQuantity(); 130480c15c48STimm Baeder return false; 130580c15c48STimm Baeder } 130680c15c48STimm Baeder 130780c15c48STimm Baeder S.Stk.push<Pointer>(Ptr); 130880c15c48STimm Baeder return true; 130980c15c48STimm Baeder } 131080c15c48STimm Baeder 131185181788STimm Baeder static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC, 131285181788STimm Baeder const InterpFrame *Frame, 131385181788STimm Baeder const Function *Func, 131485181788STimm Baeder const CallExpr *Call) { 13158951b514STimm Baeder if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() || 1316615a5eb0STimm Baeder !Call->getArg(1)->getType()->isIntegerType()) 1317615a5eb0STimm Baeder return false; 1318615a5eb0STimm Baeder 131985181788STimm Baeder PrimType ValT = *S.Ctx.classify(Call->getArg(0)); 132085181788STimm Baeder PrimType IndexT = *S.Ctx.classify(Call->getArg(1)); 132185181788STimm Baeder APSInt Val = peekToAPSInt(S.Stk, ValT, 132285181788STimm Baeder align(primSize(ValT)) + align(primSize(IndexT))); 132385181788STimm Baeder APSInt Index = peekToAPSInt(S.Stk, IndexT); 132485181788STimm Baeder 132585181788STimm Baeder unsigned BitWidth = Val.getBitWidth(); 132685181788STimm Baeder uint64_t Shift = Index.extractBitsAsZExtValue(8, 0); 132785181788STimm Baeder uint64_t Length = Index.extractBitsAsZExtValue(8, 8); 132885181788STimm Baeder Length = Length > BitWidth ? BitWidth : Length; 132985181788STimm Baeder 133085181788STimm Baeder // Handle out of bounds cases. 133185181788STimm Baeder if (Length == 0 || Shift >= BitWidth) { 133285181788STimm Baeder pushInteger(S, 0, Call->getType()); 133385181788STimm Baeder return true; 133485181788STimm Baeder } 133585181788STimm Baeder 133685181788STimm Baeder uint64_t Result = Val.getZExtValue() >> Shift; 133785181788STimm Baeder Result &= llvm::maskTrailingOnes<uint64_t>(Length); 133885181788STimm Baeder pushInteger(S, Result, Call->getType()); 133985181788STimm Baeder return true; 134085181788STimm Baeder } 134185181788STimm Baeder 13427147e88fSTimm Baeder static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC, 13437147e88fSTimm Baeder const InterpFrame *Frame, 13447147e88fSTimm Baeder const Function *Func, 13457147e88fSTimm Baeder const CallExpr *Call) { 1346235067b2STimm Baeder QualType CallType = Call->getType(); 13478951b514STimm Baeder if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() || 13488951b514STimm Baeder !Call->getArg(1)->getType()->isIntegerType() || 13498951b514STimm Baeder !CallType->isIntegerType()) 1350235067b2STimm Baeder return false; 1351235067b2STimm Baeder 13527147e88fSTimm Baeder PrimType ValT = *S.Ctx.classify(Call->getArg(0)); 13537147e88fSTimm Baeder PrimType IndexT = *S.Ctx.classify(Call->getArg(1)); 13547147e88fSTimm Baeder 13557147e88fSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, ValT, 13567147e88fSTimm Baeder align(primSize(ValT)) + align(primSize(IndexT))); 13577147e88fSTimm Baeder APSInt Idx = peekToAPSInt(S.Stk, IndexT); 13587147e88fSTimm Baeder 13597147e88fSTimm Baeder unsigned BitWidth = Val.getBitWidth(); 13607147e88fSTimm Baeder uint64_t Index = Idx.extractBitsAsZExtValue(8, 0); 13617147e88fSTimm Baeder 13627147e88fSTimm Baeder if (Index < BitWidth) 13637147e88fSTimm Baeder Val.clearHighBits(BitWidth - Index); 13647147e88fSTimm Baeder 1365235067b2STimm Baeder pushInteger(S, Val, CallType); 13667147e88fSTimm Baeder return true; 13677147e88fSTimm Baeder } 13687147e88fSTimm Baeder 13697147e88fSTimm Baeder static bool interp__builtin_ia32_lzcnt(InterpState &S, CodePtr OpPC, 13707147e88fSTimm Baeder const InterpFrame *Frame, 13717147e88fSTimm Baeder const Function *Func, 13727147e88fSTimm Baeder const CallExpr *Call) { 1373e1e788f4STimm Baeder QualType CallType = Call->getType(); 13748951b514STimm Baeder if (!CallType->isIntegerType() || 13758951b514STimm Baeder !Call->getArg(0)->getType()->isIntegerType()) 1376e1e788f4STimm Baeder return false; 1377e1e788f4STimm Baeder 13787147e88fSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0))); 1379235067b2STimm Baeder pushInteger(S, Val.countLeadingZeros(), CallType); 13807147e88fSTimm Baeder return true; 13817147e88fSTimm Baeder } 13827147e88fSTimm Baeder 13837147e88fSTimm Baeder static bool interp__builtin_ia32_tzcnt(InterpState &S, CodePtr OpPC, 13847147e88fSTimm Baeder const InterpFrame *Frame, 13857147e88fSTimm Baeder const Function *Func, 13867147e88fSTimm Baeder const CallExpr *Call) { 1387e1e788f4STimm Baeder QualType CallType = Call->getType(); 13888951b514STimm Baeder if (!CallType->isIntegerType() || 13898951b514STimm Baeder !Call->getArg(0)->getType()->isIntegerType()) 1390e1e788f4STimm Baeder return false; 1391e1e788f4STimm Baeder 13927147e88fSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0))); 1393235067b2STimm Baeder pushInteger(S, Val.countTrailingZeros(), CallType); 13947147e88fSTimm Baeder return true; 13957147e88fSTimm Baeder } 13967147e88fSTimm Baeder 1397f3baa73cSTimm Baeder static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC, 1398f3baa73cSTimm Baeder const InterpFrame *Frame, 1399f3baa73cSTimm Baeder const Function *Func, 1400f3baa73cSTimm Baeder const CallExpr *Call) { 14018951b514STimm Baeder if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() || 14025405ba50STimm Baeder !Call->getArg(1)->getType()->isIntegerType()) 14035405ba50STimm Baeder return false; 14045405ba50STimm Baeder 1405f3baa73cSTimm Baeder PrimType ValT = *S.Ctx.classify(Call->getArg(0)); 1406f3baa73cSTimm Baeder PrimType MaskT = *S.Ctx.classify(Call->getArg(1)); 1407f3baa73cSTimm Baeder 1408f3baa73cSTimm Baeder APSInt Val = 1409f3baa73cSTimm Baeder peekToAPSInt(S.Stk, ValT, align(primSize(ValT)) + align(primSize(MaskT))); 1410f3baa73cSTimm Baeder APSInt Mask = peekToAPSInt(S.Stk, MaskT); 1411f3baa73cSTimm Baeder 1412f3baa73cSTimm Baeder unsigned BitWidth = Val.getBitWidth(); 1413f3baa73cSTimm Baeder APInt Result = APInt::getZero(BitWidth); 1414f3baa73cSTimm Baeder for (unsigned I = 0, P = 0; I != BitWidth; ++I) { 1415f3baa73cSTimm Baeder if (Mask[I]) 1416f3baa73cSTimm Baeder Result.setBitVal(I, Val[P++]); 1417f3baa73cSTimm Baeder } 1418f3baa73cSTimm Baeder pushInteger(S, Result, Call->getType()); 1419f3baa73cSTimm Baeder return true; 1420f3baa73cSTimm Baeder } 1421f3baa73cSTimm Baeder 1422f3baa73cSTimm Baeder static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC, 1423f3baa73cSTimm Baeder const InterpFrame *Frame, 1424f3baa73cSTimm Baeder const Function *Func, 1425f3baa73cSTimm Baeder const CallExpr *Call) { 14268951b514STimm Baeder if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() || 14275405ba50STimm Baeder !Call->getArg(1)->getType()->isIntegerType()) 14285405ba50STimm Baeder return false; 14295405ba50STimm Baeder 1430f3baa73cSTimm Baeder PrimType ValT = *S.Ctx.classify(Call->getArg(0)); 1431f3baa73cSTimm Baeder PrimType MaskT = *S.Ctx.classify(Call->getArg(1)); 1432f3baa73cSTimm Baeder 1433f3baa73cSTimm Baeder APSInt Val = 1434f3baa73cSTimm Baeder peekToAPSInt(S.Stk, ValT, align(primSize(ValT)) + align(primSize(MaskT))); 1435f3baa73cSTimm Baeder APSInt Mask = peekToAPSInt(S.Stk, MaskT); 1436f3baa73cSTimm Baeder 1437f3baa73cSTimm Baeder unsigned BitWidth = Val.getBitWidth(); 1438f3baa73cSTimm Baeder APInt Result = APInt::getZero(BitWidth); 1439f3baa73cSTimm Baeder for (unsigned I = 0, P = 0; I != BitWidth; ++I) { 1440f3baa73cSTimm Baeder if (Mask[I]) 1441f3baa73cSTimm Baeder Result.setBitVal(P++, Val[I]); 1442f3baa73cSTimm Baeder } 1443f3baa73cSTimm Baeder pushInteger(S, Result, Call->getType()); 1444f3baa73cSTimm Baeder return true; 1445f3baa73cSTimm Baeder } 1446f3baa73cSTimm Baeder 14476f8e8551STimm Baeder static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S, 14486f8e8551STimm Baeder CodePtr OpPC, 14496f8e8551STimm Baeder const InterpFrame *Frame, 14506f8e8551STimm Baeder const Function *Func, 14516f8e8551STimm Baeder const CallExpr *Call) { 14521fd79f10STimm Baeder if (Call->getNumArgs() != 4 || !Call->getArg(0)->getType()->isIntegerType() || 1453f1eac776STimm Baeder !Call->getArg(1)->getType()->isIntegerType() || 1454f1eac776STimm Baeder !Call->getArg(2)->getType()->isIntegerType()) 1455f1eac776STimm Baeder return false; 1456f1eac776STimm Baeder 14576f8e8551STimm Baeder unsigned BuiltinOp = Func->getBuiltinID(); 14586f8e8551STimm Baeder APSInt CarryIn = getAPSIntParam(Frame, 0); 14596f8e8551STimm Baeder APSInt LHS = getAPSIntParam(Frame, 1); 14606f8e8551STimm Baeder APSInt RHS = getAPSIntParam(Frame, 2); 14616f8e8551STimm Baeder 14626f8e8551STimm Baeder bool IsAdd = BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u32 || 14636f8e8551STimm Baeder BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u64; 14646f8e8551STimm Baeder 14656f8e8551STimm Baeder unsigned BitWidth = LHS.getBitWidth(); 14666f8e8551STimm Baeder unsigned CarryInBit = CarryIn.ugt(0) ? 1 : 0; 14676f8e8551STimm Baeder APInt ExResult = 14686f8e8551STimm Baeder IsAdd ? (LHS.zext(BitWidth + 1) + (RHS.zext(BitWidth + 1) + CarryInBit)) 14696f8e8551STimm Baeder : (LHS.zext(BitWidth + 1) - (RHS.zext(BitWidth + 1) + CarryInBit)); 14706f8e8551STimm Baeder 14716f8e8551STimm Baeder APInt Result = ExResult.extractBits(BitWidth, 0); 14726f8e8551STimm Baeder APSInt CarryOut = 14736f8e8551STimm Baeder APSInt(ExResult.extractBits(1, BitWidth), /*IsUnsigned=*/true); 14746f8e8551STimm Baeder 14756f8e8551STimm Baeder Pointer &CarryOutPtr = S.Stk.peek<Pointer>(); 14766f8e8551STimm Baeder QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType(); 14776f8e8551STimm Baeder PrimType CarryOutT = *S.getContext().classify(CarryOutType); 14786f8e8551STimm Baeder assignInteger(CarryOutPtr, CarryOutT, APSInt(Result, true)); 14796f8e8551STimm Baeder 14806f8e8551STimm Baeder pushInteger(S, CarryOut, Call->getType()); 14816f8e8551STimm Baeder 14826f8e8551STimm Baeder return true; 14836f8e8551STimm Baeder } 14846f8e8551STimm Baeder 1485a07aba5dSTimm Baeder static bool interp__builtin_os_log_format_buffer_size(InterpState &S, 1486a07aba5dSTimm Baeder CodePtr OpPC, 1487a07aba5dSTimm Baeder const InterpFrame *Frame, 1488a07aba5dSTimm Baeder const Function *Func, 1489a07aba5dSTimm Baeder const CallExpr *Call) { 1490a07aba5dSTimm Baeder analyze_os_log::OSLogBufferLayout Layout; 1491d9e72860Syronglin analyze_os_log::computeOSLogBufferLayout(S.getASTContext(), Call, Layout); 1492a07aba5dSTimm Baeder pushInteger(S, Layout.size().getQuantity(), Call->getType()); 1493a07aba5dSTimm Baeder return true; 1494a07aba5dSTimm Baeder } 1495a07aba5dSTimm Baeder 1496a07aba5dSTimm Baeder static bool interp__builtin_ptrauth_string_discriminator( 1497a07aba5dSTimm Baeder InterpState &S, CodePtr OpPC, const InterpFrame *Frame, 1498a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call) { 1499a07aba5dSTimm Baeder const auto &Ptr = S.Stk.peek<Pointer>(); 1500a07aba5dSTimm Baeder assert(Ptr.getFieldDesc()->isPrimitiveArray()); 1501a07aba5dSTimm Baeder 1502a07aba5dSTimm Baeder StringRef R(&Ptr.deref<char>(), Ptr.getFieldDesc()->getNumElems() - 1); 1503a07aba5dSTimm Baeder uint64_t Result = getPointerAuthStableSipHash(R); 1504a07aba5dSTimm Baeder pushInteger(S, Result, Call->getType()); 1505a07aba5dSTimm Baeder return true; 1506a07aba5dSTimm Baeder } 1507a07aba5dSTimm Baeder 1508a07aba5dSTimm Baeder // FIXME: This implementation is not complete. 1509a07aba5dSTimm Baeder // The Compiler instance we create cannot access the current stack frame, local 1510a07aba5dSTimm Baeder // variables, function parameters, etc. We also need protection from 1511a07aba5dSTimm Baeder // side-effects, fatal errors, etc. 1512a07aba5dSTimm Baeder static bool interp__builtin_constant_p(InterpState &S, CodePtr OpPC, 1513a07aba5dSTimm Baeder const InterpFrame *Frame, 1514a07aba5dSTimm Baeder const Function *Func, 1515a07aba5dSTimm Baeder const CallExpr *Call) { 1516a07aba5dSTimm Baeder const Expr *Arg = Call->getArg(0); 1517a07aba5dSTimm Baeder QualType ArgType = Arg->getType(); 1518a07aba5dSTimm Baeder 1519a07aba5dSTimm Baeder auto returnInt = [&S, Call](bool Value) -> bool { 1520a07aba5dSTimm Baeder pushInteger(S, Value, Call->getType()); 1521a07aba5dSTimm Baeder return true; 1522a07aba5dSTimm Baeder }; 1523a07aba5dSTimm Baeder 1524a07aba5dSTimm Baeder // __builtin_constant_p always has one operand. The rules which gcc follows 1525a07aba5dSTimm Baeder // are not precisely documented, but are as follows: 1526a07aba5dSTimm Baeder // 1527a07aba5dSTimm Baeder // - If the operand is of integral, floating, complex or enumeration type, 1528a07aba5dSTimm Baeder // and can be folded to a known value of that type, it returns 1. 1529a07aba5dSTimm Baeder // - If the operand can be folded to a pointer to the first character 1530a07aba5dSTimm Baeder // of a string literal (or such a pointer cast to an integral type) 1531a07aba5dSTimm Baeder // or to a null pointer or an integer cast to a pointer, it returns 1. 1532a07aba5dSTimm Baeder // 1533a07aba5dSTimm Baeder // Otherwise, it returns 0. 1534a07aba5dSTimm Baeder // 1535a07aba5dSTimm Baeder // FIXME: GCC also intends to return 1 for literals of aggregate types, but 1536a07aba5dSTimm Baeder // its support for this did not work prior to GCC 9 and is not yet well 1537a07aba5dSTimm Baeder // understood. 1538a07aba5dSTimm Baeder if (ArgType->isIntegralOrEnumerationType() || ArgType->isFloatingType() || 1539a07aba5dSTimm Baeder ArgType->isAnyComplexType() || ArgType->isPointerType() || 1540a07aba5dSTimm Baeder ArgType->isNullPtrType()) { 1541*51c7338cSTimm Baeder auto PrevDiags = S.getEvalStatus().Diag; 1542*51c7338cSTimm Baeder S.getEvalStatus().Diag = nullptr; 1543a07aba5dSTimm Baeder InterpStack Stk; 1544a07aba5dSTimm Baeder Compiler<EvalEmitter> C(S.Ctx, S.P, S, Stk); 1545a07aba5dSTimm Baeder auto Res = C.interpretExpr(Arg, /*ConvertResultToRValue=*/Arg->isGLValue()); 1546*51c7338cSTimm Baeder S.getEvalStatus().Diag = PrevDiags; 1547a07aba5dSTimm Baeder if (Res.isInvalid()) { 1548a07aba5dSTimm Baeder C.cleanup(); 1549a07aba5dSTimm Baeder Stk.clear(); 155002b30128STimm Baeder return returnInt(false); 1551a07aba5dSTimm Baeder } 1552a07aba5dSTimm Baeder 155302b30128STimm Baeder if (!Res.empty()) { 1554a07aba5dSTimm Baeder const APValue &LV = Res.toAPValue(); 1555a07aba5dSTimm Baeder if (LV.isLValue()) { 1556a07aba5dSTimm Baeder APValue::LValueBase Base = LV.getLValueBase(); 1557a07aba5dSTimm Baeder if (Base.isNull()) { 1558a07aba5dSTimm Baeder // A null base is acceptable. 1559a07aba5dSTimm Baeder return returnInt(true); 1560a07aba5dSTimm Baeder } else if (const auto *E = Base.dyn_cast<const Expr *>()) { 1561a07aba5dSTimm Baeder if (!isa<StringLiteral>(E)) 1562a07aba5dSTimm Baeder return returnInt(false); 1563a07aba5dSTimm Baeder return returnInt(LV.getLValueOffset().isZero()); 1564a07aba5dSTimm Baeder } else if (Base.is<TypeInfoLValue>()) { 1565a07aba5dSTimm Baeder // Surprisingly, GCC considers __builtin_constant_p(&typeid(int)) to 1566a07aba5dSTimm Baeder // evaluate to true. 1567a07aba5dSTimm Baeder return returnInt(true); 1568a07aba5dSTimm Baeder } else { 1569a07aba5dSTimm Baeder // Any other base is not constant enough for GCC. 1570a07aba5dSTimm Baeder return returnInt(false); 1571a07aba5dSTimm Baeder } 1572a07aba5dSTimm Baeder } 1573a07aba5dSTimm Baeder } 1574a07aba5dSTimm Baeder 1575a07aba5dSTimm Baeder // Otherwise, any constant value is good enough. 1576a07aba5dSTimm Baeder return returnInt(true); 1577a07aba5dSTimm Baeder } 1578a07aba5dSTimm Baeder 1579a07aba5dSTimm Baeder return returnInt(false); 1580a07aba5dSTimm Baeder } 1581a07aba5dSTimm Baeder 1582610b8539STimm Baeder static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC, 1583610b8539STimm Baeder const InterpFrame *Frame, 1584610b8539STimm Baeder const Function *Func, 1585610b8539STimm Baeder const CallExpr *Call) { 1586610b8539STimm Baeder // A call to __operator_new is only valid within std::allocate<>::allocate. 1587610b8539STimm Baeder // Walk up the call stack to find the appropriate caller and get the 1588610b8539STimm Baeder // element type from it. 1589610b8539STimm Baeder QualType ElemType; 1590e6030d38STimm Baeder const CallExpr *NewCall = nullptr; 1591610b8539STimm Baeder 1592610b8539STimm Baeder for (const InterpFrame *F = Frame; F; F = F->Caller) { 1593610b8539STimm Baeder const Function *Func = F->getFunction(); 1594610b8539STimm Baeder if (!Func) 1595610b8539STimm Baeder continue; 1596610b8539STimm Baeder const auto *MD = dyn_cast_if_present<CXXMethodDecl>(Func->getDecl()); 1597610b8539STimm Baeder if (!MD) 1598610b8539STimm Baeder continue; 1599610b8539STimm Baeder const IdentifierInfo *FnII = MD->getIdentifier(); 1600610b8539STimm Baeder if (!FnII || !FnII->isStr("allocate")) 1601610b8539STimm Baeder continue; 1602610b8539STimm Baeder 1603610b8539STimm Baeder const auto *CTSD = 1604610b8539STimm Baeder dyn_cast<ClassTemplateSpecializationDecl>(MD->getParent()); 1605610b8539STimm Baeder if (!CTSD) 1606610b8539STimm Baeder continue; 1607610b8539STimm Baeder 1608610b8539STimm Baeder const IdentifierInfo *ClassII = CTSD->getIdentifier(); 1609610b8539STimm Baeder const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); 1610610b8539STimm Baeder if (CTSD->isInStdNamespace() && ClassII && ClassII->isStr("allocator") && 1611610b8539STimm Baeder TAL.size() >= 1 && TAL[0].getKind() == TemplateArgument::Type) { 1612610b8539STimm Baeder ElemType = TAL[0].getAsType(); 1613e6030d38STimm Baeder NewCall = cast<CallExpr>(F->Caller->getExpr(F->getRetPC())); 1614610b8539STimm Baeder break; 1615610b8539STimm Baeder } 1616610b8539STimm Baeder } 1617610b8539STimm Baeder 1618610b8539STimm Baeder if (ElemType.isNull()) { 1619610b8539STimm Baeder S.FFDiag(Call, S.getLangOpts().CPlusPlus20 1620610b8539STimm Baeder ? diag::note_constexpr_new_untyped 1621610b8539STimm Baeder : diag::note_constexpr_new); 1622610b8539STimm Baeder return false; 1623610b8539STimm Baeder } 1624e6030d38STimm Baeder assert(NewCall); 1625610b8539STimm Baeder 1626610b8539STimm Baeder if (ElemType->isIncompleteType() || ElemType->isFunctionType()) { 1627610b8539STimm Baeder S.FFDiag(Call, diag::note_constexpr_new_not_complete_object_type) 1628610b8539STimm Baeder << (ElemType->isIncompleteType() ? 0 : 1) << ElemType; 1629610b8539STimm Baeder return false; 1630610b8539STimm Baeder } 1631610b8539STimm Baeder 1632610b8539STimm Baeder APSInt Bytes = peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(0))); 1633610b8539STimm Baeder CharUnits ElemSize = S.getASTContext().getTypeSizeInChars(ElemType); 1634610b8539STimm Baeder assert(!ElemSize.isZero()); 1635610b8539STimm Baeder // Divide the number of bytes by sizeof(ElemType), so we get the number of 1636610b8539STimm Baeder // elements we should allocate. 1637610b8539STimm Baeder APInt NumElems, Remainder; 1638610b8539STimm Baeder APInt ElemSizeAP(Bytes.getBitWidth(), ElemSize.getQuantity()); 1639610b8539STimm Baeder APInt::udivrem(Bytes, ElemSizeAP, NumElems, Remainder); 1640610b8539STimm Baeder if (Remainder != 0) { 1641610b8539STimm Baeder // This likely indicates a bug in the implementation of 'std::allocator'. 1642610b8539STimm Baeder S.FFDiag(Call, diag::note_constexpr_operator_new_bad_size) 1643610b8539STimm Baeder << Bytes << APSInt(ElemSizeAP, true) << ElemType; 1644610b8539STimm Baeder return false; 1645610b8539STimm Baeder } 1646610b8539STimm Baeder 1647898fd396STimm Baeder // NB: The same check we're using in CheckArraySize() 1648898fd396STimm Baeder if (NumElems.getActiveBits() > 1649898fd396STimm Baeder ConstantArrayType::getMaxSizeBits(S.getASTContext()) || 1650898fd396STimm Baeder NumElems.ugt(Descriptor::MaxArrayElemBytes / ElemSize.getQuantity())) { 1651898fd396STimm Baeder // FIXME: NoThrow check? 1652898fd396STimm Baeder const SourceInfo &Loc = S.Current->getSource(OpPC); 1653898fd396STimm Baeder S.FFDiag(Loc, diag::note_constexpr_new_too_large) 1654898fd396STimm Baeder << NumElems.getZExtValue(); 1655898fd396STimm Baeder return false; 1656898fd396STimm Baeder } 1657610b8539STimm Baeder 1658610b8539STimm Baeder std::optional<PrimType> ElemT = S.getContext().classify(ElemType); 1659610b8539STimm Baeder DynamicAllocator &Allocator = S.getAllocator(); 1660610b8539STimm Baeder if (ElemT) { 1661610b8539STimm Baeder if (NumElems.ule(1)) { 1662610b8539STimm Baeder const Descriptor *Desc = 1663e6030d38STimm Baeder S.P.createDescriptor(NewCall, *ElemT, Descriptor::InlineDescMD, 1664610b8539STimm Baeder /*IsConst=*/false, /*IsTemporary=*/false, 1665610b8539STimm Baeder /*IsMutable=*/false); 1666610b8539STimm Baeder Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(), 1667610b8539STimm Baeder DynamicAllocator::Form::Operator); 1668610b8539STimm Baeder assert(B); 1669610b8539STimm Baeder 1670610b8539STimm Baeder S.Stk.push<Pointer>(B); 1671610b8539STimm Baeder return true; 1672610b8539STimm Baeder } 1673610b8539STimm Baeder assert(NumElems.ugt(1)); 1674610b8539STimm Baeder 1675610b8539STimm Baeder Block *B = 1676e6030d38STimm Baeder Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(), 1677610b8539STimm Baeder S.Ctx.getEvalID(), DynamicAllocator::Form::Operator); 1678610b8539STimm Baeder assert(B); 1679610b8539STimm Baeder S.Stk.push<Pointer>(B); 1680610b8539STimm Baeder return true; 1681610b8539STimm Baeder } 1682610b8539STimm Baeder 1683610b8539STimm Baeder assert(!ElemT); 1684610b8539STimm Baeder // Structs etc. 1685610b8539STimm Baeder const Descriptor *Desc = S.P.createDescriptor( 16864b964002STimm Baeder Call, ElemType.getTypePtr(), Descriptor::InlineDescMD, 1687610b8539STimm Baeder /*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, 1688610b8539STimm Baeder /*Init=*/nullptr); 1689610b8539STimm Baeder 1690610b8539STimm Baeder if (NumElems.ule(1)) { 1691610b8539STimm Baeder Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(), 1692610b8539STimm Baeder DynamicAllocator::Form::Operator); 1693610b8539STimm Baeder assert(B); 1694610b8539STimm Baeder S.Stk.push<Pointer>(B); 1695610b8539STimm Baeder return true; 1696610b8539STimm Baeder } 1697610b8539STimm Baeder 1698610b8539STimm Baeder Block *B = 1699610b8539STimm Baeder Allocator.allocate(Desc, NumElems.getZExtValue(), S.Ctx.getEvalID(), 1700610b8539STimm Baeder DynamicAllocator::Form::Operator); 1701610b8539STimm Baeder assert(B); 1702610b8539STimm Baeder S.Stk.push<Pointer>(B); 1703610b8539STimm Baeder return true; 1704610b8539STimm Baeder } 1705610b8539STimm Baeder 1706610b8539STimm Baeder static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC, 1707610b8539STimm Baeder const InterpFrame *Frame, 1708610b8539STimm Baeder const Function *Func, 1709610b8539STimm Baeder const CallExpr *Call) { 1710610b8539STimm Baeder const Expr *Source = nullptr; 1711610b8539STimm Baeder const Block *BlockToDelete = nullptr; 1712610b8539STimm Baeder 1713610b8539STimm Baeder { 1714610b8539STimm Baeder const Pointer &Ptr = S.Stk.peek<Pointer>(); 1715610b8539STimm Baeder 1716610b8539STimm Baeder if (Ptr.isZero()) { 1717610b8539STimm Baeder S.CCEDiag(Call, diag::note_constexpr_deallocate_null); 1718610b8539STimm Baeder return true; 1719610b8539STimm Baeder } 1720610b8539STimm Baeder 1721610b8539STimm Baeder Source = Ptr.getDeclDesc()->asExpr(); 1722610b8539STimm Baeder BlockToDelete = Ptr.block(); 1723610b8539STimm Baeder } 1724610b8539STimm Baeder assert(BlockToDelete); 1725610b8539STimm Baeder 1726610b8539STimm Baeder DynamicAllocator &Allocator = S.getAllocator(); 1727610b8539STimm Baeder const Descriptor *BlockDesc = BlockToDelete->getDescriptor(); 1728610b8539STimm Baeder std::optional<DynamicAllocator::Form> AllocForm = 1729610b8539STimm Baeder Allocator.getAllocationForm(Source); 1730610b8539STimm Baeder 1731610b8539STimm Baeder if (!Allocator.deallocate(Source, BlockToDelete, S)) { 1732610b8539STimm Baeder // Nothing has been deallocated, this must be a double-delete. 1733610b8539STimm Baeder const SourceInfo &Loc = S.Current->getSource(OpPC); 1734610b8539STimm Baeder S.FFDiag(Loc, diag::note_constexpr_double_delete); 1735610b8539STimm Baeder return false; 1736610b8539STimm Baeder } 1737610b8539STimm Baeder assert(AllocForm); 1738610b8539STimm Baeder 1739610b8539STimm Baeder return CheckNewDeleteForms( 1740610b8539STimm Baeder S, OpPC, *AllocForm, DynamicAllocator::Form::Operator, BlockDesc, Source); 1741610b8539STimm Baeder } 1742610b8539STimm Baeder 1743b46a0482STimm Baeder static bool interp__builtin_arithmetic_fence(InterpState &S, CodePtr OpPC, 1744b46a0482STimm Baeder const InterpFrame *Frame, 1745b46a0482STimm Baeder const Function *Func, 1746b46a0482STimm Baeder const CallExpr *Call) { 1747b46a0482STimm Baeder const Floating &Arg0 = S.Stk.peek<Floating>(); 1748b46a0482STimm Baeder S.Stk.push<Floating>(Arg0); 1749b46a0482STimm Baeder return true; 1750b46a0482STimm Baeder } 1751b46a0482STimm Baeder 175231bde711STimm Baeder static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC, 175331bde711STimm Baeder const InterpFrame *Frame, 175431bde711STimm Baeder const Function *Func, 175531bde711STimm Baeder const CallExpr *Call) { 175631bde711STimm Baeder const Pointer &Arg = S.Stk.peek<Pointer>(); 175731bde711STimm Baeder assert(Arg.getFieldDesc()->isPrimitiveArray()); 175831bde711STimm Baeder 175931bde711STimm Baeder unsigned ID = Func->getBuiltinID(); 176031bde711STimm Baeder QualType ElemType = Arg.getFieldDesc()->getElemQualType(); 176131bde711STimm Baeder assert(Call->getType() == ElemType); 176231bde711STimm Baeder PrimType ElemT = *S.getContext().classify(ElemType); 176331bde711STimm Baeder unsigned NumElems = Arg.getNumElems(); 176431bde711STimm Baeder 1765ccc471feSTimm Baeder INT_TYPE_SWITCH_NO_BOOL(ElemT, { 1766c1dcf75aSTimm Baeder T Result = Arg.atIndex(0).deref<T>(); 1767c1dcf75aSTimm Baeder unsigned BitWidth = Result.bitWidth(); 176831bde711STimm Baeder for (unsigned I = 1; I != NumElems; ++I) { 176931bde711STimm Baeder T Elem = Arg.atIndex(I).deref<T>(); 1770c1dcf75aSTimm Baeder T PrevResult = Result; 1771c1dcf75aSTimm Baeder 1772c1dcf75aSTimm Baeder if (ID == Builtin::BI__builtin_reduce_add) { 1773c1dcf75aSTimm Baeder if (T::add(Result, Elem, BitWidth, &Result)) { 177431bde711STimm Baeder unsigned OverflowBits = BitWidth + 1; 1775c1dcf75aSTimm Baeder (void)handleOverflow(S, OpPC, 1776c1dcf75aSTimm Baeder (PrevResult.toAPSInt(OverflowBits) + 1777c1dcf75aSTimm Baeder Elem.toAPSInt(OverflowBits))); 177831bde711STimm Baeder return false; 177931bde711STimm Baeder } 1780c1dcf75aSTimm Baeder } else if (ID == Builtin::BI__builtin_reduce_mul) { 1781c1dcf75aSTimm Baeder if (T::mul(Result, Elem, BitWidth, &Result)) { 1782c1dcf75aSTimm Baeder unsigned OverflowBits = BitWidth * 2; 1783c1dcf75aSTimm Baeder (void)handleOverflow(S, OpPC, 1784c1dcf75aSTimm Baeder (PrevResult.toAPSInt(OverflowBits) * 1785c1dcf75aSTimm Baeder Elem.toAPSInt(OverflowBits))); 1786c1dcf75aSTimm Baeder return false; 178731bde711STimm Baeder } 1788ccc471feSTimm Baeder 1789ccc471feSTimm Baeder } else if (ID == Builtin::BI__builtin_reduce_and) { 1790ccc471feSTimm Baeder (void)T::bitAnd(Result, Elem, BitWidth, &Result); 17911288f6d4STimm Baeder } else if (ID == Builtin::BI__builtin_reduce_or) { 17921288f6d4STimm Baeder (void)T::bitOr(Result, Elem, BitWidth, &Result); 1793b587b910STimm Baeder } else if (ID == Builtin::BI__builtin_reduce_xor) { 1794b587b910STimm Baeder (void)T::bitXor(Result, Elem, BitWidth, &Result); 1795c1dcf75aSTimm Baeder } else { 1796c1dcf75aSTimm Baeder llvm_unreachable("Unhandled vector reduce builtin"); 1797c1dcf75aSTimm Baeder } 1798c1dcf75aSTimm Baeder } 17991288f6d4STimm Baeder pushInteger(S, Result.toAPSInt(), Call->getType()); 180031bde711STimm Baeder }); 180131bde711STimm Baeder 180231bde711STimm Baeder return true; 180331bde711STimm Baeder } 180431bde711STimm Baeder 1805637a1ae8STimm Baeder /// Can be called with an integer or vector as the first and only parameter. 1806637a1ae8STimm Baeder static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC, 1807637a1ae8STimm Baeder const InterpFrame *Frame, 1808637a1ae8STimm Baeder const Function *Func, 1809637a1ae8STimm Baeder const CallExpr *Call) { 1810637a1ae8STimm Baeder assert(Call->getNumArgs() == 1); 1811637a1ae8STimm Baeder if (Call->getArg(0)->getType()->isIntegerType()) { 1812637a1ae8STimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 1813637a1ae8STimm Baeder APSInt Val = peekToAPSInt(S.Stk, ArgT); 1814637a1ae8STimm Baeder pushInteger(S, Val.popcount(), Call->getType()); 1815637a1ae8STimm Baeder return true; 1816637a1ae8STimm Baeder } 1817637a1ae8STimm Baeder // Otherwise, the argument must be a vector. 1818637a1ae8STimm Baeder assert(Call->getArg(0)->getType()->isVectorType()); 1819637a1ae8STimm Baeder const Pointer &Arg = S.Stk.peek<Pointer>(); 1820637a1ae8STimm Baeder assert(Arg.getFieldDesc()->isPrimitiveArray()); 1821637a1ae8STimm Baeder const Pointer &Dst = S.Stk.peek<Pointer>(primSize(PT_Ptr) * 2); 1822637a1ae8STimm Baeder assert(Dst.getFieldDesc()->isPrimitiveArray()); 1823637a1ae8STimm Baeder assert(Arg.getFieldDesc()->getNumElems() == 1824637a1ae8STimm Baeder Dst.getFieldDesc()->getNumElems()); 1825637a1ae8STimm Baeder 1826637a1ae8STimm Baeder QualType ElemType = Arg.getFieldDesc()->getElemQualType(); 1827637a1ae8STimm Baeder PrimType ElemT = *S.getContext().classify(ElemType); 1828637a1ae8STimm Baeder unsigned NumElems = Arg.getNumElems(); 1829637a1ae8STimm Baeder 1830637a1ae8STimm Baeder // FIXME: Reading from uninitialized vector elements? 1831637a1ae8STimm Baeder for (unsigned I = 0; I != NumElems; ++I) { 1832637a1ae8STimm Baeder INT_TYPE_SWITCH_NO_BOOL(ElemT, { 1833637a1ae8STimm Baeder Dst.atIndex(I).deref<T>() = 1834637a1ae8STimm Baeder T::from(Arg.atIndex(I).deref<T>().toAPSInt().popcount()); 18350f4dc427STimm Baeder Dst.atIndex(I).initialize(); 1836637a1ae8STimm Baeder }); 1837637a1ae8STimm Baeder } 1838637a1ae8STimm Baeder 1839637a1ae8STimm Baeder return true; 1840637a1ae8STimm Baeder } 18418713914dSTimm Baeder 18420611fdd3STimm Baeder static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC, 18430611fdd3STimm Baeder const InterpFrame *Frame, 18440611fdd3STimm Baeder const Function *Func, const CallExpr *Call) { 18450611fdd3STimm Baeder assert(Call->getNumArgs() == 3); 1846dac9736dSTimm Baeder unsigned ID = Func->getBuiltinID(); 18470611fdd3STimm Baeder Pointer DestPtr = getParam<Pointer>(Frame, 0); 1848f0d60170STimm Baeder const ASTContext &ASTCtx = S.getASTContext(); 18490611fdd3STimm Baeder const Pointer &SrcPtr = getParam<Pointer>(Frame, 1); 18500611fdd3STimm Baeder const APSInt &Size = 18510611fdd3STimm Baeder peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2))); 18520611fdd3STimm Baeder assert(!Size.isSigned() && "memcpy and friends take an unsigned size"); 18530611fdd3STimm Baeder 185478955136STimm Baeder if (ID == Builtin::BImemcpy || ID == Builtin::BImemmove) 1855dac9736dSTimm Baeder diagnoseNonConstexprBuiltin(S, OpPC, ID); 1856dac9736dSTimm Baeder 185778955136STimm Baeder bool Move = (ID == Builtin::BI__builtin_memmove || ID == Builtin::BImemmove); 185878955136STimm Baeder 18590611fdd3STimm Baeder // If the size is zero, we treat this as always being a valid no-op. 18600611fdd3STimm Baeder if (Size.isZero()) { 18610611fdd3STimm Baeder S.Stk.push<Pointer>(DestPtr); 18620611fdd3STimm Baeder return true; 18630611fdd3STimm Baeder } 18640611fdd3STimm Baeder 1865fc9052eeSTimm Baeder if (SrcPtr.isZero() || DestPtr.isZero()) { 1866fc9052eeSTimm Baeder Pointer DiagPtr = (SrcPtr.isZero() ? SrcPtr : DestPtr); 1867fc9052eeSTimm Baeder S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null) 186878955136STimm Baeder << /*IsMove=*/Move << /*IsWchar=*/false << !SrcPtr.isZero() 1869f0d60170STimm Baeder << DiagPtr.toDiagnosticString(ASTCtx); 1870fc9052eeSTimm Baeder return false; 1871fc9052eeSTimm Baeder } 1872fc9052eeSTimm Baeder 187345e874e3STimm Baeder // Can't read from dummy pointers. 187445e874e3STimm Baeder if (DestPtr.isDummy() || SrcPtr.isDummy()) 187545e874e3STimm Baeder return false; 187645e874e3STimm Baeder 1877f0d60170STimm Baeder QualType DestElemType; 1878f0d60170STimm Baeder size_t RemainingDestElems; 1879f0d60170STimm Baeder if (DestPtr.getFieldDesc()->isArray()) { 1880f0d60170STimm Baeder DestElemType = DestPtr.getFieldDesc()->getElemQualType(); 188134097c07STimm Baeder RemainingDestElems = DestPtr.isUnknownSizeArray() 188234097c07STimm Baeder ? 0 188334097c07STimm Baeder : (DestPtr.getNumElems() - DestPtr.getIndex()); 1884f0d60170STimm Baeder } else { 1885f0d60170STimm Baeder DestElemType = DestPtr.getType(); 1886f0d60170STimm Baeder RemainingDestElems = 1; 1887f0d60170STimm Baeder } 1888f0d60170STimm Baeder unsigned DestElemSize = ASTCtx.getTypeSizeInChars(DestElemType).getQuantity(); 18896168739fSTimm Baeder 1890f0d60170STimm Baeder if (Size.urem(DestElemSize) != 0) { 18916168739fSTimm Baeder S.FFDiag(S.Current->getSource(OpPC), 18926168739fSTimm Baeder diag::note_constexpr_memcpy_unsupported) 1893f0d60170STimm Baeder << Move << /*IsWchar=*/false << 0 << DestElemType << Size 1894f0d60170STimm Baeder << DestElemSize; 18956168739fSTimm Baeder return false; 18966168739fSTimm Baeder } 18976168739fSTimm Baeder 18981f2d9345STimm Baeder QualType SrcElemType; 1899f0d60170STimm Baeder size_t RemainingSrcElems; 1900f0d60170STimm Baeder if (SrcPtr.getFieldDesc()->isArray()) { 19011f2d9345STimm Baeder SrcElemType = SrcPtr.getFieldDesc()->getElemQualType(); 190234097c07STimm Baeder RemainingSrcElems = SrcPtr.isUnknownSizeArray() 190334097c07STimm Baeder ? 0 190434097c07STimm Baeder : (SrcPtr.getNumElems() - SrcPtr.getIndex()); 1905f0d60170STimm Baeder } else { 19061f2d9345STimm Baeder SrcElemType = SrcPtr.getType(); 1907f0d60170STimm Baeder RemainingSrcElems = 1; 1908f0d60170STimm Baeder } 1909f0d60170STimm Baeder unsigned SrcElemSize = ASTCtx.getTypeSizeInChars(SrcElemType).getQuantity(); 19101f2d9345STimm Baeder 1911f0d60170STimm Baeder if (!ASTCtx.hasSameUnqualifiedType(DestElemType, SrcElemType)) { 19121f2d9345STimm Baeder S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_type_pun) 1913f0d60170STimm Baeder << Move << SrcElemType << DestElemType; 1914f0d60170STimm Baeder return false; 1915f0d60170STimm Baeder } 1916f0d60170STimm Baeder 1917f0d60170STimm Baeder // Check if we have enough elements to read from and write to/ 1918f0d60170STimm Baeder size_t RemainingDestBytes = RemainingDestElems * DestElemSize; 1919f0d60170STimm Baeder size_t RemainingSrcBytes = RemainingSrcElems * SrcElemSize; 1920f0d60170STimm Baeder if (Size.ugt(RemainingDestBytes) || Size.ugt(RemainingSrcBytes)) { 1921f0d60170STimm Baeder APInt N = Size.udiv(DestElemSize); 1922f0d60170STimm Baeder S.FFDiag(S.Current->getSource(OpPC), 1923f0d60170STimm Baeder diag::note_constexpr_memcpy_unsupported) 1924f0d60170STimm Baeder << Move << /*IsWChar*/ false << (Size.ugt(RemainingSrcBytes) ? 1 : 2) 1925f0d60170STimm Baeder << DestElemType << toString(N, 10, /*Signed=*/false); 19261f2d9345STimm Baeder return false; 19271f2d9345STimm Baeder } 19281f2d9345STimm Baeder 19294dde52d7STimm Baeder // Check for overlapping memory regions. 1930d416cae1STimm Baeder if (!Move && Pointer::pointToSameBlock(SrcPtr, DestPtr)) { 19314dde52d7STimm Baeder unsigned SrcIndex = SrcPtr.getIndex() * SrcPtr.elemSize(); 19324dde52d7STimm Baeder unsigned DstIndex = DestPtr.getIndex() * DestPtr.elemSize(); 19334dde52d7STimm Baeder unsigned N = Size.getZExtValue(); 19344dde52d7STimm Baeder 19354dde52d7STimm Baeder if ((SrcIndex <= DstIndex && (SrcIndex + N) > DstIndex) || 19364dde52d7STimm Baeder (DstIndex <= SrcIndex && (DstIndex + N) > SrcIndex)) { 19374dde52d7STimm Baeder S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_overlap) 19384dde52d7STimm Baeder << /*IsWChar=*/false; 19394dde52d7STimm Baeder return false; 19404dde52d7STimm Baeder } 19414dde52d7STimm Baeder } 19424dde52d7STimm Baeder 1943f0d60170STimm Baeder assert(Size.getZExtValue() % DestElemSize == 0); 19441f2d9345STimm Baeder if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size.getZExtValue()).toBits())) 19450611fdd3STimm Baeder return false; 19460611fdd3STimm Baeder 19470611fdd3STimm Baeder S.Stk.push<Pointer>(DestPtr); 19480611fdd3STimm Baeder return true; 19490611fdd3STimm Baeder } 19500611fdd3STimm Baeder 19518713914dSTimm Baeder /// Determine if T is a character type for which we guarantee that 19528713914dSTimm Baeder /// sizeof(T) == 1. 19538713914dSTimm Baeder static bool isOneByteCharacterType(QualType T) { 19548713914dSTimm Baeder return T->isCharType() || T->isChar8Type(); 19558713914dSTimm Baeder } 19568713914dSTimm Baeder 19578713914dSTimm Baeder static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC, 19588713914dSTimm Baeder const InterpFrame *Frame, 19598713914dSTimm Baeder const Function *Func, const CallExpr *Call) { 19608713914dSTimm Baeder assert(Call->getNumArgs() == 3); 19618713914dSTimm Baeder unsigned ID = Func->getBuiltinID(); 19628713914dSTimm Baeder const Pointer &PtrA = getParam<Pointer>(Frame, 0); 19638713914dSTimm Baeder const Pointer &PtrB = getParam<Pointer>(Frame, 1); 19648713914dSTimm Baeder const APSInt &Size = 19658713914dSTimm Baeder peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2))); 19668713914dSTimm Baeder 1967dd6f6a09STimm Baeder if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp || 1968dd6f6a09STimm Baeder ID == Builtin::BIwmemcmp) 19698713914dSTimm Baeder diagnoseNonConstexprBuiltin(S, OpPC, ID); 19708713914dSTimm Baeder 19718713914dSTimm Baeder if (Size.isZero()) { 19728713914dSTimm Baeder pushInteger(S, 0, Call->getType()); 19738713914dSTimm Baeder return true; 19748713914dSTimm Baeder } 19758713914dSTimm Baeder 1976dd6f6a09STimm Baeder bool IsWide = 1977dd6f6a09STimm Baeder (ID == Builtin::BIwmemcmp || ID == Builtin::BI__builtin_wmemcmp); 1978dd6f6a09STimm Baeder 1979dd6f6a09STimm Baeder const ASTContext &ASTCtx = S.getASTContext(); 19808713914dSTimm Baeder // FIXME: This is an arbitrary limitation the current constant interpreter 19818713914dSTimm Baeder // had. We could remove this. 1982dd6f6a09STimm Baeder if (!IsWide && (!isOneByteCharacterType(PtrA.getType()) || 1983dd6f6a09STimm Baeder !isOneByteCharacterType(PtrB.getType()))) { 19848713914dSTimm Baeder S.FFDiag(S.Current->getSource(OpPC), 19858713914dSTimm Baeder diag::note_constexpr_memcmp_unsupported) 1986dc3cd2e9SChandler Carruth << ASTCtx.BuiltinInfo.getQuotedName(ID) << PtrA.getType() 1987dd6f6a09STimm Baeder << PtrB.getType(); 19888713914dSTimm Baeder return false; 19898713914dSTimm Baeder } 19908713914dSTimm Baeder 19918713914dSTimm Baeder if (PtrA.isDummy() || PtrB.isDummy()) 19928713914dSTimm Baeder return false; 19938713914dSTimm Baeder 19948713914dSTimm Baeder // Now, read both pointers to a buffer and compare those. 19958713914dSTimm Baeder BitcastBuffer BufferA( 1996dd6f6a09STimm Baeder Bits(ASTCtx.getTypeSize(PtrA.getFieldDesc()->getType()))); 19978713914dSTimm Baeder readPointerToBuffer(S.getContext(), PtrA, BufferA, false); 199830cbd09fSTimm Baeder // FIXME: The swapping here is UNDOING something we do when reading the 199930cbd09fSTimm Baeder // data into the buffer. 2000dd6f6a09STimm Baeder if (ASTCtx.getTargetInfo().isBigEndian()) 200130cbd09fSTimm Baeder swapBytes(BufferA.Data.get(), BufferA.byteSize().getQuantity()); 20028713914dSTimm Baeder 20038713914dSTimm Baeder BitcastBuffer BufferB( 2004dd6f6a09STimm Baeder Bits(ASTCtx.getTypeSize(PtrB.getFieldDesc()->getType()))); 20058713914dSTimm Baeder readPointerToBuffer(S.getContext(), PtrB, BufferB, false); 200630cbd09fSTimm Baeder // FIXME: The swapping here is UNDOING something we do when reading the 200730cbd09fSTimm Baeder // data into the buffer. 2008dd6f6a09STimm Baeder if (ASTCtx.getTargetInfo().isBigEndian()) 200930cbd09fSTimm Baeder swapBytes(BufferB.Data.get(), BufferB.byteSize().getQuantity()); 20108713914dSTimm Baeder 20118713914dSTimm Baeder size_t MinBufferSize = std::min(BufferA.byteSize().getQuantity(), 20128713914dSTimm Baeder BufferB.byteSize().getQuantity()); 20138713914dSTimm Baeder 2014dd6f6a09STimm Baeder unsigned ElemSize = 1; 2015dd6f6a09STimm Baeder if (IsWide) 2016dd6f6a09STimm Baeder ElemSize = ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity(); 2017dd6f6a09STimm Baeder // The Size given for the wide variants is in wide-char units. Convert it 2018dd6f6a09STimm Baeder // to bytes. 2019dd6f6a09STimm Baeder size_t ByteSize = Size.getZExtValue() * ElemSize; 2020dd6f6a09STimm Baeder size_t CmpSize = std::min(MinBufferSize, ByteSize); 2021dd6f6a09STimm Baeder 2022dd6f6a09STimm Baeder for (size_t I = 0; I != CmpSize; I += ElemSize) { 2023dd6f6a09STimm Baeder if (IsWide) { 2024dd6f6a09STimm Baeder INT_TYPE_SWITCH(*S.getContext().classify(ASTCtx.getWCharType()), { 2025dd6f6a09STimm Baeder T A = *reinterpret_cast<T *>(BufferA.Data.get() + I); 2026dd6f6a09STimm Baeder T B = *reinterpret_cast<T *>(BufferB.Data.get() + I); 2027dd6f6a09STimm Baeder if (A < B) { 2028dd6f6a09STimm Baeder pushInteger(S, -1, Call->getType()); 2029dd6f6a09STimm Baeder return true; 2030dd6f6a09STimm Baeder } else if (A > B) { 2031dd6f6a09STimm Baeder pushInteger(S, 1, Call->getType()); 2032dd6f6a09STimm Baeder return true; 2033dd6f6a09STimm Baeder } 2034dd6f6a09STimm Baeder }); 2035dd6f6a09STimm Baeder } else { 203698470c0bSTimm Baeder std::byte A = BufferA.Data[I]; 203798470c0bSTimm Baeder std::byte B = BufferB.Data[I]; 203898470c0bSTimm Baeder 203998470c0bSTimm Baeder if (A < B) { 204098470c0bSTimm Baeder pushInteger(S, -1, Call->getType()); 20418713914dSTimm Baeder return true; 204298470c0bSTimm Baeder } else if (A > B) { 204398470c0bSTimm Baeder pushInteger(S, 1, Call->getType()); 204498470c0bSTimm Baeder return true; 204598470c0bSTimm Baeder } 204698470c0bSTimm Baeder } 2047dd6f6a09STimm Baeder } 204898470c0bSTimm Baeder 204998470c0bSTimm Baeder // We compared CmpSize bytes above. If the limiting factor was the Size 205098470c0bSTimm Baeder // passed, we're done and the result is equality (0). 2051dd6f6a09STimm Baeder if (ByteSize <= CmpSize) { 205298470c0bSTimm Baeder pushInteger(S, 0, Call->getType()); 205398470c0bSTimm Baeder return true; 205498470c0bSTimm Baeder } 205598470c0bSTimm Baeder 205698470c0bSTimm Baeder // However, if we read all the available bytes but were instructed to read 205798470c0bSTimm Baeder // even more, diagnose this as a "read of dereferenced one-past-the-end 205898470c0bSTimm Baeder // pointer". This is what would happen if we called CheckRead() on every array 205998470c0bSTimm Baeder // element. 206098470c0bSTimm Baeder S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end) 206198470c0bSTimm Baeder << AK_Read << S.Current->getRange(OpPC); 206298470c0bSTimm Baeder return false; 20638713914dSTimm Baeder } 20648713914dSTimm Baeder 2065a07aba5dSTimm Baeder bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, 206678cf9b83STimm Baeder const CallExpr *Call, uint32_t BuiltinID) { 2067a07aba5dSTimm Baeder const InterpFrame *Frame = S.Current; 2068a07aba5dSTimm Baeder 2069a07aba5dSTimm Baeder std::optional<PrimType> ReturnT = S.getContext().classify(Call); 2070a07aba5dSTimm Baeder 207178cf9b83STimm Baeder switch (BuiltinID) { 2072a07aba5dSTimm Baeder case Builtin::BI__builtin_is_constant_evaluated: 2073a07aba5dSTimm Baeder if (!interp__builtin_is_constant_evaluated(S, OpPC, Frame, Call)) 2074a07aba5dSTimm Baeder return false; 2075a07aba5dSTimm Baeder break; 2076a07aba5dSTimm Baeder case Builtin::BI__builtin_assume: 2077a07aba5dSTimm Baeder case Builtin::BI__assume: 2078a07aba5dSTimm Baeder break; 2079a07aba5dSTimm Baeder case Builtin::BI__builtin_strcmp: 208046446bb2STimm Baeder case Builtin::BIstrcmp: 2081d17e51f3STimm Baeder case Builtin::BI__builtin_strncmp: 2082d17e51f3STimm Baeder case Builtin::BIstrncmp: 208346446bb2STimm Baeder if (!interp__builtin_strcmp(S, OpPC, Frame, F, Call)) 2084a07aba5dSTimm Baeder return false; 2085a07aba5dSTimm Baeder break; 2086a07aba5dSTimm Baeder case Builtin::BI__builtin_strlen: 2087dac9736dSTimm Baeder case Builtin::BIstrlen: 208800b50c91STimm Baeder case Builtin::BI__builtin_wcslen: 208900b50c91STimm Baeder case Builtin::BIwcslen: 2090dac9736dSTimm Baeder if (!interp__builtin_strlen(S, OpPC, Frame, F, Call)) 2091a07aba5dSTimm Baeder return false; 2092a07aba5dSTimm Baeder break; 2093a07aba5dSTimm Baeder case Builtin::BI__builtin_nan: 2094a07aba5dSTimm Baeder case Builtin::BI__builtin_nanf: 2095a07aba5dSTimm Baeder case Builtin::BI__builtin_nanl: 2096a07aba5dSTimm Baeder case Builtin::BI__builtin_nanf16: 2097a07aba5dSTimm Baeder case Builtin::BI__builtin_nanf128: 2098a07aba5dSTimm Baeder if (!interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/false)) 2099a07aba5dSTimm Baeder return false; 2100a07aba5dSTimm Baeder break; 2101a07aba5dSTimm Baeder case Builtin::BI__builtin_nans: 2102a07aba5dSTimm Baeder case Builtin::BI__builtin_nansf: 2103a07aba5dSTimm Baeder case Builtin::BI__builtin_nansl: 2104a07aba5dSTimm Baeder case Builtin::BI__builtin_nansf16: 2105a07aba5dSTimm Baeder case Builtin::BI__builtin_nansf128: 2106a07aba5dSTimm Baeder if (!interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/true)) 2107a07aba5dSTimm Baeder return false; 2108a07aba5dSTimm Baeder break; 2109a07aba5dSTimm Baeder 2110a07aba5dSTimm Baeder case Builtin::BI__builtin_huge_val: 2111a07aba5dSTimm Baeder case Builtin::BI__builtin_huge_valf: 2112a07aba5dSTimm Baeder case Builtin::BI__builtin_huge_vall: 2113a07aba5dSTimm Baeder case Builtin::BI__builtin_huge_valf16: 2114a07aba5dSTimm Baeder case Builtin::BI__builtin_huge_valf128: 2115a07aba5dSTimm Baeder case Builtin::BI__builtin_inf: 2116a07aba5dSTimm Baeder case Builtin::BI__builtin_inff: 2117a07aba5dSTimm Baeder case Builtin::BI__builtin_infl: 2118a07aba5dSTimm Baeder case Builtin::BI__builtin_inff16: 2119a07aba5dSTimm Baeder case Builtin::BI__builtin_inff128: 2120a07aba5dSTimm Baeder if (!interp__builtin_inf(S, OpPC, Frame, F)) 2121a07aba5dSTimm Baeder return false; 2122a07aba5dSTimm Baeder break; 2123a07aba5dSTimm Baeder case Builtin::BI__builtin_copysign: 2124a07aba5dSTimm Baeder case Builtin::BI__builtin_copysignf: 2125a07aba5dSTimm Baeder case Builtin::BI__builtin_copysignl: 2126a07aba5dSTimm Baeder case Builtin::BI__builtin_copysignf128: 2127a07aba5dSTimm Baeder if (!interp__builtin_copysign(S, OpPC, Frame, F)) 2128a07aba5dSTimm Baeder return false; 2129a07aba5dSTimm Baeder break; 2130a07aba5dSTimm Baeder 2131a07aba5dSTimm Baeder case Builtin::BI__builtin_fmin: 2132a07aba5dSTimm Baeder case Builtin::BI__builtin_fminf: 2133a07aba5dSTimm Baeder case Builtin::BI__builtin_fminl: 2134a07aba5dSTimm Baeder case Builtin::BI__builtin_fminf16: 2135a07aba5dSTimm Baeder case Builtin::BI__builtin_fminf128: 2136790d9869STimm Baeder if (!interp__builtin_fmin(S, OpPC, Frame, F, /*IsNumBuiltin=*/false)) 2137790d9869STimm Baeder return false; 2138790d9869STimm Baeder break; 2139790d9869STimm Baeder 2140790d9869STimm Baeder case Builtin::BI__builtin_fminimum_num: 2141790d9869STimm Baeder case Builtin::BI__builtin_fminimum_numf: 2142790d9869STimm Baeder case Builtin::BI__builtin_fminimum_numl: 2143790d9869STimm Baeder case Builtin::BI__builtin_fminimum_numf16: 2144790d9869STimm Baeder case Builtin::BI__builtin_fminimum_numf128: 2145790d9869STimm Baeder if (!interp__builtin_fmin(S, OpPC, Frame, F, /*IsNumBuiltin=*/true)) 2146a07aba5dSTimm Baeder return false; 2147a07aba5dSTimm Baeder break; 2148a07aba5dSTimm Baeder 2149a07aba5dSTimm Baeder case Builtin::BI__builtin_fmax: 2150a07aba5dSTimm Baeder case Builtin::BI__builtin_fmaxf: 2151a07aba5dSTimm Baeder case Builtin::BI__builtin_fmaxl: 2152a07aba5dSTimm Baeder case Builtin::BI__builtin_fmaxf16: 2153a07aba5dSTimm Baeder case Builtin::BI__builtin_fmaxf128: 2154790d9869STimm Baeder if (!interp__builtin_fmax(S, OpPC, Frame, F, /*IsNumBuiltin=*/false)) 2155790d9869STimm Baeder return false; 2156790d9869STimm Baeder break; 2157790d9869STimm Baeder 2158790d9869STimm Baeder case Builtin::BI__builtin_fmaximum_num: 2159790d9869STimm Baeder case Builtin::BI__builtin_fmaximum_numf: 2160790d9869STimm Baeder case Builtin::BI__builtin_fmaximum_numl: 2161790d9869STimm Baeder case Builtin::BI__builtin_fmaximum_numf16: 2162790d9869STimm Baeder case Builtin::BI__builtin_fmaximum_numf128: 2163790d9869STimm Baeder if (!interp__builtin_fmax(S, OpPC, Frame, F, /*IsNumBuiltin=*/true)) 2164a07aba5dSTimm Baeder return false; 2165a07aba5dSTimm Baeder break; 2166a07aba5dSTimm Baeder 2167a07aba5dSTimm Baeder case Builtin::BI__builtin_isnan: 2168a07aba5dSTimm Baeder if (!interp__builtin_isnan(S, OpPC, Frame, F, Call)) 2169a07aba5dSTimm Baeder return false; 2170a07aba5dSTimm Baeder break; 2171a07aba5dSTimm Baeder case Builtin::BI__builtin_issignaling: 2172a07aba5dSTimm Baeder if (!interp__builtin_issignaling(S, OpPC, Frame, F, Call)) 2173a07aba5dSTimm Baeder return false; 2174a07aba5dSTimm Baeder break; 2175a07aba5dSTimm Baeder 2176a07aba5dSTimm Baeder case Builtin::BI__builtin_isinf: 2177a07aba5dSTimm Baeder if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false, Call)) 2178a07aba5dSTimm Baeder return false; 2179a07aba5dSTimm Baeder break; 2180a07aba5dSTimm Baeder 2181a07aba5dSTimm Baeder case Builtin::BI__builtin_isinf_sign: 2182a07aba5dSTimm Baeder if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true, Call)) 2183a07aba5dSTimm Baeder return false; 2184a07aba5dSTimm Baeder break; 2185a07aba5dSTimm Baeder 2186a07aba5dSTimm Baeder case Builtin::BI__builtin_isfinite: 2187a07aba5dSTimm Baeder if (!interp__builtin_isfinite(S, OpPC, Frame, F, Call)) 2188a07aba5dSTimm Baeder return false; 2189a07aba5dSTimm Baeder break; 2190a07aba5dSTimm Baeder case Builtin::BI__builtin_isnormal: 2191a07aba5dSTimm Baeder if (!interp__builtin_isnormal(S, OpPC, Frame, F, Call)) 2192a07aba5dSTimm Baeder return false; 2193a07aba5dSTimm Baeder break; 2194a07aba5dSTimm Baeder case Builtin::BI__builtin_issubnormal: 2195a07aba5dSTimm Baeder if (!interp__builtin_issubnormal(S, OpPC, Frame, F, Call)) 2196a07aba5dSTimm Baeder return false; 2197a07aba5dSTimm Baeder break; 2198a07aba5dSTimm Baeder case Builtin::BI__builtin_iszero: 2199a07aba5dSTimm Baeder if (!interp__builtin_iszero(S, OpPC, Frame, F, Call)) 2200a07aba5dSTimm Baeder return false; 2201a07aba5dSTimm Baeder break; 220211259343SMital Ashok case Builtin::BI__builtin_signbit: 220311259343SMital Ashok case Builtin::BI__builtin_signbitf: 220411259343SMital Ashok case Builtin::BI__builtin_signbitl: 220511259343SMital Ashok if (!interp__builtin_signbit(S, OpPC, Frame, F, Call)) 220611259343SMital Ashok return false; 220711259343SMital Ashok break; 220811259343SMital Ashok case Builtin::BI__builtin_isgreater: 220911259343SMital Ashok case Builtin::BI__builtin_isgreaterequal: 221011259343SMital Ashok case Builtin::BI__builtin_isless: 221111259343SMital Ashok case Builtin::BI__builtin_islessequal: 221211259343SMital Ashok case Builtin::BI__builtin_islessgreater: 221311259343SMital Ashok case Builtin::BI__builtin_isunordered: 221411259343SMital Ashok if (!interp_floating_comparison(S, OpPC, Frame, F, Call)) 221511259343SMital Ashok return false; 221611259343SMital Ashok break; 2217a07aba5dSTimm Baeder case Builtin::BI__builtin_isfpclass: 2218a07aba5dSTimm Baeder if (!interp__builtin_isfpclass(S, OpPC, Frame, F, Call)) 2219a07aba5dSTimm Baeder return false; 2220a07aba5dSTimm Baeder break; 2221a07aba5dSTimm Baeder case Builtin::BI__builtin_fpclassify: 2222a07aba5dSTimm Baeder if (!interp__builtin_fpclassify(S, OpPC, Frame, F, Call)) 2223a07aba5dSTimm Baeder return false; 2224a07aba5dSTimm Baeder break; 2225a07aba5dSTimm Baeder 2226a07aba5dSTimm Baeder case Builtin::BI__builtin_fabs: 2227a07aba5dSTimm Baeder case Builtin::BI__builtin_fabsf: 2228a07aba5dSTimm Baeder case Builtin::BI__builtin_fabsl: 2229a07aba5dSTimm Baeder case Builtin::BI__builtin_fabsf128: 2230a07aba5dSTimm Baeder if (!interp__builtin_fabs(S, OpPC, Frame, F)) 2231a07aba5dSTimm Baeder return false; 2232a07aba5dSTimm Baeder break; 2233a07aba5dSTimm Baeder 2234332ac18eSc8ef case Builtin::BI__builtin_abs: 2235332ac18eSc8ef case Builtin::BI__builtin_labs: 2236332ac18eSc8ef case Builtin::BI__builtin_llabs: 2237332ac18eSc8ef if (!interp__builtin_abs(S, OpPC, Frame, F, Call)) 2238332ac18eSc8ef return false; 2239332ac18eSc8ef break; 2240332ac18eSc8ef 2241a07aba5dSTimm Baeder case Builtin::BI__builtin_popcount: 2242a07aba5dSTimm Baeder case Builtin::BI__builtin_popcountl: 2243a07aba5dSTimm Baeder case Builtin::BI__builtin_popcountll: 2244a07aba5dSTimm Baeder case Builtin::BI__builtin_popcountg: 2245a07aba5dSTimm Baeder case Builtin::BI__popcnt16: // Microsoft variants of popcount 2246a07aba5dSTimm Baeder case Builtin::BI__popcnt: 2247a07aba5dSTimm Baeder case Builtin::BI__popcnt64: 2248a07aba5dSTimm Baeder if (!interp__builtin_popcount(S, OpPC, Frame, F, Call)) 2249a07aba5dSTimm Baeder return false; 2250a07aba5dSTimm Baeder break; 2251a07aba5dSTimm Baeder 2252a07aba5dSTimm Baeder case Builtin::BI__builtin_parity: 2253a07aba5dSTimm Baeder case Builtin::BI__builtin_parityl: 2254a07aba5dSTimm Baeder case Builtin::BI__builtin_parityll: 2255a07aba5dSTimm Baeder if (!interp__builtin_parity(S, OpPC, Frame, F, Call)) 2256a07aba5dSTimm Baeder return false; 2257a07aba5dSTimm Baeder break; 2258a07aba5dSTimm Baeder 2259a07aba5dSTimm Baeder case Builtin::BI__builtin_clrsb: 2260a07aba5dSTimm Baeder case Builtin::BI__builtin_clrsbl: 2261a07aba5dSTimm Baeder case Builtin::BI__builtin_clrsbll: 2262a07aba5dSTimm Baeder if (!interp__builtin_clrsb(S, OpPC, Frame, F, Call)) 2263a07aba5dSTimm Baeder return false; 2264a07aba5dSTimm Baeder break; 2265a07aba5dSTimm Baeder 2266a07aba5dSTimm Baeder case Builtin::BI__builtin_bitreverse8: 2267a07aba5dSTimm Baeder case Builtin::BI__builtin_bitreverse16: 2268a07aba5dSTimm Baeder case Builtin::BI__builtin_bitreverse32: 2269a07aba5dSTimm Baeder case Builtin::BI__builtin_bitreverse64: 2270a07aba5dSTimm Baeder if (!interp__builtin_bitreverse(S, OpPC, Frame, F, Call)) 2271a07aba5dSTimm Baeder return false; 2272a07aba5dSTimm Baeder break; 2273a07aba5dSTimm Baeder 2274a07aba5dSTimm Baeder case Builtin::BI__builtin_classify_type: 2275a07aba5dSTimm Baeder if (!interp__builtin_classify_type(S, OpPC, Frame, F, Call)) 2276a07aba5dSTimm Baeder return false; 2277a07aba5dSTimm Baeder break; 2278a07aba5dSTimm Baeder 2279a07aba5dSTimm Baeder case Builtin::BI__builtin_expect: 2280a07aba5dSTimm Baeder case Builtin::BI__builtin_expect_with_probability: 2281a07aba5dSTimm Baeder if (!interp__builtin_expect(S, OpPC, Frame, F, Call)) 2282a07aba5dSTimm Baeder return false; 2283a07aba5dSTimm Baeder break; 2284a07aba5dSTimm Baeder 2285a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateleft8: 2286a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateleft16: 2287a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateleft32: 2288a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateleft64: 2289a07aba5dSTimm Baeder case Builtin::BI_rotl8: // Microsoft variants of rotate left 2290a07aba5dSTimm Baeder case Builtin::BI_rotl16: 2291a07aba5dSTimm Baeder case Builtin::BI_rotl: 2292a07aba5dSTimm Baeder case Builtin::BI_lrotl: 2293a07aba5dSTimm Baeder case Builtin::BI_rotl64: 2294a07aba5dSTimm Baeder if (!interp__builtin_rotate(S, OpPC, Frame, F, Call, /*Right=*/false)) 2295a07aba5dSTimm Baeder return false; 2296a07aba5dSTimm Baeder break; 2297a07aba5dSTimm Baeder 2298a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateright8: 2299a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateright16: 2300a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateright32: 2301a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateright64: 2302a07aba5dSTimm Baeder case Builtin::BI_rotr8: // Microsoft variants of rotate right 2303a07aba5dSTimm Baeder case Builtin::BI_rotr16: 2304a07aba5dSTimm Baeder case Builtin::BI_rotr: 2305a07aba5dSTimm Baeder case Builtin::BI_lrotr: 2306a07aba5dSTimm Baeder case Builtin::BI_rotr64: 2307a07aba5dSTimm Baeder if (!interp__builtin_rotate(S, OpPC, Frame, F, Call, /*Right=*/true)) 2308a07aba5dSTimm Baeder return false; 2309a07aba5dSTimm Baeder break; 2310a07aba5dSTimm Baeder 2311a07aba5dSTimm Baeder case Builtin::BI__builtin_ffs: 2312a07aba5dSTimm Baeder case Builtin::BI__builtin_ffsl: 2313a07aba5dSTimm Baeder case Builtin::BI__builtin_ffsll: 2314a07aba5dSTimm Baeder if (!interp__builtin_ffs(S, OpPC, Frame, F, Call)) 2315a07aba5dSTimm Baeder return false; 2316a07aba5dSTimm Baeder break; 2317a07aba5dSTimm Baeder case Builtin::BIaddressof: 2318a07aba5dSTimm Baeder case Builtin::BI__addressof: 2319a07aba5dSTimm Baeder case Builtin::BI__builtin_addressof: 2320a07aba5dSTimm Baeder if (!interp__builtin_addressof(S, OpPC, Frame, F, Call)) 2321a07aba5dSTimm Baeder return false; 2322a07aba5dSTimm Baeder break; 2323a07aba5dSTimm Baeder 2324a07aba5dSTimm Baeder case Builtin::BIas_const: 2325a07aba5dSTimm Baeder case Builtin::BIforward: 2326a07aba5dSTimm Baeder case Builtin::BIforward_like: 2327a07aba5dSTimm Baeder case Builtin::BImove: 2328a07aba5dSTimm Baeder case Builtin::BImove_if_noexcept: 2329a07aba5dSTimm Baeder if (!interp__builtin_move(S, OpPC, Frame, F, Call)) 2330a07aba5dSTimm Baeder return false; 2331a07aba5dSTimm Baeder break; 2332a07aba5dSTimm Baeder 2333a07aba5dSTimm Baeder case Builtin::BI__builtin_eh_return_data_regno: 2334a07aba5dSTimm Baeder if (!interp__builtin_eh_return_data_regno(S, OpPC, Frame, F, Call)) 2335a07aba5dSTimm Baeder return false; 2336a07aba5dSTimm Baeder break; 2337a07aba5dSTimm Baeder 2338a07aba5dSTimm Baeder case Builtin::BI__builtin_launder: 2339a07aba5dSTimm Baeder if (!noopPointer(S, OpPC, Frame, F, Call)) 2340a07aba5dSTimm Baeder return false; 2341a07aba5dSTimm Baeder break; 2342a07aba5dSTimm Baeder 2343a07aba5dSTimm Baeder case Builtin::BI__builtin_add_overflow: 2344a07aba5dSTimm Baeder case Builtin::BI__builtin_sub_overflow: 2345a07aba5dSTimm Baeder case Builtin::BI__builtin_mul_overflow: 2346a07aba5dSTimm Baeder case Builtin::BI__builtin_sadd_overflow: 2347a07aba5dSTimm Baeder case Builtin::BI__builtin_uadd_overflow: 2348a07aba5dSTimm Baeder case Builtin::BI__builtin_uaddl_overflow: 2349a07aba5dSTimm Baeder case Builtin::BI__builtin_uaddll_overflow: 2350a07aba5dSTimm Baeder case Builtin::BI__builtin_usub_overflow: 2351a07aba5dSTimm Baeder case Builtin::BI__builtin_usubl_overflow: 2352a07aba5dSTimm Baeder case Builtin::BI__builtin_usubll_overflow: 2353a07aba5dSTimm Baeder case Builtin::BI__builtin_umul_overflow: 2354a07aba5dSTimm Baeder case Builtin::BI__builtin_umull_overflow: 2355a07aba5dSTimm Baeder case Builtin::BI__builtin_umulll_overflow: 2356a07aba5dSTimm Baeder case Builtin::BI__builtin_saddl_overflow: 2357a07aba5dSTimm Baeder case Builtin::BI__builtin_saddll_overflow: 2358a07aba5dSTimm Baeder case Builtin::BI__builtin_ssub_overflow: 2359a07aba5dSTimm Baeder case Builtin::BI__builtin_ssubl_overflow: 2360a07aba5dSTimm Baeder case Builtin::BI__builtin_ssubll_overflow: 2361a07aba5dSTimm Baeder case Builtin::BI__builtin_smul_overflow: 2362a07aba5dSTimm Baeder case Builtin::BI__builtin_smull_overflow: 2363a07aba5dSTimm Baeder case Builtin::BI__builtin_smulll_overflow: 2364a07aba5dSTimm Baeder if (!interp__builtin_overflowop(S, OpPC, Frame, F, Call)) 2365a07aba5dSTimm Baeder return false; 2366a07aba5dSTimm Baeder break; 2367a07aba5dSTimm Baeder 2368a07aba5dSTimm Baeder case Builtin::BI__builtin_addcb: 2369a07aba5dSTimm Baeder case Builtin::BI__builtin_addcs: 2370a07aba5dSTimm Baeder case Builtin::BI__builtin_addc: 2371a07aba5dSTimm Baeder case Builtin::BI__builtin_addcl: 2372a07aba5dSTimm Baeder case Builtin::BI__builtin_addcll: 2373a07aba5dSTimm Baeder case Builtin::BI__builtin_subcb: 2374a07aba5dSTimm Baeder case Builtin::BI__builtin_subcs: 2375a07aba5dSTimm Baeder case Builtin::BI__builtin_subc: 2376a07aba5dSTimm Baeder case Builtin::BI__builtin_subcl: 2377a07aba5dSTimm Baeder case Builtin::BI__builtin_subcll: 2378a07aba5dSTimm Baeder if (!interp__builtin_carryop(S, OpPC, Frame, F, Call)) 2379a07aba5dSTimm Baeder return false; 2380a07aba5dSTimm Baeder break; 2381a07aba5dSTimm Baeder 2382a07aba5dSTimm Baeder case Builtin::BI__builtin_clz: 2383a07aba5dSTimm Baeder case Builtin::BI__builtin_clzl: 2384a07aba5dSTimm Baeder case Builtin::BI__builtin_clzll: 2385a07aba5dSTimm Baeder case Builtin::BI__builtin_clzs: 2386a07aba5dSTimm Baeder case Builtin::BI__builtin_clzg: 2387a07aba5dSTimm Baeder case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes 2388a07aba5dSTimm Baeder case Builtin::BI__lzcnt: 2389a07aba5dSTimm Baeder case Builtin::BI__lzcnt64: 2390a07aba5dSTimm Baeder if (!interp__builtin_clz(S, OpPC, Frame, F, Call)) 2391a07aba5dSTimm Baeder return false; 2392a07aba5dSTimm Baeder break; 2393a07aba5dSTimm Baeder 2394a07aba5dSTimm Baeder case Builtin::BI__builtin_ctz: 2395a07aba5dSTimm Baeder case Builtin::BI__builtin_ctzl: 2396a07aba5dSTimm Baeder case Builtin::BI__builtin_ctzll: 2397a07aba5dSTimm Baeder case Builtin::BI__builtin_ctzs: 2398a07aba5dSTimm Baeder case Builtin::BI__builtin_ctzg: 2399a07aba5dSTimm Baeder if (!interp__builtin_ctz(S, OpPC, Frame, F, Call)) 2400a07aba5dSTimm Baeder return false; 2401a07aba5dSTimm Baeder break; 2402a07aba5dSTimm Baeder 2403a07aba5dSTimm Baeder case Builtin::BI__builtin_bswap16: 2404a07aba5dSTimm Baeder case Builtin::BI__builtin_bswap32: 2405a07aba5dSTimm Baeder case Builtin::BI__builtin_bswap64: 2406a07aba5dSTimm Baeder if (!interp__builtin_bswap(S, OpPC, Frame, F, Call)) 2407a07aba5dSTimm Baeder return false; 2408a07aba5dSTimm Baeder break; 2409a07aba5dSTimm Baeder 2410a07aba5dSTimm Baeder case Builtin::BI__atomic_always_lock_free: 2411a07aba5dSTimm Baeder case Builtin::BI__atomic_is_lock_free: 2412a07aba5dSTimm Baeder case Builtin::BI__c11_atomic_is_lock_free: 2413a07aba5dSTimm Baeder if (!interp__builtin_atomic_lock_free(S, OpPC, Frame, F, Call)) 2414a07aba5dSTimm Baeder return false; 2415a07aba5dSTimm Baeder break; 2416a07aba5dSTimm Baeder 2417a07aba5dSTimm Baeder case Builtin::BI__builtin_complex: 2418a07aba5dSTimm Baeder if (!interp__builtin_complex(S, OpPC, Frame, F, Call)) 2419a07aba5dSTimm Baeder return false; 2420a07aba5dSTimm Baeder break; 2421a07aba5dSTimm Baeder 2422a07aba5dSTimm Baeder case Builtin::BI__builtin_is_aligned: 2423a07aba5dSTimm Baeder case Builtin::BI__builtin_align_up: 2424a07aba5dSTimm Baeder case Builtin::BI__builtin_align_down: 2425a07aba5dSTimm Baeder if (!interp__builtin_is_aligned_up_down(S, OpPC, Frame, F, Call)) 2426a07aba5dSTimm Baeder return false; 2427a07aba5dSTimm Baeder break; 2428a07aba5dSTimm Baeder 242980c15c48STimm Baeder case Builtin::BI__builtin_assume_aligned: 243080c15c48STimm Baeder if (!interp__builtin_assume_aligned(S, OpPC, Frame, F, Call)) 243180c15c48STimm Baeder return false; 243280c15c48STimm Baeder break; 243380c15c48STimm Baeder 243485181788STimm Baeder case clang::X86::BI__builtin_ia32_bextr_u32: 243585181788STimm Baeder case clang::X86::BI__builtin_ia32_bextr_u64: 243685181788STimm Baeder case clang::X86::BI__builtin_ia32_bextri_u32: 243785181788STimm Baeder case clang::X86::BI__builtin_ia32_bextri_u64: 243885181788STimm Baeder if (!interp__builtin_ia32_bextr(S, OpPC, Frame, F, Call)) 243985181788STimm Baeder return false; 244085181788STimm Baeder break; 244185181788STimm Baeder 24427147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_bzhi_si: 24437147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_bzhi_di: 24447147e88fSTimm Baeder if (!interp__builtin_ia32_bzhi(S, OpPC, Frame, F, Call)) 24457147e88fSTimm Baeder return false; 24467147e88fSTimm Baeder break; 24477147e88fSTimm Baeder 24487147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_lzcnt_u16: 24497147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_lzcnt_u32: 24507147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_lzcnt_u64: 24517147e88fSTimm Baeder if (!interp__builtin_ia32_lzcnt(S, OpPC, Frame, F, Call)) 24527147e88fSTimm Baeder return false; 24537147e88fSTimm Baeder break; 24547147e88fSTimm Baeder 24557147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_tzcnt_u16: 24567147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_tzcnt_u32: 24577147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_tzcnt_u64: 24587147e88fSTimm Baeder if (!interp__builtin_ia32_tzcnt(S, OpPC, Frame, F, Call)) 24597147e88fSTimm Baeder return false; 24607147e88fSTimm Baeder break; 24617147e88fSTimm Baeder 2462f3baa73cSTimm Baeder case clang::X86::BI__builtin_ia32_pdep_si: 2463f3baa73cSTimm Baeder case clang::X86::BI__builtin_ia32_pdep_di: 2464f3baa73cSTimm Baeder if (!interp__builtin_ia32_pdep(S, OpPC, Frame, F, Call)) 2465f3baa73cSTimm Baeder return false; 2466f3baa73cSTimm Baeder break; 2467f3baa73cSTimm Baeder 2468f3baa73cSTimm Baeder case clang::X86::BI__builtin_ia32_pext_si: 2469f3baa73cSTimm Baeder case clang::X86::BI__builtin_ia32_pext_di: 2470f3baa73cSTimm Baeder if (!interp__builtin_ia32_pext(S, OpPC, Frame, F, Call)) 2471f3baa73cSTimm Baeder return false; 2472f3baa73cSTimm Baeder break; 2473f3baa73cSTimm Baeder 24746f8e8551STimm Baeder case clang::X86::BI__builtin_ia32_addcarryx_u32: 24756f8e8551STimm Baeder case clang::X86::BI__builtin_ia32_addcarryx_u64: 24766f8e8551STimm Baeder case clang::X86::BI__builtin_ia32_subborrow_u32: 24776f8e8551STimm Baeder case clang::X86::BI__builtin_ia32_subborrow_u64: 24786f8e8551STimm Baeder if (!interp__builtin_ia32_addcarry_subborrow(S, OpPC, Frame, F, Call)) 24796f8e8551STimm Baeder return false; 24806f8e8551STimm Baeder break; 24816f8e8551STimm Baeder 2482a07aba5dSTimm Baeder case Builtin::BI__builtin_os_log_format_buffer_size: 2483a07aba5dSTimm Baeder if (!interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, F, Call)) 2484a07aba5dSTimm Baeder return false; 2485a07aba5dSTimm Baeder break; 2486a07aba5dSTimm Baeder 2487a07aba5dSTimm Baeder case Builtin::BI__builtin_ptrauth_string_discriminator: 2488a07aba5dSTimm Baeder if (!interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, F, Call)) 2489a07aba5dSTimm Baeder return false; 2490a07aba5dSTimm Baeder break; 2491a07aba5dSTimm Baeder 2492a07aba5dSTimm Baeder case Builtin::BI__builtin_constant_p: 2493a07aba5dSTimm Baeder if (!interp__builtin_constant_p(S, OpPC, Frame, F, Call)) 2494a07aba5dSTimm Baeder return false; 2495a07aba5dSTimm Baeder break; 2496a07aba5dSTimm Baeder 2497f838d6b1STimm Baeder case Builtin::BI__noop: 2498f838d6b1STimm Baeder pushInteger(S, 0, Call->getType()); 2499f838d6b1STimm Baeder break; 2500f838d6b1STimm Baeder 2501610b8539STimm Baeder case Builtin::BI__builtin_operator_new: 2502610b8539STimm Baeder if (!interp__builtin_operator_new(S, OpPC, Frame, F, Call)) 2503610b8539STimm Baeder return false; 2504610b8539STimm Baeder break; 2505610b8539STimm Baeder 2506610b8539STimm Baeder case Builtin::BI__builtin_operator_delete: 2507610b8539STimm Baeder if (!interp__builtin_operator_delete(S, OpPC, Frame, F, Call)) 2508610b8539STimm Baeder return false; 2509610b8539STimm Baeder break; 2510610b8539STimm Baeder 2511b46a0482STimm Baeder case Builtin::BI__arithmetic_fence: 2512b46a0482STimm Baeder if (!interp__builtin_arithmetic_fence(S, OpPC, Frame, F, Call)) 2513b46a0482STimm Baeder return false; 2514b46a0482STimm Baeder break; 2515b46a0482STimm Baeder 251631bde711STimm Baeder case Builtin::BI__builtin_reduce_add: 2517c1dcf75aSTimm Baeder case Builtin::BI__builtin_reduce_mul: 2518ccc471feSTimm Baeder case Builtin::BI__builtin_reduce_and: 25191288f6d4STimm Baeder case Builtin::BI__builtin_reduce_or: 2520b587b910STimm Baeder case Builtin::BI__builtin_reduce_xor: 252131bde711STimm Baeder if (!interp__builtin_vector_reduce(S, OpPC, Frame, F, Call)) 252231bde711STimm Baeder return false; 252331bde711STimm Baeder break; 252431bde711STimm Baeder 2525637a1ae8STimm Baeder case Builtin::BI__builtin_elementwise_popcount: 2526637a1ae8STimm Baeder if (!interp__builtin_elementwise_popcount(S, OpPC, Frame, F, Call)) 2527637a1ae8STimm Baeder return false; 2528637a1ae8STimm Baeder break; 2529637a1ae8STimm Baeder 25300611fdd3STimm Baeder case Builtin::BI__builtin_memcpy: 2531dac9736dSTimm Baeder case Builtin::BImemcpy: 253278955136STimm Baeder case Builtin::BI__builtin_memmove: 253378955136STimm Baeder case Builtin::BImemmove: 25340611fdd3STimm Baeder if (!interp__builtin_memcpy(S, OpPC, Frame, F, Call)) 25350611fdd3STimm Baeder return false; 25360611fdd3STimm Baeder break; 25370611fdd3STimm Baeder 25388713914dSTimm Baeder case Builtin::BI__builtin_memcmp: 25398713914dSTimm Baeder case Builtin::BImemcmp: 254098470c0bSTimm Baeder case Builtin::BI__builtin_bcmp: 254198470c0bSTimm Baeder case Builtin::BIbcmp: 2542dd6f6a09STimm Baeder case Builtin::BI__builtin_wmemcmp: 2543dd6f6a09STimm Baeder case Builtin::BIwmemcmp: 25448713914dSTimm Baeder if (!interp__builtin_memcmp(S, OpPC, Frame, F, Call)) 25458713914dSTimm Baeder return false; 25468713914dSTimm Baeder break; 25478713914dSTimm Baeder 2548a07aba5dSTimm Baeder default: 2549a07aba5dSTimm Baeder S.FFDiag(S.Current->getLocation(OpPC), 2550a07aba5dSTimm Baeder diag::note_invalid_subexpr_in_const_expr) 2551a07aba5dSTimm Baeder << S.Current->getRange(OpPC); 2552a07aba5dSTimm Baeder 2553a07aba5dSTimm Baeder return false; 2554a07aba5dSTimm Baeder } 2555a07aba5dSTimm Baeder 255682ed9c03STimm Baeder return retPrimValue(S, OpPC, ReturnT); 2557a07aba5dSTimm Baeder } 2558a07aba5dSTimm Baeder 2559a07aba5dSTimm Baeder bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, 2560a07aba5dSTimm Baeder llvm::ArrayRef<int64_t> ArrayIndices, 2561a07aba5dSTimm Baeder int64_t &IntResult) { 2562a07aba5dSTimm Baeder CharUnits Result; 2563a07aba5dSTimm Baeder unsigned N = E->getNumComponents(); 2564a07aba5dSTimm Baeder assert(N > 0); 2565a07aba5dSTimm Baeder 2566a07aba5dSTimm Baeder unsigned ArrayIndex = 0; 2567a07aba5dSTimm Baeder QualType CurrentType = E->getTypeSourceInfo()->getType(); 2568a07aba5dSTimm Baeder for (unsigned I = 0; I != N; ++I) { 2569a07aba5dSTimm Baeder const OffsetOfNode &Node = E->getComponent(I); 2570a07aba5dSTimm Baeder switch (Node.getKind()) { 2571a07aba5dSTimm Baeder case OffsetOfNode::Field: { 2572a07aba5dSTimm Baeder const FieldDecl *MemberDecl = Node.getField(); 2573a07aba5dSTimm Baeder const RecordType *RT = CurrentType->getAs<RecordType>(); 2574a07aba5dSTimm Baeder if (!RT) 2575a07aba5dSTimm Baeder return false; 2576a07aba5dSTimm Baeder const RecordDecl *RD = RT->getDecl(); 2577a07aba5dSTimm Baeder if (RD->isInvalidDecl()) 2578a07aba5dSTimm Baeder return false; 2579d9e72860Syronglin const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD); 2580a07aba5dSTimm Baeder unsigned FieldIndex = MemberDecl->getFieldIndex(); 2581a07aba5dSTimm Baeder assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type"); 2582d9e72860Syronglin Result += 2583d9e72860Syronglin S.getASTContext().toCharUnitsFromBits(RL.getFieldOffset(FieldIndex)); 2584a07aba5dSTimm Baeder CurrentType = MemberDecl->getType().getNonReferenceType(); 2585a07aba5dSTimm Baeder break; 2586a07aba5dSTimm Baeder } 2587a07aba5dSTimm Baeder case OffsetOfNode::Array: { 2588a07aba5dSTimm Baeder // When generating bytecode, we put all the index expressions as Sint64 on 2589a07aba5dSTimm Baeder // the stack. 2590a07aba5dSTimm Baeder int64_t Index = ArrayIndices[ArrayIndex]; 2591d9e72860Syronglin const ArrayType *AT = S.getASTContext().getAsArrayType(CurrentType); 2592a07aba5dSTimm Baeder if (!AT) 2593a07aba5dSTimm Baeder return false; 2594a07aba5dSTimm Baeder CurrentType = AT->getElementType(); 2595d9e72860Syronglin CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType); 2596a07aba5dSTimm Baeder Result += Index * ElementSize; 2597a07aba5dSTimm Baeder ++ArrayIndex; 2598a07aba5dSTimm Baeder break; 2599a07aba5dSTimm Baeder } 2600a07aba5dSTimm Baeder case OffsetOfNode::Base: { 2601a07aba5dSTimm Baeder const CXXBaseSpecifier *BaseSpec = Node.getBase(); 2602a07aba5dSTimm Baeder if (BaseSpec->isVirtual()) 2603a07aba5dSTimm Baeder return false; 2604a07aba5dSTimm Baeder 2605a07aba5dSTimm Baeder // Find the layout of the class whose base we are looking into. 2606a07aba5dSTimm Baeder const RecordType *RT = CurrentType->getAs<RecordType>(); 2607a07aba5dSTimm Baeder if (!RT) 2608a07aba5dSTimm Baeder return false; 2609a07aba5dSTimm Baeder const RecordDecl *RD = RT->getDecl(); 2610a07aba5dSTimm Baeder if (RD->isInvalidDecl()) 2611a07aba5dSTimm Baeder return false; 2612d9e72860Syronglin const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD); 2613a07aba5dSTimm Baeder 2614a07aba5dSTimm Baeder // Find the base class itself. 2615a07aba5dSTimm Baeder CurrentType = BaseSpec->getType(); 2616a07aba5dSTimm Baeder const RecordType *BaseRT = CurrentType->getAs<RecordType>(); 2617a07aba5dSTimm Baeder if (!BaseRT) 2618a07aba5dSTimm Baeder return false; 2619a07aba5dSTimm Baeder 2620a07aba5dSTimm Baeder // Add the offset to the base. 2621a07aba5dSTimm Baeder Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl())); 2622a07aba5dSTimm Baeder break; 2623a07aba5dSTimm Baeder } 2624a07aba5dSTimm Baeder case OffsetOfNode::Identifier: 2625a07aba5dSTimm Baeder llvm_unreachable("Dependent OffsetOfExpr?"); 2626a07aba5dSTimm Baeder } 2627a07aba5dSTimm Baeder } 2628a07aba5dSTimm Baeder 2629a07aba5dSTimm Baeder IntResult = Result.getQuantity(); 2630a07aba5dSTimm Baeder 2631a07aba5dSTimm Baeder return true; 2632a07aba5dSTimm Baeder } 2633a07aba5dSTimm Baeder 2634a07aba5dSTimm Baeder bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC, 2635a07aba5dSTimm Baeder const Pointer &Ptr, const APSInt &IntValue) { 2636a07aba5dSTimm Baeder 2637a07aba5dSTimm Baeder const Record *R = Ptr.getRecord(); 2638a07aba5dSTimm Baeder assert(R); 2639a07aba5dSTimm Baeder assert(R->getNumFields() == 1); 2640a07aba5dSTimm Baeder 2641a07aba5dSTimm Baeder unsigned FieldOffset = R->getField(0u)->Offset; 2642a07aba5dSTimm Baeder const Pointer &FieldPtr = Ptr.atField(FieldOffset); 2643a07aba5dSTimm Baeder PrimType FieldT = *S.getContext().classify(FieldPtr.getType()); 2644a07aba5dSTimm Baeder 2645a07aba5dSTimm Baeder INT_TYPE_SWITCH(FieldT, 2646a07aba5dSTimm Baeder FieldPtr.deref<T>() = T::from(IntValue.getSExtValue())); 2647a07aba5dSTimm Baeder FieldPtr.initialize(); 2648a07aba5dSTimm Baeder return true; 2649a07aba5dSTimm Baeder } 2650a07aba5dSTimm Baeder 2651a07aba5dSTimm Baeder static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src, 2652a07aba5dSTimm Baeder Pointer &Dest, bool Activate); 2653a07aba5dSTimm Baeder static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src, 2654a07aba5dSTimm Baeder Pointer &Dest, bool Activate = false) { 2655a07aba5dSTimm Baeder [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc(); 2656a07aba5dSTimm Baeder const Descriptor *DestDesc = Dest.getFieldDesc(); 2657a07aba5dSTimm Baeder 2658a07aba5dSTimm Baeder auto copyField = [&](const Record::Field &F, bool Activate) -> bool { 2659a07aba5dSTimm Baeder Pointer DestField = Dest.atField(F.Offset); 2660a07aba5dSTimm Baeder if (std::optional<PrimType> FT = S.Ctx.classify(F.Decl->getType())) { 2661a07aba5dSTimm Baeder TYPE_SWITCH(*FT, { 2662a07aba5dSTimm Baeder DestField.deref<T>() = Src.atField(F.Offset).deref<T>(); 2663a07aba5dSTimm Baeder if (Src.atField(F.Offset).isInitialized()) 2664a07aba5dSTimm Baeder DestField.initialize(); 2665a07aba5dSTimm Baeder if (Activate) 2666a07aba5dSTimm Baeder DestField.activate(); 2667a07aba5dSTimm Baeder }); 2668a07aba5dSTimm Baeder return true; 2669a07aba5dSTimm Baeder } 2670a07aba5dSTimm Baeder // Composite field. 2671a07aba5dSTimm Baeder return copyComposite(S, OpPC, Src.atField(F.Offset), DestField, Activate); 2672a07aba5dSTimm Baeder }; 2673a07aba5dSTimm Baeder 2674a07aba5dSTimm Baeder assert(SrcDesc->isRecord()); 2675a07aba5dSTimm Baeder assert(SrcDesc->ElemRecord == DestDesc->ElemRecord); 2676a07aba5dSTimm Baeder const Record *R = DestDesc->ElemRecord; 2677a07aba5dSTimm Baeder for (const Record::Field &F : R->fields()) { 2678a07aba5dSTimm Baeder if (R->isUnion()) { 2679a07aba5dSTimm Baeder // For unions, only copy the active field. 2680a07aba5dSTimm Baeder const Pointer &SrcField = Src.atField(F.Offset); 2681a07aba5dSTimm Baeder if (SrcField.isActive()) { 2682a07aba5dSTimm Baeder if (!copyField(F, /*Activate=*/true)) 2683a07aba5dSTimm Baeder return false; 2684a07aba5dSTimm Baeder } 2685a07aba5dSTimm Baeder } else { 2686a07aba5dSTimm Baeder if (!copyField(F, Activate)) 2687a07aba5dSTimm Baeder return false; 2688a07aba5dSTimm Baeder } 2689a07aba5dSTimm Baeder } 2690a07aba5dSTimm Baeder 2691a07aba5dSTimm Baeder for (const Record::Base &B : R->bases()) { 2692a07aba5dSTimm Baeder Pointer DestBase = Dest.atField(B.Offset); 2693a07aba5dSTimm Baeder if (!copyRecord(S, OpPC, Src.atField(B.Offset), DestBase, Activate)) 2694a07aba5dSTimm Baeder return false; 2695a07aba5dSTimm Baeder } 2696a07aba5dSTimm Baeder 2697a07aba5dSTimm Baeder Dest.initialize(); 2698a07aba5dSTimm Baeder return true; 2699a07aba5dSTimm Baeder } 2700a07aba5dSTimm Baeder 2701a07aba5dSTimm Baeder static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src, 2702a07aba5dSTimm Baeder Pointer &Dest, bool Activate = false) { 2703a07aba5dSTimm Baeder assert(Src.isLive() && Dest.isLive()); 2704a07aba5dSTimm Baeder 2705a07aba5dSTimm Baeder [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc(); 2706a07aba5dSTimm Baeder const Descriptor *DestDesc = Dest.getFieldDesc(); 2707a07aba5dSTimm Baeder 2708a07aba5dSTimm Baeder assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive()); 2709a07aba5dSTimm Baeder 2710a07aba5dSTimm Baeder if (DestDesc->isPrimitiveArray()) { 2711a07aba5dSTimm Baeder assert(SrcDesc->isPrimitiveArray()); 2712a07aba5dSTimm Baeder assert(SrcDesc->getNumElems() == DestDesc->getNumElems()); 2713a07aba5dSTimm Baeder PrimType ET = DestDesc->getPrimType(); 2714a07aba5dSTimm Baeder for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) { 2715a07aba5dSTimm Baeder Pointer DestElem = Dest.atIndex(I); 2716a07aba5dSTimm Baeder TYPE_SWITCH(ET, { 2717a07aba5dSTimm Baeder DestElem.deref<T>() = Src.atIndex(I).deref<T>(); 2718a07aba5dSTimm Baeder DestElem.initialize(); 2719a07aba5dSTimm Baeder }); 2720a07aba5dSTimm Baeder } 2721a07aba5dSTimm Baeder return true; 2722a07aba5dSTimm Baeder } 2723a07aba5dSTimm Baeder 2724a07aba5dSTimm Baeder if (DestDesc->isRecord()) 2725a07aba5dSTimm Baeder return copyRecord(S, OpPC, Src, Dest, Activate); 2726a07aba5dSTimm Baeder return Invalid(S, OpPC); 2727a07aba5dSTimm Baeder } 2728a07aba5dSTimm Baeder 2729a07aba5dSTimm Baeder bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) { 2730a07aba5dSTimm Baeder return copyComposite(S, OpPC, Src, Dest); 2731a07aba5dSTimm Baeder } 2732a07aba5dSTimm Baeder 2733a07aba5dSTimm Baeder } // namespace interp 2734a07aba5dSTimm Baeder } // namespace clang 2735