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