xref: /freebsd/contrib/llvm-project/clang/lib/AST/ByteCode/InterpBuiltin.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1*700637cbSDimitry Andric //===--- InterpBuiltin.cpp - Interpreter for the constexpr VM ---*- C++ -*-===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric #include "../ExprConstShared.h"
9*700637cbSDimitry Andric #include "Boolean.h"
10*700637cbSDimitry Andric #include "Compiler.h"
11*700637cbSDimitry Andric #include "EvalEmitter.h"
12*700637cbSDimitry Andric #include "Interp.h"
13*700637cbSDimitry Andric #include "InterpBuiltinBitCast.h"
14*700637cbSDimitry Andric #include "PrimType.h"
15*700637cbSDimitry Andric #include "clang/AST/OSLog.h"
16*700637cbSDimitry Andric #include "clang/AST/RecordLayout.h"
17*700637cbSDimitry Andric #include "clang/Basic/Builtins.h"
18*700637cbSDimitry Andric #include "clang/Basic/TargetBuiltins.h"
19*700637cbSDimitry Andric #include "clang/Basic/TargetInfo.h"
20*700637cbSDimitry Andric #include "llvm/ADT/StringExtras.h"
21*700637cbSDimitry Andric #include "llvm/Support/ErrorHandling.h"
22*700637cbSDimitry Andric #include "llvm/Support/SipHash.h"
23*700637cbSDimitry Andric 
24*700637cbSDimitry Andric namespace clang {
25*700637cbSDimitry Andric namespace interp {
26*700637cbSDimitry Andric 
isNoopBuiltin(unsigned ID)27*700637cbSDimitry Andric LLVM_ATTRIBUTE_UNUSED static bool isNoopBuiltin(unsigned ID) {
28*700637cbSDimitry Andric   switch (ID) {
29*700637cbSDimitry Andric   case Builtin::BIas_const:
30*700637cbSDimitry Andric   case Builtin::BIforward:
31*700637cbSDimitry Andric   case Builtin::BIforward_like:
32*700637cbSDimitry Andric   case Builtin::BImove:
33*700637cbSDimitry Andric   case Builtin::BImove_if_noexcept:
34*700637cbSDimitry Andric   case Builtin::BIaddressof:
35*700637cbSDimitry Andric   case Builtin::BI__addressof:
36*700637cbSDimitry Andric   case Builtin::BI__builtin_addressof:
37*700637cbSDimitry Andric   case Builtin::BI__builtin_launder:
38*700637cbSDimitry Andric     return true;
39*700637cbSDimitry Andric   default:
40*700637cbSDimitry Andric     return false;
41*700637cbSDimitry Andric   }
42*700637cbSDimitry Andric   return false;
43*700637cbSDimitry Andric }
44*700637cbSDimitry Andric 
discard(InterpStack & Stk,PrimType T)45*700637cbSDimitry Andric static void discard(InterpStack &Stk, PrimType T) {
46*700637cbSDimitry Andric   TYPE_SWITCH(T, { Stk.discard<T>(); });
47*700637cbSDimitry Andric }
48*700637cbSDimitry Andric 
popToAPSInt(InterpStack & Stk,PrimType T)49*700637cbSDimitry Andric static APSInt popToAPSInt(InterpStack &Stk, PrimType T) {
50*700637cbSDimitry Andric   INT_TYPE_SWITCH(T, return Stk.pop<T>().toAPSInt());
51*700637cbSDimitry Andric }
52*700637cbSDimitry Andric 
53*700637cbSDimitry Andric /// Pushes \p Val on the stack as the type given by \p QT.
pushInteger(InterpState & S,const APSInt & Val,QualType QT)54*700637cbSDimitry Andric static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {
55*700637cbSDimitry Andric   assert(QT->isSignedIntegerOrEnumerationType() ||
56*700637cbSDimitry Andric          QT->isUnsignedIntegerOrEnumerationType());
57*700637cbSDimitry Andric   std::optional<PrimType> T = S.getContext().classify(QT);
58*700637cbSDimitry Andric   assert(T);
59*700637cbSDimitry Andric 
60*700637cbSDimitry Andric   unsigned BitWidth = S.getASTContext().getTypeSize(QT);
61*700637cbSDimitry Andric 
62*700637cbSDimitry Andric   if (T == PT_IntAPS) {
63*700637cbSDimitry Andric     auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
64*700637cbSDimitry Andric     Result.copy(Val);
65*700637cbSDimitry Andric     S.Stk.push<IntegralAP<true>>(Result);
66*700637cbSDimitry Andric     return;
67*700637cbSDimitry Andric   }
68*700637cbSDimitry Andric 
69*700637cbSDimitry Andric   if (T == PT_IntAP) {
70*700637cbSDimitry Andric     auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
71*700637cbSDimitry Andric     Result.copy(Val);
72*700637cbSDimitry Andric     S.Stk.push<IntegralAP<false>>(Result);
73*700637cbSDimitry Andric     return;
74*700637cbSDimitry Andric   }
75*700637cbSDimitry Andric 
76*700637cbSDimitry Andric   if (QT->isSignedIntegerOrEnumerationType()) {
77*700637cbSDimitry Andric     int64_t V = Val.getSExtValue();
78*700637cbSDimitry Andric     INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });
79*700637cbSDimitry Andric   } else {
80*700637cbSDimitry Andric     assert(QT->isUnsignedIntegerOrEnumerationType());
81*700637cbSDimitry Andric     uint64_t V = Val.getZExtValue();
82*700637cbSDimitry Andric     INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });
83*700637cbSDimitry Andric   }
84*700637cbSDimitry Andric }
85*700637cbSDimitry Andric 
86*700637cbSDimitry Andric template <typename T>
pushInteger(InterpState & S,T Val,QualType QT)87*700637cbSDimitry Andric static void pushInteger(InterpState &S, T Val, QualType QT) {
88*700637cbSDimitry Andric   if constexpr (std::is_same_v<T, APInt>)
89*700637cbSDimitry Andric     pushInteger(S, APSInt(Val, !std::is_signed_v<T>), QT);
90*700637cbSDimitry Andric   else if constexpr (std::is_same_v<T, APSInt>)
91*700637cbSDimitry Andric     pushInteger(S, Val, QT);
92*700637cbSDimitry Andric   else
93*700637cbSDimitry Andric     pushInteger(S,
94*700637cbSDimitry Andric                 APSInt(APInt(sizeof(T) * 8, static_cast<uint64_t>(Val),
95*700637cbSDimitry Andric                              std::is_signed_v<T>),
96*700637cbSDimitry Andric                        !std::is_signed_v<T>),
97*700637cbSDimitry Andric                 QT);
98*700637cbSDimitry Andric }
99*700637cbSDimitry Andric 
assignInteger(InterpState & S,const Pointer & Dest,PrimType ValueT,const APSInt & Value)100*700637cbSDimitry Andric static void assignInteger(InterpState &S, const Pointer &Dest, PrimType ValueT,
101*700637cbSDimitry Andric                           const APSInt &Value) {
102*700637cbSDimitry Andric 
103*700637cbSDimitry Andric   if (ValueT == PT_IntAPS) {
104*700637cbSDimitry Andric     Dest.deref<IntegralAP<true>>() =
105*700637cbSDimitry Andric         S.allocAP<IntegralAP<true>>(Value.getBitWidth());
106*700637cbSDimitry Andric     Dest.deref<IntegralAP<true>>().copy(Value);
107*700637cbSDimitry Andric   } else if (ValueT == PT_IntAP) {
108*700637cbSDimitry Andric     Dest.deref<IntegralAP<false>>() =
109*700637cbSDimitry Andric         S.allocAP<IntegralAP<false>>(Value.getBitWidth());
110*700637cbSDimitry Andric     Dest.deref<IntegralAP<false>>().copy(Value);
111*700637cbSDimitry Andric   } else {
112*700637cbSDimitry Andric     INT_TYPE_SWITCH_NO_BOOL(
113*700637cbSDimitry Andric         ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); });
114*700637cbSDimitry Andric   }
115*700637cbSDimitry Andric }
116*700637cbSDimitry Andric 
getElemType(const Pointer & P)117*700637cbSDimitry Andric static QualType getElemType(const Pointer &P) {
118*700637cbSDimitry Andric   const Descriptor *Desc = P.getFieldDesc();
119*700637cbSDimitry Andric   QualType T = Desc->getType();
120*700637cbSDimitry Andric   if (Desc->isPrimitive())
121*700637cbSDimitry Andric     return T;
122*700637cbSDimitry Andric   if (T->isPointerType())
123*700637cbSDimitry Andric     return T->getAs<PointerType>()->getPointeeType();
124*700637cbSDimitry Andric   if (Desc->isArray())
125*700637cbSDimitry Andric     return Desc->getElemQualType();
126*700637cbSDimitry Andric   if (const auto *AT = T->getAsArrayTypeUnsafe())
127*700637cbSDimitry Andric     return AT->getElementType();
128*700637cbSDimitry Andric   return T;
129*700637cbSDimitry Andric }
130*700637cbSDimitry Andric 
diagnoseNonConstexprBuiltin(InterpState & S,CodePtr OpPC,unsigned ID)131*700637cbSDimitry Andric static void diagnoseNonConstexprBuiltin(InterpState &S, CodePtr OpPC,
132*700637cbSDimitry Andric                                         unsigned ID) {
133*700637cbSDimitry Andric   if (!S.diagnosing())
134*700637cbSDimitry Andric     return;
135*700637cbSDimitry Andric 
136*700637cbSDimitry Andric   auto Loc = S.Current->getSource(OpPC);
137*700637cbSDimitry Andric   if (S.getLangOpts().CPlusPlus11)
138*700637cbSDimitry Andric     S.CCEDiag(Loc, diag::note_constexpr_invalid_function)
139*700637cbSDimitry Andric         << /*isConstexpr=*/0 << /*isConstructor=*/0
140*700637cbSDimitry Andric         << S.getASTContext().BuiltinInfo.getQuotedName(ID);
141*700637cbSDimitry Andric   else
142*700637cbSDimitry Andric     S.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
143*700637cbSDimitry Andric }
144*700637cbSDimitry Andric 
interp__builtin_is_constant_evaluated(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)145*700637cbSDimitry Andric static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC,
146*700637cbSDimitry Andric                                                   const InterpFrame *Frame,
147*700637cbSDimitry Andric                                                   const CallExpr *Call) {
148*700637cbSDimitry Andric   unsigned Depth = S.Current->getDepth();
149*700637cbSDimitry Andric   auto isStdCall = [](const FunctionDecl *F) -> bool {
150*700637cbSDimitry Andric     return F && F->isInStdNamespace() && F->getIdentifier() &&
151*700637cbSDimitry Andric            F->getIdentifier()->isStr("is_constant_evaluated");
152*700637cbSDimitry Andric   };
153*700637cbSDimitry Andric   const InterpFrame *Caller = Frame->Caller;
154*700637cbSDimitry Andric   // The current frame is the one for __builtin_is_constant_evaluated.
155*700637cbSDimitry Andric   // The one above that, potentially the one for std::is_constant_evaluated().
156*700637cbSDimitry Andric   if (S.inConstantContext() && !S.checkingPotentialConstantExpression() &&
157*700637cbSDimitry Andric       S.getEvalStatus().Diag &&
158*700637cbSDimitry Andric       (Depth == 0 || (Depth == 1 && isStdCall(Frame->getCallee())))) {
159*700637cbSDimitry Andric     if (Caller && isStdCall(Frame->getCallee())) {
160*700637cbSDimitry Andric       const Expr *E = Caller->getExpr(Caller->getRetPC());
161*700637cbSDimitry Andric       S.report(E->getExprLoc(),
162*700637cbSDimitry Andric                diag::warn_is_constant_evaluated_always_true_constexpr)
163*700637cbSDimitry Andric           << "std::is_constant_evaluated" << E->getSourceRange();
164*700637cbSDimitry Andric     } else {
165*700637cbSDimitry Andric       S.report(Call->getExprLoc(),
166*700637cbSDimitry Andric                diag::warn_is_constant_evaluated_always_true_constexpr)
167*700637cbSDimitry Andric           << "__builtin_is_constant_evaluated" << Call->getSourceRange();
168*700637cbSDimitry Andric     }
169*700637cbSDimitry Andric   }
170*700637cbSDimitry Andric 
171*700637cbSDimitry Andric   S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
172*700637cbSDimitry Andric   return true;
173*700637cbSDimitry Andric }
174*700637cbSDimitry Andric 
175*700637cbSDimitry Andric // __builtin_assume(int)
interp__builtin_assume(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)176*700637cbSDimitry Andric static bool interp__builtin_assume(InterpState &S, CodePtr OpPC,
177*700637cbSDimitry Andric                                    const InterpFrame *Frame,
178*700637cbSDimitry Andric                                    const CallExpr *Call) {
179*700637cbSDimitry Andric   assert(Call->getNumArgs() == 1);
180*700637cbSDimitry Andric   discard(S.Stk, *S.getContext().classify(Call->getArg(0)));
181*700637cbSDimitry Andric   return true;
182*700637cbSDimitry Andric }
183*700637cbSDimitry Andric 
interp__builtin_strcmp(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,unsigned ID)184*700637cbSDimitry Andric static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
185*700637cbSDimitry Andric                                    const InterpFrame *Frame,
186*700637cbSDimitry Andric                                    const CallExpr *Call, unsigned ID) {
187*700637cbSDimitry Andric   uint64_t Limit = ~static_cast<uint64_t>(0);
188*700637cbSDimitry Andric   if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp ||
189*700637cbSDimitry Andric       ID == Builtin::BIwcsncmp || ID == Builtin::BI__builtin_wcsncmp)
190*700637cbSDimitry Andric     Limit = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)))
191*700637cbSDimitry Andric                 .getZExtValue();
192*700637cbSDimitry Andric 
193*700637cbSDimitry Andric   const Pointer &B = S.Stk.pop<Pointer>();
194*700637cbSDimitry Andric   const Pointer &A = S.Stk.pop<Pointer>();
195*700637cbSDimitry Andric   if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp ||
196*700637cbSDimitry Andric       ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp)
197*700637cbSDimitry Andric     diagnoseNonConstexprBuiltin(S, OpPC, ID);
198*700637cbSDimitry Andric 
199*700637cbSDimitry Andric   if (Limit == 0) {
200*700637cbSDimitry Andric     pushInteger(S, 0, Call->getType());
201*700637cbSDimitry Andric     return true;
202*700637cbSDimitry Andric   }
203*700637cbSDimitry Andric 
204*700637cbSDimitry Andric   if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))
205*700637cbSDimitry Andric     return false;
206*700637cbSDimitry Andric 
207*700637cbSDimitry Andric   if (A.isDummy() || B.isDummy())
208*700637cbSDimitry Andric     return false;
209*700637cbSDimitry Andric 
210*700637cbSDimitry Andric   bool IsWide = ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp ||
211*700637cbSDimitry Andric                 ID == Builtin::BI__builtin_wcscmp ||
212*700637cbSDimitry Andric                 ID == Builtin::BI__builtin_wcsncmp;
213*700637cbSDimitry Andric   assert(A.getFieldDesc()->isPrimitiveArray());
214*700637cbSDimitry Andric   assert(B.getFieldDesc()->isPrimitiveArray());
215*700637cbSDimitry Andric 
216*700637cbSDimitry Andric   assert(getElemType(A).getTypePtr() == getElemType(B).getTypePtr());
217*700637cbSDimitry Andric   PrimType ElemT = *S.getContext().classify(getElemType(A));
218*700637cbSDimitry Andric 
219*700637cbSDimitry Andric   auto returnResult = [&](int V) -> bool {
220*700637cbSDimitry Andric     pushInteger(S, V, Call->getType());
221*700637cbSDimitry Andric     return true;
222*700637cbSDimitry Andric   };
223*700637cbSDimitry Andric 
224*700637cbSDimitry Andric   unsigned IndexA = A.getIndex();
225*700637cbSDimitry Andric   unsigned IndexB = B.getIndex();
226*700637cbSDimitry Andric   uint64_t Steps = 0;
227*700637cbSDimitry Andric   for (;; ++IndexA, ++IndexB, ++Steps) {
228*700637cbSDimitry Andric 
229*700637cbSDimitry Andric     if (Steps >= Limit)
230*700637cbSDimitry Andric       break;
231*700637cbSDimitry Andric     const Pointer &PA = A.atIndex(IndexA);
232*700637cbSDimitry Andric     const Pointer &PB = B.atIndex(IndexB);
233*700637cbSDimitry Andric     if (!CheckRange(S, OpPC, PA, AK_Read) ||
234*700637cbSDimitry Andric         !CheckRange(S, OpPC, PB, AK_Read)) {
235*700637cbSDimitry Andric       return false;
236*700637cbSDimitry Andric     }
237*700637cbSDimitry Andric 
238*700637cbSDimitry Andric     if (IsWide) {
239*700637cbSDimitry Andric       INT_TYPE_SWITCH(ElemT, {
240*700637cbSDimitry Andric         T CA = PA.deref<T>();
241*700637cbSDimitry Andric         T CB = PB.deref<T>();
242*700637cbSDimitry Andric         if (CA > CB)
243*700637cbSDimitry Andric           return returnResult(1);
244*700637cbSDimitry Andric         else if (CA < CB)
245*700637cbSDimitry Andric           return returnResult(-1);
246*700637cbSDimitry Andric         else if (CA.isZero() || CB.isZero())
247*700637cbSDimitry Andric           return returnResult(0);
248*700637cbSDimitry Andric       });
249*700637cbSDimitry Andric       continue;
250*700637cbSDimitry Andric     }
251*700637cbSDimitry Andric 
252*700637cbSDimitry Andric     uint8_t CA = PA.deref<uint8_t>();
253*700637cbSDimitry Andric     uint8_t CB = PB.deref<uint8_t>();
254*700637cbSDimitry Andric 
255*700637cbSDimitry Andric     if (CA > CB)
256*700637cbSDimitry Andric       return returnResult(1);
257*700637cbSDimitry Andric     else if (CA < CB)
258*700637cbSDimitry Andric       return returnResult(-1);
259*700637cbSDimitry Andric     if (CA == 0 || CB == 0)
260*700637cbSDimitry Andric       return returnResult(0);
261*700637cbSDimitry Andric   }
262*700637cbSDimitry Andric 
263*700637cbSDimitry Andric   return returnResult(0);
264*700637cbSDimitry Andric }
265*700637cbSDimitry Andric 
interp__builtin_strlen(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,unsigned ID)266*700637cbSDimitry Andric static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
267*700637cbSDimitry Andric                                    const InterpFrame *Frame,
268*700637cbSDimitry Andric                                    const CallExpr *Call, unsigned ID) {
269*700637cbSDimitry Andric   const Pointer &StrPtr = S.Stk.pop<Pointer>();
270*700637cbSDimitry Andric 
271*700637cbSDimitry Andric   if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen)
272*700637cbSDimitry Andric     diagnoseNonConstexprBuiltin(S, OpPC, ID);
273*700637cbSDimitry Andric 
274*700637cbSDimitry Andric   if (!CheckArray(S, OpPC, StrPtr))
275*700637cbSDimitry Andric     return false;
276*700637cbSDimitry Andric 
277*700637cbSDimitry Andric   if (!CheckLive(S, OpPC, StrPtr, AK_Read))
278*700637cbSDimitry Andric     return false;
279*700637cbSDimitry Andric 
280*700637cbSDimitry Andric   if (!CheckDummy(S, OpPC, StrPtr, AK_Read))
281*700637cbSDimitry Andric     return false;
282*700637cbSDimitry Andric 
283*700637cbSDimitry Andric   assert(StrPtr.getFieldDesc()->isPrimitiveArray());
284*700637cbSDimitry Andric   unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize();
285*700637cbSDimitry Andric 
286*700637cbSDimitry Andric   if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) {
287*700637cbSDimitry Andric     [[maybe_unused]] const ASTContext &AC = S.getASTContext();
288*700637cbSDimitry Andric     assert(ElemSize == AC.getTypeSizeInChars(AC.getWCharType()).getQuantity());
289*700637cbSDimitry Andric   }
290*700637cbSDimitry Andric 
291*700637cbSDimitry Andric   size_t Len = 0;
292*700637cbSDimitry Andric   for (size_t I = StrPtr.getIndex();; ++I, ++Len) {
293*700637cbSDimitry Andric     const Pointer &ElemPtr = StrPtr.atIndex(I);
294*700637cbSDimitry Andric 
295*700637cbSDimitry Andric     if (!CheckRange(S, OpPC, ElemPtr, AK_Read))
296*700637cbSDimitry Andric       return false;
297*700637cbSDimitry Andric 
298*700637cbSDimitry Andric     uint32_t Val;
299*700637cbSDimitry Andric     switch (ElemSize) {
300*700637cbSDimitry Andric     case 1:
301*700637cbSDimitry Andric       Val = ElemPtr.deref<uint8_t>();
302*700637cbSDimitry Andric       break;
303*700637cbSDimitry Andric     case 2:
304*700637cbSDimitry Andric       Val = ElemPtr.deref<uint16_t>();
305*700637cbSDimitry Andric       break;
306*700637cbSDimitry Andric     case 4:
307*700637cbSDimitry Andric       Val = ElemPtr.deref<uint32_t>();
308*700637cbSDimitry Andric       break;
309*700637cbSDimitry Andric     default:
310*700637cbSDimitry Andric       llvm_unreachable("Unsupported char size");
311*700637cbSDimitry Andric     }
312*700637cbSDimitry Andric     if (Val == 0)
313*700637cbSDimitry Andric       break;
314*700637cbSDimitry Andric   }
315*700637cbSDimitry Andric 
316*700637cbSDimitry Andric   pushInteger(S, Len, Call->getType());
317*700637cbSDimitry Andric 
318*700637cbSDimitry Andric   return true;
319*700637cbSDimitry Andric }
320*700637cbSDimitry Andric 
interp__builtin_nan(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,bool Signaling)321*700637cbSDimitry Andric static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,
322*700637cbSDimitry Andric                                 const InterpFrame *Frame, const CallExpr *Call,
323*700637cbSDimitry Andric                                 bool Signaling) {
324*700637cbSDimitry Andric   const Pointer &Arg = S.Stk.pop<Pointer>();
325*700637cbSDimitry Andric 
326*700637cbSDimitry Andric   if (!CheckLoad(S, OpPC, Arg))
327*700637cbSDimitry Andric     return false;
328*700637cbSDimitry Andric 
329*700637cbSDimitry Andric   assert(Arg.getFieldDesc()->isPrimitiveArray());
330*700637cbSDimitry Andric 
331*700637cbSDimitry Andric   // Convert the given string to an integer using StringRef's API.
332*700637cbSDimitry Andric   llvm::APInt Fill;
333*700637cbSDimitry Andric   std::string Str;
334*700637cbSDimitry Andric   assert(Arg.getNumElems() >= 1);
335*700637cbSDimitry Andric   for (unsigned I = 0;; ++I) {
336*700637cbSDimitry Andric     const Pointer &Elem = Arg.atIndex(I);
337*700637cbSDimitry Andric 
338*700637cbSDimitry Andric     if (!CheckLoad(S, OpPC, Elem))
339*700637cbSDimitry Andric       return false;
340*700637cbSDimitry Andric 
341*700637cbSDimitry Andric     if (Elem.deref<int8_t>() == 0)
342*700637cbSDimitry Andric       break;
343*700637cbSDimitry Andric 
344*700637cbSDimitry Andric     Str += Elem.deref<char>();
345*700637cbSDimitry Andric   }
346*700637cbSDimitry Andric 
347*700637cbSDimitry Andric   // Treat empty strings as if they were zero.
348*700637cbSDimitry Andric   if (Str.empty())
349*700637cbSDimitry Andric     Fill = llvm::APInt(32, 0);
350*700637cbSDimitry Andric   else if (StringRef(Str).getAsInteger(0, Fill))
351*700637cbSDimitry Andric     return false;
352*700637cbSDimitry Andric 
353*700637cbSDimitry Andric   const llvm::fltSemantics &TargetSemantics =
354*700637cbSDimitry Andric       S.getASTContext().getFloatTypeSemantics(
355*700637cbSDimitry Andric           Call->getDirectCallee()->getReturnType());
356*700637cbSDimitry Andric 
357*700637cbSDimitry Andric   Floating Result = S.allocFloat(TargetSemantics);
358*700637cbSDimitry Andric   if (S.getASTContext().getTargetInfo().isNan2008()) {
359*700637cbSDimitry Andric     if (Signaling)
360*700637cbSDimitry Andric       Result.copy(
361*700637cbSDimitry Andric           llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
362*700637cbSDimitry Andric     else
363*700637cbSDimitry Andric       Result.copy(
364*700637cbSDimitry Andric           llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
365*700637cbSDimitry Andric   } else {
366*700637cbSDimitry Andric     // Prior to IEEE 754-2008, architectures were allowed to choose whether
367*700637cbSDimitry Andric     // the first bit of their significand was set for qNaN or sNaN. MIPS chose
368*700637cbSDimitry Andric     // a different encoding to what became a standard in 2008, and for pre-
369*700637cbSDimitry Andric     // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as
370*700637cbSDimitry Andric     // sNaN. This is now known as "legacy NaN" encoding.
371*700637cbSDimitry Andric     if (Signaling)
372*700637cbSDimitry Andric       Result.copy(
373*700637cbSDimitry Andric           llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
374*700637cbSDimitry Andric     else
375*700637cbSDimitry Andric       Result.copy(
376*700637cbSDimitry Andric           llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
377*700637cbSDimitry Andric   }
378*700637cbSDimitry Andric 
379*700637cbSDimitry Andric   S.Stk.push<Floating>(Result);
380*700637cbSDimitry Andric   return true;
381*700637cbSDimitry Andric }
382*700637cbSDimitry Andric 
interp__builtin_inf(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)383*700637cbSDimitry Andric static bool interp__builtin_inf(InterpState &S, CodePtr OpPC,
384*700637cbSDimitry Andric                                 const InterpFrame *Frame,
385*700637cbSDimitry Andric                                 const CallExpr *Call) {
386*700637cbSDimitry Andric   const llvm::fltSemantics &TargetSemantics =
387*700637cbSDimitry Andric       S.getASTContext().getFloatTypeSemantics(
388*700637cbSDimitry Andric           Call->getDirectCallee()->getReturnType());
389*700637cbSDimitry Andric 
390*700637cbSDimitry Andric   Floating Result = S.allocFloat(TargetSemantics);
391*700637cbSDimitry Andric   Result.copy(APFloat::getInf(TargetSemantics));
392*700637cbSDimitry Andric   S.Stk.push<Floating>(Result);
393*700637cbSDimitry Andric   return true;
394*700637cbSDimitry Andric }
395*700637cbSDimitry Andric 
interp__builtin_copysign(InterpState & S,CodePtr OpPC,const InterpFrame * Frame)396*700637cbSDimitry Andric static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC,
397*700637cbSDimitry Andric                                      const InterpFrame *Frame) {
398*700637cbSDimitry Andric   const Floating &Arg2 = S.Stk.pop<Floating>();
399*700637cbSDimitry Andric   const Floating &Arg1 = S.Stk.pop<Floating>();
400*700637cbSDimitry Andric   Floating Result = S.allocFloat(Arg1.getSemantics());
401*700637cbSDimitry Andric 
402*700637cbSDimitry Andric   APFloat Copy = Arg1.getAPFloat();
403*700637cbSDimitry Andric   Copy.copySign(Arg2.getAPFloat());
404*700637cbSDimitry Andric   Result.copy(Copy);
405*700637cbSDimitry Andric   S.Stk.push<Floating>(Result);
406*700637cbSDimitry Andric 
407*700637cbSDimitry Andric   return true;
408*700637cbSDimitry Andric }
409*700637cbSDimitry Andric 
interp__builtin_fmin(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,bool IsNumBuiltin)410*700637cbSDimitry Andric static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC,
411*700637cbSDimitry Andric                                  const InterpFrame *Frame, bool IsNumBuiltin) {
412*700637cbSDimitry Andric   const Floating &RHS = S.Stk.pop<Floating>();
413*700637cbSDimitry Andric   const Floating &LHS = S.Stk.pop<Floating>();
414*700637cbSDimitry Andric   Floating Result = S.allocFloat(LHS.getSemantics());
415*700637cbSDimitry Andric 
416*700637cbSDimitry Andric   if (IsNumBuiltin)
417*700637cbSDimitry Andric     Result.copy(llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()));
418*700637cbSDimitry Andric   else
419*700637cbSDimitry Andric     Result.copy(minnum(LHS.getAPFloat(), RHS.getAPFloat()));
420*700637cbSDimitry Andric   S.Stk.push<Floating>(Result);
421*700637cbSDimitry Andric   return true;
422*700637cbSDimitry Andric }
423*700637cbSDimitry Andric 
interp__builtin_fmax(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,bool IsNumBuiltin)424*700637cbSDimitry Andric static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC,
425*700637cbSDimitry Andric                                  const InterpFrame *Frame, bool IsNumBuiltin) {
426*700637cbSDimitry Andric   const Floating &RHS = S.Stk.pop<Floating>();
427*700637cbSDimitry Andric   const Floating &LHS = S.Stk.pop<Floating>();
428*700637cbSDimitry Andric   Floating Result = S.allocFloat(LHS.getSemantics());
429*700637cbSDimitry Andric 
430*700637cbSDimitry Andric   if (IsNumBuiltin)
431*700637cbSDimitry Andric     Result.copy(llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()));
432*700637cbSDimitry Andric   else
433*700637cbSDimitry Andric     Result.copy(maxnum(LHS.getAPFloat(), RHS.getAPFloat()));
434*700637cbSDimitry Andric   S.Stk.push<Floating>(Result);
435*700637cbSDimitry Andric   return true;
436*700637cbSDimitry Andric }
437*700637cbSDimitry Andric 
438*700637cbSDimitry Andric /// Defined as __builtin_isnan(...), to accommodate the fact that it can
439*700637cbSDimitry Andric /// take a float, double, long double, etc.
440*700637cbSDimitry Andric /// But for us, that's all a Floating anyway.
interp__builtin_isnan(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)441*700637cbSDimitry Andric static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC,
442*700637cbSDimitry Andric                                   const InterpFrame *Frame,
443*700637cbSDimitry Andric                                   const CallExpr *Call) {
444*700637cbSDimitry Andric   const Floating &Arg = S.Stk.pop<Floating>();
445*700637cbSDimitry Andric 
446*700637cbSDimitry Andric   pushInteger(S, Arg.isNan(), Call->getType());
447*700637cbSDimitry Andric   return true;
448*700637cbSDimitry Andric }
449*700637cbSDimitry Andric 
interp__builtin_issignaling(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)450*700637cbSDimitry Andric static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC,
451*700637cbSDimitry Andric                                         const InterpFrame *Frame,
452*700637cbSDimitry Andric                                         const CallExpr *Call) {
453*700637cbSDimitry Andric   const Floating &Arg = S.Stk.pop<Floating>();
454*700637cbSDimitry Andric 
455*700637cbSDimitry Andric   pushInteger(S, Arg.isSignaling(), Call->getType());
456*700637cbSDimitry Andric   return true;
457*700637cbSDimitry Andric }
458*700637cbSDimitry Andric 
interp__builtin_isinf(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,bool CheckSign,const CallExpr * Call)459*700637cbSDimitry Andric static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC,
460*700637cbSDimitry Andric                                   const InterpFrame *Frame, bool CheckSign,
461*700637cbSDimitry Andric                                   const CallExpr *Call) {
462*700637cbSDimitry Andric   const Floating &Arg = S.Stk.pop<Floating>();
463*700637cbSDimitry Andric   bool IsInf = Arg.isInf();
464*700637cbSDimitry Andric 
465*700637cbSDimitry Andric   if (CheckSign)
466*700637cbSDimitry Andric     pushInteger(S, IsInf ? (Arg.isNegative() ? -1 : 1) : 0, Call->getType());
467*700637cbSDimitry Andric   else
468*700637cbSDimitry Andric     pushInteger(S, Arg.isInf(), Call->getType());
469*700637cbSDimitry Andric   return true;
470*700637cbSDimitry Andric }
471*700637cbSDimitry Andric 
interp__builtin_isfinite(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)472*700637cbSDimitry Andric static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC,
473*700637cbSDimitry Andric                                      const InterpFrame *Frame,
474*700637cbSDimitry Andric                                      const CallExpr *Call) {
475*700637cbSDimitry Andric   const Floating &Arg = S.Stk.pop<Floating>();
476*700637cbSDimitry Andric 
477*700637cbSDimitry Andric   pushInteger(S, Arg.isFinite(), Call->getType());
478*700637cbSDimitry Andric   return true;
479*700637cbSDimitry Andric }
480*700637cbSDimitry Andric 
interp__builtin_isnormal(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)481*700637cbSDimitry Andric static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC,
482*700637cbSDimitry Andric                                      const InterpFrame *Frame,
483*700637cbSDimitry Andric                                      const CallExpr *Call) {
484*700637cbSDimitry Andric   const Floating &Arg = S.Stk.pop<Floating>();
485*700637cbSDimitry Andric 
486*700637cbSDimitry Andric   pushInteger(S, Arg.isNormal(), Call->getType());
487*700637cbSDimitry Andric   return true;
488*700637cbSDimitry Andric }
489*700637cbSDimitry Andric 
interp__builtin_issubnormal(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)490*700637cbSDimitry Andric static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC,
491*700637cbSDimitry Andric                                         const InterpFrame *Frame,
492*700637cbSDimitry Andric                                         const CallExpr *Call) {
493*700637cbSDimitry Andric   const Floating &Arg = S.Stk.pop<Floating>();
494*700637cbSDimitry Andric 
495*700637cbSDimitry Andric   pushInteger(S, Arg.isDenormal(), Call->getType());
496*700637cbSDimitry Andric   return true;
497*700637cbSDimitry Andric }
498*700637cbSDimitry Andric 
interp__builtin_iszero(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)499*700637cbSDimitry Andric static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC,
500*700637cbSDimitry Andric                                    const InterpFrame *Frame,
501*700637cbSDimitry Andric                                    const CallExpr *Call) {
502*700637cbSDimitry Andric   const Floating &Arg = S.Stk.pop<Floating>();
503*700637cbSDimitry Andric 
504*700637cbSDimitry Andric   pushInteger(S, Arg.isZero(), Call->getType());
505*700637cbSDimitry Andric   return true;
506*700637cbSDimitry Andric }
507*700637cbSDimitry Andric 
interp__builtin_signbit(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)508*700637cbSDimitry Andric static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC,
509*700637cbSDimitry Andric                                     const InterpFrame *Frame,
510*700637cbSDimitry Andric                                     const CallExpr *Call) {
511*700637cbSDimitry Andric   const Floating &Arg = S.Stk.pop<Floating>();
512*700637cbSDimitry Andric 
513*700637cbSDimitry Andric   pushInteger(S, Arg.isNegative(), Call->getType());
514*700637cbSDimitry Andric   return true;
515*700637cbSDimitry Andric }
516*700637cbSDimitry Andric 
interp_floating_comparison(InterpState & S,CodePtr OpPC,const CallExpr * Call,unsigned ID)517*700637cbSDimitry Andric static bool interp_floating_comparison(InterpState &S, CodePtr OpPC,
518*700637cbSDimitry Andric                                        const CallExpr *Call, unsigned ID) {
519*700637cbSDimitry Andric   const Floating &RHS = S.Stk.pop<Floating>();
520*700637cbSDimitry Andric   const Floating &LHS = S.Stk.pop<Floating>();
521*700637cbSDimitry Andric 
522*700637cbSDimitry Andric   pushInteger(
523*700637cbSDimitry Andric       S,
524*700637cbSDimitry Andric       [&] {
525*700637cbSDimitry Andric         switch (ID) {
526*700637cbSDimitry Andric         case Builtin::BI__builtin_isgreater:
527*700637cbSDimitry Andric           return LHS > RHS;
528*700637cbSDimitry Andric         case Builtin::BI__builtin_isgreaterequal:
529*700637cbSDimitry Andric           return LHS >= RHS;
530*700637cbSDimitry Andric         case Builtin::BI__builtin_isless:
531*700637cbSDimitry Andric           return LHS < RHS;
532*700637cbSDimitry Andric         case Builtin::BI__builtin_islessequal:
533*700637cbSDimitry Andric           return LHS <= RHS;
534*700637cbSDimitry Andric         case Builtin::BI__builtin_islessgreater: {
535*700637cbSDimitry Andric           ComparisonCategoryResult cmp = LHS.compare(RHS);
536*700637cbSDimitry Andric           return cmp == ComparisonCategoryResult::Less ||
537*700637cbSDimitry Andric                  cmp == ComparisonCategoryResult::Greater;
538*700637cbSDimitry Andric         }
539*700637cbSDimitry Andric         case Builtin::BI__builtin_isunordered:
540*700637cbSDimitry Andric           return LHS.compare(RHS) == ComparisonCategoryResult::Unordered;
541*700637cbSDimitry Andric         default:
542*700637cbSDimitry Andric           llvm_unreachable("Unexpected builtin ID: Should be a floating point "
543*700637cbSDimitry Andric                            "comparison function");
544*700637cbSDimitry Andric         }
545*700637cbSDimitry Andric       }(),
546*700637cbSDimitry Andric       Call->getType());
547*700637cbSDimitry Andric   return true;
548*700637cbSDimitry Andric }
549*700637cbSDimitry Andric 
550*700637cbSDimitry Andric /// First parameter to __builtin_isfpclass is the floating value, the
551*700637cbSDimitry Andric /// second one is an integral value.
interp__builtin_isfpclass(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)552*700637cbSDimitry Andric static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,
553*700637cbSDimitry Andric                                       const InterpFrame *Frame,
554*700637cbSDimitry Andric                                       const CallExpr *Call) {
555*700637cbSDimitry Andric   PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType());
556*700637cbSDimitry Andric   APSInt FPClassArg = popToAPSInt(S.Stk, FPClassArgT);
557*700637cbSDimitry Andric   const Floating &F = S.Stk.pop<Floating>();
558*700637cbSDimitry Andric 
559*700637cbSDimitry Andric   int32_t Result = static_cast<int32_t>(
560*700637cbSDimitry Andric       (F.classify() & std::move(FPClassArg)).getZExtValue());
561*700637cbSDimitry Andric   pushInteger(S, Result, Call->getType());
562*700637cbSDimitry Andric 
563*700637cbSDimitry Andric   return true;
564*700637cbSDimitry Andric }
565*700637cbSDimitry Andric 
566*700637cbSDimitry Andric /// Five int values followed by one floating value.
567*700637cbSDimitry Andric /// __builtin_fpclassify(int, int, int, int, int, float)
interp__builtin_fpclassify(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)568*700637cbSDimitry Andric static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
569*700637cbSDimitry Andric                                        const InterpFrame *Frame,
570*700637cbSDimitry Andric                                        const CallExpr *Call) {
571*700637cbSDimitry Andric   const Floating &Val = S.Stk.pop<Floating>();
572*700637cbSDimitry Andric 
573*700637cbSDimitry Andric   PrimType IntT = *S.getContext().classify(Call->getArg(0));
574*700637cbSDimitry Andric   APSInt Values[5];
575*700637cbSDimitry Andric   for (unsigned I = 0; I != 5; ++I)
576*700637cbSDimitry Andric     Values[4 - I] = popToAPSInt(S.Stk, IntT);
577*700637cbSDimitry Andric 
578*700637cbSDimitry Andric   unsigned Index;
579*700637cbSDimitry Andric   switch (Val.getCategory()) {
580*700637cbSDimitry Andric   case APFloat::fcNaN:
581*700637cbSDimitry Andric     Index = 0;
582*700637cbSDimitry Andric     break;
583*700637cbSDimitry Andric   case APFloat::fcInfinity:
584*700637cbSDimitry Andric     Index = 1;
585*700637cbSDimitry Andric     break;
586*700637cbSDimitry Andric   case APFloat::fcNormal:
587*700637cbSDimitry Andric     Index = Val.isDenormal() ? 3 : 2;
588*700637cbSDimitry Andric     break;
589*700637cbSDimitry Andric   case APFloat::fcZero:
590*700637cbSDimitry Andric     Index = 4;
591*700637cbSDimitry Andric     break;
592*700637cbSDimitry Andric   }
593*700637cbSDimitry Andric 
594*700637cbSDimitry Andric   // The last argument is first on the stack.
595*700637cbSDimitry Andric   assert(Index <= 4);
596*700637cbSDimitry Andric 
597*700637cbSDimitry Andric   pushInteger(S, Values[Index], Call->getType());
598*700637cbSDimitry Andric   return true;
599*700637cbSDimitry Andric }
600*700637cbSDimitry Andric 
601*700637cbSDimitry Andric // The C standard says "fabs raises no floating-point exceptions,
602*700637cbSDimitry Andric // even if x is a signaling NaN. The returned value is independent of
603*700637cbSDimitry Andric // the current rounding direction mode."  Therefore constant folding can
604*700637cbSDimitry Andric // proceed without regard to the floating point settings.
605*700637cbSDimitry Andric // Reference, WG14 N2478 F.10.4.3
interp__builtin_fabs(InterpState & S,CodePtr OpPC,const InterpFrame * Frame)606*700637cbSDimitry Andric static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,
607*700637cbSDimitry Andric                                  const InterpFrame *Frame) {
608*700637cbSDimitry Andric   const Floating &Val = S.Stk.pop<Floating>();
609*700637cbSDimitry Andric   APFloat F = Val.getAPFloat();
610*700637cbSDimitry Andric   if (!F.isNegative()) {
611*700637cbSDimitry Andric     S.Stk.push<Floating>(Val);
612*700637cbSDimitry Andric     return true;
613*700637cbSDimitry Andric   }
614*700637cbSDimitry Andric 
615*700637cbSDimitry Andric   Floating Result = S.allocFloat(Val.getSemantics());
616*700637cbSDimitry Andric   F.changeSign();
617*700637cbSDimitry Andric   Result.copy(F);
618*700637cbSDimitry Andric   S.Stk.push<Floating>(Result);
619*700637cbSDimitry Andric   return true;
620*700637cbSDimitry Andric }
621*700637cbSDimitry Andric 
interp__builtin_abs(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)622*700637cbSDimitry Andric static bool interp__builtin_abs(InterpState &S, CodePtr OpPC,
623*700637cbSDimitry Andric                                 const InterpFrame *Frame,
624*700637cbSDimitry Andric                                 const CallExpr *Call) {
625*700637cbSDimitry Andric   PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
626*700637cbSDimitry Andric   APSInt Val = popToAPSInt(S.Stk, ArgT);
627*700637cbSDimitry Andric   if (Val ==
628*700637cbSDimitry Andric       APSInt(APInt::getSignedMinValue(Val.getBitWidth()), /*IsUnsigned=*/false))
629*700637cbSDimitry Andric     return false;
630*700637cbSDimitry Andric   if (Val.isNegative())
631*700637cbSDimitry Andric     Val.negate();
632*700637cbSDimitry Andric   pushInteger(S, Val, Call->getType());
633*700637cbSDimitry Andric   return true;
634*700637cbSDimitry Andric }
635*700637cbSDimitry Andric 
interp__builtin_popcount(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)636*700637cbSDimitry Andric static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,
637*700637cbSDimitry Andric                                      const InterpFrame *Frame,
638*700637cbSDimitry Andric                                      const CallExpr *Call) {
639*700637cbSDimitry Andric   PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
640*700637cbSDimitry Andric   APSInt Val = popToAPSInt(S.Stk, ArgT);
641*700637cbSDimitry Andric   pushInteger(S, Val.popcount(), Call->getType());
642*700637cbSDimitry Andric   return true;
643*700637cbSDimitry Andric }
644*700637cbSDimitry Andric 
interp__builtin_parity(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)645*700637cbSDimitry Andric static bool interp__builtin_parity(InterpState &S, CodePtr OpPC,
646*700637cbSDimitry Andric                                    const InterpFrame *Frame,
647*700637cbSDimitry Andric                                    const CallExpr *Call) {
648*700637cbSDimitry Andric   PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
649*700637cbSDimitry Andric   APSInt Val = popToAPSInt(S.Stk, ArgT);
650*700637cbSDimitry Andric   pushInteger(S, Val.popcount() % 2, Call->getType());
651*700637cbSDimitry Andric   return true;
652*700637cbSDimitry Andric }
653*700637cbSDimitry Andric 
interp__builtin_clrsb(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)654*700637cbSDimitry Andric static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC,
655*700637cbSDimitry Andric                                   const InterpFrame *Frame,
656*700637cbSDimitry Andric                                   const CallExpr *Call) {
657*700637cbSDimitry Andric   PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
658*700637cbSDimitry Andric   APSInt Val = popToAPSInt(S.Stk, ArgT);
659*700637cbSDimitry Andric   pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType());
660*700637cbSDimitry Andric   return true;
661*700637cbSDimitry Andric }
662*700637cbSDimitry Andric 
interp__builtin_bitreverse(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)663*700637cbSDimitry Andric static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC,
664*700637cbSDimitry Andric                                        const InterpFrame *Frame,
665*700637cbSDimitry Andric                                        const CallExpr *Call) {
666*700637cbSDimitry Andric   PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
667*700637cbSDimitry Andric   APSInt Val = popToAPSInt(S.Stk, ArgT);
668*700637cbSDimitry Andric   pushInteger(S, Val.reverseBits(), Call->getType());
669*700637cbSDimitry Andric   return true;
670*700637cbSDimitry Andric }
671*700637cbSDimitry Andric 
interp__builtin_classify_type(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)672*700637cbSDimitry Andric static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC,
673*700637cbSDimitry Andric                                           const InterpFrame *Frame,
674*700637cbSDimitry Andric                                           const CallExpr *Call) {
675*700637cbSDimitry Andric   // This is an unevaluated call, so there are no arguments on the stack.
676*700637cbSDimitry Andric   assert(Call->getNumArgs() == 1);
677*700637cbSDimitry Andric   const Expr *Arg = Call->getArg(0);
678*700637cbSDimitry Andric 
679*700637cbSDimitry Andric   GCCTypeClass ResultClass =
680*700637cbSDimitry Andric       EvaluateBuiltinClassifyType(Arg->getType(), S.getLangOpts());
681*700637cbSDimitry Andric   int32_t ReturnVal = static_cast<int32_t>(ResultClass);
682*700637cbSDimitry Andric   pushInteger(S, ReturnVal, Call->getType());
683*700637cbSDimitry Andric   return true;
684*700637cbSDimitry Andric }
685*700637cbSDimitry Andric 
686*700637cbSDimitry Andric // __builtin_expect(long, long)
687*700637cbSDimitry Andric // __builtin_expect_with_probability(long, long, double)
interp__builtin_expect(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)688*700637cbSDimitry Andric static bool interp__builtin_expect(InterpState &S, CodePtr OpPC,
689*700637cbSDimitry Andric                                    const InterpFrame *Frame,
690*700637cbSDimitry Andric                                    const CallExpr *Call) {
691*700637cbSDimitry Andric   // The return value is simply the value of the first parameter.
692*700637cbSDimitry Andric   // We ignore the probability.
693*700637cbSDimitry Andric   unsigned NumArgs = Call->getNumArgs();
694*700637cbSDimitry Andric   assert(NumArgs == 2 || NumArgs == 3);
695*700637cbSDimitry Andric 
696*700637cbSDimitry Andric   PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
697*700637cbSDimitry Andric   if (NumArgs == 3)
698*700637cbSDimitry Andric     S.Stk.discard<Floating>();
699*700637cbSDimitry Andric   discard(S.Stk, ArgT);
700*700637cbSDimitry Andric 
701*700637cbSDimitry Andric   APSInt Val = popToAPSInt(S.Stk, ArgT);
702*700637cbSDimitry Andric   pushInteger(S, Val, Call->getType());
703*700637cbSDimitry Andric   return true;
704*700637cbSDimitry Andric }
705*700637cbSDimitry Andric 
706*700637cbSDimitry Andric /// rotateleft(value, amount)
interp__builtin_rotate(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,bool Right)707*700637cbSDimitry Andric static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC,
708*700637cbSDimitry Andric                                    const InterpFrame *Frame,
709*700637cbSDimitry Andric                                    const CallExpr *Call, bool Right) {
710*700637cbSDimitry Andric   PrimType AmountT = *S.getContext().classify(Call->getArg(1)->getType());
711*700637cbSDimitry Andric   PrimType ValueT = *S.getContext().classify(Call->getArg(0)->getType());
712*700637cbSDimitry Andric 
713*700637cbSDimitry Andric   APSInt Amount = popToAPSInt(S.Stk, AmountT);
714*700637cbSDimitry Andric   APSInt Value = popToAPSInt(S.Stk, ValueT);
715*700637cbSDimitry Andric 
716*700637cbSDimitry Andric   APSInt Result;
717*700637cbSDimitry Andric   if (Right)
718*700637cbSDimitry Andric     Result = APSInt(Value.rotr(Amount.urem(Value.getBitWidth())),
719*700637cbSDimitry Andric                     /*IsUnsigned=*/true);
720*700637cbSDimitry Andric   else // Left.
721*700637cbSDimitry Andric     Result = APSInt(Value.rotl(Amount.urem(Value.getBitWidth())),
722*700637cbSDimitry Andric                     /*IsUnsigned=*/true);
723*700637cbSDimitry Andric 
724*700637cbSDimitry Andric   pushInteger(S, Result, Call->getType());
725*700637cbSDimitry Andric   return true;
726*700637cbSDimitry Andric }
727*700637cbSDimitry Andric 
interp__builtin_ffs(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)728*700637cbSDimitry Andric static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC,
729*700637cbSDimitry Andric                                 const InterpFrame *Frame,
730*700637cbSDimitry Andric                                 const CallExpr *Call) {
731*700637cbSDimitry Andric   PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
732*700637cbSDimitry Andric   APSInt Value = popToAPSInt(S.Stk, ArgT);
733*700637cbSDimitry Andric 
734*700637cbSDimitry Andric   uint64_t N = Value.countr_zero();
735*700637cbSDimitry Andric   pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType());
736*700637cbSDimitry Andric   return true;
737*700637cbSDimitry Andric }
738*700637cbSDimitry Andric 
interp__builtin_addressof(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)739*700637cbSDimitry Andric static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC,
740*700637cbSDimitry Andric                                       const InterpFrame *Frame,
741*700637cbSDimitry Andric                                       const CallExpr *Call) {
742*700637cbSDimitry Andric #ifndef NDEBUG
743*700637cbSDimitry Andric   assert(Call->getArg(0)->isLValue());
744*700637cbSDimitry Andric   PrimType PtrT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr);
745*700637cbSDimitry Andric   assert(PtrT == PT_Ptr &&
746*700637cbSDimitry Andric          "Unsupported pointer type passed to __builtin_addressof()");
747*700637cbSDimitry Andric #endif
748*700637cbSDimitry Andric   return true;
749*700637cbSDimitry Andric }
750*700637cbSDimitry Andric 
interp__builtin_move(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)751*700637cbSDimitry Andric static bool interp__builtin_move(InterpState &S, CodePtr OpPC,
752*700637cbSDimitry Andric                                  const InterpFrame *Frame,
753*700637cbSDimitry Andric                                  const CallExpr *Call) {
754*700637cbSDimitry Andric   return Call->getDirectCallee()->isConstexpr();
755*700637cbSDimitry Andric }
756*700637cbSDimitry Andric 
interp__builtin_eh_return_data_regno(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)757*700637cbSDimitry Andric static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC,
758*700637cbSDimitry Andric                                                  const InterpFrame *Frame,
759*700637cbSDimitry Andric                                                  const CallExpr *Call) {
760*700637cbSDimitry Andric   PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
761*700637cbSDimitry Andric   APSInt Arg = popToAPSInt(S.Stk, ArgT);
762*700637cbSDimitry Andric 
763*700637cbSDimitry Andric   int Result = S.getASTContext().getTargetInfo().getEHDataRegisterNumber(
764*700637cbSDimitry Andric       Arg.getZExtValue());
765*700637cbSDimitry Andric   pushInteger(S, Result, Call->getType());
766*700637cbSDimitry Andric   return true;
767*700637cbSDimitry Andric }
768*700637cbSDimitry Andric 
769*700637cbSDimitry Andric // Two integral values followed by a pointer (lhs, rhs, resultOut)
interp__builtin_overflowop(InterpState & S,CodePtr OpPC,const CallExpr * Call,unsigned BuiltinOp)770*700637cbSDimitry Andric static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC,
771*700637cbSDimitry Andric                                        const CallExpr *Call,
772*700637cbSDimitry Andric                                        unsigned BuiltinOp) {
773*700637cbSDimitry Andric   const Pointer &ResultPtr = S.Stk.pop<Pointer>();
774*700637cbSDimitry Andric   if (ResultPtr.isDummy())
775*700637cbSDimitry Andric     return false;
776*700637cbSDimitry Andric 
777*700637cbSDimitry Andric   PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
778*700637cbSDimitry Andric   PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());
779*700637cbSDimitry Andric   APSInt RHS = popToAPSInt(S.Stk, RHST);
780*700637cbSDimitry Andric   APSInt LHS = popToAPSInt(S.Stk, LHST);
781*700637cbSDimitry Andric   QualType ResultType = Call->getArg(2)->getType()->getPointeeType();
782*700637cbSDimitry Andric   PrimType ResultT = *S.getContext().classify(ResultType);
783*700637cbSDimitry Andric   bool Overflow;
784*700637cbSDimitry Andric 
785*700637cbSDimitry Andric   APSInt Result;
786*700637cbSDimitry Andric   if (BuiltinOp == Builtin::BI__builtin_add_overflow ||
787*700637cbSDimitry Andric       BuiltinOp == Builtin::BI__builtin_sub_overflow ||
788*700637cbSDimitry Andric       BuiltinOp == Builtin::BI__builtin_mul_overflow) {
789*700637cbSDimitry Andric     bool IsSigned = LHS.isSigned() || RHS.isSigned() ||
790*700637cbSDimitry Andric                     ResultType->isSignedIntegerOrEnumerationType();
791*700637cbSDimitry Andric     bool AllSigned = LHS.isSigned() && RHS.isSigned() &&
792*700637cbSDimitry Andric                      ResultType->isSignedIntegerOrEnumerationType();
793*700637cbSDimitry Andric     uint64_t LHSSize = LHS.getBitWidth();
794*700637cbSDimitry Andric     uint64_t RHSSize = RHS.getBitWidth();
795*700637cbSDimitry Andric     uint64_t ResultSize = S.getASTContext().getTypeSize(ResultType);
796*700637cbSDimitry Andric     uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize);
797*700637cbSDimitry Andric 
798*700637cbSDimitry Andric     // Add an additional bit if the signedness isn't uniformly agreed to. We
799*700637cbSDimitry Andric     // could do this ONLY if there is a signed and an unsigned that both have
800*700637cbSDimitry Andric     // MaxBits, but the code to check that is pretty nasty.  The issue will be
801*700637cbSDimitry Andric     // caught in the shrink-to-result later anyway.
802*700637cbSDimitry Andric     if (IsSigned && !AllSigned)
803*700637cbSDimitry Andric       ++MaxBits;
804*700637cbSDimitry Andric 
805*700637cbSDimitry Andric     LHS = APSInt(LHS.extOrTrunc(MaxBits), !IsSigned);
806*700637cbSDimitry Andric     RHS = APSInt(RHS.extOrTrunc(MaxBits), !IsSigned);
807*700637cbSDimitry Andric     Result = APSInt(MaxBits, !IsSigned);
808*700637cbSDimitry Andric   }
809*700637cbSDimitry Andric 
810*700637cbSDimitry Andric   // Find largest int.
811*700637cbSDimitry Andric   switch (BuiltinOp) {
812*700637cbSDimitry Andric   default:
813*700637cbSDimitry Andric     llvm_unreachable("Invalid value for BuiltinOp");
814*700637cbSDimitry Andric   case Builtin::BI__builtin_add_overflow:
815*700637cbSDimitry Andric   case Builtin::BI__builtin_sadd_overflow:
816*700637cbSDimitry Andric   case Builtin::BI__builtin_saddl_overflow:
817*700637cbSDimitry Andric   case Builtin::BI__builtin_saddll_overflow:
818*700637cbSDimitry Andric   case Builtin::BI__builtin_uadd_overflow:
819*700637cbSDimitry Andric   case Builtin::BI__builtin_uaddl_overflow:
820*700637cbSDimitry Andric   case Builtin::BI__builtin_uaddll_overflow:
821*700637cbSDimitry Andric     Result = LHS.isSigned() ? LHS.sadd_ov(RHS, Overflow)
822*700637cbSDimitry Andric                             : LHS.uadd_ov(RHS, Overflow);
823*700637cbSDimitry Andric     break;
824*700637cbSDimitry Andric   case Builtin::BI__builtin_sub_overflow:
825*700637cbSDimitry Andric   case Builtin::BI__builtin_ssub_overflow:
826*700637cbSDimitry Andric   case Builtin::BI__builtin_ssubl_overflow:
827*700637cbSDimitry Andric   case Builtin::BI__builtin_ssubll_overflow:
828*700637cbSDimitry Andric   case Builtin::BI__builtin_usub_overflow:
829*700637cbSDimitry Andric   case Builtin::BI__builtin_usubl_overflow:
830*700637cbSDimitry Andric   case Builtin::BI__builtin_usubll_overflow:
831*700637cbSDimitry Andric     Result = LHS.isSigned() ? LHS.ssub_ov(RHS, Overflow)
832*700637cbSDimitry Andric                             : LHS.usub_ov(RHS, Overflow);
833*700637cbSDimitry Andric     break;
834*700637cbSDimitry Andric   case Builtin::BI__builtin_mul_overflow:
835*700637cbSDimitry Andric   case Builtin::BI__builtin_smul_overflow:
836*700637cbSDimitry Andric   case Builtin::BI__builtin_smull_overflow:
837*700637cbSDimitry Andric   case Builtin::BI__builtin_smulll_overflow:
838*700637cbSDimitry Andric   case Builtin::BI__builtin_umul_overflow:
839*700637cbSDimitry Andric   case Builtin::BI__builtin_umull_overflow:
840*700637cbSDimitry Andric   case Builtin::BI__builtin_umulll_overflow:
841*700637cbSDimitry Andric     Result = LHS.isSigned() ? LHS.smul_ov(RHS, Overflow)
842*700637cbSDimitry Andric                             : LHS.umul_ov(RHS, Overflow);
843*700637cbSDimitry Andric     break;
844*700637cbSDimitry Andric   }
845*700637cbSDimitry Andric 
846*700637cbSDimitry Andric   // In the case where multiple sizes are allowed, truncate and see if
847*700637cbSDimitry Andric   // the values are the same.
848*700637cbSDimitry Andric   if (BuiltinOp == Builtin::BI__builtin_add_overflow ||
849*700637cbSDimitry Andric       BuiltinOp == Builtin::BI__builtin_sub_overflow ||
850*700637cbSDimitry Andric       BuiltinOp == Builtin::BI__builtin_mul_overflow) {
851*700637cbSDimitry Andric     // APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead,
852*700637cbSDimitry Andric     // since it will give us the behavior of a TruncOrSelf in the case where
853*700637cbSDimitry Andric     // its parameter <= its size.  We previously set Result to be at least the
854*700637cbSDimitry Andric     // type-size of the result, so getTypeSize(ResultType) <= Resu
855*700637cbSDimitry Andric     APSInt Temp = Result.extOrTrunc(S.getASTContext().getTypeSize(ResultType));
856*700637cbSDimitry Andric     Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType());
857*700637cbSDimitry Andric 
858*700637cbSDimitry Andric     if (!APSInt::isSameValue(Temp, Result))
859*700637cbSDimitry Andric       Overflow = true;
860*700637cbSDimitry Andric     Result = std::move(Temp);
861*700637cbSDimitry Andric   }
862*700637cbSDimitry Andric 
863*700637cbSDimitry Andric   // Write Result to ResultPtr and put Overflow on the stack.
864*700637cbSDimitry Andric   assignInteger(S, ResultPtr, ResultT, Result);
865*700637cbSDimitry Andric   if (ResultPtr.canBeInitialized())
866*700637cbSDimitry Andric     ResultPtr.initialize();
867*700637cbSDimitry Andric 
868*700637cbSDimitry Andric   assert(Call->getDirectCallee()->getReturnType()->isBooleanType());
869*700637cbSDimitry Andric   S.Stk.push<Boolean>(Overflow);
870*700637cbSDimitry Andric   return true;
871*700637cbSDimitry Andric }
872*700637cbSDimitry Andric 
873*700637cbSDimitry Andric /// Three integral values followed by a pointer (lhs, rhs, carry, carryOut).
interp__builtin_carryop(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,unsigned BuiltinOp)874*700637cbSDimitry Andric static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,
875*700637cbSDimitry Andric                                     const InterpFrame *Frame,
876*700637cbSDimitry Andric                                     const CallExpr *Call, unsigned BuiltinOp) {
877*700637cbSDimitry Andric   const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();
878*700637cbSDimitry Andric   PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());
879*700637cbSDimitry Andric   PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
880*700637cbSDimitry Andric   APSInt CarryIn = popToAPSInt(S.Stk, LHST);
881*700637cbSDimitry Andric   APSInt RHS = popToAPSInt(S.Stk, RHST);
882*700637cbSDimitry Andric   APSInt LHS = popToAPSInt(S.Stk, LHST);
883*700637cbSDimitry Andric 
884*700637cbSDimitry Andric   APSInt CarryOut;
885*700637cbSDimitry Andric 
886*700637cbSDimitry Andric   APSInt Result;
887*700637cbSDimitry Andric   // Copy the number of bits and sign.
888*700637cbSDimitry Andric   Result = LHS;
889*700637cbSDimitry Andric   CarryOut = LHS;
890*700637cbSDimitry Andric 
891*700637cbSDimitry Andric   bool FirstOverflowed = false;
892*700637cbSDimitry Andric   bool SecondOverflowed = false;
893*700637cbSDimitry Andric   switch (BuiltinOp) {
894*700637cbSDimitry Andric   default:
895*700637cbSDimitry Andric     llvm_unreachable("Invalid value for BuiltinOp");
896*700637cbSDimitry Andric   case Builtin::BI__builtin_addcb:
897*700637cbSDimitry Andric   case Builtin::BI__builtin_addcs:
898*700637cbSDimitry Andric   case Builtin::BI__builtin_addc:
899*700637cbSDimitry Andric   case Builtin::BI__builtin_addcl:
900*700637cbSDimitry Andric   case Builtin::BI__builtin_addcll:
901*700637cbSDimitry Andric     Result =
902*700637cbSDimitry Andric         LHS.uadd_ov(RHS, FirstOverflowed).uadd_ov(CarryIn, SecondOverflowed);
903*700637cbSDimitry Andric     break;
904*700637cbSDimitry Andric   case Builtin::BI__builtin_subcb:
905*700637cbSDimitry Andric   case Builtin::BI__builtin_subcs:
906*700637cbSDimitry Andric   case Builtin::BI__builtin_subc:
907*700637cbSDimitry Andric   case Builtin::BI__builtin_subcl:
908*700637cbSDimitry Andric   case Builtin::BI__builtin_subcll:
909*700637cbSDimitry Andric     Result =
910*700637cbSDimitry Andric         LHS.usub_ov(RHS, FirstOverflowed).usub_ov(CarryIn, SecondOverflowed);
911*700637cbSDimitry Andric     break;
912*700637cbSDimitry Andric   }
913*700637cbSDimitry Andric   // It is possible for both overflows to happen but CGBuiltin uses an OR so
914*700637cbSDimitry Andric   // this is consistent.
915*700637cbSDimitry Andric   CarryOut = (uint64_t)(FirstOverflowed | SecondOverflowed);
916*700637cbSDimitry Andric 
917*700637cbSDimitry Andric   QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
918*700637cbSDimitry Andric   PrimType CarryOutT = *S.getContext().classify(CarryOutType);
919*700637cbSDimitry Andric   assignInteger(S, CarryOutPtr, CarryOutT, CarryOut);
920*700637cbSDimitry Andric   CarryOutPtr.initialize();
921*700637cbSDimitry Andric 
922*700637cbSDimitry Andric   assert(Call->getType() == Call->getArg(0)->getType());
923*700637cbSDimitry Andric   pushInteger(S, Result, Call->getType());
924*700637cbSDimitry Andric   return true;
925*700637cbSDimitry Andric }
926*700637cbSDimitry Andric 
interp__builtin_clz(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,unsigned BuiltinOp)927*700637cbSDimitry Andric static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,
928*700637cbSDimitry Andric                                 const InterpFrame *Frame, const CallExpr *Call,
929*700637cbSDimitry Andric                                 unsigned BuiltinOp) {
930*700637cbSDimitry Andric 
931*700637cbSDimitry Andric   std::optional<APSInt> Fallback;
932*700637cbSDimitry Andric   if (BuiltinOp == Builtin::BI__builtin_clzg && Call->getNumArgs() == 2) {
933*700637cbSDimitry Andric     PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
934*700637cbSDimitry Andric     Fallback = popToAPSInt(S.Stk, FallbackT);
935*700637cbSDimitry Andric   }
936*700637cbSDimitry Andric   PrimType ValT = *S.getContext().classify(Call->getArg(0));
937*700637cbSDimitry Andric   const APSInt &Val = popToAPSInt(S.Stk, ValT);
938*700637cbSDimitry Andric 
939*700637cbSDimitry Andric   // When the argument is 0, the result of GCC builtins is undefined, whereas
940*700637cbSDimitry Andric   // for Microsoft intrinsics, the result is the bit-width of the argument.
941*700637cbSDimitry Andric   bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&
942*700637cbSDimitry Andric                          BuiltinOp != Builtin::BI__lzcnt &&
943*700637cbSDimitry Andric                          BuiltinOp != Builtin::BI__lzcnt64;
944*700637cbSDimitry Andric 
945*700637cbSDimitry Andric   if (Val == 0) {
946*700637cbSDimitry Andric     if (Fallback) {
947*700637cbSDimitry Andric       pushInteger(S, *Fallback, Call->getType());
948*700637cbSDimitry Andric       return true;
949*700637cbSDimitry Andric     }
950*700637cbSDimitry Andric 
951*700637cbSDimitry Andric     if (ZeroIsUndefined)
952*700637cbSDimitry Andric       return false;
953*700637cbSDimitry Andric   }
954*700637cbSDimitry Andric 
955*700637cbSDimitry Andric   pushInteger(S, Val.countl_zero(), Call->getType());
956*700637cbSDimitry Andric   return true;
957*700637cbSDimitry Andric }
958*700637cbSDimitry Andric 
interp__builtin_ctz(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,unsigned BuiltinID)959*700637cbSDimitry Andric static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC,
960*700637cbSDimitry Andric                                 const InterpFrame *Frame, const CallExpr *Call,
961*700637cbSDimitry Andric                                 unsigned BuiltinID) {
962*700637cbSDimitry Andric   std::optional<APSInt> Fallback;
963*700637cbSDimitry Andric   if (BuiltinID == Builtin::BI__builtin_ctzg && Call->getNumArgs() == 2) {
964*700637cbSDimitry Andric     PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
965*700637cbSDimitry Andric     Fallback = popToAPSInt(S.Stk, FallbackT);
966*700637cbSDimitry Andric   }
967*700637cbSDimitry Andric   PrimType ValT = *S.getContext().classify(Call->getArg(0));
968*700637cbSDimitry Andric   const APSInt &Val = popToAPSInt(S.Stk, ValT);
969*700637cbSDimitry Andric 
970*700637cbSDimitry Andric   if (Val == 0) {
971*700637cbSDimitry Andric     if (Fallback) {
972*700637cbSDimitry Andric       pushInteger(S, *Fallback, Call->getType());
973*700637cbSDimitry Andric       return true;
974*700637cbSDimitry Andric     }
975*700637cbSDimitry Andric     return false;
976*700637cbSDimitry Andric   }
977*700637cbSDimitry Andric 
978*700637cbSDimitry Andric   pushInteger(S, Val.countr_zero(), Call->getType());
979*700637cbSDimitry Andric   return true;
980*700637cbSDimitry Andric }
981*700637cbSDimitry Andric 
interp__builtin_bswap(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)982*700637cbSDimitry Andric static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC,
983*700637cbSDimitry Andric                                   const InterpFrame *Frame,
984*700637cbSDimitry Andric                                   const CallExpr *Call) {
985*700637cbSDimitry Andric   PrimType ReturnT = *S.getContext().classify(Call->getType());
986*700637cbSDimitry Andric   PrimType ValT = *S.getContext().classify(Call->getArg(0));
987*700637cbSDimitry Andric   const APSInt &Val = popToAPSInt(S.Stk, ValT);
988*700637cbSDimitry Andric   assert(Val.getActiveBits() <= 64);
989*700637cbSDimitry Andric 
990*700637cbSDimitry Andric   INT_TYPE_SWITCH(ReturnT,
991*700637cbSDimitry Andric                   { S.Stk.push<T>(T::from(Val.byteSwap().getZExtValue())); });
992*700637cbSDimitry Andric   return true;
993*700637cbSDimitry Andric }
994*700637cbSDimitry Andric 
995*700637cbSDimitry Andric /// bool __atomic_always_lock_free(size_t, void const volatile*)
996*700637cbSDimitry Andric /// bool __atomic_is_lock_free(size_t, void const volatile*)
interp__builtin_atomic_lock_free(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,unsigned BuiltinOp)997*700637cbSDimitry Andric static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,
998*700637cbSDimitry Andric                                              const InterpFrame *Frame,
999*700637cbSDimitry Andric                                              const CallExpr *Call,
1000*700637cbSDimitry Andric                                              unsigned BuiltinOp) {
1001*700637cbSDimitry Andric   auto returnBool = [&S](bool Value) -> bool {
1002*700637cbSDimitry Andric     S.Stk.push<Boolean>(Value);
1003*700637cbSDimitry Andric     return true;
1004*700637cbSDimitry Andric   };
1005*700637cbSDimitry Andric 
1006*700637cbSDimitry Andric   PrimType ValT = *S.getContext().classify(Call->getArg(0));
1007*700637cbSDimitry Andric   const Pointer &Ptr = S.Stk.pop<Pointer>();
1008*700637cbSDimitry Andric   const APSInt &SizeVal = popToAPSInt(S.Stk, ValT);
1009*700637cbSDimitry Andric 
1010*700637cbSDimitry Andric   // For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power
1011*700637cbSDimitry Andric   // of two less than or equal to the maximum inline atomic width, we know it
1012*700637cbSDimitry Andric   // is lock-free.  If the size isn't a power of two, or greater than the
1013*700637cbSDimitry Andric   // maximum alignment where we promote atomics, we know it is not lock-free
1014*700637cbSDimitry Andric   // (at least not in the sense of atomic_is_lock_free).  Otherwise,
1015*700637cbSDimitry Andric   // the answer can only be determined at runtime; for example, 16-byte
1016*700637cbSDimitry Andric   // atomics have lock-free implementations on some, but not all,
1017*700637cbSDimitry Andric   // x86-64 processors.
1018*700637cbSDimitry Andric 
1019*700637cbSDimitry Andric   // Check power-of-two.
1020*700637cbSDimitry Andric   CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());
1021*700637cbSDimitry Andric   if (Size.isPowerOfTwo()) {
1022*700637cbSDimitry Andric     // Check against inlining width.
1023*700637cbSDimitry Andric     unsigned InlineWidthBits =
1024*700637cbSDimitry Andric         S.getASTContext().getTargetInfo().getMaxAtomicInlineWidth();
1025*700637cbSDimitry Andric     if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits)) {
1026*700637cbSDimitry Andric 
1027*700637cbSDimitry Andric       // OK, we will inline appropriately-aligned operations of this size,
1028*700637cbSDimitry Andric       // and _Atomic(T) is appropriately-aligned.
1029*700637cbSDimitry Andric       if (Size == CharUnits::One())
1030*700637cbSDimitry Andric         return returnBool(true);
1031*700637cbSDimitry Andric 
1032*700637cbSDimitry Andric       // Same for null pointers.
1033*700637cbSDimitry Andric       assert(BuiltinOp != Builtin::BI__c11_atomic_is_lock_free);
1034*700637cbSDimitry Andric       if (Ptr.isZero())
1035*700637cbSDimitry Andric         return returnBool(true);
1036*700637cbSDimitry Andric 
1037*700637cbSDimitry Andric       if (Ptr.isIntegralPointer()) {
1038*700637cbSDimitry Andric         uint64_t IntVal = Ptr.getIntegerRepresentation();
1039*700637cbSDimitry Andric         if (APSInt(APInt(64, IntVal, false), true).isAligned(Size.getAsAlign()))
1040*700637cbSDimitry Andric           return returnBool(true);
1041*700637cbSDimitry Andric       }
1042*700637cbSDimitry Andric 
1043*700637cbSDimitry Andric       const Expr *PtrArg = Call->getArg(1);
1044*700637cbSDimitry Andric       // Otherwise, check if the type's alignment against Size.
1045*700637cbSDimitry Andric       if (const auto *ICE = dyn_cast<ImplicitCastExpr>(PtrArg)) {
1046*700637cbSDimitry Andric         // Drop the potential implicit-cast to 'const volatile void*', getting
1047*700637cbSDimitry Andric         // the underlying type.
1048*700637cbSDimitry Andric         if (ICE->getCastKind() == CK_BitCast)
1049*700637cbSDimitry Andric           PtrArg = ICE->getSubExpr();
1050*700637cbSDimitry Andric       }
1051*700637cbSDimitry Andric 
1052*700637cbSDimitry Andric       if (auto PtrTy = PtrArg->getType()->getAs<PointerType>()) {
1053*700637cbSDimitry Andric         QualType PointeeType = PtrTy->getPointeeType();
1054*700637cbSDimitry Andric         if (!PointeeType->isIncompleteType() &&
1055*700637cbSDimitry Andric             S.getASTContext().getTypeAlignInChars(PointeeType) >= Size) {
1056*700637cbSDimitry Andric           // OK, we will inline operations on this object.
1057*700637cbSDimitry Andric           return returnBool(true);
1058*700637cbSDimitry Andric         }
1059*700637cbSDimitry Andric       }
1060*700637cbSDimitry Andric     }
1061*700637cbSDimitry Andric   }
1062*700637cbSDimitry Andric 
1063*700637cbSDimitry Andric   if (BuiltinOp == Builtin::BI__atomic_always_lock_free)
1064*700637cbSDimitry Andric     return returnBool(false);
1065*700637cbSDimitry Andric 
1066*700637cbSDimitry Andric   return false;
1067*700637cbSDimitry Andric }
1068*700637cbSDimitry Andric 
1069*700637cbSDimitry Andric /// bool __c11_atomic_is_lock_free(size_t)
interp__builtin_c11_atomic_is_lock_free(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1070*700637cbSDimitry Andric static bool interp__builtin_c11_atomic_is_lock_free(InterpState &S,
1071*700637cbSDimitry Andric                                                     CodePtr OpPC,
1072*700637cbSDimitry Andric                                                     const InterpFrame *Frame,
1073*700637cbSDimitry Andric                                                     const CallExpr *Call) {
1074*700637cbSDimitry Andric   PrimType ValT = *S.getContext().classify(Call->getArg(0));
1075*700637cbSDimitry Andric   const APSInt &SizeVal = popToAPSInt(S.Stk, ValT);
1076*700637cbSDimitry Andric 
1077*700637cbSDimitry Andric   auto returnBool = [&S](bool Value) -> bool {
1078*700637cbSDimitry Andric     S.Stk.push<Boolean>(Value);
1079*700637cbSDimitry Andric     return true;
1080*700637cbSDimitry Andric   };
1081*700637cbSDimitry Andric 
1082*700637cbSDimitry Andric   CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());
1083*700637cbSDimitry Andric   if (Size.isPowerOfTwo()) {
1084*700637cbSDimitry Andric     // Check against inlining width.
1085*700637cbSDimitry Andric     unsigned InlineWidthBits =
1086*700637cbSDimitry Andric         S.getASTContext().getTargetInfo().getMaxAtomicInlineWidth();
1087*700637cbSDimitry Andric     if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits))
1088*700637cbSDimitry Andric       return returnBool(true);
1089*700637cbSDimitry Andric   }
1090*700637cbSDimitry Andric 
1091*700637cbSDimitry Andric   return false; // returnBool(false);
1092*700637cbSDimitry Andric }
1093*700637cbSDimitry Andric 
1094*700637cbSDimitry Andric /// __builtin_complex(Float A, float B);
interp__builtin_complex(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1095*700637cbSDimitry Andric static bool interp__builtin_complex(InterpState &S, CodePtr OpPC,
1096*700637cbSDimitry Andric                                     const InterpFrame *Frame,
1097*700637cbSDimitry Andric                                     const CallExpr *Call) {
1098*700637cbSDimitry Andric   const Floating &Arg2 = S.Stk.pop<Floating>();
1099*700637cbSDimitry Andric   const Floating &Arg1 = S.Stk.pop<Floating>();
1100*700637cbSDimitry Andric   Pointer &Result = S.Stk.peek<Pointer>();
1101*700637cbSDimitry Andric 
1102*700637cbSDimitry Andric   Result.atIndex(0).deref<Floating>() = Arg1;
1103*700637cbSDimitry Andric   Result.atIndex(0).initialize();
1104*700637cbSDimitry Andric   Result.atIndex(1).deref<Floating>() = Arg2;
1105*700637cbSDimitry Andric   Result.atIndex(1).initialize();
1106*700637cbSDimitry Andric   Result.initialize();
1107*700637cbSDimitry Andric 
1108*700637cbSDimitry Andric   return true;
1109*700637cbSDimitry Andric }
1110*700637cbSDimitry Andric 
1111*700637cbSDimitry Andric /// __builtin_is_aligned()
1112*700637cbSDimitry Andric /// __builtin_align_up()
1113*700637cbSDimitry Andric /// __builtin_align_down()
1114*700637cbSDimitry Andric /// The first parameter is either an integer or a pointer.
1115*700637cbSDimitry Andric /// The second parameter is the requested alignment as an integer.
interp__builtin_is_aligned_up_down(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,unsigned BuiltinOp)1116*700637cbSDimitry Andric static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,
1117*700637cbSDimitry Andric                                                const InterpFrame *Frame,
1118*700637cbSDimitry Andric                                                const CallExpr *Call,
1119*700637cbSDimitry Andric                                                unsigned BuiltinOp) {
1120*700637cbSDimitry Andric   PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1));
1121*700637cbSDimitry Andric   const APSInt &Alignment = popToAPSInt(S.Stk, AlignmentT);
1122*700637cbSDimitry Andric 
1123*700637cbSDimitry Andric   if (Alignment < 0 || !Alignment.isPowerOf2()) {
1124*700637cbSDimitry Andric     S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment;
1125*700637cbSDimitry Andric     return false;
1126*700637cbSDimitry Andric   }
1127*700637cbSDimitry Andric   unsigned SrcWidth = S.getASTContext().getIntWidth(Call->getArg(0)->getType());
1128*700637cbSDimitry Andric   APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1));
1129*700637cbSDimitry Andric   if (APSInt::compareValues(Alignment, MaxValue) > 0) {
1130*700637cbSDimitry Andric     S.FFDiag(Call, diag::note_constexpr_alignment_too_big)
1131*700637cbSDimitry Andric         << MaxValue << Call->getArg(0)->getType() << Alignment;
1132*700637cbSDimitry Andric     return false;
1133*700637cbSDimitry Andric   }
1134*700637cbSDimitry Andric 
1135*700637cbSDimitry Andric   // The first parameter is either an integer or a pointer (but not a function
1136*700637cbSDimitry Andric   // pointer).
1137*700637cbSDimitry Andric   PrimType FirstArgT = *S.Ctx.classify(Call->getArg(0));
1138*700637cbSDimitry Andric 
1139*700637cbSDimitry Andric   if (isIntegralType(FirstArgT)) {
1140*700637cbSDimitry Andric     const APSInt &Src = popToAPSInt(S.Stk, FirstArgT);
1141*700637cbSDimitry Andric     APInt AlignMinusOne = Alignment.extOrTrunc(Src.getBitWidth()) - 1;
1142*700637cbSDimitry Andric     if (BuiltinOp == Builtin::BI__builtin_align_up) {
1143*700637cbSDimitry Andric       APSInt AlignedVal =
1144*700637cbSDimitry Andric           APSInt((Src + AlignMinusOne) & ~AlignMinusOne, Src.isUnsigned());
1145*700637cbSDimitry Andric       pushInteger(S, AlignedVal, Call->getType());
1146*700637cbSDimitry Andric     } else if (BuiltinOp == Builtin::BI__builtin_align_down) {
1147*700637cbSDimitry Andric       APSInt AlignedVal = APSInt(Src & ~AlignMinusOne, Src.isUnsigned());
1148*700637cbSDimitry Andric       pushInteger(S, AlignedVal, Call->getType());
1149*700637cbSDimitry Andric     } else {
1150*700637cbSDimitry Andric       assert(*S.Ctx.classify(Call->getType()) == PT_Bool);
1151*700637cbSDimitry Andric       S.Stk.push<Boolean>((Src & AlignMinusOne) == 0);
1152*700637cbSDimitry Andric     }
1153*700637cbSDimitry Andric     return true;
1154*700637cbSDimitry Andric   }
1155*700637cbSDimitry Andric 
1156*700637cbSDimitry Andric   assert(FirstArgT == PT_Ptr);
1157*700637cbSDimitry Andric   const Pointer &Ptr = S.Stk.pop<Pointer>();
1158*700637cbSDimitry Andric 
1159*700637cbSDimitry Andric   unsigned PtrOffset = Ptr.getByteOffset();
1160*700637cbSDimitry Andric   PtrOffset = Ptr.getIndex();
1161*700637cbSDimitry Andric   CharUnits BaseAlignment =
1162*700637cbSDimitry Andric       S.getASTContext().getDeclAlign(Ptr.getDeclDesc()->asValueDecl());
1163*700637cbSDimitry Andric   CharUnits PtrAlign =
1164*700637cbSDimitry Andric       BaseAlignment.alignmentAtOffset(CharUnits::fromQuantity(PtrOffset));
1165*700637cbSDimitry Andric 
1166*700637cbSDimitry Andric   if (BuiltinOp == Builtin::BI__builtin_is_aligned) {
1167*700637cbSDimitry Andric     if (PtrAlign.getQuantity() >= Alignment) {
1168*700637cbSDimitry Andric       S.Stk.push<Boolean>(true);
1169*700637cbSDimitry Andric       return true;
1170*700637cbSDimitry Andric     }
1171*700637cbSDimitry Andric     // If the alignment is not known to be sufficient, some cases could still
1172*700637cbSDimitry Andric     // be aligned at run time. However, if the requested alignment is less or
1173*700637cbSDimitry Andric     // equal to the base alignment and the offset is not aligned, we know that
1174*700637cbSDimitry Andric     // the run-time value can never be aligned.
1175*700637cbSDimitry Andric     if (BaseAlignment.getQuantity() >= Alignment &&
1176*700637cbSDimitry Andric         PtrAlign.getQuantity() < Alignment) {
1177*700637cbSDimitry Andric       S.Stk.push<Boolean>(false);
1178*700637cbSDimitry Andric       return true;
1179*700637cbSDimitry Andric     }
1180*700637cbSDimitry Andric 
1181*700637cbSDimitry Andric     S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_compute)
1182*700637cbSDimitry Andric         << Alignment;
1183*700637cbSDimitry Andric     return false;
1184*700637cbSDimitry Andric   }
1185*700637cbSDimitry Andric 
1186*700637cbSDimitry Andric   assert(BuiltinOp == Builtin::BI__builtin_align_down ||
1187*700637cbSDimitry Andric          BuiltinOp == Builtin::BI__builtin_align_up);
1188*700637cbSDimitry Andric 
1189*700637cbSDimitry Andric   // For align_up/align_down, we can return the same value if the alignment
1190*700637cbSDimitry Andric   // is known to be greater or equal to the requested value.
1191*700637cbSDimitry Andric   if (PtrAlign.getQuantity() >= Alignment) {
1192*700637cbSDimitry Andric     S.Stk.push<Pointer>(Ptr);
1193*700637cbSDimitry Andric     return true;
1194*700637cbSDimitry Andric   }
1195*700637cbSDimitry Andric 
1196*700637cbSDimitry Andric   // The alignment could be greater than the minimum at run-time, so we cannot
1197*700637cbSDimitry Andric   // infer much about the resulting pointer value. One case is possible:
1198*700637cbSDimitry Andric   // For `_Alignas(32) char buf[N]; __builtin_align_down(&buf[idx], 32)` we
1199*700637cbSDimitry Andric   // can infer the correct index if the requested alignment is smaller than
1200*700637cbSDimitry Andric   // the base alignment so we can perform the computation on the offset.
1201*700637cbSDimitry Andric   if (BaseAlignment.getQuantity() >= Alignment) {
1202*700637cbSDimitry Andric     assert(Alignment.getBitWidth() <= 64 &&
1203*700637cbSDimitry Andric            "Cannot handle > 64-bit address-space");
1204*700637cbSDimitry Andric     uint64_t Alignment64 = Alignment.getZExtValue();
1205*700637cbSDimitry Andric     CharUnits NewOffset =
1206*700637cbSDimitry Andric         CharUnits::fromQuantity(BuiltinOp == Builtin::BI__builtin_align_down
1207*700637cbSDimitry Andric                                     ? llvm::alignDown(PtrOffset, Alignment64)
1208*700637cbSDimitry Andric                                     : llvm::alignTo(PtrOffset, Alignment64));
1209*700637cbSDimitry Andric 
1210*700637cbSDimitry Andric     S.Stk.push<Pointer>(Ptr.atIndex(NewOffset.getQuantity()));
1211*700637cbSDimitry Andric     return true;
1212*700637cbSDimitry Andric   }
1213*700637cbSDimitry Andric 
1214*700637cbSDimitry Andric   // Otherwise, we cannot constant-evaluate the result.
1215*700637cbSDimitry Andric   S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_adjust) << Alignment;
1216*700637cbSDimitry Andric   return false;
1217*700637cbSDimitry Andric }
1218*700637cbSDimitry Andric 
1219*700637cbSDimitry Andric /// __builtin_assume_aligned(Ptr, Alignment[, ExtraOffset])
interp__builtin_assume_aligned(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1220*700637cbSDimitry Andric static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC,
1221*700637cbSDimitry Andric                                            const InterpFrame *Frame,
1222*700637cbSDimitry Andric                                            const CallExpr *Call) {
1223*700637cbSDimitry Andric   assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3);
1224*700637cbSDimitry Andric 
1225*700637cbSDimitry Andric   std::optional<APSInt> ExtraOffset;
1226*700637cbSDimitry Andric   if (Call->getNumArgs() == 3)
1227*700637cbSDimitry Andric     ExtraOffset = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(2)));
1228*700637cbSDimitry Andric 
1229*700637cbSDimitry Andric   APSInt Alignment = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)));
1230*700637cbSDimitry Andric   const Pointer &Ptr = S.Stk.pop<Pointer>();
1231*700637cbSDimitry Andric 
1232*700637cbSDimitry Andric   CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue());
1233*700637cbSDimitry Andric 
1234*700637cbSDimitry Andric   // If there is a base object, then it must have the correct alignment.
1235*700637cbSDimitry Andric   if (Ptr.isBlockPointer()) {
1236*700637cbSDimitry Andric     CharUnits BaseAlignment;
1237*700637cbSDimitry Andric     if (const auto *VD = Ptr.getDeclDesc()->asValueDecl())
1238*700637cbSDimitry Andric       BaseAlignment = S.getASTContext().getDeclAlign(VD);
1239*700637cbSDimitry Andric     else if (const auto *E = Ptr.getDeclDesc()->asExpr())
1240*700637cbSDimitry Andric       BaseAlignment = GetAlignOfExpr(S.getASTContext(), E, UETT_AlignOf);
1241*700637cbSDimitry Andric 
1242*700637cbSDimitry Andric     if (BaseAlignment < Align) {
1243*700637cbSDimitry Andric       S.CCEDiag(Call->getArg(0),
1244*700637cbSDimitry Andric                 diag::note_constexpr_baa_insufficient_alignment)
1245*700637cbSDimitry Andric           << 0 << BaseAlignment.getQuantity() << Align.getQuantity();
1246*700637cbSDimitry Andric       return false;
1247*700637cbSDimitry Andric     }
1248*700637cbSDimitry Andric   }
1249*700637cbSDimitry Andric 
1250*700637cbSDimitry Andric   APValue AV = Ptr.toAPValue(S.getASTContext());
1251*700637cbSDimitry Andric   CharUnits AVOffset = AV.getLValueOffset();
1252*700637cbSDimitry Andric   if (ExtraOffset)
1253*700637cbSDimitry Andric     AVOffset -= CharUnits::fromQuantity(ExtraOffset->getZExtValue());
1254*700637cbSDimitry Andric   if (AVOffset.alignTo(Align) != AVOffset) {
1255*700637cbSDimitry Andric     if (Ptr.isBlockPointer())
1256*700637cbSDimitry Andric       S.CCEDiag(Call->getArg(0),
1257*700637cbSDimitry Andric                 diag::note_constexpr_baa_insufficient_alignment)
1258*700637cbSDimitry Andric           << 1 << AVOffset.getQuantity() << Align.getQuantity();
1259*700637cbSDimitry Andric     else
1260*700637cbSDimitry Andric       S.CCEDiag(Call->getArg(0),
1261*700637cbSDimitry Andric                 diag::note_constexpr_baa_value_insufficient_alignment)
1262*700637cbSDimitry Andric           << AVOffset.getQuantity() << Align.getQuantity();
1263*700637cbSDimitry Andric     return false;
1264*700637cbSDimitry Andric   }
1265*700637cbSDimitry Andric 
1266*700637cbSDimitry Andric   S.Stk.push<Pointer>(Ptr);
1267*700637cbSDimitry Andric   return true;
1268*700637cbSDimitry Andric }
1269*700637cbSDimitry Andric 
interp__builtin_ia32_bextr(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1270*700637cbSDimitry Andric static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC,
1271*700637cbSDimitry Andric                                        const InterpFrame *Frame,
1272*700637cbSDimitry Andric                                        const CallExpr *Call) {
1273*700637cbSDimitry Andric   if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1274*700637cbSDimitry Andric       !Call->getArg(1)->getType()->isIntegerType())
1275*700637cbSDimitry Andric     return false;
1276*700637cbSDimitry Andric 
1277*700637cbSDimitry Andric   PrimType ValT = *S.Ctx.classify(Call->getArg(0));
1278*700637cbSDimitry Andric   PrimType IndexT = *S.Ctx.classify(Call->getArg(1));
1279*700637cbSDimitry Andric   APSInt Index = popToAPSInt(S.Stk, IndexT);
1280*700637cbSDimitry Andric   APSInt Val = popToAPSInt(S.Stk, ValT);
1281*700637cbSDimitry Andric 
1282*700637cbSDimitry Andric   unsigned BitWidth = Val.getBitWidth();
1283*700637cbSDimitry Andric   uint64_t Shift = Index.extractBitsAsZExtValue(8, 0);
1284*700637cbSDimitry Andric   uint64_t Length = Index.extractBitsAsZExtValue(8, 8);
1285*700637cbSDimitry Andric   Length = Length > BitWidth ? BitWidth : Length;
1286*700637cbSDimitry Andric 
1287*700637cbSDimitry Andric   // Handle out of bounds cases.
1288*700637cbSDimitry Andric   if (Length == 0 || Shift >= BitWidth) {
1289*700637cbSDimitry Andric     pushInteger(S, 0, Call->getType());
1290*700637cbSDimitry Andric     return true;
1291*700637cbSDimitry Andric   }
1292*700637cbSDimitry Andric 
1293*700637cbSDimitry Andric   uint64_t Result = Val.getZExtValue() >> Shift;
1294*700637cbSDimitry Andric   Result &= llvm::maskTrailingOnes<uint64_t>(Length);
1295*700637cbSDimitry Andric   pushInteger(S, Result, Call->getType());
1296*700637cbSDimitry Andric   return true;
1297*700637cbSDimitry Andric }
1298*700637cbSDimitry Andric 
interp__builtin_ia32_bzhi(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1299*700637cbSDimitry Andric static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC,
1300*700637cbSDimitry Andric                                       const InterpFrame *Frame,
1301*700637cbSDimitry Andric                                       const CallExpr *Call) {
1302*700637cbSDimitry Andric   QualType CallType = Call->getType();
1303*700637cbSDimitry Andric   if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1304*700637cbSDimitry Andric       !Call->getArg(1)->getType()->isIntegerType() ||
1305*700637cbSDimitry Andric       !CallType->isIntegerType())
1306*700637cbSDimitry Andric     return false;
1307*700637cbSDimitry Andric 
1308*700637cbSDimitry Andric   PrimType ValT = *S.Ctx.classify(Call->getArg(0));
1309*700637cbSDimitry Andric   PrimType IndexT = *S.Ctx.classify(Call->getArg(1));
1310*700637cbSDimitry Andric 
1311*700637cbSDimitry Andric   APSInt Idx = popToAPSInt(S.Stk, IndexT);
1312*700637cbSDimitry Andric   APSInt Val = popToAPSInt(S.Stk, ValT);
1313*700637cbSDimitry Andric 
1314*700637cbSDimitry Andric   unsigned BitWidth = Val.getBitWidth();
1315*700637cbSDimitry Andric   uint64_t Index = Idx.extractBitsAsZExtValue(8, 0);
1316*700637cbSDimitry Andric 
1317*700637cbSDimitry Andric   if (Index < BitWidth)
1318*700637cbSDimitry Andric     Val.clearHighBits(BitWidth - Index);
1319*700637cbSDimitry Andric 
1320*700637cbSDimitry Andric   pushInteger(S, Val, CallType);
1321*700637cbSDimitry Andric   return true;
1322*700637cbSDimitry Andric }
1323*700637cbSDimitry Andric 
interp__builtin_ia32_lzcnt(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1324*700637cbSDimitry Andric static bool interp__builtin_ia32_lzcnt(InterpState &S, CodePtr OpPC,
1325*700637cbSDimitry Andric                                        const InterpFrame *Frame,
1326*700637cbSDimitry Andric                                        const CallExpr *Call) {
1327*700637cbSDimitry Andric   QualType CallType = Call->getType();
1328*700637cbSDimitry Andric   if (!CallType->isIntegerType() ||
1329*700637cbSDimitry Andric       !Call->getArg(0)->getType()->isIntegerType())
1330*700637cbSDimitry Andric     return false;
1331*700637cbSDimitry Andric 
1332*700637cbSDimitry Andric   APSInt Val = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
1333*700637cbSDimitry Andric   pushInteger(S, Val.countLeadingZeros(), CallType);
1334*700637cbSDimitry Andric   return true;
1335*700637cbSDimitry Andric }
1336*700637cbSDimitry Andric 
interp__builtin_ia32_tzcnt(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1337*700637cbSDimitry Andric static bool interp__builtin_ia32_tzcnt(InterpState &S, CodePtr OpPC,
1338*700637cbSDimitry Andric                                        const InterpFrame *Frame,
1339*700637cbSDimitry Andric                                        const CallExpr *Call) {
1340*700637cbSDimitry Andric   QualType CallType = Call->getType();
1341*700637cbSDimitry Andric   if (!CallType->isIntegerType() ||
1342*700637cbSDimitry Andric       !Call->getArg(0)->getType()->isIntegerType())
1343*700637cbSDimitry Andric     return false;
1344*700637cbSDimitry Andric 
1345*700637cbSDimitry Andric   APSInt Val = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
1346*700637cbSDimitry Andric   pushInteger(S, Val.countTrailingZeros(), CallType);
1347*700637cbSDimitry Andric   return true;
1348*700637cbSDimitry Andric }
1349*700637cbSDimitry Andric 
interp__builtin_ia32_pdep(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1350*700637cbSDimitry Andric static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC,
1351*700637cbSDimitry Andric                                       const InterpFrame *Frame,
1352*700637cbSDimitry Andric                                       const CallExpr *Call) {
1353*700637cbSDimitry Andric   if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1354*700637cbSDimitry Andric       !Call->getArg(1)->getType()->isIntegerType())
1355*700637cbSDimitry Andric     return false;
1356*700637cbSDimitry Andric 
1357*700637cbSDimitry Andric   PrimType ValT = *S.Ctx.classify(Call->getArg(0));
1358*700637cbSDimitry Andric   PrimType MaskT = *S.Ctx.classify(Call->getArg(1));
1359*700637cbSDimitry Andric 
1360*700637cbSDimitry Andric   APSInt Mask = popToAPSInt(S.Stk, MaskT);
1361*700637cbSDimitry Andric   APSInt Val = popToAPSInt(S.Stk, ValT);
1362*700637cbSDimitry Andric 
1363*700637cbSDimitry Andric   unsigned BitWidth = Val.getBitWidth();
1364*700637cbSDimitry Andric   APInt Result = APInt::getZero(BitWidth);
1365*700637cbSDimitry Andric   for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
1366*700637cbSDimitry Andric     if (Mask[I])
1367*700637cbSDimitry Andric       Result.setBitVal(I, Val[P++]);
1368*700637cbSDimitry Andric   }
1369*700637cbSDimitry Andric   pushInteger(S, std::move(Result), Call->getType());
1370*700637cbSDimitry Andric   return true;
1371*700637cbSDimitry Andric }
1372*700637cbSDimitry Andric 
interp__builtin_ia32_pext(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1373*700637cbSDimitry Andric static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC,
1374*700637cbSDimitry Andric                                       const InterpFrame *Frame,
1375*700637cbSDimitry Andric                                       const CallExpr *Call) {
1376*700637cbSDimitry Andric   if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1377*700637cbSDimitry Andric       !Call->getArg(1)->getType()->isIntegerType())
1378*700637cbSDimitry Andric     return false;
1379*700637cbSDimitry Andric 
1380*700637cbSDimitry Andric   PrimType ValT = *S.Ctx.classify(Call->getArg(0));
1381*700637cbSDimitry Andric   PrimType MaskT = *S.Ctx.classify(Call->getArg(1));
1382*700637cbSDimitry Andric 
1383*700637cbSDimitry Andric   APSInt Mask = popToAPSInt(S.Stk, MaskT);
1384*700637cbSDimitry Andric   APSInt Val = popToAPSInt(S.Stk, ValT);
1385*700637cbSDimitry Andric 
1386*700637cbSDimitry Andric   unsigned BitWidth = Val.getBitWidth();
1387*700637cbSDimitry Andric   APInt Result = APInt::getZero(BitWidth);
1388*700637cbSDimitry Andric   for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
1389*700637cbSDimitry Andric     if (Mask[I])
1390*700637cbSDimitry Andric       Result.setBitVal(P++, Val[I]);
1391*700637cbSDimitry Andric   }
1392*700637cbSDimitry Andric   pushInteger(S, std::move(Result), Call->getType());
1393*700637cbSDimitry Andric   return true;
1394*700637cbSDimitry Andric }
1395*700637cbSDimitry Andric 
1396*700637cbSDimitry Andric /// (CarryIn, LHS, RHS, Result)
interp__builtin_ia32_addcarry_subborrow(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,unsigned BuiltinOp)1397*700637cbSDimitry Andric static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S,
1398*700637cbSDimitry Andric                                                     CodePtr OpPC,
1399*700637cbSDimitry Andric                                                     const InterpFrame *Frame,
1400*700637cbSDimitry Andric                                                     const CallExpr *Call,
1401*700637cbSDimitry Andric                                                     unsigned BuiltinOp) {
1402*700637cbSDimitry Andric   if (Call->getNumArgs() != 4 || !Call->getArg(0)->getType()->isIntegerType() ||
1403*700637cbSDimitry Andric       !Call->getArg(1)->getType()->isIntegerType() ||
1404*700637cbSDimitry Andric       !Call->getArg(2)->getType()->isIntegerType())
1405*700637cbSDimitry Andric     return false;
1406*700637cbSDimitry Andric 
1407*700637cbSDimitry Andric   const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();
1408*700637cbSDimitry Andric 
1409*700637cbSDimitry Andric   PrimType CarryInT = *S.getContext().classify(Call->getArg(0));
1410*700637cbSDimitry Andric   PrimType LHST = *S.getContext().classify(Call->getArg(1));
1411*700637cbSDimitry Andric   PrimType RHST = *S.getContext().classify(Call->getArg(2));
1412*700637cbSDimitry Andric   APSInt RHS = popToAPSInt(S.Stk, RHST);
1413*700637cbSDimitry Andric   APSInt LHS = popToAPSInt(S.Stk, LHST);
1414*700637cbSDimitry Andric   APSInt CarryIn = popToAPSInt(S.Stk, CarryInT);
1415*700637cbSDimitry Andric 
1416*700637cbSDimitry Andric   bool IsAdd = BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u32 ||
1417*700637cbSDimitry Andric                BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u64;
1418*700637cbSDimitry Andric 
1419*700637cbSDimitry Andric   unsigned BitWidth = LHS.getBitWidth();
1420*700637cbSDimitry Andric   unsigned CarryInBit = CarryIn.ugt(0) ? 1 : 0;
1421*700637cbSDimitry Andric   APInt ExResult =
1422*700637cbSDimitry Andric       IsAdd ? (LHS.zext(BitWidth + 1) + (RHS.zext(BitWidth + 1) + CarryInBit))
1423*700637cbSDimitry Andric             : (LHS.zext(BitWidth + 1) - (RHS.zext(BitWidth + 1) + CarryInBit));
1424*700637cbSDimitry Andric 
1425*700637cbSDimitry Andric   APInt Result = ExResult.extractBits(BitWidth, 0);
1426*700637cbSDimitry Andric   APSInt CarryOut =
1427*700637cbSDimitry Andric       APSInt(ExResult.extractBits(1, BitWidth), /*IsUnsigned=*/true);
1428*700637cbSDimitry Andric 
1429*700637cbSDimitry Andric   QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
1430*700637cbSDimitry Andric   PrimType CarryOutT = *S.getContext().classify(CarryOutType);
1431*700637cbSDimitry Andric   assignInteger(S, CarryOutPtr, CarryOutT, APSInt(std::move(Result), true));
1432*700637cbSDimitry Andric 
1433*700637cbSDimitry Andric   pushInteger(S, CarryOut, Call->getType());
1434*700637cbSDimitry Andric 
1435*700637cbSDimitry Andric   return true;
1436*700637cbSDimitry Andric }
1437*700637cbSDimitry Andric 
interp__builtin_os_log_format_buffer_size(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1438*700637cbSDimitry Andric static bool interp__builtin_os_log_format_buffer_size(InterpState &S,
1439*700637cbSDimitry Andric                                                       CodePtr OpPC,
1440*700637cbSDimitry Andric                                                       const InterpFrame *Frame,
1441*700637cbSDimitry Andric                                                       const CallExpr *Call) {
1442*700637cbSDimitry Andric   analyze_os_log::OSLogBufferLayout Layout;
1443*700637cbSDimitry Andric   analyze_os_log::computeOSLogBufferLayout(S.getASTContext(), Call, Layout);
1444*700637cbSDimitry Andric   pushInteger(S, Layout.size().getQuantity(), Call->getType());
1445*700637cbSDimitry Andric   return true;
1446*700637cbSDimitry Andric }
1447*700637cbSDimitry Andric 
1448*700637cbSDimitry Andric static bool
interp__builtin_ptrauth_string_discriminator(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1449*700637cbSDimitry Andric interp__builtin_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC,
1450*700637cbSDimitry Andric                                              const InterpFrame *Frame,
1451*700637cbSDimitry Andric                                              const CallExpr *Call) {
1452*700637cbSDimitry Andric   const auto &Ptr = S.Stk.pop<Pointer>();
1453*700637cbSDimitry Andric   assert(Ptr.getFieldDesc()->isPrimitiveArray());
1454*700637cbSDimitry Andric 
1455*700637cbSDimitry Andric   // This should be created for a StringLiteral, so should alway shold at least
1456*700637cbSDimitry Andric   // one array element.
1457*700637cbSDimitry Andric   assert(Ptr.getFieldDesc()->getNumElems() >= 1);
1458*700637cbSDimitry Andric   StringRef R(&Ptr.deref<char>(), Ptr.getFieldDesc()->getNumElems() - 1);
1459*700637cbSDimitry Andric   uint64_t Result = getPointerAuthStableSipHash(R);
1460*700637cbSDimitry Andric   pushInteger(S, Result, Call->getType());
1461*700637cbSDimitry Andric   return true;
1462*700637cbSDimitry Andric }
1463*700637cbSDimitry Andric 
interp__builtin_operator_new(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1464*700637cbSDimitry Andric static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
1465*700637cbSDimitry Andric                                          const InterpFrame *Frame,
1466*700637cbSDimitry Andric                                          const CallExpr *Call) {
1467*700637cbSDimitry Andric   // A call to __operator_new is only valid within std::allocate<>::allocate.
1468*700637cbSDimitry Andric   // Walk up the call stack to find the appropriate caller and get the
1469*700637cbSDimitry Andric   // element type from it.
1470*700637cbSDimitry Andric   auto [NewCall, ElemType] = S.getStdAllocatorCaller("allocate");
1471*700637cbSDimitry Andric 
1472*700637cbSDimitry Andric   if (ElemType.isNull()) {
1473*700637cbSDimitry Andric     S.FFDiag(Call, S.getLangOpts().CPlusPlus20
1474*700637cbSDimitry Andric                        ? diag::note_constexpr_new_untyped
1475*700637cbSDimitry Andric                        : diag::note_constexpr_new);
1476*700637cbSDimitry Andric     return false;
1477*700637cbSDimitry Andric   }
1478*700637cbSDimitry Andric   assert(NewCall);
1479*700637cbSDimitry Andric 
1480*700637cbSDimitry Andric   if (ElemType->isIncompleteType() || ElemType->isFunctionType()) {
1481*700637cbSDimitry Andric     S.FFDiag(Call, diag::note_constexpr_new_not_complete_object_type)
1482*700637cbSDimitry Andric         << (ElemType->isIncompleteType() ? 0 : 1) << ElemType;
1483*700637cbSDimitry Andric     return false;
1484*700637cbSDimitry Andric   }
1485*700637cbSDimitry Andric 
1486*700637cbSDimitry Andric   // We only care about the first parameter (the size), so discard all the
1487*700637cbSDimitry Andric   // others.
1488*700637cbSDimitry Andric   {
1489*700637cbSDimitry Andric     unsigned NumArgs = Call->getNumArgs();
1490*700637cbSDimitry Andric     assert(NumArgs >= 1);
1491*700637cbSDimitry Andric 
1492*700637cbSDimitry Andric     // The std::nothrow_t arg never gets put on the stack.
1493*700637cbSDimitry Andric     if (Call->getArg(NumArgs - 1)->getType()->isNothrowT())
1494*700637cbSDimitry Andric       --NumArgs;
1495*700637cbSDimitry Andric     auto Args = ArrayRef(Call->getArgs(), Call->getNumArgs());
1496*700637cbSDimitry Andric     // First arg is needed.
1497*700637cbSDimitry Andric     Args = Args.drop_front();
1498*700637cbSDimitry Andric 
1499*700637cbSDimitry Andric     // Discard the rest.
1500*700637cbSDimitry Andric     for (const Expr *Arg : Args)
1501*700637cbSDimitry Andric       discard(S.Stk, *S.getContext().classify(Arg));
1502*700637cbSDimitry Andric   }
1503*700637cbSDimitry Andric 
1504*700637cbSDimitry Andric   APSInt Bytes = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(0)));
1505*700637cbSDimitry Andric   CharUnits ElemSize = S.getASTContext().getTypeSizeInChars(ElemType);
1506*700637cbSDimitry Andric   assert(!ElemSize.isZero());
1507*700637cbSDimitry Andric   // Divide the number of bytes by sizeof(ElemType), so we get the number of
1508*700637cbSDimitry Andric   // elements we should allocate.
1509*700637cbSDimitry Andric   APInt NumElems, Remainder;
1510*700637cbSDimitry Andric   APInt ElemSizeAP(Bytes.getBitWidth(), ElemSize.getQuantity());
1511*700637cbSDimitry Andric   APInt::udivrem(Bytes, ElemSizeAP, NumElems, Remainder);
1512*700637cbSDimitry Andric   if (Remainder != 0) {
1513*700637cbSDimitry Andric     // This likely indicates a bug in the implementation of 'std::allocator'.
1514*700637cbSDimitry Andric     S.FFDiag(Call, diag::note_constexpr_operator_new_bad_size)
1515*700637cbSDimitry Andric         << Bytes << APSInt(ElemSizeAP, true) << ElemType;
1516*700637cbSDimitry Andric     return false;
1517*700637cbSDimitry Andric   }
1518*700637cbSDimitry Andric 
1519*700637cbSDimitry Andric   // NB: The same check we're using in CheckArraySize()
1520*700637cbSDimitry Andric   if (NumElems.getActiveBits() >
1521*700637cbSDimitry Andric           ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||
1522*700637cbSDimitry Andric       NumElems.ugt(Descriptor::MaxArrayElemBytes / ElemSize.getQuantity())) {
1523*700637cbSDimitry Andric     // FIXME: NoThrow check?
1524*700637cbSDimitry Andric     const SourceInfo &Loc = S.Current->getSource(OpPC);
1525*700637cbSDimitry Andric     S.FFDiag(Loc, diag::note_constexpr_new_too_large)
1526*700637cbSDimitry Andric         << NumElems.getZExtValue();
1527*700637cbSDimitry Andric     return false;
1528*700637cbSDimitry Andric   }
1529*700637cbSDimitry Andric 
1530*700637cbSDimitry Andric   if (!CheckArraySize(S, OpPC, NumElems.getZExtValue()))
1531*700637cbSDimitry Andric     return false;
1532*700637cbSDimitry Andric 
1533*700637cbSDimitry Andric   bool IsArray = NumElems.ugt(1);
1534*700637cbSDimitry Andric   std::optional<PrimType> ElemT = S.getContext().classify(ElemType);
1535*700637cbSDimitry Andric   DynamicAllocator &Allocator = S.getAllocator();
1536*700637cbSDimitry Andric   if (ElemT) {
1537*700637cbSDimitry Andric     Block *B =
1538*700637cbSDimitry Andric         Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(),
1539*700637cbSDimitry Andric                            S.Ctx.getEvalID(), DynamicAllocator::Form::Operator);
1540*700637cbSDimitry Andric     assert(B);
1541*700637cbSDimitry Andric     S.Stk.push<Pointer>(Pointer(B).atIndex(0));
1542*700637cbSDimitry Andric     return true;
1543*700637cbSDimitry Andric   }
1544*700637cbSDimitry Andric 
1545*700637cbSDimitry Andric   assert(!ElemT);
1546*700637cbSDimitry Andric 
1547*700637cbSDimitry Andric   // Composite arrays
1548*700637cbSDimitry Andric   if (IsArray) {
1549*700637cbSDimitry Andric     const Descriptor *Desc =
1550*700637cbSDimitry Andric         S.P.createDescriptor(NewCall, ElemType.getTypePtr(),
1551*700637cbSDimitry Andric                              IsArray ? std::nullopt : Descriptor::InlineDescMD);
1552*700637cbSDimitry Andric     Block *B =
1553*700637cbSDimitry Andric         Allocator.allocate(Desc, NumElems.getZExtValue(), S.Ctx.getEvalID(),
1554*700637cbSDimitry Andric                            DynamicAllocator::Form::Operator);
1555*700637cbSDimitry Andric     assert(B);
1556*700637cbSDimitry Andric     S.Stk.push<Pointer>(Pointer(B).atIndex(0));
1557*700637cbSDimitry Andric     return true;
1558*700637cbSDimitry Andric   }
1559*700637cbSDimitry Andric 
1560*700637cbSDimitry Andric   // Records. Still allocate them as single-element arrays.
1561*700637cbSDimitry Andric   QualType AllocType = S.getASTContext().getConstantArrayType(
1562*700637cbSDimitry Andric       ElemType, NumElems, nullptr, ArraySizeModifier::Normal, 0);
1563*700637cbSDimitry Andric 
1564*700637cbSDimitry Andric   const Descriptor *Desc =
1565*700637cbSDimitry Andric       S.P.createDescriptor(NewCall, AllocType.getTypePtr(),
1566*700637cbSDimitry Andric                            IsArray ? std::nullopt : Descriptor::InlineDescMD);
1567*700637cbSDimitry Andric   Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(),
1568*700637cbSDimitry Andric                                 DynamicAllocator::Form::Operator);
1569*700637cbSDimitry Andric   assert(B);
1570*700637cbSDimitry Andric   S.Stk.push<Pointer>(Pointer(B).atIndex(0).narrow());
1571*700637cbSDimitry Andric   return true;
1572*700637cbSDimitry Andric }
1573*700637cbSDimitry Andric 
interp__builtin_operator_delete(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1574*700637cbSDimitry Andric static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC,
1575*700637cbSDimitry Andric                                             const InterpFrame *Frame,
1576*700637cbSDimitry Andric                                             const CallExpr *Call) {
1577*700637cbSDimitry Andric   const Expr *Source = nullptr;
1578*700637cbSDimitry Andric   const Block *BlockToDelete = nullptr;
1579*700637cbSDimitry Andric 
1580*700637cbSDimitry Andric   if (S.checkingPotentialConstantExpression()) {
1581*700637cbSDimitry Andric     S.Stk.discard<Pointer>();
1582*700637cbSDimitry Andric     return false;
1583*700637cbSDimitry Andric   }
1584*700637cbSDimitry Andric 
1585*700637cbSDimitry Andric   // This is permitted only within a call to std::allocator<T>::deallocate.
1586*700637cbSDimitry Andric   if (!S.getStdAllocatorCaller("deallocate")) {
1587*700637cbSDimitry Andric     S.FFDiag(Call);
1588*700637cbSDimitry Andric     S.Stk.discard<Pointer>();
1589*700637cbSDimitry Andric     return true;
1590*700637cbSDimitry Andric   }
1591*700637cbSDimitry Andric 
1592*700637cbSDimitry Andric   {
1593*700637cbSDimitry Andric     const Pointer &Ptr = S.Stk.pop<Pointer>();
1594*700637cbSDimitry Andric 
1595*700637cbSDimitry Andric     if (Ptr.isZero()) {
1596*700637cbSDimitry Andric       S.CCEDiag(Call, diag::note_constexpr_deallocate_null);
1597*700637cbSDimitry Andric       return true;
1598*700637cbSDimitry Andric     }
1599*700637cbSDimitry Andric 
1600*700637cbSDimitry Andric     Source = Ptr.getDeclDesc()->asExpr();
1601*700637cbSDimitry Andric     BlockToDelete = Ptr.block();
1602*700637cbSDimitry Andric 
1603*700637cbSDimitry Andric     if (!BlockToDelete->isDynamic()) {
1604*700637cbSDimitry Andric       S.FFDiag(Call, diag::note_constexpr_delete_not_heap_alloc)
1605*700637cbSDimitry Andric           << Ptr.toDiagnosticString(S.getASTContext());
1606*700637cbSDimitry Andric       if (const auto *D = Ptr.getFieldDesc()->asDecl())
1607*700637cbSDimitry Andric         S.Note(D->getLocation(), diag::note_declared_at);
1608*700637cbSDimitry Andric     }
1609*700637cbSDimitry Andric   }
1610*700637cbSDimitry Andric   assert(BlockToDelete);
1611*700637cbSDimitry Andric 
1612*700637cbSDimitry Andric   DynamicAllocator &Allocator = S.getAllocator();
1613*700637cbSDimitry Andric   const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
1614*700637cbSDimitry Andric   std::optional<DynamicAllocator::Form> AllocForm =
1615*700637cbSDimitry Andric       Allocator.getAllocationForm(Source);
1616*700637cbSDimitry Andric 
1617*700637cbSDimitry Andric   if (!Allocator.deallocate(Source, BlockToDelete, S)) {
1618*700637cbSDimitry Andric     // Nothing has been deallocated, this must be a double-delete.
1619*700637cbSDimitry Andric     const SourceInfo &Loc = S.Current->getSource(OpPC);
1620*700637cbSDimitry Andric     S.FFDiag(Loc, diag::note_constexpr_double_delete);
1621*700637cbSDimitry Andric     return false;
1622*700637cbSDimitry Andric   }
1623*700637cbSDimitry Andric   assert(AllocForm);
1624*700637cbSDimitry Andric 
1625*700637cbSDimitry Andric   return CheckNewDeleteForms(
1626*700637cbSDimitry Andric       S, OpPC, *AllocForm, DynamicAllocator::Form::Operator, BlockDesc, Source);
1627*700637cbSDimitry Andric }
1628*700637cbSDimitry Andric 
interp__builtin_arithmetic_fence(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)1629*700637cbSDimitry Andric static bool interp__builtin_arithmetic_fence(InterpState &S, CodePtr OpPC,
1630*700637cbSDimitry Andric                                              const InterpFrame *Frame,
1631*700637cbSDimitry Andric                                              const CallExpr *Call) {
1632*700637cbSDimitry Andric   const Floating &Arg0 = S.Stk.pop<Floating>();
1633*700637cbSDimitry Andric   S.Stk.push<Floating>(Arg0);
1634*700637cbSDimitry Andric   return true;
1635*700637cbSDimitry Andric }
1636*700637cbSDimitry Andric 
interp__builtin_vector_reduce(InterpState & S,CodePtr OpPC,const CallExpr * Call,unsigned ID)1637*700637cbSDimitry Andric static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
1638*700637cbSDimitry Andric                                           const CallExpr *Call, unsigned ID) {
1639*700637cbSDimitry Andric   const Pointer &Arg = S.Stk.pop<Pointer>();
1640*700637cbSDimitry Andric   assert(Arg.getFieldDesc()->isPrimitiveArray());
1641*700637cbSDimitry Andric 
1642*700637cbSDimitry Andric   QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1643*700637cbSDimitry Andric   assert(Call->getType() == ElemType);
1644*700637cbSDimitry Andric   PrimType ElemT = *S.getContext().classify(ElemType);
1645*700637cbSDimitry Andric   unsigned NumElems = Arg.getNumElems();
1646*700637cbSDimitry Andric 
1647*700637cbSDimitry Andric   INT_TYPE_SWITCH_NO_BOOL(ElemT, {
1648*700637cbSDimitry Andric     T Result = Arg.atIndex(0).deref<T>();
1649*700637cbSDimitry Andric     unsigned BitWidth = Result.bitWidth();
1650*700637cbSDimitry Andric     for (unsigned I = 1; I != NumElems; ++I) {
1651*700637cbSDimitry Andric       T Elem = Arg.atIndex(I).deref<T>();
1652*700637cbSDimitry Andric       T PrevResult = Result;
1653*700637cbSDimitry Andric 
1654*700637cbSDimitry Andric       if (ID == Builtin::BI__builtin_reduce_add) {
1655*700637cbSDimitry Andric         if (T::add(Result, Elem, BitWidth, &Result)) {
1656*700637cbSDimitry Andric           unsigned OverflowBits = BitWidth + 1;
1657*700637cbSDimitry Andric           (void)handleOverflow(S, OpPC,
1658*700637cbSDimitry Andric                                (PrevResult.toAPSInt(OverflowBits) +
1659*700637cbSDimitry Andric                                 Elem.toAPSInt(OverflowBits)));
1660*700637cbSDimitry Andric           return false;
1661*700637cbSDimitry Andric         }
1662*700637cbSDimitry Andric       } else if (ID == Builtin::BI__builtin_reduce_mul) {
1663*700637cbSDimitry Andric         if (T::mul(Result, Elem, BitWidth, &Result)) {
1664*700637cbSDimitry Andric           unsigned OverflowBits = BitWidth * 2;
1665*700637cbSDimitry Andric           (void)handleOverflow(S, OpPC,
1666*700637cbSDimitry Andric                                (PrevResult.toAPSInt(OverflowBits) *
1667*700637cbSDimitry Andric                                 Elem.toAPSInt(OverflowBits)));
1668*700637cbSDimitry Andric           return false;
1669*700637cbSDimitry Andric         }
1670*700637cbSDimitry Andric 
1671*700637cbSDimitry Andric       } else if (ID == Builtin::BI__builtin_reduce_and) {
1672*700637cbSDimitry Andric         (void)T::bitAnd(Result, Elem, BitWidth, &Result);
1673*700637cbSDimitry Andric       } else if (ID == Builtin::BI__builtin_reduce_or) {
1674*700637cbSDimitry Andric         (void)T::bitOr(Result, Elem, BitWidth, &Result);
1675*700637cbSDimitry Andric       } else if (ID == Builtin::BI__builtin_reduce_xor) {
1676*700637cbSDimitry Andric         (void)T::bitXor(Result, Elem, BitWidth, &Result);
1677*700637cbSDimitry Andric       } else if (ID == Builtin::BI__builtin_reduce_min) {
1678*700637cbSDimitry Andric         if (Elem < Result)
1679*700637cbSDimitry Andric           Result = Elem;
1680*700637cbSDimitry Andric       } else if (ID == Builtin::BI__builtin_reduce_max) {
1681*700637cbSDimitry Andric         if (Elem > Result)
1682*700637cbSDimitry Andric           Result = Elem;
1683*700637cbSDimitry Andric       } else {
1684*700637cbSDimitry Andric         llvm_unreachable("Unhandled vector reduce builtin");
1685*700637cbSDimitry Andric       }
1686*700637cbSDimitry Andric     }
1687*700637cbSDimitry Andric     pushInteger(S, Result.toAPSInt(), Call->getType());
1688*700637cbSDimitry Andric   });
1689*700637cbSDimitry Andric 
1690*700637cbSDimitry Andric   return true;
1691*700637cbSDimitry Andric }
1692*700637cbSDimitry Andric 
1693*700637cbSDimitry Andric /// Can be called with an integer or vector as the first and only parameter.
interp__builtin_elementwise_popcount(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,unsigned BuiltinID)1694*700637cbSDimitry Andric static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC,
1695*700637cbSDimitry Andric                                                  const InterpFrame *Frame,
1696*700637cbSDimitry Andric                                                  const CallExpr *Call,
1697*700637cbSDimitry Andric                                                  unsigned BuiltinID) {
1698*700637cbSDimitry Andric   assert(Call->getNumArgs() == 1);
1699*700637cbSDimitry Andric   if (Call->getArg(0)->getType()->isIntegerType()) {
1700*700637cbSDimitry Andric     PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
1701*700637cbSDimitry Andric     APSInt Val = popToAPSInt(S.Stk, ArgT);
1702*700637cbSDimitry Andric 
1703*700637cbSDimitry Andric     if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) {
1704*700637cbSDimitry Andric       pushInteger(S, Val.popcount(), Call->getType());
1705*700637cbSDimitry Andric     } else {
1706*700637cbSDimitry Andric       pushInteger(S, Val.reverseBits(), Call->getType());
1707*700637cbSDimitry Andric     }
1708*700637cbSDimitry Andric     return true;
1709*700637cbSDimitry Andric   }
1710*700637cbSDimitry Andric   // Otherwise, the argument must be a vector.
1711*700637cbSDimitry Andric   assert(Call->getArg(0)->getType()->isVectorType());
1712*700637cbSDimitry Andric   const Pointer &Arg = S.Stk.pop<Pointer>();
1713*700637cbSDimitry Andric   assert(Arg.getFieldDesc()->isPrimitiveArray());
1714*700637cbSDimitry Andric   const Pointer &Dst = S.Stk.peek<Pointer>();
1715*700637cbSDimitry Andric   assert(Dst.getFieldDesc()->isPrimitiveArray());
1716*700637cbSDimitry Andric   assert(Arg.getFieldDesc()->getNumElems() ==
1717*700637cbSDimitry Andric          Dst.getFieldDesc()->getNumElems());
1718*700637cbSDimitry Andric 
1719*700637cbSDimitry Andric   QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1720*700637cbSDimitry Andric   PrimType ElemT = *S.getContext().classify(ElemType);
1721*700637cbSDimitry Andric   unsigned NumElems = Arg.getNumElems();
1722*700637cbSDimitry Andric 
1723*700637cbSDimitry Andric   // FIXME: Reading from uninitialized vector elements?
1724*700637cbSDimitry Andric   for (unsigned I = 0; I != NumElems; ++I) {
1725*700637cbSDimitry Andric     INT_TYPE_SWITCH_NO_BOOL(ElemT, {
1726*700637cbSDimitry Andric       if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) {
1727*700637cbSDimitry Andric         Dst.atIndex(I).deref<T>() =
1728*700637cbSDimitry Andric             T::from(Arg.atIndex(I).deref<T>().toAPSInt().popcount());
1729*700637cbSDimitry Andric       } else {
1730*700637cbSDimitry Andric         Dst.atIndex(I).deref<T>() = T::from(
1731*700637cbSDimitry Andric             Arg.atIndex(I).deref<T>().toAPSInt().reverseBits().getZExtValue());
1732*700637cbSDimitry Andric       }
1733*700637cbSDimitry Andric       Dst.atIndex(I).initialize();
1734*700637cbSDimitry Andric     });
1735*700637cbSDimitry Andric   }
1736*700637cbSDimitry Andric 
1737*700637cbSDimitry Andric   return true;
1738*700637cbSDimitry Andric }
1739*700637cbSDimitry Andric 
interp__builtin_memcpy(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,unsigned ID)1740*700637cbSDimitry Andric static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
1741*700637cbSDimitry Andric                                    const InterpFrame *Frame,
1742*700637cbSDimitry Andric                                    const CallExpr *Call, unsigned ID) {
1743*700637cbSDimitry Andric   assert(Call->getNumArgs() == 3);
1744*700637cbSDimitry Andric   const ASTContext &ASTCtx = S.getASTContext();
1745*700637cbSDimitry Andric   PrimType SizeT = *S.getContext().classify(Call->getArg(2));
1746*700637cbSDimitry Andric   APSInt Size = popToAPSInt(S.Stk, SizeT);
1747*700637cbSDimitry Andric   const Pointer SrcPtr = S.Stk.pop<Pointer>();
1748*700637cbSDimitry Andric   const Pointer DestPtr = S.Stk.pop<Pointer>();
1749*700637cbSDimitry Andric 
1750*700637cbSDimitry Andric   assert(!Size.isSigned() && "memcpy and friends take an unsigned size");
1751*700637cbSDimitry Andric 
1752*700637cbSDimitry Andric   if (ID == Builtin::BImemcpy || ID == Builtin::BImemmove)
1753*700637cbSDimitry Andric     diagnoseNonConstexprBuiltin(S, OpPC, ID);
1754*700637cbSDimitry Andric 
1755*700637cbSDimitry Andric   bool Move =
1756*700637cbSDimitry Andric       (ID == Builtin::BI__builtin_memmove || ID == Builtin::BImemmove ||
1757*700637cbSDimitry Andric        ID == Builtin::BI__builtin_wmemmove || ID == Builtin::BIwmemmove);
1758*700637cbSDimitry Andric   bool WChar = ID == Builtin::BIwmemcpy || ID == Builtin::BIwmemmove ||
1759*700637cbSDimitry Andric                ID == Builtin::BI__builtin_wmemcpy ||
1760*700637cbSDimitry Andric                ID == Builtin::BI__builtin_wmemmove;
1761*700637cbSDimitry Andric 
1762*700637cbSDimitry Andric   // If the size is zero, we treat this as always being a valid no-op.
1763*700637cbSDimitry Andric   if (Size.isZero()) {
1764*700637cbSDimitry Andric     S.Stk.push<Pointer>(DestPtr);
1765*700637cbSDimitry Andric     return true;
1766*700637cbSDimitry Andric   }
1767*700637cbSDimitry Andric 
1768*700637cbSDimitry Andric   if (SrcPtr.isZero() || DestPtr.isZero()) {
1769*700637cbSDimitry Andric     Pointer DiagPtr = (SrcPtr.isZero() ? SrcPtr : DestPtr);
1770*700637cbSDimitry Andric     S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
1771*700637cbSDimitry Andric         << /*IsMove=*/Move << /*IsWchar=*/WChar << !SrcPtr.isZero()
1772*700637cbSDimitry Andric         << DiagPtr.toDiagnosticString(ASTCtx);
1773*700637cbSDimitry Andric     return false;
1774*700637cbSDimitry Andric   }
1775*700637cbSDimitry Andric 
1776*700637cbSDimitry Andric   // Diagnose integral src/dest pointers specially.
1777*700637cbSDimitry Andric   if (SrcPtr.isIntegralPointer() || DestPtr.isIntegralPointer()) {
1778*700637cbSDimitry Andric     std::string DiagVal = "(void *)";
1779*700637cbSDimitry Andric     DiagVal += SrcPtr.isIntegralPointer()
1780*700637cbSDimitry Andric                    ? std::to_string(SrcPtr.getIntegerRepresentation())
1781*700637cbSDimitry Andric                    : std::to_string(DestPtr.getIntegerRepresentation());
1782*700637cbSDimitry Andric     S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
1783*700637cbSDimitry Andric         << Move << WChar << DestPtr.isIntegralPointer() << DiagVal;
1784*700637cbSDimitry Andric     return false;
1785*700637cbSDimitry Andric   }
1786*700637cbSDimitry Andric 
1787*700637cbSDimitry Andric   // Can't read from dummy pointers.
1788*700637cbSDimitry Andric   if (DestPtr.isDummy() || SrcPtr.isDummy())
1789*700637cbSDimitry Andric     return false;
1790*700637cbSDimitry Andric 
1791*700637cbSDimitry Andric   QualType DestElemType = getElemType(DestPtr);
1792*700637cbSDimitry Andric   size_t RemainingDestElems;
1793*700637cbSDimitry Andric   if (DestPtr.getFieldDesc()->isArray()) {
1794*700637cbSDimitry Andric     RemainingDestElems = DestPtr.isUnknownSizeArray()
1795*700637cbSDimitry Andric                              ? 0
1796*700637cbSDimitry Andric                              : (DestPtr.getNumElems() - DestPtr.getIndex());
1797*700637cbSDimitry Andric   } else {
1798*700637cbSDimitry Andric     RemainingDestElems = 1;
1799*700637cbSDimitry Andric   }
1800*700637cbSDimitry Andric   unsigned DestElemSize = ASTCtx.getTypeSizeInChars(DestElemType).getQuantity();
1801*700637cbSDimitry Andric 
1802*700637cbSDimitry Andric   if (WChar) {
1803*700637cbSDimitry Andric     uint64_t WCharSize =
1804*700637cbSDimitry Andric         ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();
1805*700637cbSDimitry Andric     Size *= APSInt(APInt(Size.getBitWidth(), WCharSize, /*IsSigned=*/false),
1806*700637cbSDimitry Andric                    /*IsUnsigend=*/true);
1807*700637cbSDimitry Andric   }
1808*700637cbSDimitry Andric 
1809*700637cbSDimitry Andric   if (Size.urem(DestElemSize) != 0) {
1810*700637cbSDimitry Andric     S.FFDiag(S.Current->getSource(OpPC),
1811*700637cbSDimitry Andric              diag::note_constexpr_memcpy_unsupported)
1812*700637cbSDimitry Andric         << Move << WChar << 0 << DestElemType << Size << DestElemSize;
1813*700637cbSDimitry Andric     return false;
1814*700637cbSDimitry Andric   }
1815*700637cbSDimitry Andric 
1816*700637cbSDimitry Andric   QualType SrcElemType = getElemType(SrcPtr);
1817*700637cbSDimitry Andric   size_t RemainingSrcElems;
1818*700637cbSDimitry Andric   if (SrcPtr.getFieldDesc()->isArray()) {
1819*700637cbSDimitry Andric     RemainingSrcElems = SrcPtr.isUnknownSizeArray()
1820*700637cbSDimitry Andric                             ? 0
1821*700637cbSDimitry Andric                             : (SrcPtr.getNumElems() - SrcPtr.getIndex());
1822*700637cbSDimitry Andric   } else {
1823*700637cbSDimitry Andric     RemainingSrcElems = 1;
1824*700637cbSDimitry Andric   }
1825*700637cbSDimitry Andric   unsigned SrcElemSize = ASTCtx.getTypeSizeInChars(SrcElemType).getQuantity();
1826*700637cbSDimitry Andric 
1827*700637cbSDimitry Andric   if (!ASTCtx.hasSameUnqualifiedType(DestElemType, SrcElemType)) {
1828*700637cbSDimitry Andric     S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_type_pun)
1829*700637cbSDimitry Andric         << Move << SrcElemType << DestElemType;
1830*700637cbSDimitry Andric     return false;
1831*700637cbSDimitry Andric   }
1832*700637cbSDimitry Andric 
1833*700637cbSDimitry Andric   if (DestElemType->isIncompleteType() ||
1834*700637cbSDimitry Andric       DestPtr.getType()->isIncompleteType()) {
1835*700637cbSDimitry Andric     QualType DiagType =
1836*700637cbSDimitry Andric         DestElemType->isIncompleteType() ? DestElemType : DestPtr.getType();
1837*700637cbSDimitry Andric     S.FFDiag(S.Current->getSource(OpPC),
1838*700637cbSDimitry Andric              diag::note_constexpr_memcpy_incomplete_type)
1839*700637cbSDimitry Andric         << Move << DiagType;
1840*700637cbSDimitry Andric     return false;
1841*700637cbSDimitry Andric   }
1842*700637cbSDimitry Andric 
1843*700637cbSDimitry Andric   if (!DestElemType.isTriviallyCopyableType(ASTCtx)) {
1844*700637cbSDimitry Andric     S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_nontrivial)
1845*700637cbSDimitry Andric         << Move << DestElemType;
1846*700637cbSDimitry Andric     return false;
1847*700637cbSDimitry Andric   }
1848*700637cbSDimitry Andric 
1849*700637cbSDimitry Andric   // Check if we have enough elements to read from and write to.
1850*700637cbSDimitry Andric   size_t RemainingDestBytes = RemainingDestElems * DestElemSize;
1851*700637cbSDimitry Andric   size_t RemainingSrcBytes = RemainingSrcElems * SrcElemSize;
1852*700637cbSDimitry Andric   if (Size.ugt(RemainingDestBytes) || Size.ugt(RemainingSrcBytes)) {
1853*700637cbSDimitry Andric     APInt N = Size.udiv(DestElemSize);
1854*700637cbSDimitry Andric     S.FFDiag(S.Current->getSource(OpPC),
1855*700637cbSDimitry Andric              diag::note_constexpr_memcpy_unsupported)
1856*700637cbSDimitry Andric         << Move << WChar << (Size.ugt(RemainingSrcBytes) ? 1 : 2)
1857*700637cbSDimitry Andric         << DestElemType << toString(N, 10, /*Signed=*/false);
1858*700637cbSDimitry Andric     return false;
1859*700637cbSDimitry Andric   }
1860*700637cbSDimitry Andric 
1861*700637cbSDimitry Andric   // Check for overlapping memory regions.
1862*700637cbSDimitry Andric   if (!Move && Pointer::pointToSameBlock(SrcPtr, DestPtr)) {
1863*700637cbSDimitry Andric     // Remove base casts.
1864*700637cbSDimitry Andric     Pointer SrcP = SrcPtr;
1865*700637cbSDimitry Andric     while (SrcP.isBaseClass())
1866*700637cbSDimitry Andric       SrcP = SrcP.getBase();
1867*700637cbSDimitry Andric 
1868*700637cbSDimitry Andric     Pointer DestP = DestPtr;
1869*700637cbSDimitry Andric     while (DestP.isBaseClass())
1870*700637cbSDimitry Andric       DestP = DestP.getBase();
1871*700637cbSDimitry Andric 
1872*700637cbSDimitry Andric     unsigned SrcIndex = SrcP.expand().getIndex() * SrcP.elemSize();
1873*700637cbSDimitry Andric     unsigned DstIndex = DestP.expand().getIndex() * DestP.elemSize();
1874*700637cbSDimitry Andric     unsigned N = Size.getZExtValue();
1875*700637cbSDimitry Andric 
1876*700637cbSDimitry Andric     if ((SrcIndex <= DstIndex && (SrcIndex + N) > DstIndex) ||
1877*700637cbSDimitry Andric         (DstIndex <= SrcIndex && (DstIndex + N) > SrcIndex)) {
1878*700637cbSDimitry Andric       S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_overlap)
1879*700637cbSDimitry Andric           << /*IsWChar=*/false;
1880*700637cbSDimitry Andric       return false;
1881*700637cbSDimitry Andric     }
1882*700637cbSDimitry Andric   }
1883*700637cbSDimitry Andric 
1884*700637cbSDimitry Andric   assert(Size.getZExtValue() % DestElemSize == 0);
1885*700637cbSDimitry Andric   if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size.getZExtValue()).toBits()))
1886*700637cbSDimitry Andric     return false;
1887*700637cbSDimitry Andric 
1888*700637cbSDimitry Andric   S.Stk.push<Pointer>(DestPtr);
1889*700637cbSDimitry Andric   return true;
1890*700637cbSDimitry Andric }
1891*700637cbSDimitry Andric 
1892*700637cbSDimitry Andric /// Determine if T is a character type for which we guarantee that
1893*700637cbSDimitry Andric /// sizeof(T) == 1.
isOneByteCharacterType(QualType T)1894*700637cbSDimitry Andric static bool isOneByteCharacterType(QualType T) {
1895*700637cbSDimitry Andric   return T->isCharType() || T->isChar8Type();
1896*700637cbSDimitry Andric }
1897*700637cbSDimitry Andric 
interp__builtin_memcmp(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call,unsigned ID)1898*700637cbSDimitry Andric static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
1899*700637cbSDimitry Andric                                    const InterpFrame *Frame,
1900*700637cbSDimitry Andric                                    const CallExpr *Call, unsigned ID) {
1901*700637cbSDimitry Andric   assert(Call->getNumArgs() == 3);
1902*700637cbSDimitry Andric   PrimType SizeT = *S.getContext().classify(Call->getArg(2));
1903*700637cbSDimitry Andric   const APSInt &Size = popToAPSInt(S.Stk, SizeT);
1904*700637cbSDimitry Andric   const Pointer &PtrB = S.Stk.pop<Pointer>();
1905*700637cbSDimitry Andric   const Pointer &PtrA = S.Stk.pop<Pointer>();
1906*700637cbSDimitry Andric 
1907*700637cbSDimitry Andric   if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp ||
1908*700637cbSDimitry Andric       ID == Builtin::BIwmemcmp)
1909*700637cbSDimitry Andric     diagnoseNonConstexprBuiltin(S, OpPC, ID);
1910*700637cbSDimitry Andric 
1911*700637cbSDimitry Andric   if (Size.isZero()) {
1912*700637cbSDimitry Andric     pushInteger(S, 0, Call->getType());
1913*700637cbSDimitry Andric     return true;
1914*700637cbSDimitry Andric   }
1915*700637cbSDimitry Andric 
1916*700637cbSDimitry Andric   bool IsWide =
1917*700637cbSDimitry Andric       (ID == Builtin::BIwmemcmp || ID == Builtin::BI__builtin_wmemcmp);
1918*700637cbSDimitry Andric 
1919*700637cbSDimitry Andric   const ASTContext &ASTCtx = S.getASTContext();
1920*700637cbSDimitry Andric   QualType ElemTypeA = getElemType(PtrA);
1921*700637cbSDimitry Andric   QualType ElemTypeB = getElemType(PtrB);
1922*700637cbSDimitry Andric   // FIXME: This is an arbitrary limitation the current constant interpreter
1923*700637cbSDimitry Andric   // had. We could remove this.
1924*700637cbSDimitry Andric   if (!IsWide && (!isOneByteCharacterType(ElemTypeA) ||
1925*700637cbSDimitry Andric                   !isOneByteCharacterType(ElemTypeB))) {
1926*700637cbSDimitry Andric     S.FFDiag(S.Current->getSource(OpPC),
1927*700637cbSDimitry Andric              diag::note_constexpr_memcmp_unsupported)
1928*700637cbSDimitry Andric         << ASTCtx.BuiltinInfo.getQuotedName(ID) << PtrA.getType()
1929*700637cbSDimitry Andric         << PtrB.getType();
1930*700637cbSDimitry Andric     return false;
1931*700637cbSDimitry Andric   }
1932*700637cbSDimitry Andric 
1933*700637cbSDimitry Andric   if (PtrA.isDummy() || PtrB.isDummy())
1934*700637cbSDimitry Andric     return false;
1935*700637cbSDimitry Andric 
1936*700637cbSDimitry Andric   // Now, read both pointers to a buffer and compare those.
1937*700637cbSDimitry Andric   BitcastBuffer BufferA(
1938*700637cbSDimitry Andric       Bits(ASTCtx.getTypeSize(ElemTypeA) * PtrA.getNumElems()));
1939*700637cbSDimitry Andric   readPointerToBuffer(S.getContext(), PtrA, BufferA, false);
1940*700637cbSDimitry Andric   // FIXME: The swapping here is UNDOING something we do when reading the
1941*700637cbSDimitry Andric   // data into the buffer.
1942*700637cbSDimitry Andric   if (ASTCtx.getTargetInfo().isBigEndian())
1943*700637cbSDimitry Andric     swapBytes(BufferA.Data.get(), BufferA.byteSize().getQuantity());
1944*700637cbSDimitry Andric 
1945*700637cbSDimitry Andric   BitcastBuffer BufferB(
1946*700637cbSDimitry Andric       Bits(ASTCtx.getTypeSize(ElemTypeB) * PtrB.getNumElems()));
1947*700637cbSDimitry Andric   readPointerToBuffer(S.getContext(), PtrB, BufferB, false);
1948*700637cbSDimitry Andric   // FIXME: The swapping here is UNDOING something we do when reading the
1949*700637cbSDimitry Andric   // data into the buffer.
1950*700637cbSDimitry Andric   if (ASTCtx.getTargetInfo().isBigEndian())
1951*700637cbSDimitry Andric     swapBytes(BufferB.Data.get(), BufferB.byteSize().getQuantity());
1952*700637cbSDimitry Andric 
1953*700637cbSDimitry Andric   size_t MinBufferSize = std::min(BufferA.byteSize().getQuantity(),
1954*700637cbSDimitry Andric                                   BufferB.byteSize().getQuantity());
1955*700637cbSDimitry Andric 
1956*700637cbSDimitry Andric   unsigned ElemSize = 1;
1957*700637cbSDimitry Andric   if (IsWide)
1958*700637cbSDimitry Andric     ElemSize = ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();
1959*700637cbSDimitry Andric   // The Size given for the wide variants is in wide-char units. Convert it
1960*700637cbSDimitry Andric   // to bytes.
1961*700637cbSDimitry Andric   size_t ByteSize = Size.getZExtValue() * ElemSize;
1962*700637cbSDimitry Andric   size_t CmpSize = std::min(MinBufferSize, ByteSize);
1963*700637cbSDimitry Andric 
1964*700637cbSDimitry Andric   for (size_t I = 0; I != CmpSize; I += ElemSize) {
1965*700637cbSDimitry Andric     if (IsWide) {
1966*700637cbSDimitry Andric       INT_TYPE_SWITCH(*S.getContext().classify(ASTCtx.getWCharType()), {
1967*700637cbSDimitry Andric         T A = *reinterpret_cast<T *>(BufferA.Data.get() + I);
1968*700637cbSDimitry Andric         T B = *reinterpret_cast<T *>(BufferB.Data.get() + I);
1969*700637cbSDimitry Andric         if (A < B) {
1970*700637cbSDimitry Andric           pushInteger(S, -1, Call->getType());
1971*700637cbSDimitry Andric           return true;
1972*700637cbSDimitry Andric         } else if (A > B) {
1973*700637cbSDimitry Andric           pushInteger(S, 1, Call->getType());
1974*700637cbSDimitry Andric           return true;
1975*700637cbSDimitry Andric         }
1976*700637cbSDimitry Andric       });
1977*700637cbSDimitry Andric     } else {
1978*700637cbSDimitry Andric       std::byte A = BufferA.Data[I];
1979*700637cbSDimitry Andric       std::byte B = BufferB.Data[I];
1980*700637cbSDimitry Andric 
1981*700637cbSDimitry Andric       if (A < B) {
1982*700637cbSDimitry Andric         pushInteger(S, -1, Call->getType());
1983*700637cbSDimitry Andric         return true;
1984*700637cbSDimitry Andric       } else if (A > B) {
1985*700637cbSDimitry Andric         pushInteger(S, 1, Call->getType());
1986*700637cbSDimitry Andric         return true;
1987*700637cbSDimitry Andric       }
1988*700637cbSDimitry Andric     }
1989*700637cbSDimitry Andric   }
1990*700637cbSDimitry Andric 
1991*700637cbSDimitry Andric   // We compared CmpSize bytes above. If the limiting factor was the Size
1992*700637cbSDimitry Andric   // passed, we're done and the result is equality (0).
1993*700637cbSDimitry Andric   if (ByteSize <= CmpSize) {
1994*700637cbSDimitry Andric     pushInteger(S, 0, Call->getType());
1995*700637cbSDimitry Andric     return true;
1996*700637cbSDimitry Andric   }
1997*700637cbSDimitry Andric 
1998*700637cbSDimitry Andric   // However, if we read all the available bytes but were instructed to read
1999*700637cbSDimitry Andric   // even more, diagnose this as a "read of dereferenced one-past-the-end
2000*700637cbSDimitry Andric   // pointer". This is what would happen if we called CheckLoad() on every array
2001*700637cbSDimitry Andric   // element.
2002*700637cbSDimitry Andric   S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)
2003*700637cbSDimitry Andric       << AK_Read << S.Current->getRange(OpPC);
2004*700637cbSDimitry Andric   return false;
2005*700637cbSDimitry Andric }
2006*700637cbSDimitry Andric 
2007*700637cbSDimitry Andric // __builtin_memchr(ptr, int, int)
2008*700637cbSDimitry Andric // __builtin_strchr(ptr, int)
interp__builtin_memchr(InterpState & S,CodePtr OpPC,const CallExpr * Call,unsigned ID)2009*700637cbSDimitry Andric static bool interp__builtin_memchr(InterpState &S, CodePtr OpPC,
2010*700637cbSDimitry Andric                                    const CallExpr *Call, unsigned ID) {
2011*700637cbSDimitry Andric   if (ID == Builtin::BImemchr || ID == Builtin::BIwcschr ||
2012*700637cbSDimitry Andric       ID == Builtin::BIstrchr || ID == Builtin::BIwmemchr)
2013*700637cbSDimitry Andric     diagnoseNonConstexprBuiltin(S, OpPC, ID);
2014*700637cbSDimitry Andric 
2015*700637cbSDimitry Andric   std::optional<APSInt> MaxLength;
2016*700637cbSDimitry Andric   PrimType DesiredT = *S.getContext().classify(Call->getArg(1));
2017*700637cbSDimitry Andric   if (Call->getNumArgs() == 3) {
2018*700637cbSDimitry Andric     PrimType MaxT = *S.getContext().classify(Call->getArg(2));
2019*700637cbSDimitry Andric     MaxLength = popToAPSInt(S.Stk, MaxT);
2020*700637cbSDimitry Andric   }
2021*700637cbSDimitry Andric   APSInt Desired = popToAPSInt(S.Stk, DesiredT);
2022*700637cbSDimitry Andric   const Pointer &Ptr = S.Stk.pop<Pointer>();
2023*700637cbSDimitry Andric 
2024*700637cbSDimitry Andric   if (MaxLength && MaxLength->isZero()) {
2025*700637cbSDimitry Andric     S.Stk.push<Pointer>();
2026*700637cbSDimitry Andric     return true;
2027*700637cbSDimitry Andric   }
2028*700637cbSDimitry Andric 
2029*700637cbSDimitry Andric   if (Ptr.isDummy())
2030*700637cbSDimitry Andric     return false;
2031*700637cbSDimitry Andric 
2032*700637cbSDimitry Andric   // Null is only okay if the given size is 0.
2033*700637cbSDimitry Andric   if (Ptr.isZero()) {
2034*700637cbSDimitry Andric     S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)
2035*700637cbSDimitry Andric         << AK_Read;
2036*700637cbSDimitry Andric     return false;
2037*700637cbSDimitry Andric   }
2038*700637cbSDimitry Andric 
2039*700637cbSDimitry Andric   QualType ElemTy = Ptr.getFieldDesc()->isArray()
2040*700637cbSDimitry Andric                         ? Ptr.getFieldDesc()->getElemQualType()
2041*700637cbSDimitry Andric                         : Ptr.getFieldDesc()->getType();
2042*700637cbSDimitry Andric   bool IsRawByte = ID == Builtin::BImemchr || ID == Builtin::BI__builtin_memchr;
2043*700637cbSDimitry Andric 
2044*700637cbSDimitry Andric   // Give up on byte-oriented matching against multibyte elements.
2045*700637cbSDimitry Andric   if (IsRawByte && !isOneByteCharacterType(ElemTy)) {
2046*700637cbSDimitry Andric     S.FFDiag(S.Current->getSource(OpPC),
2047*700637cbSDimitry Andric              diag::note_constexpr_memchr_unsupported)
2048*700637cbSDimitry Andric         << S.getASTContext().BuiltinInfo.getQuotedName(ID) << ElemTy;
2049*700637cbSDimitry Andric     return false;
2050*700637cbSDimitry Andric   }
2051*700637cbSDimitry Andric 
2052*700637cbSDimitry Andric   if (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr) {
2053*700637cbSDimitry Andric     // strchr compares directly to the passed integer, and therefore
2054*700637cbSDimitry Andric     // always fails if given an int that is not a char.
2055*700637cbSDimitry Andric     if (Desired !=
2056*700637cbSDimitry Andric         Desired.trunc(S.getASTContext().getCharWidth()).getSExtValue()) {
2057*700637cbSDimitry Andric       S.Stk.push<Pointer>();
2058*700637cbSDimitry Andric       return true;
2059*700637cbSDimitry Andric     }
2060*700637cbSDimitry Andric   }
2061*700637cbSDimitry Andric 
2062*700637cbSDimitry Andric   uint64_t DesiredVal;
2063*700637cbSDimitry Andric   if (ID == Builtin::BIwmemchr || ID == Builtin::BI__builtin_wmemchr ||
2064*700637cbSDimitry Andric       ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr) {
2065*700637cbSDimitry Andric     // wcschr and wmemchr are given a wchar_t to look for. Just use it.
2066*700637cbSDimitry Andric     DesiredVal = Desired.getZExtValue();
2067*700637cbSDimitry Andric   } else {
2068*700637cbSDimitry Andric     DesiredVal = Desired.trunc(S.getASTContext().getCharWidth()).getZExtValue();
2069*700637cbSDimitry Andric   }
2070*700637cbSDimitry Andric 
2071*700637cbSDimitry Andric   bool StopAtZero =
2072*700637cbSDimitry Andric       (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr ||
2073*700637cbSDimitry Andric        ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr);
2074*700637cbSDimitry Andric 
2075*700637cbSDimitry Andric   PrimType ElemT =
2076*700637cbSDimitry Andric       IsRawByte ? PT_Sint8 : *S.getContext().classify(getElemType(Ptr));
2077*700637cbSDimitry Andric 
2078*700637cbSDimitry Andric   size_t Index = Ptr.getIndex();
2079*700637cbSDimitry Andric   size_t Step = 0;
2080*700637cbSDimitry Andric   for (;;) {
2081*700637cbSDimitry Andric     const Pointer &ElemPtr =
2082*700637cbSDimitry Andric         (Index + Step) > 0 ? Ptr.atIndex(Index + Step) : Ptr;
2083*700637cbSDimitry Andric 
2084*700637cbSDimitry Andric     if (!CheckLoad(S, OpPC, ElemPtr))
2085*700637cbSDimitry Andric       return false;
2086*700637cbSDimitry Andric 
2087*700637cbSDimitry Andric     uint64_t V;
2088*700637cbSDimitry Andric     INT_TYPE_SWITCH_NO_BOOL(
2089*700637cbSDimitry Andric         ElemT, { V = static_cast<uint64_t>(ElemPtr.deref<T>().toUnsigned()); });
2090*700637cbSDimitry Andric 
2091*700637cbSDimitry Andric     if (V == DesiredVal) {
2092*700637cbSDimitry Andric       S.Stk.push<Pointer>(ElemPtr);
2093*700637cbSDimitry Andric       return true;
2094*700637cbSDimitry Andric     }
2095*700637cbSDimitry Andric 
2096*700637cbSDimitry Andric     if (StopAtZero && V == 0)
2097*700637cbSDimitry Andric       break;
2098*700637cbSDimitry Andric 
2099*700637cbSDimitry Andric     ++Step;
2100*700637cbSDimitry Andric     if (MaxLength && Step == MaxLength->getZExtValue())
2101*700637cbSDimitry Andric       break;
2102*700637cbSDimitry Andric   }
2103*700637cbSDimitry Andric 
2104*700637cbSDimitry Andric   S.Stk.push<Pointer>();
2105*700637cbSDimitry Andric   return true;
2106*700637cbSDimitry Andric }
2107*700637cbSDimitry Andric 
computeFullDescSize(const ASTContext & ASTCtx,const Descriptor * Desc)2108*700637cbSDimitry Andric static unsigned computeFullDescSize(const ASTContext &ASTCtx,
2109*700637cbSDimitry Andric                                     const Descriptor *Desc) {
2110*700637cbSDimitry Andric 
2111*700637cbSDimitry Andric   if (Desc->isPrimitive())
2112*700637cbSDimitry Andric     return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();
2113*700637cbSDimitry Andric 
2114*700637cbSDimitry Andric   if (Desc->isArray())
2115*700637cbSDimitry Andric     return ASTCtx.getTypeSizeInChars(Desc->getElemQualType()).getQuantity() *
2116*700637cbSDimitry Andric            Desc->getNumElems();
2117*700637cbSDimitry Andric 
2118*700637cbSDimitry Andric   if (Desc->isRecord())
2119*700637cbSDimitry Andric     return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();
2120*700637cbSDimitry Andric 
2121*700637cbSDimitry Andric   llvm_unreachable("Unhandled descriptor type");
2122*700637cbSDimitry Andric   return 0;
2123*700637cbSDimitry Andric }
2124*700637cbSDimitry Andric 
computePointerOffset(const ASTContext & ASTCtx,const Pointer & Ptr)2125*700637cbSDimitry Andric static unsigned computePointerOffset(const ASTContext &ASTCtx,
2126*700637cbSDimitry Andric                                      const Pointer &Ptr) {
2127*700637cbSDimitry Andric   unsigned Result = 0;
2128*700637cbSDimitry Andric 
2129*700637cbSDimitry Andric   Pointer P = Ptr;
2130*700637cbSDimitry Andric   while (P.isArrayElement() || P.isField()) {
2131*700637cbSDimitry Andric     P = P.expand();
2132*700637cbSDimitry Andric     const Descriptor *D = P.getFieldDesc();
2133*700637cbSDimitry Andric 
2134*700637cbSDimitry Andric     if (P.isArrayElement()) {
2135*700637cbSDimitry Andric       unsigned ElemSize =
2136*700637cbSDimitry Andric           ASTCtx.getTypeSizeInChars(D->getElemQualType()).getQuantity();
2137*700637cbSDimitry Andric       if (P.isOnePastEnd())
2138*700637cbSDimitry Andric         Result += ElemSize * P.getNumElems();
2139*700637cbSDimitry Andric       else
2140*700637cbSDimitry Andric         Result += ElemSize * P.getIndex();
2141*700637cbSDimitry Andric       P = P.expand().getArray();
2142*700637cbSDimitry Andric     } else if (P.isBaseClass()) {
2143*700637cbSDimitry Andric 
2144*700637cbSDimitry Andric       const auto *RD = cast<CXXRecordDecl>(D->asDecl());
2145*700637cbSDimitry Andric       bool IsVirtual = Ptr.isVirtualBaseClass();
2146*700637cbSDimitry Andric       P = P.getBase();
2147*700637cbSDimitry Andric       const Record *BaseRecord = P.getRecord();
2148*700637cbSDimitry Andric 
2149*700637cbSDimitry Andric       const ASTRecordLayout &Layout =
2150*700637cbSDimitry Andric           ASTCtx.getASTRecordLayout(cast<CXXRecordDecl>(BaseRecord->getDecl()));
2151*700637cbSDimitry Andric       if (IsVirtual)
2152*700637cbSDimitry Andric         Result += Layout.getVBaseClassOffset(RD).getQuantity();
2153*700637cbSDimitry Andric       else
2154*700637cbSDimitry Andric         Result += Layout.getBaseClassOffset(RD).getQuantity();
2155*700637cbSDimitry Andric     } else if (P.isField()) {
2156*700637cbSDimitry Andric       const FieldDecl *FD = P.getField();
2157*700637cbSDimitry Andric       const ASTRecordLayout &Layout =
2158*700637cbSDimitry Andric           ASTCtx.getASTRecordLayout(FD->getParent());
2159*700637cbSDimitry Andric       unsigned FieldIndex = FD->getFieldIndex();
2160*700637cbSDimitry Andric       uint64_t FieldOffset =
2161*700637cbSDimitry Andric           ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex))
2162*700637cbSDimitry Andric               .getQuantity();
2163*700637cbSDimitry Andric       Result += FieldOffset;
2164*700637cbSDimitry Andric       P = P.getBase();
2165*700637cbSDimitry Andric     } else
2166*700637cbSDimitry Andric       llvm_unreachable("Unhandled descriptor type");
2167*700637cbSDimitry Andric   }
2168*700637cbSDimitry Andric 
2169*700637cbSDimitry Andric   return Result;
2170*700637cbSDimitry Andric }
2171*700637cbSDimitry Andric 
interp__builtin_object_size(InterpState & S,CodePtr OpPC,const InterpFrame * Frame,const CallExpr * Call)2172*700637cbSDimitry Andric static bool interp__builtin_object_size(InterpState &S, CodePtr OpPC,
2173*700637cbSDimitry Andric                                         const InterpFrame *Frame,
2174*700637cbSDimitry Andric                                         const CallExpr *Call) {
2175*700637cbSDimitry Andric   PrimType KindT = *S.getContext().classify(Call->getArg(1));
2176*700637cbSDimitry Andric   [[maybe_unused]] unsigned Kind = popToAPSInt(S.Stk, KindT).getZExtValue();
2177*700637cbSDimitry Andric 
2178*700637cbSDimitry Andric   assert(Kind <= 3 && "unexpected kind");
2179*700637cbSDimitry Andric 
2180*700637cbSDimitry Andric   const Pointer &Ptr = S.Stk.pop<Pointer>();
2181*700637cbSDimitry Andric 
2182*700637cbSDimitry Andric   if (Ptr.isZero())
2183*700637cbSDimitry Andric     return false;
2184*700637cbSDimitry Andric 
2185*700637cbSDimitry Andric   const Descriptor *DeclDesc = Ptr.getDeclDesc();
2186*700637cbSDimitry Andric   if (!DeclDesc)
2187*700637cbSDimitry Andric     return false;
2188*700637cbSDimitry Andric 
2189*700637cbSDimitry Andric   const ASTContext &ASTCtx = S.getASTContext();
2190*700637cbSDimitry Andric 
2191*700637cbSDimitry Andric   unsigned ByteOffset = computePointerOffset(ASTCtx, Ptr);
2192*700637cbSDimitry Andric   unsigned FullSize = computeFullDescSize(ASTCtx, DeclDesc);
2193*700637cbSDimitry Andric 
2194*700637cbSDimitry Andric   pushInteger(S, FullSize - ByteOffset, Call->getType());
2195*700637cbSDimitry Andric 
2196*700637cbSDimitry Andric   return true;
2197*700637cbSDimitry Andric }
2198*700637cbSDimitry Andric 
interp__builtin_is_within_lifetime(InterpState & S,CodePtr OpPC,const CallExpr * Call)2199*700637cbSDimitry Andric static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,
2200*700637cbSDimitry Andric                                                const CallExpr *Call) {
2201*700637cbSDimitry Andric 
2202*700637cbSDimitry Andric   if (!S.inConstantContext())
2203*700637cbSDimitry Andric     return false;
2204*700637cbSDimitry Andric 
2205*700637cbSDimitry Andric   const Pointer &Ptr = S.Stk.pop<Pointer>();
2206*700637cbSDimitry Andric 
2207*700637cbSDimitry Andric   auto Error = [&](int Diag) {
2208*700637cbSDimitry Andric     bool CalledFromStd = false;
2209*700637cbSDimitry Andric     const auto *Callee = S.Current->getCallee();
2210*700637cbSDimitry Andric     if (Callee && Callee->isInStdNamespace()) {
2211*700637cbSDimitry Andric       const IdentifierInfo *Identifier = Callee->getIdentifier();
2212*700637cbSDimitry Andric       CalledFromStd = Identifier && Identifier->isStr("is_within_lifetime");
2213*700637cbSDimitry Andric     }
2214*700637cbSDimitry Andric     S.CCEDiag(CalledFromStd
2215*700637cbSDimitry Andric                   ? S.Current->Caller->getSource(S.Current->getRetPC())
2216*700637cbSDimitry Andric                   : S.Current->getSource(OpPC),
2217*700637cbSDimitry Andric               diag::err_invalid_is_within_lifetime)
2218*700637cbSDimitry Andric         << (CalledFromStd ? "std::is_within_lifetime"
2219*700637cbSDimitry Andric                           : "__builtin_is_within_lifetime")
2220*700637cbSDimitry Andric         << Diag;
2221*700637cbSDimitry Andric     return false;
2222*700637cbSDimitry Andric   };
2223*700637cbSDimitry Andric 
2224*700637cbSDimitry Andric   if (Ptr.isZero())
2225*700637cbSDimitry Andric     return Error(0);
2226*700637cbSDimitry Andric   if (Ptr.isOnePastEnd())
2227*700637cbSDimitry Andric     return Error(1);
2228*700637cbSDimitry Andric 
2229*700637cbSDimitry Andric   bool Result = Ptr.getLifetime() != Lifetime::Ended;
2230*700637cbSDimitry Andric   if (!Ptr.isActive()) {
2231*700637cbSDimitry Andric     Result = false;
2232*700637cbSDimitry Andric   } else {
2233*700637cbSDimitry Andric     if (!CheckLive(S, OpPC, Ptr, AK_Read))
2234*700637cbSDimitry Andric       return false;
2235*700637cbSDimitry Andric     if (!CheckMutable(S, OpPC, Ptr))
2236*700637cbSDimitry Andric       return false;
2237*700637cbSDimitry Andric     if (!CheckDummy(S, OpPC, Ptr, AK_Read))
2238*700637cbSDimitry Andric       return false;
2239*700637cbSDimitry Andric   }
2240*700637cbSDimitry Andric 
2241*700637cbSDimitry Andric   // Check if we're currently running an initializer.
2242*700637cbSDimitry Andric   for (InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) {
2243*700637cbSDimitry Andric     if (const Function *F = Frame->getFunction();
2244*700637cbSDimitry Andric         F && F->isConstructor() && Frame->getThis().block() == Ptr.block()) {
2245*700637cbSDimitry Andric       return Error(2);
2246*700637cbSDimitry Andric     }
2247*700637cbSDimitry Andric   }
2248*700637cbSDimitry Andric   if (S.EvaluatingDecl && Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl)
2249*700637cbSDimitry Andric     return Error(2);
2250*700637cbSDimitry Andric 
2251*700637cbSDimitry Andric   pushInteger(S, Result, Call->getType());
2252*700637cbSDimitry Andric   return true;
2253*700637cbSDimitry Andric }
2254*700637cbSDimitry Andric 
interp__builtin_elementwise_sat(InterpState & S,CodePtr OpPC,const CallExpr * Call,unsigned BuiltinID)2255*700637cbSDimitry Andric static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC,
2256*700637cbSDimitry Andric                                             const CallExpr *Call,
2257*700637cbSDimitry Andric                                             unsigned BuiltinID) {
2258*700637cbSDimitry Andric   Call->dumpColor();
2259*700637cbSDimitry Andric   assert(Call->getNumArgs() == 2);
2260*700637cbSDimitry Andric 
2261*700637cbSDimitry Andric   // Single integer case.
2262*700637cbSDimitry Andric   if (!Call->getArg(0)->getType()->isVectorType()) {
2263*700637cbSDimitry Andric     assert(!Call->getArg(1)->getType()->isVectorType());
2264*700637cbSDimitry Andric     APSInt RHS = popToAPSInt(
2265*700637cbSDimitry Andric         S.Stk, *S.getContext().classify(Call->getArg(1)->getType()));
2266*700637cbSDimitry Andric     APSInt LHS = popToAPSInt(
2267*700637cbSDimitry Andric         S.Stk, *S.getContext().classify(Call->getArg(0)->getType()));
2268*700637cbSDimitry Andric     APInt Result;
2269*700637cbSDimitry Andric     if (BuiltinID == Builtin::BI__builtin_elementwise_add_sat) {
2270*700637cbSDimitry Andric       Result = LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS);
2271*700637cbSDimitry Andric     } else if (BuiltinID == Builtin::BI__builtin_elementwise_sub_sat) {
2272*700637cbSDimitry Andric       Result = LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS);
2273*700637cbSDimitry Andric     } else {
2274*700637cbSDimitry Andric       llvm_unreachable("Wrong builtin ID");
2275*700637cbSDimitry Andric     }
2276*700637cbSDimitry Andric 
2277*700637cbSDimitry Andric     pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType());
2278*700637cbSDimitry Andric     return true;
2279*700637cbSDimitry Andric   }
2280*700637cbSDimitry Andric 
2281*700637cbSDimitry Andric   // Vector case.
2282*700637cbSDimitry Andric   assert(Call->getArg(0)->getType()->isVectorType() &&
2283*700637cbSDimitry Andric          Call->getArg(1)->getType()->isVectorType());
2284*700637cbSDimitry Andric   const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2285*700637cbSDimitry Andric   assert(VT->getElementType() ==
2286*700637cbSDimitry Andric          Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());
2287*700637cbSDimitry Andric   assert(VT->getNumElements() ==
2288*700637cbSDimitry Andric          Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());
2289*700637cbSDimitry Andric   assert(VT->getElementType()->isIntegralOrEnumerationType());
2290*700637cbSDimitry Andric 
2291*700637cbSDimitry Andric   const Pointer &RHS = S.Stk.pop<Pointer>();
2292*700637cbSDimitry Andric   const Pointer &LHS = S.Stk.pop<Pointer>();
2293*700637cbSDimitry Andric   const Pointer &Dst = S.Stk.peek<Pointer>();
2294*700637cbSDimitry Andric   PrimType ElemT = *S.getContext().classify(VT->getElementType());
2295*700637cbSDimitry Andric   unsigned NumElems = VT->getNumElements();
2296*700637cbSDimitry Andric   for (unsigned I = 0; I != NumElems; ++I) {
2297*700637cbSDimitry Andric     APSInt Elem1;
2298*700637cbSDimitry Andric     APSInt Elem2;
2299*700637cbSDimitry Andric     INT_TYPE_SWITCH_NO_BOOL(ElemT, {
2300*700637cbSDimitry Andric       Elem1 = LHS.atIndex(I).deref<T>().toAPSInt();
2301*700637cbSDimitry Andric       Elem2 = RHS.atIndex(I).deref<T>().toAPSInt();
2302*700637cbSDimitry Andric     });
2303*700637cbSDimitry Andric 
2304*700637cbSDimitry Andric     APSInt Result;
2305*700637cbSDimitry Andric     if (BuiltinID == Builtin::BI__builtin_elementwise_add_sat) {
2306*700637cbSDimitry Andric       Result = APSInt(Elem1.isSigned() ? Elem1.sadd_sat(Elem2)
2307*700637cbSDimitry Andric                                        : Elem1.uadd_sat(Elem2),
2308*700637cbSDimitry Andric                       Call->getType()->isUnsignedIntegerOrEnumerationType());
2309*700637cbSDimitry Andric     } else if (BuiltinID == Builtin::BI__builtin_elementwise_sub_sat) {
2310*700637cbSDimitry Andric       Result = APSInt(Elem1.isSigned() ? Elem1.ssub_sat(Elem2)
2311*700637cbSDimitry Andric                                        : Elem1.usub_sat(Elem2),
2312*700637cbSDimitry Andric                       Call->getType()->isUnsignedIntegerOrEnumerationType());
2313*700637cbSDimitry Andric     } else {
2314*700637cbSDimitry Andric       llvm_unreachable("Wrong builtin ID");
2315*700637cbSDimitry Andric     }
2316*700637cbSDimitry Andric 
2317*700637cbSDimitry Andric     INT_TYPE_SWITCH_NO_BOOL(ElemT, {
2318*700637cbSDimitry Andric       const Pointer &E = Dst.atIndex(I);
2319*700637cbSDimitry Andric       E.deref<T>() = static_cast<T>(Result);
2320*700637cbSDimitry Andric       E.initialize();
2321*700637cbSDimitry Andric     });
2322*700637cbSDimitry Andric   }
2323*700637cbSDimitry Andric 
2324*700637cbSDimitry Andric   return true;
2325*700637cbSDimitry Andric }
2326*700637cbSDimitry Andric 
InterpretBuiltin(InterpState & S,CodePtr OpPC,const CallExpr * Call,uint32_t BuiltinID)2327*700637cbSDimitry Andric bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
2328*700637cbSDimitry Andric                       uint32_t BuiltinID) {
2329*700637cbSDimitry Andric   if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID))
2330*700637cbSDimitry Andric     return Invalid(S, OpPC);
2331*700637cbSDimitry Andric 
2332*700637cbSDimitry Andric   const InterpFrame *Frame = S.Current;
2333*700637cbSDimitry Andric   switch (BuiltinID) {
2334*700637cbSDimitry Andric   case Builtin::BI__builtin_is_constant_evaluated:
2335*700637cbSDimitry Andric     return interp__builtin_is_constant_evaluated(S, OpPC, Frame, Call);
2336*700637cbSDimitry Andric 
2337*700637cbSDimitry Andric   case Builtin::BI__builtin_assume:
2338*700637cbSDimitry Andric   case Builtin::BI__assume:
2339*700637cbSDimitry Andric     return interp__builtin_assume(S, OpPC, Frame, Call);
2340*700637cbSDimitry Andric 
2341*700637cbSDimitry Andric   case Builtin::BI__builtin_strcmp:
2342*700637cbSDimitry Andric   case Builtin::BIstrcmp:
2343*700637cbSDimitry Andric   case Builtin::BI__builtin_strncmp:
2344*700637cbSDimitry Andric   case Builtin::BIstrncmp:
2345*700637cbSDimitry Andric   case Builtin::BI__builtin_wcsncmp:
2346*700637cbSDimitry Andric   case Builtin::BIwcsncmp:
2347*700637cbSDimitry Andric   case Builtin::BI__builtin_wcscmp:
2348*700637cbSDimitry Andric   case Builtin::BIwcscmp:
2349*700637cbSDimitry Andric     return interp__builtin_strcmp(S, OpPC, Frame, Call, BuiltinID);
2350*700637cbSDimitry Andric 
2351*700637cbSDimitry Andric   case Builtin::BI__builtin_strlen:
2352*700637cbSDimitry Andric   case Builtin::BIstrlen:
2353*700637cbSDimitry Andric   case Builtin::BI__builtin_wcslen:
2354*700637cbSDimitry Andric   case Builtin::BIwcslen:
2355*700637cbSDimitry Andric     return interp__builtin_strlen(S, OpPC, Frame, Call, BuiltinID);
2356*700637cbSDimitry Andric 
2357*700637cbSDimitry Andric   case Builtin::BI__builtin_nan:
2358*700637cbSDimitry Andric   case Builtin::BI__builtin_nanf:
2359*700637cbSDimitry Andric   case Builtin::BI__builtin_nanl:
2360*700637cbSDimitry Andric   case Builtin::BI__builtin_nanf16:
2361*700637cbSDimitry Andric   case Builtin::BI__builtin_nanf128:
2362*700637cbSDimitry Andric     return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/false);
2363*700637cbSDimitry Andric 
2364*700637cbSDimitry Andric   case Builtin::BI__builtin_nans:
2365*700637cbSDimitry Andric   case Builtin::BI__builtin_nansf:
2366*700637cbSDimitry Andric   case Builtin::BI__builtin_nansl:
2367*700637cbSDimitry Andric   case Builtin::BI__builtin_nansf16:
2368*700637cbSDimitry Andric   case Builtin::BI__builtin_nansf128:
2369*700637cbSDimitry Andric     return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/true);
2370*700637cbSDimitry Andric 
2371*700637cbSDimitry Andric   case Builtin::BI__builtin_huge_val:
2372*700637cbSDimitry Andric   case Builtin::BI__builtin_huge_valf:
2373*700637cbSDimitry Andric   case Builtin::BI__builtin_huge_vall:
2374*700637cbSDimitry Andric   case Builtin::BI__builtin_huge_valf16:
2375*700637cbSDimitry Andric   case Builtin::BI__builtin_huge_valf128:
2376*700637cbSDimitry Andric   case Builtin::BI__builtin_inf:
2377*700637cbSDimitry Andric   case Builtin::BI__builtin_inff:
2378*700637cbSDimitry Andric   case Builtin::BI__builtin_infl:
2379*700637cbSDimitry Andric   case Builtin::BI__builtin_inff16:
2380*700637cbSDimitry Andric   case Builtin::BI__builtin_inff128:
2381*700637cbSDimitry Andric     return interp__builtin_inf(S, OpPC, Frame, Call);
2382*700637cbSDimitry Andric 
2383*700637cbSDimitry Andric   case Builtin::BI__builtin_copysign:
2384*700637cbSDimitry Andric   case Builtin::BI__builtin_copysignf:
2385*700637cbSDimitry Andric   case Builtin::BI__builtin_copysignl:
2386*700637cbSDimitry Andric   case Builtin::BI__builtin_copysignf128:
2387*700637cbSDimitry Andric     return interp__builtin_copysign(S, OpPC, Frame);
2388*700637cbSDimitry Andric 
2389*700637cbSDimitry Andric   case Builtin::BI__builtin_fmin:
2390*700637cbSDimitry Andric   case Builtin::BI__builtin_fminf:
2391*700637cbSDimitry Andric   case Builtin::BI__builtin_fminl:
2392*700637cbSDimitry Andric   case Builtin::BI__builtin_fminf16:
2393*700637cbSDimitry Andric   case Builtin::BI__builtin_fminf128:
2394*700637cbSDimitry Andric     return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/false);
2395*700637cbSDimitry Andric 
2396*700637cbSDimitry Andric   case Builtin::BI__builtin_fminimum_num:
2397*700637cbSDimitry Andric   case Builtin::BI__builtin_fminimum_numf:
2398*700637cbSDimitry Andric   case Builtin::BI__builtin_fminimum_numl:
2399*700637cbSDimitry Andric   case Builtin::BI__builtin_fminimum_numf16:
2400*700637cbSDimitry Andric   case Builtin::BI__builtin_fminimum_numf128:
2401*700637cbSDimitry Andric     return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/true);
2402*700637cbSDimitry Andric 
2403*700637cbSDimitry Andric   case Builtin::BI__builtin_fmax:
2404*700637cbSDimitry Andric   case Builtin::BI__builtin_fmaxf:
2405*700637cbSDimitry Andric   case Builtin::BI__builtin_fmaxl:
2406*700637cbSDimitry Andric   case Builtin::BI__builtin_fmaxf16:
2407*700637cbSDimitry Andric   case Builtin::BI__builtin_fmaxf128:
2408*700637cbSDimitry Andric     return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/false);
2409*700637cbSDimitry Andric 
2410*700637cbSDimitry Andric   case Builtin::BI__builtin_fmaximum_num:
2411*700637cbSDimitry Andric   case Builtin::BI__builtin_fmaximum_numf:
2412*700637cbSDimitry Andric   case Builtin::BI__builtin_fmaximum_numl:
2413*700637cbSDimitry Andric   case Builtin::BI__builtin_fmaximum_numf16:
2414*700637cbSDimitry Andric   case Builtin::BI__builtin_fmaximum_numf128:
2415*700637cbSDimitry Andric     return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/true);
2416*700637cbSDimitry Andric 
2417*700637cbSDimitry Andric   case Builtin::BI__builtin_isnan:
2418*700637cbSDimitry Andric     return interp__builtin_isnan(S, OpPC, Frame, Call);
2419*700637cbSDimitry Andric 
2420*700637cbSDimitry Andric   case Builtin::BI__builtin_issignaling:
2421*700637cbSDimitry Andric     return interp__builtin_issignaling(S, OpPC, Frame, Call);
2422*700637cbSDimitry Andric 
2423*700637cbSDimitry Andric   case Builtin::BI__builtin_isinf:
2424*700637cbSDimitry Andric     return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/false, Call);
2425*700637cbSDimitry Andric 
2426*700637cbSDimitry Andric   case Builtin::BI__builtin_isinf_sign:
2427*700637cbSDimitry Andric     return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/true, Call);
2428*700637cbSDimitry Andric 
2429*700637cbSDimitry Andric   case Builtin::BI__builtin_isfinite:
2430*700637cbSDimitry Andric     return interp__builtin_isfinite(S, OpPC, Frame, Call);
2431*700637cbSDimitry Andric 
2432*700637cbSDimitry Andric   case Builtin::BI__builtin_isnormal:
2433*700637cbSDimitry Andric     return interp__builtin_isnormal(S, OpPC, Frame, Call);
2434*700637cbSDimitry Andric 
2435*700637cbSDimitry Andric   case Builtin::BI__builtin_issubnormal:
2436*700637cbSDimitry Andric     return interp__builtin_issubnormal(S, OpPC, Frame, Call);
2437*700637cbSDimitry Andric 
2438*700637cbSDimitry Andric   case Builtin::BI__builtin_iszero:
2439*700637cbSDimitry Andric     return interp__builtin_iszero(S, OpPC, Frame, Call);
2440*700637cbSDimitry Andric 
2441*700637cbSDimitry Andric   case Builtin::BI__builtin_signbit:
2442*700637cbSDimitry Andric   case Builtin::BI__builtin_signbitf:
2443*700637cbSDimitry Andric   case Builtin::BI__builtin_signbitl:
2444*700637cbSDimitry Andric     return interp__builtin_signbit(S, OpPC, Frame, Call);
2445*700637cbSDimitry Andric 
2446*700637cbSDimitry Andric   case Builtin::BI__builtin_isgreater:
2447*700637cbSDimitry Andric   case Builtin::BI__builtin_isgreaterequal:
2448*700637cbSDimitry Andric   case Builtin::BI__builtin_isless:
2449*700637cbSDimitry Andric   case Builtin::BI__builtin_islessequal:
2450*700637cbSDimitry Andric   case Builtin::BI__builtin_islessgreater:
2451*700637cbSDimitry Andric   case Builtin::BI__builtin_isunordered:
2452*700637cbSDimitry Andric     return interp_floating_comparison(S, OpPC, Call, BuiltinID);
2453*700637cbSDimitry Andric 
2454*700637cbSDimitry Andric   case Builtin::BI__builtin_isfpclass:
2455*700637cbSDimitry Andric     return interp__builtin_isfpclass(S, OpPC, Frame, Call);
2456*700637cbSDimitry Andric 
2457*700637cbSDimitry Andric   case Builtin::BI__builtin_fpclassify:
2458*700637cbSDimitry Andric     return interp__builtin_fpclassify(S, OpPC, Frame, Call);
2459*700637cbSDimitry Andric 
2460*700637cbSDimitry Andric   case Builtin::BI__builtin_fabs:
2461*700637cbSDimitry Andric   case Builtin::BI__builtin_fabsf:
2462*700637cbSDimitry Andric   case Builtin::BI__builtin_fabsl:
2463*700637cbSDimitry Andric   case Builtin::BI__builtin_fabsf128:
2464*700637cbSDimitry Andric     return interp__builtin_fabs(S, OpPC, Frame);
2465*700637cbSDimitry Andric 
2466*700637cbSDimitry Andric   case Builtin::BI__builtin_abs:
2467*700637cbSDimitry Andric   case Builtin::BI__builtin_labs:
2468*700637cbSDimitry Andric   case Builtin::BI__builtin_llabs:
2469*700637cbSDimitry Andric     return interp__builtin_abs(S, OpPC, Frame, Call);
2470*700637cbSDimitry Andric 
2471*700637cbSDimitry Andric   case Builtin::BI__builtin_popcount:
2472*700637cbSDimitry Andric   case Builtin::BI__builtin_popcountl:
2473*700637cbSDimitry Andric   case Builtin::BI__builtin_popcountll:
2474*700637cbSDimitry Andric   case Builtin::BI__builtin_popcountg:
2475*700637cbSDimitry Andric   case Builtin::BI__popcnt16: // Microsoft variants of popcount
2476*700637cbSDimitry Andric   case Builtin::BI__popcnt:
2477*700637cbSDimitry Andric   case Builtin::BI__popcnt64:
2478*700637cbSDimitry Andric     return interp__builtin_popcount(S, OpPC, Frame, Call);
2479*700637cbSDimitry Andric 
2480*700637cbSDimitry Andric   case Builtin::BI__builtin_parity:
2481*700637cbSDimitry Andric   case Builtin::BI__builtin_parityl:
2482*700637cbSDimitry Andric   case Builtin::BI__builtin_parityll:
2483*700637cbSDimitry Andric     return interp__builtin_parity(S, OpPC, Frame, Call);
2484*700637cbSDimitry Andric 
2485*700637cbSDimitry Andric   case Builtin::BI__builtin_clrsb:
2486*700637cbSDimitry Andric   case Builtin::BI__builtin_clrsbl:
2487*700637cbSDimitry Andric   case Builtin::BI__builtin_clrsbll:
2488*700637cbSDimitry Andric     return interp__builtin_clrsb(S, OpPC, Frame, Call);
2489*700637cbSDimitry Andric 
2490*700637cbSDimitry Andric   case Builtin::BI__builtin_bitreverse8:
2491*700637cbSDimitry Andric   case Builtin::BI__builtin_bitreverse16:
2492*700637cbSDimitry Andric   case Builtin::BI__builtin_bitreverse32:
2493*700637cbSDimitry Andric   case Builtin::BI__builtin_bitreverse64:
2494*700637cbSDimitry Andric     return interp__builtin_bitreverse(S, OpPC, Frame, Call);
2495*700637cbSDimitry Andric 
2496*700637cbSDimitry Andric   case Builtin::BI__builtin_classify_type:
2497*700637cbSDimitry Andric     return interp__builtin_classify_type(S, OpPC, Frame, Call);
2498*700637cbSDimitry Andric 
2499*700637cbSDimitry Andric   case Builtin::BI__builtin_expect:
2500*700637cbSDimitry Andric   case Builtin::BI__builtin_expect_with_probability:
2501*700637cbSDimitry Andric     return interp__builtin_expect(S, OpPC, Frame, Call);
2502*700637cbSDimitry Andric 
2503*700637cbSDimitry Andric   case Builtin::BI__builtin_rotateleft8:
2504*700637cbSDimitry Andric   case Builtin::BI__builtin_rotateleft16:
2505*700637cbSDimitry Andric   case Builtin::BI__builtin_rotateleft32:
2506*700637cbSDimitry Andric   case Builtin::BI__builtin_rotateleft64:
2507*700637cbSDimitry Andric   case Builtin::BI_rotl8: // Microsoft variants of rotate left
2508*700637cbSDimitry Andric   case Builtin::BI_rotl16:
2509*700637cbSDimitry Andric   case Builtin::BI_rotl:
2510*700637cbSDimitry Andric   case Builtin::BI_lrotl:
2511*700637cbSDimitry Andric   case Builtin::BI_rotl64:
2512*700637cbSDimitry Andric     return interp__builtin_rotate(S, OpPC, Frame, Call, /*Right=*/false);
2513*700637cbSDimitry Andric 
2514*700637cbSDimitry Andric   case Builtin::BI__builtin_rotateright8:
2515*700637cbSDimitry Andric   case Builtin::BI__builtin_rotateright16:
2516*700637cbSDimitry Andric   case Builtin::BI__builtin_rotateright32:
2517*700637cbSDimitry Andric   case Builtin::BI__builtin_rotateright64:
2518*700637cbSDimitry Andric   case Builtin::BI_rotr8: // Microsoft variants of rotate right
2519*700637cbSDimitry Andric   case Builtin::BI_rotr16:
2520*700637cbSDimitry Andric   case Builtin::BI_rotr:
2521*700637cbSDimitry Andric   case Builtin::BI_lrotr:
2522*700637cbSDimitry Andric   case Builtin::BI_rotr64:
2523*700637cbSDimitry Andric     return interp__builtin_rotate(S, OpPC, Frame, Call, /*Right=*/true);
2524*700637cbSDimitry Andric 
2525*700637cbSDimitry Andric   case Builtin::BI__builtin_ffs:
2526*700637cbSDimitry Andric   case Builtin::BI__builtin_ffsl:
2527*700637cbSDimitry Andric   case Builtin::BI__builtin_ffsll:
2528*700637cbSDimitry Andric     return interp__builtin_ffs(S, OpPC, Frame, Call);
2529*700637cbSDimitry Andric 
2530*700637cbSDimitry Andric   case Builtin::BIaddressof:
2531*700637cbSDimitry Andric   case Builtin::BI__addressof:
2532*700637cbSDimitry Andric   case Builtin::BI__builtin_addressof:
2533*700637cbSDimitry Andric     assert(isNoopBuiltin(BuiltinID));
2534*700637cbSDimitry Andric     return interp__builtin_addressof(S, OpPC, Frame, Call);
2535*700637cbSDimitry Andric 
2536*700637cbSDimitry Andric   case Builtin::BIas_const:
2537*700637cbSDimitry Andric   case Builtin::BIforward:
2538*700637cbSDimitry Andric   case Builtin::BIforward_like:
2539*700637cbSDimitry Andric   case Builtin::BImove:
2540*700637cbSDimitry Andric   case Builtin::BImove_if_noexcept:
2541*700637cbSDimitry Andric     assert(isNoopBuiltin(BuiltinID));
2542*700637cbSDimitry Andric     return interp__builtin_move(S, OpPC, Frame, Call);
2543*700637cbSDimitry Andric 
2544*700637cbSDimitry Andric   case Builtin::BI__builtin_eh_return_data_regno:
2545*700637cbSDimitry Andric     return interp__builtin_eh_return_data_regno(S, OpPC, Frame, Call);
2546*700637cbSDimitry Andric 
2547*700637cbSDimitry Andric   case Builtin::BI__builtin_launder:
2548*700637cbSDimitry Andric     assert(isNoopBuiltin(BuiltinID));
2549*700637cbSDimitry Andric     return true;
2550*700637cbSDimitry Andric 
2551*700637cbSDimitry Andric   case Builtin::BI__builtin_add_overflow:
2552*700637cbSDimitry Andric   case Builtin::BI__builtin_sub_overflow:
2553*700637cbSDimitry Andric   case Builtin::BI__builtin_mul_overflow:
2554*700637cbSDimitry Andric   case Builtin::BI__builtin_sadd_overflow:
2555*700637cbSDimitry Andric   case Builtin::BI__builtin_uadd_overflow:
2556*700637cbSDimitry Andric   case Builtin::BI__builtin_uaddl_overflow:
2557*700637cbSDimitry Andric   case Builtin::BI__builtin_uaddll_overflow:
2558*700637cbSDimitry Andric   case Builtin::BI__builtin_usub_overflow:
2559*700637cbSDimitry Andric   case Builtin::BI__builtin_usubl_overflow:
2560*700637cbSDimitry Andric   case Builtin::BI__builtin_usubll_overflow:
2561*700637cbSDimitry Andric   case Builtin::BI__builtin_umul_overflow:
2562*700637cbSDimitry Andric   case Builtin::BI__builtin_umull_overflow:
2563*700637cbSDimitry Andric   case Builtin::BI__builtin_umulll_overflow:
2564*700637cbSDimitry Andric   case Builtin::BI__builtin_saddl_overflow:
2565*700637cbSDimitry Andric   case Builtin::BI__builtin_saddll_overflow:
2566*700637cbSDimitry Andric   case Builtin::BI__builtin_ssub_overflow:
2567*700637cbSDimitry Andric   case Builtin::BI__builtin_ssubl_overflow:
2568*700637cbSDimitry Andric   case Builtin::BI__builtin_ssubll_overflow:
2569*700637cbSDimitry Andric   case Builtin::BI__builtin_smul_overflow:
2570*700637cbSDimitry Andric   case Builtin::BI__builtin_smull_overflow:
2571*700637cbSDimitry Andric   case Builtin::BI__builtin_smulll_overflow:
2572*700637cbSDimitry Andric     return interp__builtin_overflowop(S, OpPC, Call, BuiltinID);
2573*700637cbSDimitry Andric 
2574*700637cbSDimitry Andric   case Builtin::BI__builtin_addcb:
2575*700637cbSDimitry Andric   case Builtin::BI__builtin_addcs:
2576*700637cbSDimitry Andric   case Builtin::BI__builtin_addc:
2577*700637cbSDimitry Andric   case Builtin::BI__builtin_addcl:
2578*700637cbSDimitry Andric   case Builtin::BI__builtin_addcll:
2579*700637cbSDimitry Andric   case Builtin::BI__builtin_subcb:
2580*700637cbSDimitry Andric   case Builtin::BI__builtin_subcs:
2581*700637cbSDimitry Andric   case Builtin::BI__builtin_subc:
2582*700637cbSDimitry Andric   case Builtin::BI__builtin_subcl:
2583*700637cbSDimitry Andric   case Builtin::BI__builtin_subcll:
2584*700637cbSDimitry Andric     return interp__builtin_carryop(S, OpPC, Frame, Call, BuiltinID);
2585*700637cbSDimitry Andric 
2586*700637cbSDimitry Andric   case Builtin::BI__builtin_clz:
2587*700637cbSDimitry Andric   case Builtin::BI__builtin_clzl:
2588*700637cbSDimitry Andric   case Builtin::BI__builtin_clzll:
2589*700637cbSDimitry Andric   case Builtin::BI__builtin_clzs:
2590*700637cbSDimitry Andric   case Builtin::BI__builtin_clzg:
2591*700637cbSDimitry Andric   case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
2592*700637cbSDimitry Andric   case Builtin::BI__lzcnt:
2593*700637cbSDimitry Andric   case Builtin::BI__lzcnt64:
2594*700637cbSDimitry Andric     return interp__builtin_clz(S, OpPC, Frame, Call, BuiltinID);
2595*700637cbSDimitry Andric 
2596*700637cbSDimitry Andric   case Builtin::BI__builtin_ctz:
2597*700637cbSDimitry Andric   case Builtin::BI__builtin_ctzl:
2598*700637cbSDimitry Andric   case Builtin::BI__builtin_ctzll:
2599*700637cbSDimitry Andric   case Builtin::BI__builtin_ctzs:
2600*700637cbSDimitry Andric   case Builtin::BI__builtin_ctzg:
2601*700637cbSDimitry Andric     return interp__builtin_ctz(S, OpPC, Frame, Call, BuiltinID);
2602*700637cbSDimitry Andric 
2603*700637cbSDimitry Andric   case Builtin::BI__builtin_bswap16:
2604*700637cbSDimitry Andric   case Builtin::BI__builtin_bswap32:
2605*700637cbSDimitry Andric   case Builtin::BI__builtin_bswap64:
2606*700637cbSDimitry Andric     return interp__builtin_bswap(S, OpPC, Frame, Call);
2607*700637cbSDimitry Andric 
2608*700637cbSDimitry Andric   case Builtin::BI__atomic_always_lock_free:
2609*700637cbSDimitry Andric   case Builtin::BI__atomic_is_lock_free:
2610*700637cbSDimitry Andric     return interp__builtin_atomic_lock_free(S, OpPC, Frame, Call, BuiltinID);
2611*700637cbSDimitry Andric 
2612*700637cbSDimitry Andric   case Builtin::BI__c11_atomic_is_lock_free:
2613*700637cbSDimitry Andric     return interp__builtin_c11_atomic_is_lock_free(S, OpPC, Frame, Call);
2614*700637cbSDimitry Andric 
2615*700637cbSDimitry Andric   case Builtin::BI__builtin_complex:
2616*700637cbSDimitry Andric     return interp__builtin_complex(S, OpPC, Frame, Call);
2617*700637cbSDimitry Andric 
2618*700637cbSDimitry Andric   case Builtin::BI__builtin_is_aligned:
2619*700637cbSDimitry Andric   case Builtin::BI__builtin_align_up:
2620*700637cbSDimitry Andric   case Builtin::BI__builtin_align_down:
2621*700637cbSDimitry Andric     return interp__builtin_is_aligned_up_down(S, OpPC, Frame, Call, BuiltinID);
2622*700637cbSDimitry Andric 
2623*700637cbSDimitry Andric   case Builtin::BI__builtin_assume_aligned:
2624*700637cbSDimitry Andric     return interp__builtin_assume_aligned(S, OpPC, Frame, Call);
2625*700637cbSDimitry Andric 
2626*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_bextr_u32:
2627*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_bextr_u64:
2628*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_bextri_u32:
2629*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_bextri_u64:
2630*700637cbSDimitry Andric     return interp__builtin_ia32_bextr(S, OpPC, Frame, Call);
2631*700637cbSDimitry Andric 
2632*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_bzhi_si:
2633*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_bzhi_di:
2634*700637cbSDimitry Andric     return interp__builtin_ia32_bzhi(S, OpPC, Frame, Call);
2635*700637cbSDimitry Andric 
2636*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_lzcnt_u16:
2637*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_lzcnt_u32:
2638*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_lzcnt_u64:
2639*700637cbSDimitry Andric     return interp__builtin_ia32_lzcnt(S, OpPC, Frame, Call);
2640*700637cbSDimitry Andric 
2641*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_tzcnt_u16:
2642*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_tzcnt_u32:
2643*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_tzcnt_u64:
2644*700637cbSDimitry Andric     return interp__builtin_ia32_tzcnt(S, OpPC, Frame, Call);
2645*700637cbSDimitry Andric 
2646*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_pdep_si:
2647*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_pdep_di:
2648*700637cbSDimitry Andric     return interp__builtin_ia32_pdep(S, OpPC, Frame, Call);
2649*700637cbSDimitry Andric 
2650*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_pext_si:
2651*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_pext_di:
2652*700637cbSDimitry Andric     return interp__builtin_ia32_pext(S, OpPC, Frame, Call);
2653*700637cbSDimitry Andric 
2654*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_addcarryx_u32:
2655*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_addcarryx_u64:
2656*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_subborrow_u32:
2657*700637cbSDimitry Andric   case clang::X86::BI__builtin_ia32_subborrow_u64:
2658*700637cbSDimitry Andric     return interp__builtin_ia32_addcarry_subborrow(S, OpPC, Frame, Call,
2659*700637cbSDimitry Andric                                                    BuiltinID);
2660*700637cbSDimitry Andric 
2661*700637cbSDimitry Andric   case Builtin::BI__builtin_os_log_format_buffer_size:
2662*700637cbSDimitry Andric     return interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, Call);
2663*700637cbSDimitry Andric 
2664*700637cbSDimitry Andric   case Builtin::BI__builtin_ptrauth_string_discriminator:
2665*700637cbSDimitry Andric     return interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, Call);
2666*700637cbSDimitry Andric 
2667*700637cbSDimitry Andric   case Builtin::BI__noop:
2668*700637cbSDimitry Andric     pushInteger(S, 0, Call->getType());
2669*700637cbSDimitry Andric     return true;
2670*700637cbSDimitry Andric 
2671*700637cbSDimitry Andric   case Builtin::BI__builtin_operator_new:
2672*700637cbSDimitry Andric     return interp__builtin_operator_new(S, OpPC, Frame, Call);
2673*700637cbSDimitry Andric 
2674*700637cbSDimitry Andric   case Builtin::BI__builtin_operator_delete:
2675*700637cbSDimitry Andric     return interp__builtin_operator_delete(S, OpPC, Frame, Call);
2676*700637cbSDimitry Andric 
2677*700637cbSDimitry Andric   case Builtin::BI__arithmetic_fence:
2678*700637cbSDimitry Andric     return interp__builtin_arithmetic_fence(S, OpPC, Frame, Call);
2679*700637cbSDimitry Andric 
2680*700637cbSDimitry Andric   case Builtin::BI__builtin_reduce_add:
2681*700637cbSDimitry Andric   case Builtin::BI__builtin_reduce_mul:
2682*700637cbSDimitry Andric   case Builtin::BI__builtin_reduce_and:
2683*700637cbSDimitry Andric   case Builtin::BI__builtin_reduce_or:
2684*700637cbSDimitry Andric   case Builtin::BI__builtin_reduce_xor:
2685*700637cbSDimitry Andric   case Builtin::BI__builtin_reduce_min:
2686*700637cbSDimitry Andric   case Builtin::BI__builtin_reduce_max:
2687*700637cbSDimitry Andric     return interp__builtin_vector_reduce(S, OpPC, Call, BuiltinID);
2688*700637cbSDimitry Andric 
2689*700637cbSDimitry Andric   case Builtin::BI__builtin_elementwise_popcount:
2690*700637cbSDimitry Andric   case Builtin::BI__builtin_elementwise_bitreverse:
2691*700637cbSDimitry Andric     return interp__builtin_elementwise_popcount(S, OpPC, Frame, Call,
2692*700637cbSDimitry Andric                                                 BuiltinID);
2693*700637cbSDimitry Andric 
2694*700637cbSDimitry Andric   case Builtin::BI__builtin_memcpy:
2695*700637cbSDimitry Andric   case Builtin::BImemcpy:
2696*700637cbSDimitry Andric   case Builtin::BI__builtin_wmemcpy:
2697*700637cbSDimitry Andric   case Builtin::BIwmemcpy:
2698*700637cbSDimitry Andric   case Builtin::BI__builtin_memmove:
2699*700637cbSDimitry Andric   case Builtin::BImemmove:
2700*700637cbSDimitry Andric   case Builtin::BI__builtin_wmemmove:
2701*700637cbSDimitry Andric   case Builtin::BIwmemmove:
2702*700637cbSDimitry Andric     return interp__builtin_memcpy(S, OpPC, Frame, Call, BuiltinID);
2703*700637cbSDimitry Andric 
2704*700637cbSDimitry Andric   case Builtin::BI__builtin_memcmp:
2705*700637cbSDimitry Andric   case Builtin::BImemcmp:
2706*700637cbSDimitry Andric   case Builtin::BI__builtin_bcmp:
2707*700637cbSDimitry Andric   case Builtin::BIbcmp:
2708*700637cbSDimitry Andric   case Builtin::BI__builtin_wmemcmp:
2709*700637cbSDimitry Andric   case Builtin::BIwmemcmp:
2710*700637cbSDimitry Andric     return interp__builtin_memcmp(S, OpPC, Frame, Call, BuiltinID);
2711*700637cbSDimitry Andric 
2712*700637cbSDimitry Andric   case Builtin::BImemchr:
2713*700637cbSDimitry Andric   case Builtin::BI__builtin_memchr:
2714*700637cbSDimitry Andric   case Builtin::BIstrchr:
2715*700637cbSDimitry Andric   case Builtin::BI__builtin_strchr:
2716*700637cbSDimitry Andric   case Builtin::BIwmemchr:
2717*700637cbSDimitry Andric   case Builtin::BI__builtin_wmemchr:
2718*700637cbSDimitry Andric   case Builtin::BIwcschr:
2719*700637cbSDimitry Andric   case Builtin::BI__builtin_wcschr:
2720*700637cbSDimitry Andric   case Builtin::BI__builtin_char_memchr:
2721*700637cbSDimitry Andric     return interp__builtin_memchr(S, OpPC, Call, BuiltinID);
2722*700637cbSDimitry Andric 
2723*700637cbSDimitry Andric   case Builtin::BI__builtin_object_size:
2724*700637cbSDimitry Andric   case Builtin::BI__builtin_dynamic_object_size:
2725*700637cbSDimitry Andric     return interp__builtin_object_size(S, OpPC, Frame, Call);
2726*700637cbSDimitry Andric 
2727*700637cbSDimitry Andric   case Builtin::BI__builtin_is_within_lifetime:
2728*700637cbSDimitry Andric     return interp__builtin_is_within_lifetime(S, OpPC, Call);
2729*700637cbSDimitry Andric 
2730*700637cbSDimitry Andric   case Builtin::BI__builtin_elementwise_add_sat:
2731*700637cbSDimitry Andric   case Builtin::BI__builtin_elementwise_sub_sat:
2732*700637cbSDimitry Andric     return interp__builtin_elementwise_sat(S, OpPC, Call, BuiltinID);
2733*700637cbSDimitry Andric 
2734*700637cbSDimitry Andric   default:
2735*700637cbSDimitry Andric     S.FFDiag(S.Current->getLocation(OpPC),
2736*700637cbSDimitry Andric              diag::note_invalid_subexpr_in_const_expr)
2737*700637cbSDimitry Andric         << S.Current->getRange(OpPC);
2738*700637cbSDimitry Andric 
2739*700637cbSDimitry Andric     return false;
2740*700637cbSDimitry Andric   }
2741*700637cbSDimitry Andric 
2742*700637cbSDimitry Andric   llvm_unreachable("Unhandled builtin ID");
2743*700637cbSDimitry Andric }
2744*700637cbSDimitry Andric 
InterpretOffsetOf(InterpState & S,CodePtr OpPC,const OffsetOfExpr * E,ArrayRef<int64_t> ArrayIndices,int64_t & IntResult)2745*700637cbSDimitry Andric bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
2746*700637cbSDimitry Andric                        ArrayRef<int64_t> ArrayIndices, int64_t &IntResult) {
2747*700637cbSDimitry Andric   CharUnits Result;
2748*700637cbSDimitry Andric   unsigned N = E->getNumComponents();
2749*700637cbSDimitry Andric   assert(N > 0);
2750*700637cbSDimitry Andric 
2751*700637cbSDimitry Andric   unsigned ArrayIndex = 0;
2752*700637cbSDimitry Andric   QualType CurrentType = E->getTypeSourceInfo()->getType();
2753*700637cbSDimitry Andric   for (unsigned I = 0; I != N; ++I) {
2754*700637cbSDimitry Andric     const OffsetOfNode &Node = E->getComponent(I);
2755*700637cbSDimitry Andric     switch (Node.getKind()) {
2756*700637cbSDimitry Andric     case OffsetOfNode::Field: {
2757*700637cbSDimitry Andric       const FieldDecl *MemberDecl = Node.getField();
2758*700637cbSDimitry Andric       const RecordType *RT = CurrentType->getAs<RecordType>();
2759*700637cbSDimitry Andric       if (!RT)
2760*700637cbSDimitry Andric         return false;
2761*700637cbSDimitry Andric       const RecordDecl *RD = RT->getDecl();
2762*700637cbSDimitry Andric       if (RD->isInvalidDecl())
2763*700637cbSDimitry Andric         return false;
2764*700637cbSDimitry Andric       const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD);
2765*700637cbSDimitry Andric       unsigned FieldIndex = MemberDecl->getFieldIndex();
2766*700637cbSDimitry Andric       assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");
2767*700637cbSDimitry Andric       Result +=
2768*700637cbSDimitry Andric           S.getASTContext().toCharUnitsFromBits(RL.getFieldOffset(FieldIndex));
2769*700637cbSDimitry Andric       CurrentType = MemberDecl->getType().getNonReferenceType();
2770*700637cbSDimitry Andric       break;
2771*700637cbSDimitry Andric     }
2772*700637cbSDimitry Andric     case OffsetOfNode::Array: {
2773*700637cbSDimitry Andric       // When generating bytecode, we put all the index expressions as Sint64 on
2774*700637cbSDimitry Andric       // the stack.
2775*700637cbSDimitry Andric       int64_t Index = ArrayIndices[ArrayIndex];
2776*700637cbSDimitry Andric       const ArrayType *AT = S.getASTContext().getAsArrayType(CurrentType);
2777*700637cbSDimitry Andric       if (!AT)
2778*700637cbSDimitry Andric         return false;
2779*700637cbSDimitry Andric       CurrentType = AT->getElementType();
2780*700637cbSDimitry Andric       CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType);
2781*700637cbSDimitry Andric       Result += Index * ElementSize;
2782*700637cbSDimitry Andric       ++ArrayIndex;
2783*700637cbSDimitry Andric       break;
2784*700637cbSDimitry Andric     }
2785*700637cbSDimitry Andric     case OffsetOfNode::Base: {
2786*700637cbSDimitry Andric       const CXXBaseSpecifier *BaseSpec = Node.getBase();
2787*700637cbSDimitry Andric       if (BaseSpec->isVirtual())
2788*700637cbSDimitry Andric         return false;
2789*700637cbSDimitry Andric 
2790*700637cbSDimitry Andric       // Find the layout of the class whose base we are looking into.
2791*700637cbSDimitry Andric       const RecordType *RT = CurrentType->getAs<RecordType>();
2792*700637cbSDimitry Andric       if (!RT)
2793*700637cbSDimitry Andric         return false;
2794*700637cbSDimitry Andric       const RecordDecl *RD = RT->getDecl();
2795*700637cbSDimitry Andric       if (RD->isInvalidDecl())
2796*700637cbSDimitry Andric         return false;
2797*700637cbSDimitry Andric       const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD);
2798*700637cbSDimitry Andric 
2799*700637cbSDimitry Andric       // Find the base class itself.
2800*700637cbSDimitry Andric       CurrentType = BaseSpec->getType();
2801*700637cbSDimitry Andric       const RecordType *BaseRT = CurrentType->getAs<RecordType>();
2802*700637cbSDimitry Andric       if (!BaseRT)
2803*700637cbSDimitry Andric         return false;
2804*700637cbSDimitry Andric 
2805*700637cbSDimitry Andric       // Add the offset to the base.
2806*700637cbSDimitry Andric       Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));
2807*700637cbSDimitry Andric       break;
2808*700637cbSDimitry Andric     }
2809*700637cbSDimitry Andric     case OffsetOfNode::Identifier:
2810*700637cbSDimitry Andric       llvm_unreachable("Dependent OffsetOfExpr?");
2811*700637cbSDimitry Andric     }
2812*700637cbSDimitry Andric   }
2813*700637cbSDimitry Andric 
2814*700637cbSDimitry Andric   IntResult = Result.getQuantity();
2815*700637cbSDimitry Andric 
2816*700637cbSDimitry Andric   return true;
2817*700637cbSDimitry Andric }
2818*700637cbSDimitry Andric 
SetThreeWayComparisonField(InterpState & S,CodePtr OpPC,const Pointer & Ptr,const APSInt & IntValue)2819*700637cbSDimitry Andric bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,
2820*700637cbSDimitry Andric                                 const Pointer &Ptr, const APSInt &IntValue) {
2821*700637cbSDimitry Andric 
2822*700637cbSDimitry Andric   const Record *R = Ptr.getRecord();
2823*700637cbSDimitry Andric   assert(R);
2824*700637cbSDimitry Andric   assert(R->getNumFields() == 1);
2825*700637cbSDimitry Andric 
2826*700637cbSDimitry Andric   unsigned FieldOffset = R->getField(0u)->Offset;
2827*700637cbSDimitry Andric   const Pointer &FieldPtr = Ptr.atField(FieldOffset);
2828*700637cbSDimitry Andric   PrimType FieldT = *S.getContext().classify(FieldPtr.getType());
2829*700637cbSDimitry Andric 
2830*700637cbSDimitry Andric   INT_TYPE_SWITCH(FieldT,
2831*700637cbSDimitry Andric                   FieldPtr.deref<T>() = T::from(IntValue.getSExtValue()));
2832*700637cbSDimitry Andric   FieldPtr.initialize();
2833*700637cbSDimitry Andric   return true;
2834*700637cbSDimitry Andric }
2835*700637cbSDimitry Andric 
zeroAll(Pointer & Dest)2836*700637cbSDimitry Andric static void zeroAll(Pointer &Dest) {
2837*700637cbSDimitry Andric   const Descriptor *Desc = Dest.getFieldDesc();
2838*700637cbSDimitry Andric 
2839*700637cbSDimitry Andric   if (Desc->isPrimitive()) {
2840*700637cbSDimitry Andric     TYPE_SWITCH(Desc->getPrimType(), {
2841*700637cbSDimitry Andric       Dest.deref<T>().~T();
2842*700637cbSDimitry Andric       new (&Dest.deref<T>()) T();
2843*700637cbSDimitry Andric     });
2844*700637cbSDimitry Andric     return;
2845*700637cbSDimitry Andric   }
2846*700637cbSDimitry Andric 
2847*700637cbSDimitry Andric   if (Desc->isRecord()) {
2848*700637cbSDimitry Andric     const Record *R = Desc->ElemRecord;
2849*700637cbSDimitry Andric     for (const Record::Field &F : R->fields()) {
2850*700637cbSDimitry Andric       Pointer FieldPtr = Dest.atField(F.Offset);
2851*700637cbSDimitry Andric       zeroAll(FieldPtr);
2852*700637cbSDimitry Andric     }
2853*700637cbSDimitry Andric     return;
2854*700637cbSDimitry Andric   }
2855*700637cbSDimitry Andric 
2856*700637cbSDimitry Andric   if (Desc->isPrimitiveArray()) {
2857*700637cbSDimitry Andric     for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
2858*700637cbSDimitry Andric       TYPE_SWITCH(Desc->getPrimType(), {
2859*700637cbSDimitry Andric         Dest.deref<T>().~T();
2860*700637cbSDimitry Andric         new (&Dest.deref<T>()) T();
2861*700637cbSDimitry Andric       });
2862*700637cbSDimitry Andric     }
2863*700637cbSDimitry Andric     return;
2864*700637cbSDimitry Andric   }
2865*700637cbSDimitry Andric 
2866*700637cbSDimitry Andric   if (Desc->isCompositeArray()) {
2867*700637cbSDimitry Andric     for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
2868*700637cbSDimitry Andric       Pointer ElemPtr = Dest.atIndex(I).narrow();
2869*700637cbSDimitry Andric       zeroAll(ElemPtr);
2870*700637cbSDimitry Andric     }
2871*700637cbSDimitry Andric     return;
2872*700637cbSDimitry Andric   }
2873*700637cbSDimitry Andric }
2874*700637cbSDimitry Andric 
2875*700637cbSDimitry Andric static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
2876*700637cbSDimitry Andric                           Pointer &Dest, bool Activate);
copyRecord(InterpState & S,CodePtr OpPC,const Pointer & Src,Pointer & Dest,bool Activate=false)2877*700637cbSDimitry Andric static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,
2878*700637cbSDimitry Andric                        Pointer &Dest, bool Activate = false) {
2879*700637cbSDimitry Andric   [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
2880*700637cbSDimitry Andric   const Descriptor *DestDesc = Dest.getFieldDesc();
2881*700637cbSDimitry Andric 
2882*700637cbSDimitry Andric   auto copyField = [&](const Record::Field &F, bool Activate) -> bool {
2883*700637cbSDimitry Andric     Pointer DestField = Dest.atField(F.Offset);
2884*700637cbSDimitry Andric     if (std::optional<PrimType> FT = S.Ctx.classify(F.Decl->getType())) {
2885*700637cbSDimitry Andric       TYPE_SWITCH(*FT, {
2886*700637cbSDimitry Andric         DestField.deref<T>() = Src.atField(F.Offset).deref<T>();
2887*700637cbSDimitry Andric         if (Src.atField(F.Offset).isInitialized())
2888*700637cbSDimitry Andric           DestField.initialize();
2889*700637cbSDimitry Andric         if (Activate)
2890*700637cbSDimitry Andric           DestField.activate();
2891*700637cbSDimitry Andric       });
2892*700637cbSDimitry Andric       return true;
2893*700637cbSDimitry Andric     }
2894*700637cbSDimitry Andric     // Composite field.
2895*700637cbSDimitry Andric     return copyComposite(S, OpPC, Src.atField(F.Offset), DestField, Activate);
2896*700637cbSDimitry Andric   };
2897*700637cbSDimitry Andric 
2898*700637cbSDimitry Andric   assert(SrcDesc->isRecord());
2899*700637cbSDimitry Andric   assert(SrcDesc->ElemRecord == DestDesc->ElemRecord);
2900*700637cbSDimitry Andric   const Record *R = DestDesc->ElemRecord;
2901*700637cbSDimitry Andric   for (const Record::Field &F : R->fields()) {
2902*700637cbSDimitry Andric     if (R->isUnion()) {
2903*700637cbSDimitry Andric       // For unions, only copy the active field. Zero all others.
2904*700637cbSDimitry Andric       const Pointer &SrcField = Src.atField(F.Offset);
2905*700637cbSDimitry Andric       if (SrcField.isActive()) {
2906*700637cbSDimitry Andric         if (!copyField(F, /*Activate=*/true))
2907*700637cbSDimitry Andric           return false;
2908*700637cbSDimitry Andric       } else {
2909*700637cbSDimitry Andric         Pointer DestField = Dest.atField(F.Offset);
2910*700637cbSDimitry Andric         zeroAll(DestField);
2911*700637cbSDimitry Andric       }
2912*700637cbSDimitry Andric     } else {
2913*700637cbSDimitry Andric       if (!copyField(F, Activate))
2914*700637cbSDimitry Andric         return false;
2915*700637cbSDimitry Andric     }
2916*700637cbSDimitry Andric   }
2917*700637cbSDimitry Andric 
2918*700637cbSDimitry Andric   for (const Record::Base &B : R->bases()) {
2919*700637cbSDimitry Andric     Pointer DestBase = Dest.atField(B.Offset);
2920*700637cbSDimitry Andric     if (!copyRecord(S, OpPC, Src.atField(B.Offset), DestBase, Activate))
2921*700637cbSDimitry Andric       return false;
2922*700637cbSDimitry Andric   }
2923*700637cbSDimitry Andric 
2924*700637cbSDimitry Andric   Dest.initialize();
2925*700637cbSDimitry Andric   return true;
2926*700637cbSDimitry Andric }
2927*700637cbSDimitry Andric 
copyComposite(InterpState & S,CodePtr OpPC,const Pointer & Src,Pointer & Dest,bool Activate=false)2928*700637cbSDimitry Andric static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
2929*700637cbSDimitry Andric                           Pointer &Dest, bool Activate = false) {
2930*700637cbSDimitry Andric   assert(Src.isLive() && Dest.isLive());
2931*700637cbSDimitry Andric 
2932*700637cbSDimitry Andric   [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
2933*700637cbSDimitry Andric   const Descriptor *DestDesc = Dest.getFieldDesc();
2934*700637cbSDimitry Andric 
2935*700637cbSDimitry Andric   assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive());
2936*700637cbSDimitry Andric 
2937*700637cbSDimitry Andric   if (DestDesc->isPrimitiveArray()) {
2938*700637cbSDimitry Andric     assert(SrcDesc->isPrimitiveArray());
2939*700637cbSDimitry Andric     assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
2940*700637cbSDimitry Andric     PrimType ET = DestDesc->getPrimType();
2941*700637cbSDimitry Andric     for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
2942*700637cbSDimitry Andric       Pointer DestElem = Dest.atIndex(I);
2943*700637cbSDimitry Andric       TYPE_SWITCH(ET, {
2944*700637cbSDimitry Andric         DestElem.deref<T>() = Src.atIndex(I).deref<T>();
2945*700637cbSDimitry Andric         DestElem.initialize();
2946*700637cbSDimitry Andric       });
2947*700637cbSDimitry Andric     }
2948*700637cbSDimitry Andric     return true;
2949*700637cbSDimitry Andric   }
2950*700637cbSDimitry Andric 
2951*700637cbSDimitry Andric   if (DestDesc->isCompositeArray()) {
2952*700637cbSDimitry Andric     assert(SrcDesc->isCompositeArray());
2953*700637cbSDimitry Andric     assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
2954*700637cbSDimitry Andric     for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
2955*700637cbSDimitry Andric       const Pointer &SrcElem = Src.atIndex(I).narrow();
2956*700637cbSDimitry Andric       Pointer DestElem = Dest.atIndex(I).narrow();
2957*700637cbSDimitry Andric       if (!copyComposite(S, OpPC, SrcElem, DestElem, Activate))
2958*700637cbSDimitry Andric         return false;
2959*700637cbSDimitry Andric     }
2960*700637cbSDimitry Andric     return true;
2961*700637cbSDimitry Andric   }
2962*700637cbSDimitry Andric 
2963*700637cbSDimitry Andric   if (DestDesc->isRecord())
2964*700637cbSDimitry Andric     return copyRecord(S, OpPC, Src, Dest, Activate);
2965*700637cbSDimitry Andric   return Invalid(S, OpPC);
2966*700637cbSDimitry Andric }
2967*700637cbSDimitry Andric 
DoMemcpy(InterpState & S,CodePtr OpPC,const Pointer & Src,Pointer & Dest)2968*700637cbSDimitry Andric bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {
2969*700637cbSDimitry Andric   return copyComposite(S, OpPC, Src, Dest);
2970*700637cbSDimitry Andric }
2971*700637cbSDimitry Andric 
2972*700637cbSDimitry Andric } // namespace interp
2973*700637cbSDimitry Andric } // namespace clang
2974