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