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