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