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