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