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