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