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::BI__builtin_ffs:
4417 case Builtin::BI__builtin_ffsl:
4418 case Builtin::BI__builtin_ffsll:
4420 S, OpPC, Call, [](const APSInt &Val) {
4421 return APInt(Val.getBitWidth(),
4422 Val.isZero() ? 0u : Val.countTrailingZeros() + 1u);
4423 });
4424
4425 case Builtin::BIaddressof:
4426 case Builtin::BI__addressof:
4427 case Builtin::BI__builtin_addressof:
4428 assert(isNoopBuiltin(BuiltinID));
4429 return interp__builtin_addressof(S, OpPC, Frame, Call);
4430
4431 case Builtin::BIas_const:
4432 case Builtin::BIforward:
4433 case Builtin::BIforward_like:
4434 case Builtin::BImove:
4435 case Builtin::BImove_if_noexcept:
4436 assert(isNoopBuiltin(BuiltinID));
4437 return interp__builtin_move(S, OpPC, Frame, Call);
4438
4439 case Builtin::BI__builtin_eh_return_data_regno:
4441
4442 case Builtin::BI__builtin_launder:
4443 assert(isNoopBuiltin(BuiltinID));
4444 return true;
4445
4446 case Builtin::BI__builtin_add_overflow:
4447 case Builtin::BI__builtin_sub_overflow:
4448 case Builtin::BI__builtin_mul_overflow:
4449 case Builtin::BI__builtin_sadd_overflow:
4450 case Builtin::BI__builtin_uadd_overflow:
4451 case Builtin::BI__builtin_uaddl_overflow:
4452 case Builtin::BI__builtin_uaddll_overflow:
4453 case Builtin::BI__builtin_usub_overflow:
4454 case Builtin::BI__builtin_usubl_overflow:
4455 case Builtin::BI__builtin_usubll_overflow:
4456 case Builtin::BI__builtin_umul_overflow:
4457 case Builtin::BI__builtin_umull_overflow:
4458 case Builtin::BI__builtin_umulll_overflow:
4459 case Builtin::BI__builtin_saddl_overflow:
4460 case Builtin::BI__builtin_saddll_overflow:
4461 case Builtin::BI__builtin_ssub_overflow:
4462 case Builtin::BI__builtin_ssubl_overflow:
4463 case Builtin::BI__builtin_ssubll_overflow:
4464 case Builtin::BI__builtin_smul_overflow:
4465 case Builtin::BI__builtin_smull_overflow:
4466 case Builtin::BI__builtin_smulll_overflow:
4467 return interp__builtin_overflowop(S, OpPC, Call, BuiltinID);
4468
4469 case Builtin::BI__builtin_addcb:
4470 case Builtin::BI__builtin_addcs:
4471 case Builtin::BI__builtin_addc:
4472 case Builtin::BI__builtin_addcl:
4473 case Builtin::BI__builtin_addcll:
4474 case Builtin::BI__builtin_subcb:
4475 case Builtin::BI__builtin_subcs:
4476 case Builtin::BI__builtin_subc:
4477 case Builtin::BI__builtin_subcl:
4478 case Builtin::BI__builtin_subcll:
4479 return interp__builtin_carryop(S, OpPC, Frame, Call, BuiltinID);
4480
4481 case Builtin::BI__builtin_clz:
4482 case Builtin::BI__builtin_clzl:
4483 case Builtin::BI__builtin_clzll:
4484 case Builtin::BI__builtin_clzs:
4485 case Builtin::BI__builtin_clzg:
4486 case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
4487 case Builtin::BI__lzcnt:
4488 case Builtin::BI__lzcnt64:
4489 return interp__builtin_clz(S, OpPC, Frame, Call, BuiltinID);
4490
4491 case Builtin::BI__builtin_ctz:
4492 case Builtin::BI__builtin_ctzl:
4493 case Builtin::BI__builtin_ctzll:
4494 case Builtin::BI__builtin_ctzs:
4495 case Builtin::BI__builtin_ctzg:
4496 return interp__builtin_ctz(S, OpPC, Frame, Call, BuiltinID);
4497
4498 case Builtin::BI__builtin_elementwise_clzg:
4499 case Builtin::BI__builtin_elementwise_ctzg:
4501 BuiltinID);
4502 case Builtin::BI__builtin_bswapg:
4503 case Builtin::BI__builtin_bswap16:
4504 case Builtin::BI__builtin_bswap32:
4505 case Builtin::BI__builtin_bswap64:
4506 return interp__builtin_bswap(S, OpPC, Frame, Call);
4507
4508 case Builtin::BI__atomic_always_lock_free:
4509 case Builtin::BI__atomic_is_lock_free:
4510 return interp__builtin_atomic_lock_free(S, OpPC, Frame, Call, BuiltinID);
4511
4512 case Builtin::BI__c11_atomic_is_lock_free:
4514
4515 case Builtin::BI__builtin_complex:
4516 return interp__builtin_complex(S, OpPC, Frame, Call);
4517
4518 case Builtin::BI__builtin_is_aligned:
4519 case Builtin::BI__builtin_align_up:
4520 case Builtin::BI__builtin_align_down:
4521 return interp__builtin_is_aligned_up_down(S, OpPC, Frame, Call, BuiltinID);
4522
4523 case Builtin::BI__builtin_assume_aligned:
4524 return interp__builtin_assume_aligned(S, OpPC, Frame, Call);
4525
4526 case clang::X86::BI__builtin_ia32_crc32qi:
4527 return interp__builtin_ia32_crc32(S, OpPC, Frame, Call, 1);
4528 case clang::X86::BI__builtin_ia32_crc32hi:
4529 return interp__builtin_ia32_crc32(S, OpPC, Frame, Call, 2);
4530 case clang::X86::BI__builtin_ia32_crc32si:
4531 return interp__builtin_ia32_crc32(S, OpPC, Frame, Call, 4);
4532 case clang::X86::BI__builtin_ia32_crc32di:
4533 return interp__builtin_ia32_crc32(S, OpPC, Frame, Call, 8);
4534
4535 case clang::X86::BI__builtin_ia32_bextr_u32:
4536 case clang::X86::BI__builtin_ia32_bextr_u64:
4537 case clang::X86::BI__builtin_ia32_bextri_u32:
4538 case clang::X86::BI__builtin_ia32_bextri_u64:
4540 S, OpPC, Call, [](const APSInt &Val, const APSInt &Idx) {
4541 unsigned BitWidth = Val.getBitWidth();
4542 uint64_t Shift = Idx.extractBitsAsZExtValue(8, 0);
4543 uint64_t Length = Idx.extractBitsAsZExtValue(8, 8);
4544 if (Length > BitWidth) {
4545 Length = BitWidth;
4546 }
4547
4548 // Handle out of bounds cases.
4549 if (Length == 0 || Shift >= BitWidth)
4550 return APInt(BitWidth, 0);
4551
4552 uint64_t Result = Val.getZExtValue() >> Shift;
4553 Result &= llvm::maskTrailingOnes<uint64_t>(Length);
4554 return APInt(BitWidth, Result);
4555 });
4556
4557 case clang::X86::BI__builtin_ia32_bzhi_si:
4558 case clang::X86::BI__builtin_ia32_bzhi_di:
4560 S, OpPC, Call, [](const APSInt &Val, const APSInt &Idx) {
4561 unsigned BitWidth = Val.getBitWidth();
4562 uint64_t Index = Idx.extractBitsAsZExtValue(8, 0);
4563 APSInt Result = Val;
4564
4565 if (Index < BitWidth)
4566 Result.clearHighBits(BitWidth - Index);
4567
4568 return Result;
4569 });
4570
4571 case clang::X86::BI__builtin_ia32_ktestcqi:
4572 case clang::X86::BI__builtin_ia32_ktestchi:
4573 case clang::X86::BI__builtin_ia32_ktestcsi:
4574 case clang::X86::BI__builtin_ia32_ktestcdi:
4576 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
4577 return APInt(sizeof(unsigned char) * 8, (~A & B) == 0);
4578 });
4579
4580 case clang::X86::BI__builtin_ia32_ktestzqi:
4581 case clang::X86::BI__builtin_ia32_ktestzhi:
4582 case clang::X86::BI__builtin_ia32_ktestzsi:
4583 case clang::X86::BI__builtin_ia32_ktestzdi:
4585 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
4586 return APInt(sizeof(unsigned char) * 8, (A & B) == 0);
4587 });
4588
4589 case clang::X86::BI__builtin_ia32_kortestcqi:
4590 case clang::X86::BI__builtin_ia32_kortestchi:
4591 case clang::X86::BI__builtin_ia32_kortestcsi:
4592 case clang::X86::BI__builtin_ia32_kortestcdi:
4594 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
4595 return APInt(sizeof(unsigned char) * 8, ~(A | B) == 0);
4596 });
4597
4598 case clang::X86::BI__builtin_ia32_kortestzqi:
4599 case clang::X86::BI__builtin_ia32_kortestzhi:
4600 case clang::X86::BI__builtin_ia32_kortestzsi:
4601 case clang::X86::BI__builtin_ia32_kortestzdi:
4603 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
4604 return APInt(sizeof(unsigned char) * 8, (A | B) == 0);
4605 });
4606
4607 case clang::X86::BI__builtin_ia32_kshiftliqi:
4608 case clang::X86::BI__builtin_ia32_kshiftlihi:
4609 case clang::X86::BI__builtin_ia32_kshiftlisi:
4610 case clang::X86::BI__builtin_ia32_kshiftlidi:
4612 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
4613 unsigned Amt = RHS.getZExtValue() & 0xFF;
4614 if (Amt >= LHS.getBitWidth())
4615 return APInt::getZero(LHS.getBitWidth());
4616 return LHS.shl(Amt);
4617 });
4618
4619 case clang::X86::BI__builtin_ia32_kshiftriqi:
4620 case clang::X86::BI__builtin_ia32_kshiftrihi:
4621 case clang::X86::BI__builtin_ia32_kshiftrisi:
4622 case clang::X86::BI__builtin_ia32_kshiftridi:
4624 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
4625 unsigned Amt = RHS.getZExtValue() & 0xFF;
4626 if (Amt >= LHS.getBitWidth())
4627 return APInt::getZero(LHS.getBitWidth());
4628 return LHS.lshr(Amt);
4629 });
4630
4631 case clang::X86::BI__builtin_ia32_lzcnt_u16:
4632 case clang::X86::BI__builtin_ia32_lzcnt_u32:
4633 case clang::X86::BI__builtin_ia32_lzcnt_u64:
4635 S, OpPC, Call, [](const APSInt &Src) {
4636 return APInt(Src.getBitWidth(), Src.countLeadingZeros());
4637 });
4638
4639 case clang::X86::BI__builtin_ia32_tzcnt_u16:
4640 case clang::X86::BI__builtin_ia32_tzcnt_u32:
4641 case clang::X86::BI__builtin_ia32_tzcnt_u64:
4643 S, OpPC, Call, [](const APSInt &Src) {
4644 return APInt(Src.getBitWidth(), Src.countTrailingZeros());
4645 });
4646
4647 case clang::X86::BI__builtin_ia32_pdep_si:
4648 case clang::X86::BI__builtin_ia32_pdep_di:
4650 S, OpPC, Call, [](const APSInt &Val, const APSInt &Mask) {
4651 unsigned BitWidth = Val.getBitWidth();
4652 APInt Result = APInt::getZero(BitWidth);
4653
4654 for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
4655 if (Mask[I])
4656 Result.setBitVal(I, Val[P++]);
4657 }
4658
4659 return Result;
4660 });
4661
4662 case clang::X86::BI__builtin_ia32_pext_si:
4663 case clang::X86::BI__builtin_ia32_pext_di:
4665 S, OpPC, Call, [](const APSInt &Val, const APSInt &Mask) {
4666 unsigned BitWidth = Val.getBitWidth();
4667 APInt Result = APInt::getZero(BitWidth);
4668
4669 for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
4670 if (Mask[I])
4671 Result.setBitVal(P++, Val[I]);
4672 }
4673
4674 return Result;
4675 });
4676
4677 case clang::X86::BI__builtin_ia32_addcarryx_u32:
4678 case clang::X86::BI__builtin_ia32_addcarryx_u64:
4679 case clang::X86::BI__builtin_ia32_subborrow_u32:
4680 case clang::X86::BI__builtin_ia32_subborrow_u64:
4682 BuiltinID);
4683
4684 case Builtin::BI__builtin_os_log_format_buffer_size:
4686
4687 case Builtin::BI__builtin_ptrauth_string_discriminator:
4689
4690 case Builtin::BI__builtin_infer_alloc_token:
4692
4693 case Builtin::BI__noop:
4694 pushInteger(S, 0, Call->getType());
4695 return true;
4696
4697 case Builtin::BI__builtin_operator_new:
4698 return interp__builtin_operator_new(S, OpPC, Frame, Call);
4699
4700 case Builtin::BI__builtin_operator_delete:
4701 return interp__builtin_operator_delete(S, OpPC, Frame, Call);
4702
4703 case Builtin::BI__arithmetic_fence:
4705
4706 case Builtin::BI__builtin_reduce_add:
4707 case Builtin::BI__builtin_reduce_mul:
4708 case Builtin::BI__builtin_reduce_and:
4709 case Builtin::BI__builtin_reduce_or:
4710 case Builtin::BI__builtin_reduce_xor:
4711 case Builtin::BI__builtin_reduce_min:
4712 case Builtin::BI__builtin_reduce_max:
4713 return interp__builtin_vector_reduce(S, OpPC, Call, BuiltinID);
4714
4715 case Builtin::BI__builtin_elementwise_popcount:
4717 S, OpPC, Call, [](const APSInt &Src) {
4718 return APInt(Src.getBitWidth(), Src.popcount());
4719 });
4720 case Builtin::BI__builtin_elementwise_bitreverse:
4722 S, OpPC, Call, [](const APSInt &Src) { return Src.reverseBits(); });
4723
4724 case Builtin::BI__builtin_elementwise_abs:
4725 return interp__builtin_elementwise_abs(S, OpPC, Frame, Call, BuiltinID);
4726
4727 case Builtin::BI__builtin_memcpy:
4728 case Builtin::BImemcpy:
4729 case Builtin::BI__builtin_wmemcpy:
4730 case Builtin::BIwmemcpy:
4731 case Builtin::BI__builtin_memmove:
4732 case Builtin::BImemmove:
4733 case Builtin::BI__builtin_wmemmove:
4734 case Builtin::BIwmemmove:
4735 return interp__builtin_memcpy(S, OpPC, Frame, Call, BuiltinID);
4736
4737 case Builtin::BI__builtin_memcmp:
4738 case Builtin::BImemcmp:
4739 case Builtin::BI__builtin_bcmp:
4740 case Builtin::BIbcmp:
4741 case Builtin::BI__builtin_wmemcmp:
4742 case Builtin::BIwmemcmp:
4743 return interp__builtin_memcmp(S, OpPC, Frame, Call, BuiltinID);
4744
4745 case Builtin::BImemchr:
4746 case Builtin::BI__builtin_memchr:
4747 case Builtin::BIstrchr:
4748 case Builtin::BI__builtin_strchr:
4749 case Builtin::BIwmemchr:
4750 case Builtin::BI__builtin_wmemchr:
4751 case Builtin::BIwcschr:
4752 case Builtin::BI__builtin_wcschr:
4753 case Builtin::BI__builtin_char_memchr:
4754 return interp__builtin_memchr(S, OpPC, Call, BuiltinID);
4755
4756 case Builtin::BI__builtin_object_size:
4757 case Builtin::BI__builtin_dynamic_object_size:
4758 return interp__builtin_object_size(S, OpPC, Frame, Call);
4759
4760 case Builtin::BI__builtin_is_within_lifetime:
4762
4763 case Builtin::BI__builtin_elementwise_add_sat:
4765 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
4766 return LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS);
4767 });
4768
4769 case Builtin::BI__builtin_elementwise_sub_sat:
4771 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
4772 return LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS);
4773 });
4774 case X86::BI__builtin_ia32_extract128i256:
4775 case X86::BI__builtin_ia32_vextractf128_pd256:
4776 case X86::BI__builtin_ia32_vextractf128_ps256:
4777 case X86::BI__builtin_ia32_vextractf128_si256:
4778 return interp__builtin_x86_extract_vector(S, OpPC, Call, BuiltinID);
4779
4780 case X86::BI__builtin_ia32_extractf32x4_256_mask:
4781 case X86::BI__builtin_ia32_extractf32x4_mask:
4782 case X86::BI__builtin_ia32_extractf32x8_mask:
4783 case X86::BI__builtin_ia32_extractf64x2_256_mask:
4784 case X86::BI__builtin_ia32_extractf64x2_512_mask:
4785 case X86::BI__builtin_ia32_extractf64x4_mask:
4786 case X86::BI__builtin_ia32_extracti32x4_256_mask:
4787 case X86::BI__builtin_ia32_extracti32x4_mask:
4788 case X86::BI__builtin_ia32_extracti32x8_mask:
4789 case X86::BI__builtin_ia32_extracti64x2_256_mask:
4790 case X86::BI__builtin_ia32_extracti64x2_512_mask:
4791 case X86::BI__builtin_ia32_extracti64x4_mask:
4792 return interp__builtin_x86_extract_vector_masked(S, OpPC, Call, BuiltinID);
4793
4794 case clang::X86::BI__builtin_ia32_pmulhrsw128:
4795 case clang::X86::BI__builtin_ia32_pmulhrsw256:
4796 case clang::X86::BI__builtin_ia32_pmulhrsw512:
4798 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
4799 return (llvm::APIntOps::mulsExtended(LHS, RHS).ashr(14) + 1)
4800 .extractBits(16, 1);
4801 });
4802
4803 case clang::X86::BI__builtin_ia32_movmskps:
4804 case clang::X86::BI__builtin_ia32_movmskpd:
4805 case clang::X86::BI__builtin_ia32_pmovmskb128:
4806 case clang::X86::BI__builtin_ia32_pmovmskb256:
4807 case clang::X86::BI__builtin_ia32_movmskps256:
4808 case clang::X86::BI__builtin_ia32_movmskpd256: {
4809 return interp__builtin_ia32_movmsk_op(S, OpPC, Call);
4810 }
4811
4812 case X86::BI__builtin_ia32_psignb128:
4813 case X86::BI__builtin_ia32_psignb256:
4814 case X86::BI__builtin_ia32_psignw128:
4815 case X86::BI__builtin_ia32_psignw256:
4816 case X86::BI__builtin_ia32_psignd128:
4817 case X86::BI__builtin_ia32_psignd256:
4819 S, OpPC, Call, [](const APInt &AElem, const APInt &BElem) {
4820 if (BElem.isZero())
4821 return APInt::getZero(AElem.getBitWidth());
4822 if (BElem.isNegative())
4823 return -AElem;
4824 return AElem;
4825 });
4826
4827 case clang::X86::BI__builtin_ia32_pavgb128:
4828 case clang::X86::BI__builtin_ia32_pavgw128:
4829 case clang::X86::BI__builtin_ia32_pavgb256:
4830 case clang::X86::BI__builtin_ia32_pavgw256:
4831 case clang::X86::BI__builtin_ia32_pavgb512:
4832 case clang::X86::BI__builtin_ia32_pavgw512:
4834 llvm::APIntOps::avgCeilU);
4835
4836 case clang::X86::BI__builtin_ia32_pmaddubsw128:
4837 case clang::X86::BI__builtin_ia32_pmaddubsw256:
4838 case clang::X86::BI__builtin_ia32_pmaddubsw512:
4840 S, OpPC, Call,
4841 [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,
4842 const APSInt &HiRHS) {
4843 unsigned BitWidth = 2 * LoLHS.getBitWidth();
4844 return (LoLHS.zext(BitWidth) * LoRHS.sext(BitWidth))
4845 .sadd_sat((HiLHS.zext(BitWidth) * HiRHS.sext(BitWidth)));
4846 });
4847
4848 case clang::X86::BI__builtin_ia32_pmaddwd128:
4849 case clang::X86::BI__builtin_ia32_pmaddwd256:
4850 case clang::X86::BI__builtin_ia32_pmaddwd512:
4852 S, OpPC, Call,
4853 [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,
4854 const APSInt &HiRHS) {
4855 unsigned BitWidth = 2 * LoLHS.getBitWidth();
4856 return (LoLHS.sext(BitWidth) * LoRHS.sext(BitWidth)) +
4857 (HiLHS.sext(BitWidth) * HiRHS.sext(BitWidth));
4858 });
4859
4860 case clang::X86::BI__builtin_ia32_pmulhuw128:
4861 case clang::X86::BI__builtin_ia32_pmulhuw256:
4862 case clang::X86::BI__builtin_ia32_pmulhuw512:
4864 llvm::APIntOps::mulhu);
4865
4866 case clang::X86::BI__builtin_ia32_pmulhw128:
4867 case clang::X86::BI__builtin_ia32_pmulhw256:
4868 case clang::X86::BI__builtin_ia32_pmulhw512:
4870 llvm::APIntOps::mulhs);
4871
4872 case clang::X86::BI__builtin_ia32_psllv2di:
4873 case clang::X86::BI__builtin_ia32_psllv4di:
4874 case clang::X86::BI__builtin_ia32_psllv4si:
4875 case clang::X86::BI__builtin_ia32_psllv8di:
4876 case clang::X86::BI__builtin_ia32_psllv8hi:
4877 case clang::X86::BI__builtin_ia32_psllv8si:
4878 case clang::X86::BI__builtin_ia32_psllv16hi:
4879 case clang::X86::BI__builtin_ia32_psllv16si:
4880 case clang::X86::BI__builtin_ia32_psllv32hi:
4881 case clang::X86::BI__builtin_ia32_psllwi128:
4882 case clang::X86::BI__builtin_ia32_psllwi256:
4883 case clang::X86::BI__builtin_ia32_psllwi512:
4884 case clang::X86::BI__builtin_ia32_pslldi128:
4885 case clang::X86::BI__builtin_ia32_pslldi256:
4886 case clang::X86::BI__builtin_ia32_pslldi512:
4887 case clang::X86::BI__builtin_ia32_psllqi128:
4888 case clang::X86::BI__builtin_ia32_psllqi256:
4889 case clang::X86::BI__builtin_ia32_psllqi512:
4891 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
4892 if (RHS.uge(LHS.getBitWidth())) {
4893 return APInt::getZero(LHS.getBitWidth());
4894 }
4895 return LHS.shl(RHS.getZExtValue());
4896 });
4897
4898 case clang::X86::BI__builtin_ia32_psrav4si:
4899 case clang::X86::BI__builtin_ia32_psrav8di:
4900 case clang::X86::BI__builtin_ia32_psrav8hi:
4901 case clang::X86::BI__builtin_ia32_psrav8si:
4902 case clang::X86::BI__builtin_ia32_psrav16hi:
4903 case clang::X86::BI__builtin_ia32_psrav16si:
4904 case clang::X86::BI__builtin_ia32_psrav32hi:
4905 case clang::X86::BI__builtin_ia32_psravq128:
4906 case clang::X86::BI__builtin_ia32_psravq256:
4907 case clang::X86::BI__builtin_ia32_psrawi128:
4908 case clang::X86::BI__builtin_ia32_psrawi256:
4909 case clang::X86::BI__builtin_ia32_psrawi512:
4910 case clang::X86::BI__builtin_ia32_psradi128:
4911 case clang::X86::BI__builtin_ia32_psradi256:
4912 case clang::X86::BI__builtin_ia32_psradi512:
4913 case clang::X86::BI__builtin_ia32_psraqi128:
4914 case clang::X86::BI__builtin_ia32_psraqi256:
4915 case clang::X86::BI__builtin_ia32_psraqi512:
4917 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
4918 if (RHS.uge(LHS.getBitWidth())) {
4919 return LHS.ashr(LHS.getBitWidth() - 1);
4920 }
4921 return LHS.ashr(RHS.getZExtValue());
4922 });
4923
4924 case clang::X86::BI__builtin_ia32_psrlv2di:
4925 case clang::X86::BI__builtin_ia32_psrlv4di:
4926 case clang::X86::BI__builtin_ia32_psrlv4si:
4927 case clang::X86::BI__builtin_ia32_psrlv8di:
4928 case clang::X86::BI__builtin_ia32_psrlv8hi:
4929 case clang::X86::BI__builtin_ia32_psrlv8si:
4930 case clang::X86::BI__builtin_ia32_psrlv16hi:
4931 case clang::X86::BI__builtin_ia32_psrlv16si:
4932 case clang::X86::BI__builtin_ia32_psrlv32hi:
4933 case clang::X86::BI__builtin_ia32_psrlwi128:
4934 case clang::X86::BI__builtin_ia32_psrlwi256:
4935 case clang::X86::BI__builtin_ia32_psrlwi512:
4936 case clang::X86::BI__builtin_ia32_psrldi128:
4937 case clang::X86::BI__builtin_ia32_psrldi256:
4938 case clang::X86::BI__builtin_ia32_psrldi512:
4939 case clang::X86::BI__builtin_ia32_psrlqi128:
4940 case clang::X86::BI__builtin_ia32_psrlqi256:
4941 case clang::X86::BI__builtin_ia32_psrlqi512:
4943 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
4944 if (RHS.uge(LHS.getBitWidth())) {
4945 return APInt::getZero(LHS.getBitWidth());
4946 }
4947 return LHS.lshr(RHS.getZExtValue());
4948 });
4949 case clang::X86::BI__builtin_ia32_packsswb128:
4950 case clang::X86::BI__builtin_ia32_packsswb256:
4951 case clang::X86::BI__builtin_ia32_packsswb512:
4952 case clang::X86::BI__builtin_ia32_packssdw128:
4953 case clang::X86::BI__builtin_ia32_packssdw256:
4954 case clang::X86::BI__builtin_ia32_packssdw512:
4955 return interp__builtin_x86_pack(S, OpPC, Call, [](const APSInt &Src) {
4956 return APInt(Src).truncSSat(Src.getBitWidth() / 2);
4957 });
4958 case clang::X86::BI__builtin_ia32_packusdw128:
4959 case clang::X86::BI__builtin_ia32_packusdw256:
4960 case clang::X86::BI__builtin_ia32_packusdw512:
4961 case clang::X86::BI__builtin_ia32_packuswb128:
4962 case clang::X86::BI__builtin_ia32_packuswb256:
4963 case clang::X86::BI__builtin_ia32_packuswb512:
4964 return interp__builtin_x86_pack(S, OpPC, Call, [](const APSInt &Src) {
4965 return APInt(Src).truncSSatU(Src.getBitWidth() / 2);
4966 });
4967
4968 case clang::X86::BI__builtin_ia32_selectss_128:
4969 case clang::X86::BI__builtin_ia32_selectsd_128:
4970 case clang::X86::BI__builtin_ia32_selectsh_128:
4971 case clang::X86::BI__builtin_ia32_selectsbf_128:
4973 case clang::X86::BI__builtin_ia32_vprotbi:
4974 case clang::X86::BI__builtin_ia32_vprotdi:
4975 case clang::X86::BI__builtin_ia32_vprotqi:
4976 case clang::X86::BI__builtin_ia32_vprotwi:
4977 case clang::X86::BI__builtin_ia32_prold128:
4978 case clang::X86::BI__builtin_ia32_prold256:
4979 case clang::X86::BI__builtin_ia32_prold512:
4980 case clang::X86::BI__builtin_ia32_prolq128:
4981 case clang::X86::BI__builtin_ia32_prolq256:
4982 case clang::X86::BI__builtin_ia32_prolq512:
4984 S, OpPC, Call,
4985 [](const APSInt &LHS, const APSInt &RHS) { return LHS.rotl(RHS); });
4986
4987 case clang::X86::BI__builtin_ia32_prord128:
4988 case clang::X86::BI__builtin_ia32_prord256:
4989 case clang::X86::BI__builtin_ia32_prord512:
4990 case clang::X86::BI__builtin_ia32_prorq128:
4991 case clang::X86::BI__builtin_ia32_prorq256:
4992 case clang::X86::BI__builtin_ia32_prorq512:
4994 S, OpPC, Call,
4995 [](const APSInt &LHS, const APSInt &RHS) { return LHS.rotr(RHS); });
4996
4997 case Builtin::BI__builtin_elementwise_max:
4998 case Builtin::BI__builtin_elementwise_min:
4999 return interp__builtin_elementwise_maxmin(S, OpPC, Call, BuiltinID);
5000
5001 case clang::X86::BI__builtin_ia32_phaddw128:
5002 case clang::X86::BI__builtin_ia32_phaddw256:
5003 case clang::X86::BI__builtin_ia32_phaddd128:
5004 case clang::X86::BI__builtin_ia32_phaddd256:
5006 S, OpPC, Call,
5007 [](const APSInt &LHS, const APSInt &RHS) { return LHS + RHS; });
5008 case clang::X86::BI__builtin_ia32_phaddsw128:
5009 case clang::X86::BI__builtin_ia32_phaddsw256:
5011 S, OpPC, Call,
5012 [](const APSInt &LHS, const APSInt &RHS) { return LHS.sadd_sat(RHS); });
5013 case clang::X86::BI__builtin_ia32_phsubw128:
5014 case clang::X86::BI__builtin_ia32_phsubw256:
5015 case clang::X86::BI__builtin_ia32_phsubd128:
5016 case clang::X86::BI__builtin_ia32_phsubd256:
5018 S, OpPC, Call,
5019 [](const APSInt &LHS, const APSInt &RHS) { return LHS - RHS; });
5020 case clang::X86::BI__builtin_ia32_phsubsw128:
5021 case clang::X86::BI__builtin_ia32_phsubsw256:
5023 S, OpPC, Call,
5024 [](const APSInt &LHS, const APSInt &RHS) { return LHS.ssub_sat(RHS); });
5025 case clang::X86::BI__builtin_ia32_haddpd:
5026 case clang::X86::BI__builtin_ia32_haddps:
5027 case clang::X86::BI__builtin_ia32_haddpd256:
5028 case clang::X86::BI__builtin_ia32_haddps256:
5030 S, OpPC, Call,
5031 [](const APFloat &LHS, const APFloat &RHS, llvm::RoundingMode RM) {
5032 APFloat F = LHS;
5033 F.add(RHS, RM);
5034 return F;
5035 });
5036 case clang::X86::BI__builtin_ia32_hsubpd:
5037 case clang::X86::BI__builtin_ia32_hsubps:
5038 case clang::X86::BI__builtin_ia32_hsubpd256:
5039 case clang::X86::BI__builtin_ia32_hsubps256:
5041 S, OpPC, Call,
5042 [](const APFloat &LHS, const APFloat &RHS, llvm::RoundingMode RM) {
5043 APFloat F = LHS;
5044 F.subtract(RHS, RM);
5045 return F;
5046 });
5047 case clang::X86::BI__builtin_ia32_addsubpd:
5048 case clang::X86::BI__builtin_ia32_addsubps:
5049 case clang::X86::BI__builtin_ia32_addsubpd256:
5050 case clang::X86::BI__builtin_ia32_addsubps256:
5051 return interp__builtin_ia32_addsub(S, OpPC, Call);
5052
5053 case clang::X86::BI__builtin_ia32_pmuldq128:
5054 case clang::X86::BI__builtin_ia32_pmuldq256:
5055 case clang::X86::BI__builtin_ia32_pmuldq512:
5057 S, OpPC, Call,
5058 [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,
5059 const APSInt &HiRHS) {
5060 return llvm::APIntOps::mulsExtended(LoLHS, LoRHS);
5061 });
5062
5063 case clang::X86::BI__builtin_ia32_pmuludq128:
5064 case clang::X86::BI__builtin_ia32_pmuludq256:
5065 case clang::X86::BI__builtin_ia32_pmuludq512:
5067 S, OpPC, Call,
5068 [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,
5069 const APSInt &HiRHS) {
5070 return llvm::APIntOps::muluExtended(LoLHS, LoRHS);
5071 });
5072
5073 case clang::X86::BI__builtin_ia32_pclmulqdq128:
5074 case clang::X86::BI__builtin_ia32_pclmulqdq256:
5075 case clang::X86::BI__builtin_ia32_pclmulqdq512:
5076 return interp__builtin_ia32_pclmulqdq(S, OpPC, Call);
5077
5078 case Builtin::BI__builtin_elementwise_fma:
5080 S, OpPC, Call,
5081 [](const APFloat &X, const APFloat &Y, const APFloat &Z,
5082 llvm::RoundingMode RM) {
5083 APFloat F = X;
5084 F.fusedMultiplyAdd(Y, Z, RM);
5085 return F;
5086 });
5087
5088 case X86::BI__builtin_ia32_vpmadd52luq128:
5089 case X86::BI__builtin_ia32_vpmadd52luq256:
5090 case X86::BI__builtin_ia32_vpmadd52luq512:
5092 S, OpPC, Call, [](const APSInt &A, const APSInt &B, const APSInt &C) {
5093 return A + (B.trunc(52) * C.trunc(52)).zext(64);
5094 });
5095 case X86::BI__builtin_ia32_vpmadd52huq128:
5096 case X86::BI__builtin_ia32_vpmadd52huq256:
5097 case X86::BI__builtin_ia32_vpmadd52huq512:
5099 S, OpPC, Call, [](const APSInt &A, const APSInt &B, const APSInt &C) {
5100 return A + llvm::APIntOps::mulhu(B.trunc(52), C.trunc(52)).zext(64);
5101 });
5102
5103 case X86::BI__builtin_ia32_vpshldd128:
5104 case X86::BI__builtin_ia32_vpshldd256:
5105 case X86::BI__builtin_ia32_vpshldd512:
5106 case X86::BI__builtin_ia32_vpshldq128:
5107 case X86::BI__builtin_ia32_vpshldq256:
5108 case X86::BI__builtin_ia32_vpshldq512:
5109 case X86::BI__builtin_ia32_vpshldw128:
5110 case X86::BI__builtin_ia32_vpshldw256:
5111 case X86::BI__builtin_ia32_vpshldw512:
5113 S, OpPC, Call,
5114 [](const APSInt &Hi, const APSInt &Lo, const APSInt &Amt) {
5115 return llvm::APIntOps::fshl(Hi, Lo, Amt);
5116 });
5117
5118 case X86::BI__builtin_ia32_vpshrdd128:
5119 case X86::BI__builtin_ia32_vpshrdd256:
5120 case X86::BI__builtin_ia32_vpshrdd512:
5121 case X86::BI__builtin_ia32_vpshrdq128:
5122 case X86::BI__builtin_ia32_vpshrdq256:
5123 case X86::BI__builtin_ia32_vpshrdq512:
5124 case X86::BI__builtin_ia32_vpshrdw128:
5125 case X86::BI__builtin_ia32_vpshrdw256:
5126 case X86::BI__builtin_ia32_vpshrdw512:
5127 // NOTE: Reversed Hi/Lo operands.
5129 S, OpPC, Call,
5130 [](const APSInt &Lo, const APSInt &Hi, const APSInt &Amt) {
5131 return llvm::APIntOps::fshr(Hi, Lo, Amt);
5132 });
5133 case X86::BI__builtin_ia32_vpconflictsi_128:
5134 case X86::BI__builtin_ia32_vpconflictsi_256:
5135 case X86::BI__builtin_ia32_vpconflictsi_512:
5136 case X86::BI__builtin_ia32_vpconflictdi_128:
5137 case X86::BI__builtin_ia32_vpconflictdi_256:
5138 case X86::BI__builtin_ia32_vpconflictdi_512:
5139 return interp__builtin_ia32_vpconflict(S, OpPC, Call);
5140 case X86::BI__builtin_ia32_compressdf128_mask:
5141 case X86::BI__builtin_ia32_compressdf256_mask:
5142 case X86::BI__builtin_ia32_compressdf512_mask:
5143 case X86::BI__builtin_ia32_compressdi128_mask:
5144 case X86::BI__builtin_ia32_compressdi256_mask:
5145 case X86::BI__builtin_ia32_compressdi512_mask:
5146 case X86::BI__builtin_ia32_compresshi128_mask:
5147 case X86::BI__builtin_ia32_compresshi256_mask:
5148 case X86::BI__builtin_ia32_compresshi512_mask:
5149 case X86::BI__builtin_ia32_compressqi128_mask:
5150 case X86::BI__builtin_ia32_compressqi256_mask:
5151 case X86::BI__builtin_ia32_compressqi512_mask:
5152 case X86::BI__builtin_ia32_compresssf128_mask:
5153 case X86::BI__builtin_ia32_compresssf256_mask:
5154 case X86::BI__builtin_ia32_compresssf512_mask:
5155 case X86::BI__builtin_ia32_compresssi128_mask:
5156 case X86::BI__builtin_ia32_compresssi256_mask:
5157 case X86::BI__builtin_ia32_compresssi512_mask: {
5158 unsigned NumElems =
5159 Call->getArg(0)->getType()->castAs<VectorType>()->getNumElements();
5161 S, OpPC, Call, [NumElems](unsigned DstIdx, const APInt &ShuffleMask) {
5162 APInt CompressMask = ShuffleMask.trunc(NumElems);
5163 if (DstIdx < CompressMask.popcount()) {
5164 while (DstIdx != 0) {
5165 CompressMask = CompressMask & (CompressMask - 1);
5166 DstIdx--;
5167 }
5168 return std::pair<unsigned, int>{
5169 0, static_cast<int>(CompressMask.countr_zero())};
5170 }
5171 return std::pair<unsigned, int>{1, static_cast<int>(DstIdx)};
5172 });
5173 }
5174 case X86::BI__builtin_ia32_expanddf128_mask:
5175 case X86::BI__builtin_ia32_expanddf256_mask:
5176 case X86::BI__builtin_ia32_expanddf512_mask:
5177 case X86::BI__builtin_ia32_expanddi128_mask:
5178 case X86::BI__builtin_ia32_expanddi256_mask:
5179 case X86::BI__builtin_ia32_expanddi512_mask:
5180 case X86::BI__builtin_ia32_expandhi128_mask:
5181 case X86::BI__builtin_ia32_expandhi256_mask:
5182 case X86::BI__builtin_ia32_expandhi512_mask:
5183 case X86::BI__builtin_ia32_expandqi128_mask:
5184 case X86::BI__builtin_ia32_expandqi256_mask:
5185 case X86::BI__builtin_ia32_expandqi512_mask:
5186 case X86::BI__builtin_ia32_expandsf128_mask:
5187 case X86::BI__builtin_ia32_expandsf256_mask:
5188 case X86::BI__builtin_ia32_expandsf512_mask:
5189 case X86::BI__builtin_ia32_expandsi128_mask:
5190 case X86::BI__builtin_ia32_expandsi256_mask:
5191 case X86::BI__builtin_ia32_expandsi512_mask: {
5193 S, OpPC, Call, [](unsigned DstIdx, const APInt &ShuffleMask) {
5194 // Trunc to the sub-mask for the dst index and count the number of
5195 // src elements used prior to that.
5196 APInt ExpandMask = ShuffleMask.trunc(DstIdx + 1);
5197 if (ExpandMask[DstIdx]) {
5198 int SrcIdx = ExpandMask.popcount() - 1;
5199 return std::pair<unsigned, int>{0, SrcIdx};
5200 }
5201 return std::pair<unsigned, int>{1, static_cast<int>(DstIdx)};
5202 });
5203 }
5204 case clang::X86::BI__builtin_ia32_blendpd:
5205 case clang::X86::BI__builtin_ia32_blendpd256:
5206 case clang::X86::BI__builtin_ia32_blendps:
5207 case clang::X86::BI__builtin_ia32_blendps256:
5208 case clang::X86::BI__builtin_ia32_pblendw128:
5209 case clang::X86::BI__builtin_ia32_pblendw256:
5210 case clang::X86::BI__builtin_ia32_pblendd128:
5211 case clang::X86::BI__builtin_ia32_pblendd256:
5213 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5214 // Bit index for mask.
5215 unsigned MaskBit = (ShuffleMask >> (DstIdx % 8)) & 0x1;
5216 unsigned SrcVecIdx = MaskBit ? 1 : 0; // 1 = TrueVec, 0 = FalseVec
5217 return std::pair<unsigned, int>{SrcVecIdx, static_cast<int>(DstIdx)};
5218 });
5219
5220
5221
5222 case clang::X86::BI__builtin_ia32_blendvpd:
5223 case clang::X86::BI__builtin_ia32_blendvpd256:
5224 case clang::X86::BI__builtin_ia32_blendvps:
5225 case clang::X86::BI__builtin_ia32_blendvps256:
5227 S, OpPC, Call,
5228 [](const APFloat &F, const APFloat &T, const APFloat &C,
5229 llvm::RoundingMode) { return C.isNegative() ? T : F; });
5230
5231 case clang::X86::BI__builtin_ia32_pblendvb128:
5232 case clang::X86::BI__builtin_ia32_pblendvb256:
5234 S, OpPC, Call, [](const APSInt &F, const APSInt &T, const APSInt &C) {
5235 return ((APInt)C).isNegative() ? T : F;
5236 });
5237 case X86::BI__builtin_ia32_ptestz128:
5238 case X86::BI__builtin_ia32_ptestz256:
5239 case X86::BI__builtin_ia32_vtestzps:
5240 case X86::BI__builtin_ia32_vtestzps256:
5241 case X86::BI__builtin_ia32_vtestzpd:
5242 case X86::BI__builtin_ia32_vtestzpd256:
5244 S, OpPC, Call,
5245 [](const APInt &A, const APInt &B) { return (A & B) == 0; });
5246 case X86::BI__builtin_ia32_ptestc128:
5247 case X86::BI__builtin_ia32_ptestc256:
5248 case X86::BI__builtin_ia32_vtestcps:
5249 case X86::BI__builtin_ia32_vtestcps256:
5250 case X86::BI__builtin_ia32_vtestcpd:
5251 case X86::BI__builtin_ia32_vtestcpd256:
5253 S, OpPC, Call,
5254 [](const APInt &A, const APInt &B) { return (~A & B) == 0; });
5255 case X86::BI__builtin_ia32_ptestnzc128:
5256 case X86::BI__builtin_ia32_ptestnzc256:
5257 case X86::BI__builtin_ia32_vtestnzcps:
5258 case X86::BI__builtin_ia32_vtestnzcps256:
5259 case X86::BI__builtin_ia32_vtestnzcpd:
5260 case X86::BI__builtin_ia32_vtestnzcpd256:
5262 S, OpPC, Call, [](const APInt &A, const APInt &B) {
5263 return ((A & B) != 0) && ((~A & B) != 0);
5264 });
5265 case X86::BI__builtin_ia32_selectb_128:
5266 case X86::BI__builtin_ia32_selectb_256:
5267 case X86::BI__builtin_ia32_selectb_512:
5268 case X86::BI__builtin_ia32_selectw_128:
5269 case X86::BI__builtin_ia32_selectw_256:
5270 case X86::BI__builtin_ia32_selectw_512:
5271 case X86::BI__builtin_ia32_selectd_128:
5272 case X86::BI__builtin_ia32_selectd_256:
5273 case X86::BI__builtin_ia32_selectd_512:
5274 case X86::BI__builtin_ia32_selectq_128:
5275 case X86::BI__builtin_ia32_selectq_256:
5276 case X86::BI__builtin_ia32_selectq_512:
5277 case X86::BI__builtin_ia32_selectph_128:
5278 case X86::BI__builtin_ia32_selectph_256:
5279 case X86::BI__builtin_ia32_selectph_512:
5280 case X86::BI__builtin_ia32_selectpbf_128:
5281 case X86::BI__builtin_ia32_selectpbf_256:
5282 case X86::BI__builtin_ia32_selectpbf_512:
5283 case X86::BI__builtin_ia32_selectps_128:
5284 case X86::BI__builtin_ia32_selectps_256:
5285 case X86::BI__builtin_ia32_selectps_512:
5286 case X86::BI__builtin_ia32_selectpd_128:
5287 case X86::BI__builtin_ia32_selectpd_256:
5288 case X86::BI__builtin_ia32_selectpd_512:
5289 return interp__builtin_select(S, OpPC, Call);
5290
5291 case X86::BI__builtin_ia32_shufps:
5292 case X86::BI__builtin_ia32_shufps256:
5293 case X86::BI__builtin_ia32_shufps512:
5295 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5296 unsigned NumElemPerLane = 4;
5297 unsigned NumSelectableElems = NumElemPerLane / 2;
5298 unsigned BitsPerElem = 2;
5299 unsigned IndexMask = 0x3;
5300 unsigned MaskBits = 8;
5301 unsigned Lane = DstIdx / NumElemPerLane;
5302 unsigned ElemInLane = DstIdx % NumElemPerLane;
5303 unsigned LaneOffset = Lane * NumElemPerLane;
5304 unsigned SrcIdx = ElemInLane >= NumSelectableElems ? 1 : 0;
5305 unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;
5306 unsigned Index = (ShuffleMask >> BitIndex) & IndexMask;
5307 return std::pair<unsigned, int>{SrcIdx,
5308 static_cast<int>(LaneOffset + Index)};
5309 });
5310 case X86::BI__builtin_ia32_shufpd:
5311 case X86::BI__builtin_ia32_shufpd256:
5312 case X86::BI__builtin_ia32_shufpd512:
5314 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5315 unsigned NumElemPerLane = 2;
5316 unsigned NumSelectableElems = NumElemPerLane / 2;
5317 unsigned BitsPerElem = 1;
5318 unsigned IndexMask = 0x1;
5319 unsigned MaskBits = 8;
5320 unsigned Lane = DstIdx / NumElemPerLane;
5321 unsigned ElemInLane = DstIdx % NumElemPerLane;
5322 unsigned LaneOffset = Lane * NumElemPerLane;
5323 unsigned SrcIdx = ElemInLane >= NumSelectableElems ? 1 : 0;
5324 unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;
5325 unsigned Index = (ShuffleMask >> BitIndex) & IndexMask;
5326 return std::pair<unsigned, int>{SrcIdx,
5327 static_cast<int>(LaneOffset + Index)};
5328 });
5329
5330 case X86::BI__builtin_ia32_vgf2p8affineinvqb_v16qi:
5331 case X86::BI__builtin_ia32_vgf2p8affineinvqb_v32qi:
5332 case X86::BI__builtin_ia32_vgf2p8affineinvqb_v64qi:
5333 return interp_builtin_ia32_gfni_affine(S, OpPC, Call, true);
5334 case X86::BI__builtin_ia32_vgf2p8affineqb_v16qi:
5335 case X86::BI__builtin_ia32_vgf2p8affineqb_v32qi:
5336 case X86::BI__builtin_ia32_vgf2p8affineqb_v64qi:
5337 return interp_builtin_ia32_gfni_affine(S, OpPC, Call, false);
5338
5339 case X86::BI__builtin_ia32_vgf2p8mulb_v16qi:
5340 case X86::BI__builtin_ia32_vgf2p8mulb_v32qi:
5341 case X86::BI__builtin_ia32_vgf2p8mulb_v64qi:
5342 return interp__builtin_ia32_gfni_mul(S, OpPC, Call);
5343
5344 case X86::BI__builtin_ia32_insertps128:
5346 S, OpPC, Call, [](unsigned DstIdx, unsigned Mask) {
5347 // Bits [3:0]: zero mask - if bit is set, zero this element
5348 if ((Mask & (1 << DstIdx)) != 0) {
5349 return std::pair<unsigned, int>{0, -1};
5350 }
5351 // Bits [7:6]: select element from source vector Y (0-3)
5352 // Bits [5:4]: select destination position (0-3)
5353 unsigned SrcElem = (Mask >> 6) & 0x3;
5354 unsigned DstElem = (Mask >> 4) & 0x3;
5355 if (DstIdx == DstElem) {
5356 // Insert element from source vector (B) at this position
5357 return std::pair<unsigned, int>{1, static_cast<int>(SrcElem)};
5358 } else {
5359 // Copy from destination vector (A)
5360 return std::pair<unsigned, int>{0, static_cast<int>(DstIdx)};
5361 }
5362 });
5363 case X86::BI__builtin_ia32_permvarsi256:
5364 case X86::BI__builtin_ia32_permvarsf256:
5365 case X86::BI__builtin_ia32_permvardf512:
5366 case X86::BI__builtin_ia32_permvardi512:
5367 case X86::BI__builtin_ia32_permvarhi128:
5369 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5370 int Offset = ShuffleMask & 0x7;
5371 return std::pair<unsigned, int>{0, Offset};
5372 });
5373 case X86::BI__builtin_ia32_permvarqi128:
5374 case X86::BI__builtin_ia32_permvarhi256:
5375 case X86::BI__builtin_ia32_permvarsi512:
5376 case X86::BI__builtin_ia32_permvarsf512:
5378 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5379 int Offset = ShuffleMask & 0xF;
5380 return std::pair<unsigned, int>{0, Offset};
5381 });
5382 case X86::BI__builtin_ia32_permvardi256:
5383 case X86::BI__builtin_ia32_permvardf256:
5385 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5386 int Offset = ShuffleMask & 0x3;
5387 return std::pair<unsigned, int>{0, Offset};
5388 });
5389 case X86::BI__builtin_ia32_permvarqi256:
5390 case X86::BI__builtin_ia32_permvarhi512:
5392 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5393 int Offset = ShuffleMask & 0x1F;
5394 return std::pair<unsigned, int>{0, Offset};
5395 });
5396 case X86::BI__builtin_ia32_permvarqi512:
5398 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5399 int Offset = ShuffleMask & 0x3F;
5400 return std::pair<unsigned, int>{0, Offset};
5401 });
5402 case X86::BI__builtin_ia32_vpermi2varq128:
5403 case X86::BI__builtin_ia32_vpermi2varpd128:
5405 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5406 int Offset = ShuffleMask & 0x1;
5407 unsigned SrcIdx = (ShuffleMask >> 1) & 0x1;
5408 return std::pair<unsigned, int>{SrcIdx, Offset};
5409 });
5410 case X86::BI__builtin_ia32_vpermi2vard128:
5411 case X86::BI__builtin_ia32_vpermi2varps128:
5412 case X86::BI__builtin_ia32_vpermi2varq256:
5413 case X86::BI__builtin_ia32_vpermi2varpd256:
5415 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5416 int Offset = ShuffleMask & 0x3;
5417 unsigned SrcIdx = (ShuffleMask >> 2) & 0x1;
5418 return std::pair<unsigned, int>{SrcIdx, Offset};
5419 });
5420 case X86::BI__builtin_ia32_vpermi2varhi128:
5421 case X86::BI__builtin_ia32_vpermi2vard256:
5422 case X86::BI__builtin_ia32_vpermi2varps256:
5423 case X86::BI__builtin_ia32_vpermi2varq512:
5424 case X86::BI__builtin_ia32_vpermi2varpd512:
5426 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5427 int Offset = ShuffleMask & 0x7;
5428 unsigned SrcIdx = (ShuffleMask >> 3) & 0x1;
5429 return std::pair<unsigned, int>{SrcIdx, Offset};
5430 });
5431 case X86::BI__builtin_ia32_vpermi2varqi128:
5432 case X86::BI__builtin_ia32_vpermi2varhi256:
5433 case X86::BI__builtin_ia32_vpermi2vard512:
5434 case X86::BI__builtin_ia32_vpermi2varps512:
5436 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5437 int Offset = ShuffleMask & 0xF;
5438 unsigned SrcIdx = (ShuffleMask >> 4) & 0x1;
5439 return std::pair<unsigned, int>{SrcIdx, Offset};
5440 });
5441 case X86::BI__builtin_ia32_vpermi2varqi256:
5442 case X86::BI__builtin_ia32_vpermi2varhi512:
5444 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5445 int Offset = ShuffleMask & 0x1F;
5446 unsigned SrcIdx = (ShuffleMask >> 5) & 0x1;
5447 return std::pair<unsigned, int>{SrcIdx, Offset};
5448 });
5449 case X86::BI__builtin_ia32_vpermi2varqi512:
5451 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5452 int Offset = ShuffleMask & 0x3F;
5453 unsigned SrcIdx = (ShuffleMask >> 6) & 0x1;
5454 return std::pair<unsigned, int>{SrcIdx, Offset};
5455 });
5456 case X86::BI__builtin_ia32_vperm2f128_pd256:
5457 case X86::BI__builtin_ia32_vperm2f128_ps256:
5458 case X86::BI__builtin_ia32_vperm2f128_si256:
5459 case X86::BI__builtin_ia32_permti256: {
5460 unsigned NumElements =
5461 Call->getArg(0)->getType()->castAs<VectorType>()->getNumElements();
5462 unsigned PreservedBitsCnt = NumElements >> 2;
5464 S, OpPC, Call,
5465 [PreservedBitsCnt](unsigned DstIdx, unsigned ShuffleMask) {
5466 unsigned ControlBitsCnt = DstIdx >> PreservedBitsCnt << 2;
5467 unsigned ControlBits = ShuffleMask >> ControlBitsCnt;
5468
5469 if (ControlBits & 0b1000)
5470 return std::make_pair(0u, -1);
5471
5472 unsigned SrcVecIdx = (ControlBits & 0b10) >> 1;
5473 unsigned PreservedBitsMask = (1 << PreservedBitsCnt) - 1;
5474 int SrcIdx = ((ControlBits & 0b1) << PreservedBitsCnt) |
5475 (DstIdx & PreservedBitsMask);
5476 return std::make_pair(SrcVecIdx, SrcIdx);
5477 });
5478 }
5479 case X86::BI__builtin_ia32_pshufb128:
5480 case X86::BI__builtin_ia32_pshufb256:
5481 case X86::BI__builtin_ia32_pshufb512:
5483 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5484 uint8_t Ctlb = static_cast<uint8_t>(ShuffleMask);
5485 if (Ctlb & 0x80)
5486 return std::make_pair(0, -1);
5487
5488 unsigned LaneBase = (DstIdx / 16) * 16;
5489 unsigned SrcOffset = Ctlb & 0x0F;
5490 unsigned SrcIdx = LaneBase + SrcOffset;
5491 return std::make_pair(0, static_cast<int>(SrcIdx));
5492 });
5493
5494 case X86::BI__builtin_ia32_pshuflw:
5495 case X86::BI__builtin_ia32_pshuflw256:
5496 case X86::BI__builtin_ia32_pshuflw512:
5498 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5499 unsigned LaneBase = (DstIdx / 8) * 8;
5500 unsigned LaneIdx = DstIdx % 8;
5501 if (LaneIdx < 4) {
5502 unsigned Sel = (ShuffleMask >> (2 * LaneIdx)) & 0x3;
5503 return std::make_pair(0, static_cast<int>(LaneBase + Sel));
5504 }
5505
5506 return std::make_pair(0, static_cast<int>(DstIdx));
5507 });
5508
5509 case X86::BI__builtin_ia32_pshufhw:
5510 case X86::BI__builtin_ia32_pshufhw256:
5511 case X86::BI__builtin_ia32_pshufhw512:
5513 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5514 unsigned LaneBase = (DstIdx / 8) * 8;
5515 unsigned LaneIdx = DstIdx % 8;
5516 if (LaneIdx >= 4) {
5517 unsigned Sel = (ShuffleMask >> (2 * (LaneIdx - 4))) & 0x3;
5518 return std::make_pair(0, static_cast<int>(LaneBase + 4 + Sel));
5519 }
5520
5521 return std::make_pair(0, static_cast<int>(DstIdx));
5522 });
5523
5524 case X86::BI__builtin_ia32_pshufd:
5525 case X86::BI__builtin_ia32_pshufd256:
5526 case X86::BI__builtin_ia32_pshufd512:
5527 case X86::BI__builtin_ia32_vpermilps:
5528 case X86::BI__builtin_ia32_vpermilps256:
5529 case X86::BI__builtin_ia32_vpermilps512:
5531 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5532 unsigned LaneBase = (DstIdx / 4) * 4;
5533 unsigned LaneIdx = DstIdx % 4;
5534 unsigned Sel = (ShuffleMask >> (2 * LaneIdx)) & 0x3;
5535 return std::make_pair(0, static_cast<int>(LaneBase + Sel));
5536 });
5537
5538 case X86::BI__builtin_ia32_vpermilvarpd:
5539 case X86::BI__builtin_ia32_vpermilvarpd256:
5540 case X86::BI__builtin_ia32_vpermilvarpd512:
5542 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5543 unsigned NumElemPerLane = 2;
5544 unsigned Lane = DstIdx / NumElemPerLane;
5545 unsigned Offset = ShuffleMask & 0b10 ? 1 : 0;
5546 return std::make_pair(
5547 0, static_cast<int>(Lane * NumElemPerLane + Offset));
5548 });
5549
5550 case X86::BI__builtin_ia32_vpermilvarps:
5551 case X86::BI__builtin_ia32_vpermilvarps256:
5552 case X86::BI__builtin_ia32_vpermilvarps512:
5554 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5555 unsigned NumElemPerLane = 4;
5556 unsigned Lane = DstIdx / NumElemPerLane;
5557 unsigned Offset = ShuffleMask & 0b11;
5558 return std::make_pair(
5559 0, static_cast<int>(Lane * NumElemPerLane + Offset));
5560 });
5561
5562 case X86::BI__builtin_ia32_vpermilpd:
5563 case X86::BI__builtin_ia32_vpermilpd256:
5564 case X86::BI__builtin_ia32_vpermilpd512:
5566 S, OpPC, Call, [](unsigned DstIdx, unsigned Control) {
5567 unsigned NumElemPerLane = 2;
5568 unsigned BitsPerElem = 1;
5569 unsigned MaskBits = 8;
5570 unsigned IndexMask = 0x1;
5571 unsigned Lane = DstIdx / NumElemPerLane;
5572 unsigned LaneOffset = Lane * NumElemPerLane;
5573 unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;
5574 unsigned Index = (Control >> BitIndex) & IndexMask;
5575 return std::make_pair(0, static_cast<int>(LaneOffset + Index));
5576 });
5577
5578 case X86::BI__builtin_ia32_permdf256:
5579 case X86::BI__builtin_ia32_permdi256:
5581 S, OpPC, Call, [](unsigned DstIdx, unsigned Control) {
5582 // permute4x64 operates on 4 64-bit elements
5583 // For element i (0-3), extract bits [2*i+1:2*i] from Control
5584 unsigned Index = (Control >> (2 * DstIdx)) & 0x3;
5585 return std::make_pair(0, static_cast<int>(Index));
5586 });
5587
5588 case X86::BI__builtin_ia32_vpmultishiftqb128:
5589 case X86::BI__builtin_ia32_vpmultishiftqb256:
5590 case X86::BI__builtin_ia32_vpmultishiftqb512:
5591 return interp__builtin_ia32_multishiftqb(S, OpPC, Call);
5592 case X86::BI__builtin_ia32_kandqi:
5593 case X86::BI__builtin_ia32_kandhi:
5594 case X86::BI__builtin_ia32_kandsi:
5595 case X86::BI__builtin_ia32_kanddi:
5597 S, OpPC, Call,
5598 [](const APSInt &LHS, const APSInt &RHS) { return LHS & RHS; });
5599
5600 case X86::BI__builtin_ia32_kandnqi:
5601 case X86::BI__builtin_ia32_kandnhi:
5602 case X86::BI__builtin_ia32_kandnsi:
5603 case X86::BI__builtin_ia32_kandndi:
5605 S, OpPC, Call,
5606 [](const APSInt &LHS, const APSInt &RHS) { return ~LHS & RHS; });
5607
5608 case X86::BI__builtin_ia32_korqi:
5609 case X86::BI__builtin_ia32_korhi:
5610 case X86::BI__builtin_ia32_korsi:
5611 case X86::BI__builtin_ia32_kordi:
5613 S, OpPC, Call,
5614 [](const APSInt &LHS, const APSInt &RHS) { return LHS | RHS; });
5615
5616 case X86::BI__builtin_ia32_kxnorqi:
5617 case X86::BI__builtin_ia32_kxnorhi:
5618 case X86::BI__builtin_ia32_kxnorsi:
5619 case X86::BI__builtin_ia32_kxnordi:
5621 S, OpPC, Call,
5622 [](const APSInt &LHS, const APSInt &RHS) { return ~(LHS ^ RHS); });
5623
5624 case X86::BI__builtin_ia32_kxorqi:
5625 case X86::BI__builtin_ia32_kxorhi:
5626 case X86::BI__builtin_ia32_kxorsi:
5627 case X86::BI__builtin_ia32_kxordi:
5629 S, OpPC, Call,
5630 [](const APSInt &LHS, const APSInt &RHS) { return LHS ^ RHS; });
5631
5632 case X86::BI__builtin_ia32_knotqi:
5633 case X86::BI__builtin_ia32_knothi:
5634 case X86::BI__builtin_ia32_knotsi:
5635 case X86::BI__builtin_ia32_knotdi:
5637 S, OpPC, Call, [](const APSInt &Src) { return ~Src; });
5638
5639 case X86::BI__builtin_ia32_kaddqi:
5640 case X86::BI__builtin_ia32_kaddhi:
5641 case X86::BI__builtin_ia32_kaddsi:
5642 case X86::BI__builtin_ia32_kadddi:
5644 S, OpPC, Call,
5645 [](const APSInt &LHS, const APSInt &RHS) { return LHS + RHS; });
5646
5647 case X86::BI__builtin_ia32_kmovb:
5648 case X86::BI__builtin_ia32_kmovw:
5649 case X86::BI__builtin_ia32_kmovd:
5650 case X86::BI__builtin_ia32_kmovq:
5652 S, OpPC, Call, [](const APSInt &Src) { return Src; });
5653
5654 case X86::BI__builtin_ia32_kunpckhi:
5655 case X86::BI__builtin_ia32_kunpckdi:
5656 case X86::BI__builtin_ia32_kunpcksi:
5658 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
5659 // Generic kunpack: extract lower half of each operand and concatenate
5660 // Result = A[HalfWidth-1:0] concat B[HalfWidth-1:0]
5661 unsigned BW = A.getBitWidth();
5662 return APSInt(A.trunc(BW / 2).concat(B.trunc(BW / 2)),
5663 A.isUnsigned());
5664 });
5665
5666 case X86::BI__builtin_ia32_phminposuw128:
5667 return interp__builtin_ia32_phminposuw(S, OpPC, Call);
5668
5669 case X86::BI__builtin_ia32_psraq128:
5670 case X86::BI__builtin_ia32_psraq256:
5671 case X86::BI__builtin_ia32_psraq512:
5672 case X86::BI__builtin_ia32_psrad128:
5673 case X86::BI__builtin_ia32_psrad256:
5674 case X86::BI__builtin_ia32_psrad512:
5675 case X86::BI__builtin_ia32_psraw128:
5676 case X86::BI__builtin_ia32_psraw256:
5677 case X86::BI__builtin_ia32_psraw512:
5679 S, OpPC, Call,
5680 [](const APInt &Elt, uint64_t Count) { return Elt.ashr(Count); },
5681 [](const APInt &Elt, unsigned Width) { return Elt.ashr(Width - 1); });
5682
5683 case X86::BI__builtin_ia32_psllq128:
5684 case X86::BI__builtin_ia32_psllq256:
5685 case X86::BI__builtin_ia32_psllq512:
5686 case X86::BI__builtin_ia32_pslld128:
5687 case X86::BI__builtin_ia32_pslld256:
5688 case X86::BI__builtin_ia32_pslld512:
5689 case X86::BI__builtin_ia32_psllw128:
5690 case X86::BI__builtin_ia32_psllw256:
5691 case X86::BI__builtin_ia32_psllw512:
5693 S, OpPC, Call,
5694 [](const APInt &Elt, uint64_t Count) { return Elt.shl(Count); },
5695 [](const APInt &Elt, unsigned Width) { return APInt::getZero(Width); });
5696
5697 case X86::BI__builtin_ia32_psrlq128:
5698 case X86::BI__builtin_ia32_psrlq256:
5699 case X86::BI__builtin_ia32_psrlq512:
5700 case X86::BI__builtin_ia32_psrld128:
5701 case X86::BI__builtin_ia32_psrld256:
5702 case X86::BI__builtin_ia32_psrld512:
5703 case X86::BI__builtin_ia32_psrlw128:
5704 case X86::BI__builtin_ia32_psrlw256:
5705 case X86::BI__builtin_ia32_psrlw512:
5707 S, OpPC, Call,
5708 [](const APInt &Elt, uint64_t Count) { return Elt.lshr(Count); },
5709 [](const APInt &Elt, unsigned Width) { return APInt::getZero(Width); });
5710
5711 case X86::BI__builtin_ia32_pternlogd128_mask:
5712 case X86::BI__builtin_ia32_pternlogd256_mask:
5713 case X86::BI__builtin_ia32_pternlogd512_mask:
5714 case X86::BI__builtin_ia32_pternlogq128_mask:
5715 case X86::BI__builtin_ia32_pternlogq256_mask:
5716 case X86::BI__builtin_ia32_pternlogq512_mask:
5717 return interp__builtin_ia32_pternlog(S, OpPC, Call, /*MaskZ=*/false);
5718 case X86::BI__builtin_ia32_pternlogd128_maskz:
5719 case X86::BI__builtin_ia32_pternlogd256_maskz:
5720 case X86::BI__builtin_ia32_pternlogd512_maskz:
5721 case X86::BI__builtin_ia32_pternlogq128_maskz:
5722 case X86::BI__builtin_ia32_pternlogq256_maskz:
5723 case X86::BI__builtin_ia32_pternlogq512_maskz:
5724 return interp__builtin_ia32_pternlog(S, OpPC, Call, /*MaskZ=*/true);
5725 case Builtin::BI__builtin_elementwise_fshl:
5727 llvm::APIntOps::fshl);
5728 case Builtin::BI__builtin_elementwise_fshr:
5730 llvm::APIntOps::fshr);
5731
5732 case X86::BI__builtin_ia32_shuf_f32x4_256:
5733 case X86::BI__builtin_ia32_shuf_i32x4_256:
5734 case X86::BI__builtin_ia32_shuf_f64x2_256:
5735 case X86::BI__builtin_ia32_shuf_i64x2_256:
5736 case X86::BI__builtin_ia32_shuf_f32x4:
5737 case X86::BI__builtin_ia32_shuf_i32x4:
5738 case X86::BI__builtin_ia32_shuf_f64x2:
5739 case X86::BI__builtin_ia32_shuf_i64x2: {
5740 // Destination and sources A, B all have the same type.
5741 QualType VecQT = Call->getArg(0)->getType();
5742 const auto *VecT = VecQT->castAs<VectorType>();
5743 unsigned NumElems = VecT->getNumElements();
5744 unsigned ElemBits = S.getASTContext().getTypeSize(VecT->getElementType());
5745 unsigned LaneBits = 128u;
5746 unsigned NumLanes = (NumElems * ElemBits) / LaneBits;
5747 unsigned NumElemsPerLane = LaneBits / ElemBits;
5748
5750 S, OpPC, Call,
5751 [NumLanes, NumElemsPerLane](unsigned DstIdx, unsigned ShuffleMask) {
5752 // DstIdx determines source. ShuffleMask selects lane in source.
5753 unsigned BitsPerElem = NumLanes / 2;
5754 unsigned IndexMask = (1u << BitsPerElem) - 1;
5755 unsigned Lane = DstIdx / NumElemsPerLane;
5756 unsigned SrcIdx = (Lane < NumLanes / 2) ? 0 : 1;
5757 unsigned BitIdx = BitsPerElem * Lane;
5758 unsigned SrcLaneIdx = (ShuffleMask >> BitIdx) & IndexMask;
5759 unsigned ElemInLane = DstIdx % NumElemsPerLane;
5760 unsigned IdxToPick = SrcLaneIdx * NumElemsPerLane + ElemInLane;
5761 return std::pair<unsigned, int>{SrcIdx, IdxToPick};
5762 });
5763 }
5764
5765 case X86::BI__builtin_ia32_insertf32x4_256:
5766 case X86::BI__builtin_ia32_inserti32x4_256:
5767 case X86::BI__builtin_ia32_insertf64x2_256:
5768 case X86::BI__builtin_ia32_inserti64x2_256:
5769 case X86::BI__builtin_ia32_insertf32x4:
5770 case X86::BI__builtin_ia32_inserti32x4:
5771 case X86::BI__builtin_ia32_insertf64x2_512:
5772 case X86::BI__builtin_ia32_inserti64x2_512:
5773 case X86::BI__builtin_ia32_insertf32x8:
5774 case X86::BI__builtin_ia32_inserti32x8:
5775 case X86::BI__builtin_ia32_insertf64x4:
5776 case X86::BI__builtin_ia32_inserti64x4:
5777 case X86::BI__builtin_ia32_vinsertf128_ps256:
5778 case X86::BI__builtin_ia32_vinsertf128_pd256:
5779 case X86::BI__builtin_ia32_vinsertf128_si256:
5780 case X86::BI__builtin_ia32_insert128i256:
5781 return interp__builtin_x86_insert_subvector(S, OpPC, Call, BuiltinID);
5782
5783 case clang::X86::BI__builtin_ia32_vcvtps2ph:
5784 case clang::X86::BI__builtin_ia32_vcvtps2ph256:
5785 return interp__builtin_ia32_vcvtps2ph(S, OpPC, Call);
5786
5787 case X86::BI__builtin_ia32_vec_ext_v4hi:
5788 case X86::BI__builtin_ia32_vec_ext_v16qi:
5789 case X86::BI__builtin_ia32_vec_ext_v8hi:
5790 case X86::BI__builtin_ia32_vec_ext_v4si:
5791 case X86::BI__builtin_ia32_vec_ext_v2di:
5792 case X86::BI__builtin_ia32_vec_ext_v32qi:
5793 case X86::BI__builtin_ia32_vec_ext_v16hi:
5794 case X86::BI__builtin_ia32_vec_ext_v8si:
5795 case X86::BI__builtin_ia32_vec_ext_v4di:
5796 case X86::BI__builtin_ia32_vec_ext_v4sf:
5797 return interp__builtin_vec_ext(S, OpPC, Call, BuiltinID);
5798
5799 case X86::BI__builtin_ia32_vec_set_v4hi:
5800 case X86::BI__builtin_ia32_vec_set_v16qi:
5801 case X86::BI__builtin_ia32_vec_set_v8hi:
5802 case X86::BI__builtin_ia32_vec_set_v4si:
5803 case X86::BI__builtin_ia32_vec_set_v2di:
5804 case X86::BI__builtin_ia32_vec_set_v32qi:
5805 case X86::BI__builtin_ia32_vec_set_v16hi:
5806 case X86::BI__builtin_ia32_vec_set_v8si:
5807 case X86::BI__builtin_ia32_vec_set_v4di:
5808 return interp__builtin_vec_set(S, OpPC, Call, BuiltinID);
5809
5810 case X86::BI__builtin_ia32_cvtb2mask128:
5811 case X86::BI__builtin_ia32_cvtb2mask256:
5812 case X86::BI__builtin_ia32_cvtb2mask512:
5813 case X86::BI__builtin_ia32_cvtw2mask128:
5814 case X86::BI__builtin_ia32_cvtw2mask256:
5815 case X86::BI__builtin_ia32_cvtw2mask512:
5816 case X86::BI__builtin_ia32_cvtd2mask128:
5817 case X86::BI__builtin_ia32_cvtd2mask256:
5818 case X86::BI__builtin_ia32_cvtd2mask512:
5819 case X86::BI__builtin_ia32_cvtq2mask128:
5820 case X86::BI__builtin_ia32_cvtq2mask256:
5821 case X86::BI__builtin_ia32_cvtq2mask512:
5822 return interp__builtin_ia32_cvt_vec2mask(S, OpPC, Call, BuiltinID);
5823
5824 case X86::BI__builtin_ia32_cvtmask2b128:
5825 case X86::BI__builtin_ia32_cvtmask2b256:
5826 case X86::BI__builtin_ia32_cvtmask2b512:
5827 case X86::BI__builtin_ia32_cvtmask2w128:
5828 case X86::BI__builtin_ia32_cvtmask2w256:
5829 case X86::BI__builtin_ia32_cvtmask2w512:
5830 case X86::BI__builtin_ia32_cvtmask2d128:
5831 case X86::BI__builtin_ia32_cvtmask2d256:
5832 case X86::BI__builtin_ia32_cvtmask2d512:
5833 case X86::BI__builtin_ia32_cvtmask2q128:
5834 case X86::BI__builtin_ia32_cvtmask2q256:
5835 case X86::BI__builtin_ia32_cvtmask2q512:
5836 return interp__builtin_ia32_cvt_mask2vec(S, OpPC, Call, BuiltinID);
5837
5838 case X86::BI__builtin_ia32_cvtsd2ss:
5839 return interp__builtin_ia32_cvtsd2ss(S, OpPC, Call, false);
5840
5841 case X86::BI__builtin_ia32_cvtsd2ss_round_mask:
5842 return interp__builtin_ia32_cvtsd2ss(S, OpPC, Call, true);
5843
5844 case X86::BI__builtin_ia32_cvtpd2ps:
5845 case X86::BI__builtin_ia32_cvtpd2ps256:
5846 return interp__builtin_ia32_cvtpd2ps(S, OpPC, Call, false, false);
5847 case X86::BI__builtin_ia32_cvtpd2ps_mask:
5848 return interp__builtin_ia32_cvtpd2ps(S, OpPC, Call, true, false);
5849 case X86::BI__builtin_ia32_cvtpd2ps512_mask:
5850 return interp__builtin_ia32_cvtpd2ps(S, OpPC, Call, true, true);
5851
5852 case X86::BI__builtin_ia32_cmpb128_mask:
5853 case X86::BI__builtin_ia32_cmpw128_mask:
5854 case X86::BI__builtin_ia32_cmpd128_mask:
5855 case X86::BI__builtin_ia32_cmpq128_mask:
5856 case X86::BI__builtin_ia32_cmpb256_mask:
5857 case X86::BI__builtin_ia32_cmpw256_mask:
5858 case X86::BI__builtin_ia32_cmpd256_mask:
5859 case X86::BI__builtin_ia32_cmpq256_mask:
5860 case X86::BI__builtin_ia32_cmpb512_mask:
5861 case X86::BI__builtin_ia32_cmpw512_mask:
5862 case X86::BI__builtin_ia32_cmpd512_mask:
5863 case X86::BI__builtin_ia32_cmpq512_mask:
5864 return interp__builtin_ia32_cmp_mask(S, OpPC, Call, BuiltinID,
5865 /*IsUnsigned=*/false);
5866
5867 case X86::BI__builtin_ia32_ucmpb128_mask:
5868 case X86::BI__builtin_ia32_ucmpw128_mask:
5869 case X86::BI__builtin_ia32_ucmpd128_mask:
5870 case X86::BI__builtin_ia32_ucmpq128_mask:
5871 case X86::BI__builtin_ia32_ucmpb256_mask:
5872 case X86::BI__builtin_ia32_ucmpw256_mask:
5873 case X86::BI__builtin_ia32_ucmpd256_mask:
5874 case X86::BI__builtin_ia32_ucmpq256_mask:
5875 case X86::BI__builtin_ia32_ucmpb512_mask:
5876 case X86::BI__builtin_ia32_ucmpw512_mask:
5877 case X86::BI__builtin_ia32_ucmpd512_mask:
5878 case X86::BI__builtin_ia32_ucmpq512_mask:
5879 return interp__builtin_ia32_cmp_mask(S, OpPC, Call, BuiltinID,
5880 /*IsUnsigned=*/true);
5881
5882 case X86::BI__builtin_ia32_vpshufbitqmb128_mask:
5883 case X86::BI__builtin_ia32_vpshufbitqmb256_mask:
5884 case X86::BI__builtin_ia32_vpshufbitqmb512_mask:
5886
5887 case X86::BI__builtin_ia32_pslldqi128_byteshift:
5888 case X86::BI__builtin_ia32_pslldqi256_byteshift:
5889 case X86::BI__builtin_ia32_pslldqi512_byteshift:
5890 // These SLLDQ intrinsics always operate on byte elements (8 bits).
5891 // The lane width is hardcoded to 16 to match the SIMD register size,
5892 // but the algorithm processes one byte per iteration,
5893 // so APInt(8, ...) is correct and intentional.
5895 S, OpPC, Call,
5896 [](unsigned DstIdx, unsigned Shift) -> std::pair<unsigned, int> {
5897 unsigned LaneBase = (DstIdx / 16) * 16;
5898 unsigned LaneIdx = DstIdx % 16;
5899 if (LaneIdx < Shift)
5900 return std::make_pair(0, -1);
5901
5902 return std::make_pair(0,
5903 static_cast<int>(LaneBase + LaneIdx - Shift));
5904 });
5905
5906 case X86::BI__builtin_ia32_psrldqi128_byteshift:
5907 case X86::BI__builtin_ia32_psrldqi256_byteshift:
5908 case X86::BI__builtin_ia32_psrldqi512_byteshift:
5909 // These SRLDQ intrinsics always operate on byte elements (8 bits).
5910 // The lane width is hardcoded to 16 to match the SIMD register size,
5911 // but the algorithm processes one byte per iteration,
5912 // so APInt(8, ...) is correct and intentional.
5914 S, OpPC, Call,
5915 [](unsigned DstIdx, unsigned Shift) -> std::pair<unsigned, int> {
5916 unsigned LaneBase = (DstIdx / 16) * 16;
5917 unsigned LaneIdx = DstIdx % 16;
5918 if (LaneIdx + Shift < 16)
5919 return std::make_pair(0,
5920 static_cast<int>(LaneBase + LaneIdx + Shift));
5921
5922 return std::make_pair(0, -1);
5923 });
5924
5925 case X86::BI__builtin_ia32_palignr128:
5926 case X86::BI__builtin_ia32_palignr256:
5927 case X86::BI__builtin_ia32_palignr512:
5929 S, OpPC, Call, [](unsigned DstIdx, unsigned Shift) {
5930 // Default to -1 → zero-fill this destination element
5931 unsigned VecIdx = 1;
5932 int ElemIdx = -1;
5933
5934 int Lane = DstIdx / 16;
5935 int Offset = DstIdx % 16;
5936
5937 // Elements come from VecB first, then VecA after the shift boundary
5938 unsigned ShiftedIdx = Offset + (Shift & 0xFF);
5939 if (ShiftedIdx < 16) { // from VecB
5940 ElemIdx = ShiftedIdx + (Lane * 16);
5941 } else if (ShiftedIdx < 32) { // from VecA
5942 VecIdx = 0;
5943 ElemIdx = (ShiftedIdx - 16) + (Lane * 16);
5944 }
5945
5946 return std::pair<unsigned, int>{VecIdx, ElemIdx};
5947 });
5948
5949 case X86::BI__builtin_ia32_alignd128:
5950 case X86::BI__builtin_ia32_alignd256:
5951 case X86::BI__builtin_ia32_alignd512:
5952 case X86::BI__builtin_ia32_alignq128:
5953 case X86::BI__builtin_ia32_alignq256:
5954 case X86::BI__builtin_ia32_alignq512: {
5955 unsigned NumElems = Call->getType()->castAs<VectorType>()->getNumElements();
5957 S, OpPC, Call, [NumElems](unsigned DstIdx, unsigned Shift) {
5958 unsigned Imm = Shift & 0xFF;
5959 unsigned EffectiveShift = Imm & (NumElems - 1);
5960 unsigned SourcePos = DstIdx + EffectiveShift;
5961 unsigned VecIdx = SourcePos < NumElems ? 1u : 0u;
5962 unsigned ElemIdx = SourcePos & (NumElems - 1);
5963 return std::pair<unsigned, int>{VecIdx, static_cast<int>(ElemIdx)};
5964 });
5965 }
5966
5967 case clang::X86::BI__builtin_ia32_minps:
5968 case clang::X86::BI__builtin_ia32_minpd:
5969 case clang::X86::BI__builtin_ia32_minph128:
5970 case clang::X86::BI__builtin_ia32_minph256:
5971 case clang::X86::BI__builtin_ia32_minps256:
5972 case clang::X86::BI__builtin_ia32_minpd256:
5973 case clang::X86::BI__builtin_ia32_minps512:
5974 case clang::X86::BI__builtin_ia32_minpd512:
5975 case clang::X86::BI__builtin_ia32_minph512:
5977 S, OpPC, Call,
5978 [](const APFloat &A, const APFloat &B,
5979 std::optional<APSInt>) -> std::optional<APFloat> {
5980 if (A.isNaN() || A.isInfinity() || A.isDenormal() || B.isNaN() ||
5981 B.isInfinity() || B.isDenormal())
5982 return std::nullopt;
5983 if (A.isZero() && B.isZero())
5984 return B;
5985 return llvm::minimum(A, B);
5986 });
5987
5988 case clang::X86::BI__builtin_ia32_minss:
5989 case clang::X86::BI__builtin_ia32_minsd:
5991 S, OpPC, Call,
5992 [](const APFloat &A, const APFloat &B,
5993 std::optional<APSInt> RoundingMode) -> std::optional<APFloat> {
5994 return EvalScalarMinMaxFp(A, B, RoundingMode, /*IsMin=*/true);
5995 },
5996 /*IsScalar=*/true);
5997
5998 case clang::X86::BI__builtin_ia32_minsd_round_mask:
5999 case clang::X86::BI__builtin_ia32_minss_round_mask:
6000 case clang::X86::BI__builtin_ia32_minsh_round_mask:
6001 case clang::X86::BI__builtin_ia32_maxsd_round_mask:
6002 case clang::X86::BI__builtin_ia32_maxss_round_mask:
6003 case clang::X86::BI__builtin_ia32_maxsh_round_mask: {
6004 bool IsMin = BuiltinID == clang::X86::BI__builtin_ia32_minsd_round_mask ||
6005 BuiltinID == clang::X86::BI__builtin_ia32_minss_round_mask ||
6006 BuiltinID == clang::X86::BI__builtin_ia32_minsh_round_mask;
6008 S, OpPC, Call,
6009 [IsMin](const APFloat &A, const APFloat &B,
6010 std::optional<APSInt> RoundingMode) -> std::optional<APFloat> {
6011 return EvalScalarMinMaxFp(A, B, RoundingMode, IsMin);
6012 });
6013 }
6014
6015 case clang::X86::BI__builtin_ia32_maxps:
6016 case clang::X86::BI__builtin_ia32_maxpd:
6017 case clang::X86::BI__builtin_ia32_maxph128:
6018 case clang::X86::BI__builtin_ia32_maxph256:
6019 case clang::X86::BI__builtin_ia32_maxps256:
6020 case clang::X86::BI__builtin_ia32_maxpd256:
6021 case clang::X86::BI__builtin_ia32_maxps512:
6022 case clang::X86::BI__builtin_ia32_maxpd512:
6023 case clang::X86::BI__builtin_ia32_maxph512:
6025 S, OpPC, Call,
6026 [](const APFloat &A, const APFloat &B,
6027 std::optional<APSInt>) -> std::optional<APFloat> {
6028 if (A.isNaN() || A.isInfinity() || A.isDenormal() || B.isNaN() ||
6029 B.isInfinity() || B.isDenormal())
6030 return std::nullopt;
6031 if (A.isZero() && B.isZero())
6032 return B;
6033 return llvm::maximum(A, B);
6034 });
6035
6036 case clang::X86::BI__builtin_ia32_maxss:
6037 case clang::X86::BI__builtin_ia32_maxsd:
6039 S, OpPC, Call,
6040 [](const APFloat &A, const APFloat &B,
6041 std::optional<APSInt> RoundingMode) -> std::optional<APFloat> {
6042 return EvalScalarMinMaxFp(A, B, RoundingMode, /*IsMin=*/false);
6043 },
6044 /*IsScalar=*/true);
6045
6046 default:
6047 S.FFDiag(S.Current->getLocation(OpPC),
6048 diag::note_invalid_subexpr_in_const_expr)
6049 << S.Current->getRange(OpPC);
6050
6051 return false;
6052 }
6053
6054 llvm_unreachable("Unhandled builtin ID");
6055}
6056
6058 ArrayRef<int64_t> ArrayIndices, int64_t &IntResult) {
6061 unsigned N = E->getNumComponents();
6062 assert(N > 0);
6063
6064 unsigned ArrayIndex = 0;
6065 QualType CurrentType = E->getTypeSourceInfo()->getType();
6066 for (unsigned I = 0; I != N; ++I) {
6067 const OffsetOfNode &Node = E->getComponent(I);
6068 switch (Node.getKind()) {
6069 case OffsetOfNode::Field: {
6070 const FieldDecl *MemberDecl = Node.getField();
6071 const auto *RD = CurrentType->getAsRecordDecl();
6072 if (!RD || RD->isInvalidDecl())
6073 return false;
6075 unsigned FieldIndex = MemberDecl->getFieldIndex();
6076 assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");
6077 Result +=
6079 CurrentType = MemberDecl->getType().getNonReferenceType();
6080 break;
6081 }
6082 case OffsetOfNode::Array: {
6083 // When generating bytecode, we put all the index expressions as Sint64 on
6084 // the stack.
6085 int64_t Index = ArrayIndices[ArrayIndex];
6086 const ArrayType *AT = S.getASTContext().getAsArrayType(CurrentType);
6087 if (!AT)
6088 return false;
6089 CurrentType = AT->getElementType();
6090 CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType);
6091 Result += Index * ElementSize;
6092 ++ArrayIndex;
6093 break;
6094 }
6095 case OffsetOfNode::Base: {
6096 const CXXBaseSpecifier *BaseSpec = Node.getBase();
6097 if (BaseSpec->isVirtual())
6098 return false;
6099
6100 // Find the layout of the class whose base we are looking into.
6101 const auto *RD = CurrentType->getAsCXXRecordDecl();
6102 if (!RD || RD->isInvalidDecl())
6103 return false;
6105
6106 // Find the base class itself.
6107 CurrentType = BaseSpec->getType();
6108 const auto *BaseRD = CurrentType->getAsCXXRecordDecl();
6109 if (!BaseRD)
6110 return false;
6111
6112 // Add the offset to the base.
6113 Result += RL.getBaseClassOffset(BaseRD);
6114 break;
6115 }
6117 llvm_unreachable("Dependent OffsetOfExpr?");
6118 }
6119 }
6120
6121 IntResult = Result.getQuantity();
6122
6123 return true;
6124}
6125
6127 const Pointer &Ptr, const APSInt &IntValue) {
6128
6129 const Record *R = Ptr.getRecord();
6130 assert(R);
6131 assert(R->getNumFields() == 1);
6132
6133 unsigned FieldOffset = R->getField(0u)->Offset;
6134 const Pointer &FieldPtr = Ptr.atField(FieldOffset);
6135 PrimType FieldT = *S.getContext().classify(FieldPtr.getType());
6136
6137 INT_TYPE_SWITCH(FieldT,
6138 FieldPtr.deref<T>() = T::from(IntValue.getSExtValue()));
6139 FieldPtr.initialize();
6140 return true;
6141}
6142
6143static void zeroAll(Pointer &Dest) {
6144 const Descriptor *Desc = Dest.getFieldDesc();
6145
6146 if (Desc->isPrimitive()) {
6147 TYPE_SWITCH(Desc->getPrimType(), {
6148 Dest.deref<T>().~T();
6149 new (&Dest.deref<T>()) T();
6150 });
6151 return;
6152 }
6153
6154 if (Desc->isRecord()) {
6155 const Record *R = Desc->ElemRecord;
6156 for (const Record::Field &F : R->fields()) {
6157 Pointer FieldPtr = Dest.atField(F.Offset);
6158 zeroAll(FieldPtr);
6159 }
6160 return;
6161 }
6162
6163 if (Desc->isPrimitiveArray()) {
6164 for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
6165 TYPE_SWITCH(Desc->getPrimType(), {
6166 Dest.deref<T>().~T();
6167 new (&Dest.deref<T>()) T();
6168 });
6169 }
6170 return;
6171 }
6172
6173 if (Desc->isCompositeArray()) {
6174 for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
6175 Pointer ElemPtr = Dest.atIndex(I).narrow();
6176 zeroAll(ElemPtr);
6177 }
6178 return;
6179 }
6180}
6181
6182static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
6183 Pointer &Dest, bool Activate);
6184static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,
6185 Pointer &Dest, bool Activate = false) {
6186 [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
6187 const Descriptor *DestDesc = Dest.getFieldDesc();
6188
6189 auto copyField = [&](const Record::Field &F, bool Activate) -> bool {
6190 Pointer DestField = Dest.atField(F.Offset);
6191 if (OptPrimType FT = S.Ctx.classify(F.Decl->getType())) {
6192 TYPE_SWITCH(*FT, {
6193 DestField.deref<T>() = Src.atField(F.Offset).deref<T>();
6194 if (Src.atField(F.Offset).isInitialized())
6195 DestField.initialize();
6196 if (Activate)
6197 DestField.activate();
6198 });
6199 return true;
6200 }
6201 // Composite field.
6202 return copyComposite(S, OpPC, Src.atField(F.Offset), DestField, Activate);
6203 };
6204
6205 assert(SrcDesc->isRecord());
6206 assert(SrcDesc->ElemRecord == DestDesc->ElemRecord);
6207 const Record *R = DestDesc->ElemRecord;
6208 for (const Record::Field &F : R->fields()) {
6209 if (R->isUnion()) {
6210 // For unions, only copy the active field. Zero all others.
6211 const Pointer &SrcField = Src.atField(F.Offset);
6212 if (SrcField.isActive()) {
6213 if (!copyField(F, /*Activate=*/true))
6214 return false;
6215 } else {
6216 if (!CheckMutable(S, OpPC, Src.atField(F.Offset)))
6217 return false;
6218 Pointer DestField = Dest.atField(F.Offset);
6219 zeroAll(DestField);
6220 }
6221 } else {
6222 if (!copyField(F, Activate))
6223 return false;
6224 }
6225 }
6226
6227 for (const Record::Base &B : R->bases()) {
6228 Pointer DestBase = Dest.atField(B.Offset);
6229 if (!copyRecord(S, OpPC, Src.atField(B.Offset), DestBase, Activate))
6230 return false;
6231 }
6232
6233 Dest.initialize();
6234 return true;
6235}
6236
6237static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
6238 Pointer &Dest, bool Activate = false) {
6239 assert(Src.isLive() && Dest.isLive());
6240
6241 [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
6242 const Descriptor *DestDesc = Dest.getFieldDesc();
6243
6244 assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive());
6245
6246 if (DestDesc->isPrimitiveArray()) {
6247 assert(SrcDesc->isPrimitiveArray());
6248 assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
6249 PrimType ET = DestDesc->getPrimType();
6250 for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
6251 Pointer DestElem = Dest.atIndex(I);
6252 TYPE_SWITCH(ET, {
6253 DestElem.deref<T>() = Src.elem<T>(I);
6254 DestElem.initialize();
6255 });
6256 }
6257 return true;
6258 }
6259
6260 if (DestDesc->isCompositeArray()) {
6261 assert(SrcDesc->isCompositeArray());
6262 assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
6263 for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
6264 const Pointer &SrcElem = Src.atIndex(I).narrow();
6265 Pointer DestElem = Dest.atIndex(I).narrow();
6266 if (!copyComposite(S, OpPC, SrcElem, DestElem, Activate))
6267 return false;
6268 }
6269 return true;
6270 }
6271
6272 if (DestDesc->isRecord())
6273 return copyRecord(S, OpPC, Src, Dest, Activate);
6274 return Invalid(S, OpPC);
6275}
6276
6277bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {
6278 if (!Src.isBlockPointer() || Src.getFieldDesc()->isPrimitive())
6279 return false;
6280 if (!Dest.isBlockPointer() || Dest.getFieldDesc()->isPrimitive())
6281 return false;
6282
6283 return copyComposite(S, OpPC, Src, Dest);
6284}
6285
6286} // namespace interp
6287} // 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:796
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:635
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:594
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:711
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:547
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:119
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:1105
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:1641
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:583
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:777
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:508
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:402
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:1171
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:394
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:3653
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
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:121
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition Descriptor.h:258
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition Descriptor.h:272
QualType getElemQualType() const
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
Definition Descriptor.h:265
const ValueDecl * asValueDecl() const
Definition Descriptor.h:214
static constexpr unsigned MaxArrayElemBytes
Maximum number of bytes to be used for array elements.
Definition Descriptor.h:147
QualType getType() const
const Decl * asDecl() const
Definition Descriptor.h:210
static constexpr MetadataSize InlineDescMD
Definition Descriptor.h:143
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:263
const VarDecl * asVarDecl() const
Definition Descriptor.h:218
PrimType getPrimType() const
Definition Descriptor.h:240
bool isRecord() const
Checks if the descriptor is of a record.
Definition Descriptor.h:277
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition Descriptor.h:152
const Expr * asExpr() const
Definition Descriptor.h:211
bool isArray() const
Checks if the descriptor is of an array.
Definition Descriptor.h:275
Mapping from primitive types to their representation.
Definition PrimType.h:150