clang 23.0.0git
InterpBuiltin.cpp
Go to the documentation of this file.
1//===--- InterpBuiltin.cpp - Interpreter for the constexpr VM ---*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
9#include "Boolean.h"
10#include "Char.h"
11#include "EvalEmitter.h"
13#include "InterpHelpers.h"
14#include "PrimType.h"
15#include "Program.h"
17#include "clang/AST/OSLog.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/Support/AllocToken.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/SipHash.h"
26
27namespace clang {
28namespace interp {
29
30[[maybe_unused]] static bool isNoopBuiltin(unsigned ID) {
31 switch (ID) {
32 case Builtin::BIas_const:
33 case Builtin::BIforward:
34 case Builtin::BIforward_like:
35 case Builtin::BImove:
36 case Builtin::BImove_if_noexcept:
37 case Builtin::BIaddressof:
38 case Builtin::BI__addressof:
39 case Builtin::BI__builtin_addressof:
40 case Builtin::BI__builtin_launder:
41 return true;
42 default:
43 return false;
44 }
45 return false;
46}
47
48static void discard(InterpStack &Stk, PrimType T) {
49 TYPE_SWITCH(T, { Stk.discard<T>(); });
50}
51
52static bool popToUInt64(const InterpState &S, const Expr *E, uint64_t &Out) {
54 const auto &Val = S.Stk.pop<T>();
55 if (!Val.isNumber())
56 return false;
57 Out = static_cast<uint64_t>(Val);
58 return true;
59 });
60}
61
62static bool popToAPSInt(InterpStack &Stk, PrimType T, APSInt &Out) {
64 const auto &Val = Stk.pop<T>();
65 if (!Val.isNumber())
66 return false;
67 Out = Val.toAPSInt();
68 return true;
69 });
70}
71
72static bool popToAPSInt(InterpState &S, const Expr *E, APSInt &Out) {
73 return popToAPSInt(S.Stk, *S.getContext().classify(E->getType()), Out);
74}
75static bool popToAPSInt(InterpState &S, QualType T, APSInt &Out) {
76 return popToAPSInt(S.Stk, *S.getContext().classify(T), Out);
77}
78
79/// Check for common reasons a pointer can't be read from, which
80/// are usually not diagnosed in a builtin function.
81static bool isReadable(const Pointer &P) {
82 if (P.isDummy())
83 return false;
84 if (!P.isBlockPointer())
85 return false;
86 if (!P.isLive())
87 return false;
88 if (P.isOnePastEnd())
89 return false;
90 return true;
91}
92
93/// Pushes \p Val on the stack as the type given by \p QT.
94static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {
98 assert(T);
99 unsigned BitWidth = S.getASTContext().getIntWidth(QT);
100
101 if (T == PT_IntAPS) {
102 auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
103 Result.copy(Val);
105 return;
106 }
107
108 if (T == PT_IntAP) {
109 auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
110 Result.copy(Val);
112 return;
113 }
114
116 int64_t V = Val.getSExtValue();
117 INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });
118 } else {
120 uint64_t V = Val.getZExtValue();
121 INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });
122 }
123}
124
125template <typename T>
126static void pushInteger(InterpState &S, T Val, QualType QT) {
127 if constexpr (std::is_same_v<T, APInt>)
128 pushInteger(S, APSInt(Val, !std::is_signed_v<T>), QT);
129 else if constexpr (std::is_same_v<T, APSInt>)
130 pushInteger(S, Val, QT);
131 else
132 pushInteger(S,
133 APSInt(APInt(sizeof(T) * 8, static_cast<uint64_t>(Val),
134 std::is_signed_v<T>),
135 !std::is_signed_v<T>),
136 QT);
137}
138
139static void assignIntegral(InterpState &S, const Pointer &Dest, PrimType ValueT,
140 const APSInt &Value) {
141
142 if (ValueT == PT_IntAPS) {
143 Dest.deref<IntegralAP<true>>() =
144 S.allocAP<IntegralAP<true>>(Value.getBitWidth());
145 Dest.deref<IntegralAP<true>>().copy(Value);
146 } else if (ValueT == PT_IntAP) {
147 Dest.deref<IntegralAP<false>>() =
148 S.allocAP<IntegralAP<false>>(Value.getBitWidth());
149 Dest.deref<IntegralAP<false>>().copy(Value);
150 } else if (ValueT == PT_Bool) {
151 Dest.deref<Boolean>() = Boolean::from(!Value.isZero());
152 } else {
154 ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); });
155 }
156}
157
158static QualType getElemType(const Pointer &P) {
159 const Descriptor *Desc = P.getFieldDesc();
160 QualType T = Desc->getType();
161 if (Desc->isPrimitive())
162 return T;
163 if (T->isPointerType())
164 return T->castAs<PointerType>()->getPointeeType();
165 if (Desc->isArray())
166 return Desc->getElemQualType();
167 if (const auto *AT = T->getAsArrayTypeUnsafe())
168 return AT->getElementType();
169 return T;
170}
171
173 unsigned ID) {
174 if (!S.diagnosing())
175 return;
176
177 auto Loc = S.Current->getSource(OpPC);
178 if (S.getLangOpts().CPlusPlus11)
179 S.CCEDiag(Loc, diag::note_constexpr_invalid_function)
180 << /*isConstexpr=*/0 << /*isConstructor=*/0
182 else
183 S.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
184}
185
186static llvm::APSInt convertBoolVectorToInt(const Pointer &Val) {
187 assert(Val.getFieldDesc()->isPrimitiveArray() &&
189 "Not a boolean vector");
190 unsigned NumElems = Val.getNumElems();
191
192 // Each element is one bit, so create an integer with NumElts bits.
193 llvm::APSInt Result(NumElems, 0);
194 for (unsigned I = 0; I != NumElems; ++I) {
195 if (Val.elem<bool>(I))
196 Result.setBit(I);
197 }
198
199 return Result;
200}
201
202// Strict double -> float conversion used for X86 PD2PS/cvtsd2ss intrinsics.
203// Reject NaN/Inf/Subnormal inputs and any lossy/inexact conversions.
205 InterpState &S, const Expr *DiagExpr) {
206 if (Src.isInfinity()) {
207 if (S.diagnosing())
208 S.CCEDiag(DiagExpr, diag::note_constexpr_float_arithmetic) << 0;
209 return false;
210 }
211 if (Src.isNaN()) {
212 if (S.diagnosing())
213 S.CCEDiag(DiagExpr, diag::note_constexpr_float_arithmetic) << 1;
214 return false;
215 }
216 APFloat Val = Src;
217 bool LosesInfo = false;
218 APFloat::opStatus Status = Val.convert(
219 APFloat::IEEEsingle(), APFloat::rmNearestTiesToEven, &LosesInfo);
220 if (LosesInfo || Val.isDenormal()) {
221 if (S.diagnosing())
222 S.CCEDiag(DiagExpr, diag::note_constexpr_float_arithmetic_strict);
223 return false;
224 }
225 if (Status != APFloat::opOK) {
226 if (S.diagnosing())
227 S.CCEDiag(DiagExpr, diag::note_invalid_subexpr_in_const_expr);
228 return false;
229 }
230 Dst.copy(Val);
231 return true;
232}
233
235 const InterpFrame *Frame,
236 const CallExpr *Call) {
237 unsigned Depth = S.Current->getDepth();
238 auto isStdCall = [](const FunctionDecl *F) -> bool {
239 return F && F->isInStdNamespace() && F->getIdentifier() &&
240 F->getIdentifier()->isStr("is_constant_evaluated");
241 };
242 const InterpFrame *Caller = Frame->Caller;
243 // The current frame is the one for __builtin_is_constant_evaluated.
244 // The one above that, potentially the one for std::is_constant_evaluated().
246 S.getEvalStatus().Diag &&
247 (Depth == 0 || (Depth == 1 && isStdCall(Frame->getCallee())))) {
248 if (Caller && isStdCall(Frame->getCallee())) {
249 const Expr *E = Caller->getExpr(Caller->getRetPC());
250 S.report(E->getExprLoc(),
251 diag::warn_is_constant_evaluated_always_true_constexpr)
252 << "std::is_constant_evaluated" << E->getSourceRange();
253 } else {
254 S.report(Call->getExprLoc(),
255 diag::warn_is_constant_evaluated_always_true_constexpr)
256 << "__builtin_is_constant_evaluated" << Call->getSourceRange();
257 }
258 }
259
261 return true;
262}
263
264// __builtin_assume
265// __assume (MS extension)
267 const InterpFrame *Frame,
268 const CallExpr *Call) {
269 // Nothing to be done here since the argument is NOT evaluated.
270 assert(Call->getNumArgs() == 1);
271 return true;
272}
273
275 const InterpFrame *Frame,
276 const CallExpr *Call, unsigned ID) {
277 uint64_t Limit = ~static_cast<uint64_t>(0);
278 if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp ||
279 ID == Builtin::BIwcsncmp || ID == Builtin::BI__builtin_wcsncmp) {
280 if (!popToUInt64(S, Call->getArg(2), Limit))
281 return false;
282 }
283
284 const Pointer &B = S.Stk.pop<Pointer>();
285 const Pointer &A = S.Stk.pop<Pointer>();
286 if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp ||
287 ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp)
288 diagnoseNonConstexprBuiltin(S, OpPC, ID);
289
290 if (Limit == 0) {
291 pushInteger(S, 0, Call->getType());
292 return true;
293 }
294
295 if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))
296 return false;
297
298 if (A.isDummy() || B.isDummy())
299 return false;
300 if (!A.isBlockPointer() || !B.isBlockPointer())
301 return false;
302 if (!A.getFieldDesc()->isPrimitiveArray() ||
304 return false;
305
306 bool IsWide = ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp ||
307 ID == Builtin::BI__builtin_wcscmp ||
308 ID == Builtin::BI__builtin_wcsncmp;
309 assert(A.getFieldDesc()->isPrimitiveArray());
310 assert(B.getFieldDesc()->isPrimitiveArray());
311
312 // Different element types shouldn't happen, but with casts they can.
314 return false;
315
316 PrimType ElemT = *S.getContext().classify(getElemType(A));
317
318 auto returnResult = [&](int V) -> bool {
319 pushInteger(S, V, Call->getType());
320 return true;
321 };
322
323 unsigned IndexA = A.getIndex();
324 unsigned IndexB = B.getIndex();
325 uint64_t Steps = 0;
326 for (;; ++IndexA, ++IndexB, ++Steps) {
327
328 if (Steps >= Limit)
329 break;
330 const Pointer &PA = A.atIndex(IndexA);
331 const Pointer &PB = B.atIndex(IndexB);
332 if (!CheckRange(S, OpPC, PA, AK_Read) ||
333 !CheckRange(S, OpPC, PB, AK_Read)) {
334 return false;
335 }
336
337 if (IsWide) {
338 INT_TYPE_SWITCH(ElemT, {
339 T CA = PA.deref<T>();
340 T CB = PB.deref<T>();
341 if (CA > CB)
342 return returnResult(1);
343 if (CA < CB)
344 return returnResult(-1);
345 if (CA.isZero() || CB.isZero())
346 return returnResult(0);
347 });
348 continue;
349 }
350
351 uint8_t CA = PA.deref<uint8_t>();
352 uint8_t CB = PB.deref<uint8_t>();
353
354 if (CA > CB)
355 return returnResult(1);
356 if (CA < CB)
357 return returnResult(-1);
358 if (CA == 0 || CB == 0)
359 return returnResult(0);
360 }
361
362 return returnResult(0);
363}
364
366 const InterpFrame *Frame,
367 const CallExpr *Call, unsigned ID) {
368 const Pointer &StrPtr = S.Stk.pop<Pointer>().expand();
369
370 if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen)
371 diagnoseNonConstexprBuiltin(S, OpPC, ID);
372
373 if (!CheckArray(S, OpPC, StrPtr))
374 return false;
375
376 if (!CheckLive(S, OpPC, StrPtr, AK_Read))
377 return false;
378
379 if (!StrPtr.isBlockPointer())
380 return false;
381
382 if (!CheckDummy(S, OpPC, StrPtr.block(), AK_Read))
383 return false;
384
385 if (!StrPtr.getFieldDesc()->isPrimitiveArray())
386 return false;
387
388 assert(StrPtr.getFieldDesc()->isPrimitiveArray());
389 PrimType ElemT = StrPtr.getFieldDesc()->getPrimType();
390 unsigned ElemSize = StrPtr.getFieldDesc()->getElemDataSize();
391 if (ElemSize != 1 && ElemSize != 2 && ElemSize != 4)
392 return Invalid(S, OpPC);
393
394 if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) {
395 const ASTContext &AC = S.getASTContext();
396 unsigned WCharSize = AC.getTypeSizeInChars(AC.getWCharType()).getQuantity();
397 if (StrPtr.getFieldDesc()->getElemDataSize() != WCharSize)
398 return false;
399 }
400
401 size_t Len = 0;
402 for (size_t I = StrPtr.getIndex();; ++I, ++Len) {
403 const Pointer &ElemPtr = StrPtr.atIndex(I);
404
405 if (!CheckRange(S, OpPC, ElemPtr, AK_Read))
406 return false;
407
408 uint32_t Val;
410 ElemT, { Val = static_cast<uint32_t>(ElemPtr.deref<T>()); });
411 if (Val == 0)
412 break;
413 }
414
415 pushInteger(S, Len, Call->getType());
416
417 return true;
418}
419
421 const InterpFrame *Frame, const CallExpr *Call,
422 bool Signaling) {
423 const Pointer &Arg = S.Stk.pop<Pointer>();
424
425 if (!CheckLoad(S, OpPC, Arg))
426 return false;
427
428 if (!Arg.getFieldDesc()->isPrimitiveArray())
429 return Invalid(S, OpPC);
430
431 // Convert the given string to an integer using StringRef's API.
432 llvm::APInt Fill;
433 std::string Str;
434 unsigned ArgLength = Arg.getNumElems();
435 bool FoundZero = false;
436 for (unsigned I = 0; I != ArgLength; ++I) {
437 if (!Arg.isElementInitialized(I))
438 return false;
439
440 if (Arg.elem<int8_t>(I) == 0) {
441 FoundZero = true;
442 break;
443 }
444 Str += Arg.elem<char>(I);
445 }
446
447 // If we didn't find a NUL byte, diagnose as a one-past-the-end read.
448 if (!FoundZero)
449 return CheckRange(S, OpPC, Arg.atIndex(ArgLength), AK_Read);
450
451 // Treat empty strings as if they were zero.
452 if (Str.empty())
453 Fill = llvm::APInt(32, 0);
454 else if (StringRef(Str).getAsInteger(0, Fill))
455 return false;
456
457 const llvm::fltSemantics &TargetSemantics =
459 Call->getDirectCallee()->getReturnType());
460
461 Floating Result = S.allocFloat(TargetSemantics);
463 if (Signaling)
464 Result.copy(
465 llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
466 else
467 Result.copy(
468 llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
469 } else {
470 // Prior to IEEE 754-2008, architectures were allowed to choose whether
471 // the first bit of their significand was set for qNaN or sNaN. MIPS chose
472 // a different encoding to what became a standard in 2008, and for pre-
473 // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as
474 // sNaN. This is now known as "legacy NaN" encoding.
475 if (Signaling)
476 Result.copy(
477 llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
478 else
479 Result.copy(
480 llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
481 }
482
484 return true;
485}
486
488 const InterpFrame *Frame,
489 const CallExpr *Call) {
490 const llvm::fltSemantics &TargetSemantics =
492 Call->getDirectCallee()->getReturnType());
493
494 Floating Result = S.allocFloat(TargetSemantics);
495 Result.copy(APFloat::getInf(TargetSemantics));
497 return true;
498}
499
501 const InterpFrame *Frame) {
502 const Floating &Arg2 = S.Stk.pop<Floating>();
503 const Floating &Arg1 = S.Stk.pop<Floating>();
504 Floating Result = S.allocFloat(Arg1.getSemantics());
505
506 APFloat Copy = Arg1.getAPFloat();
507 Copy.copySign(Arg2.getAPFloat());
508 Result.copy(Copy);
510
511 return true;
512}
513
515 const InterpFrame *Frame, bool IsNumBuiltin) {
516 const Floating &RHS = S.Stk.pop<Floating>();
517 const Floating &LHS = S.Stk.pop<Floating>();
518 Floating Result = S.allocFloat(LHS.getSemantics());
519
520 if (IsNumBuiltin)
521 Result.copy(llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()));
522 else
523 Result.copy(minnum(LHS.getAPFloat(), RHS.getAPFloat()));
525 return true;
526}
527
529 const InterpFrame *Frame, bool IsNumBuiltin) {
530 const Floating &RHS = S.Stk.pop<Floating>();
531 const Floating &LHS = S.Stk.pop<Floating>();
532 Floating Result = S.allocFloat(LHS.getSemantics());
533
534 if (IsNumBuiltin)
535 Result.copy(llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()));
536 else
537 Result.copy(maxnum(LHS.getAPFloat(), RHS.getAPFloat()));
539 return true;
540}
541
542/// Defined as __builtin_isnan(...), to accommodate the fact that it can
543/// take a float, double, long double, etc.
544/// But for us, that's all a Floating anyway.
546 const InterpFrame *Frame,
547 const CallExpr *Call) {
548 const Floating &Arg = S.Stk.pop<Floating>();
549
550 pushInteger(S, Arg.isNan(), Call->getType());
551 return true;
552}
553
555 const InterpFrame *Frame,
556 const CallExpr *Call) {
557 const Floating &Arg = S.Stk.pop<Floating>();
558
559 pushInteger(S, Arg.isSignaling(), Call->getType());
560 return true;
561}
562
564 const InterpFrame *Frame, bool CheckSign,
565 const CallExpr *Call) {
566 const Floating &Arg = S.Stk.pop<Floating>();
567 APFloat F = Arg.getAPFloat();
568 bool IsInf = F.isInfinity();
569
570 if (CheckSign)
571 pushInteger(S, IsInf ? (F.isNegative() ? -1 : 1) : 0, Call->getType());
572 else
573 pushInteger(S, IsInf, Call->getType());
574 return true;
575}
576
578 const InterpFrame *Frame,
579 const CallExpr *Call) {
580 const Floating &Arg = S.Stk.pop<Floating>();
581
582 pushInteger(S, Arg.isFinite(), Call->getType());
583 return true;
584}
585
587 const InterpFrame *Frame,
588 const CallExpr *Call) {
589 const Floating &Arg = S.Stk.pop<Floating>();
590
591 pushInteger(S, Arg.isNormal(), Call->getType());
592 return true;
593}
594
596 const InterpFrame *Frame,
597 const CallExpr *Call) {
598 const Floating &Arg = S.Stk.pop<Floating>();
599
600 pushInteger(S, Arg.isDenormal(), Call->getType());
601 return true;
602}
603
605 const InterpFrame *Frame,
606 const CallExpr *Call) {
607 const Floating &Arg = S.Stk.pop<Floating>();
608
609 pushInteger(S, Arg.isZero(), Call->getType());
610 return true;
611}
612
614 const InterpFrame *Frame,
615 const CallExpr *Call) {
616 const Floating &Arg = S.Stk.pop<Floating>();
617
618 pushInteger(S, Arg.isNegative(), Call->getType());
619 return true;
620}
621
623 const CallExpr *Call, unsigned ID) {
624 const Floating &RHS = S.Stk.pop<Floating>();
625 const Floating &LHS = S.Stk.pop<Floating>();
626
628 S,
629 [&] {
630 switch (ID) {
631 case Builtin::BI__builtin_isgreater:
632 return LHS > RHS;
633 case Builtin::BI__builtin_isgreaterequal:
634 return LHS >= RHS;
635 case Builtin::BI__builtin_isless:
636 return LHS < RHS;
637 case Builtin::BI__builtin_islessequal:
638 return LHS <= RHS;
639 case Builtin::BI__builtin_islessgreater: {
640 ComparisonCategoryResult Cmp = LHS.compare(RHS);
643 }
644 case Builtin::BI__builtin_isunordered:
646 default:
647 llvm_unreachable("Unexpected builtin ID: Should be a floating point "
648 "comparison function");
649 }
650 }(),
651 Call->getType());
652 return true;
653}
654
655/// First parameter to __builtin_isfpclass is the floating value, the
656/// second one is an integral value.
658 const InterpFrame *Frame,
659 const CallExpr *Call) {
660 APSInt FPClassArg;
661 if (!popToAPSInt(S, Call->getArg(1), FPClassArg))
662 return false;
663 const Floating &F = S.Stk.pop<Floating>();
664
665 int32_t Result = static_cast<int32_t>(
666 (F.classify() & std::move(FPClassArg)).getZExtValue());
667 pushInteger(S, Result, Call->getType());
668
669 return true;
670}
671
672/// Five int values followed by one floating value.
673/// __builtin_fpclassify(int, int, int, int, int, float)
675 const InterpFrame *Frame,
676 const CallExpr *Call) {
677 const Floating &Val = S.Stk.pop<Floating>();
678
679 PrimType IntT = *S.getContext().classify(Call->getArg(0));
680 APSInt Values[5];
681 for (unsigned I = 0; I != 5; ++I) {
682 if (!popToAPSInt(S.Stk, IntT, Values[4 - I]))
683 return false;
684 }
685
686 unsigned Index;
687 switch (Val.getCategory()) {
688 case APFloat::fcNaN:
689 Index = 0;
690 break;
691 case APFloat::fcInfinity:
692 Index = 1;
693 break;
694 case APFloat::fcNormal:
695 Index = Val.isDenormal() ? 3 : 2;
696 break;
697 case APFloat::fcZero:
698 Index = 4;
699 break;
700 }
701
702 // The last argument is first on the stack.
703 assert(Index <= 4);
704
705 pushInteger(S, Values[Index], Call->getType());
706 return true;
707}
708
709static inline Floating abs(InterpState &S, const Floating &In) {
710 if (!In.isNegative())
711 return In;
712
713 Floating Output = S.allocFloat(In.getSemantics());
714 APFloat New = In.getAPFloat();
715 New.changeSign();
716 Output.copy(New);
717 return Output;
718}
719
720// The C standard says "fabs raises no floating-point exceptions,
721// even if x is a signaling NaN. The returned value is independent of
722// the current rounding direction mode." Therefore constant folding can
723// proceed without regard to the floating point settings.
724// Reference, WG14 N2478 F.10.4.3
726 const InterpFrame *Frame) {
727 const Floating &Val = S.Stk.pop<Floating>();
728 S.Stk.push<Floating>(abs(S, Val));
729 return true;
730}
731
733 const InterpFrame *Frame,
734 const CallExpr *Call) {
735 APSInt Val;
736 if (!popToAPSInt(S, Call->getArg(0), Val))
737 return false;
738 if (Val ==
739 APSInt(APInt::getSignedMinValue(Val.getBitWidth()), /*IsUnsigned=*/false))
740 return false;
741 if (Val.isNegative())
742 Val.negate();
743 pushInteger(S, Val, Call->getType());
744 return true;
745}
746
748 const InterpFrame *Frame,
749 const CallExpr *Call) {
750 APSInt Val;
751 if (Call->getArg(0)->getType()->isExtVectorBoolType()) {
752 const Pointer &Arg = S.Stk.pop<Pointer>();
753 Val = convertBoolVectorToInt(Arg);
754 } else {
755 if (!popToAPSInt(S, Call->getArg(0), Val))
756 return false;
757 }
758 pushInteger(S, Val.popcount(), Call->getType());
759 return true;
760}
761
763 const InterpFrame *Frame,
764 const CallExpr *Call,
765 unsigned DataBytes) {
766 uint64_t DataVal;
767 if (!popToUInt64(S, Call->getArg(1), DataVal))
768 return false;
769 uint64_t CRCVal;
770 if (!popToUInt64(S, Call->getArg(0), CRCVal))
771 return false;
772
773 // CRC32C polynomial (iSCSI polynomial, bit-reversed)
774 static const uint32_t CRC32C_POLY = 0x82F63B78;
775
776 // Process each byte
777 uint32_t Result = static_cast<uint32_t>(CRCVal);
778 for (unsigned I = 0; I != DataBytes; ++I) {
779 uint8_t Byte = static_cast<uint8_t>((DataVal >> (I * 8)) & 0xFF);
780 Result ^= Byte;
781 for (int J = 0; J != 8; ++J) {
782 Result = (Result >> 1) ^ ((Result & 1) ? CRC32C_POLY : 0);
783 }
784 }
785
786 pushInteger(S, Result, Call->getType());
787 return true;
788}
789
791 const InterpFrame *Frame,
792 const CallExpr *Call) {
793 // This is an unevaluated call, so there are no arguments on the stack.
794 assert(Call->getNumArgs() == 1);
795 const Expr *Arg = Call->getArg(0);
796
797 GCCTypeClass ResultClass =
799 int32_t ReturnVal = static_cast<int32_t>(ResultClass);
800 pushInteger(S, ReturnVal, Call->getType());
801 return true;
802}
803
804// __builtin_expect(long, long)
805// __builtin_expect_with_probability(long, long, double)
807 const InterpFrame *Frame,
808 const CallExpr *Call) {
809 // The return value is simply the value of the first parameter.
810 // We ignore the probability.
811 unsigned NumArgs = Call->getNumArgs();
812 assert(NumArgs == 2 || NumArgs == 3);
813
814 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
815 if (NumArgs == 3)
816 S.Stk.discard<Floating>();
817 discard(S.Stk, ArgT);
818
819 APSInt Val;
820 if (!popToAPSInt(S.Stk, ArgT, Val))
821 return false;
822 pushInteger(S, Val, Call->getType());
823 return true;
824}
825
827 const InterpFrame *Frame,
828 const CallExpr *Call) {
829#ifndef NDEBUG
830 assert(Call->getArg(0)->isLValue());
831 PrimType PtrT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr);
832 assert(PtrT == PT_Ptr &&
833 "Unsupported pointer type passed to __builtin_addressof()");
834#endif
835 return true;
836}
837
839 const InterpFrame *Frame,
840 const CallExpr *Call) {
841 return Call->getDirectCallee()->isConstexpr();
842}
843
845 const InterpFrame *Frame,
846 const CallExpr *Call) {
847 APSInt Arg;
848 if (!popToAPSInt(S, Call->getArg(0), Arg))
849 return false;
850
852 Arg.getZExtValue());
853 pushInteger(S, Result, Call->getType());
854 return true;
855}
856
857// Two integral values followed by a pointer (lhs, rhs, resultOut)
859 const CallExpr *Call,
860 unsigned BuiltinOp) {
861 const Pointer &ResultPtr = S.Stk.pop<Pointer>();
862 if (ResultPtr.isDummy() || !ResultPtr.isBlockPointer())
863 return false;
864
865 PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
866 PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());
867 APSInt RHS;
868 if (!popToAPSInt(S.Stk, RHST, RHS))
869 return false;
870 APSInt LHS;
871 if (!popToAPSInt(S.Stk, LHST, LHS))
872 return false;
873 QualType ResultType = Call->getArg(2)->getType()->getPointeeType();
874 PrimType ResultT = *S.getContext().classify(ResultType);
875 bool Overflow;
876
878 if (BuiltinOp == Builtin::BI__builtin_add_overflow ||
879 BuiltinOp == Builtin::BI__builtin_sub_overflow ||
880 BuiltinOp == Builtin::BI__builtin_mul_overflow) {
881 bool IsSigned = LHS.isSigned() || RHS.isSigned() ||
883 bool AllSigned = LHS.isSigned() && RHS.isSigned() &&
885 uint64_t LHSSize = LHS.getBitWidth();
886 uint64_t RHSSize = RHS.getBitWidth();
887 uint64_t ResultSize = S.getASTContext().getIntWidth(ResultType);
888 uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize);
889
890 // Add an additional bit if the signedness isn't uniformly agreed to. We
891 // could do this ONLY if there is a signed and an unsigned that both have
892 // MaxBits, but the code to check that is pretty nasty. The issue will be
893 // caught in the shrink-to-result later anyway.
894 if (IsSigned && !AllSigned)
895 ++MaxBits;
896
897 LHS = APSInt(LHS.extOrTrunc(MaxBits), !IsSigned);
898 RHS = APSInt(RHS.extOrTrunc(MaxBits), !IsSigned);
899 Result = APSInt(MaxBits, !IsSigned);
900 }
901
902 // Find largest int.
903 switch (BuiltinOp) {
904 default:
905 llvm_unreachable("Invalid value for BuiltinOp");
906 case Builtin::BI__builtin_add_overflow:
907 case Builtin::BI__builtin_sadd_overflow:
908 case Builtin::BI__builtin_saddl_overflow:
909 case Builtin::BI__builtin_saddll_overflow:
910 case Builtin::BI__builtin_uadd_overflow:
911 case Builtin::BI__builtin_uaddl_overflow:
912 case Builtin::BI__builtin_uaddll_overflow:
913 Result = LHS.isSigned() ? LHS.sadd_ov(RHS, Overflow)
914 : LHS.uadd_ov(RHS, Overflow);
915 break;
916 case Builtin::BI__builtin_sub_overflow:
917 case Builtin::BI__builtin_ssub_overflow:
918 case Builtin::BI__builtin_ssubl_overflow:
919 case Builtin::BI__builtin_ssubll_overflow:
920 case Builtin::BI__builtin_usub_overflow:
921 case Builtin::BI__builtin_usubl_overflow:
922 case Builtin::BI__builtin_usubll_overflow:
923 Result = LHS.isSigned() ? LHS.ssub_ov(RHS, Overflow)
924 : LHS.usub_ov(RHS, Overflow);
925 break;
926 case Builtin::BI__builtin_mul_overflow:
927 case Builtin::BI__builtin_smul_overflow:
928 case Builtin::BI__builtin_smull_overflow:
929 case Builtin::BI__builtin_smulll_overflow:
930 case Builtin::BI__builtin_umul_overflow:
931 case Builtin::BI__builtin_umull_overflow:
932 case Builtin::BI__builtin_umulll_overflow:
933 Result = LHS.isSigned() ? LHS.smul_ov(RHS, Overflow)
934 : LHS.umul_ov(RHS, Overflow);
935 break;
936 }
937
938 // In the case where multiple sizes are allowed, truncate and see if
939 // the values are the same.
940 if (BuiltinOp == Builtin::BI__builtin_add_overflow ||
941 BuiltinOp == Builtin::BI__builtin_sub_overflow ||
942 BuiltinOp == Builtin::BI__builtin_mul_overflow) {
943 // APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead,
944 // since it will give us the behavior of a TruncOrSelf in the case where
945 // its parameter <= its size. We previously set Result to be at least the
946 // integer width of the result, so getIntWidth(ResultType) <=
947 // Result.BitWidth
948 APSInt Temp = Result.extOrTrunc(S.getASTContext().getIntWidth(ResultType));
949 Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType());
950
951 if (!APSInt::isSameValue(Temp, Result))
952 Overflow = true;
953 Result = std::move(Temp);
954 }
955
956 // Write Result to ResultPtr and put Overflow on the stack.
957 assignIntegral(S, ResultPtr, ResultT, Result);
958 if (ResultPtr.canBeInitialized())
959 ResultPtr.initialize();
960
961 assert(Call->getDirectCallee()->getReturnType()->isBooleanType());
962 S.Stk.push<Boolean>(Overflow);
963 return true;
964}
965
966/// Three integral values followed by a pointer (lhs, rhs, carry, carryOut).
968 const InterpFrame *Frame,
969 const CallExpr *Call, unsigned BuiltinOp) {
970 const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();
971 PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());
972 PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
973 APSInt CarryIn;
974 if (!popToAPSInt(S.Stk, LHST, CarryIn))
975 return false;
976 APSInt RHS;
977 if (!popToAPSInt(S.Stk, RHST, RHS))
978 return false;
979 APSInt LHS;
980 if (!popToAPSInt(S.Stk, LHST, LHS))
981 return false;
982
983 if (CarryOutPtr.isDummy() || !CarryOutPtr.isBlockPointer())
984 return false;
985
986 APSInt CarryOut;
987
989 // Copy the number of bits and sign.
990 Result = LHS;
991 CarryOut = LHS;
992
993 bool FirstOverflowed = false;
994 bool SecondOverflowed = false;
995 switch (BuiltinOp) {
996 default:
997 llvm_unreachable("Invalid value for BuiltinOp");
998 case Builtin::BI__builtin_addcb:
999 case Builtin::BI__builtin_addcs:
1000 case Builtin::BI__builtin_addc:
1001 case Builtin::BI__builtin_addcl:
1002 case Builtin::BI__builtin_addcll:
1003 Result =
1004 LHS.uadd_ov(RHS, FirstOverflowed).uadd_ov(CarryIn, SecondOverflowed);
1005 break;
1006 case Builtin::BI__builtin_subcb:
1007 case Builtin::BI__builtin_subcs:
1008 case Builtin::BI__builtin_subc:
1009 case Builtin::BI__builtin_subcl:
1010 case Builtin::BI__builtin_subcll:
1011 Result =
1012 LHS.usub_ov(RHS, FirstOverflowed).usub_ov(CarryIn, SecondOverflowed);
1013 break;
1014 }
1015 // It is possible for both overflows to happen but CGBuiltin uses an OR so
1016 // this is consistent.
1017 CarryOut = (uint64_t)(FirstOverflowed | SecondOverflowed);
1018
1019 QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
1020 PrimType CarryOutT = *S.getContext().classify(CarryOutType);
1021 assignIntegral(S, CarryOutPtr, CarryOutT, CarryOut);
1022 CarryOutPtr.initialize();
1023
1024 assert(Call->getType() == Call->getArg(0)->getType());
1025 pushInteger(S, Result, Call->getType());
1026 return true;
1027}
1028
1030 const InterpFrame *Frame, const CallExpr *Call,
1031 unsigned BuiltinOp) {
1032
1033 std::optional<APSInt> Fallback;
1034 if (BuiltinOp == Builtin::BI__builtin_clzg && Call->getNumArgs() == 2) {
1035 APSInt FallbackVal;
1036 if (!popToAPSInt(S, Call->getArg(1), FallbackVal))
1037 return false;
1038 Fallback = FallbackVal;
1039 }
1040
1041 APSInt Val;
1042 if (Call->getArg(0)->getType()->isExtVectorBoolType()) {
1043 const Pointer &Arg = S.Stk.pop<Pointer>();
1044 Val = convertBoolVectorToInt(Arg);
1045 } else {
1046 if (!popToAPSInt(S, Call->getArg(0), Val))
1047 return false;
1048 }
1049
1050 // When the argument is 0, the result of GCC builtins is undefined, whereas
1051 // for Microsoft intrinsics, the result is the bit-width of the argument.
1052 bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&
1053 BuiltinOp != Builtin::BI__lzcnt &&
1054 BuiltinOp != Builtin::BI__lzcnt64;
1055
1056 if (Val == 0) {
1057 if (Fallback) {
1058 pushInteger(S, *Fallback, Call->getType());
1059 return true;
1060 }
1061
1062 if (ZeroIsUndefined)
1063 return false;
1064 }
1065
1066 pushInteger(S, Val.countl_zero(), Call->getType());
1067 return true;
1068}
1069
1071 const InterpFrame *Frame, const CallExpr *Call,
1072 unsigned BuiltinID) {
1073 std::optional<APSInt> Fallback;
1074 if (BuiltinID == Builtin::BI__builtin_ctzg && Call->getNumArgs() == 2) {
1075 APSInt FallbackVal;
1076 if (!popToAPSInt(S, Call->getArg(1), FallbackVal))
1077 return false;
1078 Fallback = FallbackVal;
1079 }
1080
1081 APSInt Val;
1082 if (Call->getArg(0)->getType()->isExtVectorBoolType()) {
1083 const Pointer &Arg = S.Stk.pop<Pointer>();
1084 Val = convertBoolVectorToInt(Arg);
1085 } else {
1086 if (!popToAPSInt(S, Call->getArg(0), Val))
1087 return false;
1088 }
1089
1090 if (Val == 0) {
1091 if (Fallback) {
1092 pushInteger(S, *Fallback, Call->getType());
1093 return true;
1094 }
1095 return false;
1096 }
1097
1098 pushInteger(S, Val.countr_zero(), Call->getType());
1099 return true;
1100}
1101
1103 const InterpFrame *Frame,
1104 const CallExpr *Call) {
1105 APSInt Val;
1106 if (!popToAPSInt(S, Call->getArg(0), Val))
1107 return false;
1108 if (Val.getBitWidth() == 8 || Val.getBitWidth() == 1)
1109 pushInteger(S, Val, Call->getType());
1110 else
1111 pushInteger(S, Val.byteSwap(), Call->getType());
1112 return true;
1113}
1114
1115/// bool __atomic_always_lock_free(size_t, void const volatile*)
1116/// bool __atomic_is_lock_free(size_t, void const volatile*)
1118 const InterpFrame *Frame,
1119 const CallExpr *Call,
1120 unsigned BuiltinOp) {
1121 auto returnBool = [&S](bool Value) -> bool {
1122 S.Stk.push<Boolean>(Value);
1123 return true;
1124 };
1125
1126 const Pointer &Ptr = S.Stk.pop<Pointer>();
1127 uint64_t SizeVal;
1128 if (!popToUInt64(S, Call->getArg(0), SizeVal))
1129 return false;
1130
1131 // For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power
1132 // of two less than or equal to the maximum inline atomic width, we know it
1133 // is lock-free. If the size isn't a power of two, or greater than the
1134 // maximum alignment where we promote atomics, we know it is not lock-free
1135 // (at least not in the sense of atomic_is_lock_free). Otherwise,
1136 // the answer can only be determined at runtime; for example, 16-byte
1137 // atomics have lock-free implementations on some, but not all,
1138 // x86-64 processors.
1139
1140 // Check power-of-two.
1141 CharUnits Size = CharUnits::fromQuantity(SizeVal);
1142 if (Size.isPowerOfTwo()) {
1143 // Check against inlining width.
1144 unsigned InlineWidthBits =
1146 if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits)) {
1147
1148 // OK, we will inline appropriately-aligned operations of this size,
1149 // and _Atomic(T) is appropriately-aligned.
1150 if (Size == CharUnits::One())
1151 return returnBool(true);
1152
1153 // Same for null pointers.
1154 assert(BuiltinOp != Builtin::BI__c11_atomic_is_lock_free);
1155 if (Ptr.isZero())
1156 return returnBool(true);
1157
1158 if (Ptr.isIntegralPointer()) {
1159 uint64_t IntVal = Ptr.getIntegerRepresentation();
1160 if (APSInt(APInt(64, IntVal, false), true).isAligned(Size.getAsAlign()))
1161 return returnBool(true);
1162 }
1163
1164 const Expr *PtrArg = Call->getArg(1);
1165 // Otherwise, check if the type's alignment against Size.
1166 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(PtrArg)) {
1167 // Drop the potential implicit-cast to 'const volatile void*', getting
1168 // the underlying type.
1169 if (ICE->getCastKind() == CK_BitCast)
1170 PtrArg = ICE->getSubExpr();
1171 }
1172
1173 if (const auto *PtrTy = PtrArg->getType()->getAs<PointerType>()) {
1174 QualType PointeeType = PtrTy->getPointeeType();
1175 if (!PointeeType->isIncompleteType() &&
1176 S.getASTContext().getTypeAlignInChars(PointeeType) >= Size) {
1177 // OK, we will inline operations on this object.
1178 return returnBool(true);
1179 }
1180 }
1181 }
1182 }
1183
1184 if (BuiltinOp == Builtin::BI__atomic_always_lock_free)
1185 return returnBool(false);
1186
1187 return Invalid(S, OpPC);
1188}
1189
1190/// bool __c11_atomic_is_lock_free(size_t)
1192 CodePtr OpPC,
1193 const InterpFrame *Frame,
1194 const CallExpr *Call) {
1195 uint64_t SizeVal;
1196 if (!popToUInt64(S, Call->getArg(0), SizeVal))
1197 return false;
1198
1199 CharUnits Size = CharUnits::fromQuantity(SizeVal);
1200 if (Size.isPowerOfTwo()) {
1201 // Check against inlining width.
1202 unsigned InlineWidthBits =
1204 if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits)) {
1205 S.Stk.push<Boolean>(true);
1206 return true;
1207 }
1208 }
1209
1210 return false; // returnBool(false);
1211}
1212
1213/// __builtin_complex(Float A, float B);
1215 const InterpFrame *Frame,
1216 const CallExpr *Call) {
1217 const Floating &Arg2 = S.Stk.pop<Floating>();
1218 const Floating &Arg1 = S.Stk.pop<Floating>();
1219 Pointer &Result = S.Stk.peek<Pointer>();
1220
1221 Result.elem<Floating>(0) = Arg1;
1222 Result.elem<Floating>(1) = Arg2;
1223 Result.initializeAllElements();
1224
1225 return true;
1226}
1227
1228/// __builtin_is_aligned()
1229/// __builtin_align_up()
1230/// __builtin_align_down()
1231/// The first parameter is either an integer or a pointer.
1232/// The second parameter is the requested alignment as an integer.
1234 const InterpFrame *Frame,
1235 const CallExpr *Call,
1236 unsigned BuiltinOp) {
1237 APSInt Alignment;
1238 if (!popToAPSInt(S, Call->getArg(1), Alignment))
1239 return false;
1240
1241 if (Alignment < 0 || !Alignment.isPowerOf2()) {
1242 S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment;
1243 return false;
1244 }
1245 unsigned SrcWidth = S.getASTContext().getIntWidth(Call->getArg(0)->getType());
1246 APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1));
1247 if (APSInt::compareValues(Alignment, MaxValue) > 0) {
1248 S.FFDiag(Call, diag::note_constexpr_alignment_too_big)
1249 << MaxValue << Call->getArg(0)->getType() << Alignment;
1250 return false;
1251 }
1252
1253 // The first parameter is either an integer or a pointer.
1254 PrimType FirstArgT = *S.Ctx.classify(Call->getArg(0));
1255
1256 if (isIntegerType(FirstArgT)) {
1257 APSInt Src;
1258 if (!popToAPSInt(S.Stk, FirstArgT, Src))
1259 return false;
1260 APInt AlignMinusOne = Alignment.extOrTrunc(Src.getBitWidth()) - 1;
1261 if (BuiltinOp == Builtin::BI__builtin_align_up) {
1262 APSInt AlignedVal =
1263 APSInt((Src + AlignMinusOne) & ~AlignMinusOne, Src.isUnsigned());
1264 pushInteger(S, AlignedVal, Call->getType());
1265 } else if (BuiltinOp == Builtin::BI__builtin_align_down) {
1266 APSInt AlignedVal = APSInt(Src & ~AlignMinusOne, Src.isUnsigned());
1267 pushInteger(S, AlignedVal, Call->getType());
1268 } else {
1269 assert(*S.Ctx.classify(Call->getType()) == PT_Bool);
1270 S.Stk.push<Boolean>((Src & AlignMinusOne) == 0);
1271 }
1272 return true;
1273 }
1274 assert(FirstArgT == PT_Ptr);
1275 const Pointer &Ptr = S.Stk.pop<Pointer>();
1276 if (!Ptr.isBlockPointer())
1277 return false;
1278
1279 const ValueDecl *PtrDecl = Ptr.getDeclDesc()->asValueDecl();
1280 // We need a pointer for a declaration here.
1281 if (!PtrDecl) {
1282 if (BuiltinOp == Builtin::BI__builtin_is_aligned)
1283 S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_compute)
1284 << Alignment;
1285 else
1286 S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_adjust)
1287 << Alignment;
1288 return false;
1289 }
1290
1291 // For one-past-end pointers, we can't call getIndex() since it asserts.
1292 // Use getNumElems() instead which gives the correct index for past-end.
1293 unsigned PtrOffset =
1294 Ptr.isElementPastEnd() ? Ptr.getNumElems() : Ptr.getIndex();
1295 CharUnits BaseAlignment = S.getASTContext().getDeclAlign(PtrDecl);
1296 CharUnits PtrAlign =
1297 BaseAlignment.alignmentAtOffset(CharUnits::fromQuantity(PtrOffset));
1298
1299 if (BuiltinOp == Builtin::BI__builtin_is_aligned) {
1300 if (PtrAlign.getQuantity() >= Alignment) {
1301 S.Stk.push<Boolean>(true);
1302 return true;
1303 }
1304 // If the alignment is not known to be sufficient, some cases could still
1305 // be aligned at run time. However, if the requested alignment is less or
1306 // equal to the base alignment and the offset is not aligned, we know that
1307 // the run-time value can never be aligned.
1308 if (BaseAlignment.getQuantity() >= Alignment &&
1309 PtrAlign.getQuantity() < Alignment) {
1310 S.Stk.push<Boolean>(false);
1311 return true;
1312 }
1313
1314 S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_compute)
1315 << Alignment;
1316 return false;
1317 }
1318
1319 assert(BuiltinOp == Builtin::BI__builtin_align_down ||
1320 BuiltinOp == Builtin::BI__builtin_align_up);
1321
1322 // For align_up/align_down, we can return the same value if the alignment
1323 // is known to be greater or equal to the requested value.
1324 if (PtrAlign.getQuantity() >= Alignment) {
1325 S.Stk.push<Pointer>(Ptr);
1326 return true;
1327 }
1328
1329 // The alignment could be greater than the minimum at run-time, so we cannot
1330 // infer much about the resulting pointer value. One case is possible:
1331 // For `_Alignas(32) char buf[N]; __builtin_align_down(&buf[idx], 32)` we
1332 // can infer the correct index if the requested alignment is smaller than
1333 // the base alignment so we can perform the computation on the offset.
1334 if (BaseAlignment.getQuantity() >= Alignment) {
1335 assert(Alignment.getBitWidth() <= 64 &&
1336 "Cannot handle > 64-bit address-space");
1337 uint64_t Alignment64 = Alignment.getZExtValue();
1338 CharUnits NewOffset =
1339 CharUnits::fromQuantity(BuiltinOp == Builtin::BI__builtin_align_down
1340 ? llvm::alignDown(PtrOffset, Alignment64)
1341 : llvm::alignTo(PtrOffset, Alignment64));
1342
1343 S.Stk.push<Pointer>(Ptr.atIndex(NewOffset.getQuantity()));
1344 return true;
1345 }
1346
1347 // Otherwise, we cannot constant-evaluate the result.
1348 S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_adjust) << Alignment;
1349 return false;
1350}
1351
1352/// __builtin_assume_aligned(Ptr, Alignment[, ExtraOffset])
1354 const InterpFrame *Frame,
1355 const CallExpr *Call) {
1356 assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3);
1357
1358 std::optional<APSInt> ExtraOffset;
1359 if (Call->getNumArgs() == 3) {
1360 APSInt ExtraOffsetVal;
1361 if (!popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(2)), ExtraOffsetVal))
1362 return false;
1363 ExtraOffset = ExtraOffsetVal;
1364 }
1365
1366 APSInt Alignment;
1367 if (!popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)), Alignment))
1368 return false;
1369 const Pointer &Ptr = S.Stk.pop<Pointer>();
1370
1371 CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue());
1372
1373 // If there is a base object, then it must have the correct alignment.
1374 if (Ptr.isBlockPointer()) {
1375 CharUnits BaseAlignment;
1376 if (const auto *VD = Ptr.getDeclDesc()->asValueDecl())
1377 BaseAlignment = S.getASTContext().getDeclAlign(VD);
1378 else if (const auto *E = Ptr.getDeclDesc()->asExpr())
1379 BaseAlignment = GetAlignOfExpr(S.getASTContext(), E, UETT_AlignOf);
1380
1381 if (BaseAlignment < Align) {
1382 S.CCEDiag(Call->getArg(0),
1383 diag::note_constexpr_baa_insufficient_alignment)
1384 << 0 << BaseAlignment.getQuantity() << Align.getQuantity();
1385 return false;
1386 }
1387 }
1388
1389 APValue AV = Ptr.toAPValue(S.getASTContext());
1390 CharUnits AVOffset = AV.getLValueOffset();
1391 if (ExtraOffset)
1392 AVOffset -= CharUnits::fromQuantity(ExtraOffset->getZExtValue());
1393 if (AVOffset.alignTo(Align) != AVOffset) {
1394 if (Ptr.isBlockPointer())
1395 S.CCEDiag(Call->getArg(0),
1396 diag::note_constexpr_baa_insufficient_alignment)
1397 << 1 << AVOffset.getQuantity() << Align.getQuantity();
1398 else
1399 S.CCEDiag(Call->getArg(0),
1400 diag::note_constexpr_baa_value_insufficient_alignment)
1401 << AVOffset.getQuantity() << Align.getQuantity();
1402 return false;
1403 }
1404
1405 S.Stk.push<Pointer>(Ptr);
1406 return true;
1407}
1408
1409/// (CarryIn, LHS, RHS, Result)
1411 CodePtr OpPC,
1412 const InterpFrame *Frame,
1413 const CallExpr *Call,
1414 unsigned BuiltinOp) {
1415 if (Call->getNumArgs() != 4 || !Call->getArg(0)->getType()->isIntegerType() ||
1416 !Call->getArg(1)->getType()->isIntegerType() ||
1417 !Call->getArg(2)->getType()->isIntegerType())
1418 return false;
1419
1420 const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();
1421
1422 APSInt RHS;
1423 if (!popToAPSInt(S, Call->getArg(2), RHS))
1424 return false;
1425 APSInt LHS;
1426 if (!popToAPSInt(S, Call->getArg(1), LHS))
1427 return false;
1428 APSInt CarryIn;
1429 if (!popToAPSInt(S, Call->getArg(0), CarryIn))
1430 return false;
1431
1432 bool IsAdd = BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u32 ||
1433 BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u64;
1434
1435 unsigned BitWidth = LHS.getBitWidth();
1436 unsigned CarryInBit = CarryIn.ugt(0) ? 1 : 0;
1437 APInt ExResult =
1438 IsAdd ? (LHS.zext(BitWidth + 1) + (RHS.zext(BitWidth + 1) + CarryInBit))
1439 : (LHS.zext(BitWidth + 1) - (RHS.zext(BitWidth + 1) + CarryInBit));
1440
1441 APInt Result = ExResult.extractBits(BitWidth, 0);
1442 APSInt CarryOut =
1443 APSInt(ExResult.extractBits(1, BitWidth), /*IsUnsigned=*/true);
1444
1445 QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
1446 PrimType CarryOutT = *S.getContext().classify(CarryOutType);
1447 assignIntegral(S, CarryOutPtr, CarryOutT, APSInt(std::move(Result), true));
1448
1449 pushInteger(S, CarryOut, Call->getType());
1450
1451 return true;
1452}
1453
1455 CodePtr OpPC,
1456 const InterpFrame *Frame,
1457 const CallExpr *Call) {
1460 pushInteger(S, Layout.size().getQuantity(), Call->getType());
1461 return true;
1462}
1463
1464static bool
1466 const InterpFrame *Frame,
1467 const CallExpr *Call) {
1468 const auto &Ptr = S.Stk.pop<Pointer>();
1469 assert(Ptr.getFieldDesc()->isPrimitiveArray());
1470
1471 // This should be created for a StringLiteral, so always holds at least
1472 // one array element.
1473 assert(Ptr.getFieldDesc()->getNumElems() >= 1);
1474 uint64_t Result = getPointerAuthStableSipHash(
1475 cast<StringLiteral>(Ptr.getFieldDesc()->asExpr())->getString());
1476 pushInteger(S, Result, Call->getType());
1477 return true;
1478}
1479
1481 const InterpFrame *Frame,
1482 const CallExpr *Call) {
1483 const ASTContext &ASTCtx = S.getASTContext();
1484 uint64_t BitWidth = ASTCtx.getTypeSize(ASTCtx.getSizeType());
1485 auto Mode =
1486 ASTCtx.getLangOpts().AllocTokenMode.value_or(llvm::DefaultAllocTokenMode);
1487 auto MaxTokensOpt = ASTCtx.getLangOpts().AllocTokenMax;
1488 uint64_t MaxTokens =
1489 MaxTokensOpt.value_or(0) ? *MaxTokensOpt : (~0ULL >> (64 - BitWidth));
1490
1491 // We do not read any of the arguments; discard them.
1492 for (int I = Call->getNumArgs() - 1; I >= 0; --I)
1493 discard(S.Stk, S.getContext().classify(Call->getArg(I)).value_or(PT_Ptr));
1494
1495 // Note: Type inference from a surrounding cast is not supported in
1496 // constexpr evaluation.
1497 QualType AllocType = infer_alloc::inferPossibleType(Call, ASTCtx, nullptr);
1498 if (AllocType.isNull()) {
1499 S.CCEDiag(Call,
1500 diag::note_constexpr_infer_alloc_token_type_inference_failed);
1501 return false;
1502 }
1503
1504 auto ATMD = infer_alloc::getAllocTokenMetadata(AllocType, ASTCtx);
1505 if (!ATMD) {
1506 S.CCEDiag(Call, diag::note_constexpr_infer_alloc_token_no_metadata);
1507 return false;
1508 }
1509
1510 auto MaybeToken = llvm::getAllocToken(Mode, *ATMD, MaxTokens);
1511 if (!MaybeToken) {
1512 S.CCEDiag(Call, diag::note_constexpr_infer_alloc_token_stateful_mode);
1513 return false;
1514 }
1515
1516 pushInteger(S, llvm::APInt(BitWidth, *MaybeToken), ASTCtx.getSizeType());
1517 return true;
1518}
1519
1521 const InterpFrame *Frame,
1522 const CallExpr *Call) {
1523 // A call to __operator_new is only valid within std::allocate<>::allocate.
1524 // Walk up the call stack to find the appropriate caller and get the
1525 // element type from it.
1526 auto [NewCall, ElemType] = S.getStdAllocatorCaller("allocate");
1527
1528 if (ElemType.isNull()) {
1529 S.FFDiag(Call, S.getLangOpts().CPlusPlus20
1530 ? diag::note_constexpr_new_untyped
1531 : diag::note_constexpr_new);
1532 return false;
1533 }
1534 assert(NewCall);
1535
1536 if (ElemType->isIncompleteType() || ElemType->isFunctionType()) {
1537 S.FFDiag(Call, diag::note_constexpr_new_not_complete_object_type)
1538 << (ElemType->isIncompleteType() ? 0 : 1) << ElemType;
1539 return false;
1540 }
1541
1542 // We only care about the first parameter (the size), so discard all the
1543 // others.
1544 {
1545 unsigned NumArgs = Call->getNumArgs();
1546 assert(NumArgs >= 1);
1547
1548 // The std::nothrow_t arg never gets put on the stack.
1549 if (Call->getArg(NumArgs - 1)->getType()->isNothrowT())
1550 --NumArgs;
1551 auto Args = ArrayRef(Call->getArgs(), Call->getNumArgs());
1552 // First arg is needed.
1553 Args = Args.drop_front();
1554
1555 // Discard the rest.
1556 for (const Expr *Arg : Args)
1557 discard(S.Stk, *S.getContext().classify(Arg));
1558 }
1559
1560 APSInt Bytes;
1561 if (!popToAPSInt(S, Call->getArg(0), Bytes))
1562 return false;
1563 CharUnits ElemSize = S.getASTContext().getTypeSizeInChars(ElemType);
1564 assert(!ElemSize.isZero());
1565 // Divide the number of bytes by sizeof(ElemType), so we get the number of
1566 // elements we should allocate.
1567 APInt NumElems, Remainder;
1568 APInt ElemSizeAP(Bytes.getBitWidth(), ElemSize.getQuantity());
1569 APInt::udivrem(Bytes, ElemSizeAP, NumElems, Remainder);
1570 if (Remainder != 0) {
1571 // This likely indicates a bug in the implementation of 'std::allocator'.
1572 S.FFDiag(Call, diag::note_constexpr_operator_new_bad_size)
1573 << Bytes << APSInt(ElemSizeAP, true) << ElemType;
1574 return false;
1575 }
1576
1577 // NB: The same check we're using in CheckArraySize()
1578 if (NumElems.getActiveBits() >
1580 NumElems.ugt(Descriptor::MaxArrayElemBytes / ElemSize.getQuantity())) {
1581 // FIXME: NoThrow check?
1582 const SourceInfo &Loc = S.Current->getSource(OpPC);
1583 S.FFDiag(Loc, diag::note_constexpr_new_too_large)
1584 << NumElems.getZExtValue();
1585 return false;
1586 }
1587
1588 if (!CheckArraySize(S, OpPC, NumElems.getZExtValue()))
1589 return false;
1590
1591 bool IsArray = NumElems.ugt(1);
1592 OptPrimType ElemT = S.getContext().classify(ElemType);
1593 DynamicAllocator &Allocator = S.getAllocator();
1594 if (ElemT) {
1595 Block *B =
1596 Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(),
1598 assert(B);
1599 S.Stk.push<Pointer>(Pointer(B).atIndex(0));
1600 return true;
1601 }
1602
1603 assert(!ElemT);
1604
1605 // Composite arrays
1606 if (IsArray) {
1607 const Descriptor *Desc =
1608 S.P.createDescriptor(NewCall, ElemType.getTypePtr(), std::nullopt);
1609 Block *B =
1610 Allocator.allocate(Desc, NumElems.getZExtValue(), S.Ctx.getEvalID(),
1612 assert(B);
1613 S.Stk.push<Pointer>(Pointer(B).atIndex(0).narrow());
1614 return true;
1615 }
1616
1617 // Records. Still allocate them as single-element arrays.
1619 ElemType, NumElems, nullptr, ArraySizeModifier::Normal, 0);
1620
1621 const Descriptor *Desc = S.P.createDescriptor(NewCall, AllocType.getTypePtr(),
1623 Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(),
1625 assert(B);
1626 S.Stk.push<Pointer>(Pointer(B).atIndex(0).narrow());
1627 return true;
1628}
1629
1631 const InterpFrame *Frame,
1632 const CallExpr *Call) {
1633 const Expr *Source = nullptr;
1634 const Block *BlockToDelete = nullptr;
1635
1637 S.Stk.discard<Pointer>();
1638 return false;
1639 }
1640
1641 // This is permitted only within a call to std::allocator<T>::deallocate.
1642 if (!S.getStdAllocatorCaller("deallocate")) {
1643 S.FFDiag(Call);
1644 S.Stk.discard<Pointer>();
1645 return true;
1646 }
1647
1648 {
1649 const Pointer &Ptr = S.Stk.pop<Pointer>();
1650
1651 if (Ptr.isZero()) {
1652 S.CCEDiag(Call, diag::note_constexpr_deallocate_null);
1653 return true;
1654 }
1655
1656 Source = Ptr.getDeclDesc()->asExpr();
1657 BlockToDelete = Ptr.block();
1658
1659 if (!BlockToDelete->isDynamic()) {
1660 S.FFDiag(Call, diag::note_constexpr_delete_not_heap_alloc)
1662 if (const auto *D = Ptr.getFieldDesc()->asDecl())
1663 S.Note(D->getLocation(), diag::note_declared_at);
1664 }
1665 }
1666 assert(BlockToDelete);
1667
1668 DynamicAllocator &Allocator = S.getAllocator();
1669 const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
1670 std::optional<DynamicAllocator::Form> AllocForm =
1671 Allocator.getAllocationForm(Source);
1672
1673 if (!Allocator.deallocate(Source, BlockToDelete, S)) {
1674 // Nothing has been deallocated, this must be a double-delete.
1675 const SourceInfo &Loc = S.Current->getSource(OpPC);
1676 S.FFDiag(Loc, diag::note_constexpr_double_delete);
1677 return false;
1678 }
1679 assert(AllocForm);
1680
1681 return CheckNewDeleteForms(
1682 S, OpPC, *AllocForm, DynamicAllocator::Form::Operator, BlockDesc, Source);
1683}
1684
1686 const InterpFrame *Frame,
1687 const CallExpr *Call) {
1688 const Floating &Arg0 = S.Stk.pop<Floating>();
1689 S.Stk.push<Floating>(Arg0);
1690 return true;
1691}
1692
1694 const CallExpr *Call, unsigned ID) {
1695 const Pointer &Arg = S.Stk.pop<Pointer>();
1696 assert(Arg.getFieldDesc()->isPrimitiveArray());
1697
1698 QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1699 assert(Call->getType() == ElemType);
1700 PrimType ElemT = *S.getContext().classify(ElemType);
1701 unsigned NumElems = Arg.getNumElems();
1702
1704 T Result = Arg.elem<T>(0);
1705 unsigned BitWidth = Result.bitWidth();
1706 for (unsigned I = 1; I != NumElems; ++I) {
1707 T Elem = Arg.elem<T>(I);
1708 T PrevResult = Result;
1709
1710 if (ID == Builtin::BI__builtin_reduce_add) {
1711 if (T::add(Result, Elem, BitWidth, &Result)) {
1712 unsigned OverflowBits = BitWidth + 1;
1713 (void)handleOverflow(S, OpPC,
1714 (PrevResult.toAPSInt(OverflowBits) +
1715 Elem.toAPSInt(OverflowBits)));
1716 return false;
1717 }
1718 } else if (ID == Builtin::BI__builtin_reduce_mul) {
1719 if (T::mul(Result, Elem, BitWidth, &Result)) {
1720 unsigned OverflowBits = BitWidth * 2;
1721 (void)handleOverflow(S, OpPC,
1722 (PrevResult.toAPSInt(OverflowBits) *
1723 Elem.toAPSInt(OverflowBits)));
1724 return false;
1725 }
1726
1727 } else if (ID == Builtin::BI__builtin_reduce_and) {
1728 (void)T::bitAnd(Result, Elem, BitWidth, &Result);
1729 } else if (ID == Builtin::BI__builtin_reduce_or) {
1730 (void)T::bitOr(Result, Elem, BitWidth, &Result);
1731 } else if (ID == Builtin::BI__builtin_reduce_xor) {
1732 (void)T::bitXor(Result, Elem, BitWidth, &Result);
1733 } else if (ID == Builtin::BI__builtin_reduce_min) {
1734 if (Elem < Result)
1735 Result = Elem;
1736 } else if (ID == Builtin::BI__builtin_reduce_max) {
1737 if (Elem > Result)
1738 Result = Elem;
1739 } else {
1740 llvm_unreachable("Unhandled vector reduce builtin");
1741 }
1742 }
1743 pushInteger(S, Result.toAPSInt(), Call->getType());
1744 });
1745
1746 return true;
1747}
1748
1750 const InterpFrame *Frame,
1751 const CallExpr *Call,
1752 unsigned BuiltinID) {
1753 assert(Call->getNumArgs() == 1);
1754 QualType Ty = Call->getArg(0)->getType();
1755 if (Ty->isIntegerType()) {
1756 APSInt Val;
1757 if (!popToAPSInt(S, Call->getArg(0), Val))
1758 return false;
1759 pushInteger(S, Val.abs(), Call->getType());
1760 return true;
1761 }
1762
1763 if (Ty->isFloatingType()) {
1764 Floating Val = S.Stk.pop<Floating>();
1765 Floating Result = abs(S, Val);
1766 S.Stk.push<Floating>(Result);
1767 return true;
1768 }
1769
1770 // Otherwise, the argument must be a vector.
1771 assert(Call->getArg(0)->getType()->isVectorType());
1772 const Pointer &Arg = S.Stk.pop<Pointer>();
1773 assert(Arg.getFieldDesc()->isPrimitiveArray());
1774 const Pointer &Dst = S.Stk.peek<Pointer>();
1775 assert(Dst.getFieldDesc()->isPrimitiveArray());
1776 assert(Arg.getFieldDesc()->getNumElems() ==
1777 Dst.getFieldDesc()->getNumElems());
1778
1779 QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1780 PrimType ElemT = *S.getContext().classify(ElemType);
1781 unsigned NumElems = Arg.getNumElems();
1782 // we can either have a vector of integer or a vector of floating point
1783 for (unsigned I = 0; I != NumElems; ++I) {
1784 if (ElemType->isIntegerType()) {
1786 Dst.elem<T>(I) = T::from(static_cast<T>(
1787 APSInt(Arg.elem<T>(I).toAPSInt().abs(),
1789 });
1790 } else {
1791 Floating Val = Arg.elem<Floating>(I);
1792 Dst.elem<Floating>(I) = abs(S, Val);
1793 }
1794 }
1796
1797 return true;
1798}
1799
1800/// Can be called with an integer or vector as the first and only parameter.
1802 CodePtr OpPC,
1803 const InterpFrame *Frame,
1804 const CallExpr *Call,
1805 unsigned BuiltinID) {
1806 bool HasZeroArg = Call->getNumArgs() == 2;
1807 bool IsCTTZ = BuiltinID == Builtin::BI__builtin_elementwise_ctzg;
1808 assert(Call->getNumArgs() == 1 || HasZeroArg);
1809 if (Call->getArg(0)->getType()->isIntegerType()) {
1810 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
1811 APSInt Val;
1812 if (!popToAPSInt(S.Stk, ArgT, Val))
1813 return false;
1814 std::optional<APSInt> ZeroVal;
1815 if (HasZeroArg) {
1816 ZeroVal = Val;
1817 if (!popToAPSInt(S.Stk, ArgT, Val))
1818 return false;
1819 }
1820
1821 if (Val.isZero()) {
1822 if (ZeroVal) {
1823 pushInteger(S, *ZeroVal, Call->getType());
1824 return true;
1825 }
1826 // If we haven't been provided the second argument, the result is
1827 // undefined
1828 S.FFDiag(S.Current->getSource(OpPC),
1829 diag::note_constexpr_countzeroes_zero)
1830 << /*IsTrailing=*/IsCTTZ;
1831 return false;
1832 }
1833
1834 if (BuiltinID == Builtin::BI__builtin_elementwise_clzg) {
1835 pushInteger(S, Val.countLeadingZeros(), Call->getType());
1836 } else {
1837 pushInteger(S, Val.countTrailingZeros(), Call->getType());
1838 }
1839 return true;
1840 }
1841 // Otherwise, the argument must be a vector.
1842 const ASTContext &ASTCtx = S.getASTContext();
1843 Pointer ZeroArg;
1844 if (HasZeroArg) {
1845 assert(Call->getArg(1)->getType()->isVectorType() &&
1846 ASTCtx.hasSameUnqualifiedType(Call->getArg(0)->getType(),
1847 Call->getArg(1)->getType()));
1848 (void)ASTCtx;
1849 ZeroArg = S.Stk.pop<Pointer>();
1850 assert(ZeroArg.getFieldDesc()->isPrimitiveArray());
1851 }
1852 assert(Call->getArg(0)->getType()->isVectorType());
1853 const Pointer &Arg = S.Stk.pop<Pointer>();
1854 assert(Arg.getFieldDesc()->isPrimitiveArray());
1855 const Pointer &Dst = S.Stk.peek<Pointer>();
1856 assert(Dst.getFieldDesc()->isPrimitiveArray());
1857 assert(Arg.getFieldDesc()->getNumElems() ==
1858 Dst.getFieldDesc()->getNumElems());
1859
1860 QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1861 PrimType ElemT = *S.getContext().classify(ElemType);
1862 unsigned NumElems = Arg.getNumElems();
1863
1864 // FIXME: Reading from uninitialized vector elements?
1865 for (unsigned I = 0; I != NumElems; ++I) {
1867 APInt EltVal = Arg.atIndex(I).deref<T>().toAPSInt();
1868 if (EltVal.isZero()) {
1869 if (HasZeroArg) {
1870 Dst.atIndex(I).deref<T>() = ZeroArg.atIndex(I).deref<T>();
1871 } else {
1872 // If we haven't been provided the second argument, the result is
1873 // undefined
1874 S.FFDiag(S.Current->getSource(OpPC),
1875 diag::note_constexpr_countzeroes_zero)
1876 << /*IsTrailing=*/IsCTTZ;
1877 return false;
1878 }
1879 } else if (IsCTTZ) {
1880 Dst.atIndex(I).deref<T>() = T::from(EltVal.countTrailingZeros());
1881 } else {
1882 Dst.atIndex(I).deref<T>() = T::from(EltVal.countLeadingZeros());
1883 }
1884 Dst.atIndex(I).initialize();
1885 });
1886 }
1887
1888 return true;
1889}
1890
1892 const InterpFrame *Frame,
1893 const CallExpr *Call, unsigned ID) {
1894 assert(Call->getNumArgs() == 3);
1895 const ASTContext &ASTCtx = S.getASTContext();
1896 uint64_t Size;
1897 if (!popToUInt64(S, Call->getArg(2), Size))
1898 return false;
1899 Pointer SrcPtr = S.Stk.pop<Pointer>().expand();
1900 Pointer DestPtr = S.Stk.pop<Pointer>().expand();
1901
1902 if (ID == Builtin::BImemcpy || ID == Builtin::BImemmove)
1903 diagnoseNonConstexprBuiltin(S, OpPC, ID);
1904
1905 bool Move =
1906 (ID == Builtin::BI__builtin_memmove || ID == Builtin::BImemmove ||
1907 ID == Builtin::BI__builtin_wmemmove || ID == Builtin::BIwmemmove);
1908 bool WChar = ID == Builtin::BIwmemcpy || ID == Builtin::BIwmemmove ||
1909 ID == Builtin::BI__builtin_wmemcpy ||
1910 ID == Builtin::BI__builtin_wmemmove;
1911
1912 // If the size is zero, we treat this as always being a valid no-op.
1913 if (Size == 0) {
1914 S.Stk.push<Pointer>(DestPtr);
1915 return true;
1916 }
1917
1918 if (SrcPtr.isZero() || DestPtr.isZero()) {
1919 Pointer DiagPtr = (SrcPtr.isZero() ? SrcPtr : DestPtr);
1920 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
1921 << /*IsMove=*/Move << /*IsWchar=*/WChar << !SrcPtr.isZero()
1922 << DiagPtr.toDiagnosticString(ASTCtx);
1923 return false;
1924 }
1925
1926 // Diagnose integral src/dest pointers specially.
1927 if (SrcPtr.isIntegralPointer() || DestPtr.isIntegralPointer()) {
1928 std::string DiagVal = "(void *)";
1929 DiagVal += SrcPtr.isIntegralPointer()
1930 ? std::to_string(SrcPtr.getIntegerRepresentation())
1931 : std::to_string(DestPtr.getIntegerRepresentation());
1932 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
1933 << Move << WChar << DestPtr.isIntegralPointer() << DiagVal;
1934 return false;
1935 }
1936
1937 if (!isReadable(DestPtr) || !isReadable(SrcPtr))
1938 return false;
1939
1940 if (DestPtr.getType()->isIncompleteType()) {
1941 S.FFDiag(S.Current->getSource(OpPC),
1942 diag::note_constexpr_memcpy_incomplete_type)
1943 << Move << DestPtr.getType();
1944 return false;
1945 }
1946 if (SrcPtr.getType()->isIncompleteType()) {
1947 S.FFDiag(S.Current->getSource(OpPC),
1948 diag::note_constexpr_memcpy_incomplete_type)
1949 << Move << SrcPtr.getType();
1950 return false;
1951 }
1952
1953 QualType DestElemType = getElemType(DestPtr);
1954 if (DestElemType->isIncompleteType()) {
1955 S.FFDiag(S.Current->getSource(OpPC),
1956 diag::note_constexpr_memcpy_incomplete_type)
1957 << Move << DestElemType;
1958 return false;
1959 }
1960
1961 size_t RemainingDestElems;
1962 if (DestPtr.getFieldDesc()->isArray()) {
1963 RemainingDestElems = DestPtr.isUnknownSizeArray()
1964 ? 0
1965 : (DestPtr.getNumElems() - DestPtr.getIndex());
1966 } else {
1967 RemainingDestElems = 1;
1968 }
1969 unsigned DestElemSize = ASTCtx.getTypeSizeInChars(DestElemType).getQuantity();
1970
1971 if (WChar) {
1972 uint64_t WCharSize =
1973 ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();
1974 Size *= WCharSize;
1975 }
1976
1977 if (Size % DestElemSize != 0) {
1978 S.FFDiag(S.Current->getSource(OpPC),
1979 diag::note_constexpr_memcpy_unsupported)
1980 << Move << WChar << 0 << DestElemType << Size << DestElemSize;
1981 return false;
1982 }
1983
1984 QualType SrcElemType = getElemType(SrcPtr);
1985 size_t RemainingSrcElems;
1986 if (SrcPtr.getFieldDesc()->isArray()) {
1987 RemainingSrcElems = SrcPtr.isUnknownSizeArray()
1988 ? 0
1989 : (SrcPtr.getNumElems() - SrcPtr.getIndex());
1990 } else {
1991 RemainingSrcElems = 1;
1992 }
1993 unsigned SrcElemSize = ASTCtx.getTypeSizeInChars(SrcElemType).getQuantity();
1994
1995 if (!ASTCtx.hasSameUnqualifiedType(DestElemType, SrcElemType)) {
1996 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_type_pun)
1997 << Move << SrcElemType << DestElemType;
1998 return false;
1999 }
2000
2001 if (!DestElemType.isTriviallyCopyableType(ASTCtx)) {
2002 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_nontrivial)
2003 << Move << DestElemType;
2004 return false;
2005 }
2006
2007 // Check if we have enough elements to read from and write to.
2008 size_t RemainingDestBytes = RemainingDestElems * DestElemSize;
2009 size_t RemainingSrcBytes = RemainingSrcElems * SrcElemSize;
2010 if (Size > RemainingDestBytes || Size > RemainingSrcBytes) {
2011 APInt N = APInt(64, Size / DestElemSize);
2012 S.FFDiag(S.Current->getSource(OpPC),
2013 diag::note_constexpr_memcpy_unsupported)
2014 << Move << WChar << (Size > RemainingSrcBytes ? 1 : 2) << DestElemType
2015 << toString(N, 10, /*Signed=*/false);
2016 return false;
2017 }
2018
2019 // Check for overlapping memory regions.
2020 if (!Move && Pointer::pointToSameBlock(SrcPtr, DestPtr)) {
2021 // Remove base casts.
2022 Pointer SrcP = SrcPtr.stripBaseCasts();
2023 Pointer DestP = DestPtr.stripBaseCasts();
2024
2025 unsigned SrcIndex = SrcP.expand().getIndex() * SrcElemSize;
2026 unsigned DstIndex = DestP.expand().getIndex() * DestElemSize;
2027
2028 if ((SrcIndex <= DstIndex && (SrcIndex + Size) > DstIndex) ||
2029 (DstIndex <= SrcIndex && (DstIndex + Size) > SrcIndex)) {
2030 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_overlap)
2031 << /*IsWChar=*/false;
2032 return false;
2033 }
2034 }
2035
2036 assert(Size % DestElemSize == 0);
2037 if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size).toBits()))
2038 return false;
2039
2040 S.Stk.push<Pointer>(DestPtr);
2041 return true;
2042}
2043
2044/// Determine if T is a character type for which we guarantee that
2045/// sizeof(T) == 1.
2047 return T->isCharType() || T->isChar8Type();
2048}
2049
2051 const InterpFrame *Frame,
2052 const CallExpr *Call, unsigned ID) {
2053 assert(Call->getNumArgs() == 3);
2054 uint64_t Size;
2055 if (!popToUInt64(S, Call->getArg(2), Size))
2056 return false;
2057 const Pointer &PtrB = S.Stk.pop<Pointer>();
2058 const Pointer &PtrA = S.Stk.pop<Pointer>();
2059
2060 if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp ||
2061 ID == Builtin::BIwmemcmp)
2062 diagnoseNonConstexprBuiltin(S, OpPC, ID);
2063
2064 if (Size == 0) {
2065 pushInteger(S, 0, Call->getType());
2066 return true;
2067 }
2068
2069 if (!PtrA.isBlockPointer() || !PtrB.isBlockPointer())
2070 return false;
2071
2072 bool IsWide =
2073 (ID == Builtin::BIwmemcmp || ID == Builtin::BI__builtin_wmemcmp);
2074
2075 const ASTContext &ASTCtx = S.getASTContext();
2076 QualType ElemTypeA = getElemType(PtrA);
2077 QualType ElemTypeB = getElemType(PtrB);
2078 // FIXME: This is an arbitrary limitation the current constant interpreter
2079 // had. We could remove this.
2080 if (!IsWide && (!isOneByteCharacterType(ElemTypeA) ||
2081 !isOneByteCharacterType(ElemTypeB))) {
2082 S.FFDiag(S.Current->getSource(OpPC),
2083 diag::note_constexpr_memcmp_unsupported)
2084 << ASTCtx.BuiltinInfo.getQuotedName(ID) << PtrA.getType()
2085 << PtrB.getType();
2086 return false;
2087 }
2088
2089 if (!CheckLoad(S, OpPC, PtrA, AK_Read) || !CheckLoad(S, OpPC, PtrB, AK_Read))
2090 return false;
2091
2092 // Now, read both pointers to a buffer and compare those.
2093 BitcastBuffer BufferA(
2094 Bits(ASTCtx.getTypeSize(ElemTypeA) * PtrA.getNumElems()));
2095 readPointerToBuffer(S.getContext(), PtrA, BufferA, false);
2096
2097 // FIXME: The swapping here is UNDOING something we do when reading the
2098 // data into the buffer.
2099 if (ASTCtx.getTargetInfo().isBigEndian())
2100 swapBytes(BufferA.Data.get(), BufferA.byteSize().getQuantity());
2101
2102 BitcastBuffer BufferB(
2103 Bits(ASTCtx.getTypeSize(ElemTypeB) * PtrB.getNumElems()));
2104 readPointerToBuffer(S.getContext(), PtrB, BufferB, false);
2105 // FIXME: The swapping here is UNDOING something we do when reading the
2106 // data into the buffer.
2107 if (ASTCtx.getTargetInfo().isBigEndian())
2108 swapBytes(BufferB.Data.get(), BufferB.byteSize().getQuantity());
2109
2110 size_t MinBufferSize = std::min(BufferA.byteSize().getQuantity(),
2111 BufferB.byteSize().getQuantity());
2112
2113 unsigned ElemSize = 1;
2114 if (IsWide)
2115 ElemSize = ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();
2116 // The Size given for the wide variants is in wide-char units. Convert it
2117 // to bytes.
2118 size_t ByteSize = Size * ElemSize;
2119 size_t CmpSize = std::min(MinBufferSize, ByteSize);
2120
2121 for (size_t I = 0; I != CmpSize; I += ElemSize) {
2122 if (IsWide) {
2124 *S.getContext().classify(ASTCtx.getWCharType()), {
2125 T A = T::bitcastFromMemory(BufferA.atByte(I), T::bitWidth());
2126 T B = T::bitcastFromMemory(BufferB.atByte(I), T::bitWidth());
2127 if (A < B) {
2128 pushInteger(S, -1, Call->getType());
2129 return true;
2130 }
2131 if (A > B) {
2132 pushInteger(S, 1, Call->getType());
2133 return true;
2134 }
2135 });
2136 } else {
2137 auto A = BufferA.deref<std::byte>(Bytes(I));
2138 auto B = BufferB.deref<std::byte>(Bytes(I));
2139
2140 if (A < B) {
2141 pushInteger(S, -1, Call->getType());
2142 return true;
2143 }
2144 if (A > B) {
2145 pushInteger(S, 1, Call->getType());
2146 return true;
2147 }
2148 }
2149 }
2150
2151 // We compared CmpSize bytes above. If the limiting factor was the Size
2152 // passed, we're done and the result is equality (0).
2153 if (ByteSize <= CmpSize) {
2154 pushInteger(S, 0, Call->getType());
2155 return true;
2156 }
2157
2158 // However, if we read all the available bytes but were instructed to read
2159 // even more, diagnose this as a "read of dereferenced one-past-the-end
2160 // pointer". This is what would happen if we called CheckLoad() on every array
2161 // element.
2162 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)
2163 << AK_Read << S.Current->getRange(OpPC);
2164 return false;
2165}
2166
2167// __builtin_memchr(ptr, int, int)
2168// __builtin_strchr(ptr, int)
2170 const CallExpr *Call, unsigned ID) {
2171 if (ID == Builtin::BImemchr || ID == Builtin::BIwcschr ||
2172 ID == Builtin::BIstrchr || ID == Builtin::BIwmemchr)
2173 diagnoseNonConstexprBuiltin(S, OpPC, ID);
2174
2175 std::optional<APSInt> MaxLength;
2176 if (Call->getNumArgs() == 3) {
2177 APSInt MaxLengthVal;
2178 if (!popToAPSInt(S, Call->getArg(2), MaxLengthVal))
2179 return false;
2180 MaxLength = MaxLengthVal;
2181 }
2182
2183 APSInt Desired;
2184 if (!popToAPSInt(S, Call->getArg(1), Desired))
2185 return false;
2186 const Pointer &Ptr = S.Stk.pop<Pointer>();
2187
2188 if (MaxLength && MaxLength->isZero()) {
2189 S.Stk.push<Pointer>();
2190 return true;
2191 }
2192
2193 if (Ptr.isDummy()) {
2194 if (Ptr.getType()->isIncompleteType())
2195 S.FFDiag(S.Current->getSource(OpPC),
2196 diag::note_constexpr_ltor_incomplete_type)
2197 << Ptr.getType();
2198 return false;
2199 }
2200
2201 // Null is only okay if the given size is 0.
2202 if (Ptr.isZero()) {
2203 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)
2204 << AK_Read;
2205 return false;
2206 }
2207
2208 if (!Ptr.isBlockPointer())
2209 return false;
2210
2211 QualType ElemTy = Ptr.getFieldDesc()->isArray()
2212 ? Ptr.getFieldDesc()->getElemQualType()
2213 : Ptr.getFieldDesc()->getType();
2214 bool IsRawByte = ID == Builtin::BImemchr || ID == Builtin::BI__builtin_memchr;
2215
2216 // Give up on byte-oriented matching against multibyte elements.
2217 if (IsRawByte && !isOneByteCharacterType(ElemTy)) {
2218 S.FFDiag(S.Current->getSource(OpPC),
2219 diag::note_constexpr_memchr_unsupported)
2220 << S.getASTContext().BuiltinInfo.getQuotedName(ID) << ElemTy;
2221 return false;
2222 }
2223
2224 if (!isReadable(Ptr))
2225 return false;
2226
2227 if (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr) {
2228 int64_t DesiredTrunc;
2229 if (S.getASTContext().CharTy->isSignedIntegerType())
2230 DesiredTrunc =
2231 Desired.trunc(S.getASTContext().getCharWidth()).getSExtValue();
2232 else
2233 DesiredTrunc =
2234 Desired.trunc(S.getASTContext().getCharWidth()).getZExtValue();
2235 // strchr compares directly to the passed integer, and therefore
2236 // always fails if given an int that is not a char.
2237 if (Desired != DesiredTrunc) {
2238 S.Stk.push<Pointer>();
2239 return true;
2240 }
2241 }
2242
2243 uint64_t DesiredVal;
2244 if (ID == Builtin::BIwmemchr || ID == Builtin::BI__builtin_wmemchr ||
2245 ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr) {
2246 // wcschr and wmemchr are given a wchar_t to look for. Just use it.
2247 DesiredVal = Desired.getZExtValue();
2248 } else {
2249 DesiredVal = Desired.trunc(S.getASTContext().getCharWidth()).getZExtValue();
2250 }
2251
2252 bool StopAtZero =
2253 (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr ||
2254 ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr);
2255
2256 PrimType ElemT =
2257 IsRawByte ? PT_Sint8 : *S.getContext().classify(getElemType(Ptr));
2258
2259 size_t Index = Ptr.getIndex();
2260 size_t Step = 0;
2261 for (;;) {
2262 const Pointer &ElemPtr =
2263 (Index + Step) > 0 ? Ptr.atIndex(Index + Step) : Ptr;
2264
2265 if (!CheckLoad(S, OpPC, ElemPtr))
2266 return false;
2267
2268 uint64_t V;
2270 ElemT, { V = static_cast<uint64_t>(ElemPtr.deref<T>().toUnsigned()); });
2271
2272 if (V == DesiredVal) {
2273 S.Stk.push<Pointer>(ElemPtr);
2274 return true;
2275 }
2276
2277 if (StopAtZero && V == 0)
2278 break;
2279
2280 ++Step;
2281 if (MaxLength && Step == MaxLength->getZExtValue())
2282 break;
2283 }
2284
2285 S.Stk.push<Pointer>();
2286 return true;
2287}
2288
2289static std::optional<unsigned> computeFullDescSize(const ASTContext &ASTCtx,
2290 const Descriptor *Desc) {
2291 if (Desc->isPrimitive())
2292 return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();
2293 if (Desc->isArray())
2294 return ASTCtx.getTypeSizeInChars(Desc->getElemQualType()).getQuantity() *
2295 Desc->getNumElems();
2296 if (Desc->isRecord()) {
2297 // Can't use Descriptor::getType() as that may return a pointer type. Look
2298 // at the decl directly.
2299 return ASTCtx
2301 ASTCtx.getCanonicalTagType(Desc->ElemRecord->getDecl()))
2302 .getQuantity();
2303 }
2304
2305 return std::nullopt;
2306}
2307
2308/// Compute the byte offset of \p Ptr in the full declaration.
2309static unsigned computePointerOffset(const ASTContext &ASTCtx,
2310 const Pointer &Ptr) {
2311 unsigned Result = 0;
2312
2313 Pointer P = Ptr;
2314 while (P.isField() || P.isArrayElement()) {
2315 P = P.expand();
2316 const Descriptor *D = P.getFieldDesc();
2317
2318 if (P.isArrayElement()) {
2319 unsigned ElemSize =
2321 if (P.isOnePastEnd())
2322 Result += ElemSize * P.getNumElems();
2323 else
2324 Result += ElemSize * P.getIndex();
2325 P = P.expand().getArray();
2326 } else if (P.isBaseClass()) {
2327 const auto *RD = cast<CXXRecordDecl>(D->asDecl());
2328 bool IsVirtual = Ptr.isVirtualBaseClass();
2329 P = P.getBase();
2330 const Record *BaseRecord = P.getRecord();
2331
2332 const ASTRecordLayout &Layout =
2333 ASTCtx.getASTRecordLayout(cast<CXXRecordDecl>(BaseRecord->getDecl()));
2334 if (IsVirtual)
2335 Result += Layout.getVBaseClassOffset(RD).getQuantity();
2336 else
2337 Result += Layout.getBaseClassOffset(RD).getQuantity();
2338 } else if (P.isField()) {
2339 const FieldDecl *FD = P.getField();
2340 const ASTRecordLayout &Layout =
2341 ASTCtx.getASTRecordLayout(FD->getParent());
2342 unsigned FieldIndex = FD->getFieldIndex();
2343 uint64_t FieldOffset =
2344 ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex))
2345 .getQuantity();
2346 Result += FieldOffset;
2347 P = P.getBase();
2348 } else
2349 llvm_unreachable("Unhandled descriptor type");
2350 }
2351
2352 return Result;
2353}
2354
2355/// Does Ptr point to the last subobject?
2356static bool pointsToLastObject(const Pointer &Ptr) {
2357 Pointer P = Ptr;
2358 while (!P.isRoot()) {
2359
2360 if (P.isArrayElement()) {
2361 P = P.expand().getArray();
2362 continue;
2363 }
2364 if (P.isBaseClass()) {
2365 if (P.getRecord()->getNumFields() > 0)
2366 return false;
2367 P = P.getBase();
2368 continue;
2369 }
2370
2371 Pointer Base = P.getBase();
2372 if (const Record *R = Base.getRecord()) {
2373 assert(P.getField());
2374 if (P.getField()->getFieldIndex() != R->getNumFields() - 1)
2375 return false;
2376 }
2377 P = Base;
2378 }
2379
2380 return true;
2381}
2382
2383/// Does Ptr point to the last object AND to a flexible array member?
2384static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const Pointer &Ptr,
2385 bool InvalidBase) {
2386 auto isFlexibleArrayMember = [&](const Descriptor *FieldDesc) {
2388 FAMKind StrictFlexArraysLevel =
2389 Ctx.getLangOpts().getStrictFlexArraysLevel();
2390
2391 if (StrictFlexArraysLevel == FAMKind::Default)
2392 return true;
2393
2394 unsigned NumElems = FieldDesc->getNumElems();
2395 if (NumElems == 0 && StrictFlexArraysLevel != FAMKind::IncompleteOnly)
2396 return true;
2397
2398 if (NumElems == 1 && StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)
2399 return true;
2400 return false;
2401 };
2402
2403 const Descriptor *FieldDesc = Ptr.getFieldDesc();
2404 if (!FieldDesc->isArray())
2405 return false;
2406
2407 return InvalidBase && pointsToLastObject(Ptr) &&
2408 isFlexibleArrayMember(FieldDesc);
2409}
2410
2412 unsigned Kind, Pointer &Ptr) {
2413 if (Ptr.isZero() || !Ptr.isBlockPointer())
2414 return std::nullopt;
2415
2416 if (Ptr.isDummy() && Ptr.getType()->isPointerType())
2417 return std::nullopt;
2418
2419 bool InvalidBase = false;
2420
2421 if (Ptr.isDummy()) {
2422 if (const VarDecl *VD = Ptr.getDeclDesc()->asVarDecl();
2423 VD && VD->getType()->isPointerType())
2424 InvalidBase = true;
2425 }
2426
2427 // According to the GCC documentation, we want the size of the subobject
2428 // denoted by the pointer. But that's not quite right -- what we actually
2429 // want is the size of the immediately-enclosing array, if there is one.
2430 if (Ptr.isArrayElement())
2431 Ptr = Ptr.expand();
2432
2433 bool DetermineForCompleteObject = Ptr.getFieldDesc() == Ptr.getDeclDesc();
2434 const Descriptor *DeclDesc = Ptr.getDeclDesc();
2435 assert(DeclDesc);
2436
2437 bool UseFieldDesc = (Kind & 1u);
2438 bool ReportMinimum = (Kind & 2u);
2439 if (!UseFieldDesc || DetermineForCompleteObject) {
2440 // Can't read beyond the pointer decl desc.
2441 if (!ReportMinimum && DeclDesc->getType()->isPointerType())
2442 return std::nullopt;
2443
2444 if (InvalidBase)
2445 return std::nullopt;
2446 } else {
2447 if (isUserWritingOffTheEnd(ASTCtx, Ptr, InvalidBase)) {
2448 // If we cannot determine the size of the initial allocation, then we
2449 // can't given an accurate upper-bound. However, we are still able to give
2450 // conservative lower-bounds for Type=3.
2451 if (Kind == 1)
2452 return std::nullopt;
2453 }
2454 }
2455
2456 // The "closest surrounding subobject" is NOT a base class,
2457 // so strip the base class casts.
2458 if (UseFieldDesc && Ptr.isBaseClass())
2459 Ptr = Ptr.stripBaseCasts();
2460
2461 const Descriptor *Desc = UseFieldDesc ? Ptr.getFieldDesc() : DeclDesc;
2462 assert(Desc);
2463
2464 std::optional<unsigned> FullSize = computeFullDescSize(ASTCtx, Desc);
2465 if (!FullSize)
2466 return std::nullopt;
2467
2468 unsigned ByteOffset;
2469 if (UseFieldDesc) {
2470 if (Ptr.isBaseClass()) {
2471 assert(computePointerOffset(ASTCtx, Ptr.getBase()) <=
2472 computePointerOffset(ASTCtx, Ptr));
2473 ByteOffset = computePointerOffset(ASTCtx, Ptr.getBase()) -
2474 computePointerOffset(ASTCtx, Ptr);
2475 } else {
2476 if (Ptr.inArray())
2477 ByteOffset =
2478 computePointerOffset(ASTCtx, Ptr) -
2479 computePointerOffset(ASTCtx, Ptr.expand().atIndex(0).narrow());
2480 else
2481 ByteOffset = 0;
2482 }
2483 } else
2484 ByteOffset = computePointerOffset(ASTCtx, Ptr);
2485
2486 assert(ByteOffset <= *FullSize);
2487 return *FullSize - ByteOffset;
2488}
2489
2491 const InterpFrame *Frame,
2492 const CallExpr *Call) {
2493 const ASTContext &ASTCtx = S.getASTContext();
2494 // From the GCC docs:
2495 // Kind is an integer constant from 0 to 3. If the least significant bit is
2496 // clear, objects are whole variables. If it is set, a closest surrounding
2497 // subobject is considered the object a pointer points to. The second bit
2498 // determines if maximum or minimum of remaining bytes is computed.
2499 uint64_t Kind;
2500 if (!popToUInt64(S, Call->getArg(1), Kind))
2501 return false;
2502 assert(Kind <= 3 && "unexpected kind");
2503 Pointer Ptr = S.Stk.pop<Pointer>();
2504
2505 if (Call->getArg(0)->HasSideEffects(ASTCtx)) {
2506 // "If there are any side effects in them, it returns (size_t) -1
2507 // for type 0 or 1 and (size_t) 0 for type 2 or 3."
2508 pushInteger(S, Kind <= 1 ? -1 : 0, Call->getType());
2509 return true;
2510 }
2511
2512 if (auto Result = evaluateBuiltinObjectSize(ASTCtx, Kind, Ptr)) {
2513 pushInteger(S, *Result, Call->getType());
2514 return true;
2515 }
2516 return false;
2517}
2518
2520 const CallExpr *Call) {
2521
2522 if (!S.inConstantContext())
2523 return false;
2524
2525 const Pointer &Ptr = S.Stk.pop<Pointer>();
2526
2527 auto Error = [&](int Diag) {
2528 bool CalledFromStd = false;
2529 const auto *Callee = S.Current->getCallee();
2530 if (Callee && Callee->isInStdNamespace()) {
2531 const IdentifierInfo *Identifier = Callee->getIdentifier();
2532 CalledFromStd = Identifier && Identifier->isStr("is_within_lifetime");
2533 }
2534 S.CCEDiag(CalledFromStd
2536 : S.Current->getSource(OpPC),
2537 diag::err_invalid_is_within_lifetime)
2538 << (CalledFromStd ? "std::is_within_lifetime"
2539 : "__builtin_is_within_lifetime")
2540 << Diag;
2541 return false;
2542 };
2543
2544 if (Ptr.isZero())
2545 return Error(0);
2546 if (Ptr.isOnePastEnd())
2547 return Error(1);
2548
2549 bool Result = Ptr.getLifetime() != Lifetime::Ended;
2550 if (!Ptr.isActive()) {
2551 Result = false;
2552 } else {
2553 if (!CheckLive(S, OpPC, Ptr, AK_Read))
2554 return false;
2555 if (!CheckMutable(S, OpPC, Ptr))
2556 return false;
2557 if (!CheckDummy(S, OpPC, Ptr.block(), AK_Read))
2558 return false;
2559 }
2560
2561 // Check if we're currently running an initializer.
2562 if (llvm::is_contained(S.InitializingBlocks, Ptr.block()))
2563 return Error(2);
2564 if (S.EvaluatingDecl && Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl)
2565 return Error(2);
2566
2567 pushInteger(S, Result, Call->getType());
2568 return true;
2569}
2570
2572 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2573 llvm::function_ref<APInt(const APSInt &)> Fn) {
2574 assert(Call->getNumArgs() == 1);
2575
2576 // Single integer case.
2577 if (!Call->getArg(0)->getType()->isVectorType()) {
2578 assert(Call->getType()->isIntegerType());
2579 APSInt Src;
2580 if (!popToAPSInt(S, Call->getArg(0), Src))
2581 return false;
2582 APInt Result = Fn(Src);
2583 pushInteger(S, APSInt(std::move(Result), !Src.isSigned()), Call->getType());
2584 return true;
2585 }
2586
2587 // Vector case.
2588 const Pointer &Arg = S.Stk.pop<Pointer>();
2589 assert(Arg.getFieldDesc()->isPrimitiveArray());
2590 const Pointer &Dst = S.Stk.peek<Pointer>();
2591 assert(Dst.getFieldDesc()->isPrimitiveArray());
2592 assert(Arg.getFieldDesc()->getNumElems() ==
2593 Dst.getFieldDesc()->getNumElems());
2594
2595 QualType ElemType = Arg.getFieldDesc()->getElemQualType();
2596 PrimType ElemT = *S.getContext().classify(ElemType);
2597 unsigned NumElems = Arg.getNumElems();
2598 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
2599
2600 for (unsigned I = 0; I != NumElems; ++I) {
2602 APSInt Src = Arg.elem<T>(I).toAPSInt();
2603 APInt Result = Fn(Src);
2604 Dst.elem<T>(I) = static_cast<T>(APSInt(std::move(Result), DestUnsigned));
2605 });
2606 }
2608
2609 return true;
2610}
2611
2613 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2614 llvm::function_ref<std::optional<APFloat>(
2615 const APFloat &, const APFloat &, std::optional<APSInt> RoundingMode)>
2616 Fn,
2617 bool IsScalar = false) {
2618 assert((Call->getNumArgs() == 2) || (Call->getNumArgs() == 3));
2619 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2620 assert(VT->getElementType()->isFloatingType());
2621 unsigned NumElems = VT->getNumElements();
2622
2623 // Vector case.
2624 assert(Call->getArg(0)->getType()->isVectorType() &&
2625 Call->getArg(1)->getType()->isVectorType());
2626 assert(VT->getElementType() ==
2627 Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());
2628 assert(VT->getNumElements() ==
2629 Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());
2630
2631 std::optional<APSInt> RoundingMode = std::nullopt;
2632 if (Call->getNumArgs() == 3) {
2633 APSInt RoundingModeVal;
2634 if (!popToAPSInt(S, Call->getArg(2), RoundingModeVal))
2635 return false;
2636 RoundingMode = RoundingModeVal;
2637 }
2638
2639 const Pointer &BPtr = S.Stk.pop<Pointer>();
2640 const Pointer &APtr = S.Stk.pop<Pointer>();
2641 const Pointer &Dst = S.Stk.peek<Pointer>();
2642 for (unsigned ElemIdx = 0; ElemIdx != NumElems; ++ElemIdx) {
2643 using T = PrimConv<PT_Float>::T;
2644 if (IsScalar && ElemIdx > 0) {
2645 Dst.elem<T>(ElemIdx) = APtr.elem<T>(ElemIdx);
2646 continue;
2647 }
2648 APFloat ElemA = APtr.elem<T>(ElemIdx).getAPFloat();
2649 APFloat ElemB = BPtr.elem<T>(ElemIdx).getAPFloat();
2650 std::optional<APFloat> Result = Fn(ElemA, ElemB, RoundingMode);
2651 if (!Result)
2652 return false;
2653 Dst.elem<T>(ElemIdx) = static_cast<T>(*Result);
2654 }
2655
2657
2658 return true;
2659}
2660
2662 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2663 llvm::function_ref<std::optional<APFloat>(const APFloat &, const APFloat &,
2664 std::optional<APSInt>)>
2665 Fn) {
2666 assert(Call->getNumArgs() == 5);
2667 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2668 unsigned NumElems = VT->getNumElements();
2669
2670 APSInt RoundingMode;
2671 if (!popToAPSInt(S, Call->getArg(4), RoundingMode))
2672 return false;
2673 uint64_t MaskVal;
2674 if (!popToUInt64(S, Call->getArg(3), MaskVal))
2675 return false;
2676 const Pointer &SrcPtr = S.Stk.pop<Pointer>();
2677 const Pointer &BPtr = S.Stk.pop<Pointer>();
2678 const Pointer &APtr = S.Stk.pop<Pointer>();
2679 const Pointer &Dst = S.Stk.peek<Pointer>();
2680
2681 using T = PrimConv<PT_Float>::T;
2682
2683 if (MaskVal & 1) {
2684 APFloat ElemA = APtr.elem<T>(0).getAPFloat();
2685 APFloat ElemB = BPtr.elem<T>(0).getAPFloat();
2686 std::optional<APFloat> Result = Fn(ElemA, ElemB, RoundingMode);
2687 if (!Result)
2688 return false;
2689 Dst.elem<T>(0) = static_cast<T>(*Result);
2690 } else {
2691 Dst.elem<T>(0) = SrcPtr.elem<T>(0);
2692 }
2693
2694 for (unsigned I = 1; I < NumElems; ++I)
2695 Dst.elem<T>(I) = APtr.elem<T>(I);
2696
2697 Dst.initializeAllElements();
2698
2699 return true;
2700}
2701
2703 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2704 llvm::function_ref<APInt(const APSInt &, const APSInt &)> Fn) {
2705 assert(Call->getNumArgs() == 2);
2706
2707 // Single integer case.
2708 if (!Call->getArg(0)->getType()->isVectorType()) {
2709 assert(!Call->getArg(1)->getType()->isVectorType());
2710 APSInt RHS;
2711 if (!popToAPSInt(S, Call->getArg(1), RHS))
2712 return false;
2713 APSInt LHS;
2714 if (!popToAPSInt(S, Call->getArg(0), LHS))
2715 return false;
2716 APInt Result = Fn(LHS, RHS);
2717 pushInteger(S, APSInt(std::move(Result), !LHS.isSigned()), Call->getType());
2718 return true;
2719 }
2720
2721 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2722 assert(VT->getElementType()->isIntegralOrEnumerationType());
2723 PrimType ElemT = *S.getContext().classify(VT->getElementType());
2724 unsigned NumElems = VT->getNumElements();
2725 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
2726
2727 // Vector + Scalar case.
2728 if (!Call->getArg(1)->getType()->isVectorType()) {
2729 assert(Call->getArg(1)->getType()->isIntegralOrEnumerationType());
2730
2731 APSInt RHS;
2732 if (!popToAPSInt(S, Call->getArg(1), RHS))
2733 return false;
2734 const Pointer &LHS = S.Stk.pop<Pointer>();
2735 const Pointer &Dst = S.Stk.peek<Pointer>();
2736
2737 for (unsigned I = 0; I != NumElems; ++I) {
2739 Dst.elem<T>(I) = static_cast<T>(
2740 APSInt(Fn(LHS.elem<T>(I).toAPSInt(), RHS), DestUnsigned));
2741 });
2742 }
2744 return true;
2745 }
2746
2747 // Vector case.
2748 assert(Call->getArg(0)->getType()->isVectorType() &&
2749 Call->getArg(1)->getType()->isVectorType());
2750 assert(VT->getElementType() ==
2751 Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());
2752 assert(VT->getNumElements() ==
2753 Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());
2754 assert(VT->getElementType()->isIntegralOrEnumerationType());
2755
2756 const Pointer &RHS = S.Stk.pop<Pointer>();
2757 const Pointer &LHS = S.Stk.pop<Pointer>();
2758 const Pointer &Dst = S.Stk.peek<Pointer>();
2759 for (unsigned I = 0; I != NumElems; ++I) {
2761 APSInt Elem1 = LHS.elem<T>(I).toAPSInt();
2762 APSInt Elem2 = RHS.elem<T>(I).toAPSInt();
2763 Dst.elem<T>(I) = static_cast<T>(APSInt(Fn(Elem1, Elem2), DestUnsigned));
2764 });
2765 }
2767
2768 return true;
2769}
2770
2771static bool
2773 llvm::function_ref<APInt(const APSInt &)> PackFn) {
2774 const auto *VT0 = E->getArg(0)->getType()->castAs<VectorType>();
2775 [[maybe_unused]] const auto *VT1 =
2776 E->getArg(1)->getType()->castAs<VectorType>();
2777 assert(VT0 && VT1 && "pack builtin VT0 and VT1 must be VectorType");
2778 assert(VT0->getElementType() == VT1->getElementType() &&
2779 VT0->getNumElements() == VT1->getNumElements() &&
2780 "pack builtin VT0 and VT1 ElementType must be same");
2781
2782 const Pointer &RHS = S.Stk.pop<Pointer>();
2783 const Pointer &LHS = S.Stk.pop<Pointer>();
2784 const Pointer &Dst = S.Stk.peek<Pointer>();
2785
2786 const ASTContext &ASTCtx = S.getASTContext();
2787 unsigned SrcBits = ASTCtx.getIntWidth(VT0->getElementType());
2788 unsigned LHSVecLen = VT0->getNumElements();
2789 unsigned SrcPerLane = 128 / SrcBits;
2790 unsigned Lanes = LHSVecLen * SrcBits / 128;
2791
2792 PrimType SrcT = *S.getContext().classify(VT0->getElementType());
2793 PrimType DstT = *S.getContext().classify(getElemType(Dst));
2794 bool IsUnsigend = getElemType(Dst)->isUnsignedIntegerType();
2795
2796 for (unsigned Lane = 0; Lane != Lanes; ++Lane) {
2797 unsigned BaseSrc = Lane * SrcPerLane;
2798 unsigned BaseDst = Lane * (2 * SrcPerLane);
2799
2800 for (unsigned I = 0; I != SrcPerLane; ++I) {
2802 APSInt A = LHS.elem<T>(BaseSrc + I).toAPSInt();
2803 APSInt B = RHS.elem<T>(BaseSrc + I).toAPSInt();
2804
2805 assignIntegral(S, Dst.atIndex(BaseDst + I), DstT,
2806 APSInt(PackFn(A), IsUnsigend));
2807 assignIntegral(S, Dst.atIndex(BaseDst + SrcPerLane + I), DstT,
2808 APSInt(PackFn(B), IsUnsigend));
2809 });
2810 }
2811 }
2812
2813 Dst.initializeAllElements();
2814 return true;
2815}
2816
2818 const CallExpr *Call,
2819 unsigned BuiltinID) {
2820 assert(Call->getNumArgs() == 2);
2821
2822 QualType Arg0Type = Call->getArg(0)->getType();
2823
2824 // TODO: Support floating-point types.
2825 if (!(Arg0Type->isIntegerType() ||
2826 (Arg0Type->isVectorType() &&
2827 Arg0Type->castAs<VectorType>()->getElementType()->isIntegerType())))
2828 return false;
2829
2830 if (!Arg0Type->isVectorType()) {
2831 assert(!Call->getArg(1)->getType()->isVectorType());
2832 APSInt RHS;
2833 if (!popToAPSInt(S, Call->getArg(1), RHS))
2834 return false;
2835 APSInt LHS;
2836 if (!popToAPSInt(S, Arg0Type, LHS))
2837 return false;
2838 APInt Result;
2839 if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
2840 Result = std::max(LHS, RHS);
2841 } else if (BuiltinID == Builtin::BI__builtin_elementwise_min) {
2842 Result = std::min(LHS, RHS);
2843 } else {
2844 llvm_unreachable("Wrong builtin ID");
2845 }
2846
2847 pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType());
2848 return true;
2849 }
2850
2851 // Vector case.
2852 assert(Call->getArg(0)->getType()->isVectorType() &&
2853 Call->getArg(1)->getType()->isVectorType());
2854 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2855 assert(VT->getElementType() ==
2856 Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());
2857 assert(VT->getNumElements() ==
2858 Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());
2859 assert(VT->getElementType()->isIntegralOrEnumerationType());
2860
2861 const Pointer &RHS = S.Stk.pop<Pointer>();
2862 const Pointer &LHS = S.Stk.pop<Pointer>();
2863 const Pointer &Dst = S.Stk.peek<Pointer>();
2864 PrimType ElemT = *S.getContext().classify(VT->getElementType());
2865 unsigned NumElems = VT->getNumElements();
2866 for (unsigned I = 0; I != NumElems; ++I) {
2867 APSInt Elem1;
2868 APSInt Elem2;
2870 Elem1 = LHS.elem<T>(I).toAPSInt();
2871 Elem2 = RHS.elem<T>(I).toAPSInt();
2872 });
2873
2874 APSInt Result;
2875 if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
2876 Result = APSInt(std::max(Elem1, Elem2),
2877 Call->getType()->isUnsignedIntegerOrEnumerationType());
2878 } else if (BuiltinID == Builtin::BI__builtin_elementwise_min) {
2879 Result = APSInt(std::min(Elem1, Elem2),
2880 Call->getType()->isUnsignedIntegerOrEnumerationType());
2881 } else {
2882 llvm_unreachable("Wrong builtin ID");
2883 }
2884
2886 { Dst.elem<T>(I) = static_cast<T>(Result); });
2887 }
2888 Dst.initializeAllElements();
2889
2890 return true;
2891}
2892
2894 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2895 llvm::function_ref<APInt(const APSInt &, const APSInt &, const APSInt &,
2896 const APSInt &)>
2897 Fn) {
2898 assert(Call->getArg(0)->getType()->isVectorType() &&
2899 Call->getArg(1)->getType()->isVectorType());
2900 const Pointer &RHS = S.Stk.pop<Pointer>();
2901 const Pointer &LHS = S.Stk.pop<Pointer>();
2902 const Pointer &Dst = S.Stk.peek<Pointer>();
2903
2904 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2905 PrimType ElemT = *S.getContext().classify(VT->getElementType());
2906 unsigned NumElems = VT->getNumElements();
2907 const auto *DestVT = Call->getType()->castAs<VectorType>();
2908 PrimType DestElemT = *S.getContext().classify(DestVT->getElementType());
2909 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
2910
2911 unsigned DstElem = 0;
2912 for (unsigned I = 0; I != NumElems; I += 2) {
2913 APSInt Result;
2915 APSInt LoLHS = LHS.elem<T>(I).toAPSInt();
2916 APSInt HiLHS = LHS.elem<T>(I + 1).toAPSInt();
2917 APSInt LoRHS = RHS.elem<T>(I).toAPSInt();
2918 APSInt HiRHS = RHS.elem<T>(I + 1).toAPSInt();
2919 Result = APSInt(Fn(LoLHS, HiLHS, LoRHS, HiRHS), DestUnsigned);
2920 });
2921
2922 INT_TYPE_SWITCH_NO_BOOL(DestElemT,
2923 { Dst.elem<T>(DstElem) = static_cast<T>(Result); });
2924 ++DstElem;
2925 }
2926
2927 Dst.initializeAllElements();
2928 return true;
2929}
2930
2932 const CallExpr *Call) {
2933 assert(Call->getNumArgs() == 3);
2934 uint64_t Imm;
2935 if (!popToUInt64(S, Call->getArg(2), Imm))
2936 return false;
2937
2938 const Pointer &Src2 = S.Stk.pop<Pointer>();
2939 const Pointer &Src1 = S.Stk.pop<Pointer>();
2940 const Pointer &Dst = S.Stk.peek<Pointer>();
2941
2942 const auto *SrcVT = Call->getArg(0)->getType()->castAs<VectorType>();
2943 PrimType SrcElemT = *S.getContext().classify(SrcVT->getElementType());
2944 unsigned SourceLen = SrcVT->getNumElements();
2945
2946 const auto *DestVT = Call->getType()->castAs<VectorType>();
2947 PrimType DestElemT = *S.getContext().classify(DestVT->getElementType());
2948 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
2949
2950 constexpr unsigned LaneSize = 16; // 128-bit lane = 16 bytes
2951
2952 // Phase 1: Shuffle Src2 using all four 2-bit fields of imm8.
2953 // Within each 128-bit lane, for group j (0..3), select a 4-byte block
2954 // from Src2 based on bits [2*j+1:2*j] of imm8.
2955 SmallVector<uint8_t, 64> Shuffled(SourceLen);
2956 for (unsigned I = 0; I < SourceLen; I += LaneSize) {
2957 for (unsigned J = 0; J < 4; ++J) {
2958 unsigned Part = (Imm >> (2 * J)) & 3;
2959 for (unsigned K = 0; K < 4; ++K) {
2960 INT_TYPE_SWITCH_NO_BOOL(SrcElemT, {
2961 Shuffled[I + 4 * J + K] =
2962 static_cast<uint8_t>(Src2.elem<T>(I + 4 * Part + K));
2963 });
2964 }
2965 }
2966 }
2967
2968 // Phase 2: Sliding SAD computation.
2969 // For every group of 4 output u16 values, compute absolute differences
2970 // using overlapping windows into Src1 and the shuffled array.
2971 unsigned Size = SourceLen / 2; // number of output u16 elements
2972 for (unsigned I = 0; I < Size; I += 4) {
2973 unsigned Sad[4] = {0, 0, 0, 0};
2974 for (unsigned J = 0; J < 4; ++J) {
2975 uint8_t A1, A2;
2976 INT_TYPE_SWITCH_NO_BOOL(SrcElemT, {
2977 A1 = static_cast<uint8_t>(Src1.elem<T>(2 * I + J));
2978 A2 = static_cast<uint8_t>(Src1.elem<T>(2 * I + J + 4));
2979 });
2980 uint8_t B0 = Shuffled[2 * I + J];
2981 uint8_t B1 = Shuffled[2 * I + J + 1];
2982 uint8_t B2 = Shuffled[2 * I + J + 2];
2983 uint8_t B3 = Shuffled[2 * I + J + 3];
2984 Sad[0] += (A1 > B0) ? (A1 - B0) : (B0 - A1);
2985 Sad[1] += (A1 > B1) ? (A1 - B1) : (B1 - A1);
2986 Sad[2] += (A2 > B2) ? (A2 - B2) : (B2 - A2);
2987 Sad[3] += (A2 > B3) ? (A2 - B3) : (B3 - A2);
2988 }
2989 for (unsigned R = 0; R < 4; ++R) {
2990 INT_TYPE_SWITCH_NO_BOOL(DestElemT, {
2991 Dst.elem<T>(I + R) =
2992 static_cast<T>(APSInt(APInt(16, Sad[R]), DestUnsigned));
2993 });
2994 }
2995 }
2996
2997 Dst.initializeAllElements();
2998 return true;
2999}
3000
3002 InterpState &S, CodePtr OpPC, const CallExpr *Call,
3003 llvm::function_ref<APInt(const APSInt &, const APSInt &)> Fn) {
3004 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
3005 PrimType ElemT = *S.getContext().classify(VT->getElementType());
3006 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
3007
3008 const Pointer &RHS = S.Stk.pop<Pointer>();
3009 const Pointer &LHS = S.Stk.pop<Pointer>();
3010 const Pointer &Dst = S.Stk.peek<Pointer>();
3011 unsigned NumElts = VT->getNumElements();
3012 unsigned EltBits = S.getASTContext().getIntWidth(VT->getElementType());
3013 unsigned EltsPerLane = 128 / EltBits;
3014 unsigned Lanes = NumElts * EltBits / 128;
3015 unsigned DestIndex = 0;
3016
3017 for (unsigned Lane = 0; Lane < Lanes; ++Lane) {
3018 unsigned LaneStart = Lane * EltsPerLane;
3019 for (unsigned I = 0; I < EltsPerLane; I += 2) {
3021 APSInt Elem1 = LHS.elem<T>(LaneStart + I).toAPSInt();
3022 APSInt Elem2 = LHS.elem<T>(LaneStart + I + 1).toAPSInt();
3023 APSInt ResL = APSInt(Fn(Elem1, Elem2), DestUnsigned);
3024 Dst.elem<T>(DestIndex++) = static_cast<T>(ResL);
3025 });
3026 }
3027
3028 for (unsigned I = 0; I < EltsPerLane; I += 2) {
3030 APSInt Elem1 = RHS.elem<T>(LaneStart + I).toAPSInt();
3031 APSInt Elem2 = RHS.elem<T>(LaneStart + I + 1).toAPSInt();
3032 APSInt ResR = APSInt(Fn(Elem1, Elem2), DestUnsigned);
3033 Dst.elem<T>(DestIndex++) = static_cast<T>(ResR);
3034 });
3035 }
3036 }
3037 Dst.initializeAllElements();
3038 return true;
3039}
3040
3042 InterpState &S, CodePtr OpPC, const CallExpr *Call,
3043 llvm::function_ref<APFloat(const APFloat &, const APFloat &,
3044 llvm::RoundingMode)>
3045 Fn) {
3046 const Pointer &RHS = S.Stk.pop<Pointer>();
3047 const Pointer &LHS = S.Stk.pop<Pointer>();
3048 const Pointer &Dst = S.Stk.peek<Pointer>();
3049 FPOptions FPO = Call->getFPFeaturesInEffect(S.Ctx.getLangOpts());
3050 llvm::RoundingMode RM = getRoundingMode(FPO);
3051 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
3052
3053 unsigned NumElts = VT->getNumElements();
3054 unsigned EltBits = S.getASTContext().getTypeSize(VT->getElementType());
3055 unsigned NumLanes = NumElts * EltBits / 128;
3056 unsigned NumElemsPerLane = NumElts / NumLanes;
3057 unsigned HalfElemsPerLane = NumElemsPerLane / 2;
3058
3059 for (unsigned L = 0; L != NumElts; L += NumElemsPerLane) {
3060 using T = PrimConv<PT_Float>::T;
3061 for (unsigned E = 0; E != HalfElemsPerLane; ++E) {
3062 APFloat Elem1 = LHS.elem<T>(L + (2 * E) + 0).getAPFloat();
3063 APFloat Elem2 = LHS.elem<T>(L + (2 * E) + 1).getAPFloat();
3064 Dst.elem<T>(L + E) = static_cast<T>(Fn(Elem1, Elem2, RM));
3065 }
3066 for (unsigned E = 0; E != HalfElemsPerLane; ++E) {
3067 APFloat Elem1 = RHS.elem<T>(L + (2 * E) + 0).getAPFloat();
3068 APFloat Elem2 = RHS.elem<T>(L + (2 * E) + 1).getAPFloat();
3069 Dst.elem<T>(L + E + HalfElemsPerLane) =
3070 static_cast<T>(Fn(Elem1, Elem2, RM));
3071 }
3072 }
3073 Dst.initializeAllElements();
3074 return true;
3075}
3076
3078 const CallExpr *Call) {
3079 // Addsub: alternates between subtraction and addition
3080 // Result[i] = (i % 2 == 0) ? (a[i] - b[i]) : (a[i] + b[i])
3081 const Pointer &RHS = S.Stk.pop<Pointer>();
3082 const Pointer &LHS = S.Stk.pop<Pointer>();
3083 const Pointer &Dst = S.Stk.peek<Pointer>();
3084 FPOptions FPO = Call->getFPFeaturesInEffect(S.Ctx.getLangOpts());
3085 llvm::RoundingMode RM = getRoundingMode(FPO);
3086 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
3087 unsigned NumElems = VT->getNumElements();
3088
3089 using T = PrimConv<PT_Float>::T;
3090 for (unsigned I = 0; I != NumElems; ++I) {
3091 APFloat LElem = LHS.elem<T>(I).getAPFloat();
3092 APFloat RElem = RHS.elem<T>(I).getAPFloat();
3093 if (I % 2 == 0) {
3094 // Even indices: subtract
3095 LElem.subtract(RElem, RM);
3096 } else {
3097 // Odd indices: add
3098 LElem.add(RElem, RM);
3099 }
3100 Dst.elem<T>(I) = static_cast<T>(LElem);
3101 }
3102 Dst.initializeAllElements();
3103 return true;
3104}
3105
3107 const CallExpr *Call) {
3108 // PCLMULQDQ: carry-less multiplication of selected 64-bit halves
3109 // imm8 bit 0: selects lower (0) or upper (1) 64 bits of first operand
3110 // imm8 bit 4: selects lower (0) or upper (1) 64 bits of second operand
3111 assert(Call->getArg(0)->getType()->isVectorType() &&
3112 Call->getArg(1)->getType()->isVectorType());
3113
3114 // Extract imm8 argument
3115 APSInt Imm8;
3116 if (!popToAPSInt(S, Call->getArg(2), Imm8))
3117 return false;
3118 bool SelectUpperA = (Imm8 & 0x01) != 0;
3119 bool SelectUpperB = (Imm8 & 0x10) != 0;
3120
3121 const Pointer &RHS = S.Stk.pop<Pointer>();
3122 const Pointer &LHS = S.Stk.pop<Pointer>();
3123 const Pointer &Dst = S.Stk.peek<Pointer>();
3124
3125 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
3126 PrimType ElemT = *S.getContext().classify(VT->getElementType());
3127 unsigned NumElems = VT->getNumElements();
3128 const auto *DestVT = Call->getType()->castAs<VectorType>();
3129 PrimType DestElemT = *S.getContext().classify(DestVT->getElementType());
3130 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
3131
3132 // Process each 128-bit lane (2 elements at a time)
3133 for (unsigned Lane = 0; Lane < NumElems; Lane += 2) {
3134 APSInt A0, A1, B0, B1;
3136 A0 = LHS.elem<T>(Lane + 0).toAPSInt();
3137 A1 = LHS.elem<T>(Lane + 1).toAPSInt();
3138 B0 = RHS.elem<T>(Lane + 0).toAPSInt();
3139 B1 = RHS.elem<T>(Lane + 1).toAPSInt();
3140 });
3141
3142 // Select the appropriate 64-bit values based on imm8
3143 APInt A = SelectUpperA ? A1 : A0;
3144 APInt B = SelectUpperB ? B1 : B0;
3145
3146 // Extend both operands to 128 bits for carry-less multiplication
3147 APInt A128 = A.zext(128);
3148 APInt B128 = B.zext(128);
3149
3150 // Use APIntOps::clmul for carry-less multiplication
3151 APInt Result = llvm::APIntOps::clmul(A128, B128);
3152
3153 // Split the 128-bit result into two 64-bit halves
3154 APSInt ResultLow(Result.extractBits(64, 0), DestUnsigned);
3155 APSInt ResultHigh(Result.extractBits(64, 64), DestUnsigned);
3156
3157 INT_TYPE_SWITCH_NO_BOOL(DestElemT, {
3158 Dst.elem<T>(Lane + 0) = static_cast<T>(ResultLow);
3159 Dst.elem<T>(Lane + 1) = static_cast<T>(ResultHigh);
3160 });
3161 }
3162
3163 Dst.initializeAllElements();
3164 return true;
3165}
3166
3168 InterpState &S, CodePtr OpPC, const CallExpr *Call,
3169 llvm::function_ref<APFloat(const APFloat &, const APFloat &,
3170 const APFloat &, llvm::RoundingMode)>
3171 Fn) {
3172 assert(Call->getNumArgs() == 3);
3173
3174 FPOptions FPO = Call->getFPFeaturesInEffect(S.Ctx.getLangOpts());
3175 llvm::RoundingMode RM = getRoundingMode(FPO);
3176 QualType Arg1Type = Call->getArg(0)->getType();
3177 QualType Arg2Type = Call->getArg(1)->getType();
3178 QualType Arg3Type = Call->getArg(2)->getType();
3179
3180 // Non-vector floating point types.
3181 if (!Arg1Type->isVectorType()) {
3182 assert(!Arg2Type->isVectorType());
3183 assert(!Arg3Type->isVectorType());
3184 (void)Arg2Type;
3185 (void)Arg3Type;
3186
3187 const Floating &Z = S.Stk.pop<Floating>();
3188 const Floating &Y = S.Stk.pop<Floating>();
3189 const Floating &X = S.Stk.pop<Floating>();
3190 APFloat F = Fn(X.getAPFloat(), Y.getAPFloat(), Z.getAPFloat(), RM);
3191 Floating Result = S.allocFloat(X.getSemantics());
3192 Result.copy(F);
3193 S.Stk.push<Floating>(Result);
3194 return true;
3195 }
3196
3197 // Vector type.
3198 assert(Arg1Type->isVectorType() && Arg2Type->isVectorType() &&
3199 Arg3Type->isVectorType());
3200
3201 const VectorType *VecTy = Arg1Type->castAs<VectorType>();
3202 QualType ElemQT = VecTy->getElementType();
3203 unsigned NumElems = VecTy->getNumElements();
3204
3205 assert(ElemQT == Arg2Type->castAs<VectorType>()->getElementType() &&
3206 ElemQT == Arg3Type->castAs<VectorType>()->getElementType());
3207 assert(NumElems == Arg2Type->castAs<VectorType>()->getNumElements() &&
3208 NumElems == Arg3Type->castAs<VectorType>()->getNumElements());
3209 assert(ElemQT->isRealFloatingType());
3210 (void)ElemQT;
3211
3212 const Pointer &VZ = S.Stk.pop<Pointer>();
3213 const Pointer &VY = S.Stk.pop<Pointer>();
3214 const Pointer &VX = S.Stk.pop<Pointer>();
3215 const Pointer &Dst = S.Stk.peek<Pointer>();
3216 for (unsigned I = 0; I != NumElems; ++I) {
3217 using T = PrimConv<PT_Float>::T;
3218 APFloat X = VX.elem<T>(I).getAPFloat();
3219 APFloat Y = VY.elem<T>(I).getAPFloat();
3220 APFloat Z = VZ.elem<T>(I).getAPFloat();
3221 APFloat F = Fn(X, Y, Z, RM);
3222 Dst.elem<Floating>(I) = Floating(F);
3223 }
3225 return true;
3226}
3227
3228/// AVX512 predicated move: "Result = Mask[] ? LHS[] : RHS[]".
3230 const CallExpr *Call) {
3231 const Pointer &RHS = S.Stk.pop<Pointer>();
3232 const Pointer &LHS = S.Stk.pop<Pointer>();
3233 APSInt Mask;
3234 if (!popToAPSInt(S, Call->getArg(0), Mask))
3235 return false;
3236 const Pointer &Dst = S.Stk.peek<Pointer>();
3237
3238 assert(LHS.getNumElems() == RHS.getNumElems());
3239 assert(LHS.getNumElems() == Dst.getNumElems());
3240 unsigned NumElems = LHS.getNumElems();
3241 PrimType ElemT = LHS.getFieldDesc()->getPrimType();
3242 PrimType DstElemT = Dst.getFieldDesc()->getPrimType();
3243
3244 for (unsigned I = 0; I != NumElems; ++I) {
3245 if (ElemT == PT_Float) {
3246 assert(DstElemT == PT_Float);
3247 Dst.elem<Floating>(I) =
3248 Mask[I] ? LHS.elem<Floating>(I) : RHS.elem<Floating>(I);
3249 } else {
3250 APSInt Elem;
3251 INT_TYPE_SWITCH(ElemT, {
3252 Elem = Mask[I] ? LHS.elem<T>(I).toAPSInt() : RHS.elem<T>(I).toAPSInt();
3253 });
3254 INT_TYPE_SWITCH_NO_BOOL(DstElemT,
3255 { Dst.elem<T>(I) = static_cast<T>(Elem); });
3256 }
3257 }
3259
3260 return true;
3261}
3262
3263/// Scalar variant of AVX512 predicated select:
3264/// Result[i] = (Mask bit 0) ? LHS[i] : RHS[i], but only element 0 may change.
3265/// All other elements are taken from RHS.
3267 const CallExpr *Call) {
3268 unsigned N =
3269 Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements();
3270
3271 const Pointer &W = S.Stk.pop<Pointer>();
3272 const Pointer &A = S.Stk.pop<Pointer>();
3273 APSInt U;
3274 if (!popToAPSInt(S, Call->getArg(0), U))
3275 return false;
3276 const Pointer &Dst = S.Stk.peek<Pointer>();
3277
3278 bool TakeA0 = U.getZExtValue() & 1ULL;
3279
3280 for (unsigned I = TakeA0; I != N; ++I)
3281 Dst.elem<Floating>(I) = W.elem<Floating>(I);
3282 if (TakeA0)
3283 Dst.elem<Floating>(0) = A.elem<Floating>(0);
3284
3286 return true;
3287}
3288
3290 InterpState &S, CodePtr OpPC, const CallExpr *Call,
3291 llvm::function_ref<bool(const APInt &A, const APInt &B)> Fn) {
3292 const Pointer &RHS = S.Stk.pop<Pointer>();
3293 const Pointer &LHS = S.Stk.pop<Pointer>();
3294
3295 assert(LHS.getNumElems() == RHS.getNumElems());
3296
3297 unsigned SourceLen = LHS.getNumElems();
3298 QualType ElemQT = getElemType(LHS);
3299 OptPrimType ElemPT = S.getContext().classify(ElemQT);
3300 unsigned LaneWidth = S.getASTContext().getTypeSize(ElemQT);
3301
3302 APInt AWide(LaneWidth * SourceLen, 0);
3303 APInt BWide(LaneWidth * SourceLen, 0);
3304
3305 for (unsigned I = 0; I != SourceLen; ++I) {
3306 APInt ALane;
3307 APInt BLane;
3308
3309 if (ElemQT->isIntegerType()) { // Get value.
3310 INT_TYPE_SWITCH_NO_BOOL(*ElemPT, {
3311 ALane = LHS.elem<T>(I).toAPSInt();
3312 BLane = RHS.elem<T>(I).toAPSInt();
3313 });
3314 } else if (ElemQT->isFloatingType()) { // Get only sign bit.
3315 using T = PrimConv<PT_Float>::T;
3316 ALane = LHS.elem<T>(I).getAPFloat().bitcastToAPInt().isNegative();
3317 BLane = RHS.elem<T>(I).getAPFloat().bitcastToAPInt().isNegative();
3318 } else { // Must be integer or floating type.
3319 return false;
3320 }
3321 AWide.insertBits(ALane, I * LaneWidth);
3322 BWide.insertBits(BLane, I * LaneWidth);
3323 }
3324 pushInteger(S, Fn(AWide, BWide), Call->getType());
3325 return true;
3326}
3327
3329 const CallExpr *Call) {
3330 assert(Call->getNumArgs() == 1);
3331
3332 const Pointer &Source = S.Stk.pop<Pointer>();
3333
3334 unsigned SourceLen = Source.getNumElems();
3335 QualType ElemQT = getElemType(Source);
3336 OptPrimType ElemT = S.getContext().classify(ElemQT);
3337 unsigned ResultLen =
3338 S.getASTContext().getTypeSize(Call->getType()); // Always 32-bit integer.
3339 APInt Result(ResultLen, 0);
3340
3341 for (unsigned I = 0; I != SourceLen; ++I) {
3342 APInt Elem;
3343 if (ElemQT->isIntegerType()) {
3344 INT_TYPE_SWITCH_NO_BOOL(*ElemT, { Elem = Source.elem<T>(I).toAPSInt(); });
3345 } else if (ElemQT->isRealFloatingType()) {
3346 using T = PrimConv<PT_Float>::T;
3347 Elem = Source.elem<T>(I).getAPFloat().bitcastToAPInt();
3348 } else {
3349 return false;
3350 }
3351 Result.setBitVal(I, Elem.isNegative());
3352 }
3353 pushInteger(S, Result, Call->getType());
3354 return true;
3355}
3356
3358 InterpState &S, CodePtr OpPC, const CallExpr *Call,
3359 llvm::function_ref<APInt(const APSInt &, const APSInt &, const APSInt &)>
3360 Fn) {
3361 assert(Call->getNumArgs() == 3);
3362
3363 QualType Arg0Type = Call->getArg(0)->getType();
3364 QualType Arg2Type = Call->getArg(2)->getType();
3365 // Non-vector integer types.
3366 if (!Arg0Type->isVectorType()) {
3367 APSInt Op2;
3368 if (!popToAPSInt(S, Arg2Type, Op2))
3369 return false;
3370 APSInt Op1;
3371 if (!popToAPSInt(S, Call->getArg(1), Op1))
3372 return false;
3373 APSInt Op0;
3374 if (!popToAPSInt(S, Arg0Type, Op0))
3375 return false;
3376 APSInt Result = APSInt(Fn(Op0, Op1, Op2), Op0.isUnsigned());
3377 pushInteger(S, Result, Call->getType());
3378 return true;
3379 }
3380
3381 const auto *VecT = Arg0Type->castAs<VectorType>();
3382 PrimType ElemT = *S.getContext().classify(VecT->getElementType());
3383 unsigned NumElems = VecT->getNumElements();
3384 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
3385
3386 // Vector + Vector + Scalar case.
3387 if (!Arg2Type->isVectorType()) {
3388 APSInt Op2;
3389 if (!popToAPSInt(S, Arg2Type, Op2))
3390 return false;
3391
3392 const Pointer &Op1 = S.Stk.pop<Pointer>();
3393 const Pointer &Op0 = S.Stk.pop<Pointer>();
3394 const Pointer &Dst = S.Stk.peek<Pointer>();
3395 for (unsigned I = 0; I != NumElems; ++I) {
3397 Dst.elem<T>(I) = static_cast<T>(APSInt(
3398 Fn(Op0.elem<T>(I).toAPSInt(), Op1.elem<T>(I).toAPSInt(), Op2),
3399 DestUnsigned));
3400 });
3401 }
3403
3404 return true;
3405 }
3406
3407 // Vector type.
3408 const Pointer &Op2 = S.Stk.pop<Pointer>();
3409 const Pointer &Op1 = S.Stk.pop<Pointer>();
3410 const Pointer &Op0 = S.Stk.pop<Pointer>();
3411 const Pointer &Dst = S.Stk.peek<Pointer>();
3412 for (unsigned I = 0; I != NumElems; ++I) {
3413 APSInt Val0, Val1, Val2;
3415 Val0 = Op0.elem<T>(I).toAPSInt();
3416 Val1 = Op1.elem<T>(I).toAPSInt();
3417 Val2 = Op2.elem<T>(I).toAPSInt();
3418 });
3419 APSInt Result = APSInt(Fn(Val0, Val1, Val2), Val0.isUnsigned());
3421 { Dst.elem<T>(I) = static_cast<T>(Result); });
3422 }
3424
3425 return true;
3426}
3427
3429 const CallExpr *Call,
3430 unsigned ID) {
3431 assert(Call->getNumArgs() == 2);
3432
3433 APSInt ImmAPS;
3434 if (!popToAPSInt(S, Call->getArg(1), ImmAPS))
3435 return false;
3436 uint64_t Index = ImmAPS.getZExtValue();
3437
3438 const Pointer &Src = S.Stk.pop<Pointer>();
3439 if (!Src.getFieldDesc()->isPrimitiveArray())
3440 return false;
3441
3442 const Pointer &Dst = S.Stk.peek<Pointer>();
3443 if (!Dst.getFieldDesc()->isPrimitiveArray())
3444 return false;
3445
3446 unsigned SrcElems = Src.getNumElems();
3447 unsigned DstElems = Dst.getNumElems();
3448
3449 unsigned NumLanes = SrcElems / DstElems;
3450 unsigned Lane = static_cast<unsigned>(Index % NumLanes);
3451 unsigned ExtractPos = Lane * DstElems;
3452
3453 PrimType ElemT = Src.getFieldDesc()->getPrimType();
3454
3455 TYPE_SWITCH(ElemT, {
3456 for (unsigned I = 0; I != DstElems; ++I) {
3457 Dst.elem<T>(I) = Src.elem<T>(ExtractPos + I);
3458 }
3459 });
3460
3462 return true;
3463}
3464
3466 CodePtr OpPC,
3467 const CallExpr *Call,
3468 unsigned ID) {
3469 assert(Call->getNumArgs() == 4);
3470
3471 APSInt MaskAPS;
3472 if (!popToAPSInt(S, Call->getArg(3), MaskAPS))
3473 return false;
3474 const Pointer &Merge = S.Stk.pop<Pointer>();
3475 APSInt ImmAPS;
3476 if (!popToAPSInt(S, Call->getArg(1), ImmAPS))
3477 return false;
3478 const Pointer &Src = S.Stk.pop<Pointer>();
3479
3480 if (!Src.getFieldDesc()->isPrimitiveArray() ||
3481 !Merge.getFieldDesc()->isPrimitiveArray())
3482 return false;
3483
3484 const Pointer &Dst = S.Stk.peek<Pointer>();
3485 if (!Dst.getFieldDesc()->isPrimitiveArray())
3486 return false;
3487
3488 unsigned SrcElems = Src.getNumElems();
3489 unsigned DstElems = Dst.getNumElems();
3490
3491 unsigned NumLanes = SrcElems / DstElems;
3492 unsigned Lane = static_cast<unsigned>(ImmAPS.getZExtValue() % NumLanes);
3493 unsigned Base = Lane * DstElems;
3494
3495 PrimType ElemT = Src.getFieldDesc()->getPrimType();
3496
3497 TYPE_SWITCH(ElemT, {
3498 for (unsigned I = 0; I != DstElems; ++I) {
3499 if (MaskAPS[I])
3500 Dst.elem<T>(I) = Src.elem<T>(Base + I);
3501 else
3502 Dst.elem<T>(I) = Merge.elem<T>(I);
3503 }
3504 });
3505
3507 return true;
3508}
3509
3511 const CallExpr *Call,
3512 unsigned ID) {
3513 assert(Call->getNumArgs() == 3);
3514
3515 APSInt ImmAPS;
3516 if (!popToAPSInt(S, Call->getArg(2), ImmAPS))
3517 return false;
3518 uint64_t Index = ImmAPS.getZExtValue();
3519
3520 const Pointer &SubVec = S.Stk.pop<Pointer>();
3521 if (!SubVec.getFieldDesc()->isPrimitiveArray())
3522 return false;
3523
3524 const Pointer &BaseVec = S.Stk.pop<Pointer>();
3525 if (!BaseVec.getFieldDesc()->isPrimitiveArray())
3526 return false;
3527
3528 const Pointer &Dst = S.Stk.peek<Pointer>();
3529
3530 unsigned BaseElements = BaseVec.getNumElems();
3531 unsigned SubElements = SubVec.getNumElems();
3532
3533 assert(SubElements != 0 && BaseElements != 0 &&
3534 (BaseElements % SubElements) == 0);
3535
3536 unsigned NumLanes = BaseElements / SubElements;
3537 unsigned Lane = static_cast<unsigned>(Index % NumLanes);
3538 unsigned InsertPos = Lane * SubElements;
3539
3540 PrimType ElemT = BaseVec.getFieldDesc()->getPrimType();
3541
3542 TYPE_SWITCH(ElemT, {
3543 for (unsigned I = 0; I != BaseElements; ++I)
3544 Dst.elem<T>(I) = BaseVec.elem<T>(I);
3545 for (unsigned I = 0; I != SubElements; ++I)
3546 Dst.elem<T>(InsertPos + I) = SubVec.elem<T>(I);
3547 });
3548
3550 return true;
3551}
3552
3554 const CallExpr *Call) {
3555 assert(Call->getNumArgs() == 1);
3556
3557 const Pointer &Source = S.Stk.pop<Pointer>();
3558 const Pointer &Dest = S.Stk.peek<Pointer>();
3559
3560 unsigned SourceLen = Source.getNumElems();
3561 QualType ElemQT = getElemType(Source);
3562 OptPrimType ElemT = S.getContext().classify(ElemQT);
3563 unsigned ElemBitWidth = S.getASTContext().getTypeSize(ElemQT);
3564
3565 bool DestUnsigned = Call->getCallReturnType(S.getASTContext())
3566 ->castAs<VectorType>()
3567 ->getElementType()
3569
3570 INT_TYPE_SWITCH_NO_BOOL(*ElemT, {
3571 APSInt MinIndex(ElemBitWidth, DestUnsigned);
3572 APSInt MinVal = Source.elem<T>(0).toAPSInt();
3573
3574 for (unsigned I = 1; I != SourceLen; ++I) {
3575 APSInt Val = Source.elem<T>(I).toAPSInt();
3576 if (MinVal.ugt(Val)) {
3577 MinVal = Val;
3578 MinIndex = I;
3579 }
3580 }
3581
3582 Dest.elem<T>(0) = static_cast<T>(MinVal);
3583 Dest.elem<T>(1) = static_cast<T>(MinIndex);
3584 for (unsigned I = 2; I != SourceLen; ++I) {
3585 Dest.elem<T>(I) = static_cast<T>(APSInt(ElemBitWidth, DestUnsigned));
3586 }
3587 });
3588 Dest.initializeAllElements();
3589 return true;
3590}
3591
3593 const CallExpr *Call, bool MaskZ) {
3594 assert(Call->getNumArgs() == 5);
3595
3596 APSInt UVal;
3597 if (!popToAPSInt(S, Call->getArg(4), UVal))
3598 return false;
3599 APInt U = UVal; // Lane mask
3600 APSInt ImmVal;
3601 if (!popToAPSInt(S, Call->getArg(3), ImmVal))
3602 return false;
3603 APInt Imm = ImmVal; // Ternary truth table
3604 const Pointer &C = S.Stk.pop<Pointer>();
3605 const Pointer &B = S.Stk.pop<Pointer>();
3606 const Pointer &A = S.Stk.pop<Pointer>();
3607 const Pointer &Dst = S.Stk.peek<Pointer>();
3608
3609 unsigned DstLen = A.getNumElems();
3610 QualType ElemQT = getElemType(A);
3611 OptPrimType ElemT = S.getContext().classify(ElemQT);
3612 unsigned LaneWidth = S.getASTContext().getTypeSize(ElemQT);
3613 bool DstUnsigned = ElemQT->isUnsignedIntegerOrEnumerationType();
3614
3615 INT_TYPE_SWITCH_NO_BOOL(*ElemT, {
3616 for (unsigned I = 0; I != DstLen; ++I) {
3617 APInt ALane = A.elem<T>(I).toAPSInt();
3618 APInt BLane = B.elem<T>(I).toAPSInt();
3619 APInt CLane = C.elem<T>(I).toAPSInt();
3620 APInt RLane(LaneWidth, 0);
3621 if (U[I]) { // If lane not masked, compute ternary logic.
3622 for (unsigned Bit = 0; Bit != LaneWidth; ++Bit) {
3623 unsigned ABit = ALane[Bit];
3624 unsigned BBit = BLane[Bit];
3625 unsigned CBit = CLane[Bit];
3626 unsigned Idx = (ABit << 2) | (BBit << 1) | (CBit);
3627 RLane.setBitVal(Bit, Imm[Idx]);
3628 }
3629 Dst.elem<T>(I) = static_cast<T>(APSInt(RLane, DstUnsigned));
3630 } else if (MaskZ) { // If zero masked, zero the lane.
3631 Dst.elem<T>(I) = static_cast<T>(APSInt(RLane, DstUnsigned));
3632 } else { // Just masked, put in A lane.
3633 Dst.elem<T>(I) = static_cast<T>(APSInt(ALane, DstUnsigned));
3634 }
3635 }
3636 });
3637 Dst.initializeAllElements();
3638 return true;
3639}
3640
3642 const CallExpr *Call, unsigned ID) {
3643 assert(Call->getNumArgs() == 2);
3644
3645 APSInt ImmAPS;
3646 if (!popToAPSInt(S, Call->getArg(1), ImmAPS))
3647 return false;
3648 const Pointer &Vec = S.Stk.pop<Pointer>();
3649 if (!Vec.getFieldDesc()->isPrimitiveArray())
3650 return false;
3651
3652 unsigned NumElems = Vec.getNumElems();
3653 unsigned Index =
3654 static_cast<unsigned>(ImmAPS.getZExtValue() & (NumElems - 1));
3655
3656 PrimType ElemT = Vec.getFieldDesc()->getPrimType();
3657 // FIXME(#161685): Replace float+int split with a numeric-only type switch
3658 if (ElemT == PT_Float) {
3659 S.Stk.push<Floating>(Vec.elem<Floating>(Index));
3660 return true;
3661 }
3663 APSInt V = Vec.elem<T>(Index).toAPSInt();
3664 pushInteger(S, V, Call->getType());
3665 });
3666
3667 return true;
3668}
3669
3671 const CallExpr *Call, unsigned ID) {
3672 assert(Call->getNumArgs() == 3);
3673
3674 APSInt ImmAPS;
3675 if (!popToAPSInt(S, Call->getArg(2), ImmAPS))
3676 return false;
3677 APSInt ValAPS;
3678 if (!popToAPSInt(S, Call->getArg(1), ValAPS))
3679 return false;
3680
3681 const Pointer &Base = S.Stk.pop<Pointer>();
3682 if (!Base.getFieldDesc()->isPrimitiveArray())
3683 return false;
3684
3685 const Pointer &Dst = S.Stk.peek<Pointer>();
3686
3687 unsigned NumElems = Base.getNumElems();
3688 unsigned Index =
3689 static_cast<unsigned>(ImmAPS.getZExtValue() & (NumElems - 1));
3690
3691 PrimType ElemT = Base.getFieldDesc()->getPrimType();
3693 for (unsigned I = 0; I != NumElems; ++I)
3694 Dst.elem<T>(I) = Base.elem<T>(I);
3695 Dst.elem<T>(Index) = static_cast<T>(ValAPS);
3696 });
3697
3699 return true;
3700}
3701
3702static bool evalICmpImm(uint8_t Imm, const APSInt &A, const APSInt &B,
3703 bool IsUnsigned) {
3704 switch (Imm & 0x7) {
3705 case 0x00: // _MM_CMPINT_EQ
3706 return (A == B);
3707 case 0x01: // _MM_CMPINT_LT
3708 return IsUnsigned ? A.ult(B) : A.slt(B);
3709 case 0x02: // _MM_CMPINT_LE
3710 return IsUnsigned ? A.ule(B) : A.sle(B);
3711 case 0x03: // _MM_CMPINT_FALSE
3712 return false;
3713 case 0x04: // _MM_CMPINT_NE
3714 return (A != B);
3715 case 0x05: // _MM_CMPINT_NLT
3716 return IsUnsigned ? A.ugt(B) : A.sgt(B);
3717 case 0x06: // _MM_CMPINT_NLE
3718 return IsUnsigned ? A.uge(B) : A.sge(B);
3719 case 0x07: // _MM_CMPINT_TRUE
3720 return true;
3721 default:
3722 llvm_unreachable("Invalid Op");
3723 }
3724}
3725
3727 const CallExpr *Call, unsigned ID,
3728 bool IsUnsigned) {
3729 assert(Call->getNumArgs() == 4);
3730
3731 APSInt Mask;
3732 if (!popToAPSInt(S, Call->getArg(3), Mask))
3733 return false;
3734 APSInt Opcode;
3735 if (!popToAPSInt(S, Call->getArg(2), Opcode))
3736 return false;
3737 unsigned CmpOp = static_cast<unsigned>(Opcode.getZExtValue());
3738 const Pointer &RHS = S.Stk.pop<Pointer>();
3739 const Pointer &LHS = S.Stk.pop<Pointer>();
3740
3741 assert(LHS.getNumElems() == RHS.getNumElems());
3742
3743 APInt RetMask = APInt::getZero(LHS.getNumElems());
3744 unsigned VectorLen = LHS.getNumElems();
3745 PrimType ElemT = LHS.getFieldDesc()->getPrimType();
3746
3747 for (unsigned ElemNum = 0; ElemNum < VectorLen; ++ElemNum) {
3748 APSInt A, B;
3750 A = LHS.elem<T>(ElemNum).toAPSInt();
3751 B = RHS.elem<T>(ElemNum).toAPSInt();
3752 });
3753 RetMask.setBitVal(ElemNum,
3754 Mask[ElemNum] && evalICmpImm(CmpOp, A, B, IsUnsigned));
3755 }
3756 pushInteger(S, RetMask, Call->getType());
3757 return true;
3758}
3759
3761 const CallExpr *Call) {
3762 assert(Call->getNumArgs() == 1);
3763
3764 QualType Arg0Type = Call->getArg(0)->getType();
3765 const auto *VecT = Arg0Type->castAs<VectorType>();
3766 PrimType ElemT = *S.getContext().classify(VecT->getElementType());
3767 unsigned NumElems = VecT->getNumElements();
3768 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
3769 const Pointer &Src = S.Stk.pop<Pointer>();
3770 const Pointer &Dst = S.Stk.peek<Pointer>();
3771
3772 for (unsigned I = 0; I != NumElems; ++I) {
3774 APSInt ElemI = Src.elem<T>(I).toAPSInt();
3775 APInt ConflictMask(ElemI.getBitWidth(), 0);
3776 for (unsigned J = 0; J != I; ++J) {
3777 APSInt ElemJ = Src.elem<T>(J).toAPSInt();
3778 ConflictMask.setBitVal(J, ElemI == ElemJ);
3779 }
3780 Dst.elem<T>(I) = static_cast<T>(APSInt(ConflictMask, DestUnsigned));
3781 });
3782 }
3784 return true;
3785}
3786
3788 const CallExpr *Call,
3789 unsigned ID) {
3790 assert(Call->getNumArgs() == 1);
3791
3792 const Pointer &Vec = S.Stk.pop<Pointer>();
3793 unsigned RetWidth = S.getASTContext().getIntWidth(Call->getType());
3794 APInt RetMask(RetWidth, 0);
3795
3796 unsigned VectorLen = Vec.getNumElems();
3797 PrimType ElemT = Vec.getFieldDesc()->getPrimType();
3798
3799 for (unsigned ElemNum = 0; ElemNum != VectorLen; ++ElemNum) {
3800 APSInt A;
3801 INT_TYPE_SWITCH_NO_BOOL(ElemT, { A = Vec.elem<T>(ElemNum).toAPSInt(); });
3802 unsigned MSB = A[A.getBitWidth() - 1];
3803 RetMask.setBitVal(ElemNum, MSB);
3804 }
3805 pushInteger(S, RetMask, Call->getType());
3806 return true;
3807}
3808
3810 const CallExpr *Call,
3811 unsigned ID) {
3812 assert(Call->getNumArgs() == 1);
3813
3814 APSInt Mask;
3815 if (!popToAPSInt(S, Call->getArg(0), Mask))
3816 return false;
3817
3818 const Pointer &Vec = S.Stk.peek<Pointer>();
3819 unsigned NumElems = Vec.getNumElems();
3820 PrimType ElemT = Vec.getFieldDesc()->getPrimType();
3821
3822 for (unsigned I = 0; I != NumElems; ++I) {
3823 bool BitSet = Mask[I];
3824
3826 ElemT, { Vec.elem<T>(I) = BitSet ? T::from(-1) : T::from(0); });
3827 }
3828
3830
3831 return true;
3832}
3833
3835 const CallExpr *Call,
3836 bool HasRoundingMask) {
3837 APSInt Rounding, MaskInt;
3838 Pointer Src, B, A;
3839
3840 if (HasRoundingMask) {
3841 assert(Call->getNumArgs() == 5);
3842 if (!popToAPSInt(S, Call->getArg(4), Rounding))
3843 return false;
3844 if (!popToAPSInt(S, Call->getArg(3), MaskInt))
3845 return false;
3846 Src = S.Stk.pop<Pointer>();
3847 B = S.Stk.pop<Pointer>();
3848 A = S.Stk.pop<Pointer>();
3849 if (!CheckLoad(S, OpPC, A) || !CheckLoad(S, OpPC, B) ||
3850 !CheckLoad(S, OpPC, Src))
3851 return false;
3852 } else {
3853 assert(Call->getNumArgs() == 2);
3854 B = S.Stk.pop<Pointer>();
3855 A = S.Stk.pop<Pointer>();
3856 if (!CheckLoad(S, OpPC, A) || !CheckLoad(S, OpPC, B))
3857 return false;
3858 }
3859
3860 const auto *DstVTy = Call->getType()->castAs<VectorType>();
3861 unsigned NumElems = DstVTy->getNumElements();
3862 const Pointer &Dst = S.Stk.peek<Pointer>();
3863
3864 // Copy all elements except lane 0 (overwritten below) from A to Dst.
3865 for (unsigned I = 1; I != NumElems; ++I)
3866 Dst.elem<Floating>(I) = A.elem<Floating>(I);
3867
3868 // Convert element 0 from double to float, or use Src if masked off.
3869 if (!HasRoundingMask || (MaskInt.getZExtValue() & 0x1)) {
3870 assert(S.getASTContext().FloatTy == DstVTy->getElementType() &&
3871 "cvtsd2ss requires float element type in destination vector");
3872
3873 Floating Conv = S.allocFloat(
3874 S.getASTContext().getFloatTypeSemantics(DstVTy->getElementType()));
3875 APFloat SrcVal = B.elem<Floating>(0).getAPFloat();
3876 if (!convertDoubleToFloatStrict(SrcVal, Conv, S, Call))
3877 return false;
3878 Dst.elem<Floating>(0) = Conv;
3879 } else {
3880 Dst.elem<Floating>(0) = Src.elem<Floating>(0);
3881 }
3882
3884 return true;
3885}
3886
3888 const CallExpr *Call, bool IsMasked,
3889 bool HasRounding) {
3890
3891 APSInt MaskVal;
3892 Pointer PassThrough;
3893 Pointer Src;
3894 APSInt Rounding;
3895
3896 if (IsMasked) {
3897 // Pop in reverse order.
3898 if (HasRounding) {
3899 if (!popToAPSInt(S, Call->getArg(3), Rounding))
3900 return false;
3901 if (!popToAPSInt(S, Call->getArg(2), MaskVal))
3902 return false;
3903 PassThrough = S.Stk.pop<Pointer>();
3904 Src = S.Stk.pop<Pointer>();
3905 } else {
3906 if (!popToAPSInt(S, Call->getArg(2), MaskVal))
3907 return false;
3908 PassThrough = S.Stk.pop<Pointer>();
3909 Src = S.Stk.pop<Pointer>();
3910 }
3911
3912 if (!CheckLoad(S, OpPC, PassThrough))
3913 return false;
3914 } else {
3915 // Pop source only.
3916 Src = S.Stk.pop<Pointer>();
3917 }
3918
3919 if (!CheckLoad(S, OpPC, Src))
3920 return false;
3921
3922 const auto *RetVTy = Call->getType()->castAs<VectorType>();
3923 unsigned RetElems = RetVTy->getNumElements();
3924 unsigned SrcElems = Src.getNumElems();
3925 const Pointer &Dst = S.Stk.peek<Pointer>();
3926
3927 // Initialize destination with passthrough or zeros.
3928 for (unsigned I = 0; I != RetElems; ++I)
3929 if (IsMasked)
3930 Dst.elem<Floating>(I) = PassThrough.elem<Floating>(I);
3931 else
3932 Dst.elem<Floating>(I) = Floating(APFloat(0.0f));
3933
3934 assert(S.getASTContext().FloatTy == RetVTy->getElementType() &&
3935 "cvtpd2ps requires float element type in return vector");
3936
3937 // Convert double to float for enabled elements (only process source elements
3938 // that exist).
3939 for (unsigned I = 0; I != SrcElems; ++I) {
3940 if (IsMasked && !MaskVal[I])
3941 continue;
3942
3943 APFloat SrcVal = Src.elem<Floating>(I).getAPFloat();
3944
3945 Floating Conv = S.allocFloat(
3946 S.getASTContext().getFloatTypeSemantics(RetVTy->getElementType()));
3947 if (!convertDoubleToFloatStrict(SrcVal, Conv, S, Call))
3948 return false;
3949 Dst.elem<Floating>(I) = Conv;
3950 }
3951
3953 return true;
3954}
3955
3957 InterpState &S, CodePtr OpPC, const CallExpr *Call,
3958 llvm::function_ref<std::pair<unsigned, int>(unsigned, const APInt &)>
3959 GetSourceIndex) {
3960
3961 assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3);
3962
3963 APInt ShuffleMask;
3964 Pointer A, MaskVector, B;
3965 bool IsVectorMask = false;
3966 bool IsSingleOperand = (Call->getNumArgs() == 2);
3967
3968 if (IsSingleOperand) {
3969 QualType MaskType = Call->getArg(1)->getType();
3970 if (MaskType->isVectorType()) {
3971 IsVectorMask = true;
3972 MaskVector = S.Stk.pop<Pointer>();
3973 A = S.Stk.pop<Pointer>();
3974 B = A;
3975 } else if (MaskType->isIntegerType()) {
3976 APSInt MaskVal;
3977 if (!popToAPSInt(S, Call->getArg(1), MaskVal))
3978 return false;
3979 ShuffleMask = MaskVal;
3980 A = S.Stk.pop<Pointer>();
3981 B = A;
3982 } else {
3983 return false;
3984 }
3985 } else {
3986 QualType Arg2Type = Call->getArg(2)->getType();
3987 if (Arg2Type->isVectorType()) {
3988 IsVectorMask = true;
3989 B = S.Stk.pop<Pointer>();
3990 MaskVector = S.Stk.pop<Pointer>();
3991 A = S.Stk.pop<Pointer>();
3992 } else if (Arg2Type->isIntegerType()) {
3993 APSInt MaskVal;
3994 if (!popToAPSInt(S, Call->getArg(2), MaskVal))
3995 return false;
3996 ShuffleMask = MaskVal;
3997 B = S.Stk.pop<Pointer>();
3998 A = S.Stk.pop<Pointer>();
3999 } else {
4000 return false;
4001 }
4002 }
4003
4004 QualType Arg0Type = Call->getArg(0)->getType();
4005 const auto *VecT = Arg0Type->castAs<VectorType>();
4006 PrimType ElemT = *S.getContext().classify(VecT->getElementType());
4007 unsigned NumElems = VecT->getNumElements();
4008
4009 const Pointer &Dst = S.Stk.peek<Pointer>();
4010
4011 PrimType MaskElemT = PT_Uint32;
4012 if (IsVectorMask) {
4013 QualType Arg1Type = Call->getArg(1)->getType();
4014 const auto *MaskVecT = Arg1Type->castAs<VectorType>();
4015 QualType MaskElemType = MaskVecT->getElementType();
4016 MaskElemT = *S.getContext().classify(MaskElemType);
4017 }
4018
4019 for (unsigned DstIdx = 0; DstIdx != NumElems; ++DstIdx) {
4020 if (IsVectorMask) {
4021 INT_TYPE_SWITCH(MaskElemT,
4022 { ShuffleMask = MaskVector.elem<T>(DstIdx).toAPSInt(); });
4023 }
4024
4025 auto [SrcVecIdx, SrcIdx] = GetSourceIndex(DstIdx, ShuffleMask);
4026
4027 if (SrcIdx < 0) {
4028 // Zero out this element
4029 if (ElemT == PT_Float) {
4030 Dst.elem<Floating>(DstIdx) = Floating(
4031 S.getASTContext().getFloatTypeSemantics(VecT->getElementType()));
4032 } else {
4033 INT_TYPE_SWITCH_NO_BOOL(ElemT, { Dst.elem<T>(DstIdx) = T::from(0); });
4034 }
4035 } else {
4036 const Pointer &Src = (SrcVecIdx == 0) ? A : B;
4037 TYPE_SWITCH(ElemT, { Dst.elem<T>(DstIdx) = Src.elem<T>(SrcIdx); });
4038 }
4039 }
4041
4042 return true;
4043}
4044
4046 InterpState &S, CodePtr OpPC, const CallExpr *Call,
4047 llvm::function_ref<std::pair<unsigned, int>(unsigned, unsigned)>
4048 GetSourceIndex) {
4050 S, OpPC, Call,
4051 [&GetSourceIndex](unsigned DstIdx,
4052 const APInt &Mask) -> std::pair<unsigned, int> {
4053 return GetSourceIndex(DstIdx, Mask.getZExtValue());
4054 });
4055}
4056
4058 InterpState &S, CodePtr OpPC, const CallExpr *Call,
4059 llvm::function_ref<APInt(const APInt &, uint64_t)> ShiftOp,
4060 llvm::function_ref<APInt(const APInt &, unsigned)> OverflowOp) {
4061
4062 assert(Call->getNumArgs() == 2);
4063
4064 const Pointer &Count = S.Stk.pop<Pointer>();
4065 const Pointer &Source = S.Stk.pop<Pointer>();
4066
4067 QualType SourceType = Call->getArg(0)->getType();
4068 QualType CountType = Call->getArg(1)->getType();
4069 assert(SourceType->isVectorType() && CountType->isVectorType());
4070
4071 const auto *SourceVecT = SourceType->castAs<VectorType>();
4072 const auto *CountVecT = CountType->castAs<VectorType>();
4073 PrimType SourceElemT = *S.getContext().classify(SourceVecT->getElementType());
4074 PrimType CountElemT = *S.getContext().classify(CountVecT->getElementType());
4075
4076 const Pointer &Dst = S.Stk.peek<Pointer>();
4077
4078 unsigned DestEltWidth =
4079 S.getASTContext().getTypeSize(SourceVecT->getElementType());
4080 bool IsDestUnsigned = SourceVecT->getElementType()->isUnsignedIntegerType();
4081 unsigned DestLen = SourceVecT->getNumElements();
4082 unsigned CountEltWidth =
4083 S.getASTContext().getTypeSize(CountVecT->getElementType());
4084 unsigned NumBitsInQWord = 64;
4085 unsigned NumCountElts = NumBitsInQWord / CountEltWidth;
4086
4087 uint64_t CountLQWord = 0;
4088 for (unsigned EltIdx = 0; EltIdx != NumCountElts; ++EltIdx) {
4089 uint64_t Elt = 0;
4090 INT_TYPE_SWITCH(CountElemT,
4091 { Elt = static_cast<uint64_t>(Count.elem<T>(EltIdx)); });
4092 CountLQWord |= (Elt << (EltIdx * CountEltWidth));
4093 }
4094
4095 for (unsigned EltIdx = 0; EltIdx != DestLen; ++EltIdx) {
4096 APSInt Elt;
4097 INT_TYPE_SWITCH(SourceElemT, { Elt = Source.elem<T>(EltIdx).toAPSInt(); });
4098
4099 APInt Result;
4100 if (CountLQWord < DestEltWidth) {
4101 Result = ShiftOp(Elt, CountLQWord);
4102 } else {
4103 Result = OverflowOp(Elt, DestEltWidth);
4104 }
4105 if (IsDestUnsigned) {
4106 INT_TYPE_SWITCH(SourceElemT, {
4107 Dst.elem<T>(EltIdx) = T::from(Result.getZExtValue());
4108 });
4109 } else {
4110 INT_TYPE_SWITCH(SourceElemT, {
4111 Dst.elem<T>(EltIdx) = T::from(Result.getSExtValue());
4112 });
4113 }
4114 }
4115
4117 return true;
4118}
4119
4121 const CallExpr *Call) {
4122
4123 assert(Call->getNumArgs() == 3);
4124
4125 QualType SourceType = Call->getArg(0)->getType();
4126 QualType ShuffleMaskType = Call->getArg(1)->getType();
4127 QualType ZeroMaskType = Call->getArg(2)->getType();
4128 if (!SourceType->isVectorType() || !ShuffleMaskType->isVectorType() ||
4129 !ZeroMaskType->isIntegerType()) {
4130 return false;
4131 }
4132
4133 Pointer Source, ShuffleMask;
4134 APSInt ZeroMask;
4135 if (!popToAPSInt(S, Call->getArg(2), ZeroMask))
4136 return false;
4137 ShuffleMask = S.Stk.pop<Pointer>();
4138 Source = S.Stk.pop<Pointer>();
4139
4140 const auto *SourceVecT = SourceType->castAs<VectorType>();
4141 const auto *ShuffleMaskVecT = ShuffleMaskType->castAs<VectorType>();
4142 assert(SourceVecT->getNumElements() == ShuffleMaskVecT->getNumElements());
4143 assert(ZeroMask.getBitWidth() == SourceVecT->getNumElements());
4144
4145 PrimType SourceElemT = *S.getContext().classify(SourceVecT->getElementType());
4146 PrimType ShuffleMaskElemT =
4147 *S.getContext().classify(ShuffleMaskVecT->getElementType());
4148
4149 unsigned NumBytesInQWord = 8;
4150 unsigned NumBitsInByte = 8;
4151 unsigned NumBytes = SourceVecT->getNumElements();
4152 unsigned NumQWords = NumBytes / NumBytesInQWord;
4153 unsigned RetWidth = ZeroMask.getBitWidth();
4154 APSInt RetMask(llvm::APInt(RetWidth, 0), /*isUnsigned=*/true);
4155
4156 for (unsigned QWordId = 0; QWordId != NumQWords; ++QWordId) {
4157 APInt SourceQWord(64, 0);
4158 for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {
4159 uint64_t Byte = 0;
4160 INT_TYPE_SWITCH(SourceElemT, {
4161 Byte = static_cast<uint64_t>(
4162 Source.elem<T>(QWordId * NumBytesInQWord + ByteIdx));
4163 });
4164 SourceQWord.insertBits(APInt(8, Byte & 0xFF), ByteIdx * NumBitsInByte);
4165 }
4166
4167 for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {
4168 unsigned SelIdx = QWordId * NumBytesInQWord + ByteIdx;
4169 unsigned M = 0;
4170 INT_TYPE_SWITCH(ShuffleMaskElemT, {
4171 M = static_cast<unsigned>(ShuffleMask.elem<T>(SelIdx)) & 0x3F;
4172 });
4173
4174 if (ZeroMask[SelIdx]) {
4175 RetMask.setBitVal(SelIdx, SourceQWord[M]);
4176 }
4177 }
4178 }
4179
4180 pushInteger(S, RetMask, Call->getType());
4181 return true;
4182}
4183
4185 const CallExpr *Call) {
4186 // Arguments are: vector of floats, rounding immediate
4187 assert(Call->getNumArgs() == 2);
4188
4189 APSInt Imm;
4190 if (!popToAPSInt(S, Call->getArg(1), Imm))
4191 return false;
4192 const Pointer &Src = S.Stk.pop<Pointer>();
4193 const Pointer &Dst = S.Stk.peek<Pointer>();
4194
4195 assert(Src.getFieldDesc()->isPrimitiveArray());
4196 assert(Dst.getFieldDesc()->isPrimitiveArray());
4197
4198 const auto *SrcVTy = Call->getArg(0)->getType()->castAs<VectorType>();
4199 unsigned SrcNumElems = SrcVTy->getNumElements();
4200 const auto *DstVTy = Call->getType()->castAs<VectorType>();
4201 unsigned DstNumElems = DstVTy->getNumElements();
4202
4203 const llvm::fltSemantics &HalfSem =
4205
4206 // imm[2] == 1 means use MXCSR rounding mode.
4207 // In that case, we can only evaluate if the conversion is exact.
4208 int ImmVal = Imm.getZExtValue();
4209 bool UseMXCSR = (ImmVal & 4) != 0;
4210 bool IsFPConstrained =
4211 Call->getFPFeaturesInEffect(S.getASTContext().getLangOpts())
4212 .isFPConstrained();
4213
4214 llvm::RoundingMode RM;
4215 if (!UseMXCSR) {
4216 switch (ImmVal & 3) {
4217 case 0:
4218 RM = llvm::RoundingMode::NearestTiesToEven;
4219 break;
4220 case 1:
4221 RM = llvm::RoundingMode::TowardNegative;
4222 break;
4223 case 2:
4224 RM = llvm::RoundingMode::TowardPositive;
4225 break;
4226 case 3:
4227 RM = llvm::RoundingMode::TowardZero;
4228 break;
4229 default:
4230 llvm_unreachable("Invalid immediate rounding mode");
4231 }
4232 } else {
4233 // For MXCSR, we must check for exactness. We can use any rounding mode
4234 // for the trial conversion since the result is the same if it's exact.
4235 RM = llvm::RoundingMode::NearestTiesToEven;
4236 }
4237
4238 QualType DstElemQT = Dst.getFieldDesc()->getElemQualType();
4239 PrimType DstElemT = *S.getContext().classify(DstElemQT);
4240
4241 for (unsigned I = 0; I != SrcNumElems; ++I) {
4242 Floating SrcVal = Src.elem<Floating>(I);
4243 APFloat DstVal = SrcVal.getAPFloat();
4244
4245 bool LostInfo;
4246 APFloat::opStatus St = DstVal.convert(HalfSem, RM, &LostInfo);
4247
4248 if (UseMXCSR && IsFPConstrained && St != APFloat::opOK) {
4249 S.FFDiag(S.Current->getSource(OpPC),
4250 diag::note_constexpr_dynamic_rounding);
4251 return false;
4252 }
4253
4254 INT_TYPE_SWITCH_NO_BOOL(DstElemT, {
4255 // Convert the destination value's bit pattern to an unsigned integer,
4256 // then reconstruct the element using the target type's 'from' method.
4257 uint64_t RawBits = DstVal.bitcastToAPInt().getZExtValue();
4258 Dst.elem<T>(I) = T::from(RawBits);
4259 });
4260 }
4261
4262 // Zero out remaining elements if the destination has more elements
4263 // (e.g., vcvtps2ph converting 4 floats to 8 shorts).
4264 if (DstNumElems > SrcNumElems) {
4265 for (unsigned I = SrcNumElems; I != DstNumElems; ++I) {
4266 INT_TYPE_SWITCH_NO_BOOL(DstElemT, { Dst.elem<T>(I) = T::from(0); });
4267 }
4268 }
4269
4270 Dst.initializeAllElements();
4271 return true;
4272}
4273
4275 const CallExpr *Call) {
4276 assert(Call->getNumArgs() == 2);
4277
4278 QualType ATy = Call->getArg(0)->getType();
4279 QualType BTy = Call->getArg(1)->getType();
4280 if (!ATy->isVectorType() || !BTy->isVectorType()) {
4281 return false;
4282 }
4283
4284 const Pointer &BPtr = S.Stk.pop<Pointer>();
4285 const Pointer &APtr = S.Stk.pop<Pointer>();
4286 const auto *AVecT = ATy->castAs<VectorType>();
4287 assert(AVecT->getNumElements() ==
4288 BTy->castAs<VectorType>()->getNumElements());
4289
4290 PrimType ElemT = *S.getContext().classify(AVecT->getElementType());
4291
4292 unsigned NumBytesInQWord = 8;
4293 unsigned NumBitsInByte = 8;
4294 unsigned NumBytes = AVecT->getNumElements();
4295 unsigned NumQWords = NumBytes / NumBytesInQWord;
4296 const Pointer &Dst = S.Stk.peek<Pointer>();
4297
4298 for (unsigned QWordId = 0; QWordId != NumQWords; ++QWordId) {
4299 APInt BQWord(64, 0);
4300 for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {
4301 unsigned Idx = QWordId * NumBytesInQWord + ByteIdx;
4302 INT_TYPE_SWITCH(ElemT, {
4303 uint64_t Byte = static_cast<uint64_t>(BPtr.elem<T>(Idx));
4304 BQWord.insertBits(APInt(8, Byte & 0xFF), ByteIdx * NumBitsInByte);
4305 });
4306 }
4307
4308 for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {
4309 unsigned Idx = QWordId * NumBytesInQWord + ByteIdx;
4310 uint64_t Ctrl = 0;
4312 ElemT, { Ctrl = static_cast<uint64_t>(APtr.elem<T>(Idx)) & 0x3F; });
4313
4314 APInt Byte(8, 0);
4315 for (unsigned BitIdx = 0; BitIdx != NumBitsInByte; ++BitIdx) {
4316 Byte.setBitVal(BitIdx, BQWord[(Ctrl + BitIdx) & 0x3F]);
4317 }
4318 INT_TYPE_SWITCH(ElemT,
4319 { Dst.elem<T>(Idx) = T::from(Byte.getZExtValue()); });
4320 }
4321 }
4322
4324
4325 return true;
4326}
4327
4329 const CallExpr *Call,
4330 bool Inverse) {
4331 assert(Call->getNumArgs() == 3);
4332 QualType XType = Call->getArg(0)->getType();
4333 QualType AType = Call->getArg(1)->getType();
4334 QualType ImmType = Call->getArg(2)->getType();
4335 if (!XType->isVectorType() || !AType->isVectorType() ||
4336 !ImmType->isIntegerType()) {
4337 return false;
4338 }
4339
4340 Pointer X, A;
4341 APSInt Imm;
4342 if (!popToAPSInt(S, Call->getArg(2), Imm))
4343 return false;
4344 A = S.Stk.pop<Pointer>();
4345 X = S.Stk.pop<Pointer>();
4346
4347 const Pointer &Dst = S.Stk.peek<Pointer>();
4348 const auto *AVecT = AType->castAs<VectorType>();
4349 assert(XType->castAs<VectorType>()->getNumElements() ==
4350 AVecT->getNumElements());
4351 unsigned NumBytesInQWord = 8;
4352 unsigned NumBytes = AVecT->getNumElements();
4353 unsigned NumBitsInQWord = 64;
4354 unsigned NumQWords = NumBytes / NumBytesInQWord;
4355 unsigned NumBitsInByte = 8;
4356 PrimType AElemT = *S.getContext().classify(AVecT->getElementType());
4357
4358 // computing A*X + Imm
4359 for (unsigned QWordIdx = 0; QWordIdx != NumQWords; ++QWordIdx) {
4360 // Extract the QWords from X, A
4361 APInt XQWord(NumBitsInQWord, 0);
4362 APInt AQWord(NumBitsInQWord, 0);
4363 for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {
4364 unsigned Idx = QWordIdx * NumBytesInQWord + ByteIdx;
4365 uint8_t XByte;
4366 uint8_t AByte;
4367 INT_TYPE_SWITCH(AElemT, {
4368 XByte = static_cast<uint8_t>(X.elem<T>(Idx));
4369 AByte = static_cast<uint8_t>(A.elem<T>(Idx));
4370 });
4371
4372 XQWord.insertBits(APInt(NumBitsInByte, XByte), ByteIdx * NumBitsInByte);
4373 AQWord.insertBits(APInt(NumBitsInByte, AByte), ByteIdx * NumBitsInByte);
4374 }
4375
4376 for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {
4377 unsigned Idx = QWordIdx * NumBytesInQWord + ByteIdx;
4378 uint8_t XByte =
4379 XQWord.lshr(ByteIdx * NumBitsInByte).getLoBits(8).getZExtValue();
4380 INT_TYPE_SWITCH(AElemT, {
4381 Dst.elem<T>(Idx) = T::from(GFNIAffine(XByte, AQWord, Imm, Inverse));
4382 });
4383 }
4384 }
4385 Dst.initializeAllElements();
4386 return true;
4387}
4388
4390 const CallExpr *Call) {
4391 assert(Call->getNumArgs() == 2);
4392
4393 QualType AType = Call->getArg(0)->getType();
4394 QualType BType = Call->getArg(1)->getType();
4395 if (!AType->isVectorType() || !BType->isVectorType()) {
4396 return false;
4397 }
4398
4399 Pointer A, B;
4400 B = S.Stk.pop<Pointer>();
4401 A = S.Stk.pop<Pointer>();
4402
4403 const Pointer &Dst = S.Stk.peek<Pointer>();
4404 const auto *AVecT = AType->castAs<VectorType>();
4405 assert(AVecT->getNumElements() ==
4406 BType->castAs<VectorType>()->getNumElements());
4407
4408 PrimType AElemT = *S.getContext().classify(AVecT->getElementType());
4409 unsigned NumBytes = A.getNumElems();
4410
4411 for (unsigned ByteIdx = 0; ByteIdx != NumBytes; ++ByteIdx) {
4412 uint8_t AByte, BByte;
4413 INT_TYPE_SWITCH(AElemT, {
4414 AByte = static_cast<uint8_t>(A.elem<T>(ByteIdx));
4415 BByte = static_cast<uint8_t>(B.elem<T>(ByteIdx));
4416 Dst.elem<T>(ByteIdx) = T::from(GFNIMul(AByte, BByte));
4417 });
4418 }
4419
4420 Dst.initializeAllElements();
4421 return true;
4422}
4423
4425 uint32_t BuiltinID) {
4426 if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID))
4427 return Invalid(S, OpPC);
4428
4429 const InterpFrame *Frame = S.Current;
4430 switch (BuiltinID) {
4431 case Builtin::BI__builtin_is_constant_evaluated:
4433
4434 case Builtin::BI__builtin_assume:
4435 case Builtin::BI__assume:
4436 return interp__builtin_assume(S, OpPC, Frame, Call);
4437
4438 case Builtin::BI__builtin_strcmp:
4439 case Builtin::BIstrcmp:
4440 case Builtin::BI__builtin_strncmp:
4441 case Builtin::BIstrncmp:
4442 case Builtin::BI__builtin_wcsncmp:
4443 case Builtin::BIwcsncmp:
4444 case Builtin::BI__builtin_wcscmp:
4445 case Builtin::BIwcscmp:
4446 return interp__builtin_strcmp(S, OpPC, Frame, Call, BuiltinID);
4447
4448 case Builtin::BI__builtin_strlen:
4449 case Builtin::BIstrlen:
4450 case Builtin::BI__builtin_wcslen:
4451 case Builtin::BIwcslen:
4452 return interp__builtin_strlen(S, OpPC, Frame, Call, BuiltinID);
4453
4454 case Builtin::BI__builtin_nan:
4455 case Builtin::BI__builtin_nanf:
4456 case Builtin::BI__builtin_nanl:
4457 case Builtin::BI__builtin_nanf16:
4458 case Builtin::BI__builtin_nanf128:
4459 return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/false);
4460
4461 case Builtin::BI__builtin_nans:
4462 case Builtin::BI__builtin_nansf:
4463 case Builtin::BI__builtin_nansl:
4464 case Builtin::BI__builtin_nansf16:
4465 case Builtin::BI__builtin_nansf128:
4466 return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/true);
4467
4468 case Builtin::BI__builtin_huge_val:
4469 case Builtin::BI__builtin_huge_valf:
4470 case Builtin::BI__builtin_huge_vall:
4471 case Builtin::BI__builtin_huge_valf16:
4472 case Builtin::BI__builtin_huge_valf128:
4473 case Builtin::BI__builtin_inf:
4474 case Builtin::BI__builtin_inff:
4475 case Builtin::BI__builtin_infl:
4476 case Builtin::BI__builtin_inff16:
4477 case Builtin::BI__builtin_inff128:
4478 return interp__builtin_inf(S, OpPC, Frame, Call);
4479
4480 case Builtin::BI__builtin_copysign:
4481 case Builtin::BI__builtin_copysignf:
4482 case Builtin::BI__builtin_copysignl:
4483 case Builtin::BI__builtin_copysignf128:
4484 return interp__builtin_copysign(S, OpPC, Frame);
4485
4486 case Builtin::BI__builtin_fmin:
4487 case Builtin::BI__builtin_fminf:
4488 case Builtin::BI__builtin_fminl:
4489 case Builtin::BI__builtin_fminf16:
4490 case Builtin::BI__builtin_fminf128:
4491 return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/false);
4492
4493 case Builtin::BI__builtin_fminimum_num:
4494 case Builtin::BI__builtin_fminimum_numf:
4495 case Builtin::BI__builtin_fminimum_numl:
4496 case Builtin::BI__builtin_fminimum_numf16:
4497 case Builtin::BI__builtin_fminimum_numf128:
4498 return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/true);
4499
4500 case Builtin::BI__builtin_fmax:
4501 case Builtin::BI__builtin_fmaxf:
4502 case Builtin::BI__builtin_fmaxl:
4503 case Builtin::BI__builtin_fmaxf16:
4504 case Builtin::BI__builtin_fmaxf128:
4505 return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/false);
4506
4507 case Builtin::BI__builtin_fmaximum_num:
4508 case Builtin::BI__builtin_fmaximum_numf:
4509 case Builtin::BI__builtin_fmaximum_numl:
4510 case Builtin::BI__builtin_fmaximum_numf16:
4511 case Builtin::BI__builtin_fmaximum_numf128:
4512 return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/true);
4513
4514 case Builtin::BI__builtin_isnan:
4515 return interp__builtin_isnan(S, OpPC, Frame, Call);
4516
4517 case Builtin::BI__builtin_issignaling:
4518 return interp__builtin_issignaling(S, OpPC, Frame, Call);
4519
4520 case Builtin::BI__builtin_isinf:
4521 return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/false, Call);
4522
4523 case Builtin::BI__builtin_isinf_sign:
4524 return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/true, Call);
4525
4526 case Builtin::BI__builtin_isfinite:
4527 return interp__builtin_isfinite(S, OpPC, Frame, Call);
4528
4529 case Builtin::BI__builtin_isnormal:
4530 return interp__builtin_isnormal(S, OpPC, Frame, Call);
4531
4532 case Builtin::BI__builtin_issubnormal:
4533 return interp__builtin_issubnormal(S, OpPC, Frame, Call);
4534
4535 case Builtin::BI__builtin_iszero:
4536 return interp__builtin_iszero(S, OpPC, Frame, Call);
4537
4538 case Builtin::BI__builtin_signbit:
4539 case Builtin::BI__builtin_signbitf:
4540 case Builtin::BI__builtin_signbitl:
4541 return interp__builtin_signbit(S, OpPC, Frame, Call);
4542
4543 case Builtin::BI__builtin_isgreater:
4544 case Builtin::BI__builtin_isgreaterequal:
4545 case Builtin::BI__builtin_isless:
4546 case Builtin::BI__builtin_islessequal:
4547 case Builtin::BI__builtin_islessgreater:
4548 case Builtin::BI__builtin_isunordered:
4549 return interp_floating_comparison(S, OpPC, Call, BuiltinID);
4550
4551 case Builtin::BI__builtin_isfpclass:
4552 return interp__builtin_isfpclass(S, OpPC, Frame, Call);
4553
4554 case Builtin::BI__builtin_fpclassify:
4555 return interp__builtin_fpclassify(S, OpPC, Frame, Call);
4556
4557 case Builtin::BI__builtin_fabs:
4558 case Builtin::BI__builtin_fabsf:
4559 case Builtin::BI__builtin_fabsl:
4560 case Builtin::BI__builtin_fabsf128:
4561 return interp__builtin_fabs(S, OpPC, Frame);
4562
4563 case Builtin::BI__builtin_abs:
4564 case Builtin::BI__builtin_labs:
4565 case Builtin::BI__builtin_llabs:
4566 return interp__builtin_abs(S, OpPC, Frame, Call);
4567
4568 case Builtin::BI__builtin_popcount:
4569 case Builtin::BI__builtin_popcountl:
4570 case Builtin::BI__builtin_popcountll:
4571 case Builtin::BI__builtin_popcountg:
4572 case Builtin::BI__popcnt16: // Microsoft variants of popcount
4573 case Builtin::BI__popcnt:
4574 case Builtin::BI__popcnt64:
4575 return interp__builtin_popcount(S, OpPC, Frame, Call);
4576
4577 case Builtin::BI__builtin_parity:
4578 case Builtin::BI__builtin_parityl:
4579 case Builtin::BI__builtin_parityll:
4581 S, OpPC, Call, [](const APSInt &Val) {
4582 return APInt(Val.getBitWidth(), Val.popcount() % 2);
4583 });
4584 case Builtin::BI__builtin_clrsb:
4585 case Builtin::BI__builtin_clrsbl:
4586 case Builtin::BI__builtin_clrsbll:
4588 S, OpPC, Call, [](const APSInt &Val) {
4589 return APInt(Val.getBitWidth(),
4590 Val.getBitWidth() - Val.getSignificantBits());
4591 });
4592 case Builtin::BI__builtin_bitreverseg:
4593 case Builtin::BI__builtin_bitreverse8:
4594 case Builtin::BI__builtin_bitreverse16:
4595 case Builtin::BI__builtin_bitreverse32:
4596 case Builtin::BI__builtin_bitreverse64:
4598 S, OpPC, Call, [](const APSInt &Val) { return Val.reverseBits(); });
4599
4600 case Builtin::BI__builtin_classify_type:
4601 return interp__builtin_classify_type(S, OpPC, Frame, Call);
4602
4603 case Builtin::BI__builtin_expect:
4604 case Builtin::BI__builtin_expect_with_probability:
4605 return interp__builtin_expect(S, OpPC, Frame, Call);
4606
4607 case Builtin::BI__builtin_rotateleft8:
4608 case Builtin::BI__builtin_rotateleft16:
4609 case Builtin::BI__builtin_rotateleft32:
4610 case Builtin::BI__builtin_rotateleft64:
4611 case Builtin::BI__builtin_stdc_rotate_left:
4612 case Builtin::BI_rotl8: // Microsoft variants of rotate left
4613 case Builtin::BI_rotl16:
4614 case Builtin::BI_rotl:
4615 case Builtin::BI_lrotl:
4616 case Builtin::BI_rotl64:
4617 case Builtin::BI__builtin_rotateright8:
4618 case Builtin::BI__builtin_rotateright16:
4619 case Builtin::BI__builtin_rotateright32:
4620 case Builtin::BI__builtin_rotateright64:
4621 case Builtin::BI__builtin_stdc_rotate_right:
4622 case Builtin::BI_rotr8: // Microsoft variants of rotate right
4623 case Builtin::BI_rotr16:
4624 case Builtin::BI_rotr:
4625 case Builtin::BI_lrotr:
4626 case Builtin::BI_rotr64: {
4627 // Determine if this is a rotate right operation
4628 bool IsRotateRight;
4629 switch (BuiltinID) {
4630 case Builtin::BI__builtin_rotateright8:
4631 case Builtin::BI__builtin_rotateright16:
4632 case Builtin::BI__builtin_rotateright32:
4633 case Builtin::BI__builtin_rotateright64:
4634 case Builtin::BI__builtin_stdc_rotate_right:
4635 case Builtin::BI_rotr8:
4636 case Builtin::BI_rotr16:
4637 case Builtin::BI_rotr:
4638 case Builtin::BI_lrotr:
4639 case Builtin::BI_rotr64:
4640 IsRotateRight = true;
4641 break;
4642 default:
4643 IsRotateRight = false;
4644 break;
4645 }
4646
4648 S, OpPC, Call, [IsRotateRight](const APSInt &Value, APSInt Amount) {
4649 Amount = NormalizeRotateAmount(Value, Amount);
4650 return IsRotateRight ? Value.rotr(Amount.getZExtValue())
4651 : Value.rotl(Amount.getZExtValue());
4652 });
4653 }
4654
4655 case Builtin::BIstdc_leading_zeros_uc:
4656 case Builtin::BIstdc_leading_zeros_us:
4657 case Builtin::BIstdc_leading_zeros_ui:
4658 case Builtin::BIstdc_leading_zeros_ul:
4659 case Builtin::BIstdc_leading_zeros_ull:
4660 case Builtin::BIstdc_leading_zeros:
4661 case Builtin::BI__builtin_stdc_leading_zeros: {
4662 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4664 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4665 return APInt(ResWidth, Val.countl_zero());
4666 });
4667 }
4668
4669 case Builtin::BIstdc_leading_ones_uc:
4670 case Builtin::BIstdc_leading_ones_us:
4671 case Builtin::BIstdc_leading_ones_ui:
4672 case Builtin::BIstdc_leading_ones_ul:
4673 case Builtin::BIstdc_leading_ones_ull:
4674 case Builtin::BIstdc_leading_ones:
4675 case Builtin::BI__builtin_stdc_leading_ones: {
4676 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4678 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4679 return APInt(ResWidth, Val.countl_one());
4680 });
4681 }
4682
4683 case Builtin::BIstdc_trailing_zeros_uc:
4684 case Builtin::BIstdc_trailing_zeros_us:
4685 case Builtin::BIstdc_trailing_zeros_ui:
4686 case Builtin::BIstdc_trailing_zeros_ul:
4687 case Builtin::BIstdc_trailing_zeros_ull:
4688 case Builtin::BIstdc_trailing_zeros:
4689 case Builtin::BI__builtin_stdc_trailing_zeros: {
4690 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4692 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4693 return APInt(ResWidth, Val.countr_zero());
4694 });
4695 }
4696
4697 case Builtin::BIstdc_trailing_ones_uc:
4698 case Builtin::BIstdc_trailing_ones_us:
4699 case Builtin::BIstdc_trailing_ones_ui:
4700 case Builtin::BIstdc_trailing_ones_ul:
4701 case Builtin::BIstdc_trailing_ones_ull:
4702 case Builtin::BIstdc_trailing_ones:
4703 case Builtin::BI__builtin_stdc_trailing_ones: {
4704 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4706 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4707 return APInt(ResWidth, Val.countr_one());
4708 });
4709 }
4710
4711 case Builtin::BIstdc_first_leading_zero_uc:
4712 case Builtin::BIstdc_first_leading_zero_us:
4713 case Builtin::BIstdc_first_leading_zero_ui:
4714 case Builtin::BIstdc_first_leading_zero_ul:
4715 case Builtin::BIstdc_first_leading_zero_ull:
4716 case Builtin::BIstdc_first_leading_zero:
4717 case Builtin::BI__builtin_stdc_first_leading_zero: {
4718 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4720 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4721 return APInt(ResWidth, Val.isAllOnes() ? 0 : Val.countl_one() + 1);
4722 });
4723 }
4724
4725 case Builtin::BIstdc_first_leading_one_uc:
4726 case Builtin::BIstdc_first_leading_one_us:
4727 case Builtin::BIstdc_first_leading_one_ui:
4728 case Builtin::BIstdc_first_leading_one_ul:
4729 case Builtin::BIstdc_first_leading_one_ull:
4730 case Builtin::BIstdc_first_leading_one:
4731 case Builtin::BI__builtin_stdc_first_leading_one: {
4732 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4734 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4735 return APInt(ResWidth, Val.isZero() ? 0 : Val.countl_zero() + 1);
4736 });
4737 }
4738
4739 case Builtin::BIstdc_first_trailing_zero_uc:
4740 case Builtin::BIstdc_first_trailing_zero_us:
4741 case Builtin::BIstdc_first_trailing_zero_ui:
4742 case Builtin::BIstdc_first_trailing_zero_ul:
4743 case Builtin::BIstdc_first_trailing_zero_ull:
4744 case Builtin::BIstdc_first_trailing_zero:
4745 case Builtin::BI__builtin_stdc_first_trailing_zero: {
4746 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4748 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4749 return APInt(ResWidth, Val.isAllOnes() ? 0 : Val.countr_one() + 1);
4750 });
4751 }
4752
4753 case Builtin::BIstdc_first_trailing_one_uc:
4754 case Builtin::BIstdc_first_trailing_one_us:
4755 case Builtin::BIstdc_first_trailing_one_ui:
4756 case Builtin::BIstdc_first_trailing_one_ul:
4757 case Builtin::BIstdc_first_trailing_one_ull:
4758 case Builtin::BIstdc_first_trailing_one:
4759 case Builtin::BI__builtin_stdc_first_trailing_one: {
4760 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4762 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4763 return APInt(ResWidth, Val.isZero() ? 0 : Val.countr_zero() + 1);
4764 });
4765 }
4766
4767 case Builtin::BIstdc_count_zeros_uc:
4768 case Builtin::BIstdc_count_zeros_us:
4769 case Builtin::BIstdc_count_zeros_ui:
4770 case Builtin::BIstdc_count_zeros_ul:
4771 case Builtin::BIstdc_count_zeros_ull:
4772 case Builtin::BIstdc_count_zeros:
4773 case Builtin::BI__builtin_stdc_count_zeros: {
4774 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4776 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4777 unsigned BitWidth = Val.getBitWidth();
4778 return APInt(ResWidth, BitWidth - Val.popcount());
4779 });
4780 }
4781
4782 case Builtin::BIstdc_count_ones_uc:
4783 case Builtin::BIstdc_count_ones_us:
4784 case Builtin::BIstdc_count_ones_ui:
4785 case Builtin::BIstdc_count_ones_ul:
4786 case Builtin::BIstdc_count_ones_ull:
4787 case Builtin::BIstdc_count_ones:
4788 case Builtin::BI__builtin_stdc_count_ones: {
4789 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4791 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4792 return APInt(ResWidth, Val.popcount());
4793 });
4794 }
4795
4796 case Builtin::BIstdc_has_single_bit_uc:
4797 case Builtin::BIstdc_has_single_bit_us:
4798 case Builtin::BIstdc_has_single_bit_ui:
4799 case Builtin::BIstdc_has_single_bit_ul:
4800 case Builtin::BIstdc_has_single_bit_ull:
4801 case Builtin::BIstdc_has_single_bit:
4802 case Builtin::BI__builtin_stdc_has_single_bit: {
4803 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4805 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4806 return APInt(ResWidth, Val.popcount() == 1 ? 1 : 0);
4807 });
4808 }
4809
4810 case Builtin::BIstdc_bit_width_uc:
4811 case Builtin::BIstdc_bit_width_us:
4812 case Builtin::BIstdc_bit_width_ui:
4813 case Builtin::BIstdc_bit_width_ul:
4814 case Builtin::BIstdc_bit_width_ull:
4815 case Builtin::BIstdc_bit_width:
4816 case Builtin::BI__builtin_stdc_bit_width: {
4817 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4819 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4820 unsigned BitWidth = Val.getBitWidth();
4821 return APInt(ResWidth, BitWidth - Val.countl_zero());
4822 });
4823 }
4824
4825 case Builtin::BIstdc_bit_floor_uc:
4826 case Builtin::BIstdc_bit_floor_us:
4827 case Builtin::BIstdc_bit_floor_ui:
4828 case Builtin::BIstdc_bit_floor_ul:
4829 case Builtin::BIstdc_bit_floor_ull:
4830 case Builtin::BIstdc_bit_floor:
4831 case Builtin::BI__builtin_stdc_bit_floor:
4833 S, OpPC, Call, [](const APSInt &Val) {
4834 unsigned BitWidth = Val.getBitWidth();
4835 if (Val.isZero())
4836 return APInt::getZero(BitWidth);
4837 return APInt::getOneBitSet(BitWidth,
4838 BitWidth - Val.countl_zero() - 1);
4839 });
4840
4841 case Builtin::BIstdc_bit_ceil_uc:
4842 case Builtin::BIstdc_bit_ceil_us:
4843 case Builtin::BIstdc_bit_ceil_ui:
4844 case Builtin::BIstdc_bit_ceil_ul:
4845 case Builtin::BIstdc_bit_ceil_ull:
4846 case Builtin::BIstdc_bit_ceil:
4847 case Builtin::BI__builtin_stdc_bit_ceil:
4849 S, OpPC, Call, [](const APSInt &Val) {
4850 unsigned BitWidth = Val.getBitWidth();
4851 if (Val.ule(1))
4852 return APInt(BitWidth, 1);
4853 APInt V = Val;
4854 APInt ValMinusOne = V - 1;
4855 unsigned LeadingZeros = ValMinusOne.countl_zero();
4856 if (LeadingZeros == 0)
4857 return APInt(BitWidth, 0); // overflows; wrap to 0
4858 return APInt::getOneBitSet(BitWidth, BitWidth - LeadingZeros);
4859 });
4860
4861 case Builtin::BI__builtin_ffs:
4862 case Builtin::BI__builtin_ffsl:
4863 case Builtin::BI__builtin_ffsll:
4865 S, OpPC, Call, [](const APSInt &Val) {
4866 return APInt(Val.getBitWidth(),
4867 Val.isZero() ? 0u : Val.countTrailingZeros() + 1u);
4868 });
4869
4870 case Builtin::BIaddressof:
4871 case Builtin::BI__addressof:
4872 case Builtin::BI__builtin_addressof:
4873 assert(isNoopBuiltin(BuiltinID));
4874 return interp__builtin_addressof(S, OpPC, Frame, Call);
4875
4876 case Builtin::BIas_const:
4877 case Builtin::BIforward:
4878 case Builtin::BIforward_like:
4879 case Builtin::BImove:
4880 case Builtin::BImove_if_noexcept:
4881 assert(isNoopBuiltin(BuiltinID));
4882 return interp__builtin_move(S, OpPC, Frame, Call);
4883
4884 case Builtin::BI__builtin_eh_return_data_regno:
4886
4887 case Builtin::BI__builtin_launder:
4888 assert(isNoopBuiltin(BuiltinID));
4889 return true;
4890
4891 case Builtin::BI__builtin_add_overflow:
4892 case Builtin::BI__builtin_sub_overflow:
4893 case Builtin::BI__builtin_mul_overflow:
4894 case Builtin::BI__builtin_sadd_overflow:
4895 case Builtin::BI__builtin_uadd_overflow:
4896 case Builtin::BI__builtin_uaddl_overflow:
4897 case Builtin::BI__builtin_uaddll_overflow:
4898 case Builtin::BI__builtin_usub_overflow:
4899 case Builtin::BI__builtin_usubl_overflow:
4900 case Builtin::BI__builtin_usubll_overflow:
4901 case Builtin::BI__builtin_umul_overflow:
4902 case Builtin::BI__builtin_umull_overflow:
4903 case Builtin::BI__builtin_umulll_overflow:
4904 case Builtin::BI__builtin_saddl_overflow:
4905 case Builtin::BI__builtin_saddll_overflow:
4906 case Builtin::BI__builtin_ssub_overflow:
4907 case Builtin::BI__builtin_ssubl_overflow:
4908 case Builtin::BI__builtin_ssubll_overflow:
4909 case Builtin::BI__builtin_smul_overflow:
4910 case Builtin::BI__builtin_smull_overflow:
4911 case Builtin::BI__builtin_smulll_overflow:
4912 return interp__builtin_overflowop(S, OpPC, Call, BuiltinID);
4913
4914 case Builtin::BI__builtin_addcb:
4915 case Builtin::BI__builtin_addcs:
4916 case Builtin::BI__builtin_addc:
4917 case Builtin::BI__builtin_addcl:
4918 case Builtin::BI__builtin_addcll:
4919 case Builtin::BI__builtin_subcb:
4920 case Builtin::BI__builtin_subcs:
4921 case Builtin::BI__builtin_subc:
4922 case Builtin::BI__builtin_subcl:
4923 case Builtin::BI__builtin_subcll:
4924 return interp__builtin_carryop(S, OpPC, Frame, Call, BuiltinID);
4925
4926 case Builtin::BI__builtin_clz:
4927 case Builtin::BI__builtin_clzl:
4928 case Builtin::BI__builtin_clzll:
4929 case Builtin::BI__builtin_clzs:
4930 case Builtin::BI__builtin_clzg:
4931 case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
4932 case Builtin::BI__lzcnt:
4933 case Builtin::BI__lzcnt64:
4934 return interp__builtin_clz(S, OpPC, Frame, Call, BuiltinID);
4935
4936 case Builtin::BI__builtin_ctz:
4937 case Builtin::BI__builtin_ctzl:
4938 case Builtin::BI__builtin_ctzll:
4939 case Builtin::BI__builtin_ctzs:
4940 case Builtin::BI__builtin_ctzg:
4941 return interp__builtin_ctz(S, OpPC, Frame, Call, BuiltinID);
4942
4943 case Builtin::BI__builtin_elementwise_clzg:
4944 case Builtin::BI__builtin_elementwise_ctzg:
4946 BuiltinID);
4947 case Builtin::BI__builtin_bswapg:
4948 case Builtin::BI__builtin_bswap16:
4949 case Builtin::BI__builtin_bswap32:
4950 case Builtin::BI__builtin_bswap64:
4951 return interp__builtin_bswap(S, OpPC, Frame, Call);
4952
4953 case Builtin::BI__atomic_always_lock_free:
4954 case Builtin::BI__atomic_is_lock_free:
4955 return interp__builtin_atomic_lock_free(S, OpPC, Frame, Call, BuiltinID);
4956
4957 case Builtin::BI__c11_atomic_is_lock_free:
4959
4960 case Builtin::BI__builtin_complex:
4961 return interp__builtin_complex(S, OpPC, Frame, Call);
4962
4963 case Builtin::BI__builtin_is_aligned:
4964 case Builtin::BI__builtin_align_up:
4965 case Builtin::BI__builtin_align_down:
4966 return interp__builtin_is_aligned_up_down(S, OpPC, Frame, Call, BuiltinID);
4967
4968 case Builtin::BI__builtin_assume_aligned:
4969 return interp__builtin_assume_aligned(S, OpPC, Frame, Call);
4970
4971 case clang::X86::BI__builtin_ia32_crc32qi:
4972 return interp__builtin_ia32_crc32(S, OpPC, Frame, Call, 1);
4973 case clang::X86::BI__builtin_ia32_crc32hi:
4974 return interp__builtin_ia32_crc32(S, OpPC, Frame, Call, 2);
4975 case clang::X86::BI__builtin_ia32_crc32si:
4976 return interp__builtin_ia32_crc32(S, OpPC, Frame, Call, 4);
4977 case clang::X86::BI__builtin_ia32_crc32di:
4978 return interp__builtin_ia32_crc32(S, OpPC, Frame, Call, 8);
4979
4980 case clang::X86::BI__builtin_ia32_bextr_u32:
4981 case clang::X86::BI__builtin_ia32_bextr_u64:
4982 case clang::X86::BI__builtin_ia32_bextri_u32:
4983 case clang::X86::BI__builtin_ia32_bextri_u64:
4985 S, OpPC, Call, [](const APSInt &Val, const APSInt &Idx) {
4986 unsigned BitWidth = Val.getBitWidth();
4987 uint64_t Shift = Idx.extractBitsAsZExtValue(8, 0);
4988 uint64_t Length = Idx.extractBitsAsZExtValue(8, 8);
4989 if (Length > BitWidth) {
4990 Length = BitWidth;
4991 }
4992
4993 // Handle out of bounds cases.
4994 if (Length == 0 || Shift >= BitWidth)
4995 return APInt(BitWidth, 0);
4996
4997 uint64_t Result = Val.getZExtValue() >> Shift;
4998 Result &= llvm::maskTrailingOnes<uint64_t>(Length);
4999 return APInt(BitWidth, Result);
5000 });
5001
5002 case clang::X86::BI__builtin_ia32_bzhi_si:
5003 case clang::X86::BI__builtin_ia32_bzhi_di:
5005 S, OpPC, Call, [](const APSInt &Val, const APSInt &Idx) {
5006 unsigned BitWidth = Val.getBitWidth();
5007 uint64_t Index = Idx.extractBitsAsZExtValue(8, 0);
5008 APSInt Result = Val;
5009
5010 if (Index < BitWidth)
5011 Result.clearHighBits(BitWidth - Index);
5012
5013 return Result;
5014 });
5015
5016 case clang::X86::BI__builtin_ia32_ktestcqi:
5017 case clang::X86::BI__builtin_ia32_ktestchi:
5018 case clang::X86::BI__builtin_ia32_ktestcsi:
5019 case clang::X86::BI__builtin_ia32_ktestcdi:
5021 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
5022 return APInt(sizeof(unsigned char) * 8, (~A & B) == 0);
5023 });
5024
5025 case clang::X86::BI__builtin_ia32_ktestzqi:
5026 case clang::X86::BI__builtin_ia32_ktestzhi:
5027 case clang::X86::BI__builtin_ia32_ktestzsi:
5028 case clang::X86::BI__builtin_ia32_ktestzdi:
5030 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
5031 return APInt(sizeof(unsigned char) * 8, (A & B) == 0);
5032 });
5033
5034 case clang::X86::BI__builtin_ia32_kortestcqi:
5035 case clang::X86::BI__builtin_ia32_kortestchi:
5036 case clang::X86::BI__builtin_ia32_kortestcsi:
5037 case clang::X86::BI__builtin_ia32_kortestcdi:
5039 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
5040 return APInt(sizeof(unsigned char) * 8, ~(A | B) == 0);
5041 });
5042
5043 case clang::X86::BI__builtin_ia32_kortestzqi:
5044 case clang::X86::BI__builtin_ia32_kortestzhi:
5045 case clang::X86::BI__builtin_ia32_kortestzsi:
5046 case clang::X86::BI__builtin_ia32_kortestzdi:
5048 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
5049 return APInt(sizeof(unsigned char) * 8, (A | B) == 0);
5050 });
5051
5052 case clang::X86::BI__builtin_ia32_kshiftliqi:
5053 case clang::X86::BI__builtin_ia32_kshiftlihi:
5054 case clang::X86::BI__builtin_ia32_kshiftlisi:
5055 case clang::X86::BI__builtin_ia32_kshiftlidi:
5057 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5058 unsigned Amt = RHS.getZExtValue() & 0xFF;
5059 if (Amt >= LHS.getBitWidth())
5060 return APInt::getZero(LHS.getBitWidth());
5061 return LHS.shl(Amt);
5062 });
5063
5064 case clang::X86::BI__builtin_ia32_kshiftriqi:
5065 case clang::X86::BI__builtin_ia32_kshiftrihi:
5066 case clang::X86::BI__builtin_ia32_kshiftrisi:
5067 case clang::X86::BI__builtin_ia32_kshiftridi:
5069 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5070 unsigned Amt = RHS.getZExtValue() & 0xFF;
5071 if (Amt >= LHS.getBitWidth())
5072 return APInt::getZero(LHS.getBitWidth());
5073 return LHS.lshr(Amt);
5074 });
5075
5076 case clang::X86::BI__builtin_ia32_lzcnt_u16:
5077 case clang::X86::BI__builtin_ia32_lzcnt_u32:
5078 case clang::X86::BI__builtin_ia32_lzcnt_u64:
5080 S, OpPC, Call, [](const APSInt &Src) {
5081 return APInt(Src.getBitWidth(), Src.countLeadingZeros());
5082 });
5083
5084 case clang::X86::BI__builtin_ia32_tzcnt_u16:
5085 case clang::X86::BI__builtin_ia32_tzcnt_u32:
5086 case clang::X86::BI__builtin_ia32_tzcnt_u64:
5088 S, OpPC, Call, [](const APSInt &Src) {
5089 return APInt(Src.getBitWidth(), Src.countTrailingZeros());
5090 });
5091
5092 case clang::X86::BI__builtin_ia32_pdep_si:
5093 case clang::X86::BI__builtin_ia32_pdep_di:
5095 S, OpPC, Call, [](const APSInt &Val, const APSInt &Mask) {
5096 unsigned BitWidth = Val.getBitWidth();
5097 APInt Result = APInt::getZero(BitWidth);
5098
5099 for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
5100 if (Mask[I])
5101 Result.setBitVal(I, Val[P++]);
5102 }
5103
5104 return Result;
5105 });
5106
5107 case clang::X86::BI__builtin_ia32_pext_si:
5108 case clang::X86::BI__builtin_ia32_pext_di:
5110 S, OpPC, Call, [](const APSInt &Val, const APSInt &Mask) {
5111 unsigned BitWidth = Val.getBitWidth();
5112 APInt Result = APInt::getZero(BitWidth);
5113
5114 for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
5115 if (Mask[I])
5116 Result.setBitVal(P++, Val[I]);
5117 }
5118
5119 return Result;
5120 });
5121
5122 case clang::X86::BI__builtin_ia32_addcarryx_u32:
5123 case clang::X86::BI__builtin_ia32_addcarryx_u64:
5124 case clang::X86::BI__builtin_ia32_subborrow_u32:
5125 case clang::X86::BI__builtin_ia32_subborrow_u64:
5127 BuiltinID);
5128
5129 case Builtin::BI__builtin_os_log_format_buffer_size:
5131
5132 case Builtin::BI__builtin_ptrauth_string_discriminator:
5134
5135 case Builtin::BI__builtin_infer_alloc_token:
5137
5138 case Builtin::BI__noop:
5139 pushInteger(S, 0, Call->getType());
5140 return true;
5141
5142 case Builtin::BI__builtin_operator_new:
5143 return interp__builtin_operator_new(S, OpPC, Frame, Call);
5144
5145 case Builtin::BI__builtin_operator_delete:
5146 return interp__builtin_operator_delete(S, OpPC, Frame, Call);
5147
5148 case Builtin::BI__arithmetic_fence:
5150
5151 case Builtin::BI__builtin_reduce_add:
5152 case Builtin::BI__builtin_reduce_mul:
5153 case Builtin::BI__builtin_reduce_and:
5154 case Builtin::BI__builtin_reduce_or:
5155 case Builtin::BI__builtin_reduce_xor:
5156 case Builtin::BI__builtin_reduce_min:
5157 case Builtin::BI__builtin_reduce_max:
5158 return interp__builtin_vector_reduce(S, OpPC, Call, BuiltinID);
5159
5160 case Builtin::BI__builtin_elementwise_popcount:
5162 S, OpPC, Call, [](const APSInt &Src) {
5163 return APInt(Src.getBitWidth(), Src.popcount());
5164 });
5165 case Builtin::BI__builtin_elementwise_bitreverse:
5167 S, OpPC, Call, [](const APSInt &Src) { return Src.reverseBits(); });
5168
5169 case Builtin::BI__builtin_elementwise_abs:
5170 return interp__builtin_elementwise_abs(S, OpPC, Frame, Call, BuiltinID);
5171
5172 case Builtin::BI__builtin_memcpy:
5173 case Builtin::BImemcpy:
5174 case Builtin::BI__builtin_wmemcpy:
5175 case Builtin::BIwmemcpy:
5176 case Builtin::BI__builtin_memmove:
5177 case Builtin::BImemmove:
5178 case Builtin::BI__builtin_wmemmove:
5179 case Builtin::BIwmemmove:
5180 return interp__builtin_memcpy(S, OpPC, Frame, Call, BuiltinID);
5181
5182 case Builtin::BI__builtin_memcmp:
5183 case Builtin::BImemcmp:
5184 case Builtin::BI__builtin_bcmp:
5185 case Builtin::BIbcmp:
5186 case Builtin::BI__builtin_wmemcmp:
5187 case Builtin::BIwmemcmp:
5188 return interp__builtin_memcmp(S, OpPC, Frame, Call, BuiltinID);
5189
5190 case Builtin::BImemchr:
5191 case Builtin::BI__builtin_memchr:
5192 case Builtin::BIstrchr:
5193 case Builtin::BI__builtin_strchr:
5194 case Builtin::BIwmemchr:
5195 case Builtin::BI__builtin_wmemchr:
5196 case Builtin::BIwcschr:
5197 case Builtin::BI__builtin_wcschr:
5198 case Builtin::BI__builtin_char_memchr:
5199 return interp__builtin_memchr(S, OpPC, Call, BuiltinID);
5200
5201 case Builtin::BI__builtin_object_size:
5202 case Builtin::BI__builtin_dynamic_object_size:
5203 return interp__builtin_object_size(S, OpPC, Frame, Call);
5204
5205 case Builtin::BI__builtin_is_within_lifetime:
5207
5208 case Builtin::BI__builtin_elementwise_add_sat:
5210 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5211 return LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS);
5212 });
5213
5214 case Builtin::BI__builtin_elementwise_sub_sat:
5216 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5217 return LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS);
5218 });
5219 case X86::BI__builtin_ia32_extract128i256:
5220 case X86::BI__builtin_ia32_vextractf128_pd256:
5221 case X86::BI__builtin_ia32_vextractf128_ps256:
5222 case X86::BI__builtin_ia32_vextractf128_si256:
5223 return interp__builtin_x86_extract_vector(S, OpPC, Call, BuiltinID);
5224
5225 case X86::BI__builtin_ia32_extractf32x4_256_mask:
5226 case X86::BI__builtin_ia32_extractf32x4_mask:
5227 case X86::BI__builtin_ia32_extractf32x8_mask:
5228 case X86::BI__builtin_ia32_extractf64x2_256_mask:
5229 case X86::BI__builtin_ia32_extractf64x2_512_mask:
5230 case X86::BI__builtin_ia32_extractf64x4_mask:
5231 case X86::BI__builtin_ia32_extracti32x4_256_mask:
5232 case X86::BI__builtin_ia32_extracti32x4_mask:
5233 case X86::BI__builtin_ia32_extracti32x8_mask:
5234 case X86::BI__builtin_ia32_extracti64x2_256_mask:
5235 case X86::BI__builtin_ia32_extracti64x2_512_mask:
5236 case X86::BI__builtin_ia32_extracti64x4_mask:
5237 return interp__builtin_x86_extract_vector_masked(S, OpPC, Call, BuiltinID);
5238
5239 case clang::X86::BI__builtin_ia32_pmulhrsw128:
5240 case clang::X86::BI__builtin_ia32_pmulhrsw256:
5241 case clang::X86::BI__builtin_ia32_pmulhrsw512:
5243 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5244 return (llvm::APIntOps::mulsExtended(LHS, RHS).ashr(14) + 1)
5245 .extractBits(16, 1);
5246 });
5247
5248 case clang::X86::BI__builtin_ia32_movmskps:
5249 case clang::X86::BI__builtin_ia32_movmskpd:
5250 case clang::X86::BI__builtin_ia32_pmovmskb128:
5251 case clang::X86::BI__builtin_ia32_pmovmskb256:
5252 case clang::X86::BI__builtin_ia32_movmskps256:
5253 case clang::X86::BI__builtin_ia32_movmskpd256: {
5254 return interp__builtin_ia32_movmsk_op(S, OpPC, Call);
5255 }
5256
5257 case X86::BI__builtin_ia32_psignb128:
5258 case X86::BI__builtin_ia32_psignb256:
5259 case X86::BI__builtin_ia32_psignw128:
5260 case X86::BI__builtin_ia32_psignw256:
5261 case X86::BI__builtin_ia32_psignd128:
5262 case X86::BI__builtin_ia32_psignd256:
5264 S, OpPC, Call, [](const APInt &AElem, const APInt &BElem) {
5265 if (BElem.isZero())
5266 return APInt::getZero(AElem.getBitWidth());
5267 if (BElem.isNegative())
5268 return -AElem;
5269 return AElem;
5270 });
5271
5272 case clang::X86::BI__builtin_ia32_pavgb128:
5273 case clang::X86::BI__builtin_ia32_pavgw128:
5274 case clang::X86::BI__builtin_ia32_pavgb256:
5275 case clang::X86::BI__builtin_ia32_pavgw256:
5276 case clang::X86::BI__builtin_ia32_pavgb512:
5277 case clang::X86::BI__builtin_ia32_pavgw512:
5279 llvm::APIntOps::avgCeilU);
5280
5281 case clang::X86::BI__builtin_ia32_pmaddubsw128:
5282 case clang::X86::BI__builtin_ia32_pmaddubsw256:
5283 case clang::X86::BI__builtin_ia32_pmaddubsw512:
5285 S, OpPC, Call,
5286 [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,
5287 const APSInt &HiRHS) {
5288 unsigned BitWidth = 2 * LoLHS.getBitWidth();
5289 return (LoLHS.zext(BitWidth) * LoRHS.sext(BitWidth))
5290 .sadd_sat((HiLHS.zext(BitWidth) * HiRHS.sext(BitWidth)));
5291 });
5292
5293 case clang::X86::BI__builtin_ia32_pmaddwd128:
5294 case clang::X86::BI__builtin_ia32_pmaddwd256:
5295 case clang::X86::BI__builtin_ia32_pmaddwd512:
5297 S, OpPC, Call,
5298 [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,
5299 const APSInt &HiRHS) {
5300 unsigned BitWidth = 2 * LoLHS.getBitWidth();
5301 return (LoLHS.sext(BitWidth) * LoRHS.sext(BitWidth)) +
5302 (HiLHS.sext(BitWidth) * HiRHS.sext(BitWidth));
5303 });
5304
5305 case clang::X86::BI__builtin_ia32_dbpsadbw128:
5306 case clang::X86::BI__builtin_ia32_dbpsadbw256:
5307 case clang::X86::BI__builtin_ia32_dbpsadbw512:
5308 return interp__builtin_ia32_dbpsadbw(S, OpPC, Call);
5309
5310 case clang::X86::BI__builtin_ia32_pmulhuw128:
5311 case clang::X86::BI__builtin_ia32_pmulhuw256:
5312 case clang::X86::BI__builtin_ia32_pmulhuw512:
5314 llvm::APIntOps::mulhu);
5315
5316 case clang::X86::BI__builtin_ia32_pmulhw128:
5317 case clang::X86::BI__builtin_ia32_pmulhw256:
5318 case clang::X86::BI__builtin_ia32_pmulhw512:
5320 llvm::APIntOps::mulhs);
5321
5322 case clang::X86::BI__builtin_ia32_psllv2di:
5323 case clang::X86::BI__builtin_ia32_psllv4di:
5324 case clang::X86::BI__builtin_ia32_psllv4si:
5325 case clang::X86::BI__builtin_ia32_psllv8di:
5326 case clang::X86::BI__builtin_ia32_psllv8hi:
5327 case clang::X86::BI__builtin_ia32_psllv8si:
5328 case clang::X86::BI__builtin_ia32_psllv16hi:
5329 case clang::X86::BI__builtin_ia32_psllv16si:
5330 case clang::X86::BI__builtin_ia32_psllv32hi:
5331 case clang::X86::BI__builtin_ia32_psllwi128:
5332 case clang::X86::BI__builtin_ia32_psllwi256:
5333 case clang::X86::BI__builtin_ia32_psllwi512:
5334 case clang::X86::BI__builtin_ia32_pslldi128:
5335 case clang::X86::BI__builtin_ia32_pslldi256:
5336 case clang::X86::BI__builtin_ia32_pslldi512:
5337 case clang::X86::BI__builtin_ia32_psllqi128:
5338 case clang::X86::BI__builtin_ia32_psllqi256:
5339 case clang::X86::BI__builtin_ia32_psllqi512:
5341 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5342 if (RHS.uge(LHS.getBitWidth())) {
5343 return APInt::getZero(LHS.getBitWidth());
5344 }
5345 return LHS.shl(RHS.getZExtValue());
5346 });
5347
5348 case clang::X86::BI__builtin_ia32_psrav4si:
5349 case clang::X86::BI__builtin_ia32_psrav8di:
5350 case clang::X86::BI__builtin_ia32_psrav8hi:
5351 case clang::X86::BI__builtin_ia32_psrav8si:
5352 case clang::X86::BI__builtin_ia32_psrav16hi:
5353 case clang::X86::BI__builtin_ia32_psrav16si:
5354 case clang::X86::BI__builtin_ia32_psrav32hi:
5355 case clang::X86::BI__builtin_ia32_psravq128:
5356 case clang::X86::BI__builtin_ia32_psravq256:
5357 case clang::X86::BI__builtin_ia32_psrawi128:
5358 case clang::X86::BI__builtin_ia32_psrawi256:
5359 case clang::X86::BI__builtin_ia32_psrawi512:
5360 case clang::X86::BI__builtin_ia32_psradi128:
5361 case clang::X86::BI__builtin_ia32_psradi256:
5362 case clang::X86::BI__builtin_ia32_psradi512:
5363 case clang::X86::BI__builtin_ia32_psraqi128:
5364 case clang::X86::BI__builtin_ia32_psraqi256:
5365 case clang::X86::BI__builtin_ia32_psraqi512:
5367 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5368 if (RHS.uge(LHS.getBitWidth())) {
5369 return LHS.ashr(LHS.getBitWidth() - 1);
5370 }
5371 return LHS.ashr(RHS.getZExtValue());
5372 });
5373
5374 case clang::X86::BI__builtin_ia32_psrlv2di:
5375 case clang::X86::BI__builtin_ia32_psrlv4di:
5376 case clang::X86::BI__builtin_ia32_psrlv4si:
5377 case clang::X86::BI__builtin_ia32_psrlv8di:
5378 case clang::X86::BI__builtin_ia32_psrlv8hi:
5379 case clang::X86::BI__builtin_ia32_psrlv8si:
5380 case clang::X86::BI__builtin_ia32_psrlv16hi:
5381 case clang::X86::BI__builtin_ia32_psrlv16si:
5382 case clang::X86::BI__builtin_ia32_psrlv32hi:
5383 case clang::X86::BI__builtin_ia32_psrlwi128:
5384 case clang::X86::BI__builtin_ia32_psrlwi256:
5385 case clang::X86::BI__builtin_ia32_psrlwi512:
5386 case clang::X86::BI__builtin_ia32_psrldi128:
5387 case clang::X86::BI__builtin_ia32_psrldi256:
5388 case clang::X86::BI__builtin_ia32_psrldi512:
5389 case clang::X86::BI__builtin_ia32_psrlqi128:
5390 case clang::X86::BI__builtin_ia32_psrlqi256:
5391 case clang::X86::BI__builtin_ia32_psrlqi512:
5393 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5394 if (RHS.uge(LHS.getBitWidth())) {
5395 return APInt::getZero(LHS.getBitWidth());
5396 }
5397 return LHS.lshr(RHS.getZExtValue());
5398 });
5399 case clang::X86::BI__builtin_ia32_packsswb128:
5400 case clang::X86::BI__builtin_ia32_packsswb256:
5401 case clang::X86::BI__builtin_ia32_packsswb512:
5402 case clang::X86::BI__builtin_ia32_packssdw128:
5403 case clang::X86::BI__builtin_ia32_packssdw256:
5404 case clang::X86::BI__builtin_ia32_packssdw512:
5405 return interp__builtin_x86_pack(S, OpPC, Call, [](const APSInt &Src) {
5406 return APInt(Src).truncSSat(Src.getBitWidth() / 2);
5407 });
5408 case clang::X86::BI__builtin_ia32_packusdw128:
5409 case clang::X86::BI__builtin_ia32_packusdw256:
5410 case clang::X86::BI__builtin_ia32_packusdw512:
5411 case clang::X86::BI__builtin_ia32_packuswb128:
5412 case clang::X86::BI__builtin_ia32_packuswb256:
5413 case clang::X86::BI__builtin_ia32_packuswb512:
5414 return interp__builtin_x86_pack(S, OpPC, Call, [](const APSInt &Src) {
5415 return APInt(Src).truncSSatU(Src.getBitWidth() / 2);
5416 });
5417
5418 case clang::X86::BI__builtin_ia32_selectss_128:
5419 case clang::X86::BI__builtin_ia32_selectsd_128:
5420 case clang::X86::BI__builtin_ia32_selectsh_128:
5421 case clang::X86::BI__builtin_ia32_selectsbf_128:
5423 case clang::X86::BI__builtin_ia32_vprotbi:
5424 case clang::X86::BI__builtin_ia32_vprotdi:
5425 case clang::X86::BI__builtin_ia32_vprotqi:
5426 case clang::X86::BI__builtin_ia32_vprotwi:
5427 case clang::X86::BI__builtin_ia32_prold128:
5428 case clang::X86::BI__builtin_ia32_prold256:
5429 case clang::X86::BI__builtin_ia32_prold512:
5430 case clang::X86::BI__builtin_ia32_prolq128:
5431 case clang::X86::BI__builtin_ia32_prolq256:
5432 case clang::X86::BI__builtin_ia32_prolq512:
5434 S, OpPC, Call,
5435 [](const APSInt &LHS, const APSInt &RHS) { return LHS.rotl(RHS); });
5436
5437 case clang::X86::BI__builtin_ia32_prord128:
5438 case clang::X86::BI__builtin_ia32_prord256:
5439 case clang::X86::BI__builtin_ia32_prord512:
5440 case clang::X86::BI__builtin_ia32_prorq128:
5441 case clang::X86::BI__builtin_ia32_prorq256:
5442 case clang::X86::BI__builtin_ia32_prorq512:
5444 S, OpPC, Call,
5445 [](const APSInt &LHS, const APSInt &RHS) { return LHS.rotr(RHS); });
5446
5447 case Builtin::BI__builtin_elementwise_max:
5448 case Builtin::BI__builtin_elementwise_min:
5449 return interp__builtin_elementwise_maxmin(S, OpPC, Call, BuiltinID);
5450
5451 case clang::X86::BI__builtin_ia32_phaddw128:
5452 case clang::X86::BI__builtin_ia32_phaddw256:
5453 case clang::X86::BI__builtin_ia32_phaddd128:
5454 case clang::X86::BI__builtin_ia32_phaddd256:
5456 S, OpPC, Call,
5457 [](const APSInt &LHS, const APSInt &RHS) { return LHS + RHS; });
5458 case clang::X86::BI__builtin_ia32_phaddsw128:
5459 case clang::X86::BI__builtin_ia32_phaddsw256:
5461 S, OpPC, Call,
5462 [](const APSInt &LHS, const APSInt &RHS) { return LHS.sadd_sat(RHS); });
5463 case clang::X86::BI__builtin_ia32_phsubw128:
5464 case clang::X86::BI__builtin_ia32_phsubw256:
5465 case clang::X86::BI__builtin_ia32_phsubd128:
5466 case clang::X86::BI__builtin_ia32_phsubd256:
5468 S, OpPC, Call,
5469 [](const APSInt &LHS, const APSInt &RHS) { return LHS - RHS; });
5470 case clang::X86::BI__builtin_ia32_phsubsw128:
5471 case clang::X86::BI__builtin_ia32_phsubsw256:
5473 S, OpPC, Call,
5474 [](const APSInt &LHS, const APSInt &RHS) { return LHS.ssub_sat(RHS); });
5475 case clang::X86::BI__builtin_ia32_haddpd:
5476 case clang::X86::BI__builtin_ia32_haddps:
5477 case clang::X86::BI__builtin_ia32_haddpd256:
5478 case clang::X86::BI__builtin_ia32_haddps256:
5480 S, OpPC, Call,
5481 [](const APFloat &LHS, const APFloat &RHS, llvm::RoundingMode RM) {
5482 APFloat F = LHS;
5483 F.add(RHS, RM);
5484 return F;
5485 });
5486 case clang::X86::BI__builtin_ia32_hsubpd:
5487 case clang::X86::BI__builtin_ia32_hsubps:
5488 case clang::X86::BI__builtin_ia32_hsubpd256:
5489 case clang::X86::BI__builtin_ia32_hsubps256:
5491 S, OpPC, Call,
5492 [](const APFloat &LHS, const APFloat &RHS, llvm::RoundingMode RM) {
5493 APFloat F = LHS;
5494 F.subtract(RHS, RM);
5495 return F;
5496 });
5497 case clang::X86::BI__builtin_ia32_addsubpd:
5498 case clang::X86::BI__builtin_ia32_addsubps:
5499 case clang::X86::BI__builtin_ia32_addsubpd256:
5500 case clang::X86::BI__builtin_ia32_addsubps256:
5501 return interp__builtin_ia32_addsub(S, OpPC, Call);
5502
5503 case clang::X86::BI__builtin_ia32_pmuldq128:
5504 case clang::X86::BI__builtin_ia32_pmuldq256:
5505 case clang::X86::BI__builtin_ia32_pmuldq512:
5507 S, OpPC, Call,
5508 [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,
5509 const APSInt &HiRHS) {
5510 return llvm::APIntOps::mulsExtended(LoLHS, LoRHS);
5511 });
5512
5513 case clang::X86::BI__builtin_ia32_pmuludq128:
5514 case clang::X86::BI__builtin_ia32_pmuludq256:
5515 case clang::X86::BI__builtin_ia32_pmuludq512:
5517 S, OpPC, Call,
5518 [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,
5519 const APSInt &HiRHS) {
5520 return llvm::APIntOps::muluExtended(LoLHS, LoRHS);
5521 });
5522
5523 case clang::X86::BI__builtin_ia32_pclmulqdq128:
5524 case clang::X86::BI__builtin_ia32_pclmulqdq256:
5525 case clang::X86::BI__builtin_ia32_pclmulqdq512:
5526 return interp__builtin_ia32_pclmulqdq(S, OpPC, Call);
5527
5528 case Builtin::BI__builtin_elementwise_fma:
5530 S, OpPC, Call,
5531 [](const APFloat &X, const APFloat &Y, const APFloat &Z,
5532 llvm::RoundingMode RM) {
5533 APFloat F = X;
5534 F.fusedMultiplyAdd(Y, Z, RM);
5535 return F;
5536 });
5537
5538 case X86::BI__builtin_ia32_vpmadd52luq128:
5539 case X86::BI__builtin_ia32_vpmadd52luq256:
5540 case X86::BI__builtin_ia32_vpmadd52luq512:
5542 S, OpPC, Call, [](const APSInt &A, const APSInt &B, const APSInt &C) {
5543 return A + (B.trunc(52) * C.trunc(52)).zext(64);
5544 });
5545 case X86::BI__builtin_ia32_vpmadd52huq128:
5546 case X86::BI__builtin_ia32_vpmadd52huq256:
5547 case X86::BI__builtin_ia32_vpmadd52huq512:
5549 S, OpPC, Call, [](const APSInt &A, const APSInt &B, const APSInt &C) {
5550 return A + llvm::APIntOps::mulhu(B.trunc(52), C.trunc(52)).zext(64);
5551 });
5552
5553 case X86::BI__builtin_ia32_vpshldd128:
5554 case X86::BI__builtin_ia32_vpshldd256:
5555 case X86::BI__builtin_ia32_vpshldd512:
5556 case X86::BI__builtin_ia32_vpshldq128:
5557 case X86::BI__builtin_ia32_vpshldq256:
5558 case X86::BI__builtin_ia32_vpshldq512:
5559 case X86::BI__builtin_ia32_vpshldw128:
5560 case X86::BI__builtin_ia32_vpshldw256:
5561 case X86::BI__builtin_ia32_vpshldw512:
5563 S, OpPC, Call,
5564 [](const APSInt &Hi, const APSInt &Lo, const APSInt &Amt) {
5565 return llvm::APIntOps::fshl(Hi, Lo, Amt);
5566 });
5567
5568 case X86::BI__builtin_ia32_vpshrdd128:
5569 case X86::BI__builtin_ia32_vpshrdd256:
5570 case X86::BI__builtin_ia32_vpshrdd512:
5571 case X86::BI__builtin_ia32_vpshrdq128:
5572 case X86::BI__builtin_ia32_vpshrdq256:
5573 case X86::BI__builtin_ia32_vpshrdq512:
5574 case X86::BI__builtin_ia32_vpshrdw128:
5575 case X86::BI__builtin_ia32_vpshrdw256:
5576 case X86::BI__builtin_ia32_vpshrdw512:
5577 // NOTE: Reversed Hi/Lo operands.
5579 S, OpPC, Call,
5580 [](const APSInt &Lo, const APSInt &Hi, const APSInt &Amt) {
5581 return llvm::APIntOps::fshr(Hi, Lo, Amt);
5582 });
5583 case X86::BI__builtin_ia32_vpconflictsi_128:
5584 case X86::BI__builtin_ia32_vpconflictsi_256:
5585 case X86::BI__builtin_ia32_vpconflictsi_512:
5586 case X86::BI__builtin_ia32_vpconflictdi_128:
5587 case X86::BI__builtin_ia32_vpconflictdi_256:
5588 case X86::BI__builtin_ia32_vpconflictdi_512:
5589 return interp__builtin_ia32_vpconflict(S, OpPC, Call);
5590 case X86::BI__builtin_ia32_compressdf128_mask:
5591 case X86::BI__builtin_ia32_compressdf256_mask:
5592 case X86::BI__builtin_ia32_compressdf512_mask:
5593 case X86::BI__builtin_ia32_compressdi128_mask:
5594 case X86::BI__builtin_ia32_compressdi256_mask:
5595 case X86::BI__builtin_ia32_compressdi512_mask:
5596 case X86::BI__builtin_ia32_compresshi128_mask:
5597 case X86::BI__builtin_ia32_compresshi256_mask:
5598 case X86::BI__builtin_ia32_compresshi512_mask:
5599 case X86::BI__builtin_ia32_compressqi128_mask:
5600 case X86::BI__builtin_ia32_compressqi256_mask:
5601 case X86::BI__builtin_ia32_compressqi512_mask:
5602 case X86::BI__builtin_ia32_compresssf128_mask:
5603 case X86::BI__builtin_ia32_compresssf256_mask:
5604 case X86::BI__builtin_ia32_compresssf512_mask:
5605 case X86::BI__builtin_ia32_compresssi128_mask:
5606 case X86::BI__builtin_ia32_compresssi256_mask:
5607 case X86::BI__builtin_ia32_compresssi512_mask: {
5608 unsigned NumElems =
5609 Call->getArg(0)->getType()->castAs<VectorType>()->getNumElements();
5611 S, OpPC, Call, [NumElems](unsigned DstIdx, const APInt &ShuffleMask) {
5612 APInt CompressMask = ShuffleMask.trunc(NumElems);
5613 if (DstIdx < CompressMask.popcount()) {
5614 while (DstIdx != 0) {
5615 CompressMask = CompressMask & (CompressMask - 1);
5616 DstIdx--;
5617 }
5618 return std::pair<unsigned, int>{
5619 0, static_cast<int>(CompressMask.countr_zero())};
5620 }
5621 return std::pair<unsigned, int>{1, static_cast<int>(DstIdx)};
5622 });
5623 }
5624 case X86::BI__builtin_ia32_expanddf128_mask:
5625 case X86::BI__builtin_ia32_expanddf256_mask:
5626 case X86::BI__builtin_ia32_expanddf512_mask:
5627 case X86::BI__builtin_ia32_expanddi128_mask:
5628 case X86::BI__builtin_ia32_expanddi256_mask:
5629 case X86::BI__builtin_ia32_expanddi512_mask:
5630 case X86::BI__builtin_ia32_expandhi128_mask:
5631 case X86::BI__builtin_ia32_expandhi256_mask:
5632 case X86::BI__builtin_ia32_expandhi512_mask:
5633 case X86::BI__builtin_ia32_expandqi128_mask:
5634 case X86::BI__builtin_ia32_expandqi256_mask:
5635 case X86::BI__builtin_ia32_expandqi512_mask:
5636 case X86::BI__builtin_ia32_expandsf128_mask:
5637 case X86::BI__builtin_ia32_expandsf256_mask:
5638 case X86::BI__builtin_ia32_expandsf512_mask:
5639 case X86::BI__builtin_ia32_expandsi128_mask:
5640 case X86::BI__builtin_ia32_expandsi256_mask:
5641 case X86::BI__builtin_ia32_expandsi512_mask: {
5643 S, OpPC, Call, [](unsigned DstIdx, const APInt &ShuffleMask) {
5644 // Trunc to the sub-mask for the dst index and count the number of
5645 // src elements used prior to that.
5646 APInt ExpandMask = ShuffleMask.trunc(DstIdx + 1);
5647 if (ExpandMask[DstIdx]) {
5648 int SrcIdx = ExpandMask.popcount() - 1;
5649 return std::pair<unsigned, int>{0, SrcIdx};
5650 }
5651 return std::pair<unsigned, int>{1, static_cast<int>(DstIdx)};
5652 });
5653 }
5654 case clang::X86::BI__builtin_ia32_blendpd:
5655 case clang::X86::BI__builtin_ia32_blendpd256:
5656 case clang::X86::BI__builtin_ia32_blendps:
5657 case clang::X86::BI__builtin_ia32_blendps256:
5658 case clang::X86::BI__builtin_ia32_pblendw128:
5659 case clang::X86::BI__builtin_ia32_pblendw256:
5660 case clang::X86::BI__builtin_ia32_pblendd128:
5661 case clang::X86::BI__builtin_ia32_pblendd256:
5663 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5664 // Bit index for mask.
5665 unsigned MaskBit = (ShuffleMask >> (DstIdx % 8)) & 0x1;
5666 unsigned SrcVecIdx = MaskBit ? 1 : 0; // 1 = TrueVec, 0 = FalseVec
5667 return std::pair<unsigned, int>{SrcVecIdx, static_cast<int>(DstIdx)};
5668 });
5669
5670
5671
5672 case clang::X86::BI__builtin_ia32_blendvpd:
5673 case clang::X86::BI__builtin_ia32_blendvpd256:
5674 case clang::X86::BI__builtin_ia32_blendvps:
5675 case clang::X86::BI__builtin_ia32_blendvps256:
5677 S, OpPC, Call,
5678 [](const APFloat &F, const APFloat &T, const APFloat &C,
5679 llvm::RoundingMode) { return C.isNegative() ? T : F; });
5680
5681 case clang::X86::BI__builtin_ia32_pblendvb128:
5682 case clang::X86::BI__builtin_ia32_pblendvb256:
5684 S, OpPC, Call, [](const APSInt &F, const APSInt &T, const APSInt &C) {
5685 return ((APInt)C).isNegative() ? T : F;
5686 });
5687 case X86::BI__builtin_ia32_ptestz128:
5688 case X86::BI__builtin_ia32_ptestz256:
5689 case X86::BI__builtin_ia32_vtestzps:
5690 case X86::BI__builtin_ia32_vtestzps256:
5691 case X86::BI__builtin_ia32_vtestzpd:
5692 case X86::BI__builtin_ia32_vtestzpd256:
5694 S, OpPC, Call,
5695 [](const APInt &A, const APInt &B) { return (A & B) == 0; });
5696 case X86::BI__builtin_ia32_ptestc128:
5697 case X86::BI__builtin_ia32_ptestc256:
5698 case X86::BI__builtin_ia32_vtestcps:
5699 case X86::BI__builtin_ia32_vtestcps256:
5700 case X86::BI__builtin_ia32_vtestcpd:
5701 case X86::BI__builtin_ia32_vtestcpd256:
5703 S, OpPC, Call,
5704 [](const APInt &A, const APInt &B) { return (~A & B) == 0; });
5705 case X86::BI__builtin_ia32_ptestnzc128:
5706 case X86::BI__builtin_ia32_ptestnzc256:
5707 case X86::BI__builtin_ia32_vtestnzcps:
5708 case X86::BI__builtin_ia32_vtestnzcps256:
5709 case X86::BI__builtin_ia32_vtestnzcpd:
5710 case X86::BI__builtin_ia32_vtestnzcpd256:
5712 S, OpPC, Call, [](const APInt &A, const APInt &B) {
5713 return ((A & B) != 0) && ((~A & B) != 0);
5714 });
5715 case X86::BI__builtin_ia32_selectb_128:
5716 case X86::BI__builtin_ia32_selectb_256:
5717 case X86::BI__builtin_ia32_selectb_512:
5718 case X86::BI__builtin_ia32_selectw_128:
5719 case X86::BI__builtin_ia32_selectw_256:
5720 case X86::BI__builtin_ia32_selectw_512:
5721 case X86::BI__builtin_ia32_selectd_128:
5722 case X86::BI__builtin_ia32_selectd_256:
5723 case X86::BI__builtin_ia32_selectd_512:
5724 case X86::BI__builtin_ia32_selectq_128:
5725 case X86::BI__builtin_ia32_selectq_256:
5726 case X86::BI__builtin_ia32_selectq_512:
5727 case X86::BI__builtin_ia32_selectph_128:
5728 case X86::BI__builtin_ia32_selectph_256:
5729 case X86::BI__builtin_ia32_selectph_512:
5730 case X86::BI__builtin_ia32_selectpbf_128:
5731 case X86::BI__builtin_ia32_selectpbf_256:
5732 case X86::BI__builtin_ia32_selectpbf_512:
5733 case X86::BI__builtin_ia32_selectps_128:
5734 case X86::BI__builtin_ia32_selectps_256:
5735 case X86::BI__builtin_ia32_selectps_512:
5736 case X86::BI__builtin_ia32_selectpd_128:
5737 case X86::BI__builtin_ia32_selectpd_256:
5738 case X86::BI__builtin_ia32_selectpd_512:
5739 return interp__builtin_select(S, OpPC, Call);
5740
5741 case X86::BI__builtin_ia32_shufps:
5742 case X86::BI__builtin_ia32_shufps256:
5743 case X86::BI__builtin_ia32_shufps512:
5745 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5746 unsigned NumElemPerLane = 4;
5747 unsigned NumSelectableElems = NumElemPerLane / 2;
5748 unsigned BitsPerElem = 2;
5749 unsigned IndexMask = 0x3;
5750 unsigned MaskBits = 8;
5751 unsigned Lane = DstIdx / NumElemPerLane;
5752 unsigned ElemInLane = DstIdx % NumElemPerLane;
5753 unsigned LaneOffset = Lane * NumElemPerLane;
5754 unsigned SrcIdx = ElemInLane >= NumSelectableElems ? 1 : 0;
5755 unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;
5756 unsigned Index = (ShuffleMask >> BitIndex) & IndexMask;
5757 return std::pair<unsigned, int>{SrcIdx,
5758 static_cast<int>(LaneOffset + Index)};
5759 });
5760 case X86::BI__builtin_ia32_shufpd:
5761 case X86::BI__builtin_ia32_shufpd256:
5762 case X86::BI__builtin_ia32_shufpd512:
5764 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5765 unsigned NumElemPerLane = 2;
5766 unsigned NumSelectableElems = NumElemPerLane / 2;
5767 unsigned BitsPerElem = 1;
5768 unsigned IndexMask = 0x1;
5769 unsigned MaskBits = 8;
5770 unsigned Lane = DstIdx / NumElemPerLane;
5771 unsigned ElemInLane = DstIdx % NumElemPerLane;
5772 unsigned LaneOffset = Lane * NumElemPerLane;
5773 unsigned SrcIdx = ElemInLane >= NumSelectableElems ? 1 : 0;
5774 unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;
5775 unsigned Index = (ShuffleMask >> BitIndex) & IndexMask;
5776 return std::pair<unsigned, int>{SrcIdx,
5777 static_cast<int>(LaneOffset + Index)};
5778 });
5779
5780 case X86::BI__builtin_ia32_vgf2p8affineinvqb_v16qi:
5781 case X86::BI__builtin_ia32_vgf2p8affineinvqb_v32qi:
5782 case X86::BI__builtin_ia32_vgf2p8affineinvqb_v64qi:
5783 return interp_builtin_ia32_gfni_affine(S, OpPC, Call, true);
5784 case X86::BI__builtin_ia32_vgf2p8affineqb_v16qi:
5785 case X86::BI__builtin_ia32_vgf2p8affineqb_v32qi:
5786 case X86::BI__builtin_ia32_vgf2p8affineqb_v64qi:
5787 return interp_builtin_ia32_gfni_affine(S, OpPC, Call, false);
5788
5789 case X86::BI__builtin_ia32_vgf2p8mulb_v16qi:
5790 case X86::BI__builtin_ia32_vgf2p8mulb_v32qi:
5791 case X86::BI__builtin_ia32_vgf2p8mulb_v64qi:
5792 return interp__builtin_ia32_gfni_mul(S, OpPC, Call);
5793
5794 case X86::BI__builtin_ia32_insertps128:
5796 S, OpPC, Call, [](unsigned DstIdx, unsigned Mask) {
5797 // Bits [3:0]: zero mask - if bit is set, zero this element
5798 if ((Mask & (1 << DstIdx)) != 0) {
5799 return std::pair<unsigned, int>{0, -1};
5800 }
5801 // Bits [7:6]: select element from source vector Y (0-3)
5802 // Bits [5:4]: select destination position (0-3)
5803 unsigned SrcElem = (Mask >> 6) & 0x3;
5804 unsigned DstElem = (Mask >> 4) & 0x3;
5805 if (DstIdx == DstElem) {
5806 // Insert element from source vector (B) at this position
5807 return std::pair<unsigned, int>{1, static_cast<int>(SrcElem)};
5808 } else {
5809 // Copy from destination vector (A)
5810 return std::pair<unsigned, int>{0, static_cast<int>(DstIdx)};
5811 }
5812 });
5813 case X86::BI__builtin_ia32_permvarsi256:
5814 case X86::BI__builtin_ia32_permvarsf256:
5815 case X86::BI__builtin_ia32_permvardf512:
5816 case X86::BI__builtin_ia32_permvardi512:
5817 case X86::BI__builtin_ia32_permvarhi128:
5819 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5820 int Offset = ShuffleMask & 0x7;
5821 return std::pair<unsigned, int>{0, Offset};
5822 });
5823 case X86::BI__builtin_ia32_permvarqi128:
5824 case X86::BI__builtin_ia32_permvarhi256:
5825 case X86::BI__builtin_ia32_permvarsi512:
5826 case X86::BI__builtin_ia32_permvarsf512:
5828 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5829 int Offset = ShuffleMask & 0xF;
5830 return std::pair<unsigned, int>{0, Offset};
5831 });
5832 case X86::BI__builtin_ia32_permvardi256:
5833 case X86::BI__builtin_ia32_permvardf256:
5835 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5836 int Offset = ShuffleMask & 0x3;
5837 return std::pair<unsigned, int>{0, Offset};
5838 });
5839 case X86::BI__builtin_ia32_permvarqi256:
5840 case X86::BI__builtin_ia32_permvarhi512:
5842 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5843 int Offset = ShuffleMask & 0x1F;
5844 return std::pair<unsigned, int>{0, Offset};
5845 });
5846 case X86::BI__builtin_ia32_permvarqi512:
5848 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5849 int Offset = ShuffleMask & 0x3F;
5850 return std::pair<unsigned, int>{0, Offset};
5851 });
5852 case X86::BI__builtin_ia32_vpermi2varq128:
5853 case X86::BI__builtin_ia32_vpermi2varpd128:
5855 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5856 int Offset = ShuffleMask & 0x1;
5857 unsigned SrcIdx = (ShuffleMask >> 1) & 0x1;
5858 return std::pair<unsigned, int>{SrcIdx, Offset};
5859 });
5860 case X86::BI__builtin_ia32_vpermi2vard128:
5861 case X86::BI__builtin_ia32_vpermi2varps128:
5862 case X86::BI__builtin_ia32_vpermi2varq256:
5863 case X86::BI__builtin_ia32_vpermi2varpd256:
5865 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5866 int Offset = ShuffleMask & 0x3;
5867 unsigned SrcIdx = (ShuffleMask >> 2) & 0x1;
5868 return std::pair<unsigned, int>{SrcIdx, Offset};
5869 });
5870 case X86::BI__builtin_ia32_vpermi2varhi128:
5871 case X86::BI__builtin_ia32_vpermi2vard256:
5872 case X86::BI__builtin_ia32_vpermi2varps256:
5873 case X86::BI__builtin_ia32_vpermi2varq512:
5874 case X86::BI__builtin_ia32_vpermi2varpd512:
5876 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5877 int Offset = ShuffleMask & 0x7;
5878 unsigned SrcIdx = (ShuffleMask >> 3) & 0x1;
5879 return std::pair<unsigned, int>{SrcIdx, Offset};
5880 });
5881 case X86::BI__builtin_ia32_vpermi2varqi128:
5882 case X86::BI__builtin_ia32_vpermi2varhi256:
5883 case X86::BI__builtin_ia32_vpermi2vard512:
5884 case X86::BI__builtin_ia32_vpermi2varps512:
5886 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5887 int Offset = ShuffleMask & 0xF;
5888 unsigned SrcIdx = (ShuffleMask >> 4) & 0x1;
5889 return std::pair<unsigned, int>{SrcIdx, Offset};
5890 });
5891 case X86::BI__builtin_ia32_vpermi2varqi256:
5892 case X86::BI__builtin_ia32_vpermi2varhi512:
5894 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5895 int Offset = ShuffleMask & 0x1F;
5896 unsigned SrcIdx = (ShuffleMask >> 5) & 0x1;
5897 return std::pair<unsigned, int>{SrcIdx, Offset};
5898 });
5899 case X86::BI__builtin_ia32_vpermi2varqi512:
5901 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5902 int Offset = ShuffleMask & 0x3F;
5903 unsigned SrcIdx = (ShuffleMask >> 6) & 0x1;
5904 return std::pair<unsigned, int>{SrcIdx, Offset};
5905 });
5906 case X86::BI__builtin_ia32_vperm2f128_pd256:
5907 case X86::BI__builtin_ia32_vperm2f128_ps256:
5908 case X86::BI__builtin_ia32_vperm2f128_si256:
5909 case X86::BI__builtin_ia32_permti256: {
5910 unsigned NumElements =
5911 Call->getArg(0)->getType()->castAs<VectorType>()->getNumElements();
5912 unsigned PreservedBitsCnt = NumElements >> 2;
5914 S, OpPC, Call,
5915 [PreservedBitsCnt](unsigned DstIdx, unsigned ShuffleMask) {
5916 unsigned ControlBitsCnt = DstIdx >> PreservedBitsCnt << 2;
5917 unsigned ControlBits = ShuffleMask >> ControlBitsCnt;
5918
5919 if (ControlBits & 0b1000)
5920 return std::make_pair(0u, -1);
5921
5922 unsigned SrcVecIdx = (ControlBits & 0b10) >> 1;
5923 unsigned PreservedBitsMask = (1 << PreservedBitsCnt) - 1;
5924 int SrcIdx = ((ControlBits & 0b1) << PreservedBitsCnt) |
5925 (DstIdx & PreservedBitsMask);
5926 return std::make_pair(SrcVecIdx, SrcIdx);
5927 });
5928 }
5929 case X86::BI__builtin_ia32_pshufb128:
5930 case X86::BI__builtin_ia32_pshufb256:
5931 case X86::BI__builtin_ia32_pshufb512:
5933 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5934 uint8_t Ctlb = static_cast<uint8_t>(ShuffleMask);
5935 if (Ctlb & 0x80)
5936 return std::make_pair(0, -1);
5937
5938 unsigned LaneBase = (DstIdx / 16) * 16;
5939 unsigned SrcOffset = Ctlb & 0x0F;
5940 unsigned SrcIdx = LaneBase + SrcOffset;
5941 return std::make_pair(0, static_cast<int>(SrcIdx));
5942 });
5943
5944 case X86::BI__builtin_ia32_pshuflw:
5945 case X86::BI__builtin_ia32_pshuflw256:
5946 case X86::BI__builtin_ia32_pshuflw512:
5948 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5949 unsigned LaneBase = (DstIdx / 8) * 8;
5950 unsigned LaneIdx = DstIdx % 8;
5951 if (LaneIdx < 4) {
5952 unsigned Sel = (ShuffleMask >> (2 * LaneIdx)) & 0x3;
5953 return std::make_pair(0, static_cast<int>(LaneBase + Sel));
5954 }
5955
5956 return std::make_pair(0, static_cast<int>(DstIdx));
5957 });
5958
5959 case X86::BI__builtin_ia32_pshufhw:
5960 case X86::BI__builtin_ia32_pshufhw256:
5961 case X86::BI__builtin_ia32_pshufhw512:
5963 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5964 unsigned LaneBase = (DstIdx / 8) * 8;
5965 unsigned LaneIdx = DstIdx % 8;
5966 if (LaneIdx >= 4) {
5967 unsigned Sel = (ShuffleMask >> (2 * (LaneIdx - 4))) & 0x3;
5968 return std::make_pair(0, static_cast<int>(LaneBase + 4 + Sel));
5969 }
5970
5971 return std::make_pair(0, static_cast<int>(DstIdx));
5972 });
5973
5974 case X86::BI__builtin_ia32_pshufd:
5975 case X86::BI__builtin_ia32_pshufd256:
5976 case X86::BI__builtin_ia32_pshufd512:
5977 case X86::BI__builtin_ia32_vpermilps:
5978 case X86::BI__builtin_ia32_vpermilps256:
5979 case X86::BI__builtin_ia32_vpermilps512:
5981 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5982 unsigned LaneBase = (DstIdx / 4) * 4;
5983 unsigned LaneIdx = DstIdx % 4;
5984 unsigned Sel = (ShuffleMask >> (2 * LaneIdx)) & 0x3;
5985 return std::make_pair(0, static_cast<int>(LaneBase + Sel));
5986 });
5987
5988 case X86::BI__builtin_ia32_vpermilvarpd:
5989 case X86::BI__builtin_ia32_vpermilvarpd256:
5990 case X86::BI__builtin_ia32_vpermilvarpd512:
5992 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5993 unsigned NumElemPerLane = 2;
5994 unsigned Lane = DstIdx / NumElemPerLane;
5995 unsigned Offset = ShuffleMask & 0b10 ? 1 : 0;
5996 return std::make_pair(
5997 0, static_cast<int>(Lane * NumElemPerLane + Offset));
5998 });
5999
6000 case X86::BI__builtin_ia32_vpermilvarps:
6001 case X86::BI__builtin_ia32_vpermilvarps256:
6002 case X86::BI__builtin_ia32_vpermilvarps512:
6004 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6005 unsigned NumElemPerLane = 4;
6006 unsigned Lane = DstIdx / NumElemPerLane;
6007 unsigned Offset = ShuffleMask & 0b11;
6008 return std::make_pair(
6009 0, static_cast<int>(Lane * NumElemPerLane + Offset));
6010 });
6011
6012 case X86::BI__builtin_ia32_vpermilpd:
6013 case X86::BI__builtin_ia32_vpermilpd256:
6014 case X86::BI__builtin_ia32_vpermilpd512:
6016 S, OpPC, Call, [](unsigned DstIdx, unsigned Control) {
6017 unsigned NumElemPerLane = 2;
6018 unsigned BitsPerElem = 1;
6019 unsigned MaskBits = 8;
6020 unsigned IndexMask = 0x1;
6021 unsigned Lane = DstIdx / NumElemPerLane;
6022 unsigned LaneOffset = Lane * NumElemPerLane;
6023 unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;
6024 unsigned Index = (Control >> BitIndex) & IndexMask;
6025 return std::make_pair(0, static_cast<int>(LaneOffset + Index));
6026 });
6027
6028 case X86::BI__builtin_ia32_permdf256:
6029 case X86::BI__builtin_ia32_permdi256:
6031 S, OpPC, Call, [](unsigned DstIdx, unsigned Control) {
6032 // permute4x64 operates on 4 64-bit elements
6033 // For element i (0-3), extract bits [2*i+1:2*i] from Control
6034 unsigned Index = (Control >> (2 * DstIdx)) & 0x3;
6035 return std::make_pair(0, static_cast<int>(Index));
6036 });
6037
6038 case X86::BI__builtin_ia32_vpmultishiftqb128:
6039 case X86::BI__builtin_ia32_vpmultishiftqb256:
6040 case X86::BI__builtin_ia32_vpmultishiftqb512:
6041 return interp__builtin_ia32_multishiftqb(S, OpPC, Call);
6042 case X86::BI__builtin_ia32_kandqi:
6043 case X86::BI__builtin_ia32_kandhi:
6044 case X86::BI__builtin_ia32_kandsi:
6045 case X86::BI__builtin_ia32_kanddi:
6047 S, OpPC, Call,
6048 [](const APSInt &LHS, const APSInt &RHS) { return LHS & RHS; });
6049
6050 case X86::BI__builtin_ia32_kandnqi:
6051 case X86::BI__builtin_ia32_kandnhi:
6052 case X86::BI__builtin_ia32_kandnsi:
6053 case X86::BI__builtin_ia32_kandndi:
6055 S, OpPC, Call,
6056 [](const APSInt &LHS, const APSInt &RHS) { return ~LHS & RHS; });
6057
6058 case X86::BI__builtin_ia32_korqi:
6059 case X86::BI__builtin_ia32_korhi:
6060 case X86::BI__builtin_ia32_korsi:
6061 case X86::BI__builtin_ia32_kordi:
6063 S, OpPC, Call,
6064 [](const APSInt &LHS, const APSInt &RHS) { return LHS | RHS; });
6065
6066 case X86::BI__builtin_ia32_kxnorqi:
6067 case X86::BI__builtin_ia32_kxnorhi:
6068 case X86::BI__builtin_ia32_kxnorsi:
6069 case X86::BI__builtin_ia32_kxnordi:
6071 S, OpPC, Call,
6072 [](const APSInt &LHS, const APSInt &RHS) { return ~(LHS ^ RHS); });
6073
6074 case X86::BI__builtin_ia32_kxorqi:
6075 case X86::BI__builtin_ia32_kxorhi:
6076 case X86::BI__builtin_ia32_kxorsi:
6077 case X86::BI__builtin_ia32_kxordi:
6079 S, OpPC, Call,
6080 [](const APSInt &LHS, const APSInt &RHS) { return LHS ^ RHS; });
6081
6082 case X86::BI__builtin_ia32_knotqi:
6083 case X86::BI__builtin_ia32_knothi:
6084 case X86::BI__builtin_ia32_knotsi:
6085 case X86::BI__builtin_ia32_knotdi:
6087 S, OpPC, Call, [](const APSInt &Src) { return ~Src; });
6088
6089 case X86::BI__builtin_ia32_kaddqi:
6090 case X86::BI__builtin_ia32_kaddhi:
6091 case X86::BI__builtin_ia32_kaddsi:
6092 case X86::BI__builtin_ia32_kadddi:
6094 S, OpPC, Call,
6095 [](const APSInt &LHS, const APSInt &RHS) { return LHS + RHS; });
6096
6097 case X86::BI__builtin_ia32_kmovb:
6098 case X86::BI__builtin_ia32_kmovw:
6099 case X86::BI__builtin_ia32_kmovd:
6100 case X86::BI__builtin_ia32_kmovq:
6102 S, OpPC, Call, [](const APSInt &Src) { return Src; });
6103
6104 case X86::BI__builtin_ia32_kunpckhi:
6105 case X86::BI__builtin_ia32_kunpckdi:
6106 case X86::BI__builtin_ia32_kunpcksi:
6108 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
6109 // Generic kunpack: extract lower half of each operand and concatenate
6110 // Result = A[HalfWidth-1:0] concat B[HalfWidth-1:0]
6111 unsigned BW = A.getBitWidth();
6112 return APSInt(A.trunc(BW / 2).concat(B.trunc(BW / 2)),
6113 A.isUnsigned());
6114 });
6115
6116 case X86::BI__builtin_ia32_phminposuw128:
6117 return interp__builtin_ia32_phminposuw(S, OpPC, Call);
6118
6119 case X86::BI__builtin_ia32_psraq128:
6120 case X86::BI__builtin_ia32_psraq256:
6121 case X86::BI__builtin_ia32_psraq512:
6122 case X86::BI__builtin_ia32_psrad128:
6123 case X86::BI__builtin_ia32_psrad256:
6124 case X86::BI__builtin_ia32_psrad512:
6125 case X86::BI__builtin_ia32_psraw128:
6126 case X86::BI__builtin_ia32_psraw256:
6127 case X86::BI__builtin_ia32_psraw512:
6129 S, OpPC, Call,
6130 [](const APInt &Elt, uint64_t Count) { return Elt.ashr(Count); },
6131 [](const APInt &Elt, unsigned Width) { return Elt.ashr(Width - 1); });
6132
6133 case X86::BI__builtin_ia32_psllq128:
6134 case X86::BI__builtin_ia32_psllq256:
6135 case X86::BI__builtin_ia32_psllq512:
6136 case X86::BI__builtin_ia32_pslld128:
6137 case X86::BI__builtin_ia32_pslld256:
6138 case X86::BI__builtin_ia32_pslld512:
6139 case X86::BI__builtin_ia32_psllw128:
6140 case X86::BI__builtin_ia32_psllw256:
6141 case X86::BI__builtin_ia32_psllw512:
6143 S, OpPC, Call,
6144 [](const APInt &Elt, uint64_t Count) { return Elt.shl(Count); },
6145 [](const APInt &Elt, unsigned Width) { return APInt::getZero(Width); });
6146
6147 case X86::BI__builtin_ia32_psrlq128:
6148 case X86::BI__builtin_ia32_psrlq256:
6149 case X86::BI__builtin_ia32_psrlq512:
6150 case X86::BI__builtin_ia32_psrld128:
6151 case X86::BI__builtin_ia32_psrld256:
6152 case X86::BI__builtin_ia32_psrld512:
6153 case X86::BI__builtin_ia32_psrlw128:
6154 case X86::BI__builtin_ia32_psrlw256:
6155 case X86::BI__builtin_ia32_psrlw512:
6157 S, OpPC, Call,
6158 [](const APInt &Elt, uint64_t Count) { return Elt.lshr(Count); },
6159 [](const APInt &Elt, unsigned Width) { return APInt::getZero(Width); });
6160
6161 case X86::BI__builtin_ia32_pternlogd128_mask:
6162 case X86::BI__builtin_ia32_pternlogd256_mask:
6163 case X86::BI__builtin_ia32_pternlogd512_mask:
6164 case X86::BI__builtin_ia32_pternlogq128_mask:
6165 case X86::BI__builtin_ia32_pternlogq256_mask:
6166 case X86::BI__builtin_ia32_pternlogq512_mask:
6167 return interp__builtin_ia32_pternlog(S, OpPC, Call, /*MaskZ=*/false);
6168 case X86::BI__builtin_ia32_pternlogd128_maskz:
6169 case X86::BI__builtin_ia32_pternlogd256_maskz:
6170 case X86::BI__builtin_ia32_pternlogd512_maskz:
6171 case X86::BI__builtin_ia32_pternlogq128_maskz:
6172 case X86::BI__builtin_ia32_pternlogq256_maskz:
6173 case X86::BI__builtin_ia32_pternlogq512_maskz:
6174 return interp__builtin_ia32_pternlog(S, OpPC, Call, /*MaskZ=*/true);
6175 case Builtin::BI__builtin_elementwise_fshl:
6177 llvm::APIntOps::fshl);
6178 case Builtin::BI__builtin_elementwise_fshr:
6180 llvm::APIntOps::fshr);
6181
6182 case X86::BI__builtin_ia32_shuf_f32x4_256:
6183 case X86::BI__builtin_ia32_shuf_i32x4_256:
6184 case X86::BI__builtin_ia32_shuf_f64x2_256:
6185 case X86::BI__builtin_ia32_shuf_i64x2_256:
6186 case X86::BI__builtin_ia32_shuf_f32x4:
6187 case X86::BI__builtin_ia32_shuf_i32x4:
6188 case X86::BI__builtin_ia32_shuf_f64x2:
6189 case X86::BI__builtin_ia32_shuf_i64x2: {
6190 // Destination and sources A, B all have the same type.
6191 QualType VecQT = Call->getArg(0)->getType();
6192 const auto *VecT = VecQT->castAs<VectorType>();
6193 unsigned NumElems = VecT->getNumElements();
6194 unsigned ElemBits = S.getASTContext().getTypeSize(VecT->getElementType());
6195 unsigned LaneBits = 128u;
6196 unsigned NumLanes = (NumElems * ElemBits) / LaneBits;
6197 unsigned NumElemsPerLane = LaneBits / ElemBits;
6198
6200 S, OpPC, Call,
6201 [NumLanes, NumElemsPerLane](unsigned DstIdx, unsigned ShuffleMask) {
6202 // DstIdx determines source. ShuffleMask selects lane in source.
6203 unsigned BitsPerElem = NumLanes / 2;
6204 unsigned IndexMask = (1u << BitsPerElem) - 1;
6205 unsigned Lane = DstIdx / NumElemsPerLane;
6206 unsigned SrcIdx = (Lane < NumLanes / 2) ? 0 : 1;
6207 unsigned BitIdx = BitsPerElem * Lane;
6208 unsigned SrcLaneIdx = (ShuffleMask >> BitIdx) & IndexMask;
6209 unsigned ElemInLane = DstIdx % NumElemsPerLane;
6210 unsigned IdxToPick = SrcLaneIdx * NumElemsPerLane + ElemInLane;
6211 return std::pair<unsigned, int>{SrcIdx, IdxToPick};
6212 });
6213 }
6214
6215 case X86::BI__builtin_ia32_insertf32x4_256:
6216 case X86::BI__builtin_ia32_inserti32x4_256:
6217 case X86::BI__builtin_ia32_insertf64x2_256:
6218 case X86::BI__builtin_ia32_inserti64x2_256:
6219 case X86::BI__builtin_ia32_insertf32x4:
6220 case X86::BI__builtin_ia32_inserti32x4:
6221 case X86::BI__builtin_ia32_insertf64x2_512:
6222 case X86::BI__builtin_ia32_inserti64x2_512:
6223 case X86::BI__builtin_ia32_insertf32x8:
6224 case X86::BI__builtin_ia32_inserti32x8:
6225 case X86::BI__builtin_ia32_insertf64x4:
6226 case X86::BI__builtin_ia32_inserti64x4:
6227 case X86::BI__builtin_ia32_vinsertf128_ps256:
6228 case X86::BI__builtin_ia32_vinsertf128_pd256:
6229 case X86::BI__builtin_ia32_vinsertf128_si256:
6230 case X86::BI__builtin_ia32_insert128i256:
6231 return interp__builtin_x86_insert_subvector(S, OpPC, Call, BuiltinID);
6232
6233 case clang::X86::BI__builtin_ia32_vcvtps2ph:
6234 case clang::X86::BI__builtin_ia32_vcvtps2ph256:
6235 return interp__builtin_ia32_vcvtps2ph(S, OpPC, Call);
6236
6237 case X86::BI__builtin_ia32_vec_ext_v4hi:
6238 case X86::BI__builtin_ia32_vec_ext_v16qi:
6239 case X86::BI__builtin_ia32_vec_ext_v8hi:
6240 case X86::BI__builtin_ia32_vec_ext_v4si:
6241 case X86::BI__builtin_ia32_vec_ext_v2di:
6242 case X86::BI__builtin_ia32_vec_ext_v32qi:
6243 case X86::BI__builtin_ia32_vec_ext_v16hi:
6244 case X86::BI__builtin_ia32_vec_ext_v8si:
6245 case X86::BI__builtin_ia32_vec_ext_v4di:
6246 case X86::BI__builtin_ia32_vec_ext_v4sf:
6247 return interp__builtin_vec_ext(S, OpPC, Call, BuiltinID);
6248
6249 case X86::BI__builtin_ia32_vec_set_v4hi:
6250 case X86::BI__builtin_ia32_vec_set_v16qi:
6251 case X86::BI__builtin_ia32_vec_set_v8hi:
6252 case X86::BI__builtin_ia32_vec_set_v4si:
6253 case X86::BI__builtin_ia32_vec_set_v2di:
6254 case X86::BI__builtin_ia32_vec_set_v32qi:
6255 case X86::BI__builtin_ia32_vec_set_v16hi:
6256 case X86::BI__builtin_ia32_vec_set_v8si:
6257 case X86::BI__builtin_ia32_vec_set_v4di:
6258 return interp__builtin_vec_set(S, OpPC, Call, BuiltinID);
6259
6260 case X86::BI__builtin_ia32_cvtb2mask128:
6261 case X86::BI__builtin_ia32_cvtb2mask256:
6262 case X86::BI__builtin_ia32_cvtb2mask512:
6263 case X86::BI__builtin_ia32_cvtw2mask128:
6264 case X86::BI__builtin_ia32_cvtw2mask256:
6265 case X86::BI__builtin_ia32_cvtw2mask512:
6266 case X86::BI__builtin_ia32_cvtd2mask128:
6267 case X86::BI__builtin_ia32_cvtd2mask256:
6268 case X86::BI__builtin_ia32_cvtd2mask512:
6269 case X86::BI__builtin_ia32_cvtq2mask128:
6270 case X86::BI__builtin_ia32_cvtq2mask256:
6271 case X86::BI__builtin_ia32_cvtq2mask512:
6272 return interp__builtin_ia32_cvt_vec2mask(S, OpPC, Call, BuiltinID);
6273
6274 case X86::BI__builtin_ia32_cvtmask2b128:
6275 case X86::BI__builtin_ia32_cvtmask2b256:
6276 case X86::BI__builtin_ia32_cvtmask2b512:
6277 case X86::BI__builtin_ia32_cvtmask2w128:
6278 case X86::BI__builtin_ia32_cvtmask2w256:
6279 case X86::BI__builtin_ia32_cvtmask2w512:
6280 case X86::BI__builtin_ia32_cvtmask2d128:
6281 case X86::BI__builtin_ia32_cvtmask2d256:
6282 case X86::BI__builtin_ia32_cvtmask2d512:
6283 case X86::BI__builtin_ia32_cvtmask2q128:
6284 case X86::BI__builtin_ia32_cvtmask2q256:
6285 case X86::BI__builtin_ia32_cvtmask2q512:
6286 return interp__builtin_ia32_cvt_mask2vec(S, OpPC, Call, BuiltinID);
6287
6288 case X86::BI__builtin_ia32_cvtsd2ss:
6289 return interp__builtin_ia32_cvtsd2ss(S, OpPC, Call, false);
6290
6291 case X86::BI__builtin_ia32_cvtsd2ss_round_mask:
6292 return interp__builtin_ia32_cvtsd2ss(S, OpPC, Call, true);
6293
6294 case X86::BI__builtin_ia32_cvtpd2ps:
6295 case X86::BI__builtin_ia32_cvtpd2ps256:
6296 return interp__builtin_ia32_cvtpd2ps(S, OpPC, Call, false, false);
6297 case X86::BI__builtin_ia32_cvtpd2ps_mask:
6298 return interp__builtin_ia32_cvtpd2ps(S, OpPC, Call, true, false);
6299 case X86::BI__builtin_ia32_cvtpd2ps512_mask:
6300 return interp__builtin_ia32_cvtpd2ps(S, OpPC, Call, true, true);
6301
6302 case X86::BI__builtin_ia32_cmpb128_mask:
6303 case X86::BI__builtin_ia32_cmpw128_mask:
6304 case X86::BI__builtin_ia32_cmpd128_mask:
6305 case X86::BI__builtin_ia32_cmpq128_mask:
6306 case X86::BI__builtin_ia32_cmpb256_mask:
6307 case X86::BI__builtin_ia32_cmpw256_mask:
6308 case X86::BI__builtin_ia32_cmpd256_mask:
6309 case X86::BI__builtin_ia32_cmpq256_mask:
6310 case X86::BI__builtin_ia32_cmpb512_mask:
6311 case X86::BI__builtin_ia32_cmpw512_mask:
6312 case X86::BI__builtin_ia32_cmpd512_mask:
6313 case X86::BI__builtin_ia32_cmpq512_mask:
6314 return interp__builtin_ia32_cmp_mask(S, OpPC, Call, BuiltinID,
6315 /*IsUnsigned=*/false);
6316
6317 case X86::BI__builtin_ia32_ucmpb128_mask:
6318 case X86::BI__builtin_ia32_ucmpw128_mask:
6319 case X86::BI__builtin_ia32_ucmpd128_mask:
6320 case X86::BI__builtin_ia32_ucmpq128_mask:
6321 case X86::BI__builtin_ia32_ucmpb256_mask:
6322 case X86::BI__builtin_ia32_ucmpw256_mask:
6323 case X86::BI__builtin_ia32_ucmpd256_mask:
6324 case X86::BI__builtin_ia32_ucmpq256_mask:
6325 case X86::BI__builtin_ia32_ucmpb512_mask:
6326 case X86::BI__builtin_ia32_ucmpw512_mask:
6327 case X86::BI__builtin_ia32_ucmpd512_mask:
6328 case X86::BI__builtin_ia32_ucmpq512_mask:
6329 return interp__builtin_ia32_cmp_mask(S, OpPC, Call, BuiltinID,
6330 /*IsUnsigned=*/true);
6331
6332 case X86::BI__builtin_ia32_vpshufbitqmb128_mask:
6333 case X86::BI__builtin_ia32_vpshufbitqmb256_mask:
6334 case X86::BI__builtin_ia32_vpshufbitqmb512_mask:
6336
6337 case X86::BI__builtin_ia32_pslldqi128_byteshift:
6338 case X86::BI__builtin_ia32_pslldqi256_byteshift:
6339 case X86::BI__builtin_ia32_pslldqi512_byteshift:
6340 // These SLLDQ intrinsics always operate on byte elements (8 bits).
6341 // The lane width is hardcoded to 16 to match the SIMD register size,
6342 // but the algorithm processes one byte per iteration,
6343 // so APInt(8, ...) is correct and intentional.
6345 S, OpPC, Call,
6346 [](unsigned DstIdx, unsigned Shift) -> std::pair<unsigned, int> {
6347 unsigned LaneBase = (DstIdx / 16) * 16;
6348 unsigned LaneIdx = DstIdx % 16;
6349 if (LaneIdx < Shift)
6350 return std::make_pair(0, -1);
6351
6352 return std::make_pair(0,
6353 static_cast<int>(LaneBase + LaneIdx - Shift));
6354 });
6355
6356 case X86::BI__builtin_ia32_psrldqi128_byteshift:
6357 case X86::BI__builtin_ia32_psrldqi256_byteshift:
6358 case X86::BI__builtin_ia32_psrldqi512_byteshift:
6359 // These SRLDQ intrinsics always operate on byte elements (8 bits).
6360 // The lane width is hardcoded to 16 to match the SIMD register size,
6361 // but the algorithm processes one byte per iteration,
6362 // so APInt(8, ...) is correct and intentional.
6364 S, OpPC, Call,
6365 [](unsigned DstIdx, unsigned Shift) -> std::pair<unsigned, int> {
6366 unsigned LaneBase = (DstIdx / 16) * 16;
6367 unsigned LaneIdx = DstIdx % 16;
6368 if (LaneIdx + Shift < 16)
6369 return std::make_pair(0,
6370 static_cast<int>(LaneBase + LaneIdx + Shift));
6371
6372 return std::make_pair(0, -1);
6373 });
6374
6375 case X86::BI__builtin_ia32_palignr128:
6376 case X86::BI__builtin_ia32_palignr256:
6377 case X86::BI__builtin_ia32_palignr512:
6379 S, OpPC, Call, [](unsigned DstIdx, unsigned Shift) {
6380 // Default to -1 → zero-fill this destination element
6381 unsigned VecIdx = 1;
6382 int ElemIdx = -1;
6383
6384 int Lane = DstIdx / 16;
6385 int Offset = DstIdx % 16;
6386
6387 // Elements come from VecB first, then VecA after the shift boundary
6388 unsigned ShiftedIdx = Offset + (Shift & 0xFF);
6389 if (ShiftedIdx < 16) { // from VecB
6390 ElemIdx = ShiftedIdx + (Lane * 16);
6391 } else if (ShiftedIdx < 32) { // from VecA
6392 VecIdx = 0;
6393 ElemIdx = (ShiftedIdx - 16) + (Lane * 16);
6394 }
6395
6396 return std::pair<unsigned, int>{VecIdx, ElemIdx};
6397 });
6398
6399 case X86::BI__builtin_ia32_alignd128:
6400 case X86::BI__builtin_ia32_alignd256:
6401 case X86::BI__builtin_ia32_alignd512:
6402 case X86::BI__builtin_ia32_alignq128:
6403 case X86::BI__builtin_ia32_alignq256:
6404 case X86::BI__builtin_ia32_alignq512: {
6405 unsigned NumElems = Call->getType()->castAs<VectorType>()->getNumElements();
6407 S, OpPC, Call, [NumElems](unsigned DstIdx, unsigned Shift) {
6408 unsigned Imm = Shift & 0xFF;
6409 unsigned EffectiveShift = Imm & (NumElems - 1);
6410 unsigned SourcePos = DstIdx + EffectiveShift;
6411 unsigned VecIdx = SourcePos < NumElems ? 1u : 0u;
6412 unsigned ElemIdx = SourcePos & (NumElems - 1);
6413 return std::pair<unsigned, int>{VecIdx, static_cast<int>(ElemIdx)};
6414 });
6415 }
6416
6417 case clang::X86::BI__builtin_ia32_minps:
6418 case clang::X86::BI__builtin_ia32_minpd:
6419 case clang::X86::BI__builtin_ia32_minph128:
6420 case clang::X86::BI__builtin_ia32_minph256:
6421 case clang::X86::BI__builtin_ia32_minps256:
6422 case clang::X86::BI__builtin_ia32_minpd256:
6423 case clang::X86::BI__builtin_ia32_minps512:
6424 case clang::X86::BI__builtin_ia32_minpd512:
6425 case clang::X86::BI__builtin_ia32_minph512:
6427 S, OpPC, Call,
6428 [](const APFloat &A, const APFloat &B,
6429 std::optional<APSInt>) -> std::optional<APFloat> {
6430 if (A.isNaN() || A.isInfinity() || A.isDenormal() || B.isNaN() ||
6431 B.isInfinity() || B.isDenormal())
6432 return std::nullopt;
6433 if (A.isZero() && B.isZero())
6434 return B;
6435 return llvm::minimum(A, B);
6436 });
6437
6438 case clang::X86::BI__builtin_ia32_minss:
6439 case clang::X86::BI__builtin_ia32_minsd:
6441 S, OpPC, Call,
6442 [](const APFloat &A, const APFloat &B,
6443 std::optional<APSInt> RoundingMode) -> std::optional<APFloat> {
6444 return EvalScalarMinMaxFp(A, B, RoundingMode, /*IsMin=*/true);
6445 },
6446 /*IsScalar=*/true);
6447
6448 case clang::X86::BI__builtin_ia32_minsd_round_mask:
6449 case clang::X86::BI__builtin_ia32_minss_round_mask:
6450 case clang::X86::BI__builtin_ia32_minsh_round_mask:
6451 case clang::X86::BI__builtin_ia32_maxsd_round_mask:
6452 case clang::X86::BI__builtin_ia32_maxss_round_mask:
6453 case clang::X86::BI__builtin_ia32_maxsh_round_mask: {
6454 bool IsMin = BuiltinID == clang::X86::BI__builtin_ia32_minsd_round_mask ||
6455 BuiltinID == clang::X86::BI__builtin_ia32_minss_round_mask ||
6456 BuiltinID == clang::X86::BI__builtin_ia32_minsh_round_mask;
6458 S, OpPC, Call,
6459 [IsMin](const APFloat &A, const APFloat &B,
6460 std::optional<APSInt> RoundingMode) -> std::optional<APFloat> {
6461 return EvalScalarMinMaxFp(A, B, RoundingMode, IsMin);
6462 });
6463 }
6464
6465 case clang::X86::BI__builtin_ia32_maxps:
6466 case clang::X86::BI__builtin_ia32_maxpd:
6467 case clang::X86::BI__builtin_ia32_maxph128:
6468 case clang::X86::BI__builtin_ia32_maxph256:
6469 case clang::X86::BI__builtin_ia32_maxps256:
6470 case clang::X86::BI__builtin_ia32_maxpd256:
6471 case clang::X86::BI__builtin_ia32_maxps512:
6472 case clang::X86::BI__builtin_ia32_maxpd512:
6473 case clang::X86::BI__builtin_ia32_maxph512:
6475 S, OpPC, Call,
6476 [](const APFloat &A, const APFloat &B,
6477 std::optional<APSInt>) -> std::optional<APFloat> {
6478 if (A.isNaN() || A.isInfinity() || A.isDenormal() || B.isNaN() ||
6479 B.isInfinity() || B.isDenormal())
6480 return std::nullopt;
6481 if (A.isZero() && B.isZero())
6482 return B;
6483 return llvm::maximum(A, B);
6484 });
6485
6486 case clang::X86::BI__builtin_ia32_maxss:
6487 case clang::X86::BI__builtin_ia32_maxsd:
6489 S, OpPC, Call,
6490 [](const APFloat &A, const APFloat &B,
6491 std::optional<APSInt> RoundingMode) -> std::optional<APFloat> {
6492 return EvalScalarMinMaxFp(A, B, RoundingMode, /*IsMin=*/false);
6493 },
6494 /*IsScalar=*/true);
6495
6496 default:
6497 S.FFDiag(S.Current->getLocation(OpPC),
6498 diag::note_invalid_subexpr_in_const_expr)
6499 << S.Current->getRange(OpPC);
6500
6501 return false;
6502 }
6503
6504 llvm_unreachable("Unhandled builtin ID");
6505}
6506
6508 ArrayRef<int64_t> ArrayIndices, int64_t &IntResult) {
6511 unsigned N = E->getNumComponents();
6512 assert(N > 0);
6513
6514 unsigned ArrayIndex = 0;
6515 QualType CurrentType = E->getTypeSourceInfo()->getType();
6516 for (unsigned I = 0; I != N; ++I) {
6517 const OffsetOfNode &Node = E->getComponent(I);
6518 switch (Node.getKind()) {
6519 case OffsetOfNode::Field: {
6520 const FieldDecl *MemberDecl = Node.getField();
6521 const auto *RD = CurrentType->getAsRecordDecl();
6522 if (!RD || RD->isInvalidDecl())
6523 return false;
6525 unsigned FieldIndex = MemberDecl->getFieldIndex();
6526 assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");
6527 Result +=
6529 CurrentType = MemberDecl->getType().getNonReferenceType();
6530 break;
6531 }
6532 case OffsetOfNode::Array: {
6533 // When generating bytecode, we put all the index expressions as Sint64 on
6534 // the stack.
6535 int64_t Index = ArrayIndices[ArrayIndex];
6536 const ArrayType *AT = S.getASTContext().getAsArrayType(CurrentType);
6537 if (!AT)
6538 return false;
6539 CurrentType = AT->getElementType();
6540 CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType);
6541 Result += Index * ElementSize;
6542 ++ArrayIndex;
6543 break;
6544 }
6545 case OffsetOfNode::Base: {
6546 const CXXBaseSpecifier *BaseSpec = Node.getBase();
6547 if (BaseSpec->isVirtual())
6548 return false;
6549
6550 // Find the layout of the class whose base we are looking into.
6551 const auto *RD = CurrentType->getAsCXXRecordDecl();
6552 if (!RD || RD->isInvalidDecl())
6553 return false;
6555
6556 // Find the base class itself.
6557 CurrentType = BaseSpec->getType();
6558 const auto *BaseRD = CurrentType->getAsCXXRecordDecl();
6559 if (!BaseRD)
6560 return false;
6561
6562 // Add the offset to the base.
6563 Result += RL.getBaseClassOffset(BaseRD);
6564 break;
6565 }
6567 llvm_unreachable("Dependent OffsetOfExpr?");
6568 }
6569 }
6570
6571 IntResult = Result.getQuantity();
6572
6573 return true;
6574}
6575
6577 const Pointer &Ptr, const APSInt &IntValue) {
6578
6579 const Record *R = Ptr.getRecord();
6580 assert(R);
6581 assert(R->getNumFields() == 1);
6582
6583 unsigned FieldOffset = R->getField(0u)->Offset;
6584 const Pointer &FieldPtr = Ptr.atField(FieldOffset);
6585 PrimType FieldT = *S.getContext().classify(FieldPtr.getType());
6586
6587 INT_TYPE_SWITCH(FieldT,
6588 FieldPtr.deref<T>() = T::from(IntValue.getSExtValue()));
6589 FieldPtr.initialize();
6590 return true;
6591}
6592
6593static void zeroAll(Pointer &Dest) {
6594 const Descriptor *Desc = Dest.getFieldDesc();
6595
6596 if (Desc->isPrimitive()) {
6597 TYPE_SWITCH(Desc->getPrimType(), {
6598 Dest.deref<T>().~T();
6599 new (&Dest.deref<T>()) T();
6600 });
6601 return;
6602 }
6603
6604 if (Desc->isRecord()) {
6605 const Record *R = Desc->ElemRecord;
6606 for (const Record::Field &F : R->fields()) {
6607 Pointer FieldPtr = Dest.atField(F.Offset);
6608 zeroAll(FieldPtr);
6609 }
6610 return;
6611 }
6612
6613 if (Desc->isPrimitiveArray()) {
6614 for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
6615 TYPE_SWITCH(Desc->getPrimType(), {
6616 Dest.deref<T>().~T();
6617 new (&Dest.deref<T>()) T();
6618 });
6619 }
6620 return;
6621 }
6622
6623 if (Desc->isCompositeArray()) {
6624 for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
6625 Pointer ElemPtr = Dest.atIndex(I).narrow();
6626 zeroAll(ElemPtr);
6627 }
6628 return;
6629 }
6630}
6631
6632static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
6633 Pointer &Dest, bool Activate);
6634static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,
6635 Pointer &Dest, bool Activate = false) {
6636 [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
6637 const Descriptor *DestDesc = Dest.getFieldDesc();
6638
6639 auto copyField = [&](const Record::Field &F, bool Activate) -> bool {
6640 Pointer DestField = Dest.atField(F.Offset);
6641 if (OptPrimType FT = S.Ctx.classify(F.Decl->getType())) {
6642 TYPE_SWITCH(*FT, {
6643 DestField.deref<T>() = Src.atField(F.Offset).deref<T>();
6644 if (Src.atField(F.Offset).isInitialized())
6645 DestField.initialize();
6646 if (Activate)
6647 DestField.activate();
6648 });
6649 return true;
6650 }
6651 // Composite field.
6652 return copyComposite(S, OpPC, Src.atField(F.Offset), DestField, Activate);
6653 };
6654
6655 assert(SrcDesc->isRecord());
6656 assert(SrcDesc->ElemRecord == DestDesc->ElemRecord);
6657 const Record *R = DestDesc->ElemRecord;
6658 for (const Record::Field &F : R->fields()) {
6659 if (R->isUnion()) {
6660 // For unions, only copy the active field. Zero all others.
6661 const Pointer &SrcField = Src.atField(F.Offset);
6662 if (SrcField.isActive()) {
6663 if (!copyField(F, /*Activate=*/true))
6664 return false;
6665 } else {
6666 if (!CheckMutable(S, OpPC, Src.atField(F.Offset)))
6667 return false;
6668 Pointer DestField = Dest.atField(F.Offset);
6669 zeroAll(DestField);
6670 }
6671 } else {
6672 if (!copyField(F, Activate))
6673 return false;
6674 }
6675 }
6676
6677 for (const Record::Base &B : R->bases()) {
6678 Pointer DestBase = Dest.atField(B.Offset);
6679 if (!copyRecord(S, OpPC, Src.atField(B.Offset), DestBase, Activate))
6680 return false;
6681 }
6682
6683 Dest.initialize();
6684 return true;
6685}
6686
6687static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
6688 Pointer &Dest, bool Activate = false) {
6689 assert(Src.isLive() && Dest.isLive());
6690
6691 [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
6692 const Descriptor *DestDesc = Dest.getFieldDesc();
6693
6694 assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive());
6695
6696 if (DestDesc->isPrimitiveArray()) {
6697 assert(SrcDesc->isPrimitiveArray());
6698 assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
6699 PrimType ET = DestDesc->getPrimType();
6700 for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
6701 Pointer DestElem = Dest.atIndex(I);
6702 TYPE_SWITCH(ET, {
6703 DestElem.deref<T>() = Src.elem<T>(I);
6704 DestElem.initialize();
6705 });
6706 }
6707 return true;
6708 }
6709
6710 if (DestDesc->isCompositeArray()) {
6711 assert(SrcDesc->isCompositeArray());
6712 assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
6713 for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
6714 const Pointer &SrcElem = Src.atIndex(I).narrow();
6715 Pointer DestElem = Dest.atIndex(I).narrow();
6716 if (!copyComposite(S, OpPC, SrcElem, DestElem, Activate))
6717 return false;
6718 }
6719 return true;
6720 }
6721
6722 if (DestDesc->isRecord())
6723 return copyRecord(S, OpPC, Src, Dest, Activate);
6724 return Invalid(S, OpPC);
6725}
6726
6727bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {
6728 if (!Src.isBlockPointer() || Src.getFieldDesc()->isPrimitive())
6729 return false;
6730 if (!Dest.isBlockPointer() || Dest.getFieldDesc()->isPrimitive())
6731 return false;
6732
6733 return copyComposite(S, OpPC, Src, Dest);
6734}
6735
6736} // namespace interp
6737} // namespace clang
#define V(N, I)
Defines enum values for all the target-independent builtin functions.
llvm::APSInt APSInt
Definition Compiler.cpp:24
GCCTypeClass
Values returned by __builtin_classify_type, chosen to match the values produced by GCC's builtin.
std::optional< APFloat > EvalScalarMinMaxFp(const APFloat &A, const APFloat &B, std::optional< APSInt > RoundingMode, bool IsMin)
CharUnits GetAlignOfExpr(const ASTContext &Ctx, const Expr *E, UnaryExprOrTypeTrait ExprKind)
GCCTypeClass EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts)
EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way as GCC.
static bool isOneByteCharacterType(QualType T)
static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal)
Attempts to detect a user writing into a piece of memory that's impossible to figure out the size of ...
uint8_t GFNIMul(uint8_t AByte, uint8_t BByte)
uint8_t GFNIAffine(uint8_t XByte, const APInt &AQword, const APSInt &Imm, bool Inverse)
APSInt NormalizeRotateAmount(const APSInt &Value, const APSInt &Amount)
TokenType getType() const
Returns the token's type, e.g.
#define X(type, name)
Definition Value.h:97
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
#define FIXED_SIZE_INT_TYPE_SWITCH(Expr, B)
Definition PrimType.h:263
#define INT_TYPE_SWITCH_NO_BOOL(Expr, B)
Definition PrimType.h:279
#define INT_TYPE_SWITCH(Expr, B)
Definition PrimType.h:244
#define TYPE_SWITCH(Expr, B)
Definition PrimType.h:223
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static QualType getPointeeType(const MemRegion *R)
Enumerates target-specific builtins in their own namespaces within namespace clang.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
CharUnits & getLValueOffset()
Definition APValue.cpp:1025
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:227
CharUnits getTypeAlignInChars(QualType T) const
Return the ABI-specified alignment of a (complete) type T, in characters.
unsigned getIntWidth(QualType T) const
const llvm::fltSemantics & getFloatTypeSemantics(QualType T) const
Return the APFloat 'semantics' for the specified scalar floating point type.
CanQualType FloatTy
const ASTRecordLayout & getASTRecordLayout(const RecordDecl *D) const
Get or compute information about the layout of the specified record (struct/union/class) D,...
Builtin::Context & BuiltinInfo
Definition ASTContext.h:807
QualType getConstantArrayType(QualType EltTy, const llvm::APInt &ArySize, const Expr *SizeExpr, ArraySizeModifier ASM, unsigned IndexTypeQuals) const
Return the unique reference to the type for a constant array of the specified element type.
const LangOptions & getLangOpts() const
Definition ASTContext.h:959
CanQualType CharTy
CharUnits getDeclAlign(const Decl *D, bool ForAlignof=false) const
Return a conservative estimate of the alignment of the specified decl D.
QualType getWCharType() const
Return the unique wchar_t type available in C++ (and available as __wchar_t as a Microsoft extension)...
const ArrayType * getAsArrayType(QualType T) const
Type Query functions.
uint64_t getTypeSize(QualType T) const
Return the size of the specified (complete) type T, in bits.
CharUnits getTypeSizeInChars(QualType T) const
Return the size of the specified (complete) type T, in characters.
void recordOffsetOfEvaluation(const OffsetOfExpr *E)
QualType getSizeType() const
Return the unique type for "size_t" (C99 7.17), defined in <stddef.h>.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:924
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
static bool hasSameUnqualifiedType(QualType T1, QualType T2)
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
CanQualType HalfTy
uint64_t getCharWidth() const
Return the size of the character type, in bits.
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
CharUnits getVBaseClassOffset(const CXXRecordDecl *VBase) const
getVBaseClassOffset - Get the offset, in chars, for the given base class.
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition TypeBase.h:3777
QualType getElementType() const
Definition TypeBase.h:3789
std::string getQuotedName(unsigned ID) const
Return the identifier name for the specified builtin inside single quotes for a diagnostic,...
Definition Builtins.cpp:85
bool isConstantEvaluated(unsigned ID) const
Return true if this function can be constant evaluated by Clang frontend.
Definition Builtins.h:459
Represents a base class of a C++ class.
Definition DeclCXX.h:146
bool isVirtual() const
Determines whether the base class is a virtual base class (or not).
Definition DeclCXX.h:203
QualType getType() const
Retrieves the type of the base class.
Definition DeclCXX.h:249
CallExpr - Represents a function call (C99 6.5.2.2, C++ [expr.call]).
Definition Expr.h:2946
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3150
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
Definition CharUnits.h:207
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition CharUnits.h:122
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
Definition CharUnits.h:201
static unsigned getMaxSizeBits(const ASTContext &Context)
Determine the maximum number of active bits that an array's size can require, which limits the maximu...
Definition Type.cpp:291
This represents one expression.
Definition Expr.h:112
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:277
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3178
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3263
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3414
Represents a function declaration or definition.
Definition Decl.h:2018
One of these records is kept for each identifier that is lexed.
bool isStr(const char(&Str)[StrLen]) const
Return true if this is the identifier for the specified string.
std::optional< llvm::AllocTokenMode > AllocTokenMode
The allocation token mode.
std::optional< uint64_t > AllocTokenMax
Maximum number of allocation tokens (0 = target SIZE_MAX), nullopt if none set (use target SIZE_MAX).
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
Definition Expr.h:2530
const OffsetOfNode & getComponent(unsigned Idx) const
Definition Expr.h:2577
TypeSourceInfo * getTypeSourceInfo() const
Definition Expr.h:2570
unsigned getNumComponents() const
Definition Expr.h:2585
Helper class for OffsetOfExpr.
Definition Expr.h:2424
FieldDecl * getField() const
For a field offsetof node, returns the field.
Definition Expr.h:2488
@ Array
An index into an array.
Definition Expr.h:2429
@ Identifier
A field in a dependent type, known only by its name.
Definition Expr.h:2433
@ Field
A field.
Definition Expr.h:2431
@ Base
An implicit indirection through a C++ base class, when the field found is in a base class.
Definition Expr.h:2436
Kind getKind() const
Determine what kind of offsetof node this is.
Definition Expr.h:2478
CXXBaseSpecifier * getBase() const
For a base class node, returns the base specifier.
Definition Expr.h:2498
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3383
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition Type.cpp:2961
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8436
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition TypeBase.h:8621
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:343
unsigned getMaxAtomicInlineWidth() const
Return the maximum width lock-free atomic operation which can be inlined given the supported features...
Definition TargetInfo.h:859
bool isBigEndian() const
virtual int getEHDataRegisterNumber(unsigned RegNo) const
Return the register number that __builtin_eh_return_regno would return with the specified argument.
virtual bool isNan2008() const
Returns true if NaN encoding is IEEE 754-2008.
QualType getType() const
Return the type wrapped by this type source info.
Definition TypeBase.h:8418
bool isBooleanType() const
Definition TypeBase.h:9176
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2289
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
Definition Type.cpp:2355
CXXRecordDecl * getAsCXXRecordDecl() const
Retrieves the CXXRecordDecl that this type refers to, either because the type is a RecordType or beca...
Definition Type.h:26
RecordDecl * getAsRecordDecl() const
Retrieves the RecordDecl this type refers to.
Definition Type.h:41
bool isPointerType() const
Definition TypeBase.h:8673
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9083
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9333
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:789
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2527
bool isVectorType() const
Definition TypeBase.h:8812
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2405
bool isFloatingType() const
Definition Type.cpp:2389
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9266
Represent the declaration of a variable (in which case it is an lvalue) a function (in which case it ...
Definition Decl.h:712
QualType getType() const
Definition Decl.h:723
Represents a variable declaration or definition.
Definition Decl.h:924
Represents a GCC generic vector type.
Definition TypeBase.h:4230
unsigned getNumElements() const
Definition TypeBase.h:4245
QualType getElementType() const
Definition TypeBase.h:4244
A memory block, either on the stack or in the heap.
Definition InterpBlock.h:44
const Descriptor * getDescriptor() const
Returns the block's descriptor.
Definition InterpBlock.h:73
bool isDynamic() const
Definition InterpBlock.h:83
Wrapper around boolean types.
Definition Boolean.h:25
static Boolean from(T Value)
Definition Boolean.h:96
Pointer into the code segment.
Definition Source.h:30
const LangOptions & getLangOpts() const
Returns the language options.
Definition Context.cpp:374
OptPrimType classify(QualType T) const
Classifies a type.
Definition Context.cpp:408
unsigned getEvalID() const
Definition Context.h:166
Manages dynamic memory allocations done during bytecode interpretation.
bool deallocate(const Expr *Source, const Block *BlockToDelete, InterpState &S)
Deallocate the given source+block combination.
std::optional< Form > getAllocationForm(const Expr *Source) const
Checks whether the allocation done at the given source is an array allocation.
Block * allocate(const Descriptor *D, unsigned EvalID, Form AllocForm)
Allocate ONE element of the given descriptor.
If a Floating is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Definition Floating.h:35
void copy(const APFloat &F)
Definition Floating.h:123
llvm::FPClassTest classify() const
Definition Floating.h:154
bool isSignaling() const
Definition Floating.h:149
bool isNormal() const
Definition Floating.h:152
ComparisonCategoryResult compare(const Floating &RHS) const
Definition Floating.h:157
bool isZero() const
Definition Floating.h:144
bool isNegative() const
Definition Floating.h:143
bool isFinite() const
Definition Floating.h:151
bool isDenormal() const
Definition Floating.h:153
APFloat::fltCategory getCategory() const
Definition Floating.h:155
APFloat getAPFloat() const
Definition Floating.h:64
Base class for stack frames, shared between VM and walker.
Definition Frame.h:25
virtual const FunctionDecl * getCallee() const =0
Returns the called function's declaration.
If an IntegralAP is constructed from Memory, it DOES NOT OWN THAT MEMORY.
Definition IntegralAP.h:36
Frame storing local variables.
Definition InterpFrame.h:27
const Expr * getExpr(CodePtr PC) const
InterpFrame * Caller
The frame of the previous function.
Definition InterpFrame.h:30
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
CodePtr getRetPC() const
Returns the return address of the frame.
SourceLocation getLocation(CodePtr PC) const
SourceRange getRange(CodePtr PC) const
unsigned getDepth() const
const FunctionDecl * getCallee() const override
Returns the caller.
Stack frame storing temporaries and parameters.
Definition InterpStack.h:25
T pop()
Returns the value from the top of the stack and removes it.
Definition InterpStack.h:39
void push(Tys &&...Args)
Constructs a value in place on the top of the stack.
Definition InterpStack.h:33
void discard()
Discards the top value from the stack.
Definition InterpStack.h:50
T & peek() const
Returns a reference to the value on the top of the stack.
Definition InterpStack.h:62
Interpreter context.
Definition InterpState.h:36
Context & getContext() const
Definition InterpState.h:74
DynamicAllocator & getAllocator()
Definition InterpState.h:78
Context & Ctx
Interpreter Context.
Floating allocFloat(const llvm::fltSemantics &Sem)
llvm::SmallVector< const Block * > InitializingBlocks
List of blocks we're currently running either constructors or destructors for.
InterpStack & Stk
Temporary stack.
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
InterpFrame * Current
The current frame.
T allocAP(unsigned BitWidth)
StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const
Program & P
Reference to the module containing all bytecode.
PrimType value_or(PrimType PT) const
Definition PrimType.h:88
A pointer to a memory block, live or dead.
Definition Pointer.h:97
Pointer narrow() const
Restricts the scope of an array element pointer.
Definition Pointer.h:194
Pointer stripBaseCasts() const
Strip base casts from this Pointer.
Definition Pointer.h:797
bool isInitialized() const
Checks if an object was initialized.
Definition Pointer.cpp:443
bool isElementInitialized(unsigned Index) const
Like isInitialized(), but for primitive arrays.
Definition Pointer.cpp:465
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
Definition Pointer.h:162
bool isDummy() const
Checks if the pointer points to a dummy value.
Definition Pointer.h:562
int64_t getIndex() const
Returns the index into an array.
Definition Pointer.h:627
bool isActive() const
Checks if the object is active.
Definition Pointer.h:551
Pointer atField(unsigned Off) const
Creates a pointer to a field.
Definition Pointer.h:179
T & deref() const
Dereferences the pointer, if it's live.
Definition Pointer.h:687
unsigned getNumElems() const
Returns the number of elements.
Definition Pointer.h:611
Pointer getArray() const
Returns the parent array.
Definition Pointer.h:326
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition Pointer.h:426
void activate() const
Activats a field.
Definition Pointer.cpp:624
bool isIntegralPointer() const
Definition Pointer.h:480
QualType getType() const
Returns the type of the innermost field.
Definition Pointer.h:346
bool isArrayElement() const
Checks if the pointer points to an array.
Definition Pointer.h:432
void initializeAllElements() const
Initialize all elements of a primitive array at once.
Definition Pointer.cpp:583
bool isLive() const
Checks if the pointer is live.
Definition Pointer.h:278
bool inArray() const
Checks if the innermost field is an array.
Definition Pointer.h:408
T & elem(unsigned I) const
Dereferences the element at index I.
Definition Pointer.h:703
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition Pointer.h:317
std::string toDiagnosticString(const ASTContext &Ctx) const
Converts the pointer to a string usable in diagnostics.
Definition Pointer.cpp:433
bool isZero() const
Checks if the pointer is null.
Definition Pointer.h:264
bool isRoot() const
Pointer points directly to a block.
Definition Pointer.h:448
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition Pointer.h:292
static bool pointToSameBlock(const Pointer &A, const Pointer &B)
Checks if both given pointers point to the same block.
Definition Pointer.cpp:706
APValue toAPValue(const ASTContext &ASTCtx) const
Converts the pointer to an APValue.
Definition Pointer.cpp:173
bool isOnePastEnd() const
Checks if the index is one past end.
Definition Pointer.h:644
uint64_t getIntegerRepresentation() const
Definition Pointer.h:149
const FieldDecl * getField() const
Returns the field information.
Definition Pointer.h:492
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
Definition Pointer.h:229
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
Definition Pointer.h:666
bool isBlockPointer() const
Definition Pointer.h:479
const Block * block() const
Definition Pointer.h:617
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
Definition Pointer.h:336
bool isVirtualBaseClass() const
Definition Pointer.h:558
bool isBaseClass() const
Checks if a structure is a base class.
Definition Pointer.h:557
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
Definition Pointer.h:455
Lifetime getLifetime() const
Definition Pointer.h:761
void initialize() const
Initializes a field.
Definition Pointer.cpp:535
bool isField() const
Checks if the item is a field in an object.
Definition Pointer.h:284
const Record * getRecord() const
Returns the record descriptor of a class.
Definition Pointer.h:485
Descriptor * createDescriptor(const DeclTy &D, PrimType T, const Type *SourceTy=nullptr, Descriptor::MetadataSize MDSize=std::nullopt, bool IsConst=false, bool IsTemporary=false, bool IsMutable=false, bool IsVolatile=false)
Creates a descriptor for a primitive type.
Definition Program.h:121
Structure/Class descriptor.
Definition Record.h:25
const RecordDecl * getDecl() const
Returns the underlying declaration.
Definition Record.h:65
unsigned getNumFields() const
Definition Record.h:94
Describes the statement/declaration an opcode was generated from.
Definition Source.h:74
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
Definition State.cpp:63
Expr::EvalStatus & getEvalStatus() const
Definition State.h:92
DiagnosticBuilder report(SourceLocation Loc, diag::kind DiagId)
Directly reports a diagnostic message.
Definition State.cpp:74
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
Definition State.cpp:21
ASTContext & getASTContext() const
Definition State.h:93
OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation does not produce a C++11 core constant expression.
Definition State.cpp:42
const LangOptions & getLangOpts() const
Definition State.h:94
bool checkingPotentialConstantExpression() const
Are we checking whether the expression is a potential constant expression?
Definition State.h:120
Defines the clang::TargetInfo interface.
bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E, OSLogBufferLayout &layout)
Definition OSLog.cpp:192
std::optional< llvm::AllocTokenMetadata > getAllocTokenMetadata(QualType T, const ASTContext &Ctx)
Get the information required for construction of an allocation token ID.
QualType inferPossibleType(const CallExpr *E, const ASTContext &Ctx, const CastExpr *CastE)
Infer the possible allocated type from an allocation call expression.
static bool isNoopBuiltin(unsigned ID)
static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static bool interp__builtin_ia32_shuffle_generic(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< std::pair< unsigned, int >(unsigned, const APInt &)> GetSourceIndex)
static bool interp__builtin_ia32_phminposuw(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static void assignIntegral(InterpState &S, const Pointer &Dest, PrimType ValueT, const APSInt &Value)
static bool interp_builtin_ia32_gfni_affine(InterpState &S, CodePtr OpPC, const CallExpr *Call, bool Inverse)
bool readPointerToBuffer(const Context &Ctx, const Pointer &FromPtr, BitcastBuffer &Buffer, bool ReturnOnUninit)
static Floating abs(InterpState &S, const Floating &In)
static bool interp__builtin_x86_extract_vector(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, bool IsNumBuiltin)
static bool interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned BuiltinID)
static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_elementwise_triop(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< APInt(const APSInt &, const APSInt &, const APSInt &)> Fn)
static bool interp__builtin_assume(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
bool CheckNewDeleteForms(InterpState &S, CodePtr OpPC, DynamicAllocator::Form AllocForm, DynamicAllocator::Form DeleteForm, const Descriptor *D, const Expr *NewExpr)
Diagnose mismatched new[]/delete or new/delete[] pairs.
Definition Interp.cpp:1119
static bool interp__builtin_ia32_shift_with_count(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< APInt(const APInt &, uint64_t)> ShiftOp, llvm::function_ref< APInt(const APInt &, unsigned)> OverflowOp)
static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
Defined as __builtin_isnan(...), to accommodate the fact that it can take a float,...
static llvm::RoundingMode getRoundingMode(FPOptions FPO)
static bool interp__builtin_ia32_crc32(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned DataBytes)
static bool interp__builtin_elementwise_countzeroes(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinID)
Can be called with an integer or vector as the first and only parameter.
bool Call(InterpState &S, CodePtr OpPC, const Function *Func, uint32_t VarArgSize)
Definition Interp.cpp:1747
static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, bool IsNumBuiltin)
bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, const APSInt &IntValue)
Sets the given integral value to the pointer, which is of a std::{weak,partial,strong}...
static bool interp__builtin_elementwise_fp_binop(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< std::optional< APFloat >(const APFloat &, const APFloat &, std::optional< APSInt > RoundingMode)> Fn, bool IsScalar=false)
static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC, const InterpFrame *Frame)
static bool interp__builtin_ia32_vpconflict(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned ID)
static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinOp)
bool __atomic_always_lock_free(size_t, void const volatile*) bool __atomic_is_lock_free(size_t,...
static llvm::APSInt convertBoolVectorToInt(const Pointer &Val)
static bool interp__builtin_move(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_clz(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinOp)
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
Definition Interp.cpp:590
static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinOp)
__builtin_is_aligned() __builtin_align_up() __builtin_align_down() The first parameter is either an i...
static bool interp__builtin_ia32_addsub(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static bool Activate(InterpState &S, CodePtr OpPC)
Definition Interp.h:2154
static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinOp)
(CarryIn, LHS, RHS, Result)
static bool popToUInt64(const InterpState &S, const Expr *E, uint64_t &Out)
static bool isOneByteCharacterType(QualType T)
Determine if T is a character type for which we guarantee that sizeof(T) == 1.
static bool convertDoubleToFloatStrict(APFloat Src, Floating &Dst, InterpState &S, const Expr *DiagExpr)
static unsigned computePointerOffset(const ASTContext &ASTCtx, const Pointer &Ptr)
Compute the byte offset of Ptr in the full declaration.
static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned ID)
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a value can be loaded from a block.
Definition Interp.cpp:791
static bool interp__builtin_ia32_cmp_mask(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID, bool IsUnsigned)
static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned BuiltinOp)
static bool isReadable(const Pointer &P)
Check for common reasons a pointer can't be read from, which are usually not diagnosed in a builtin f...
static bool interp__builtin_inf(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_vec_ext(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
static bool interp__builtin_ia32_dbpsadbw(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static bool interp__builtin_ia32_test_op(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< bool(const APInt &A, const APInt &B)> Fn)
static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, bool CheckSign, const CallExpr *Call)
static bool interp__builtin_os_log_format_buffer_size(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, ArrayRef< int64_t > ArrayIndices, int64_t &IntResult)
Interpret an offsetof operation.
static bool interp__builtin_x86_insert_subvector(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
Definition Interp.cpp:513
static bool pointsToLastObject(const Pointer &Ptr)
Does Ptr point to the last subobject?
static bool interp__builtin_select(InterpState &S, CodePtr OpPC, const CallExpr *Call)
AVX512 predicated move: "Result = Mask[] ? LHS[] : RHS[]".
llvm::APFloat APFloat
Definition Floating.h:27
static void discard(InterpStack &Stk, PrimType T)
static bool interp__builtin_select_scalar(InterpState &S, const CallExpr *Call)
Scalar variant of AVX512 predicated select: Result[i] = (Mask bit 0) ?
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
Definition Interp.cpp:412
static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
Five int values followed by one floating value.
static bool interp__builtin_abs(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp_floating_comparison(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
static bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue)
llvm::APInt APInt
Definition FixedPoint.h:19
static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest, bool Activate)
static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest, bool Activate=false)
static bool interp__builtin_c11_atomic_is_lock_free(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
bool __c11_atomic_is_lock_free(size_t)
static void zeroAll(Pointer &Dest)
static bool interp__builtin_elementwise_int_binop(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< APInt(const APSInt &, const APSInt &)> Fn)
static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_arithmetic_fence(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_x86_extract_vector_masked(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
static bool interp__builtin_ia32_cvt_mask2vec(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
PrimType
Enumeration of the primitive types of the VM.
Definition PrimType.h:34
static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call, uint32_t BuiltinID)
Interpret a builtin function.
static bool interp__builtin_expect(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_vec_set(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
static bool interp__builtin_complex(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
__builtin_complex(Float A, float B);
static bool evalICmpImm(uint8_t Imm, const APSInt &A, const APSInt &B, bool IsUnsigned)
bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK)
Checks if a pointer is a dummy pointer.
Definition Interp.cpp:1181
static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
__builtin_assume_aligned(Ptr, Alignment[, ExtraOffset])
static bool interp__builtin_ia32_cvt_vec2mask(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
static bool interp__builtin_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_memchr(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
static bool interp__builtin_ia32_pmul(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< APInt(const APSInt &, const APSInt &, const APSInt &, const APSInt &)> Fn)
static bool interp__builtin_x86_pack(InterpState &S, CodePtr, const CallExpr *E, llvm::function_ref< APInt(const APSInt &)> PackFn)
static void pushInteger(InterpState &S, const APSInt &Val, QualType QT)
Pushes Val on the stack as the type given by QT.
static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned ID)
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
Definition Interp.cpp:404
static bool interp__builtin_elementwise_abs(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinID)
static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC, const InterpFrame *Frame)
static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
bool Error(InterpState &S, CodePtr OpPC)
Do nothing and just abort execution.
Definition Interp.h:3590
static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
static bool interp__builtin_ia32_movmsk_op(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned ID)
static bool popToAPSInt(InterpStack &Stk, PrimType T, APSInt &Out)
static bool interp_builtin_horizontal_fp_binop(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< APFloat(const APFloat &, const APFloat &, llvm::RoundingMode)> Fn)
static bool interp__builtin_ia32_pclmulqdq(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static bool interp__builtin_elementwise_triop_fp(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< APFloat(const APFloat &, const APFloat &, const APFloat &, llvm::RoundingMode)> Fn)
static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_object_size(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinOp)
Three integral values followed by a pointer (lhs, rhs, carry, carryOut).
bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems)
static bool interp__builtin_scalar_fp_round_mask_binop(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< std::optional< APFloat >(const APFloat &, const APFloat &, std::optional< APSInt >)> Fn)
static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinID)
static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static std::optional< unsigned > computeFullDescSize(const ASTContext &ASTCtx, const Descriptor *Desc)
static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
First parameter to __builtin_isfpclass is the floating value, the second one is an integral value.
static bool interp__builtin_ia32_vcvtps2ph(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_ia32_multishiftqb(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static bool interp__builtin_ia32_shufbitqmb_mask(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static bool interp__builtin_nan(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, bool Signaling)
bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest)
Copy the contents of Src into Dest.
static bool interp__builtin_elementwise_int_unaryop(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< APInt(const APSInt &)> Fn)
constexpr bool isIntegerType(PrimType T)
Definition PrimType.h:53
static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_infer_alloc_token(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
UnsignedOrNone evaluateBuiltinObjectSize(const ASTContext &ASTCtx, unsigned Kind, Pointer &Ptr)
static bool interp_builtin_horizontal_int_binop(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< APInt(const APSInt &, const APSInt &)> Fn)
static bool interp__builtin_ia32_cvtsd2ss(InterpState &S, CodePtr OpPC, const CallExpr *Call, bool HasRoundingMask)
static void diagnoseNonConstexprBuiltin(InterpState &S, CodePtr OpPC, unsigned ID)
llvm::APSInt APSInt
Definition FixedPoint.h:20
static bool interp__builtin_ia32_gfni_mul(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static QualType getElemType(const Pointer &P)
static bool interp__builtin_ia32_pternlog(InterpState &S, CodePtr OpPC, const CallExpr *Call, bool MaskZ)
static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static void swapBytes(std::byte *M, size_t N)
static bool interp__builtin_ia32_cvtpd2ps(InterpState &S, CodePtr OpPC, const CallExpr *Call, bool IsMasked, bool HasRounding)
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
@ Result
The result type of a method or function.
Definition TypeBase.h:905
@ AK_Read
Definition State.h:29
OptionalUnsigned< unsigned > UnsignedOrNone
U cast(CodeGen::Address addr)
Definition Address.h:327
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition Expr.h:636
Track what bits have been initialized to known values and which ones have indeterminate value.
T deref(Bytes Offset) const
Dereferences the value at the given offset.
std::unique_ptr< std::byte[]> Data
A quantity in bits.
A quantity in bytes.
size_t getQuantity() const
Describes a memory block created by an allocation site.
Definition Descriptor.h:123
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition Descriptor.h:260
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition Descriptor.h:274
QualType getElemQualType() const
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
Definition Descriptor.h:267
const ValueDecl * asValueDecl() const
Definition Descriptor.h:216
static constexpr unsigned MaxArrayElemBytes
Maximum number of bytes to be used for array elements.
Definition Descriptor.h:149
QualType getType() const
const Decl * asDecl() const
Definition Descriptor.h:212
static constexpr MetadataSize InlineDescMD
Definition Descriptor.h:145
unsigned getElemDataSize() const
Returns the element data size, i.e.
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition Descriptor.h:265
const VarDecl * asVarDecl() const
Definition Descriptor.h:220
PrimType getPrimType() const
Definition Descriptor.h:242
bool isRecord() const
Checks if the descriptor is of a record.
Definition Descriptor.h:279
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition Descriptor.h:154
const Expr * asExpr() const
Definition Descriptor.h:213
bool isArray() const
Checks if the descriptor is of an array.
Definition Descriptor.h:277
Mapping from primitive types to their representation.
Definition PrimType.h:150