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" 20a07aba5dSTimm Baeder #include "llvm/Support/SipHash.h" 21a07aba5dSTimm Baeder 22a07aba5dSTimm Baeder namespace clang { 23a07aba5dSTimm Baeder namespace interp { 24a07aba5dSTimm Baeder 25a07aba5dSTimm Baeder static unsigned callArgSize(const InterpState &S, const CallExpr *C) { 26a07aba5dSTimm Baeder unsigned O = 0; 27a07aba5dSTimm Baeder 28a07aba5dSTimm Baeder for (const Expr *E : C->arguments()) { 29a07aba5dSTimm Baeder O += align(primSize(*S.getContext().classify(E))); 30a07aba5dSTimm Baeder } 31a07aba5dSTimm Baeder 32a07aba5dSTimm Baeder return O; 33a07aba5dSTimm Baeder } 34a07aba5dSTimm Baeder 35a07aba5dSTimm Baeder template <typename T> 36a07aba5dSTimm Baeder static T getParam(const InterpFrame *Frame, unsigned Index) { 37a07aba5dSTimm Baeder assert(Frame->getFunction()->getNumParams() > Index); 38a07aba5dSTimm Baeder unsigned Offset = Frame->getFunction()->getParamOffset(Index); 39a07aba5dSTimm Baeder return Frame->getParam<T>(Offset); 40a07aba5dSTimm Baeder } 41a07aba5dSTimm Baeder 426f8e8551STimm Baeder static APSInt getAPSIntParam(const InterpFrame *Frame, unsigned Index) { 436f8e8551STimm Baeder APSInt R; 446f8e8551STimm Baeder unsigned Offset = Frame->getFunction()->getParamOffset(Index); 456f8e8551STimm Baeder INT_TYPE_SWITCH(Frame->getFunction()->getParamType(Index), 466f8e8551STimm Baeder R = Frame->getParam<T>(Offset).toAPSInt()); 476f8e8551STimm Baeder return R; 486f8e8551STimm Baeder } 496f8e8551STimm Baeder 50cbdd14eeSCongcong Cai static PrimType getIntPrimType(const InterpState &S) { 51d9e72860Syronglin const TargetInfo &TI = S.getASTContext().getTargetInfo(); 52a07aba5dSTimm Baeder unsigned IntWidth = TI.getIntWidth(); 53a07aba5dSTimm Baeder 54a07aba5dSTimm Baeder if (IntWidth == 32) 55a07aba5dSTimm Baeder return PT_Sint32; 56a07aba5dSTimm Baeder else if (IntWidth == 16) 57a07aba5dSTimm Baeder return PT_Sint16; 58a07aba5dSTimm Baeder llvm_unreachable("Int isn't 16 or 32 bit?"); 59a07aba5dSTimm Baeder } 60a07aba5dSTimm Baeder 61cbdd14eeSCongcong Cai static PrimType getLongPrimType(const InterpState &S) { 62d9e72860Syronglin const TargetInfo &TI = S.getASTContext().getTargetInfo(); 63a07aba5dSTimm Baeder unsigned LongWidth = TI.getLongWidth(); 64a07aba5dSTimm Baeder 65a07aba5dSTimm Baeder if (LongWidth == 64) 66a07aba5dSTimm Baeder return PT_Sint64; 67a07aba5dSTimm Baeder else if (LongWidth == 32) 68a07aba5dSTimm Baeder return PT_Sint32; 69a07aba5dSTimm Baeder else if (LongWidth == 16) 70a07aba5dSTimm Baeder return PT_Sint16; 71a07aba5dSTimm Baeder llvm_unreachable("long isn't 16, 32 or 64 bit?"); 72a07aba5dSTimm Baeder } 73a07aba5dSTimm Baeder 74a07aba5dSTimm Baeder /// Peek an integer value from the stack into an APSInt. 75a07aba5dSTimm Baeder static APSInt peekToAPSInt(InterpStack &Stk, PrimType T, size_t Offset = 0) { 76a07aba5dSTimm Baeder if (Offset == 0) 77a07aba5dSTimm Baeder Offset = align(primSize(T)); 78a07aba5dSTimm Baeder 79a07aba5dSTimm Baeder APSInt R; 80a07aba5dSTimm Baeder INT_TYPE_SWITCH(T, R = Stk.peek<T>(Offset).toAPSInt()); 81a07aba5dSTimm Baeder 82a07aba5dSTimm Baeder return R; 83a07aba5dSTimm Baeder } 84a07aba5dSTimm Baeder 85a07aba5dSTimm Baeder /// Pushes \p Val on the stack as the type given by \p QT. 86a07aba5dSTimm Baeder static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) { 87a07aba5dSTimm Baeder assert(QT->isSignedIntegerOrEnumerationType() || 88a07aba5dSTimm Baeder QT->isUnsignedIntegerOrEnumerationType()); 89a07aba5dSTimm Baeder std::optional<PrimType> T = S.getContext().classify(QT); 90a07aba5dSTimm Baeder assert(T); 91a07aba5dSTimm Baeder 9231bde711STimm Baeder unsigned BitWidth = S.getASTContext().getTypeSize(QT); 93a07aba5dSTimm Baeder if (QT->isSignedIntegerOrEnumerationType()) { 94a07aba5dSTimm Baeder int64_t V = Val.getSExtValue(); 9531bde711STimm Baeder INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); }); 96a07aba5dSTimm Baeder } else { 97a07aba5dSTimm Baeder assert(QT->isUnsignedIntegerOrEnumerationType()); 98a07aba5dSTimm Baeder uint64_t V = Val.getZExtValue(); 9931bde711STimm Baeder INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); }); 100a07aba5dSTimm Baeder } 101a07aba5dSTimm Baeder } 102a07aba5dSTimm Baeder 103a07aba5dSTimm Baeder template <typename T> 104a07aba5dSTimm Baeder static void pushInteger(InterpState &S, T Val, QualType QT) { 105a07aba5dSTimm Baeder if constexpr (std::is_same_v<T, APInt>) 106a07aba5dSTimm Baeder pushInteger(S, APSInt(Val, !std::is_signed_v<T>), QT); 1071288f6d4STimm Baeder else if constexpr (std::is_same_v<T, APSInt>) 1081288f6d4STimm Baeder pushInteger(S, Val, QT); 109a07aba5dSTimm Baeder else 110a07aba5dSTimm Baeder pushInteger(S, 111a07aba5dSTimm Baeder APSInt(APInt(sizeof(T) * 8, static_cast<uint64_t>(Val), 112a07aba5dSTimm Baeder std::is_signed_v<T>), 113a07aba5dSTimm Baeder !std::is_signed_v<T>), 114a07aba5dSTimm Baeder QT); 115a07aba5dSTimm Baeder } 116a07aba5dSTimm Baeder 117a07aba5dSTimm Baeder static void assignInteger(Pointer &Dest, PrimType ValueT, const APSInt &Value) { 118a07aba5dSTimm Baeder INT_TYPE_SWITCH_NO_BOOL( 119a07aba5dSTimm Baeder ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); }); 120a07aba5dSTimm Baeder } 121a07aba5dSTimm Baeder 12282ed9c03STimm Baeder static bool retPrimValue(InterpState &S, CodePtr OpPC, 123a07aba5dSTimm Baeder std::optional<PrimType> &T) { 124a07aba5dSTimm Baeder if (!T) 12582ed9c03STimm Baeder return RetVoid(S, OpPC); 126a07aba5dSTimm Baeder 127a07aba5dSTimm Baeder #define RET_CASE(X) \ 128a07aba5dSTimm Baeder case X: \ 12982ed9c03STimm Baeder return Ret<X>(S, OpPC); 130a07aba5dSTimm Baeder switch (*T) { 131a07aba5dSTimm Baeder RET_CASE(PT_Ptr); 132a07aba5dSTimm Baeder RET_CASE(PT_FnPtr); 133a07aba5dSTimm Baeder RET_CASE(PT_Float); 134a07aba5dSTimm Baeder RET_CASE(PT_Bool); 135a07aba5dSTimm Baeder RET_CASE(PT_Sint8); 136a07aba5dSTimm Baeder RET_CASE(PT_Uint8); 137a07aba5dSTimm Baeder RET_CASE(PT_Sint16); 138a07aba5dSTimm Baeder RET_CASE(PT_Uint16); 139a07aba5dSTimm Baeder RET_CASE(PT_Sint32); 140a07aba5dSTimm Baeder RET_CASE(PT_Uint32); 141a07aba5dSTimm Baeder RET_CASE(PT_Sint64); 142a07aba5dSTimm Baeder RET_CASE(PT_Uint64); 14331bde711STimm Baeder RET_CASE(PT_IntAP); 14431bde711STimm Baeder RET_CASE(PT_IntAPS); 145a07aba5dSTimm Baeder default: 146a07aba5dSTimm Baeder llvm_unreachable("Unsupported return type for builtin function"); 147a07aba5dSTimm Baeder } 148a07aba5dSTimm Baeder #undef RET_CASE 149a07aba5dSTimm Baeder } 150a07aba5dSTimm Baeder 151a07aba5dSTimm Baeder static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC, 152a07aba5dSTimm Baeder const InterpFrame *Frame, 153a07aba5dSTimm Baeder const CallExpr *Call) { 154a024a0ceSTimm Baeder unsigned Depth = S.Current->getDepth(); 155a07aba5dSTimm Baeder auto isStdCall = [](const FunctionDecl *F) -> bool { 156a07aba5dSTimm Baeder return F && F->isInStdNamespace() && F->getIdentifier() && 157a07aba5dSTimm Baeder F->getIdentifier()->isStr("is_constant_evaluated"); 158a07aba5dSTimm Baeder }; 159a07aba5dSTimm Baeder const InterpFrame *Caller = Frame->Caller; 160a024a0ceSTimm Baeder // The current frame is the one for __builtin_is_constant_evaluated. 161a024a0ceSTimm Baeder // The one above that, potentially the one for std::is_constant_evaluated(). 162a024a0ceSTimm Baeder if (S.inConstantContext() && !S.checkingPotentialConstantExpression() && 163a024a0ceSTimm Baeder S.getEvalStatus().Diag && 164a024a0ceSTimm Baeder (Depth == 1 || (Depth == 2 && isStdCall(Caller->getCallee())))) { 165a07aba5dSTimm Baeder if (Caller->Caller && isStdCall(Caller->getCallee())) { 166a07aba5dSTimm Baeder const Expr *E = Caller->Caller->getExpr(Caller->getRetPC()); 167a07aba5dSTimm Baeder S.report(E->getExprLoc(), 168a07aba5dSTimm Baeder diag::warn_is_constant_evaluated_always_true_constexpr) 169a07aba5dSTimm Baeder << "std::is_constant_evaluated" << E->getSourceRange(); 170a07aba5dSTimm Baeder } else { 171a07aba5dSTimm Baeder const Expr *E = Frame->Caller->getExpr(Frame->getRetPC()); 172a07aba5dSTimm Baeder S.report(E->getExprLoc(), 173a07aba5dSTimm Baeder diag::warn_is_constant_evaluated_always_true_constexpr) 174a07aba5dSTimm Baeder << "__builtin_is_constant_evaluated" << E->getSourceRange(); 175a07aba5dSTimm Baeder } 176a07aba5dSTimm Baeder } 177a07aba5dSTimm Baeder 178a07aba5dSTimm Baeder S.Stk.push<Boolean>(Boolean::from(S.inConstantContext())); 179a07aba5dSTimm Baeder return true; 180a07aba5dSTimm Baeder } 181a07aba5dSTimm Baeder 182a07aba5dSTimm Baeder static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, 183a07aba5dSTimm Baeder const InterpFrame *Frame, 184a07aba5dSTimm Baeder const CallExpr *Call) { 185a07aba5dSTimm Baeder const Pointer &A = getParam<Pointer>(Frame, 0); 186a07aba5dSTimm Baeder const Pointer &B = getParam<Pointer>(Frame, 1); 187a07aba5dSTimm Baeder 188a07aba5dSTimm Baeder if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read)) 189a07aba5dSTimm Baeder return false; 190a07aba5dSTimm Baeder 191a07aba5dSTimm Baeder if (A.isDummy() || B.isDummy()) 192a07aba5dSTimm Baeder return false; 193a07aba5dSTimm Baeder 194a07aba5dSTimm Baeder assert(A.getFieldDesc()->isPrimitiveArray()); 195a07aba5dSTimm Baeder assert(B.getFieldDesc()->isPrimitiveArray()); 196a07aba5dSTimm Baeder 197a07aba5dSTimm Baeder unsigned IndexA = A.getIndex(); 198a07aba5dSTimm Baeder unsigned IndexB = B.getIndex(); 199a07aba5dSTimm Baeder int32_t Result = 0; 200a07aba5dSTimm Baeder for (;; ++IndexA, ++IndexB) { 201a07aba5dSTimm Baeder const Pointer &PA = A.atIndex(IndexA); 202a07aba5dSTimm Baeder const Pointer &PB = B.atIndex(IndexB); 203a07aba5dSTimm Baeder if (!CheckRange(S, OpPC, PA, AK_Read) || 204a07aba5dSTimm Baeder !CheckRange(S, OpPC, PB, AK_Read)) { 205a07aba5dSTimm Baeder return false; 206a07aba5dSTimm Baeder } 207a07aba5dSTimm Baeder uint8_t CA = PA.deref<uint8_t>(); 208a07aba5dSTimm Baeder uint8_t CB = PB.deref<uint8_t>(); 209a07aba5dSTimm Baeder 210a07aba5dSTimm Baeder if (CA > CB) { 211a07aba5dSTimm Baeder Result = 1; 212a07aba5dSTimm Baeder break; 213a07aba5dSTimm Baeder } else if (CA < CB) { 214a07aba5dSTimm Baeder Result = -1; 215a07aba5dSTimm Baeder break; 216a07aba5dSTimm Baeder } 217a07aba5dSTimm Baeder if (CA == 0 || CB == 0) 218a07aba5dSTimm Baeder break; 219a07aba5dSTimm Baeder } 220a07aba5dSTimm Baeder 221a07aba5dSTimm Baeder pushInteger(S, Result, Call->getType()); 222a07aba5dSTimm Baeder return true; 223a07aba5dSTimm Baeder } 224a07aba5dSTimm Baeder 225*dac9736dSTimm Baeder static void diagnoseNonConstexprBuiltin(InterpState &S, CodePtr OpPC, 226*dac9736dSTimm Baeder unsigned ID) { 227*dac9736dSTimm Baeder auto Loc = S.Current->getSource(OpPC); 228*dac9736dSTimm Baeder if (S.getLangOpts().CPlusPlus11) 229*dac9736dSTimm Baeder S.CCEDiag(Loc, diag::note_constexpr_invalid_function) 230*dac9736dSTimm Baeder << /*isConstexpr=*/0 << /*isConstructor=*/0 231*dac9736dSTimm Baeder << ("'" + S.getASTContext().BuiltinInfo.getName(ID) + "'").str(); 232*dac9736dSTimm Baeder else 233*dac9736dSTimm Baeder S.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr); 234*dac9736dSTimm Baeder } 235a07aba5dSTimm Baeder static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, 236a07aba5dSTimm Baeder const InterpFrame *Frame, 237*dac9736dSTimm Baeder const Function *Func, const CallExpr *Call) { 238*dac9736dSTimm Baeder unsigned ID = Func->getBuiltinID(); 239a07aba5dSTimm Baeder const Pointer &StrPtr = getParam<Pointer>(Frame, 0); 240a07aba5dSTimm Baeder 241*dac9736dSTimm Baeder if (ID == Builtin::BIstrlen) 242*dac9736dSTimm Baeder diagnoseNonConstexprBuiltin(S, OpPC, ID); 243*dac9736dSTimm Baeder 244a07aba5dSTimm Baeder if (!CheckArray(S, OpPC, StrPtr)) 245a07aba5dSTimm Baeder return false; 246a07aba5dSTimm Baeder 247a07aba5dSTimm Baeder if (!CheckLive(S, OpPC, StrPtr, AK_Read)) 248a07aba5dSTimm Baeder return false; 249a07aba5dSTimm Baeder 250a07aba5dSTimm Baeder if (!CheckDummy(S, OpPC, StrPtr, AK_Read)) 251a07aba5dSTimm Baeder return false; 252a07aba5dSTimm Baeder 253a07aba5dSTimm Baeder assert(StrPtr.getFieldDesc()->isPrimitiveArray()); 254a07aba5dSTimm Baeder 255a07aba5dSTimm Baeder size_t Len = 0; 256a07aba5dSTimm Baeder for (size_t I = StrPtr.getIndex();; ++I, ++Len) { 257a07aba5dSTimm Baeder const Pointer &ElemPtr = StrPtr.atIndex(I); 258a07aba5dSTimm Baeder 259a07aba5dSTimm Baeder if (!CheckRange(S, OpPC, ElemPtr, AK_Read)) 260a07aba5dSTimm Baeder return false; 261a07aba5dSTimm Baeder 262a07aba5dSTimm Baeder uint8_t Val = ElemPtr.deref<uint8_t>(); 263a07aba5dSTimm Baeder if (Val == 0) 264a07aba5dSTimm Baeder break; 265a07aba5dSTimm Baeder } 266a07aba5dSTimm Baeder 267a07aba5dSTimm Baeder pushInteger(S, Len, Call->getType()); 268a07aba5dSTimm Baeder 269a07aba5dSTimm Baeder return true; 270a07aba5dSTimm Baeder } 271a07aba5dSTimm Baeder 272a07aba5dSTimm Baeder static bool interp__builtin_nan(InterpState &S, CodePtr OpPC, 273a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *F, 274a07aba5dSTimm Baeder bool Signaling) { 275a07aba5dSTimm Baeder const Pointer &Arg = getParam<Pointer>(Frame, 0); 276a07aba5dSTimm Baeder 277a07aba5dSTimm Baeder if (!CheckLoad(S, OpPC, Arg)) 278a07aba5dSTimm Baeder return false; 279a07aba5dSTimm Baeder 280a07aba5dSTimm Baeder assert(Arg.getFieldDesc()->isPrimitiveArray()); 281a07aba5dSTimm Baeder 282a07aba5dSTimm Baeder // Convert the given string to an integer using StringRef's API. 283a07aba5dSTimm Baeder llvm::APInt Fill; 284a07aba5dSTimm Baeder std::string Str; 285a07aba5dSTimm Baeder assert(Arg.getNumElems() >= 1); 286a07aba5dSTimm Baeder for (unsigned I = 0;; ++I) { 287a07aba5dSTimm Baeder const Pointer &Elem = Arg.atIndex(I); 288a07aba5dSTimm Baeder 289a07aba5dSTimm Baeder if (!CheckLoad(S, OpPC, Elem)) 290a07aba5dSTimm Baeder return false; 291a07aba5dSTimm Baeder 292a07aba5dSTimm Baeder if (Elem.deref<int8_t>() == 0) 293a07aba5dSTimm Baeder break; 294a07aba5dSTimm Baeder 295a07aba5dSTimm Baeder Str += Elem.deref<char>(); 296a07aba5dSTimm Baeder } 297a07aba5dSTimm Baeder 298a07aba5dSTimm Baeder // Treat empty strings as if they were zero. 299a07aba5dSTimm Baeder if (Str.empty()) 300a07aba5dSTimm Baeder Fill = llvm::APInt(32, 0); 301a07aba5dSTimm Baeder else if (StringRef(Str).getAsInteger(0, Fill)) 302a07aba5dSTimm Baeder return false; 303a07aba5dSTimm Baeder 304a07aba5dSTimm Baeder const llvm::fltSemantics &TargetSemantics = 305d9e72860Syronglin S.getASTContext().getFloatTypeSemantics(F->getDecl()->getReturnType()); 306a07aba5dSTimm Baeder 307a07aba5dSTimm Baeder Floating Result; 308d9e72860Syronglin if (S.getASTContext().getTargetInfo().isNan2008()) { 309a07aba5dSTimm Baeder if (Signaling) 310a07aba5dSTimm Baeder Result = Floating( 311a07aba5dSTimm Baeder llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill)); 312a07aba5dSTimm Baeder else 313a07aba5dSTimm Baeder Result = Floating( 314a07aba5dSTimm Baeder llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill)); 315a07aba5dSTimm Baeder } else { 316a07aba5dSTimm Baeder // Prior to IEEE 754-2008, architectures were allowed to choose whether 317a07aba5dSTimm Baeder // the first bit of their significand was set for qNaN or sNaN. MIPS chose 318a07aba5dSTimm Baeder // a different encoding to what became a standard in 2008, and for pre- 319a07aba5dSTimm Baeder // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as 320a07aba5dSTimm Baeder // sNaN. This is now known as "legacy NaN" encoding. 321a07aba5dSTimm Baeder if (Signaling) 322a07aba5dSTimm Baeder Result = Floating( 323a07aba5dSTimm Baeder llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill)); 324a07aba5dSTimm Baeder else 325a07aba5dSTimm Baeder Result = Floating( 326a07aba5dSTimm Baeder llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill)); 327a07aba5dSTimm Baeder } 328a07aba5dSTimm Baeder 329a07aba5dSTimm Baeder S.Stk.push<Floating>(Result); 330a07aba5dSTimm Baeder return true; 331a07aba5dSTimm Baeder } 332a07aba5dSTimm Baeder 333a07aba5dSTimm Baeder static bool interp__builtin_inf(InterpState &S, CodePtr OpPC, 334a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *F) { 335a07aba5dSTimm Baeder const llvm::fltSemantics &TargetSemantics = 336d9e72860Syronglin S.getASTContext().getFloatTypeSemantics(F->getDecl()->getReturnType()); 337a07aba5dSTimm Baeder 338a07aba5dSTimm Baeder S.Stk.push<Floating>(Floating::getInf(TargetSemantics)); 339a07aba5dSTimm Baeder return true; 340a07aba5dSTimm Baeder } 341a07aba5dSTimm Baeder 342a07aba5dSTimm Baeder static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC, 343a07aba5dSTimm Baeder const InterpFrame *Frame, 344a07aba5dSTimm Baeder const Function *F) { 345a07aba5dSTimm Baeder const Floating &Arg1 = getParam<Floating>(Frame, 0); 346a07aba5dSTimm Baeder const Floating &Arg2 = getParam<Floating>(Frame, 1); 347a07aba5dSTimm Baeder 348a07aba5dSTimm Baeder APFloat Copy = Arg1.getAPFloat(); 349a07aba5dSTimm Baeder Copy.copySign(Arg2.getAPFloat()); 350a07aba5dSTimm Baeder S.Stk.push<Floating>(Floating(Copy)); 351a07aba5dSTimm Baeder 352a07aba5dSTimm Baeder return true; 353a07aba5dSTimm Baeder } 354a07aba5dSTimm Baeder 355a07aba5dSTimm Baeder static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC, 356790d9869STimm Baeder const InterpFrame *Frame, const Function *F, 357790d9869STimm Baeder bool IsNumBuiltin) { 358a07aba5dSTimm Baeder const Floating &LHS = getParam<Floating>(Frame, 0); 359a07aba5dSTimm Baeder const Floating &RHS = getParam<Floating>(Frame, 1); 360a07aba5dSTimm Baeder 361a07aba5dSTimm Baeder Floating Result; 362a07aba5dSTimm Baeder 363790d9869STimm Baeder if (IsNumBuiltin) { 364790d9869STimm Baeder Result = llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()); 365790d9869STimm Baeder } else { 366a07aba5dSTimm Baeder // When comparing zeroes, return -0.0 if one of the zeroes is negative. 367a07aba5dSTimm Baeder if (LHS.isZero() && RHS.isZero() && RHS.isNegative()) 368a07aba5dSTimm Baeder Result = RHS; 369a07aba5dSTimm Baeder else if (LHS.isNan() || RHS < LHS) 370a07aba5dSTimm Baeder Result = RHS; 371a07aba5dSTimm Baeder else 372a07aba5dSTimm Baeder Result = LHS; 373790d9869STimm Baeder } 374a07aba5dSTimm Baeder 375a07aba5dSTimm Baeder S.Stk.push<Floating>(Result); 376a07aba5dSTimm Baeder return true; 377a07aba5dSTimm Baeder } 378a07aba5dSTimm Baeder 379a07aba5dSTimm Baeder static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC, 380790d9869STimm Baeder const InterpFrame *Frame, const Function *Func, 381790d9869STimm Baeder bool IsNumBuiltin) { 382a07aba5dSTimm Baeder const Floating &LHS = getParam<Floating>(Frame, 0); 383a07aba5dSTimm Baeder const Floating &RHS = getParam<Floating>(Frame, 1); 384a07aba5dSTimm Baeder 385a07aba5dSTimm Baeder Floating Result; 386a07aba5dSTimm Baeder 387790d9869STimm Baeder if (IsNumBuiltin) { 388790d9869STimm Baeder Result = llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()); 389790d9869STimm Baeder } else { 390a07aba5dSTimm Baeder // When comparing zeroes, return +0.0 if one of the zeroes is positive. 391a07aba5dSTimm Baeder if (LHS.isZero() && RHS.isZero() && LHS.isNegative()) 392a07aba5dSTimm Baeder Result = RHS; 393a07aba5dSTimm Baeder else if (LHS.isNan() || RHS > LHS) 394a07aba5dSTimm Baeder Result = RHS; 395a07aba5dSTimm Baeder else 396a07aba5dSTimm Baeder Result = LHS; 397790d9869STimm Baeder } 398a07aba5dSTimm Baeder 399a07aba5dSTimm Baeder S.Stk.push<Floating>(Result); 400a07aba5dSTimm Baeder return true; 401a07aba5dSTimm Baeder } 402a07aba5dSTimm Baeder 403a07aba5dSTimm Baeder /// Defined as __builtin_isnan(...), to accommodate the fact that it can 404a07aba5dSTimm Baeder /// take a float, double, long double, etc. 405a07aba5dSTimm Baeder /// But for us, that's all a Floating anyway. 406a07aba5dSTimm Baeder static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC, 407a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *F, 408a07aba5dSTimm Baeder const CallExpr *Call) { 409a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 410a07aba5dSTimm Baeder 411a07aba5dSTimm Baeder pushInteger(S, Arg.isNan(), Call->getType()); 412a07aba5dSTimm Baeder return true; 413a07aba5dSTimm Baeder } 414a07aba5dSTimm Baeder 415a07aba5dSTimm Baeder static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC, 416a07aba5dSTimm Baeder const InterpFrame *Frame, 417a07aba5dSTimm Baeder const Function *F, 418a07aba5dSTimm Baeder const CallExpr *Call) { 419a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 420a07aba5dSTimm Baeder 421a07aba5dSTimm Baeder pushInteger(S, Arg.isSignaling(), Call->getType()); 422a07aba5dSTimm Baeder return true; 423a07aba5dSTimm Baeder } 424a07aba5dSTimm Baeder 425a07aba5dSTimm Baeder static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC, 426a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *F, 427a07aba5dSTimm Baeder bool CheckSign, const CallExpr *Call) { 428a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 429a07aba5dSTimm Baeder bool IsInf = Arg.isInf(); 430a07aba5dSTimm Baeder 431a07aba5dSTimm Baeder if (CheckSign) 432a07aba5dSTimm Baeder pushInteger(S, IsInf ? (Arg.isNegative() ? -1 : 1) : 0, Call->getType()); 433a07aba5dSTimm Baeder else 434a07aba5dSTimm Baeder pushInteger(S, Arg.isInf(), Call->getType()); 435a07aba5dSTimm Baeder return true; 436a07aba5dSTimm Baeder } 437a07aba5dSTimm Baeder 438a07aba5dSTimm Baeder static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC, 439a07aba5dSTimm Baeder const InterpFrame *Frame, 440a07aba5dSTimm Baeder const Function *F, const CallExpr *Call) { 441a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 442a07aba5dSTimm Baeder 443a07aba5dSTimm Baeder pushInteger(S, Arg.isFinite(), Call->getType()); 444a07aba5dSTimm Baeder return true; 445a07aba5dSTimm Baeder } 446a07aba5dSTimm Baeder 447a07aba5dSTimm Baeder static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC, 448a07aba5dSTimm Baeder const InterpFrame *Frame, 449a07aba5dSTimm Baeder const Function *F, const CallExpr *Call) { 450a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 451a07aba5dSTimm Baeder 452a07aba5dSTimm Baeder pushInteger(S, Arg.isNormal(), Call->getType()); 453a07aba5dSTimm Baeder return true; 454a07aba5dSTimm Baeder } 455a07aba5dSTimm Baeder 456a07aba5dSTimm Baeder static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC, 457a07aba5dSTimm Baeder const InterpFrame *Frame, 458a07aba5dSTimm Baeder const Function *F, 459a07aba5dSTimm Baeder const CallExpr *Call) { 460a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 461a07aba5dSTimm Baeder 462a07aba5dSTimm Baeder pushInteger(S, Arg.isDenormal(), Call->getType()); 463a07aba5dSTimm Baeder return true; 464a07aba5dSTimm Baeder } 465a07aba5dSTimm Baeder 466a07aba5dSTimm Baeder static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC, 467a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *F, 468a07aba5dSTimm Baeder const CallExpr *Call) { 469a07aba5dSTimm Baeder const Floating &Arg = S.Stk.peek<Floating>(); 470a07aba5dSTimm Baeder 471a07aba5dSTimm Baeder pushInteger(S, Arg.isZero(), Call->getType()); 472a07aba5dSTimm Baeder return true; 473a07aba5dSTimm Baeder } 474a07aba5dSTimm Baeder 47511259343SMital Ashok static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC, 47611259343SMital Ashok const InterpFrame *Frame, const Function *F, 47711259343SMital Ashok const CallExpr *Call) { 47811259343SMital Ashok const Floating &Arg = S.Stk.peek<Floating>(); 47911259343SMital Ashok 48011259343SMital Ashok pushInteger(S, Arg.isNegative(), Call->getType()); 48111259343SMital Ashok return true; 48211259343SMital Ashok } 48311259343SMital Ashok 48411259343SMital Ashok static bool interp_floating_comparison(InterpState &S, CodePtr OpPC, 48511259343SMital Ashok const InterpFrame *Frame, 48611259343SMital Ashok const Function *F, 48711259343SMital Ashok const CallExpr *Call) { 48811259343SMital Ashok const Floating &RHS = S.Stk.peek<Floating>(); 48911259343SMital Ashok const Floating &LHS = S.Stk.peek<Floating>(align(2u * primSize(PT_Float))); 49011259343SMital Ashok unsigned ID = F->getBuiltinID(); 49111259343SMital Ashok 49211259343SMital Ashok pushInteger( 49311259343SMital Ashok S, 49411259343SMital Ashok [&] { 49511259343SMital Ashok switch (ID) { 49611259343SMital Ashok case Builtin::BI__builtin_isgreater: 49711259343SMital Ashok return LHS > RHS; 49811259343SMital Ashok case Builtin::BI__builtin_isgreaterequal: 49911259343SMital Ashok return LHS >= RHS; 50011259343SMital Ashok case Builtin::BI__builtin_isless: 50111259343SMital Ashok return LHS < RHS; 50211259343SMital Ashok case Builtin::BI__builtin_islessequal: 50311259343SMital Ashok return LHS <= RHS; 50411259343SMital Ashok case Builtin::BI__builtin_islessgreater: { 50511259343SMital Ashok ComparisonCategoryResult cmp = LHS.compare(RHS); 50611259343SMital Ashok return cmp == ComparisonCategoryResult::Less || 50711259343SMital Ashok cmp == ComparisonCategoryResult::Greater; 50811259343SMital Ashok } 50911259343SMital Ashok case Builtin::BI__builtin_isunordered: 51011259343SMital Ashok return LHS.compare(RHS) == ComparisonCategoryResult::Unordered; 51111259343SMital Ashok default: 51211259343SMital Ashok llvm_unreachable("Unexpected builtin ID: Should be a floating point " 51311259343SMital Ashok "comparison function"); 51411259343SMital Ashok } 51511259343SMital Ashok }(), 51611259343SMital Ashok Call->getType()); 51711259343SMital Ashok return true; 51811259343SMital Ashok } 51911259343SMital Ashok 520a07aba5dSTimm Baeder /// First parameter to __builtin_isfpclass is the floating value, the 521a07aba5dSTimm Baeder /// second one is an integral value. 522a07aba5dSTimm Baeder static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC, 523a07aba5dSTimm Baeder const InterpFrame *Frame, 524a07aba5dSTimm Baeder const Function *Func, 525a07aba5dSTimm Baeder const CallExpr *Call) { 526a07aba5dSTimm Baeder PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType()); 527a07aba5dSTimm Baeder APSInt FPClassArg = peekToAPSInt(S.Stk, FPClassArgT); 528a07aba5dSTimm Baeder const Floating &F = 529a07aba5dSTimm Baeder S.Stk.peek<Floating>(align(primSize(FPClassArgT) + primSize(PT_Float))); 530a07aba5dSTimm Baeder 531a07aba5dSTimm Baeder int32_t Result = 532a07aba5dSTimm Baeder static_cast<int32_t>((F.classify() & FPClassArg).getZExtValue()); 533a07aba5dSTimm Baeder pushInteger(S, Result, Call->getType()); 534a07aba5dSTimm Baeder 535a07aba5dSTimm Baeder return true; 536a07aba5dSTimm Baeder } 537a07aba5dSTimm Baeder 538a07aba5dSTimm Baeder /// Five int values followed by one floating value. 539a07aba5dSTimm Baeder static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC, 540a07aba5dSTimm Baeder const InterpFrame *Frame, 541a07aba5dSTimm Baeder const Function *Func, 542a07aba5dSTimm Baeder const CallExpr *Call) { 543a07aba5dSTimm Baeder const Floating &Val = S.Stk.peek<Floating>(); 544a07aba5dSTimm Baeder 545a07aba5dSTimm Baeder unsigned Index; 546a07aba5dSTimm Baeder switch (Val.getCategory()) { 547a07aba5dSTimm Baeder case APFloat::fcNaN: 548a07aba5dSTimm Baeder Index = 0; 549a07aba5dSTimm Baeder break; 550a07aba5dSTimm Baeder case APFloat::fcInfinity: 551a07aba5dSTimm Baeder Index = 1; 552a07aba5dSTimm Baeder break; 553a07aba5dSTimm Baeder case APFloat::fcNormal: 554a07aba5dSTimm Baeder Index = Val.isDenormal() ? 3 : 2; 555a07aba5dSTimm Baeder break; 556a07aba5dSTimm Baeder case APFloat::fcZero: 557a07aba5dSTimm Baeder Index = 4; 558a07aba5dSTimm Baeder break; 559a07aba5dSTimm Baeder } 560a07aba5dSTimm Baeder 561a07aba5dSTimm Baeder // The last argument is first on the stack. 562a07aba5dSTimm Baeder assert(Index <= 4); 563a07aba5dSTimm Baeder unsigned IntSize = primSize(getIntPrimType(S)); 564a07aba5dSTimm Baeder unsigned Offset = 565a07aba5dSTimm Baeder align(primSize(PT_Float)) + ((1 + (4 - Index)) * align(IntSize)); 566a07aba5dSTimm Baeder 567a07aba5dSTimm Baeder APSInt I = peekToAPSInt(S.Stk, getIntPrimType(S), Offset); 568a07aba5dSTimm Baeder pushInteger(S, I, Call->getType()); 569a07aba5dSTimm Baeder return true; 570a07aba5dSTimm Baeder } 571a07aba5dSTimm Baeder 572a07aba5dSTimm Baeder // The C standard says "fabs raises no floating-point exceptions, 573a07aba5dSTimm Baeder // even if x is a signaling NaN. The returned value is independent of 574a07aba5dSTimm Baeder // the current rounding direction mode." Therefore constant folding can 575a07aba5dSTimm Baeder // proceed without regard to the floating point settings. 576a07aba5dSTimm Baeder // Reference, WG14 N2478 F.10.4.3 577a07aba5dSTimm Baeder static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC, 578a07aba5dSTimm Baeder const InterpFrame *Frame, 579a07aba5dSTimm Baeder const Function *Func) { 580a07aba5dSTimm Baeder const Floating &Val = getParam<Floating>(Frame, 0); 581a07aba5dSTimm Baeder 582a07aba5dSTimm Baeder S.Stk.push<Floating>(Floating::abs(Val)); 583a07aba5dSTimm Baeder return true; 584a07aba5dSTimm Baeder } 585a07aba5dSTimm Baeder 586332ac18eSc8ef static bool interp__builtin_abs(InterpState &S, CodePtr OpPC, 587332ac18eSc8ef const InterpFrame *Frame, const Function *Func, 588332ac18eSc8ef const CallExpr *Call) { 589332ac18eSc8ef PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 590332ac18eSc8ef APSInt Val = peekToAPSInt(S.Stk, ArgT); 591332ac18eSc8ef if (Val == 592332ac18eSc8ef APSInt(APInt::getSignedMinValue(Val.getBitWidth()), /*IsUnsigned=*/false)) 593332ac18eSc8ef return false; 594332ac18eSc8ef if (Val.isNegative()) 595332ac18eSc8ef Val.negate(); 596332ac18eSc8ef pushInteger(S, Val, Call->getType()); 597332ac18eSc8ef return true; 598332ac18eSc8ef } 599332ac18eSc8ef 600a07aba5dSTimm Baeder static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC, 601a07aba5dSTimm Baeder const InterpFrame *Frame, 602a07aba5dSTimm Baeder const Function *Func, 603a07aba5dSTimm Baeder const CallExpr *Call) { 604a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 605a07aba5dSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, ArgT); 606a07aba5dSTimm Baeder pushInteger(S, Val.popcount(), Call->getType()); 607a07aba5dSTimm Baeder return true; 608a07aba5dSTimm Baeder } 609a07aba5dSTimm Baeder 610a07aba5dSTimm Baeder static bool interp__builtin_parity(InterpState &S, CodePtr OpPC, 611a07aba5dSTimm Baeder const InterpFrame *Frame, 612a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call) { 613a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 614a07aba5dSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, ArgT); 615a07aba5dSTimm Baeder pushInteger(S, Val.popcount() % 2, Call->getType()); 616a07aba5dSTimm Baeder return true; 617a07aba5dSTimm Baeder } 618a07aba5dSTimm Baeder 619a07aba5dSTimm Baeder static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC, 620a07aba5dSTimm Baeder const InterpFrame *Frame, 621a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call) { 622a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 623a07aba5dSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, ArgT); 624a07aba5dSTimm Baeder pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType()); 625a07aba5dSTimm Baeder return true; 626a07aba5dSTimm Baeder } 627a07aba5dSTimm Baeder 628a07aba5dSTimm Baeder static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC, 629a07aba5dSTimm Baeder const InterpFrame *Frame, 630a07aba5dSTimm Baeder const Function *Func, 631a07aba5dSTimm Baeder const CallExpr *Call) { 632a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 633a07aba5dSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, ArgT); 634a07aba5dSTimm Baeder pushInteger(S, Val.reverseBits(), Call->getType()); 635a07aba5dSTimm Baeder return true; 636a07aba5dSTimm Baeder } 637a07aba5dSTimm Baeder 638a07aba5dSTimm Baeder static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC, 639a07aba5dSTimm Baeder const InterpFrame *Frame, 640a07aba5dSTimm Baeder const Function *Func, 641a07aba5dSTimm Baeder const CallExpr *Call) { 642a07aba5dSTimm Baeder // This is an unevaluated call, so there are no arguments on the stack. 643a07aba5dSTimm Baeder assert(Call->getNumArgs() == 1); 644a07aba5dSTimm Baeder const Expr *Arg = Call->getArg(0); 645a07aba5dSTimm Baeder 646a07aba5dSTimm Baeder GCCTypeClass ResultClass = 647a07aba5dSTimm Baeder EvaluateBuiltinClassifyType(Arg->getType(), S.getLangOpts()); 648a07aba5dSTimm Baeder int32_t ReturnVal = static_cast<int32_t>(ResultClass); 649a07aba5dSTimm Baeder pushInteger(S, ReturnVal, Call->getType()); 650a07aba5dSTimm Baeder return true; 651a07aba5dSTimm Baeder } 652a07aba5dSTimm Baeder 653a07aba5dSTimm Baeder // __builtin_expect(long, long) 654a07aba5dSTimm Baeder // __builtin_expect_with_probability(long, long, double) 655a07aba5dSTimm Baeder static bool interp__builtin_expect(InterpState &S, CodePtr OpPC, 656a07aba5dSTimm Baeder const InterpFrame *Frame, 657a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call) { 658a07aba5dSTimm Baeder // The return value is simply the value of the first parameter. 659a07aba5dSTimm Baeder // We ignore the probability. 660a07aba5dSTimm Baeder unsigned NumArgs = Call->getNumArgs(); 661a07aba5dSTimm Baeder assert(NumArgs == 2 || NumArgs == 3); 662a07aba5dSTimm Baeder 663a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 664a07aba5dSTimm Baeder unsigned Offset = align(primSize(getLongPrimType(S))) * 2; 665a07aba5dSTimm Baeder if (NumArgs == 3) 666a07aba5dSTimm Baeder Offset += align(primSize(PT_Float)); 667a07aba5dSTimm Baeder 668a07aba5dSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, ArgT, Offset); 669a07aba5dSTimm Baeder pushInteger(S, Val, Call->getType()); 670a07aba5dSTimm Baeder return true; 671a07aba5dSTimm Baeder } 672a07aba5dSTimm Baeder 673a07aba5dSTimm Baeder /// rotateleft(value, amount) 674a07aba5dSTimm Baeder static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC, 675a07aba5dSTimm Baeder const InterpFrame *Frame, 676a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call, 677a07aba5dSTimm Baeder bool Right) { 678a07aba5dSTimm Baeder PrimType AmountT = *S.getContext().classify(Call->getArg(1)->getType()); 679a07aba5dSTimm Baeder PrimType ValueT = *S.getContext().classify(Call->getArg(0)->getType()); 680a07aba5dSTimm Baeder 681a07aba5dSTimm Baeder APSInt Amount = peekToAPSInt(S.Stk, AmountT); 682a07aba5dSTimm Baeder APSInt Value = peekToAPSInt( 683a07aba5dSTimm Baeder S.Stk, ValueT, align(primSize(AmountT)) + align(primSize(ValueT))); 684a07aba5dSTimm Baeder 685a07aba5dSTimm Baeder APSInt Result; 686a07aba5dSTimm Baeder if (Right) 687a07aba5dSTimm Baeder Result = APSInt(Value.rotr(Amount.urem(Value.getBitWidth())), 688a07aba5dSTimm Baeder /*IsUnsigned=*/true); 689a07aba5dSTimm Baeder else // Left. 690a07aba5dSTimm Baeder Result = APSInt(Value.rotl(Amount.urem(Value.getBitWidth())), 691a07aba5dSTimm Baeder /*IsUnsigned=*/true); 692a07aba5dSTimm Baeder 693a07aba5dSTimm Baeder pushInteger(S, Result, Call->getType()); 694a07aba5dSTimm Baeder return true; 695a07aba5dSTimm Baeder } 696a07aba5dSTimm Baeder 697a07aba5dSTimm Baeder static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC, 698a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *Func, 699a07aba5dSTimm Baeder const CallExpr *Call) { 700a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 701a07aba5dSTimm Baeder APSInt Value = peekToAPSInt(S.Stk, ArgT); 702a07aba5dSTimm Baeder 703a07aba5dSTimm Baeder uint64_t N = Value.countr_zero(); 704a07aba5dSTimm Baeder pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType()); 705a07aba5dSTimm Baeder return true; 706a07aba5dSTimm Baeder } 707a07aba5dSTimm Baeder 708a07aba5dSTimm Baeder static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC, 709a07aba5dSTimm Baeder const InterpFrame *Frame, 710a07aba5dSTimm Baeder const Function *Func, 711a07aba5dSTimm Baeder const CallExpr *Call) { 712a07aba5dSTimm Baeder assert(Call->getArg(0)->isLValue()); 713a07aba5dSTimm Baeder PrimType PtrT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr); 714a07aba5dSTimm Baeder 715a07aba5dSTimm Baeder if (PtrT == PT_FnPtr) { 716a07aba5dSTimm Baeder const FunctionPointer &Arg = S.Stk.peek<FunctionPointer>(); 717a07aba5dSTimm Baeder S.Stk.push<FunctionPointer>(Arg); 718a07aba5dSTimm Baeder } else if (PtrT == PT_Ptr) { 719a07aba5dSTimm Baeder const Pointer &Arg = S.Stk.peek<Pointer>(); 720a07aba5dSTimm Baeder S.Stk.push<Pointer>(Arg); 721a07aba5dSTimm Baeder } else { 722a07aba5dSTimm Baeder assert(false && "Unsupported pointer type passed to __builtin_addressof()"); 723a07aba5dSTimm Baeder } 724a07aba5dSTimm Baeder return true; 725a07aba5dSTimm Baeder } 726a07aba5dSTimm Baeder 727a07aba5dSTimm Baeder static bool interp__builtin_move(InterpState &S, CodePtr OpPC, 728a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *Func, 729a07aba5dSTimm Baeder const CallExpr *Call) { 730a07aba5dSTimm Baeder 731a07aba5dSTimm Baeder PrimType ArgT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr); 732a07aba5dSTimm Baeder 733a07aba5dSTimm Baeder TYPE_SWITCH(ArgT, const T &Arg = S.Stk.peek<T>(); S.Stk.push<T>(Arg);); 734a07aba5dSTimm Baeder 735a07aba5dSTimm Baeder return Func->getDecl()->isConstexpr(); 736a07aba5dSTimm Baeder } 737a07aba5dSTimm Baeder 738a07aba5dSTimm Baeder static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC, 739a07aba5dSTimm Baeder const InterpFrame *Frame, 740a07aba5dSTimm Baeder const Function *Func, 741a07aba5dSTimm Baeder const CallExpr *Call) { 742a07aba5dSTimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 743a07aba5dSTimm Baeder APSInt Arg = peekToAPSInt(S.Stk, ArgT); 744a07aba5dSTimm Baeder 745d9e72860Syronglin int Result = S.getASTContext().getTargetInfo().getEHDataRegisterNumber( 746d9e72860Syronglin Arg.getZExtValue()); 747a07aba5dSTimm Baeder pushInteger(S, Result, Call->getType()); 748a07aba5dSTimm Baeder return true; 749a07aba5dSTimm Baeder } 750a07aba5dSTimm Baeder 751a07aba5dSTimm Baeder /// Just takes the first Argument to the call and puts it on the stack. 752a07aba5dSTimm Baeder static bool noopPointer(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, 753a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call) { 754a07aba5dSTimm Baeder const Pointer &Arg = S.Stk.peek<Pointer>(); 755a07aba5dSTimm Baeder S.Stk.push<Pointer>(Arg); 756a07aba5dSTimm Baeder return true; 757a07aba5dSTimm Baeder } 758a07aba5dSTimm Baeder 759a07aba5dSTimm Baeder // Two integral values followed by a pointer (lhs, rhs, resultOut) 760a07aba5dSTimm Baeder static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC, 761a07aba5dSTimm Baeder const InterpFrame *Frame, 762a07aba5dSTimm Baeder const Function *Func, 763a07aba5dSTimm Baeder const CallExpr *Call) { 764a07aba5dSTimm Baeder Pointer &ResultPtr = S.Stk.peek<Pointer>(); 765a07aba5dSTimm Baeder if (ResultPtr.isDummy()) 766a07aba5dSTimm Baeder return false; 767a07aba5dSTimm Baeder 768a07aba5dSTimm Baeder unsigned BuiltinOp = Func->getBuiltinID(); 769a07aba5dSTimm Baeder PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType()); 770a07aba5dSTimm Baeder PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType()); 771a07aba5dSTimm Baeder APSInt RHS = peekToAPSInt(S.Stk, RHST, 772a07aba5dSTimm Baeder align(primSize(PT_Ptr)) + align(primSize(RHST))); 773a07aba5dSTimm Baeder APSInt LHS = peekToAPSInt(S.Stk, LHST, 774a07aba5dSTimm Baeder align(primSize(PT_Ptr)) + align(primSize(RHST)) + 775a07aba5dSTimm Baeder align(primSize(LHST))); 776a07aba5dSTimm Baeder QualType ResultType = Call->getArg(2)->getType()->getPointeeType(); 777a07aba5dSTimm Baeder PrimType ResultT = *S.getContext().classify(ResultType); 778a07aba5dSTimm Baeder bool Overflow; 779a07aba5dSTimm Baeder 780a07aba5dSTimm Baeder APSInt Result; 781a07aba5dSTimm Baeder if (BuiltinOp == Builtin::BI__builtin_add_overflow || 782a07aba5dSTimm Baeder BuiltinOp == Builtin::BI__builtin_sub_overflow || 783a07aba5dSTimm Baeder BuiltinOp == Builtin::BI__builtin_mul_overflow) { 784a07aba5dSTimm Baeder bool IsSigned = LHS.isSigned() || RHS.isSigned() || 785a07aba5dSTimm Baeder ResultType->isSignedIntegerOrEnumerationType(); 786a07aba5dSTimm Baeder bool AllSigned = LHS.isSigned() && RHS.isSigned() && 787a07aba5dSTimm Baeder ResultType->isSignedIntegerOrEnumerationType(); 788a07aba5dSTimm Baeder uint64_t LHSSize = LHS.getBitWidth(); 789a07aba5dSTimm Baeder uint64_t RHSSize = RHS.getBitWidth(); 790d9e72860Syronglin uint64_t ResultSize = S.getASTContext().getTypeSize(ResultType); 791a07aba5dSTimm Baeder uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize); 792a07aba5dSTimm Baeder 793a07aba5dSTimm Baeder // Add an additional bit if the signedness isn't uniformly agreed to. We 794a07aba5dSTimm Baeder // could do this ONLY if there is a signed and an unsigned that both have 795a07aba5dSTimm Baeder // MaxBits, but the code to check that is pretty nasty. The issue will be 796a07aba5dSTimm Baeder // caught in the shrink-to-result later anyway. 797a07aba5dSTimm Baeder if (IsSigned && !AllSigned) 798a07aba5dSTimm Baeder ++MaxBits; 799a07aba5dSTimm Baeder 800a07aba5dSTimm Baeder LHS = APSInt(LHS.extOrTrunc(MaxBits), !IsSigned); 801a07aba5dSTimm Baeder RHS = APSInt(RHS.extOrTrunc(MaxBits), !IsSigned); 802a07aba5dSTimm Baeder Result = APSInt(MaxBits, !IsSigned); 803a07aba5dSTimm Baeder } 804a07aba5dSTimm Baeder 805a07aba5dSTimm Baeder // Find largest int. 806a07aba5dSTimm Baeder switch (BuiltinOp) { 807a07aba5dSTimm Baeder default: 808a07aba5dSTimm Baeder llvm_unreachable("Invalid value for BuiltinOp"); 809a07aba5dSTimm Baeder case Builtin::BI__builtin_add_overflow: 810a07aba5dSTimm Baeder case Builtin::BI__builtin_sadd_overflow: 811a07aba5dSTimm Baeder case Builtin::BI__builtin_saddl_overflow: 812a07aba5dSTimm Baeder case Builtin::BI__builtin_saddll_overflow: 813a07aba5dSTimm Baeder case Builtin::BI__builtin_uadd_overflow: 814a07aba5dSTimm Baeder case Builtin::BI__builtin_uaddl_overflow: 815a07aba5dSTimm Baeder case Builtin::BI__builtin_uaddll_overflow: 816a07aba5dSTimm Baeder Result = LHS.isSigned() ? LHS.sadd_ov(RHS, Overflow) 817a07aba5dSTimm Baeder : LHS.uadd_ov(RHS, Overflow); 818a07aba5dSTimm Baeder break; 819a07aba5dSTimm Baeder case Builtin::BI__builtin_sub_overflow: 820a07aba5dSTimm Baeder case Builtin::BI__builtin_ssub_overflow: 821a07aba5dSTimm Baeder case Builtin::BI__builtin_ssubl_overflow: 822a07aba5dSTimm Baeder case Builtin::BI__builtin_ssubll_overflow: 823a07aba5dSTimm Baeder case Builtin::BI__builtin_usub_overflow: 824a07aba5dSTimm Baeder case Builtin::BI__builtin_usubl_overflow: 825a07aba5dSTimm Baeder case Builtin::BI__builtin_usubll_overflow: 826a07aba5dSTimm Baeder Result = LHS.isSigned() ? LHS.ssub_ov(RHS, Overflow) 827a07aba5dSTimm Baeder : LHS.usub_ov(RHS, Overflow); 828a07aba5dSTimm Baeder break; 829a07aba5dSTimm Baeder case Builtin::BI__builtin_mul_overflow: 830a07aba5dSTimm Baeder case Builtin::BI__builtin_smul_overflow: 831a07aba5dSTimm Baeder case Builtin::BI__builtin_smull_overflow: 832a07aba5dSTimm Baeder case Builtin::BI__builtin_smulll_overflow: 833a07aba5dSTimm Baeder case Builtin::BI__builtin_umul_overflow: 834a07aba5dSTimm Baeder case Builtin::BI__builtin_umull_overflow: 835a07aba5dSTimm Baeder case Builtin::BI__builtin_umulll_overflow: 836a07aba5dSTimm Baeder Result = LHS.isSigned() ? LHS.smul_ov(RHS, Overflow) 837a07aba5dSTimm Baeder : LHS.umul_ov(RHS, Overflow); 838a07aba5dSTimm Baeder break; 839a07aba5dSTimm Baeder } 840a07aba5dSTimm Baeder 841a07aba5dSTimm Baeder // In the case where multiple sizes are allowed, truncate and see if 842a07aba5dSTimm Baeder // the values are the same. 843a07aba5dSTimm Baeder if (BuiltinOp == Builtin::BI__builtin_add_overflow || 844a07aba5dSTimm Baeder BuiltinOp == Builtin::BI__builtin_sub_overflow || 845a07aba5dSTimm Baeder BuiltinOp == Builtin::BI__builtin_mul_overflow) { 846a07aba5dSTimm Baeder // APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead, 847a07aba5dSTimm Baeder // since it will give us the behavior of a TruncOrSelf in the case where 848a07aba5dSTimm Baeder // its parameter <= its size. We previously set Result to be at least the 849a07aba5dSTimm Baeder // type-size of the result, so getTypeSize(ResultType) <= Resu 850d9e72860Syronglin APSInt Temp = Result.extOrTrunc(S.getASTContext().getTypeSize(ResultType)); 851a07aba5dSTimm Baeder Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType()); 852a07aba5dSTimm Baeder 853a07aba5dSTimm Baeder if (!APSInt::isSameValue(Temp, Result)) 854a07aba5dSTimm Baeder Overflow = true; 855a07aba5dSTimm Baeder Result = Temp; 856a07aba5dSTimm Baeder } 857a07aba5dSTimm Baeder 858a07aba5dSTimm Baeder // Write Result to ResultPtr and put Overflow on the stacl. 859a07aba5dSTimm Baeder assignInteger(ResultPtr, ResultT, Result); 860a07aba5dSTimm Baeder ResultPtr.initialize(); 861a07aba5dSTimm Baeder assert(Func->getDecl()->getReturnType()->isBooleanType()); 862a07aba5dSTimm Baeder S.Stk.push<Boolean>(Overflow); 863a07aba5dSTimm Baeder return true; 864a07aba5dSTimm Baeder } 865a07aba5dSTimm Baeder 866a07aba5dSTimm Baeder /// Three integral values followed by a pointer (lhs, rhs, carry, carryOut). 867a07aba5dSTimm Baeder static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC, 868a07aba5dSTimm Baeder const InterpFrame *Frame, 869a07aba5dSTimm Baeder const Function *Func, 870a07aba5dSTimm Baeder const CallExpr *Call) { 871a07aba5dSTimm Baeder unsigned BuiltinOp = Func->getBuiltinID(); 872a07aba5dSTimm Baeder PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType()); 873a07aba5dSTimm Baeder PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType()); 874a07aba5dSTimm Baeder PrimType CarryT = *S.getContext().classify(Call->getArg(2)->getType()); 875a07aba5dSTimm Baeder APSInt RHS = peekToAPSInt(S.Stk, RHST, 876a07aba5dSTimm Baeder align(primSize(PT_Ptr)) + align(primSize(CarryT)) + 877a07aba5dSTimm Baeder align(primSize(RHST))); 878a07aba5dSTimm Baeder APSInt LHS = 879a07aba5dSTimm Baeder peekToAPSInt(S.Stk, LHST, 880a07aba5dSTimm Baeder align(primSize(PT_Ptr)) + align(primSize(RHST)) + 881a07aba5dSTimm Baeder align(primSize(CarryT)) + align(primSize(LHST))); 882a07aba5dSTimm Baeder APSInt CarryIn = peekToAPSInt( 883a07aba5dSTimm Baeder S.Stk, LHST, align(primSize(PT_Ptr)) + align(primSize(CarryT))); 884a07aba5dSTimm Baeder APSInt CarryOut; 885a07aba5dSTimm Baeder 886a07aba5dSTimm Baeder APSInt Result; 887a07aba5dSTimm Baeder // Copy the number of bits and sign. 888a07aba5dSTimm Baeder Result = LHS; 889a07aba5dSTimm Baeder CarryOut = LHS; 890a07aba5dSTimm Baeder 891a07aba5dSTimm Baeder bool FirstOverflowed = false; 892a07aba5dSTimm Baeder bool SecondOverflowed = false; 893a07aba5dSTimm Baeder switch (BuiltinOp) { 894a07aba5dSTimm Baeder default: 895a07aba5dSTimm Baeder llvm_unreachable("Invalid value for BuiltinOp"); 896a07aba5dSTimm Baeder case Builtin::BI__builtin_addcb: 897a07aba5dSTimm Baeder case Builtin::BI__builtin_addcs: 898a07aba5dSTimm Baeder case Builtin::BI__builtin_addc: 899a07aba5dSTimm Baeder case Builtin::BI__builtin_addcl: 900a07aba5dSTimm Baeder case Builtin::BI__builtin_addcll: 901a07aba5dSTimm Baeder Result = 902a07aba5dSTimm Baeder LHS.uadd_ov(RHS, FirstOverflowed).uadd_ov(CarryIn, SecondOverflowed); 903a07aba5dSTimm Baeder break; 904a07aba5dSTimm Baeder case Builtin::BI__builtin_subcb: 905a07aba5dSTimm Baeder case Builtin::BI__builtin_subcs: 906a07aba5dSTimm Baeder case Builtin::BI__builtin_subc: 907a07aba5dSTimm Baeder case Builtin::BI__builtin_subcl: 908a07aba5dSTimm Baeder case Builtin::BI__builtin_subcll: 909a07aba5dSTimm Baeder Result = 910a07aba5dSTimm Baeder LHS.usub_ov(RHS, FirstOverflowed).usub_ov(CarryIn, SecondOverflowed); 911a07aba5dSTimm Baeder break; 912a07aba5dSTimm Baeder } 913a07aba5dSTimm Baeder // It is possible for both overflows to happen but CGBuiltin uses an OR so 914a07aba5dSTimm Baeder // this is consistent. 915a07aba5dSTimm Baeder CarryOut = (uint64_t)(FirstOverflowed | SecondOverflowed); 916a07aba5dSTimm Baeder 917a07aba5dSTimm Baeder Pointer &CarryOutPtr = S.Stk.peek<Pointer>(); 918a07aba5dSTimm Baeder QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType(); 919a07aba5dSTimm Baeder PrimType CarryOutT = *S.getContext().classify(CarryOutType); 920a07aba5dSTimm Baeder assignInteger(CarryOutPtr, CarryOutT, CarryOut); 921a07aba5dSTimm Baeder CarryOutPtr.initialize(); 922a07aba5dSTimm Baeder 923a07aba5dSTimm Baeder assert(Call->getType() == Call->getArg(0)->getType()); 924a07aba5dSTimm Baeder pushInteger(S, Result, Call->getType()); 925a07aba5dSTimm Baeder return true; 926a07aba5dSTimm Baeder } 927a07aba5dSTimm Baeder 928a07aba5dSTimm Baeder static bool interp__builtin_clz(InterpState &S, CodePtr OpPC, 929a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *Func, 930a07aba5dSTimm Baeder const CallExpr *Call) { 931a07aba5dSTimm Baeder unsigned CallSize = callArgSize(S, Call); 932a07aba5dSTimm Baeder unsigned BuiltinOp = Func->getBuiltinID(); 933a07aba5dSTimm Baeder PrimType ValT = *S.getContext().classify(Call->getArg(0)); 934a07aba5dSTimm Baeder const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize); 935a07aba5dSTimm Baeder 936a07aba5dSTimm Baeder // When the argument is 0, the result of GCC builtins is undefined, whereas 937a07aba5dSTimm Baeder // for Microsoft intrinsics, the result is the bit-width of the argument. 938a07aba5dSTimm Baeder bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 && 939a07aba5dSTimm Baeder BuiltinOp != Builtin::BI__lzcnt && 940a07aba5dSTimm Baeder BuiltinOp != Builtin::BI__lzcnt64; 941a07aba5dSTimm Baeder 942a07aba5dSTimm Baeder if (Val == 0) { 943a07aba5dSTimm Baeder if (Func->getBuiltinID() == Builtin::BI__builtin_clzg && 944a07aba5dSTimm Baeder Call->getNumArgs() == 2) { 945a07aba5dSTimm Baeder // We have a fallback parameter. 946a07aba5dSTimm Baeder PrimType FallbackT = *S.getContext().classify(Call->getArg(1)); 947a07aba5dSTimm Baeder const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT); 948a07aba5dSTimm Baeder pushInteger(S, Fallback, Call->getType()); 949a07aba5dSTimm Baeder return true; 950a07aba5dSTimm Baeder } 951a07aba5dSTimm Baeder 952a07aba5dSTimm Baeder if (ZeroIsUndefined) 953a07aba5dSTimm Baeder return false; 954a07aba5dSTimm Baeder } 955a07aba5dSTimm Baeder 956a07aba5dSTimm Baeder pushInteger(S, Val.countl_zero(), Call->getType()); 957a07aba5dSTimm Baeder return true; 958a07aba5dSTimm Baeder } 959a07aba5dSTimm Baeder 960a07aba5dSTimm Baeder static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC, 961a07aba5dSTimm Baeder const InterpFrame *Frame, const Function *Func, 962a07aba5dSTimm Baeder const CallExpr *Call) { 963a07aba5dSTimm Baeder unsigned CallSize = callArgSize(S, Call); 964a07aba5dSTimm Baeder PrimType ValT = *S.getContext().classify(Call->getArg(0)); 965a07aba5dSTimm Baeder const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize); 966a07aba5dSTimm Baeder 967a07aba5dSTimm Baeder if (Val == 0) { 968a07aba5dSTimm Baeder if (Func->getBuiltinID() == Builtin::BI__builtin_ctzg && 969a07aba5dSTimm Baeder Call->getNumArgs() == 2) { 970a07aba5dSTimm Baeder // We have a fallback parameter. 971a07aba5dSTimm Baeder PrimType FallbackT = *S.getContext().classify(Call->getArg(1)); 972a07aba5dSTimm Baeder const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT); 973a07aba5dSTimm Baeder pushInteger(S, Fallback, Call->getType()); 974a07aba5dSTimm Baeder return true; 975a07aba5dSTimm Baeder } 976a07aba5dSTimm Baeder return false; 977a07aba5dSTimm Baeder } 978a07aba5dSTimm Baeder 979a07aba5dSTimm Baeder pushInteger(S, Val.countr_zero(), Call->getType()); 980a07aba5dSTimm Baeder return true; 981a07aba5dSTimm Baeder } 982a07aba5dSTimm Baeder 983a07aba5dSTimm Baeder static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC, 984a07aba5dSTimm Baeder const InterpFrame *Frame, 985a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call) { 986a07aba5dSTimm Baeder PrimType ReturnT = *S.getContext().classify(Call->getType()); 987a07aba5dSTimm Baeder PrimType ValT = *S.getContext().classify(Call->getArg(0)); 988a07aba5dSTimm Baeder const APSInt &Val = peekToAPSInt(S.Stk, ValT); 989a07aba5dSTimm Baeder assert(Val.getActiveBits() <= 64); 990a07aba5dSTimm Baeder 991a07aba5dSTimm Baeder INT_TYPE_SWITCH(ReturnT, 992a07aba5dSTimm Baeder { S.Stk.push<T>(T::from(Val.byteSwap().getZExtValue())); }); 993a07aba5dSTimm Baeder return true; 994a07aba5dSTimm Baeder } 995a07aba5dSTimm Baeder 996a07aba5dSTimm Baeder /// bool __atomic_always_lock_free(size_t, void const volatile*) 997a07aba5dSTimm Baeder /// bool __atomic_is_lock_free(size_t, void const volatile*) 998a07aba5dSTimm Baeder /// bool __c11_atomic_is_lock_free(size_t) 999a07aba5dSTimm Baeder static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC, 1000a07aba5dSTimm Baeder const InterpFrame *Frame, 1001a07aba5dSTimm Baeder const Function *Func, 1002a07aba5dSTimm Baeder const CallExpr *Call) { 1003a07aba5dSTimm Baeder unsigned BuiltinOp = Func->getBuiltinID(); 1004a07aba5dSTimm Baeder 1005a07aba5dSTimm Baeder PrimType ValT = *S.getContext().classify(Call->getArg(0)); 1006a07aba5dSTimm Baeder unsigned SizeValOffset = 0; 1007a07aba5dSTimm Baeder if (BuiltinOp != Builtin::BI__c11_atomic_is_lock_free) 1008a07aba5dSTimm Baeder SizeValOffset = align(primSize(ValT)) + align(primSize(PT_Ptr)); 1009a07aba5dSTimm Baeder const APSInt &SizeVal = peekToAPSInt(S.Stk, ValT, SizeValOffset); 1010a07aba5dSTimm Baeder 1011a07aba5dSTimm Baeder auto returnBool = [&S](bool Value) -> bool { 1012a07aba5dSTimm Baeder S.Stk.push<Boolean>(Value); 1013a07aba5dSTimm Baeder return true; 1014a07aba5dSTimm Baeder }; 1015a07aba5dSTimm Baeder 1016a07aba5dSTimm Baeder // For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power 1017a07aba5dSTimm Baeder // of two less than or equal to the maximum inline atomic width, we know it 1018a07aba5dSTimm Baeder // is lock-free. If the size isn't a power of two, or greater than the 1019a07aba5dSTimm Baeder // maximum alignment where we promote atomics, we know it is not lock-free 1020a07aba5dSTimm Baeder // (at least not in the sense of atomic_is_lock_free). Otherwise, 1021a07aba5dSTimm Baeder // the answer can only be determined at runtime; for example, 16-byte 1022a07aba5dSTimm Baeder // atomics have lock-free implementations on some, but not all, 1023a07aba5dSTimm Baeder // x86-64 processors. 1024a07aba5dSTimm Baeder 1025a07aba5dSTimm Baeder // Check power-of-two. 1026a07aba5dSTimm Baeder CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue()); 1027a07aba5dSTimm Baeder if (Size.isPowerOfTwo()) { 1028a07aba5dSTimm Baeder // Check against inlining width. 1029a07aba5dSTimm Baeder unsigned InlineWidthBits = 1030d9e72860Syronglin S.getASTContext().getTargetInfo().getMaxAtomicInlineWidth(); 1031d9e72860Syronglin if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits)) { 1032a07aba5dSTimm Baeder 1033a07aba5dSTimm Baeder // OK, we will inline appropriately-aligned operations of this size, 1034a07aba5dSTimm Baeder // and _Atomic(T) is appropriately-aligned. 1035a07aba5dSTimm Baeder if (BuiltinOp == Builtin::BI__c11_atomic_is_lock_free || 1036a07aba5dSTimm Baeder Size == CharUnits::One()) 1037a07aba5dSTimm Baeder return returnBool(true); 1038a07aba5dSTimm Baeder 1039a07aba5dSTimm Baeder // Same for null pointers. 1040a07aba5dSTimm Baeder assert(BuiltinOp != Builtin::BI__c11_atomic_is_lock_free); 1041a07aba5dSTimm Baeder const Pointer &Ptr = S.Stk.peek<Pointer>(); 1042a07aba5dSTimm Baeder if (Ptr.isZero()) 1043a07aba5dSTimm Baeder return returnBool(true); 1044a07aba5dSTimm Baeder 1045a07aba5dSTimm Baeder if (Ptr.isIntegralPointer()) { 1046a07aba5dSTimm Baeder uint64_t IntVal = Ptr.getIntegerRepresentation(); 1047a07aba5dSTimm Baeder if (APSInt(APInt(64, IntVal, false), true).isAligned(Size.getAsAlign())) 1048a07aba5dSTimm Baeder return returnBool(true); 1049a07aba5dSTimm Baeder } 1050a07aba5dSTimm Baeder 1051a07aba5dSTimm Baeder const Expr *PtrArg = Call->getArg(1); 1052a07aba5dSTimm Baeder // Otherwise, check if the type's alignment against Size. 1053a07aba5dSTimm Baeder if (const auto *ICE = dyn_cast<ImplicitCastExpr>(PtrArg)) { 1054a07aba5dSTimm Baeder // Drop the potential implicit-cast to 'const volatile void*', getting 1055a07aba5dSTimm Baeder // the underlying type. 1056a07aba5dSTimm Baeder if (ICE->getCastKind() == CK_BitCast) 1057a07aba5dSTimm Baeder PtrArg = ICE->getSubExpr(); 1058a07aba5dSTimm Baeder } 1059a07aba5dSTimm Baeder 1060a07aba5dSTimm Baeder if (auto PtrTy = PtrArg->getType()->getAs<PointerType>()) { 1061a07aba5dSTimm Baeder QualType PointeeType = PtrTy->getPointeeType(); 1062a07aba5dSTimm Baeder if (!PointeeType->isIncompleteType() && 1063d9e72860Syronglin S.getASTContext().getTypeAlignInChars(PointeeType) >= Size) { 1064a07aba5dSTimm Baeder // OK, we will inline operations on this object. 1065a07aba5dSTimm Baeder return returnBool(true); 1066a07aba5dSTimm Baeder } 1067a07aba5dSTimm Baeder } 1068a07aba5dSTimm Baeder } 1069a07aba5dSTimm Baeder } 1070a07aba5dSTimm Baeder 1071a07aba5dSTimm Baeder if (BuiltinOp == Builtin::BI__atomic_always_lock_free) 1072a07aba5dSTimm Baeder return returnBool(false); 1073a07aba5dSTimm Baeder 1074a07aba5dSTimm Baeder return false; 1075a07aba5dSTimm Baeder } 1076a07aba5dSTimm Baeder 1077a07aba5dSTimm Baeder /// __builtin_complex(Float A, float B); 1078a07aba5dSTimm Baeder static bool interp__builtin_complex(InterpState &S, CodePtr OpPC, 1079a07aba5dSTimm Baeder const InterpFrame *Frame, 1080a07aba5dSTimm Baeder const Function *Func, 1081a07aba5dSTimm Baeder const CallExpr *Call) { 1082a07aba5dSTimm Baeder const Floating &Arg2 = S.Stk.peek<Floating>(); 1083a07aba5dSTimm Baeder const Floating &Arg1 = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2); 1084a07aba5dSTimm Baeder Pointer &Result = S.Stk.peek<Pointer>(align(primSize(PT_Float)) * 2 + 1085a07aba5dSTimm Baeder align(primSize(PT_Ptr))); 1086a07aba5dSTimm Baeder 1087a07aba5dSTimm Baeder Result.atIndex(0).deref<Floating>() = Arg1; 1088a07aba5dSTimm Baeder Result.atIndex(0).initialize(); 1089a07aba5dSTimm Baeder Result.atIndex(1).deref<Floating>() = Arg2; 1090a07aba5dSTimm Baeder Result.atIndex(1).initialize(); 1091a07aba5dSTimm Baeder Result.initialize(); 1092a07aba5dSTimm Baeder 1093a07aba5dSTimm Baeder return true; 1094a07aba5dSTimm Baeder } 1095a07aba5dSTimm Baeder 1096a07aba5dSTimm Baeder /// __builtin_is_aligned() 1097a07aba5dSTimm Baeder /// __builtin_align_up() 1098a07aba5dSTimm Baeder /// __builtin_align_down() 1099a07aba5dSTimm Baeder /// The first parameter is either an integer or a pointer. 1100a07aba5dSTimm Baeder /// The second parameter is the requested alignment as an integer. 1101a07aba5dSTimm Baeder static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC, 1102a07aba5dSTimm Baeder const InterpFrame *Frame, 1103a07aba5dSTimm Baeder const Function *Func, 1104a07aba5dSTimm Baeder const CallExpr *Call) { 1105a07aba5dSTimm Baeder unsigned BuiltinOp = Func->getBuiltinID(); 1106a07aba5dSTimm Baeder unsigned CallSize = callArgSize(S, Call); 1107a07aba5dSTimm Baeder 1108a07aba5dSTimm Baeder PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1)); 1109a07aba5dSTimm Baeder const APSInt &Alignment = peekToAPSInt(S.Stk, AlignmentT); 1110a07aba5dSTimm Baeder 1111a07aba5dSTimm Baeder if (Alignment < 0 || !Alignment.isPowerOf2()) { 1112a07aba5dSTimm Baeder S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment; 1113a07aba5dSTimm Baeder return false; 1114a07aba5dSTimm Baeder } 1115d9e72860Syronglin unsigned SrcWidth = S.getASTContext().getIntWidth(Call->getArg(0)->getType()); 1116a07aba5dSTimm Baeder APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1)); 1117a07aba5dSTimm Baeder if (APSInt::compareValues(Alignment, MaxValue) > 0) { 1118a07aba5dSTimm Baeder S.FFDiag(Call, diag::note_constexpr_alignment_too_big) 1119a07aba5dSTimm Baeder << MaxValue << Call->getArg(0)->getType() << Alignment; 1120a07aba5dSTimm Baeder return false; 1121a07aba5dSTimm Baeder } 1122a07aba5dSTimm Baeder 1123a07aba5dSTimm Baeder // The first parameter is either an integer or a pointer (but not a function 1124a07aba5dSTimm Baeder // pointer). 1125a07aba5dSTimm Baeder PrimType FirstArgT = *S.Ctx.classify(Call->getArg(0)); 1126a07aba5dSTimm Baeder 1127a07aba5dSTimm Baeder if (isIntegralType(FirstArgT)) { 1128a07aba5dSTimm Baeder const APSInt &Src = peekToAPSInt(S.Stk, FirstArgT, CallSize); 1129a07aba5dSTimm Baeder APSInt Align = Alignment.extOrTrunc(Src.getBitWidth()); 1130a07aba5dSTimm Baeder if (BuiltinOp == Builtin::BI__builtin_align_up) { 1131a07aba5dSTimm Baeder APSInt AlignedVal = 1132a07aba5dSTimm Baeder APSInt((Src + (Align - 1)) & ~(Align - 1), Src.isUnsigned()); 1133a07aba5dSTimm Baeder pushInteger(S, AlignedVal, Call->getType()); 1134a07aba5dSTimm Baeder } else if (BuiltinOp == Builtin::BI__builtin_align_down) { 1135a07aba5dSTimm Baeder APSInt AlignedVal = APSInt(Src & ~(Align - 1), Src.isUnsigned()); 1136a07aba5dSTimm Baeder pushInteger(S, AlignedVal, Call->getType()); 1137a07aba5dSTimm Baeder } else { 1138a07aba5dSTimm Baeder assert(*S.Ctx.classify(Call->getType()) == PT_Bool); 1139a07aba5dSTimm Baeder S.Stk.push<Boolean>((Src & (Align - 1)) == 0); 1140a07aba5dSTimm Baeder } 1141a07aba5dSTimm Baeder return true; 1142a07aba5dSTimm Baeder } 1143a07aba5dSTimm Baeder 1144a07aba5dSTimm Baeder assert(FirstArgT == PT_Ptr); 1145a07aba5dSTimm Baeder const Pointer &Ptr = S.Stk.peek<Pointer>(CallSize); 1146a07aba5dSTimm Baeder 1147a07aba5dSTimm Baeder unsigned PtrOffset = Ptr.getByteOffset(); 1148a07aba5dSTimm Baeder PtrOffset = Ptr.getIndex(); 1149a07aba5dSTimm Baeder CharUnits BaseAlignment = 1150d9e72860Syronglin S.getASTContext().getDeclAlign(Ptr.getDeclDesc()->asValueDecl()); 1151a07aba5dSTimm Baeder CharUnits PtrAlign = 1152a07aba5dSTimm Baeder BaseAlignment.alignmentAtOffset(CharUnits::fromQuantity(PtrOffset)); 1153a07aba5dSTimm Baeder 1154a07aba5dSTimm Baeder if (BuiltinOp == Builtin::BI__builtin_is_aligned) { 1155a07aba5dSTimm Baeder if (PtrAlign.getQuantity() >= Alignment) { 1156a07aba5dSTimm Baeder S.Stk.push<Boolean>(true); 1157a07aba5dSTimm Baeder return true; 1158a07aba5dSTimm Baeder } 1159a07aba5dSTimm Baeder // If the alignment is not known to be sufficient, some cases could still 1160a07aba5dSTimm Baeder // be aligned at run time. However, if the requested alignment is less or 1161a07aba5dSTimm Baeder // equal to the base alignment and the offset is not aligned, we know that 1162a07aba5dSTimm Baeder // the run-time value can never be aligned. 1163a07aba5dSTimm Baeder if (BaseAlignment.getQuantity() >= Alignment && 1164a07aba5dSTimm Baeder PtrAlign.getQuantity() < Alignment) { 1165a07aba5dSTimm Baeder S.Stk.push<Boolean>(false); 1166a07aba5dSTimm Baeder return true; 1167a07aba5dSTimm Baeder } 1168a07aba5dSTimm Baeder 1169a07aba5dSTimm Baeder S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_compute) 1170a07aba5dSTimm Baeder << Alignment; 1171a07aba5dSTimm Baeder return false; 1172a07aba5dSTimm Baeder } 1173a07aba5dSTimm Baeder 1174a07aba5dSTimm Baeder assert(BuiltinOp == Builtin::BI__builtin_align_down || 1175a07aba5dSTimm Baeder BuiltinOp == Builtin::BI__builtin_align_up); 1176a07aba5dSTimm Baeder 1177a07aba5dSTimm Baeder // For align_up/align_down, we can return the same value if the alignment 1178a07aba5dSTimm Baeder // is known to be greater or equal to the requested value. 1179a07aba5dSTimm Baeder if (PtrAlign.getQuantity() >= Alignment) { 1180a07aba5dSTimm Baeder S.Stk.push<Pointer>(Ptr); 1181a07aba5dSTimm Baeder return true; 1182a07aba5dSTimm Baeder } 1183a07aba5dSTimm Baeder 1184a07aba5dSTimm Baeder // The alignment could be greater than the minimum at run-time, so we cannot 1185a07aba5dSTimm Baeder // infer much about the resulting pointer value. One case is possible: 1186a07aba5dSTimm Baeder // For `_Alignas(32) char buf[N]; __builtin_align_down(&buf[idx], 32)` we 1187a07aba5dSTimm Baeder // can infer the correct index if the requested alignment is smaller than 1188a07aba5dSTimm Baeder // the base alignment so we can perform the computation on the offset. 1189a07aba5dSTimm Baeder if (BaseAlignment.getQuantity() >= Alignment) { 1190a07aba5dSTimm Baeder assert(Alignment.getBitWidth() <= 64 && 1191a07aba5dSTimm Baeder "Cannot handle > 64-bit address-space"); 1192a07aba5dSTimm Baeder uint64_t Alignment64 = Alignment.getZExtValue(); 1193a07aba5dSTimm Baeder CharUnits NewOffset = 1194a07aba5dSTimm Baeder CharUnits::fromQuantity(BuiltinOp == Builtin::BI__builtin_align_down 1195a07aba5dSTimm Baeder ? llvm::alignDown(PtrOffset, Alignment64) 1196a07aba5dSTimm Baeder : llvm::alignTo(PtrOffset, Alignment64)); 1197a07aba5dSTimm Baeder 1198a07aba5dSTimm Baeder S.Stk.push<Pointer>(Ptr.atIndex(NewOffset.getQuantity())); 1199a07aba5dSTimm Baeder return true; 1200a07aba5dSTimm Baeder } 1201a07aba5dSTimm Baeder 1202a07aba5dSTimm Baeder // Otherwise, we cannot constant-evaluate the result. 1203a07aba5dSTimm Baeder S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_adjust) << Alignment; 1204a07aba5dSTimm Baeder return false; 1205a07aba5dSTimm Baeder } 1206a07aba5dSTimm Baeder 120780c15c48STimm Baeder /// __builtin_assume_aligned(Ptr, Alignment[, ExtraOffset]) 120880c15c48STimm Baeder static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC, 120980c15c48STimm Baeder const InterpFrame *Frame, 121080c15c48STimm Baeder const Function *Func, 121180c15c48STimm Baeder const CallExpr *Call) { 121280c15c48STimm Baeder assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3); 121380c15c48STimm Baeder 121480c15c48STimm Baeder // Might be called with function pointers in C. 121580c15c48STimm Baeder std::optional<PrimType> PtrT = S.Ctx.classify(Call->getArg(0)); 121680c15c48STimm Baeder if (PtrT != PT_Ptr) 121780c15c48STimm Baeder return false; 121880c15c48STimm Baeder 121980c15c48STimm Baeder unsigned ArgSize = callArgSize(S, Call); 122080c15c48STimm Baeder const Pointer &Ptr = S.Stk.peek<Pointer>(ArgSize); 122180c15c48STimm Baeder std::optional<APSInt> ExtraOffset; 122280c15c48STimm Baeder APSInt Alignment; 122380c15c48STimm Baeder if (Call->getNumArgs() == 2) { 122480c15c48STimm Baeder Alignment = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1))); 122580c15c48STimm Baeder } else { 122680c15c48STimm Baeder PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1)); 122780c15c48STimm Baeder PrimType ExtraOffsetT = *S.Ctx.classify(Call->getArg(2)); 122880c15c48STimm Baeder Alignment = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)), 122980c15c48STimm Baeder align(primSize(AlignmentT)) + 123080c15c48STimm Baeder align(primSize(ExtraOffsetT))); 123180c15c48STimm Baeder ExtraOffset = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(2))); 123280c15c48STimm Baeder } 123380c15c48STimm Baeder 123480c15c48STimm Baeder CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue()); 123580c15c48STimm Baeder 123680c15c48STimm Baeder // If there is a base object, then it must have the correct alignment. 123780c15c48STimm Baeder if (Ptr.isBlockPointer()) { 123880c15c48STimm Baeder CharUnits BaseAlignment; 123980c15c48STimm Baeder if (const auto *VD = Ptr.getDeclDesc()->asValueDecl()) 124080c15c48STimm Baeder BaseAlignment = S.getASTContext().getDeclAlign(VD); 124180c15c48STimm Baeder else if (const auto *E = Ptr.getDeclDesc()->asExpr()) 124280c15c48STimm Baeder BaseAlignment = GetAlignOfExpr(S.getASTContext(), E, UETT_AlignOf); 124380c15c48STimm Baeder 124480c15c48STimm Baeder if (BaseAlignment < Align) { 124580c15c48STimm Baeder S.CCEDiag(Call->getArg(0), 124680c15c48STimm Baeder diag::note_constexpr_baa_insufficient_alignment) 124780c15c48STimm Baeder << 0 << BaseAlignment.getQuantity() << Align.getQuantity(); 124880c15c48STimm Baeder return false; 124980c15c48STimm Baeder } 125080c15c48STimm Baeder } 125180c15c48STimm Baeder 125280c15c48STimm Baeder APValue AV = Ptr.toAPValue(S.getASTContext()); 125380c15c48STimm Baeder CharUnits AVOffset = AV.getLValueOffset(); 125480c15c48STimm Baeder if (ExtraOffset) 125580c15c48STimm Baeder AVOffset -= CharUnits::fromQuantity(ExtraOffset->getZExtValue()); 125680c15c48STimm Baeder if (AVOffset.alignTo(Align) != AVOffset) { 125780c15c48STimm Baeder if (Ptr.isBlockPointer()) 125880c15c48STimm Baeder S.CCEDiag(Call->getArg(0), 125980c15c48STimm Baeder diag::note_constexpr_baa_insufficient_alignment) 126080c15c48STimm Baeder << 1 << AVOffset.getQuantity() << Align.getQuantity(); 126180c15c48STimm Baeder else 126280c15c48STimm Baeder S.CCEDiag(Call->getArg(0), 126380c15c48STimm Baeder diag::note_constexpr_baa_value_insufficient_alignment) 126480c15c48STimm Baeder << AVOffset.getQuantity() << Align.getQuantity(); 126580c15c48STimm Baeder return false; 126680c15c48STimm Baeder } 126780c15c48STimm Baeder 126880c15c48STimm Baeder S.Stk.push<Pointer>(Ptr); 126980c15c48STimm Baeder return true; 127080c15c48STimm Baeder } 127180c15c48STimm Baeder 127285181788STimm Baeder static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC, 127385181788STimm Baeder const InterpFrame *Frame, 127485181788STimm Baeder const Function *Func, 127585181788STimm Baeder const CallExpr *Call) { 12768951b514STimm Baeder if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() || 1277615a5eb0STimm Baeder !Call->getArg(1)->getType()->isIntegerType()) 1278615a5eb0STimm Baeder return false; 1279615a5eb0STimm Baeder 128085181788STimm Baeder PrimType ValT = *S.Ctx.classify(Call->getArg(0)); 128185181788STimm Baeder PrimType IndexT = *S.Ctx.classify(Call->getArg(1)); 128285181788STimm Baeder APSInt Val = peekToAPSInt(S.Stk, ValT, 128385181788STimm Baeder align(primSize(ValT)) + align(primSize(IndexT))); 128485181788STimm Baeder APSInt Index = peekToAPSInt(S.Stk, IndexT); 128585181788STimm Baeder 128685181788STimm Baeder unsigned BitWidth = Val.getBitWidth(); 128785181788STimm Baeder uint64_t Shift = Index.extractBitsAsZExtValue(8, 0); 128885181788STimm Baeder uint64_t Length = Index.extractBitsAsZExtValue(8, 8); 128985181788STimm Baeder Length = Length > BitWidth ? BitWidth : Length; 129085181788STimm Baeder 129185181788STimm Baeder // Handle out of bounds cases. 129285181788STimm Baeder if (Length == 0 || Shift >= BitWidth) { 129385181788STimm Baeder pushInteger(S, 0, Call->getType()); 129485181788STimm Baeder return true; 129585181788STimm Baeder } 129685181788STimm Baeder 129785181788STimm Baeder uint64_t Result = Val.getZExtValue() >> Shift; 129885181788STimm Baeder Result &= llvm::maskTrailingOnes<uint64_t>(Length); 129985181788STimm Baeder pushInteger(S, Result, Call->getType()); 130085181788STimm Baeder return true; 130185181788STimm Baeder } 130285181788STimm Baeder 13037147e88fSTimm Baeder static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC, 13047147e88fSTimm Baeder const InterpFrame *Frame, 13057147e88fSTimm Baeder const Function *Func, 13067147e88fSTimm Baeder const CallExpr *Call) { 1307235067b2STimm Baeder QualType CallType = Call->getType(); 13088951b514STimm Baeder if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() || 13098951b514STimm Baeder !Call->getArg(1)->getType()->isIntegerType() || 13108951b514STimm Baeder !CallType->isIntegerType()) 1311235067b2STimm Baeder return false; 1312235067b2STimm Baeder 13137147e88fSTimm Baeder PrimType ValT = *S.Ctx.classify(Call->getArg(0)); 13147147e88fSTimm Baeder PrimType IndexT = *S.Ctx.classify(Call->getArg(1)); 13157147e88fSTimm Baeder 13167147e88fSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, ValT, 13177147e88fSTimm Baeder align(primSize(ValT)) + align(primSize(IndexT))); 13187147e88fSTimm Baeder APSInt Idx = peekToAPSInt(S.Stk, IndexT); 13197147e88fSTimm Baeder 13207147e88fSTimm Baeder unsigned BitWidth = Val.getBitWidth(); 13217147e88fSTimm Baeder uint64_t Index = Idx.extractBitsAsZExtValue(8, 0); 13227147e88fSTimm Baeder 13237147e88fSTimm Baeder if (Index < BitWidth) 13247147e88fSTimm Baeder Val.clearHighBits(BitWidth - Index); 13257147e88fSTimm Baeder 1326235067b2STimm Baeder pushInteger(S, Val, CallType); 13277147e88fSTimm Baeder return true; 13287147e88fSTimm Baeder } 13297147e88fSTimm Baeder 13307147e88fSTimm Baeder static bool interp__builtin_ia32_lzcnt(InterpState &S, CodePtr OpPC, 13317147e88fSTimm Baeder const InterpFrame *Frame, 13327147e88fSTimm Baeder const Function *Func, 13337147e88fSTimm Baeder const CallExpr *Call) { 1334e1e788f4STimm Baeder QualType CallType = Call->getType(); 13358951b514STimm Baeder if (!CallType->isIntegerType() || 13368951b514STimm Baeder !Call->getArg(0)->getType()->isIntegerType()) 1337e1e788f4STimm Baeder return false; 1338e1e788f4STimm Baeder 13397147e88fSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0))); 1340235067b2STimm Baeder pushInteger(S, Val.countLeadingZeros(), CallType); 13417147e88fSTimm Baeder return true; 13427147e88fSTimm Baeder } 13437147e88fSTimm Baeder 13447147e88fSTimm Baeder static bool interp__builtin_ia32_tzcnt(InterpState &S, CodePtr OpPC, 13457147e88fSTimm Baeder const InterpFrame *Frame, 13467147e88fSTimm Baeder const Function *Func, 13477147e88fSTimm Baeder const CallExpr *Call) { 1348e1e788f4STimm Baeder QualType CallType = Call->getType(); 13498951b514STimm Baeder if (!CallType->isIntegerType() || 13508951b514STimm Baeder !Call->getArg(0)->getType()->isIntegerType()) 1351e1e788f4STimm Baeder return false; 1352e1e788f4STimm Baeder 13537147e88fSTimm Baeder APSInt Val = peekToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0))); 1354235067b2STimm Baeder pushInteger(S, Val.countTrailingZeros(), CallType); 13557147e88fSTimm Baeder return true; 13567147e88fSTimm Baeder } 13577147e88fSTimm Baeder 1358f3baa73cSTimm Baeder static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC, 1359f3baa73cSTimm Baeder const InterpFrame *Frame, 1360f3baa73cSTimm Baeder const Function *Func, 1361f3baa73cSTimm Baeder const CallExpr *Call) { 13628951b514STimm Baeder if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() || 13635405ba50STimm Baeder !Call->getArg(1)->getType()->isIntegerType()) 13645405ba50STimm Baeder return false; 13655405ba50STimm Baeder 1366f3baa73cSTimm Baeder PrimType ValT = *S.Ctx.classify(Call->getArg(0)); 1367f3baa73cSTimm Baeder PrimType MaskT = *S.Ctx.classify(Call->getArg(1)); 1368f3baa73cSTimm Baeder 1369f3baa73cSTimm Baeder APSInt Val = 1370f3baa73cSTimm Baeder peekToAPSInt(S.Stk, ValT, align(primSize(ValT)) + align(primSize(MaskT))); 1371f3baa73cSTimm Baeder APSInt Mask = peekToAPSInt(S.Stk, MaskT); 1372f3baa73cSTimm Baeder 1373f3baa73cSTimm Baeder unsigned BitWidth = Val.getBitWidth(); 1374f3baa73cSTimm Baeder APInt Result = APInt::getZero(BitWidth); 1375f3baa73cSTimm Baeder for (unsigned I = 0, P = 0; I != BitWidth; ++I) { 1376f3baa73cSTimm Baeder if (Mask[I]) 1377f3baa73cSTimm Baeder Result.setBitVal(I, Val[P++]); 1378f3baa73cSTimm Baeder } 1379f3baa73cSTimm Baeder pushInteger(S, Result, Call->getType()); 1380f3baa73cSTimm Baeder return true; 1381f3baa73cSTimm Baeder } 1382f3baa73cSTimm Baeder 1383f3baa73cSTimm Baeder static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC, 1384f3baa73cSTimm Baeder const InterpFrame *Frame, 1385f3baa73cSTimm Baeder const Function *Func, 1386f3baa73cSTimm Baeder const CallExpr *Call) { 13878951b514STimm Baeder if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() || 13885405ba50STimm Baeder !Call->getArg(1)->getType()->isIntegerType()) 13895405ba50STimm Baeder return false; 13905405ba50STimm Baeder 1391f3baa73cSTimm Baeder PrimType ValT = *S.Ctx.classify(Call->getArg(0)); 1392f3baa73cSTimm Baeder PrimType MaskT = *S.Ctx.classify(Call->getArg(1)); 1393f3baa73cSTimm Baeder 1394f3baa73cSTimm Baeder APSInt Val = 1395f3baa73cSTimm Baeder peekToAPSInt(S.Stk, ValT, align(primSize(ValT)) + align(primSize(MaskT))); 1396f3baa73cSTimm Baeder APSInt Mask = peekToAPSInt(S.Stk, MaskT); 1397f3baa73cSTimm Baeder 1398f3baa73cSTimm Baeder unsigned BitWidth = Val.getBitWidth(); 1399f3baa73cSTimm Baeder APInt Result = APInt::getZero(BitWidth); 1400f3baa73cSTimm Baeder for (unsigned I = 0, P = 0; I != BitWidth; ++I) { 1401f3baa73cSTimm Baeder if (Mask[I]) 1402f3baa73cSTimm Baeder Result.setBitVal(P++, Val[I]); 1403f3baa73cSTimm Baeder } 1404f3baa73cSTimm Baeder pushInteger(S, Result, Call->getType()); 1405f3baa73cSTimm Baeder return true; 1406f3baa73cSTimm Baeder } 1407f3baa73cSTimm Baeder 14086f8e8551STimm Baeder static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S, 14096f8e8551STimm Baeder CodePtr OpPC, 14106f8e8551STimm Baeder const InterpFrame *Frame, 14116f8e8551STimm Baeder const Function *Func, 14126f8e8551STimm Baeder const CallExpr *Call) { 14131fd79f10STimm Baeder if (Call->getNumArgs() != 4 || !Call->getArg(0)->getType()->isIntegerType() || 1414f1eac776STimm Baeder !Call->getArg(1)->getType()->isIntegerType() || 1415f1eac776STimm Baeder !Call->getArg(2)->getType()->isIntegerType()) 1416f1eac776STimm Baeder return false; 1417f1eac776STimm Baeder 14186f8e8551STimm Baeder unsigned BuiltinOp = Func->getBuiltinID(); 14196f8e8551STimm Baeder APSInt CarryIn = getAPSIntParam(Frame, 0); 14206f8e8551STimm Baeder APSInt LHS = getAPSIntParam(Frame, 1); 14216f8e8551STimm Baeder APSInt RHS = getAPSIntParam(Frame, 2); 14226f8e8551STimm Baeder 14236f8e8551STimm Baeder bool IsAdd = BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u32 || 14246f8e8551STimm Baeder BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u64; 14256f8e8551STimm Baeder 14266f8e8551STimm Baeder unsigned BitWidth = LHS.getBitWidth(); 14276f8e8551STimm Baeder unsigned CarryInBit = CarryIn.ugt(0) ? 1 : 0; 14286f8e8551STimm Baeder APInt ExResult = 14296f8e8551STimm Baeder IsAdd ? (LHS.zext(BitWidth + 1) + (RHS.zext(BitWidth + 1) + CarryInBit)) 14306f8e8551STimm Baeder : (LHS.zext(BitWidth + 1) - (RHS.zext(BitWidth + 1) + CarryInBit)); 14316f8e8551STimm Baeder 14326f8e8551STimm Baeder APInt Result = ExResult.extractBits(BitWidth, 0); 14336f8e8551STimm Baeder APSInt CarryOut = 14346f8e8551STimm Baeder APSInt(ExResult.extractBits(1, BitWidth), /*IsUnsigned=*/true); 14356f8e8551STimm Baeder 14366f8e8551STimm Baeder Pointer &CarryOutPtr = S.Stk.peek<Pointer>(); 14376f8e8551STimm Baeder QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType(); 14386f8e8551STimm Baeder PrimType CarryOutT = *S.getContext().classify(CarryOutType); 14396f8e8551STimm Baeder assignInteger(CarryOutPtr, CarryOutT, APSInt(Result, true)); 14406f8e8551STimm Baeder 14416f8e8551STimm Baeder pushInteger(S, CarryOut, Call->getType()); 14426f8e8551STimm Baeder 14436f8e8551STimm Baeder return true; 14446f8e8551STimm Baeder } 14456f8e8551STimm Baeder 1446a07aba5dSTimm Baeder static bool interp__builtin_os_log_format_buffer_size(InterpState &S, 1447a07aba5dSTimm Baeder CodePtr OpPC, 1448a07aba5dSTimm Baeder const InterpFrame *Frame, 1449a07aba5dSTimm Baeder const Function *Func, 1450a07aba5dSTimm Baeder const CallExpr *Call) { 1451a07aba5dSTimm Baeder analyze_os_log::OSLogBufferLayout Layout; 1452d9e72860Syronglin analyze_os_log::computeOSLogBufferLayout(S.getASTContext(), Call, Layout); 1453a07aba5dSTimm Baeder pushInteger(S, Layout.size().getQuantity(), Call->getType()); 1454a07aba5dSTimm Baeder return true; 1455a07aba5dSTimm Baeder } 1456a07aba5dSTimm Baeder 1457a07aba5dSTimm Baeder static bool interp__builtin_ptrauth_string_discriminator( 1458a07aba5dSTimm Baeder InterpState &S, CodePtr OpPC, const InterpFrame *Frame, 1459a07aba5dSTimm Baeder const Function *Func, const CallExpr *Call) { 1460a07aba5dSTimm Baeder const auto &Ptr = S.Stk.peek<Pointer>(); 1461a07aba5dSTimm Baeder assert(Ptr.getFieldDesc()->isPrimitiveArray()); 1462a07aba5dSTimm Baeder 1463a07aba5dSTimm Baeder StringRef R(&Ptr.deref<char>(), Ptr.getFieldDesc()->getNumElems() - 1); 1464a07aba5dSTimm Baeder uint64_t Result = getPointerAuthStableSipHash(R); 1465a07aba5dSTimm Baeder pushInteger(S, Result, Call->getType()); 1466a07aba5dSTimm Baeder return true; 1467a07aba5dSTimm Baeder } 1468a07aba5dSTimm Baeder 1469a07aba5dSTimm Baeder // FIXME: This implementation is not complete. 1470a07aba5dSTimm Baeder // The Compiler instance we create cannot access the current stack frame, local 1471a07aba5dSTimm Baeder // variables, function parameters, etc. We also need protection from 1472a07aba5dSTimm Baeder // side-effects, fatal errors, etc. 1473a07aba5dSTimm Baeder static bool interp__builtin_constant_p(InterpState &S, CodePtr OpPC, 1474a07aba5dSTimm Baeder const InterpFrame *Frame, 1475a07aba5dSTimm Baeder const Function *Func, 1476a07aba5dSTimm Baeder const CallExpr *Call) { 1477a07aba5dSTimm Baeder const Expr *Arg = Call->getArg(0); 1478a07aba5dSTimm Baeder QualType ArgType = Arg->getType(); 1479a07aba5dSTimm Baeder 1480a07aba5dSTimm Baeder auto returnInt = [&S, Call](bool Value) -> bool { 1481a07aba5dSTimm Baeder pushInteger(S, Value, Call->getType()); 1482a07aba5dSTimm Baeder return true; 1483a07aba5dSTimm Baeder }; 1484a07aba5dSTimm Baeder 1485a07aba5dSTimm Baeder // __builtin_constant_p always has one operand. The rules which gcc follows 1486a07aba5dSTimm Baeder // are not precisely documented, but are as follows: 1487a07aba5dSTimm Baeder // 1488a07aba5dSTimm Baeder // - If the operand is of integral, floating, complex or enumeration type, 1489a07aba5dSTimm Baeder // and can be folded to a known value of that type, it returns 1. 1490a07aba5dSTimm Baeder // - If the operand can be folded to a pointer to the first character 1491a07aba5dSTimm Baeder // of a string literal (or such a pointer cast to an integral type) 1492a07aba5dSTimm Baeder // or to a null pointer or an integer cast to a pointer, it returns 1. 1493a07aba5dSTimm Baeder // 1494a07aba5dSTimm Baeder // Otherwise, it returns 0. 1495a07aba5dSTimm Baeder // 1496a07aba5dSTimm Baeder // FIXME: GCC also intends to return 1 for literals of aggregate types, but 1497a07aba5dSTimm Baeder // its support for this did not work prior to GCC 9 and is not yet well 1498a07aba5dSTimm Baeder // understood. 1499a07aba5dSTimm Baeder if (ArgType->isIntegralOrEnumerationType() || ArgType->isFloatingType() || 1500a07aba5dSTimm Baeder ArgType->isAnyComplexType() || ArgType->isPointerType() || 1501a07aba5dSTimm Baeder ArgType->isNullPtrType()) { 1502a07aba5dSTimm Baeder InterpStack Stk; 1503a07aba5dSTimm Baeder Compiler<EvalEmitter> C(S.Ctx, S.P, S, Stk); 1504a07aba5dSTimm Baeder auto Res = C.interpretExpr(Arg, /*ConvertResultToRValue=*/Arg->isGLValue()); 1505a07aba5dSTimm Baeder if (Res.isInvalid()) { 1506a07aba5dSTimm Baeder C.cleanup(); 1507a07aba5dSTimm Baeder Stk.clear(); 1508a07aba5dSTimm Baeder } 1509a07aba5dSTimm Baeder 1510a07aba5dSTimm Baeder if (!Res.isInvalid() && !Res.empty()) { 1511a07aba5dSTimm Baeder const APValue &LV = Res.toAPValue(); 1512a07aba5dSTimm Baeder if (LV.isLValue()) { 1513a07aba5dSTimm Baeder APValue::LValueBase Base = LV.getLValueBase(); 1514a07aba5dSTimm Baeder if (Base.isNull()) { 1515a07aba5dSTimm Baeder // A null base is acceptable. 1516a07aba5dSTimm Baeder return returnInt(true); 1517a07aba5dSTimm Baeder } else if (const auto *E = Base.dyn_cast<const Expr *>()) { 1518a07aba5dSTimm Baeder if (!isa<StringLiteral>(E)) 1519a07aba5dSTimm Baeder return returnInt(false); 1520a07aba5dSTimm Baeder return returnInt(LV.getLValueOffset().isZero()); 1521a07aba5dSTimm Baeder } else if (Base.is<TypeInfoLValue>()) { 1522a07aba5dSTimm Baeder // Surprisingly, GCC considers __builtin_constant_p(&typeid(int)) to 1523a07aba5dSTimm Baeder // evaluate to true. 1524a07aba5dSTimm Baeder return returnInt(true); 1525a07aba5dSTimm Baeder } else { 1526a07aba5dSTimm Baeder // Any other base is not constant enough for GCC. 1527a07aba5dSTimm Baeder return returnInt(false); 1528a07aba5dSTimm Baeder } 1529a07aba5dSTimm Baeder } 1530a07aba5dSTimm Baeder } 1531a07aba5dSTimm Baeder 1532a07aba5dSTimm Baeder // Otherwise, any constant value is good enough. 1533a07aba5dSTimm Baeder return returnInt(true); 1534a07aba5dSTimm Baeder } 1535a07aba5dSTimm Baeder 1536a07aba5dSTimm Baeder return returnInt(false); 1537a07aba5dSTimm Baeder } 1538a07aba5dSTimm Baeder 1539610b8539STimm Baeder static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC, 1540610b8539STimm Baeder const InterpFrame *Frame, 1541610b8539STimm Baeder const Function *Func, 1542610b8539STimm Baeder const CallExpr *Call) { 1543610b8539STimm Baeder // A call to __operator_new is only valid within std::allocate<>::allocate. 1544610b8539STimm Baeder // Walk up the call stack to find the appropriate caller and get the 1545610b8539STimm Baeder // element type from it. 1546610b8539STimm Baeder QualType ElemType; 1547610b8539STimm Baeder 1548610b8539STimm Baeder for (const InterpFrame *F = Frame; F; F = F->Caller) { 1549610b8539STimm Baeder const Function *Func = F->getFunction(); 1550610b8539STimm Baeder if (!Func) 1551610b8539STimm Baeder continue; 1552610b8539STimm Baeder const auto *MD = dyn_cast_if_present<CXXMethodDecl>(Func->getDecl()); 1553610b8539STimm Baeder if (!MD) 1554610b8539STimm Baeder continue; 1555610b8539STimm Baeder const IdentifierInfo *FnII = MD->getIdentifier(); 1556610b8539STimm Baeder if (!FnII || !FnII->isStr("allocate")) 1557610b8539STimm Baeder continue; 1558610b8539STimm Baeder 1559610b8539STimm Baeder const auto *CTSD = 1560610b8539STimm Baeder dyn_cast<ClassTemplateSpecializationDecl>(MD->getParent()); 1561610b8539STimm Baeder if (!CTSD) 1562610b8539STimm Baeder continue; 1563610b8539STimm Baeder 1564610b8539STimm Baeder const IdentifierInfo *ClassII = CTSD->getIdentifier(); 1565610b8539STimm Baeder const TemplateArgumentList &TAL = CTSD->getTemplateArgs(); 1566610b8539STimm Baeder if (CTSD->isInStdNamespace() && ClassII && ClassII->isStr("allocator") && 1567610b8539STimm Baeder TAL.size() >= 1 && TAL[0].getKind() == TemplateArgument::Type) { 1568610b8539STimm Baeder ElemType = TAL[0].getAsType(); 1569610b8539STimm Baeder break; 1570610b8539STimm Baeder } 1571610b8539STimm Baeder } 1572610b8539STimm Baeder 1573610b8539STimm Baeder if (ElemType.isNull()) { 1574610b8539STimm Baeder S.FFDiag(Call, S.getLangOpts().CPlusPlus20 1575610b8539STimm Baeder ? diag::note_constexpr_new_untyped 1576610b8539STimm Baeder : diag::note_constexpr_new); 1577610b8539STimm Baeder return false; 1578610b8539STimm Baeder } 1579610b8539STimm Baeder 1580610b8539STimm Baeder if (ElemType->isIncompleteType() || ElemType->isFunctionType()) { 1581610b8539STimm Baeder S.FFDiag(Call, diag::note_constexpr_new_not_complete_object_type) 1582610b8539STimm Baeder << (ElemType->isIncompleteType() ? 0 : 1) << ElemType; 1583610b8539STimm Baeder return false; 1584610b8539STimm Baeder } 1585610b8539STimm Baeder 1586610b8539STimm Baeder APSInt Bytes = peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(0))); 1587610b8539STimm Baeder CharUnits ElemSize = S.getASTContext().getTypeSizeInChars(ElemType); 1588610b8539STimm Baeder assert(!ElemSize.isZero()); 1589610b8539STimm Baeder // Divide the number of bytes by sizeof(ElemType), so we get the number of 1590610b8539STimm Baeder // elements we should allocate. 1591610b8539STimm Baeder APInt NumElems, Remainder; 1592610b8539STimm Baeder APInt ElemSizeAP(Bytes.getBitWidth(), ElemSize.getQuantity()); 1593610b8539STimm Baeder APInt::udivrem(Bytes, ElemSizeAP, NumElems, Remainder); 1594610b8539STimm Baeder if (Remainder != 0) { 1595610b8539STimm Baeder // This likely indicates a bug in the implementation of 'std::allocator'. 1596610b8539STimm Baeder S.FFDiag(Call, diag::note_constexpr_operator_new_bad_size) 1597610b8539STimm Baeder << Bytes << APSInt(ElemSizeAP, true) << ElemType; 1598610b8539STimm Baeder return false; 1599610b8539STimm Baeder } 1600610b8539STimm Baeder 1601898fd396STimm Baeder // NB: The same check we're using in CheckArraySize() 1602898fd396STimm Baeder if (NumElems.getActiveBits() > 1603898fd396STimm Baeder ConstantArrayType::getMaxSizeBits(S.getASTContext()) || 1604898fd396STimm Baeder NumElems.ugt(Descriptor::MaxArrayElemBytes / ElemSize.getQuantity())) { 1605898fd396STimm Baeder // FIXME: NoThrow check? 1606898fd396STimm Baeder const SourceInfo &Loc = S.Current->getSource(OpPC); 1607898fd396STimm Baeder S.FFDiag(Loc, diag::note_constexpr_new_too_large) 1608898fd396STimm Baeder << NumElems.getZExtValue(); 1609898fd396STimm Baeder return false; 1610898fd396STimm Baeder } 1611610b8539STimm Baeder 1612610b8539STimm Baeder std::optional<PrimType> ElemT = S.getContext().classify(ElemType); 1613610b8539STimm Baeder DynamicAllocator &Allocator = S.getAllocator(); 1614610b8539STimm Baeder if (ElemT) { 1615610b8539STimm Baeder if (NumElems.ule(1)) { 1616610b8539STimm Baeder const Descriptor *Desc = 1617610b8539STimm Baeder S.P.createDescriptor(Call, *ElemT, Descriptor::InlineDescMD, 1618610b8539STimm Baeder /*IsConst=*/false, /*IsTemporary=*/false, 1619610b8539STimm Baeder /*IsMutable=*/false); 1620610b8539STimm Baeder Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(), 1621610b8539STimm Baeder DynamicAllocator::Form::Operator); 1622610b8539STimm Baeder assert(B); 1623610b8539STimm Baeder 1624610b8539STimm Baeder S.Stk.push<Pointer>(B); 1625610b8539STimm Baeder return true; 1626610b8539STimm Baeder } 1627610b8539STimm Baeder assert(NumElems.ugt(1)); 1628610b8539STimm Baeder 1629610b8539STimm Baeder Block *B = 1630610b8539STimm Baeder Allocator.allocate(Call, *ElemT, NumElems.getZExtValue(), 1631610b8539STimm Baeder S.Ctx.getEvalID(), DynamicAllocator::Form::Operator); 1632610b8539STimm Baeder assert(B); 1633610b8539STimm Baeder S.Stk.push<Pointer>(B); 1634610b8539STimm Baeder return true; 1635610b8539STimm Baeder } 1636610b8539STimm Baeder 1637610b8539STimm Baeder assert(!ElemT); 1638610b8539STimm Baeder // Structs etc. 1639610b8539STimm Baeder const Descriptor *Desc = S.P.createDescriptor( 16404b964002STimm Baeder Call, ElemType.getTypePtr(), Descriptor::InlineDescMD, 1641610b8539STimm Baeder /*IsConst=*/false, /*IsTemporary=*/false, /*IsMutable=*/false, 1642610b8539STimm Baeder /*Init=*/nullptr); 1643610b8539STimm Baeder 1644610b8539STimm Baeder if (NumElems.ule(1)) { 1645610b8539STimm Baeder Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(), 1646610b8539STimm Baeder DynamicAllocator::Form::Operator); 1647610b8539STimm Baeder assert(B); 1648610b8539STimm Baeder S.Stk.push<Pointer>(B); 1649610b8539STimm Baeder return true; 1650610b8539STimm Baeder } 1651610b8539STimm Baeder 1652610b8539STimm Baeder Block *B = 1653610b8539STimm Baeder Allocator.allocate(Desc, NumElems.getZExtValue(), S.Ctx.getEvalID(), 1654610b8539STimm Baeder DynamicAllocator::Form::Operator); 1655610b8539STimm Baeder assert(B); 1656610b8539STimm Baeder S.Stk.push<Pointer>(B); 1657610b8539STimm Baeder return true; 1658610b8539STimm Baeder } 1659610b8539STimm Baeder 1660610b8539STimm Baeder static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC, 1661610b8539STimm Baeder const InterpFrame *Frame, 1662610b8539STimm Baeder const Function *Func, 1663610b8539STimm Baeder const CallExpr *Call) { 1664610b8539STimm Baeder const Expr *Source = nullptr; 1665610b8539STimm Baeder const Block *BlockToDelete = nullptr; 1666610b8539STimm Baeder 1667610b8539STimm Baeder { 1668610b8539STimm Baeder const Pointer &Ptr = S.Stk.peek<Pointer>(); 1669610b8539STimm Baeder 1670610b8539STimm Baeder if (Ptr.isZero()) { 1671610b8539STimm Baeder S.CCEDiag(Call, diag::note_constexpr_deallocate_null); 1672610b8539STimm Baeder return true; 1673610b8539STimm Baeder } 1674610b8539STimm Baeder 1675610b8539STimm Baeder Source = Ptr.getDeclDesc()->asExpr(); 1676610b8539STimm Baeder BlockToDelete = Ptr.block(); 1677610b8539STimm Baeder } 1678610b8539STimm Baeder assert(BlockToDelete); 1679610b8539STimm Baeder 1680610b8539STimm Baeder DynamicAllocator &Allocator = S.getAllocator(); 1681610b8539STimm Baeder const Descriptor *BlockDesc = BlockToDelete->getDescriptor(); 1682610b8539STimm Baeder std::optional<DynamicAllocator::Form> AllocForm = 1683610b8539STimm Baeder Allocator.getAllocationForm(Source); 1684610b8539STimm Baeder 1685610b8539STimm Baeder if (!Allocator.deallocate(Source, BlockToDelete, S)) { 1686610b8539STimm Baeder // Nothing has been deallocated, this must be a double-delete. 1687610b8539STimm Baeder const SourceInfo &Loc = S.Current->getSource(OpPC); 1688610b8539STimm Baeder S.FFDiag(Loc, diag::note_constexpr_double_delete); 1689610b8539STimm Baeder return false; 1690610b8539STimm Baeder } 1691610b8539STimm Baeder assert(AllocForm); 1692610b8539STimm Baeder 1693610b8539STimm Baeder return CheckNewDeleteForms( 1694610b8539STimm Baeder S, OpPC, *AllocForm, DynamicAllocator::Form::Operator, BlockDesc, Source); 1695610b8539STimm Baeder } 1696610b8539STimm Baeder 1697b46a0482STimm Baeder static bool interp__builtin_arithmetic_fence(InterpState &S, CodePtr OpPC, 1698b46a0482STimm Baeder const InterpFrame *Frame, 1699b46a0482STimm Baeder const Function *Func, 1700b46a0482STimm Baeder const CallExpr *Call) { 1701b46a0482STimm Baeder const Floating &Arg0 = S.Stk.peek<Floating>(); 1702b46a0482STimm Baeder S.Stk.push<Floating>(Arg0); 1703b46a0482STimm Baeder return true; 1704b46a0482STimm Baeder } 1705b46a0482STimm Baeder 170631bde711STimm Baeder static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC, 170731bde711STimm Baeder const InterpFrame *Frame, 170831bde711STimm Baeder const Function *Func, 170931bde711STimm Baeder const CallExpr *Call) { 171031bde711STimm Baeder const Pointer &Arg = S.Stk.peek<Pointer>(); 171131bde711STimm Baeder assert(Arg.getFieldDesc()->isPrimitiveArray()); 171231bde711STimm Baeder 171331bde711STimm Baeder unsigned ID = Func->getBuiltinID(); 171431bde711STimm Baeder QualType ElemType = Arg.getFieldDesc()->getElemQualType(); 171531bde711STimm Baeder assert(Call->getType() == ElemType); 171631bde711STimm Baeder PrimType ElemT = *S.getContext().classify(ElemType); 171731bde711STimm Baeder unsigned NumElems = Arg.getNumElems(); 171831bde711STimm Baeder 1719ccc471feSTimm Baeder INT_TYPE_SWITCH_NO_BOOL(ElemT, { 1720c1dcf75aSTimm Baeder T Result = Arg.atIndex(0).deref<T>(); 1721c1dcf75aSTimm Baeder unsigned BitWidth = Result.bitWidth(); 172231bde711STimm Baeder for (unsigned I = 1; I != NumElems; ++I) { 172331bde711STimm Baeder T Elem = Arg.atIndex(I).deref<T>(); 1724c1dcf75aSTimm Baeder T PrevResult = Result; 1725c1dcf75aSTimm Baeder 1726c1dcf75aSTimm Baeder if (ID == Builtin::BI__builtin_reduce_add) { 1727c1dcf75aSTimm Baeder if (T::add(Result, Elem, BitWidth, &Result)) { 172831bde711STimm Baeder unsigned OverflowBits = BitWidth + 1; 1729c1dcf75aSTimm Baeder (void)handleOverflow(S, OpPC, 1730c1dcf75aSTimm Baeder (PrevResult.toAPSInt(OverflowBits) + 1731c1dcf75aSTimm Baeder Elem.toAPSInt(OverflowBits))); 173231bde711STimm Baeder return false; 173331bde711STimm Baeder } 1734c1dcf75aSTimm Baeder } else if (ID == Builtin::BI__builtin_reduce_mul) { 1735c1dcf75aSTimm Baeder if (T::mul(Result, Elem, BitWidth, &Result)) { 1736c1dcf75aSTimm Baeder unsigned OverflowBits = BitWidth * 2; 1737c1dcf75aSTimm Baeder (void)handleOverflow(S, OpPC, 1738c1dcf75aSTimm Baeder (PrevResult.toAPSInt(OverflowBits) * 1739c1dcf75aSTimm Baeder Elem.toAPSInt(OverflowBits))); 1740c1dcf75aSTimm Baeder return false; 174131bde711STimm Baeder } 1742ccc471feSTimm Baeder 1743ccc471feSTimm Baeder } else if (ID == Builtin::BI__builtin_reduce_and) { 1744ccc471feSTimm Baeder (void)T::bitAnd(Result, Elem, BitWidth, &Result); 17451288f6d4STimm Baeder } else if (ID == Builtin::BI__builtin_reduce_or) { 17461288f6d4STimm Baeder (void)T::bitOr(Result, Elem, BitWidth, &Result); 1747b587b910STimm Baeder } else if (ID == Builtin::BI__builtin_reduce_xor) { 1748b587b910STimm Baeder (void)T::bitXor(Result, Elem, BitWidth, &Result); 1749c1dcf75aSTimm Baeder } else { 1750c1dcf75aSTimm Baeder llvm_unreachable("Unhandled vector reduce builtin"); 1751c1dcf75aSTimm Baeder } 1752c1dcf75aSTimm Baeder } 17531288f6d4STimm Baeder pushInteger(S, Result.toAPSInt(), Call->getType()); 175431bde711STimm Baeder }); 175531bde711STimm Baeder 175631bde711STimm Baeder return true; 175731bde711STimm Baeder } 175831bde711STimm Baeder 1759637a1ae8STimm Baeder /// Can be called with an integer or vector as the first and only parameter. 1760637a1ae8STimm Baeder static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC, 1761637a1ae8STimm Baeder const InterpFrame *Frame, 1762637a1ae8STimm Baeder const Function *Func, 1763637a1ae8STimm Baeder const CallExpr *Call) { 1764637a1ae8STimm Baeder assert(Call->getNumArgs() == 1); 1765637a1ae8STimm Baeder if (Call->getArg(0)->getType()->isIntegerType()) { 1766637a1ae8STimm Baeder PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType()); 1767637a1ae8STimm Baeder APSInt Val = peekToAPSInt(S.Stk, ArgT); 1768637a1ae8STimm Baeder pushInteger(S, Val.popcount(), Call->getType()); 1769637a1ae8STimm Baeder return true; 1770637a1ae8STimm Baeder } 1771637a1ae8STimm Baeder // Otherwise, the argument must be a vector. 1772637a1ae8STimm Baeder assert(Call->getArg(0)->getType()->isVectorType()); 1773637a1ae8STimm Baeder const Pointer &Arg = S.Stk.peek<Pointer>(); 1774637a1ae8STimm Baeder assert(Arg.getFieldDesc()->isPrimitiveArray()); 1775637a1ae8STimm Baeder const Pointer &Dst = S.Stk.peek<Pointer>(primSize(PT_Ptr) * 2); 1776637a1ae8STimm Baeder assert(Dst.getFieldDesc()->isPrimitiveArray()); 1777637a1ae8STimm Baeder assert(Arg.getFieldDesc()->getNumElems() == 1778637a1ae8STimm Baeder Dst.getFieldDesc()->getNumElems()); 1779637a1ae8STimm Baeder 1780637a1ae8STimm Baeder QualType ElemType = Arg.getFieldDesc()->getElemQualType(); 1781637a1ae8STimm Baeder PrimType ElemT = *S.getContext().classify(ElemType); 1782637a1ae8STimm Baeder unsigned NumElems = Arg.getNumElems(); 1783637a1ae8STimm Baeder 1784637a1ae8STimm Baeder // FIXME: Reading from uninitialized vector elements? 1785637a1ae8STimm Baeder for (unsigned I = 0; I != NumElems; ++I) { 1786637a1ae8STimm Baeder INT_TYPE_SWITCH_NO_BOOL(ElemT, { 1787637a1ae8STimm Baeder Dst.atIndex(I).deref<T>() = 1788637a1ae8STimm Baeder T::from(Arg.atIndex(I).deref<T>().toAPSInt().popcount()); 1789637a1ae8STimm Baeder }); 1790637a1ae8STimm Baeder } 1791637a1ae8STimm Baeder 1792637a1ae8STimm Baeder return true; 1793637a1ae8STimm Baeder } 17940611fdd3STimm Baeder static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC, 17950611fdd3STimm Baeder const InterpFrame *Frame, 17960611fdd3STimm Baeder const Function *Func, const CallExpr *Call) { 17970611fdd3STimm Baeder assert(Call->getNumArgs() == 3); 1798*dac9736dSTimm Baeder unsigned ID = Func->getBuiltinID(); 17990611fdd3STimm Baeder Pointer DestPtr = getParam<Pointer>(Frame, 0); 18000611fdd3STimm Baeder const Pointer &SrcPtr = getParam<Pointer>(Frame, 1); 18010611fdd3STimm Baeder const APSInt &Size = 18020611fdd3STimm Baeder peekToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2))); 18030611fdd3STimm Baeder assert(!Size.isSigned() && "memcpy and friends take an unsigned size"); 18040611fdd3STimm Baeder 1805*dac9736dSTimm Baeder if (ID == Builtin::BImemcpy) 1806*dac9736dSTimm Baeder diagnoseNonConstexprBuiltin(S, OpPC, ID); 1807*dac9736dSTimm Baeder 18080611fdd3STimm Baeder if (DestPtr.isDummy() || SrcPtr.isDummy()) 18090611fdd3STimm Baeder return false; 18100611fdd3STimm Baeder 18110611fdd3STimm Baeder // If the size is zero, we treat this as always being a valid no-op. 18120611fdd3STimm Baeder if (Size.isZero()) { 18130611fdd3STimm Baeder S.Stk.push<Pointer>(DestPtr); 18140611fdd3STimm Baeder return true; 18150611fdd3STimm Baeder } 18160611fdd3STimm Baeder 1817fc9052eeSTimm Baeder if (SrcPtr.isZero() || DestPtr.isZero()) { 1818fc9052eeSTimm Baeder Pointer DiagPtr = (SrcPtr.isZero() ? SrcPtr : DestPtr); 1819fc9052eeSTimm Baeder S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null) 1820fc9052eeSTimm Baeder << /*IsMove=*/false << /*IsWchar=*/false << !SrcPtr.isZero() 1821fc9052eeSTimm Baeder << DiagPtr.toDiagnosticString(S.getASTContext()); 1822fc9052eeSTimm Baeder return false; 1823fc9052eeSTimm Baeder } 1824fc9052eeSTimm Baeder 18250611fdd3STimm Baeder if (!DoBitCastPtr(S, OpPC, SrcPtr, DestPtr)) 18260611fdd3STimm Baeder return false; 18270611fdd3STimm Baeder 18280611fdd3STimm Baeder S.Stk.push<Pointer>(DestPtr); 18290611fdd3STimm Baeder return true; 18300611fdd3STimm Baeder } 18310611fdd3STimm Baeder 1832a07aba5dSTimm Baeder bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, 183378cf9b83STimm Baeder const CallExpr *Call, uint32_t BuiltinID) { 1834a07aba5dSTimm Baeder const InterpFrame *Frame = S.Current; 1835a07aba5dSTimm Baeder 1836a07aba5dSTimm Baeder std::optional<PrimType> ReturnT = S.getContext().classify(Call); 1837a07aba5dSTimm Baeder 183878cf9b83STimm Baeder switch (BuiltinID) { 1839a07aba5dSTimm Baeder case Builtin::BI__builtin_is_constant_evaluated: 1840a07aba5dSTimm Baeder if (!interp__builtin_is_constant_evaluated(S, OpPC, Frame, Call)) 1841a07aba5dSTimm Baeder return false; 1842a07aba5dSTimm Baeder break; 1843a07aba5dSTimm Baeder case Builtin::BI__builtin_assume: 1844a07aba5dSTimm Baeder case Builtin::BI__assume: 1845a07aba5dSTimm Baeder break; 1846a07aba5dSTimm Baeder case Builtin::BI__builtin_strcmp: 1847a07aba5dSTimm Baeder if (!interp__builtin_strcmp(S, OpPC, Frame, Call)) 1848a07aba5dSTimm Baeder return false; 1849a07aba5dSTimm Baeder break; 1850a07aba5dSTimm Baeder case Builtin::BI__builtin_strlen: 1851*dac9736dSTimm Baeder case Builtin::BIstrlen: 1852*dac9736dSTimm Baeder if (!interp__builtin_strlen(S, OpPC, Frame, F, Call)) 1853a07aba5dSTimm Baeder return false; 1854a07aba5dSTimm Baeder break; 1855a07aba5dSTimm Baeder case Builtin::BI__builtin_nan: 1856a07aba5dSTimm Baeder case Builtin::BI__builtin_nanf: 1857a07aba5dSTimm Baeder case Builtin::BI__builtin_nanl: 1858a07aba5dSTimm Baeder case Builtin::BI__builtin_nanf16: 1859a07aba5dSTimm Baeder case Builtin::BI__builtin_nanf128: 1860a07aba5dSTimm Baeder if (!interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/false)) 1861a07aba5dSTimm Baeder return false; 1862a07aba5dSTimm Baeder break; 1863a07aba5dSTimm Baeder case Builtin::BI__builtin_nans: 1864a07aba5dSTimm Baeder case Builtin::BI__builtin_nansf: 1865a07aba5dSTimm Baeder case Builtin::BI__builtin_nansl: 1866a07aba5dSTimm Baeder case Builtin::BI__builtin_nansf16: 1867a07aba5dSTimm Baeder case Builtin::BI__builtin_nansf128: 1868a07aba5dSTimm Baeder if (!interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/true)) 1869a07aba5dSTimm Baeder return false; 1870a07aba5dSTimm Baeder break; 1871a07aba5dSTimm Baeder 1872a07aba5dSTimm Baeder case Builtin::BI__builtin_huge_val: 1873a07aba5dSTimm Baeder case Builtin::BI__builtin_huge_valf: 1874a07aba5dSTimm Baeder case Builtin::BI__builtin_huge_vall: 1875a07aba5dSTimm Baeder case Builtin::BI__builtin_huge_valf16: 1876a07aba5dSTimm Baeder case Builtin::BI__builtin_huge_valf128: 1877a07aba5dSTimm Baeder case Builtin::BI__builtin_inf: 1878a07aba5dSTimm Baeder case Builtin::BI__builtin_inff: 1879a07aba5dSTimm Baeder case Builtin::BI__builtin_infl: 1880a07aba5dSTimm Baeder case Builtin::BI__builtin_inff16: 1881a07aba5dSTimm Baeder case Builtin::BI__builtin_inff128: 1882a07aba5dSTimm Baeder if (!interp__builtin_inf(S, OpPC, Frame, F)) 1883a07aba5dSTimm Baeder return false; 1884a07aba5dSTimm Baeder break; 1885a07aba5dSTimm Baeder case Builtin::BI__builtin_copysign: 1886a07aba5dSTimm Baeder case Builtin::BI__builtin_copysignf: 1887a07aba5dSTimm Baeder case Builtin::BI__builtin_copysignl: 1888a07aba5dSTimm Baeder case Builtin::BI__builtin_copysignf128: 1889a07aba5dSTimm Baeder if (!interp__builtin_copysign(S, OpPC, Frame, F)) 1890a07aba5dSTimm Baeder return false; 1891a07aba5dSTimm Baeder break; 1892a07aba5dSTimm Baeder 1893a07aba5dSTimm Baeder case Builtin::BI__builtin_fmin: 1894a07aba5dSTimm Baeder case Builtin::BI__builtin_fminf: 1895a07aba5dSTimm Baeder case Builtin::BI__builtin_fminl: 1896a07aba5dSTimm Baeder case Builtin::BI__builtin_fminf16: 1897a07aba5dSTimm Baeder case Builtin::BI__builtin_fminf128: 1898790d9869STimm Baeder if (!interp__builtin_fmin(S, OpPC, Frame, F, /*IsNumBuiltin=*/false)) 1899790d9869STimm Baeder return false; 1900790d9869STimm Baeder break; 1901790d9869STimm Baeder 1902790d9869STimm Baeder case Builtin::BI__builtin_fminimum_num: 1903790d9869STimm Baeder case Builtin::BI__builtin_fminimum_numf: 1904790d9869STimm Baeder case Builtin::BI__builtin_fminimum_numl: 1905790d9869STimm Baeder case Builtin::BI__builtin_fminimum_numf16: 1906790d9869STimm Baeder case Builtin::BI__builtin_fminimum_numf128: 1907790d9869STimm Baeder if (!interp__builtin_fmin(S, OpPC, Frame, F, /*IsNumBuiltin=*/true)) 1908a07aba5dSTimm Baeder return false; 1909a07aba5dSTimm Baeder break; 1910a07aba5dSTimm Baeder 1911a07aba5dSTimm Baeder case Builtin::BI__builtin_fmax: 1912a07aba5dSTimm Baeder case Builtin::BI__builtin_fmaxf: 1913a07aba5dSTimm Baeder case Builtin::BI__builtin_fmaxl: 1914a07aba5dSTimm Baeder case Builtin::BI__builtin_fmaxf16: 1915a07aba5dSTimm Baeder case Builtin::BI__builtin_fmaxf128: 1916790d9869STimm Baeder if (!interp__builtin_fmax(S, OpPC, Frame, F, /*IsNumBuiltin=*/false)) 1917790d9869STimm Baeder return false; 1918790d9869STimm Baeder break; 1919790d9869STimm Baeder 1920790d9869STimm Baeder case Builtin::BI__builtin_fmaximum_num: 1921790d9869STimm Baeder case Builtin::BI__builtin_fmaximum_numf: 1922790d9869STimm Baeder case Builtin::BI__builtin_fmaximum_numl: 1923790d9869STimm Baeder case Builtin::BI__builtin_fmaximum_numf16: 1924790d9869STimm Baeder case Builtin::BI__builtin_fmaximum_numf128: 1925790d9869STimm Baeder if (!interp__builtin_fmax(S, OpPC, Frame, F, /*IsNumBuiltin=*/true)) 1926a07aba5dSTimm Baeder return false; 1927a07aba5dSTimm Baeder break; 1928a07aba5dSTimm Baeder 1929a07aba5dSTimm Baeder case Builtin::BI__builtin_isnan: 1930a07aba5dSTimm Baeder if (!interp__builtin_isnan(S, OpPC, Frame, F, Call)) 1931a07aba5dSTimm Baeder return false; 1932a07aba5dSTimm Baeder break; 1933a07aba5dSTimm Baeder case Builtin::BI__builtin_issignaling: 1934a07aba5dSTimm Baeder if (!interp__builtin_issignaling(S, OpPC, Frame, F, Call)) 1935a07aba5dSTimm Baeder return false; 1936a07aba5dSTimm Baeder break; 1937a07aba5dSTimm Baeder 1938a07aba5dSTimm Baeder case Builtin::BI__builtin_isinf: 1939a07aba5dSTimm Baeder if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false, Call)) 1940a07aba5dSTimm Baeder return false; 1941a07aba5dSTimm Baeder break; 1942a07aba5dSTimm Baeder 1943a07aba5dSTimm Baeder case Builtin::BI__builtin_isinf_sign: 1944a07aba5dSTimm Baeder if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true, Call)) 1945a07aba5dSTimm Baeder return false; 1946a07aba5dSTimm Baeder break; 1947a07aba5dSTimm Baeder 1948a07aba5dSTimm Baeder case Builtin::BI__builtin_isfinite: 1949a07aba5dSTimm Baeder if (!interp__builtin_isfinite(S, OpPC, Frame, F, Call)) 1950a07aba5dSTimm Baeder return false; 1951a07aba5dSTimm Baeder break; 1952a07aba5dSTimm Baeder case Builtin::BI__builtin_isnormal: 1953a07aba5dSTimm Baeder if (!interp__builtin_isnormal(S, OpPC, Frame, F, Call)) 1954a07aba5dSTimm Baeder return false; 1955a07aba5dSTimm Baeder break; 1956a07aba5dSTimm Baeder case Builtin::BI__builtin_issubnormal: 1957a07aba5dSTimm Baeder if (!interp__builtin_issubnormal(S, OpPC, Frame, F, Call)) 1958a07aba5dSTimm Baeder return false; 1959a07aba5dSTimm Baeder break; 1960a07aba5dSTimm Baeder case Builtin::BI__builtin_iszero: 1961a07aba5dSTimm Baeder if (!interp__builtin_iszero(S, OpPC, Frame, F, Call)) 1962a07aba5dSTimm Baeder return false; 1963a07aba5dSTimm Baeder break; 196411259343SMital Ashok case Builtin::BI__builtin_signbit: 196511259343SMital Ashok case Builtin::BI__builtin_signbitf: 196611259343SMital Ashok case Builtin::BI__builtin_signbitl: 196711259343SMital Ashok if (!interp__builtin_signbit(S, OpPC, Frame, F, Call)) 196811259343SMital Ashok return false; 196911259343SMital Ashok break; 197011259343SMital Ashok case Builtin::BI__builtin_isgreater: 197111259343SMital Ashok case Builtin::BI__builtin_isgreaterequal: 197211259343SMital Ashok case Builtin::BI__builtin_isless: 197311259343SMital Ashok case Builtin::BI__builtin_islessequal: 197411259343SMital Ashok case Builtin::BI__builtin_islessgreater: 197511259343SMital Ashok case Builtin::BI__builtin_isunordered: 197611259343SMital Ashok if (!interp_floating_comparison(S, OpPC, Frame, F, Call)) 197711259343SMital Ashok return false; 197811259343SMital Ashok break; 1979a07aba5dSTimm Baeder case Builtin::BI__builtin_isfpclass: 1980a07aba5dSTimm Baeder if (!interp__builtin_isfpclass(S, OpPC, Frame, F, Call)) 1981a07aba5dSTimm Baeder return false; 1982a07aba5dSTimm Baeder break; 1983a07aba5dSTimm Baeder case Builtin::BI__builtin_fpclassify: 1984a07aba5dSTimm Baeder if (!interp__builtin_fpclassify(S, OpPC, Frame, F, Call)) 1985a07aba5dSTimm Baeder return false; 1986a07aba5dSTimm Baeder break; 1987a07aba5dSTimm Baeder 1988a07aba5dSTimm Baeder case Builtin::BI__builtin_fabs: 1989a07aba5dSTimm Baeder case Builtin::BI__builtin_fabsf: 1990a07aba5dSTimm Baeder case Builtin::BI__builtin_fabsl: 1991a07aba5dSTimm Baeder case Builtin::BI__builtin_fabsf128: 1992a07aba5dSTimm Baeder if (!interp__builtin_fabs(S, OpPC, Frame, F)) 1993a07aba5dSTimm Baeder return false; 1994a07aba5dSTimm Baeder break; 1995a07aba5dSTimm Baeder 1996332ac18eSc8ef case Builtin::BI__builtin_abs: 1997332ac18eSc8ef case Builtin::BI__builtin_labs: 1998332ac18eSc8ef case Builtin::BI__builtin_llabs: 1999332ac18eSc8ef if (!interp__builtin_abs(S, OpPC, Frame, F, Call)) 2000332ac18eSc8ef return false; 2001332ac18eSc8ef break; 2002332ac18eSc8ef 2003a07aba5dSTimm Baeder case Builtin::BI__builtin_popcount: 2004a07aba5dSTimm Baeder case Builtin::BI__builtin_popcountl: 2005a07aba5dSTimm Baeder case Builtin::BI__builtin_popcountll: 2006a07aba5dSTimm Baeder case Builtin::BI__builtin_popcountg: 2007a07aba5dSTimm Baeder case Builtin::BI__popcnt16: // Microsoft variants of popcount 2008a07aba5dSTimm Baeder case Builtin::BI__popcnt: 2009a07aba5dSTimm Baeder case Builtin::BI__popcnt64: 2010a07aba5dSTimm Baeder if (!interp__builtin_popcount(S, OpPC, Frame, F, Call)) 2011a07aba5dSTimm Baeder return false; 2012a07aba5dSTimm Baeder break; 2013a07aba5dSTimm Baeder 2014a07aba5dSTimm Baeder case Builtin::BI__builtin_parity: 2015a07aba5dSTimm Baeder case Builtin::BI__builtin_parityl: 2016a07aba5dSTimm Baeder case Builtin::BI__builtin_parityll: 2017a07aba5dSTimm Baeder if (!interp__builtin_parity(S, OpPC, Frame, F, Call)) 2018a07aba5dSTimm Baeder return false; 2019a07aba5dSTimm Baeder break; 2020a07aba5dSTimm Baeder 2021a07aba5dSTimm Baeder case Builtin::BI__builtin_clrsb: 2022a07aba5dSTimm Baeder case Builtin::BI__builtin_clrsbl: 2023a07aba5dSTimm Baeder case Builtin::BI__builtin_clrsbll: 2024a07aba5dSTimm Baeder if (!interp__builtin_clrsb(S, OpPC, Frame, F, Call)) 2025a07aba5dSTimm Baeder return false; 2026a07aba5dSTimm Baeder break; 2027a07aba5dSTimm Baeder 2028a07aba5dSTimm Baeder case Builtin::BI__builtin_bitreverse8: 2029a07aba5dSTimm Baeder case Builtin::BI__builtin_bitreverse16: 2030a07aba5dSTimm Baeder case Builtin::BI__builtin_bitreverse32: 2031a07aba5dSTimm Baeder case Builtin::BI__builtin_bitreverse64: 2032a07aba5dSTimm Baeder if (!interp__builtin_bitreverse(S, OpPC, Frame, F, Call)) 2033a07aba5dSTimm Baeder return false; 2034a07aba5dSTimm Baeder break; 2035a07aba5dSTimm Baeder 2036a07aba5dSTimm Baeder case Builtin::BI__builtin_classify_type: 2037a07aba5dSTimm Baeder if (!interp__builtin_classify_type(S, OpPC, Frame, F, Call)) 2038a07aba5dSTimm Baeder return false; 2039a07aba5dSTimm Baeder break; 2040a07aba5dSTimm Baeder 2041a07aba5dSTimm Baeder case Builtin::BI__builtin_expect: 2042a07aba5dSTimm Baeder case Builtin::BI__builtin_expect_with_probability: 2043a07aba5dSTimm Baeder if (!interp__builtin_expect(S, OpPC, Frame, F, Call)) 2044a07aba5dSTimm Baeder return false; 2045a07aba5dSTimm Baeder break; 2046a07aba5dSTimm Baeder 2047a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateleft8: 2048a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateleft16: 2049a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateleft32: 2050a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateleft64: 2051a07aba5dSTimm Baeder case Builtin::BI_rotl8: // Microsoft variants of rotate left 2052a07aba5dSTimm Baeder case Builtin::BI_rotl16: 2053a07aba5dSTimm Baeder case Builtin::BI_rotl: 2054a07aba5dSTimm Baeder case Builtin::BI_lrotl: 2055a07aba5dSTimm Baeder case Builtin::BI_rotl64: 2056a07aba5dSTimm Baeder if (!interp__builtin_rotate(S, OpPC, Frame, F, Call, /*Right=*/false)) 2057a07aba5dSTimm Baeder return false; 2058a07aba5dSTimm Baeder break; 2059a07aba5dSTimm Baeder 2060a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateright8: 2061a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateright16: 2062a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateright32: 2063a07aba5dSTimm Baeder case Builtin::BI__builtin_rotateright64: 2064a07aba5dSTimm Baeder case Builtin::BI_rotr8: // Microsoft variants of rotate right 2065a07aba5dSTimm Baeder case Builtin::BI_rotr16: 2066a07aba5dSTimm Baeder case Builtin::BI_rotr: 2067a07aba5dSTimm Baeder case Builtin::BI_lrotr: 2068a07aba5dSTimm Baeder case Builtin::BI_rotr64: 2069a07aba5dSTimm Baeder if (!interp__builtin_rotate(S, OpPC, Frame, F, Call, /*Right=*/true)) 2070a07aba5dSTimm Baeder return false; 2071a07aba5dSTimm Baeder break; 2072a07aba5dSTimm Baeder 2073a07aba5dSTimm Baeder case Builtin::BI__builtin_ffs: 2074a07aba5dSTimm Baeder case Builtin::BI__builtin_ffsl: 2075a07aba5dSTimm Baeder case Builtin::BI__builtin_ffsll: 2076a07aba5dSTimm Baeder if (!interp__builtin_ffs(S, OpPC, Frame, F, Call)) 2077a07aba5dSTimm Baeder return false; 2078a07aba5dSTimm Baeder break; 2079a07aba5dSTimm Baeder case Builtin::BIaddressof: 2080a07aba5dSTimm Baeder case Builtin::BI__addressof: 2081a07aba5dSTimm Baeder case Builtin::BI__builtin_addressof: 2082a07aba5dSTimm Baeder if (!interp__builtin_addressof(S, OpPC, Frame, F, Call)) 2083a07aba5dSTimm Baeder return false; 2084a07aba5dSTimm Baeder break; 2085a07aba5dSTimm Baeder 2086a07aba5dSTimm Baeder case Builtin::BIas_const: 2087a07aba5dSTimm Baeder case Builtin::BIforward: 2088a07aba5dSTimm Baeder case Builtin::BIforward_like: 2089a07aba5dSTimm Baeder case Builtin::BImove: 2090a07aba5dSTimm Baeder case Builtin::BImove_if_noexcept: 2091a07aba5dSTimm Baeder if (!interp__builtin_move(S, OpPC, Frame, F, Call)) 2092a07aba5dSTimm Baeder return false; 2093a07aba5dSTimm Baeder break; 2094a07aba5dSTimm Baeder 2095a07aba5dSTimm Baeder case Builtin::BI__builtin_eh_return_data_regno: 2096a07aba5dSTimm Baeder if (!interp__builtin_eh_return_data_regno(S, OpPC, Frame, F, Call)) 2097a07aba5dSTimm Baeder return false; 2098a07aba5dSTimm Baeder break; 2099a07aba5dSTimm Baeder 2100a07aba5dSTimm Baeder case Builtin::BI__builtin_launder: 2101a07aba5dSTimm Baeder if (!noopPointer(S, OpPC, Frame, F, Call)) 2102a07aba5dSTimm Baeder return false; 2103a07aba5dSTimm Baeder break; 2104a07aba5dSTimm Baeder 2105a07aba5dSTimm Baeder case Builtin::BI__builtin_add_overflow: 2106a07aba5dSTimm Baeder case Builtin::BI__builtin_sub_overflow: 2107a07aba5dSTimm Baeder case Builtin::BI__builtin_mul_overflow: 2108a07aba5dSTimm Baeder case Builtin::BI__builtin_sadd_overflow: 2109a07aba5dSTimm Baeder case Builtin::BI__builtin_uadd_overflow: 2110a07aba5dSTimm Baeder case Builtin::BI__builtin_uaddl_overflow: 2111a07aba5dSTimm Baeder case Builtin::BI__builtin_uaddll_overflow: 2112a07aba5dSTimm Baeder case Builtin::BI__builtin_usub_overflow: 2113a07aba5dSTimm Baeder case Builtin::BI__builtin_usubl_overflow: 2114a07aba5dSTimm Baeder case Builtin::BI__builtin_usubll_overflow: 2115a07aba5dSTimm Baeder case Builtin::BI__builtin_umul_overflow: 2116a07aba5dSTimm Baeder case Builtin::BI__builtin_umull_overflow: 2117a07aba5dSTimm Baeder case Builtin::BI__builtin_umulll_overflow: 2118a07aba5dSTimm Baeder case Builtin::BI__builtin_saddl_overflow: 2119a07aba5dSTimm Baeder case Builtin::BI__builtin_saddll_overflow: 2120a07aba5dSTimm Baeder case Builtin::BI__builtin_ssub_overflow: 2121a07aba5dSTimm Baeder case Builtin::BI__builtin_ssubl_overflow: 2122a07aba5dSTimm Baeder case Builtin::BI__builtin_ssubll_overflow: 2123a07aba5dSTimm Baeder case Builtin::BI__builtin_smul_overflow: 2124a07aba5dSTimm Baeder case Builtin::BI__builtin_smull_overflow: 2125a07aba5dSTimm Baeder case Builtin::BI__builtin_smulll_overflow: 2126a07aba5dSTimm Baeder if (!interp__builtin_overflowop(S, OpPC, Frame, F, Call)) 2127a07aba5dSTimm Baeder return false; 2128a07aba5dSTimm Baeder break; 2129a07aba5dSTimm Baeder 2130a07aba5dSTimm Baeder case Builtin::BI__builtin_addcb: 2131a07aba5dSTimm Baeder case Builtin::BI__builtin_addcs: 2132a07aba5dSTimm Baeder case Builtin::BI__builtin_addc: 2133a07aba5dSTimm Baeder case Builtin::BI__builtin_addcl: 2134a07aba5dSTimm Baeder case Builtin::BI__builtin_addcll: 2135a07aba5dSTimm Baeder case Builtin::BI__builtin_subcb: 2136a07aba5dSTimm Baeder case Builtin::BI__builtin_subcs: 2137a07aba5dSTimm Baeder case Builtin::BI__builtin_subc: 2138a07aba5dSTimm Baeder case Builtin::BI__builtin_subcl: 2139a07aba5dSTimm Baeder case Builtin::BI__builtin_subcll: 2140a07aba5dSTimm Baeder if (!interp__builtin_carryop(S, OpPC, Frame, F, Call)) 2141a07aba5dSTimm Baeder return false; 2142a07aba5dSTimm Baeder break; 2143a07aba5dSTimm Baeder 2144a07aba5dSTimm Baeder case Builtin::BI__builtin_clz: 2145a07aba5dSTimm Baeder case Builtin::BI__builtin_clzl: 2146a07aba5dSTimm Baeder case Builtin::BI__builtin_clzll: 2147a07aba5dSTimm Baeder case Builtin::BI__builtin_clzs: 2148a07aba5dSTimm Baeder case Builtin::BI__builtin_clzg: 2149a07aba5dSTimm Baeder case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes 2150a07aba5dSTimm Baeder case Builtin::BI__lzcnt: 2151a07aba5dSTimm Baeder case Builtin::BI__lzcnt64: 2152a07aba5dSTimm Baeder if (!interp__builtin_clz(S, OpPC, Frame, F, Call)) 2153a07aba5dSTimm Baeder return false; 2154a07aba5dSTimm Baeder break; 2155a07aba5dSTimm Baeder 2156a07aba5dSTimm Baeder case Builtin::BI__builtin_ctz: 2157a07aba5dSTimm Baeder case Builtin::BI__builtin_ctzl: 2158a07aba5dSTimm Baeder case Builtin::BI__builtin_ctzll: 2159a07aba5dSTimm Baeder case Builtin::BI__builtin_ctzs: 2160a07aba5dSTimm Baeder case Builtin::BI__builtin_ctzg: 2161a07aba5dSTimm Baeder if (!interp__builtin_ctz(S, OpPC, Frame, F, Call)) 2162a07aba5dSTimm Baeder return false; 2163a07aba5dSTimm Baeder break; 2164a07aba5dSTimm Baeder 2165a07aba5dSTimm Baeder case Builtin::BI__builtin_bswap16: 2166a07aba5dSTimm Baeder case Builtin::BI__builtin_bswap32: 2167a07aba5dSTimm Baeder case Builtin::BI__builtin_bswap64: 2168a07aba5dSTimm Baeder if (!interp__builtin_bswap(S, OpPC, Frame, F, Call)) 2169a07aba5dSTimm Baeder return false; 2170a07aba5dSTimm Baeder break; 2171a07aba5dSTimm Baeder 2172a07aba5dSTimm Baeder case Builtin::BI__atomic_always_lock_free: 2173a07aba5dSTimm Baeder case Builtin::BI__atomic_is_lock_free: 2174a07aba5dSTimm Baeder case Builtin::BI__c11_atomic_is_lock_free: 2175a07aba5dSTimm Baeder if (!interp__builtin_atomic_lock_free(S, OpPC, Frame, F, Call)) 2176a07aba5dSTimm Baeder return false; 2177a07aba5dSTimm Baeder break; 2178a07aba5dSTimm Baeder 2179a07aba5dSTimm Baeder case Builtin::BI__builtin_complex: 2180a07aba5dSTimm Baeder if (!interp__builtin_complex(S, OpPC, Frame, F, Call)) 2181a07aba5dSTimm Baeder return false; 2182a07aba5dSTimm Baeder break; 2183a07aba5dSTimm Baeder 2184a07aba5dSTimm Baeder case Builtin::BI__builtin_is_aligned: 2185a07aba5dSTimm Baeder case Builtin::BI__builtin_align_up: 2186a07aba5dSTimm Baeder case Builtin::BI__builtin_align_down: 2187a07aba5dSTimm Baeder if (!interp__builtin_is_aligned_up_down(S, OpPC, Frame, F, Call)) 2188a07aba5dSTimm Baeder return false; 2189a07aba5dSTimm Baeder break; 2190a07aba5dSTimm Baeder 219180c15c48STimm Baeder case Builtin::BI__builtin_assume_aligned: 219280c15c48STimm Baeder if (!interp__builtin_assume_aligned(S, OpPC, Frame, F, Call)) 219380c15c48STimm Baeder return false; 219480c15c48STimm Baeder break; 219580c15c48STimm Baeder 219685181788STimm Baeder case clang::X86::BI__builtin_ia32_bextr_u32: 219785181788STimm Baeder case clang::X86::BI__builtin_ia32_bextr_u64: 219885181788STimm Baeder case clang::X86::BI__builtin_ia32_bextri_u32: 219985181788STimm Baeder case clang::X86::BI__builtin_ia32_bextri_u64: 220085181788STimm Baeder if (!interp__builtin_ia32_bextr(S, OpPC, Frame, F, Call)) 220185181788STimm Baeder return false; 220285181788STimm Baeder break; 220385181788STimm Baeder 22047147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_bzhi_si: 22057147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_bzhi_di: 22067147e88fSTimm Baeder if (!interp__builtin_ia32_bzhi(S, OpPC, Frame, F, Call)) 22077147e88fSTimm Baeder return false; 22087147e88fSTimm Baeder break; 22097147e88fSTimm Baeder 22107147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_lzcnt_u16: 22117147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_lzcnt_u32: 22127147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_lzcnt_u64: 22137147e88fSTimm Baeder if (!interp__builtin_ia32_lzcnt(S, OpPC, Frame, F, Call)) 22147147e88fSTimm Baeder return false; 22157147e88fSTimm Baeder break; 22167147e88fSTimm Baeder 22177147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_tzcnt_u16: 22187147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_tzcnt_u32: 22197147e88fSTimm Baeder case clang::X86::BI__builtin_ia32_tzcnt_u64: 22207147e88fSTimm Baeder if (!interp__builtin_ia32_tzcnt(S, OpPC, Frame, F, Call)) 22217147e88fSTimm Baeder return false; 22227147e88fSTimm Baeder break; 22237147e88fSTimm Baeder 2224f3baa73cSTimm Baeder case clang::X86::BI__builtin_ia32_pdep_si: 2225f3baa73cSTimm Baeder case clang::X86::BI__builtin_ia32_pdep_di: 2226f3baa73cSTimm Baeder if (!interp__builtin_ia32_pdep(S, OpPC, Frame, F, Call)) 2227f3baa73cSTimm Baeder return false; 2228f3baa73cSTimm Baeder break; 2229f3baa73cSTimm Baeder 2230f3baa73cSTimm Baeder case clang::X86::BI__builtin_ia32_pext_si: 2231f3baa73cSTimm Baeder case clang::X86::BI__builtin_ia32_pext_di: 2232f3baa73cSTimm Baeder if (!interp__builtin_ia32_pext(S, OpPC, Frame, F, Call)) 2233f3baa73cSTimm Baeder return false; 2234f3baa73cSTimm Baeder break; 2235f3baa73cSTimm Baeder 22366f8e8551STimm Baeder case clang::X86::BI__builtin_ia32_addcarryx_u32: 22376f8e8551STimm Baeder case clang::X86::BI__builtin_ia32_addcarryx_u64: 22386f8e8551STimm Baeder case clang::X86::BI__builtin_ia32_subborrow_u32: 22396f8e8551STimm Baeder case clang::X86::BI__builtin_ia32_subborrow_u64: 22406f8e8551STimm Baeder if (!interp__builtin_ia32_addcarry_subborrow(S, OpPC, Frame, F, Call)) 22416f8e8551STimm Baeder return false; 22426f8e8551STimm Baeder break; 22436f8e8551STimm Baeder 2244a07aba5dSTimm Baeder case Builtin::BI__builtin_os_log_format_buffer_size: 2245a07aba5dSTimm Baeder if (!interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, F, Call)) 2246a07aba5dSTimm Baeder return false; 2247a07aba5dSTimm Baeder break; 2248a07aba5dSTimm Baeder 2249a07aba5dSTimm Baeder case Builtin::BI__builtin_ptrauth_string_discriminator: 2250a07aba5dSTimm Baeder if (!interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, F, Call)) 2251a07aba5dSTimm Baeder return false; 2252a07aba5dSTimm Baeder break; 2253a07aba5dSTimm Baeder 2254a07aba5dSTimm Baeder case Builtin::BI__builtin_constant_p: 2255a07aba5dSTimm Baeder if (!interp__builtin_constant_p(S, OpPC, Frame, F, Call)) 2256a07aba5dSTimm Baeder return false; 2257a07aba5dSTimm Baeder break; 2258a07aba5dSTimm Baeder 2259f838d6b1STimm Baeder case Builtin::BI__noop: 2260f838d6b1STimm Baeder pushInteger(S, 0, Call->getType()); 2261f838d6b1STimm Baeder break; 2262f838d6b1STimm Baeder 2263610b8539STimm Baeder case Builtin::BI__builtin_operator_new: 2264610b8539STimm Baeder if (!interp__builtin_operator_new(S, OpPC, Frame, F, Call)) 2265610b8539STimm Baeder return false; 2266610b8539STimm Baeder break; 2267610b8539STimm Baeder 2268610b8539STimm Baeder case Builtin::BI__builtin_operator_delete: 2269610b8539STimm Baeder if (!interp__builtin_operator_delete(S, OpPC, Frame, F, Call)) 2270610b8539STimm Baeder return false; 2271610b8539STimm Baeder break; 2272610b8539STimm Baeder 2273b46a0482STimm Baeder case Builtin::BI__arithmetic_fence: 2274b46a0482STimm Baeder if (!interp__builtin_arithmetic_fence(S, OpPC, Frame, F, Call)) 2275b46a0482STimm Baeder return false; 2276b46a0482STimm Baeder break; 2277b46a0482STimm Baeder 227831bde711STimm Baeder case Builtin::BI__builtin_reduce_add: 2279c1dcf75aSTimm Baeder case Builtin::BI__builtin_reduce_mul: 2280ccc471feSTimm Baeder case Builtin::BI__builtin_reduce_and: 22811288f6d4STimm Baeder case Builtin::BI__builtin_reduce_or: 2282b587b910STimm Baeder case Builtin::BI__builtin_reduce_xor: 228331bde711STimm Baeder if (!interp__builtin_vector_reduce(S, OpPC, Frame, F, Call)) 228431bde711STimm Baeder return false; 228531bde711STimm Baeder break; 228631bde711STimm Baeder 2287637a1ae8STimm Baeder case Builtin::BI__builtin_elementwise_popcount: 2288637a1ae8STimm Baeder if (!interp__builtin_elementwise_popcount(S, OpPC, Frame, F, Call)) 2289637a1ae8STimm Baeder return false; 2290637a1ae8STimm Baeder break; 2291637a1ae8STimm Baeder 22920611fdd3STimm Baeder case Builtin::BI__builtin_memcpy: 2293*dac9736dSTimm Baeder case Builtin::BImemcpy: 22940611fdd3STimm Baeder if (!interp__builtin_memcpy(S, OpPC, Frame, F, Call)) 22950611fdd3STimm Baeder return false; 22960611fdd3STimm Baeder break; 22970611fdd3STimm Baeder 2298a07aba5dSTimm Baeder default: 2299a07aba5dSTimm Baeder S.FFDiag(S.Current->getLocation(OpPC), 2300a07aba5dSTimm Baeder diag::note_invalid_subexpr_in_const_expr) 2301a07aba5dSTimm Baeder << S.Current->getRange(OpPC); 2302a07aba5dSTimm Baeder 2303a07aba5dSTimm Baeder return false; 2304a07aba5dSTimm Baeder } 2305a07aba5dSTimm Baeder 230682ed9c03STimm Baeder return retPrimValue(S, OpPC, ReturnT); 2307a07aba5dSTimm Baeder } 2308a07aba5dSTimm Baeder 2309a07aba5dSTimm Baeder bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, 2310a07aba5dSTimm Baeder llvm::ArrayRef<int64_t> ArrayIndices, 2311a07aba5dSTimm Baeder int64_t &IntResult) { 2312a07aba5dSTimm Baeder CharUnits Result; 2313a07aba5dSTimm Baeder unsigned N = E->getNumComponents(); 2314a07aba5dSTimm Baeder assert(N > 0); 2315a07aba5dSTimm Baeder 2316a07aba5dSTimm Baeder unsigned ArrayIndex = 0; 2317a07aba5dSTimm Baeder QualType CurrentType = E->getTypeSourceInfo()->getType(); 2318a07aba5dSTimm Baeder for (unsigned I = 0; I != N; ++I) { 2319a07aba5dSTimm Baeder const OffsetOfNode &Node = E->getComponent(I); 2320a07aba5dSTimm Baeder switch (Node.getKind()) { 2321a07aba5dSTimm Baeder case OffsetOfNode::Field: { 2322a07aba5dSTimm Baeder const FieldDecl *MemberDecl = Node.getField(); 2323a07aba5dSTimm Baeder const RecordType *RT = CurrentType->getAs<RecordType>(); 2324a07aba5dSTimm Baeder if (!RT) 2325a07aba5dSTimm Baeder return false; 2326a07aba5dSTimm Baeder const RecordDecl *RD = RT->getDecl(); 2327a07aba5dSTimm Baeder if (RD->isInvalidDecl()) 2328a07aba5dSTimm Baeder return false; 2329d9e72860Syronglin const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD); 2330a07aba5dSTimm Baeder unsigned FieldIndex = MemberDecl->getFieldIndex(); 2331a07aba5dSTimm Baeder assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type"); 2332d9e72860Syronglin Result += 2333d9e72860Syronglin S.getASTContext().toCharUnitsFromBits(RL.getFieldOffset(FieldIndex)); 2334a07aba5dSTimm Baeder CurrentType = MemberDecl->getType().getNonReferenceType(); 2335a07aba5dSTimm Baeder break; 2336a07aba5dSTimm Baeder } 2337a07aba5dSTimm Baeder case OffsetOfNode::Array: { 2338a07aba5dSTimm Baeder // When generating bytecode, we put all the index expressions as Sint64 on 2339a07aba5dSTimm Baeder // the stack. 2340a07aba5dSTimm Baeder int64_t Index = ArrayIndices[ArrayIndex]; 2341d9e72860Syronglin const ArrayType *AT = S.getASTContext().getAsArrayType(CurrentType); 2342a07aba5dSTimm Baeder if (!AT) 2343a07aba5dSTimm Baeder return false; 2344a07aba5dSTimm Baeder CurrentType = AT->getElementType(); 2345d9e72860Syronglin CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType); 2346a07aba5dSTimm Baeder Result += Index * ElementSize; 2347a07aba5dSTimm Baeder ++ArrayIndex; 2348a07aba5dSTimm Baeder break; 2349a07aba5dSTimm Baeder } 2350a07aba5dSTimm Baeder case OffsetOfNode::Base: { 2351a07aba5dSTimm Baeder const CXXBaseSpecifier *BaseSpec = Node.getBase(); 2352a07aba5dSTimm Baeder if (BaseSpec->isVirtual()) 2353a07aba5dSTimm Baeder return false; 2354a07aba5dSTimm Baeder 2355a07aba5dSTimm Baeder // Find the layout of the class whose base we are looking into. 2356a07aba5dSTimm Baeder const RecordType *RT = CurrentType->getAs<RecordType>(); 2357a07aba5dSTimm Baeder if (!RT) 2358a07aba5dSTimm Baeder return false; 2359a07aba5dSTimm Baeder const RecordDecl *RD = RT->getDecl(); 2360a07aba5dSTimm Baeder if (RD->isInvalidDecl()) 2361a07aba5dSTimm Baeder return false; 2362d9e72860Syronglin const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD); 2363a07aba5dSTimm Baeder 2364a07aba5dSTimm Baeder // Find the base class itself. 2365a07aba5dSTimm Baeder CurrentType = BaseSpec->getType(); 2366a07aba5dSTimm Baeder const RecordType *BaseRT = CurrentType->getAs<RecordType>(); 2367a07aba5dSTimm Baeder if (!BaseRT) 2368a07aba5dSTimm Baeder return false; 2369a07aba5dSTimm Baeder 2370a07aba5dSTimm Baeder // Add the offset to the base. 2371a07aba5dSTimm Baeder Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl())); 2372a07aba5dSTimm Baeder break; 2373a07aba5dSTimm Baeder } 2374a07aba5dSTimm Baeder case OffsetOfNode::Identifier: 2375a07aba5dSTimm Baeder llvm_unreachable("Dependent OffsetOfExpr?"); 2376a07aba5dSTimm Baeder } 2377a07aba5dSTimm Baeder } 2378a07aba5dSTimm Baeder 2379a07aba5dSTimm Baeder IntResult = Result.getQuantity(); 2380a07aba5dSTimm Baeder 2381a07aba5dSTimm Baeder return true; 2382a07aba5dSTimm Baeder } 2383a07aba5dSTimm Baeder 2384a07aba5dSTimm Baeder bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC, 2385a07aba5dSTimm Baeder const Pointer &Ptr, const APSInt &IntValue) { 2386a07aba5dSTimm Baeder 2387a07aba5dSTimm Baeder const Record *R = Ptr.getRecord(); 2388a07aba5dSTimm Baeder assert(R); 2389a07aba5dSTimm Baeder assert(R->getNumFields() == 1); 2390a07aba5dSTimm Baeder 2391a07aba5dSTimm Baeder unsigned FieldOffset = R->getField(0u)->Offset; 2392a07aba5dSTimm Baeder const Pointer &FieldPtr = Ptr.atField(FieldOffset); 2393a07aba5dSTimm Baeder PrimType FieldT = *S.getContext().classify(FieldPtr.getType()); 2394a07aba5dSTimm Baeder 2395a07aba5dSTimm Baeder INT_TYPE_SWITCH(FieldT, 2396a07aba5dSTimm Baeder FieldPtr.deref<T>() = T::from(IntValue.getSExtValue())); 2397a07aba5dSTimm Baeder FieldPtr.initialize(); 2398a07aba5dSTimm Baeder return true; 2399a07aba5dSTimm Baeder } 2400a07aba5dSTimm Baeder 2401a07aba5dSTimm Baeder static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src, 2402a07aba5dSTimm Baeder Pointer &Dest, bool Activate); 2403a07aba5dSTimm Baeder static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src, 2404a07aba5dSTimm Baeder Pointer &Dest, bool Activate = false) { 2405a07aba5dSTimm Baeder [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc(); 2406a07aba5dSTimm Baeder const Descriptor *DestDesc = Dest.getFieldDesc(); 2407a07aba5dSTimm Baeder 2408a07aba5dSTimm Baeder auto copyField = [&](const Record::Field &F, bool Activate) -> bool { 2409a07aba5dSTimm Baeder Pointer DestField = Dest.atField(F.Offset); 2410a07aba5dSTimm Baeder if (std::optional<PrimType> FT = S.Ctx.classify(F.Decl->getType())) { 2411a07aba5dSTimm Baeder TYPE_SWITCH(*FT, { 2412a07aba5dSTimm Baeder DestField.deref<T>() = Src.atField(F.Offset).deref<T>(); 2413a07aba5dSTimm Baeder if (Src.atField(F.Offset).isInitialized()) 2414a07aba5dSTimm Baeder DestField.initialize(); 2415a07aba5dSTimm Baeder if (Activate) 2416a07aba5dSTimm Baeder DestField.activate(); 2417a07aba5dSTimm Baeder }); 2418a07aba5dSTimm Baeder return true; 2419a07aba5dSTimm Baeder } 2420a07aba5dSTimm Baeder // Composite field. 2421a07aba5dSTimm Baeder return copyComposite(S, OpPC, Src.atField(F.Offset), DestField, Activate); 2422a07aba5dSTimm Baeder }; 2423a07aba5dSTimm Baeder 2424a07aba5dSTimm Baeder assert(SrcDesc->isRecord()); 2425a07aba5dSTimm Baeder assert(SrcDesc->ElemRecord == DestDesc->ElemRecord); 2426a07aba5dSTimm Baeder const Record *R = DestDesc->ElemRecord; 2427a07aba5dSTimm Baeder for (const Record::Field &F : R->fields()) { 2428a07aba5dSTimm Baeder if (R->isUnion()) { 2429a07aba5dSTimm Baeder // For unions, only copy the active field. 2430a07aba5dSTimm Baeder const Pointer &SrcField = Src.atField(F.Offset); 2431a07aba5dSTimm Baeder if (SrcField.isActive()) { 2432a07aba5dSTimm Baeder if (!copyField(F, /*Activate=*/true)) 2433a07aba5dSTimm Baeder return false; 2434a07aba5dSTimm Baeder } 2435a07aba5dSTimm Baeder } else { 2436a07aba5dSTimm Baeder if (!copyField(F, Activate)) 2437a07aba5dSTimm Baeder return false; 2438a07aba5dSTimm Baeder } 2439a07aba5dSTimm Baeder } 2440a07aba5dSTimm Baeder 2441a07aba5dSTimm Baeder for (const Record::Base &B : R->bases()) { 2442a07aba5dSTimm Baeder Pointer DestBase = Dest.atField(B.Offset); 2443a07aba5dSTimm Baeder if (!copyRecord(S, OpPC, Src.atField(B.Offset), DestBase, Activate)) 2444a07aba5dSTimm Baeder return false; 2445a07aba5dSTimm Baeder } 2446a07aba5dSTimm Baeder 2447a07aba5dSTimm Baeder Dest.initialize(); 2448a07aba5dSTimm Baeder return true; 2449a07aba5dSTimm Baeder } 2450a07aba5dSTimm Baeder 2451a07aba5dSTimm Baeder static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src, 2452a07aba5dSTimm Baeder Pointer &Dest, bool Activate = false) { 2453a07aba5dSTimm Baeder assert(Src.isLive() && Dest.isLive()); 2454a07aba5dSTimm Baeder 2455a07aba5dSTimm Baeder [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc(); 2456a07aba5dSTimm Baeder const Descriptor *DestDesc = Dest.getFieldDesc(); 2457a07aba5dSTimm Baeder 2458a07aba5dSTimm Baeder assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive()); 2459a07aba5dSTimm Baeder 2460a07aba5dSTimm Baeder if (DestDesc->isPrimitiveArray()) { 2461a07aba5dSTimm Baeder assert(SrcDesc->isPrimitiveArray()); 2462a07aba5dSTimm Baeder assert(SrcDesc->getNumElems() == DestDesc->getNumElems()); 2463a07aba5dSTimm Baeder PrimType ET = DestDesc->getPrimType(); 2464a07aba5dSTimm Baeder for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) { 2465a07aba5dSTimm Baeder Pointer DestElem = Dest.atIndex(I); 2466a07aba5dSTimm Baeder TYPE_SWITCH(ET, { 2467a07aba5dSTimm Baeder DestElem.deref<T>() = Src.atIndex(I).deref<T>(); 2468a07aba5dSTimm Baeder DestElem.initialize(); 2469a07aba5dSTimm Baeder }); 2470a07aba5dSTimm Baeder } 2471a07aba5dSTimm Baeder return true; 2472a07aba5dSTimm Baeder } 2473a07aba5dSTimm Baeder 2474a07aba5dSTimm Baeder if (DestDesc->isRecord()) 2475a07aba5dSTimm Baeder return copyRecord(S, OpPC, Src, Dest, Activate); 2476a07aba5dSTimm Baeder return Invalid(S, OpPC); 2477a07aba5dSTimm Baeder } 2478a07aba5dSTimm Baeder 2479a07aba5dSTimm Baeder bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) { 2480a07aba5dSTimm Baeder return copyComposite(S, OpPC, Src, Dest); 2481a07aba5dSTimm Baeder } 2482a07aba5dSTimm Baeder 2483a07aba5dSTimm Baeder } // namespace interp 2484a07aba5dSTimm Baeder } // namespace clang 2485