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