clang 23.0.0git
InterpBuiltin.cpp
Go to the documentation of this file.
1//===--- InterpBuiltin.cpp - Interpreter for the constexpr VM ---*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
9#include "Boolean.h"
10#include "Char.h"
11#include "EvalEmitter.h"
13#include "InterpHelpers.h"
14#include "PrimType.h"
15#include "Program.h"
17#include "clang/AST/OSLog.h"
22#include "llvm/ADT/StringExtras.h"
23#include "llvm/Support/AllocToken.h"
24#include "llvm/Support/ErrorHandling.h"
25#include "llvm/Support/SipHash.h"
26
27namespace clang {
28namespace interp {
29
30[[maybe_unused]] static bool isNoopBuiltin(unsigned ID) {
31 switch (ID) {
32 case Builtin::BIas_const:
33 case Builtin::BIforward:
34 case Builtin::BIforward_like:
35 case Builtin::BImove:
36 case Builtin::BImove_if_noexcept:
37 case Builtin::BIaddressof:
38 case Builtin::BI__addressof:
39 case Builtin::BI__builtin_addressof:
40 case Builtin::BI__builtin_launder:
41 return true;
42 default:
43 return false;
44 }
45 return false;
46}
47
48static void discard(InterpStack &Stk, PrimType T) {
49 TYPE_SWITCH(T, { Stk.discard<T>(); });
50}
51
52static 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) {
97 OptPrimType T = *S.getContext().classify(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.
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 CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue());
1378
1379 // If there is a base object, then it must have the correct alignment.
1380 if (Ptr.isBlockPointer()) {
1381 CharUnits BaseAlignment;
1382 if (const auto *VD = Ptr.getDeclDesc()->asValueDecl())
1383 BaseAlignment = S.getASTContext().getDeclAlign(VD);
1384 else if (const auto *E = Ptr.getDeclDesc()->asExpr())
1385 BaseAlignment = GetAlignOfExpr(S.getASTContext(), E, UETT_AlignOf);
1386
1387 if (BaseAlignment < Align) {
1388 S.CCEDiag(Call->getArg(0),
1389 diag::note_constexpr_baa_insufficient_alignment)
1390 << 0 << BaseAlignment.getQuantity() << Align.getQuantity();
1391 return false;
1392 }
1393 }
1394
1395 APValue AV = Ptr.toAPValue(S.getASTContext());
1396 CharUnits AVOffset = AV.getLValueOffset();
1397 if (ExtraOffset)
1398 AVOffset -= CharUnits::fromQuantity(ExtraOffset->getZExtValue());
1399 if (AVOffset.alignTo(Align) != AVOffset) {
1400 if (Ptr.isBlockPointer())
1401 S.CCEDiag(Call->getArg(0),
1402 diag::note_constexpr_baa_insufficient_alignment)
1403 << 1 << AVOffset.getQuantity() << Align.getQuantity();
1404 else
1405 S.CCEDiag(Call->getArg(0),
1406 diag::note_constexpr_baa_value_insufficient_alignment)
1407 << AVOffset.getQuantity() << Align.getQuantity();
1408 return false;
1409 }
1410
1411 S.Stk.push<Pointer>(Ptr);
1412 return true;
1413}
1414
1415/// (CarryIn, LHS, RHS, Result)
1417 CodePtr OpPC,
1418 const InterpFrame *Frame,
1419 const CallExpr *Call,
1420 bool IsAdd) {
1421 if (Call->getNumArgs() != 4 || !Call->getArg(0)->getType()->isIntegerType() ||
1422 !Call->getArg(1)->getType()->isIntegerType() ||
1423 !Call->getArg(2)->getType()->isIntegerType())
1424 return false;
1425
1426 const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();
1427
1428 APSInt RHS;
1429 if (!popToAPSInt(S, Call->getArg(2), RHS))
1430 return false;
1431 APSInt LHS;
1432 if (!popToAPSInt(S, Call->getArg(1), LHS))
1433 return false;
1434 APSInt CarryIn;
1435 if (!popToAPSInt(S, Call->getArg(0), CarryIn))
1436 return false;
1437
1438 unsigned BitWidth = LHS.getBitWidth();
1439 unsigned CarryInBit = CarryIn.ugt(0) ? 1 : 0;
1440 APInt ExResult =
1441 IsAdd ? (LHS.zext(BitWidth + 1) + (RHS.zext(BitWidth + 1) + CarryInBit))
1442 : (LHS.zext(BitWidth + 1) - (RHS.zext(BitWidth + 1) + CarryInBit));
1443
1444 APInt Result = ExResult.extractBits(BitWidth, 0);
1445 APSInt CarryOut =
1446 APSInt(ExResult.extractBits(1, BitWidth), /*IsUnsigned=*/true);
1447
1448 QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
1449 PrimType CarryOutT = *S.getContext().classify(CarryOutType);
1450 assignIntegral(S, CarryOutPtr, CarryOutT, APSInt(std::move(Result), true));
1451
1452 pushInteger(S, CarryOut, Call->getType());
1453
1454 return true;
1455}
1456
1458 CodePtr OpPC,
1459 const InterpFrame *Frame,
1460 const CallExpr *Call) {
1463 pushInteger(S, Layout.size().getQuantity(), Call->getType());
1464 return true;
1465}
1466
1467static bool
1469 const InterpFrame *Frame,
1470 const CallExpr *Call) {
1471 const auto &Ptr = S.Stk.pop<Pointer>();
1472 assert(Ptr.getFieldDesc()->isPrimitiveArray());
1473
1474 // This should be created for a StringLiteral, so always holds at least
1475 // one array element.
1476 assert(Ptr.getFieldDesc()->getNumElems() >= 1);
1477 uint64_t Result = getPointerAuthStableSipHash(
1478 cast<StringLiteral>(Ptr.getFieldDesc()->asExpr())->getString());
1479 pushInteger(S, Result, Call->getType());
1480 return true;
1481}
1482
1484 const InterpFrame *Frame,
1485 const CallExpr *Call) {
1486 const ASTContext &ASTCtx = S.getASTContext();
1487 uint64_t BitWidth = ASTCtx.getTypeSize(ASTCtx.getSizeType());
1488 auto Mode =
1489 ASTCtx.getLangOpts().AllocTokenMode.value_or(llvm::DefaultAllocTokenMode);
1490 auto MaxTokensOpt = ASTCtx.getLangOpts().AllocTokenMax;
1491 uint64_t MaxTokens =
1492 MaxTokensOpt.value_or(0) ? *MaxTokensOpt : (~0ULL >> (64 - BitWidth));
1493
1494 // We do not read any of the arguments; discard them.
1495 for (int I = Call->getNumArgs() - 1; I >= 0; --I)
1496 discard(S.Stk, S.getContext().classify(Call->getArg(I)).value_or(PT_Ptr));
1497
1498 // Note: Type inference from a surrounding cast is not supported in
1499 // constexpr evaluation.
1500 QualType AllocType = infer_alloc::inferPossibleType(Call, ASTCtx, nullptr);
1501 if (AllocType.isNull()) {
1502 S.CCEDiag(Call,
1503 diag::note_constexpr_infer_alloc_token_type_inference_failed);
1504 return false;
1505 }
1506
1507 auto ATMD = infer_alloc::getAllocTokenMetadata(AllocType, ASTCtx);
1508 if (!ATMD) {
1509 S.CCEDiag(Call, diag::note_constexpr_infer_alloc_token_no_metadata);
1510 return false;
1511 }
1512
1513 auto MaybeToken = llvm::getAllocToken(Mode, *ATMD, MaxTokens);
1514 if (!MaybeToken) {
1515 S.CCEDiag(Call, diag::note_constexpr_infer_alloc_token_stateful_mode);
1516 return false;
1517 }
1518
1519 pushInteger(S, llvm::APInt(BitWidth, *MaybeToken), ASTCtx.getSizeType());
1520 return true;
1521}
1522
1524 const InterpFrame *Frame,
1525 const CallExpr *Call) {
1526 // A call to __operator_new is only valid within std::allocate<>::allocate.
1527 // Walk up the call stack to find the appropriate caller and get the
1528 // element type from it.
1529 auto [NewCall, ElemType] = S.getStdAllocatorCaller("allocate");
1530
1531 if (ElemType.isNull()) {
1532 S.FFDiag(Call, S.getLangOpts().CPlusPlus20
1533 ? diag::note_constexpr_new_untyped
1534 : diag::note_constexpr_new);
1535 return false;
1536 }
1537 assert(NewCall);
1538
1539 if (ElemType->isIncompleteType() || ElemType->isFunctionType()) {
1540 S.FFDiag(Call, diag::note_constexpr_new_not_complete_object_type)
1541 << (ElemType->isIncompleteType() ? 0 : 1) << ElemType;
1542 return false;
1543 }
1544
1545 // We only care about the first parameter (the size), so discard all the
1546 // others.
1547 {
1548 unsigned NumArgs = Call->getNumArgs();
1549 assert(NumArgs >= 1);
1550
1551 // The std::nothrow_t arg never gets put on the stack.
1552 if (Call->getArg(NumArgs - 1)->getType()->isNothrowT())
1553 --NumArgs;
1554 auto Args = ArrayRef(Call->getArgs(), Call->getNumArgs());
1555 // First arg is needed.
1556 Args = Args.drop_front();
1557
1558 // Discard the rest.
1559 for (const Expr *Arg : Args)
1560 discard(S.Stk, *S.getContext().classify(Arg));
1561 }
1562
1563 APSInt Bytes;
1564 if (!popToAPSInt(S, Call->getArg(0), Bytes))
1565 return false;
1566 CharUnits ElemSize = S.getASTContext().getTypeSizeInChars(ElemType);
1567 assert(!ElemSize.isZero());
1568 // Divide the number of bytes by sizeof(ElemType), so we get the number of
1569 // elements we should allocate.
1570 APInt NumElems, Remainder;
1571 APInt ElemSizeAP(Bytes.getBitWidth(), ElemSize.getQuantity());
1572 APInt::udivrem(Bytes, ElemSizeAP, NumElems, Remainder);
1573 if (Remainder != 0) {
1574 // This likely indicates a bug in the implementation of 'std::allocator'.
1575 S.FFDiag(Call, diag::note_constexpr_operator_new_bad_size)
1576 << Bytes << APSInt(ElemSizeAP, true) << ElemType;
1577 return false;
1578 }
1579
1580 // NB: The same check we're using in CheckArraySize()
1581 if (NumElems.getActiveBits() >
1583 NumElems.ugt(Descriptor::MaxArrayElemBytes / ElemSize.getQuantity())) {
1584 // FIXME: NoThrow check?
1585 const SourceInfo &Loc = S.Current->getSource(OpPC);
1586 S.FFDiag(Loc, diag::note_constexpr_new_too_large)
1587 << NumElems.getZExtValue();
1588 return false;
1589 }
1590
1591 if (!CheckArraySize(S, OpPC, NumElems.getZExtValue()))
1592 return false;
1593
1594 bool IsArray = NumElems.ugt(1);
1595 OptPrimType ElemT = S.getContext().classify(ElemType);
1596 DynamicAllocator &Allocator = S.getAllocator();
1597 if (ElemT) {
1598 Block *B =
1599 Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(),
1601 assert(B);
1602 S.Stk.push<Pointer>(Pointer(B).atIndex(0));
1603 return true;
1604 }
1605
1606 assert(!ElemT);
1607
1608 // Composite arrays
1609 if (IsArray) {
1610 const Descriptor *Desc =
1611 S.P.createDescriptor(NewCall, ElemType.getTypePtr(), std::nullopt);
1612 Block *B =
1613 Allocator.allocate(Desc, NumElems.getZExtValue(), S.Ctx.getEvalID(),
1615 assert(B);
1616 S.Stk.push<Pointer>(Pointer(B).atIndex(0).narrow());
1617 return true;
1618 }
1619
1620 // Records. Still allocate them as single-element arrays.
1622 ElemType, NumElems, nullptr, ArraySizeModifier::Normal, 0);
1623
1624 const Descriptor *Desc = S.P.createDescriptor(NewCall, AllocType.getTypePtr(),
1626 Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(),
1628 assert(B);
1629 S.Stk.push<Pointer>(Pointer(B).atIndex(0).narrow());
1630 return true;
1631}
1632
1634 const InterpFrame *Frame,
1635 const CallExpr *Call) {
1636 const Expr *Source = nullptr;
1637 const Block *BlockToDelete = nullptr;
1638
1639 unsigned NumArgs = Call->getNumArgs();
1640 assert(NumArgs >= 1);
1641
1642 // Args are pushed in source order. The trailing sized/aligned delete
1643 // operands are above the pointer on the stack.
1644 for (unsigned I = NumArgs - 1; I != 0; --I)
1645 discard(S.Stk, *S.getContext().classify(Call->getArg(I)));
1646
1648 S.Stk.discard<Pointer>();
1649 return false;
1650 }
1651
1652 // This is permitted only within a call to std::allocator<T>::deallocate.
1653 if (!S.getStdAllocatorCaller("deallocate")) {
1654 S.FFDiag(Call);
1655 S.Stk.discard<Pointer>();
1656 return true;
1657 }
1658
1659 {
1660 const Pointer &Ptr = S.Stk.pop<Pointer>();
1661
1662 if (Ptr.isZero()) {
1663 S.CCEDiag(Call, diag::note_constexpr_deallocate_null);
1664 return true;
1665 }
1666
1667 Source = Ptr.getDeclDesc()->asExpr();
1668 BlockToDelete = Ptr.block();
1669
1670 if (!BlockToDelete->isDynamic()) {
1671 S.FFDiag(Call, diag::note_constexpr_delete_not_heap_alloc)
1673 if (const auto *D = Ptr.getFieldDesc()->asDecl())
1674 S.Note(D->getLocation(), diag::note_declared_at);
1675 }
1676 }
1677 assert(BlockToDelete);
1678
1679 DynamicAllocator &Allocator = S.getAllocator();
1680 const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
1681 std::optional<DynamicAllocator::Form> AllocForm =
1682 Allocator.getAllocationForm(Source);
1683
1684 if (!Allocator.deallocate(Source, BlockToDelete)) {
1685 // Nothing has been deallocated, this must be a double-delete.
1686 const SourceInfo &Loc = S.Current->getSource(OpPC);
1687 S.FFDiag(Loc, diag::note_constexpr_double_delete);
1688 return false;
1689 }
1690 assert(AllocForm);
1691
1692 return CheckNewDeleteForms(
1693 S, OpPC, *AllocForm, DynamicAllocator::Form::Operator, BlockDesc, Source);
1694}
1695
1697 const InterpFrame *Frame,
1698 const CallExpr *Call) {
1699 const Floating &Arg0 = S.Stk.pop<Floating>();
1700 S.Stk.push<Floating>(Arg0);
1701 return true;
1702}
1703
1705 const CallExpr *Call, unsigned ID) {
1706 const Pointer &Arg = S.Stk.pop<Pointer>();
1707 assert(Arg.getFieldDesc()->isPrimitiveArray());
1708
1709 QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1710 assert(Call->getType() == ElemType);
1711 PrimType ElemT = *S.getContext().classify(ElemType);
1712 unsigned NumElems = Arg.getNumElems();
1713
1715 T Result = Arg.elem<T>(0);
1716 unsigned BitWidth = Result.bitWidth();
1717 for (unsigned I = 1; I != NumElems; ++I) {
1718 T Elem = Arg.elem<T>(I);
1719 T PrevResult = Result;
1720
1721 if (ID == Builtin::BI__builtin_reduce_add) {
1722 if (T::add(Result, Elem, BitWidth, &Result)) {
1723 unsigned OverflowBits = BitWidth + 1;
1724 (void)handleOverflow(S, OpPC,
1725 (PrevResult.toAPSInt(OverflowBits) +
1726 Elem.toAPSInt(OverflowBits)));
1727 return false;
1728 }
1729 } else if (ID == Builtin::BI__builtin_reduce_mul) {
1730 if (T::mul(Result, Elem, BitWidth, &Result)) {
1731 unsigned OverflowBits = BitWidth * 2;
1732 (void)handleOverflow(S, OpPC,
1733 (PrevResult.toAPSInt(OverflowBits) *
1734 Elem.toAPSInt(OverflowBits)));
1735 return false;
1736 }
1737
1738 } else if (ID == Builtin::BI__builtin_reduce_and) {
1739 (void)T::bitAnd(Result, Elem, BitWidth, &Result);
1740 } else if (ID == Builtin::BI__builtin_reduce_or) {
1741 (void)T::bitOr(Result, Elem, BitWidth, &Result);
1742 } else if (ID == Builtin::BI__builtin_reduce_xor) {
1743 (void)T::bitXor(Result, Elem, BitWidth, &Result);
1744 } else if (ID == Builtin::BI__builtin_reduce_min) {
1745 if (Elem < Result)
1746 Result = Elem;
1747 } else if (ID == Builtin::BI__builtin_reduce_max) {
1748 if (Elem > Result)
1749 Result = Elem;
1750 } else {
1751 llvm_unreachable("Unhandled vector reduce builtin");
1752 }
1753 }
1754 pushInteger(S, Result.toAPSInt(), Call->getType());
1755 });
1756
1757 return true;
1758}
1759
1761 const InterpFrame *Frame,
1762 const CallExpr *Call,
1763 unsigned BuiltinID) {
1764 assert(Call->getNumArgs() == 1);
1765 QualType Ty = Call->getArg(0)->getType();
1766 if (Ty->isIntegerType()) {
1767 APSInt Val;
1768 if (!popToAPSInt(S, Call->getArg(0), Val))
1769 return false;
1770 pushInteger(S, Val.abs(), Call->getType());
1771 return true;
1772 }
1773
1774 if (Ty->isFloatingType()) {
1775 Floating Val = S.Stk.pop<Floating>();
1776 Floating Result = abs(S, Val);
1777 S.Stk.push<Floating>(Result);
1778 return true;
1779 }
1780
1781 // Otherwise, the argument must be a vector.
1782 assert(Call->getArg(0)->getType()->isVectorType());
1783 const Pointer &Arg = S.Stk.pop<Pointer>();
1784 assert(Arg.getFieldDesc()->isPrimitiveArray());
1785 const Pointer &Dst = S.Stk.peek<Pointer>();
1786 assert(Dst.getFieldDesc()->isPrimitiveArray());
1787 assert(Arg.getFieldDesc()->getNumElems() ==
1788 Dst.getFieldDesc()->getNumElems());
1789
1790 QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1791 PrimType ElemT = *S.getContext().classify(ElemType);
1792 unsigned NumElems = Arg.getNumElems();
1793 // we can either have a vector of integer or a vector of floating point
1794 for (unsigned I = 0; I != NumElems; ++I) {
1795 if (ElemType->isIntegerType()) {
1797 Dst.elem<T>(I) = T::from(static_cast<T>(
1798 APSInt(Arg.elem<T>(I).toAPSInt().abs(),
1800 });
1801 } else {
1802 Floating Val = Arg.elem<Floating>(I);
1803 Dst.elem<Floating>(I) = abs(S, Val);
1804 }
1805 }
1807
1808 return true;
1809}
1810
1811/// Can be called with an integer or vector as the first and only parameter.
1813 CodePtr OpPC,
1814 const InterpFrame *Frame,
1815 const CallExpr *Call,
1816 unsigned BuiltinID) {
1817 bool HasZeroArg = Call->getNumArgs() == 2;
1818 bool IsCTTZ = BuiltinID == Builtin::BI__builtin_elementwise_ctzg;
1819 assert(Call->getNumArgs() == 1 || HasZeroArg);
1820 if (Call->getArg(0)->getType()->isIntegerType()) {
1821 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
1822 APSInt Val;
1823 if (!popToAPSInt(S.Stk, ArgT, Val))
1824 return false;
1825 std::optional<APSInt> ZeroVal;
1826 if (HasZeroArg) {
1827 ZeroVal = Val;
1828 if (!popToAPSInt(S.Stk, ArgT, Val))
1829 return false;
1830 }
1831
1832 if (Val.isZero()) {
1833 if (ZeroVal) {
1834 pushInteger(S, *ZeroVal, Call->getType());
1835 return true;
1836 }
1837 // If we haven't been provided the second argument, the result is
1838 // undefined
1839 S.FFDiag(S.Current->getSource(OpPC),
1840 diag::note_constexpr_countzeroes_zero)
1841 << /*IsTrailing=*/IsCTTZ;
1842 return false;
1843 }
1844
1845 if (BuiltinID == Builtin::BI__builtin_elementwise_clzg) {
1846 pushInteger(S, Val.countLeadingZeros(), Call->getType());
1847 } else {
1848 pushInteger(S, Val.countTrailingZeros(), Call->getType());
1849 }
1850 return true;
1851 }
1852 // Otherwise, the argument must be a vector.
1853 const ASTContext &ASTCtx = S.getASTContext();
1854 Pointer ZeroArg;
1855 if (HasZeroArg) {
1856 assert(Call->getArg(1)->getType()->isVectorType() &&
1857 ASTCtx.hasSameUnqualifiedType(Call->getArg(0)->getType(),
1858 Call->getArg(1)->getType()));
1859 (void)ASTCtx;
1860 ZeroArg = S.Stk.pop<Pointer>();
1861 assert(ZeroArg.getFieldDesc()->isPrimitiveArray());
1862 }
1863 assert(Call->getArg(0)->getType()->isVectorType());
1864 const Pointer &Arg = S.Stk.pop<Pointer>();
1865 assert(Arg.getFieldDesc()->isPrimitiveArray());
1866 const Pointer &Dst = S.Stk.peek<Pointer>();
1867 assert(Dst.getFieldDesc()->isPrimitiveArray());
1868 assert(Arg.getFieldDesc()->getNumElems() ==
1869 Dst.getFieldDesc()->getNumElems());
1870
1871 QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1872 PrimType ElemT = *S.getContext().classify(ElemType);
1873 unsigned NumElems = Arg.getNumElems();
1874
1875 // FIXME: Reading from uninitialized vector elements?
1876 for (unsigned I = 0; I != NumElems; ++I) {
1878 APInt EltVal = Arg.atIndex(I).deref<T>().toAPSInt();
1879 if (EltVal.isZero()) {
1880 if (HasZeroArg) {
1881 Dst.atIndex(I).deref<T>() = ZeroArg.atIndex(I).deref<T>();
1882 } else {
1883 // If we haven't been provided the second argument, the result is
1884 // undefined
1885 S.FFDiag(S.Current->getSource(OpPC),
1886 diag::note_constexpr_countzeroes_zero)
1887 << /*IsTrailing=*/IsCTTZ;
1888 return false;
1889 }
1890 } else if (IsCTTZ) {
1891 Dst.atIndex(I).deref<T>() = T::from(EltVal.countTrailingZeros());
1892 } else {
1893 Dst.atIndex(I).deref<T>() = T::from(EltVal.countLeadingZeros());
1894 }
1895 Dst.atIndex(I).initialize();
1896 });
1897 }
1898
1899 return true;
1900}
1901
1903 const InterpFrame *Frame,
1904 const CallExpr *Call, unsigned ID) {
1905 assert(Call->getNumArgs() == 3);
1906 const ASTContext &ASTCtx = S.getASTContext();
1907 uint64_t Size;
1908 if (!popToUInt64(S, Call->getArg(2), Size))
1909 return false;
1910 Pointer SrcPtr = S.Stk.pop<Pointer>().expand();
1911 Pointer DestPtr = S.Stk.pop<Pointer>().expand();
1912
1913 if (ID == Builtin::BImemcpy || ID == Builtin::BImemmove)
1914 diagnoseNonConstexprBuiltin(S, OpPC, ID);
1915
1916 bool Move =
1917 (ID == Builtin::BI__builtin_memmove || ID == Builtin::BImemmove ||
1918 ID == Builtin::BI__builtin_wmemmove || ID == Builtin::BIwmemmove);
1919 bool WChar = ID == Builtin::BIwmemcpy || ID == Builtin::BIwmemmove ||
1920 ID == Builtin::BI__builtin_wmemcpy ||
1921 ID == Builtin::BI__builtin_wmemmove;
1922
1923 // If the size is zero, we treat this as always being a valid no-op.
1924 if (Size == 0) {
1925 S.Stk.push<Pointer>(DestPtr);
1926 return true;
1927 }
1928
1929 if (SrcPtr.isZero() || DestPtr.isZero()) {
1930 Pointer DiagPtr = (SrcPtr.isZero() ? SrcPtr : DestPtr);
1931 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
1932 << /*IsMove=*/Move << /*IsWchar=*/WChar << !SrcPtr.isZero()
1933 << DiagPtr.toDiagnosticString(ASTCtx);
1934 return false;
1935 }
1936
1937 // Diagnose integral src/dest pointers specially.
1938 if (SrcPtr.isIntegralPointer() || DestPtr.isIntegralPointer()) {
1939 std::string DiagVal = "(void *)";
1940 DiagVal += SrcPtr.isIntegralPointer()
1941 ? std::to_string(SrcPtr.getIntegerRepresentation())
1942 : std::to_string(DestPtr.getIntegerRepresentation());
1943 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
1944 << Move << WChar << DestPtr.isIntegralPointer() << DiagVal;
1945 return false;
1946 }
1947
1948 if (!isReadable(DestPtr) || !isReadable(SrcPtr))
1949 return false;
1950
1951 if (DestPtr.getType()->isIncompleteType()) {
1952 S.FFDiag(S.Current->getSource(OpPC),
1953 diag::note_constexpr_memcpy_incomplete_type)
1954 << Move << DestPtr.getType();
1955 return false;
1956 }
1957 if (SrcPtr.getType()->isIncompleteType()) {
1958 S.FFDiag(S.Current->getSource(OpPC),
1959 diag::note_constexpr_memcpy_incomplete_type)
1960 << Move << SrcPtr.getType();
1961 return false;
1962 }
1963
1964 QualType DestElemType = getElemType(DestPtr);
1965 if (DestElemType->isIncompleteType()) {
1966 S.FFDiag(S.Current->getSource(OpPC),
1967 diag::note_constexpr_memcpy_incomplete_type)
1968 << Move << DestElemType;
1969 return false;
1970 }
1971
1972 size_t RemainingDestElems;
1973 if (DestPtr.getFieldDesc()->isArray()) {
1974 RemainingDestElems = DestPtr.isUnknownSizeArray()
1975 ? 0
1976 : (DestPtr.getNumElems() - DestPtr.getIndex());
1977 } else {
1978 RemainingDestElems = 1;
1979 }
1980 unsigned DestElemSize = ASTCtx.getTypeSizeInChars(DestElemType).getQuantity();
1981
1982 if (WChar) {
1983 uint64_t WCharSize =
1984 ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();
1985 Size *= WCharSize;
1986 }
1987
1988 if (Size % DestElemSize != 0) {
1989 S.FFDiag(S.Current->getSource(OpPC),
1990 diag::note_constexpr_memcpy_unsupported)
1991 << Move << WChar << 0 << DestElemType << Size << DestElemSize;
1992 return false;
1993 }
1994
1995 QualType SrcElemType = getElemType(SrcPtr);
1996 size_t RemainingSrcElems;
1997 if (SrcPtr.getFieldDesc()->isArray()) {
1998 RemainingSrcElems = SrcPtr.isUnknownSizeArray()
1999 ? 0
2000 : (SrcPtr.getNumElems() - SrcPtr.getIndex());
2001 } else {
2002 RemainingSrcElems = 1;
2003 }
2004 unsigned SrcElemSize = ASTCtx.getTypeSizeInChars(SrcElemType).getQuantity();
2005
2006 if (!ASTCtx.hasSameUnqualifiedType(DestElemType, SrcElemType)) {
2007 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_type_pun)
2008 << Move << SrcElemType << DestElemType;
2009 return false;
2010 }
2011
2012 if (!DestElemType.isTriviallyCopyableType(ASTCtx)) {
2013 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_nontrivial)
2014 << Move << DestElemType;
2015 return false;
2016 }
2017
2018 // Check if we have enough elements to read from and write to.
2019 size_t RemainingDestBytes = RemainingDestElems * DestElemSize;
2020 size_t RemainingSrcBytes = RemainingSrcElems * SrcElemSize;
2021 if (Size > RemainingDestBytes || Size > RemainingSrcBytes) {
2022 APInt N = APInt(64, Size / DestElemSize);
2023 S.FFDiag(S.Current->getSource(OpPC),
2024 diag::note_constexpr_memcpy_unsupported)
2025 << Move << WChar << (Size > RemainingSrcBytes ? 1 : 2) << DestElemType
2026 << toString(N, 10, /*Signed=*/false);
2027 return false;
2028 }
2029
2030 // Check for overlapping memory regions.
2031 if (!Move && Pointer::pointToSameBlock(SrcPtr, DestPtr)) {
2032 // Remove base casts.
2033 Pointer SrcP = SrcPtr.stripBaseCasts();
2034 Pointer DestP = DestPtr.stripBaseCasts();
2035
2036 unsigned SrcIndex = SrcP.expand().getIndex() * SrcElemSize;
2037 unsigned DstIndex = DestP.expand().getIndex() * DestElemSize;
2038
2039 if ((SrcIndex <= DstIndex && (SrcIndex + Size) > DstIndex) ||
2040 (DstIndex <= SrcIndex && (DstIndex + Size) > SrcIndex)) {
2041 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_overlap)
2042 << /*IsWChar=*/false;
2043 return false;
2044 }
2045 }
2046
2047 assert(Size % DestElemSize == 0);
2048 if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size).toBits()))
2049 return false;
2050
2051 S.Stk.push<Pointer>(DestPtr);
2052 return true;
2053}
2054
2055/// Determine if T is a character type for which we guarantee that
2056/// sizeof(T) == 1.
2058 return T->isCharType() || T->isChar8Type();
2059}
2060
2062 const InterpFrame *Frame,
2063 const CallExpr *Call, unsigned ID) {
2064 assert(Call->getNumArgs() == 3);
2065 uint64_t Size;
2066 if (!popToUInt64(S, Call->getArg(2), Size))
2067 return false;
2068 const Pointer &PtrB = S.Stk.pop<Pointer>();
2069 const Pointer &PtrA = S.Stk.pop<Pointer>();
2070
2071 if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp ||
2072 ID == Builtin::BIwmemcmp)
2073 diagnoseNonConstexprBuiltin(S, OpPC, ID);
2074
2075 if (Size == 0) {
2076 pushInteger(S, 0, Call->getType());
2077 return true;
2078 }
2079
2080 if (!PtrA.isBlockPointer() || !PtrB.isBlockPointer())
2081 return false;
2082
2083 bool IsWide =
2084 (ID == Builtin::BIwmemcmp || ID == Builtin::BI__builtin_wmemcmp);
2085
2086 const ASTContext &ASTCtx = S.getASTContext();
2087 QualType ElemTypeA = getElemType(PtrA);
2088 QualType ElemTypeB = getElemType(PtrB);
2089 // FIXME: This is an arbitrary limitation the current constant interpreter
2090 // had. We could remove this.
2091 if (!IsWide && (!isOneByteCharacterType(ElemTypeA) ||
2092 !isOneByteCharacterType(ElemTypeB))) {
2093 S.FFDiag(S.Current->getSource(OpPC),
2094 diag::note_constexpr_memcmp_unsupported)
2095 << ASTCtx.BuiltinInfo.getQuotedName(ID) << PtrA.getType()
2096 << PtrB.getType();
2097 return false;
2098 }
2099
2100 if (!CheckLoad(S, OpPC, PtrA, AK_Read) || !CheckLoad(S, OpPC, PtrB, AK_Read))
2101 return false;
2102
2103 // Now, read both pointers to a buffer and compare those.
2104 BitcastBuffer BufferA(
2105 Bits(ASTCtx.getTypeSize(ElemTypeA) * PtrA.getNumElems()));
2106 readPointerToBuffer(S.getContext(), PtrA, BufferA, false);
2107
2108 // FIXME: The swapping here is UNDOING something we do when reading the
2109 // data into the buffer.
2110 if (ASTCtx.getTargetInfo().isBigEndian())
2111 swapBytes(BufferA.Data.get(), BufferA.byteSize().getQuantity());
2112
2113 BitcastBuffer BufferB(
2114 Bits(ASTCtx.getTypeSize(ElemTypeB) * PtrB.getNumElems()));
2115 readPointerToBuffer(S.getContext(), PtrB, BufferB, false);
2116 // FIXME: The swapping here is UNDOING something we do when reading the
2117 // data into the buffer.
2118 if (ASTCtx.getTargetInfo().isBigEndian())
2119 swapBytes(BufferB.Data.get(), BufferB.byteSize().getQuantity());
2120
2121 size_t MinBufferSize = std::min(BufferA.byteSize().getQuantity(),
2122 BufferB.byteSize().getQuantity());
2123
2124 unsigned ElemSize = 1;
2125 if (IsWide)
2126 ElemSize = ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();
2127 // The Size given for the wide variants is in wide-char units. Convert it
2128 // to bytes.
2129 size_t ByteSize = Size * ElemSize;
2130 size_t CmpSize = std::min(MinBufferSize, ByteSize);
2131
2132 for (size_t I = 0; I != CmpSize; I += ElemSize) {
2133 if (IsWide) {
2135 *S.getContext().classify(ASTCtx.getWCharType()), {
2136 T A = T::bitcastFromMemory(BufferA.atByte(I), T::bitWidth());
2137 T B = T::bitcastFromMemory(BufferB.atByte(I), T::bitWidth());
2138 if (A < B) {
2139 pushInteger(S, -1, Call->getType());
2140 return true;
2141 }
2142 if (A > B) {
2143 pushInteger(S, 1, Call->getType());
2144 return true;
2145 }
2146 });
2147 } else {
2148 auto A = BufferA.deref<std::byte>(Bytes(I));
2149 auto B = BufferB.deref<std::byte>(Bytes(I));
2150
2151 if (A < B) {
2152 pushInteger(S, -1, Call->getType());
2153 return true;
2154 }
2155 if (A > B) {
2156 pushInteger(S, 1, Call->getType());
2157 return true;
2158 }
2159 }
2160 }
2161
2162 // We compared CmpSize bytes above. If the limiting factor was the Size
2163 // passed, we're done and the result is equality (0).
2164 if (ByteSize <= CmpSize) {
2165 pushInteger(S, 0, Call->getType());
2166 return true;
2167 }
2168
2169 // However, if we read all the available bytes but were instructed to read
2170 // even more, diagnose this as a "read of dereferenced one-past-the-end
2171 // pointer". This is what would happen if we called CheckLoad() on every array
2172 // element.
2173 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)
2174 << AK_Read << S.Current->getRange(OpPC);
2175 return false;
2176}
2177
2178// __builtin_memchr(ptr, int, int)
2179// __builtin_strchr(ptr, int)
2181 const CallExpr *Call, unsigned ID) {
2182 if (ID == Builtin::BImemchr || ID == Builtin::BIwcschr ||
2183 ID == Builtin::BIstrchr || ID == Builtin::BIwmemchr)
2184 diagnoseNonConstexprBuiltin(S, OpPC, ID);
2185
2186 std::optional<APSInt> MaxLength;
2187 if (Call->getNumArgs() == 3) {
2188 APSInt MaxLengthVal;
2189 if (!popToAPSInt(S, Call->getArg(2), MaxLengthVal))
2190 return false;
2191 MaxLength = MaxLengthVal;
2192 }
2193
2194 APSInt Desired;
2195 if (!popToAPSInt(S, Call->getArg(1), Desired))
2196 return false;
2197 const Pointer &Ptr = S.Stk.pop<Pointer>();
2198
2199 if (MaxLength && MaxLength->isZero()) {
2200 S.Stk.push<Pointer>();
2201 return true;
2202 }
2203
2204 if (Ptr.isDummy()) {
2205 if (Ptr.getType()->isIncompleteType())
2206 S.FFDiag(S.Current->getSource(OpPC),
2207 diag::note_constexpr_ltor_incomplete_type)
2208 << Ptr.getType();
2209 return false;
2210 }
2211
2212 // Null is only okay if the given size is 0.
2213 if (Ptr.isZero()) {
2214 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)
2215 << AK_Read;
2216 return false;
2217 }
2218
2219 if (!Ptr.isBlockPointer())
2220 return false;
2221
2222 QualType ElemTy = Ptr.getFieldDesc()->isArray()
2223 ? Ptr.getFieldDesc()->getElemQualType()
2224 : Ptr.getFieldDesc()->getType();
2225 bool IsRawByte = ID == Builtin::BImemchr || ID == Builtin::BI__builtin_memchr;
2226
2227 // Give up on byte-oriented matching against multibyte elements.
2228 if (IsRawByte && !isOneByteCharacterType(ElemTy)) {
2229 S.FFDiag(S.Current->getSource(OpPC),
2230 diag::note_constexpr_memchr_unsupported)
2231 << S.getASTContext().BuiltinInfo.getQuotedName(ID) << ElemTy;
2232 return false;
2233 }
2234
2235 if (!isReadable(Ptr))
2236 return false;
2237
2238 if (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr) {
2239 int64_t DesiredTrunc;
2240 if (S.getASTContext().CharTy->isSignedIntegerType())
2241 DesiredTrunc =
2242 Desired.trunc(S.getASTContext().getCharWidth()).getSExtValue();
2243 else
2244 DesiredTrunc =
2245 Desired.trunc(S.getASTContext().getCharWidth()).getZExtValue();
2246 // strchr compares directly to the passed integer, and therefore
2247 // always fails if given an int that is not a char.
2248 if (Desired != DesiredTrunc) {
2249 S.Stk.push<Pointer>();
2250 return true;
2251 }
2252 }
2253
2254 uint64_t DesiredVal;
2255 if (ID == Builtin::BIwmemchr || ID == Builtin::BI__builtin_wmemchr ||
2256 ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr) {
2257 // wcschr and wmemchr are given a wchar_t to look for. Just use it.
2258 DesiredVal = Desired.getZExtValue();
2259 } else {
2260 DesiredVal = Desired.trunc(S.getASTContext().getCharWidth()).getZExtValue();
2261 }
2262
2263 bool StopAtZero =
2264 (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr ||
2265 ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr);
2266
2267 PrimType ElemT =
2268 IsRawByte ? PT_Sint8 : *S.getContext().classify(getElemType(Ptr));
2269
2270 size_t Index = Ptr.getIndex();
2271 size_t Step = 0;
2272 for (;;) {
2273 const Pointer &ElemPtr =
2274 (Index + Step) > 0 ? Ptr.atIndex(Index + Step) : Ptr;
2275
2276 if (!CheckLoad(S, OpPC, ElemPtr))
2277 return false;
2278
2279 uint64_t V;
2281 ElemT, { V = static_cast<uint64_t>(ElemPtr.deref<T>().toUnsigned()); });
2282
2283 if (V == DesiredVal) {
2284 S.Stk.push<Pointer>(ElemPtr);
2285 return true;
2286 }
2287
2288 if (StopAtZero && V == 0)
2289 break;
2290
2291 ++Step;
2292 if (MaxLength && Step == MaxLength->getZExtValue())
2293 break;
2294 }
2295
2296 S.Stk.push<Pointer>();
2297 return true;
2298}
2299
2300static std::optional<unsigned> computeFullDescSize(const ASTContext &ASTCtx,
2301 const Descriptor *Desc) {
2302 if (Desc->isPrimitive())
2303 return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();
2304 if (Desc->isArray())
2305 return ASTCtx.getTypeSizeInChars(Desc->getElemQualType()).getQuantity() *
2306 Desc->getNumElems();
2307 if (Desc->isRecord()) {
2308 // Can't use Descriptor::getType() as that may return a pointer type. Look
2309 // at the decl directly.
2310 return ASTCtx
2312 ASTCtx.getCanonicalTagType(Desc->ElemRecord->getDecl()))
2313 .getQuantity();
2314 }
2315
2316 return std::nullopt;
2317}
2318
2319/// Compute the byte offset of \p Ptr in the full declaration.
2320static unsigned computePointerOffset(const ASTContext &ASTCtx,
2321 const Pointer &Ptr) {
2322 unsigned Result = 0;
2323
2324 Pointer P = Ptr;
2325 while (P.isField() || P.isArrayElement()) {
2326 P = P.expand();
2327 const Descriptor *D = P.getFieldDesc();
2328
2329 if (P.isArrayElement()) {
2330 unsigned ElemSize =
2332 if (P.isOnePastEnd())
2333 Result += ElemSize * P.getNumElems();
2334 else
2335 Result += ElemSize * P.getIndex();
2336 P = P.expand().getArray();
2337 } else if (P.isBaseClass()) {
2338 const auto *RD = cast<CXXRecordDecl>(D->asDecl());
2339 bool IsVirtual = Ptr.isVirtualBaseClass();
2340 P = P.getBase();
2341 const Record *BaseRecord = P.getRecord();
2342
2343 const ASTRecordLayout &Layout =
2344 ASTCtx.getASTRecordLayout(cast<CXXRecordDecl>(BaseRecord->getDecl()));
2345 if (IsVirtual)
2346 Result += Layout.getVBaseClassOffset(RD).getQuantity();
2347 else
2348 Result += Layout.getBaseClassOffset(RD).getQuantity();
2349 } else if (P.isField()) {
2350 const FieldDecl *FD = P.getField();
2351 const ASTRecordLayout &Layout =
2352 ASTCtx.getASTRecordLayout(FD->getParent());
2353 unsigned FieldIndex = FD->getFieldIndex();
2354 uint64_t FieldOffset =
2355 ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex))
2356 .getQuantity();
2357 Result += FieldOffset;
2358 P = P.getBase();
2359 } else
2360 llvm_unreachable("Unhandled descriptor type");
2361 }
2362
2363 return Result;
2364}
2365
2366/// Does Ptr point to the last subobject?
2367static bool pointsToLastObject(const Pointer &Ptr) {
2368 Pointer P = Ptr;
2369 while (!P.isRoot()) {
2370
2371 if (P.isArrayElement()) {
2372 P = P.expand().getArray();
2373 continue;
2374 }
2375 if (P.isBaseClass()) {
2376 if (P.getRecord()->getNumFields() > 0)
2377 return false;
2378 P = P.getBase();
2379 continue;
2380 }
2381
2382 Pointer Base = P.getBase();
2383 if (const Record *R = Base.getRecord()) {
2384 assert(P.getField());
2385 if (P.getField()->getFieldIndex() != R->getNumFields() - 1)
2386 return false;
2387 }
2388 P = Base;
2389 }
2390
2391 return true;
2392}
2393
2394/// Does Ptr point to the last object AND to a flexible array member?
2395static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const Pointer &Ptr,
2396 bool InvalidBase) {
2397 auto isFlexibleArrayMember = [&](const Descriptor *FieldDesc) {
2399 FAMKind StrictFlexArraysLevel =
2400 Ctx.getLangOpts().getStrictFlexArraysLevel();
2401
2402 if (StrictFlexArraysLevel == FAMKind::Default)
2403 return true;
2404
2405 unsigned NumElems = FieldDesc->getNumElems();
2406 if (NumElems == 0 && StrictFlexArraysLevel != FAMKind::IncompleteOnly)
2407 return true;
2408
2409 if (NumElems == 1 && StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)
2410 return true;
2411 return false;
2412 };
2413
2414 const Descriptor *FieldDesc = Ptr.getFieldDesc();
2415 if (!FieldDesc->isArray())
2416 return false;
2417
2418 return InvalidBase && pointsToLastObject(Ptr) &&
2419 isFlexibleArrayMember(FieldDesc);
2420}
2421
2423 unsigned Kind, Pointer &Ptr) {
2424 if (Ptr.isZero() || !Ptr.isBlockPointer())
2425 return std::nullopt;
2426
2427 if (Ptr.isDummy() && Ptr.getType()->isPointerType())
2428 return std::nullopt;
2429
2430 bool InvalidBase = false;
2431
2432 if (Ptr.isDummy()) {
2433 if (const VarDecl *VD = Ptr.getDeclDesc()->asVarDecl();
2434 VD && VD->getType()->isPointerType())
2435 InvalidBase = true;
2436 }
2437
2438 // According to the GCC documentation, we want the size of the subobject
2439 // denoted by the pointer. But that's not quite right -- what we actually
2440 // want is the size of the immediately-enclosing array, if there is one.
2441 if (Ptr.isArrayElement())
2442 Ptr = Ptr.expand();
2443
2444 bool DetermineForCompleteObject = Ptr.getFieldDesc() == Ptr.getDeclDesc();
2445 const Descriptor *DeclDesc = Ptr.getDeclDesc();
2446 assert(DeclDesc);
2447
2448 bool UseFieldDesc = (Kind & 1u);
2449 bool ReportMinimum = (Kind & 2u);
2450 if (!UseFieldDesc || DetermineForCompleteObject) {
2451 // Can't read beyond the pointer decl desc.
2452 if (!ReportMinimum && DeclDesc->getType()->isPointerType())
2453 return std::nullopt;
2454
2455 if (InvalidBase)
2456 return std::nullopt;
2457 } else {
2458 if (isUserWritingOffTheEnd(ASTCtx, Ptr, InvalidBase)) {
2459 // If we cannot determine the size of the initial allocation, then we
2460 // can't given an accurate upper-bound. However, we are still able to give
2461 // conservative lower-bounds for Type=3.
2462 if (Kind == 1)
2463 return std::nullopt;
2464 }
2465 // For Type=1, defer to the runtime path on a true incomplete-array
2466 // flexible array member (e.g. 'char fam[]') even when the base is a
2467 // concrete local/global. Without this, the bytecode interpreter would
2468 // happily fold &af.fam to 'NumElems * elemSize = 0' below; the default
2469 // const-evaluator avoids the same trap, and CGBuiltin emits
2470 // @llvm.objectsize for the correct layout-derived answer (matching
2471 // GCC's __bos/__bdos on '&af.fam').
2472 if (Kind == 1 && pointsToLastObject(Ptr) && Ptr.getFieldDesc()->isArray() &&
2474 return std::nullopt;
2475 }
2476
2477 // The "closest surrounding subobject" is NOT a base class,
2478 // so strip the base class casts.
2479 if (UseFieldDesc && Ptr.isBaseClass())
2480 Ptr = Ptr.stripBaseCasts();
2481
2482 const Descriptor *Desc = UseFieldDesc ? Ptr.getFieldDesc() : DeclDesc;
2483 assert(Desc);
2484
2485 std::optional<unsigned> FullSize = computeFullDescSize(ASTCtx, Desc);
2486 if (!FullSize)
2487 return std::nullopt;
2488
2489 unsigned ByteOffset;
2490 if (UseFieldDesc) {
2491 if (Ptr.isBaseClass()) {
2492 assert(computePointerOffset(ASTCtx, Ptr.getBase()) <=
2493 computePointerOffset(ASTCtx, Ptr));
2494 ByteOffset = computePointerOffset(ASTCtx, Ptr.getBase()) -
2495 computePointerOffset(ASTCtx, Ptr);
2496 } else {
2497 if (Ptr.inArray())
2498 ByteOffset =
2499 computePointerOffset(ASTCtx, Ptr) -
2500 computePointerOffset(ASTCtx, Ptr.expand().atIndex(0).narrow());
2501 else
2502 ByteOffset = 0;
2503 }
2504 } else
2505 ByteOffset = computePointerOffset(ASTCtx, Ptr);
2506
2507 assert(ByteOffset <= *FullSize);
2508 return *FullSize - ByteOffset;
2509}
2510
2512 const InterpFrame *Frame,
2513 const CallExpr *Call) {
2514 const ASTContext &ASTCtx = S.getASTContext();
2515 // From the GCC docs:
2516 // Kind is an integer constant from 0 to 3. If the least significant bit is
2517 // clear, objects are whole variables. If it is set, a closest surrounding
2518 // subobject is considered the object a pointer points to. The second bit
2519 // determines if maximum or minimum of remaining bytes is computed.
2520 uint64_t Kind;
2521 if (!popToUInt64(S, Call->getArg(1), Kind))
2522 return false;
2523 assert(Kind <= 3 && "unexpected kind");
2524 Pointer Ptr = S.Stk.pop<Pointer>();
2525
2526 if (Call->getArg(0)->HasSideEffects(ASTCtx)) {
2527 // "If there are any side effects in them, it returns (size_t) -1
2528 // for type 0 or 1 and (size_t) 0 for type 2 or 3."
2529 pushInteger(S, Kind <= 1 ? -1 : 0, Call->getType());
2530 return true;
2531 }
2532
2533 if (auto Result = evaluateBuiltinObjectSize(ASTCtx, Kind, Ptr)) {
2534 pushInteger(S, *Result, Call->getType());
2535 return true;
2536 }
2537 return false;
2538}
2539
2541 const CallExpr *Call) {
2542
2543 if (!S.inConstantContext())
2544 return false;
2545
2546 const Pointer &Ptr = S.Stk.pop<Pointer>();
2547
2548 auto Error = [&](int Diag) {
2549 bool CalledFromStd = false;
2550 const auto *Callee = S.Current->getCallee();
2551 if (Callee && Callee->isInStdNamespace()) {
2552 const IdentifierInfo *Identifier = Callee->getIdentifier();
2553 CalledFromStd = Identifier && Identifier->isStr("is_within_lifetime");
2554 }
2555 S.CCEDiag(CalledFromStd
2557 : S.Current->getSource(OpPC),
2558 diag::err_invalid_is_within_lifetime)
2559 << (CalledFromStd ? "std::is_within_lifetime"
2560 : "__builtin_is_within_lifetime")
2561 << Diag;
2562 return false;
2563 };
2564
2565 if (Ptr.isZero())
2566 return Error(0);
2567 if (Ptr.isOnePastEnd())
2568 return Error(1);
2569
2570 bool Result = Ptr.getLifetime() != Lifetime::Ended;
2571 if (!Ptr.isActive()) {
2572 Result = false;
2573 } else {
2574 if (!CheckLive(S, OpPC, Ptr, AK_Read))
2575 return false;
2576 if (!CheckMutable(S, OpPC, Ptr))
2577 return false;
2578 if (!CheckDummy(S, OpPC, Ptr.block(), AK_Read))
2579 return false;
2580 }
2581
2582 // Check if we're currently running an initializer.
2583 if (S.initializingBlock(Ptr.block()))
2584 return Error(2);
2585 if (S.EvaluatingDecl && Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl)
2586 return Error(2);
2587
2588 pushInteger(S, Result, Call->getType());
2589 return true;
2590}
2591
2593 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2594 llvm::function_ref<APInt(const APSInt &)> Fn) {
2595 assert(Call->getNumArgs() == 1);
2596
2597 // Single integer case.
2598 if (!Call->getArg(0)->getType()->isVectorType()) {
2599 assert(Call->getType()->isIntegerType());
2600 APSInt Src;
2601 if (!popToAPSInt(S, Call->getArg(0), Src))
2602 return false;
2603 APInt Result = Fn(Src);
2604 pushInteger(S, APSInt(std::move(Result), !Src.isSigned()), Call->getType());
2605 return true;
2606 }
2607
2608 // Vector case.
2609 const Pointer &Arg = S.Stk.pop<Pointer>();
2610 assert(Arg.getFieldDesc()->isPrimitiveArray());
2611 const Pointer &Dst = S.Stk.peek<Pointer>();
2612 assert(Dst.getFieldDesc()->isPrimitiveArray());
2613 assert(Arg.getFieldDesc()->getNumElems() ==
2614 Dst.getFieldDesc()->getNumElems());
2615
2616 QualType ElemType = Arg.getFieldDesc()->getElemQualType();
2617 PrimType ElemT = *S.getContext().classify(ElemType);
2618 unsigned NumElems = Arg.getNumElems();
2619 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
2620
2621 for (unsigned I = 0; I != NumElems; ++I) {
2623 APSInt Src = Arg.elem<T>(I).toAPSInt();
2624 APInt Result = Fn(Src);
2625 Dst.elem<T>(I) = static_cast<T>(APSInt(std::move(Result), DestUnsigned));
2626 });
2627 }
2629
2630 return true;
2631}
2632
2634 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2635 llvm::function_ref<std::optional<APFloat>(
2636 const APFloat &, const APFloat &, std::optional<APSInt> RoundingMode)>
2637 Fn,
2638 bool IsScalar = false) {
2639 assert((Call->getNumArgs() == 2) || (Call->getNumArgs() == 3));
2640 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2641 assert(VT->getElementType()->isFloatingType());
2642 unsigned NumElems = VT->getNumElements();
2643
2644 // Vector case.
2645 assert(Call->getArg(0)->getType()->isVectorType() &&
2646 Call->getArg(1)->getType()->isVectorType());
2647 assert(VT->getElementType() ==
2648 Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());
2649 assert(VT->getNumElements() ==
2650 Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());
2651
2652 std::optional<APSInt> RoundingMode = std::nullopt;
2653 if (Call->getNumArgs() == 3) {
2654 APSInt RoundingModeVal;
2655 if (!popToAPSInt(S, Call->getArg(2), RoundingModeVal))
2656 return false;
2657 RoundingMode = RoundingModeVal;
2658 }
2659
2660 const Pointer &BPtr = S.Stk.pop<Pointer>();
2661 const Pointer &APtr = S.Stk.pop<Pointer>();
2662 const Pointer &Dst = S.Stk.peek<Pointer>();
2663 for (unsigned ElemIdx = 0; ElemIdx != NumElems; ++ElemIdx) {
2664 using T = PrimConv<PT_Float>::T;
2665 if (IsScalar && ElemIdx > 0) {
2666 Dst.elem<T>(ElemIdx) = APtr.elem<T>(ElemIdx);
2667 continue;
2668 }
2669 APFloat ElemA = APtr.elem<T>(ElemIdx).getAPFloat();
2670 APFloat ElemB = BPtr.elem<T>(ElemIdx).getAPFloat();
2671 std::optional<APFloat> Result = Fn(ElemA, ElemB, RoundingMode);
2672 if (!Result)
2673 return false;
2674 Dst.elem<T>(ElemIdx) = static_cast<T>(*Result);
2675 }
2676
2678
2679 return true;
2680}
2681
2683 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2684 llvm::function_ref<std::optional<APFloat>(const APFloat &, const APFloat &,
2685 std::optional<APSInt>)>
2686 Fn) {
2687 assert(Call->getNumArgs() == 5);
2688 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2689 unsigned NumElems = VT->getNumElements();
2690
2691 APSInt RoundingMode;
2692 if (!popToAPSInt(S, Call->getArg(4), RoundingMode))
2693 return false;
2694 uint64_t MaskVal;
2695 if (!popToUInt64(S, Call->getArg(3), MaskVal))
2696 return false;
2697 const Pointer &SrcPtr = S.Stk.pop<Pointer>();
2698 const Pointer &BPtr = S.Stk.pop<Pointer>();
2699 const Pointer &APtr = S.Stk.pop<Pointer>();
2700 const Pointer &Dst = S.Stk.peek<Pointer>();
2701
2702 using T = PrimConv<PT_Float>::T;
2703
2704 if (MaskVal & 1) {
2705 APFloat ElemA = APtr.elem<T>(0).getAPFloat();
2706 APFloat ElemB = BPtr.elem<T>(0).getAPFloat();
2707 std::optional<APFloat> Result = Fn(ElemA, ElemB, RoundingMode);
2708 if (!Result)
2709 return false;
2710 Dst.elem<T>(0) = static_cast<T>(*Result);
2711 } else {
2712 Dst.elem<T>(0) = SrcPtr.elem<T>(0);
2713 }
2714
2715 for (unsigned I = 1; I < NumElems; ++I)
2716 Dst.elem<T>(I) = APtr.elem<T>(I);
2717
2718 Dst.initializeAllElements();
2719
2720 return true;
2721}
2722
2724 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2725 llvm::function_ref<APInt(const APSInt &, const APSInt &)> Fn) {
2726 assert(Call->getNumArgs() == 2);
2727
2728 // Single integer case.
2729 if (!Call->getArg(0)->getType()->isVectorType()) {
2730 assert(!Call->getArg(1)->getType()->isVectorType());
2731 APSInt RHS;
2732 if (!popToAPSInt(S, Call->getArg(1), RHS))
2733 return false;
2734 APSInt LHS;
2735 if (!popToAPSInt(S, Call->getArg(0), LHS))
2736 return false;
2737 APInt Result = Fn(LHS, RHS);
2738 pushInteger(S, APSInt(std::move(Result), !LHS.isSigned()), Call->getType());
2739 return true;
2740 }
2741
2742 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2743 assert(VT->getElementType()->isIntegralOrEnumerationType());
2744 PrimType ElemT = *S.getContext().classify(VT->getElementType());
2745 unsigned NumElems = VT->getNumElements();
2746 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
2747
2748 // Vector + Scalar case.
2749 if (!Call->getArg(1)->getType()->isVectorType()) {
2750 assert(Call->getArg(1)->getType()->isIntegralOrEnumerationType());
2751
2752 APSInt RHS;
2753 if (!popToAPSInt(S, Call->getArg(1), RHS))
2754 return false;
2755 const Pointer &LHS = S.Stk.pop<Pointer>();
2756 const Pointer &Dst = S.Stk.peek<Pointer>();
2757
2758 for (unsigned I = 0; I != NumElems; ++I) {
2760 Dst.elem<T>(I) = static_cast<T>(
2761 APSInt(Fn(LHS.elem<T>(I).toAPSInt(), RHS), DestUnsigned));
2762 });
2763 }
2765 return true;
2766 }
2767
2768 // Vector case.
2769 assert(Call->getArg(0)->getType()->isVectorType() &&
2770 Call->getArg(1)->getType()->isVectorType());
2771 assert(VT->getElementType() ==
2772 Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());
2773 assert(VT->getNumElements() ==
2774 Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());
2775 assert(VT->getElementType()->isIntegralOrEnumerationType());
2776
2777 const Pointer &RHS = S.Stk.pop<Pointer>();
2778 const Pointer &LHS = S.Stk.pop<Pointer>();
2779 const Pointer &Dst = S.Stk.peek<Pointer>();
2780 for (unsigned I = 0; I != NumElems; ++I) {
2782 APSInt Elem1 = LHS.elem<T>(I).toAPSInt();
2783 APSInt Elem2 = RHS.elem<T>(I).toAPSInt();
2784 Dst.elem<T>(I) = static_cast<T>(APSInt(Fn(Elem1, Elem2), DestUnsigned));
2785 });
2786 }
2788
2789 return true;
2790}
2791
2792static bool
2794 llvm::function_ref<APInt(const APSInt &)> PackFn) {
2795 const auto *VT0 = E->getArg(0)->getType()->castAs<VectorType>();
2796 [[maybe_unused]] const auto *VT1 =
2797 E->getArg(1)->getType()->castAs<VectorType>();
2798 assert(VT0 && VT1 && "pack builtin VT0 and VT1 must be VectorType");
2799 assert(VT0->getElementType() == VT1->getElementType() &&
2800 VT0->getNumElements() == VT1->getNumElements() &&
2801 "pack builtin VT0 and VT1 ElementType must be same");
2802
2803 const Pointer &RHS = S.Stk.pop<Pointer>();
2804 const Pointer &LHS = S.Stk.pop<Pointer>();
2805 const Pointer &Dst = S.Stk.peek<Pointer>();
2806
2807 const ASTContext &ASTCtx = S.getASTContext();
2808 unsigned SrcBits = ASTCtx.getIntWidth(VT0->getElementType());
2809 unsigned LHSVecLen = VT0->getNumElements();
2810 unsigned SrcPerLane = 128 / SrcBits;
2811 unsigned Lanes = LHSVecLen * SrcBits / 128;
2812
2813 PrimType SrcT = *S.getContext().classify(VT0->getElementType());
2814 PrimType DstT = *S.getContext().classify(getElemType(Dst));
2815 bool IsUnsigend = getElemType(Dst)->isUnsignedIntegerType();
2816
2817 for (unsigned Lane = 0; Lane != Lanes; ++Lane) {
2818 unsigned BaseSrc = Lane * SrcPerLane;
2819 unsigned BaseDst = Lane * (2 * SrcPerLane);
2820
2821 for (unsigned I = 0; I != SrcPerLane; ++I) {
2823 APSInt A = LHS.elem<T>(BaseSrc + I).toAPSInt();
2824 APSInt B = RHS.elem<T>(BaseSrc + I).toAPSInt();
2825
2826 assignIntegral(S, Dst.atIndex(BaseDst + I), DstT,
2827 APSInt(PackFn(A), IsUnsigend));
2828 assignIntegral(S, Dst.atIndex(BaseDst + SrcPerLane + I), DstT,
2829 APSInt(PackFn(B), IsUnsigend));
2830 });
2831 }
2832 }
2833
2834 Dst.initializeAllElements();
2835 return true;
2836}
2837
2839 const CallExpr *Call,
2840 unsigned BuiltinID) {
2841 assert(Call->getNumArgs() == 2);
2842
2843 QualType Arg0Type = Call->getArg(0)->getType();
2844
2845 // TODO: Support floating-point types.
2846 if (!(Arg0Type->isIntegerType() ||
2847 (Arg0Type->isVectorType() &&
2848 Arg0Type->castAs<VectorType>()->getElementType()->isIntegerType())))
2849 return false;
2850
2851 if (!Arg0Type->isVectorType()) {
2852 assert(!Call->getArg(1)->getType()->isVectorType());
2853 APSInt RHS;
2854 if (!popToAPSInt(S, Call->getArg(1), RHS))
2855 return false;
2856 APSInt LHS;
2857 if (!popToAPSInt(S, Arg0Type, LHS))
2858 return false;
2859 APInt Result;
2860 if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
2861 Result = std::max(LHS, RHS);
2862 } else if (BuiltinID == Builtin::BI__builtin_elementwise_min) {
2863 Result = std::min(LHS, RHS);
2864 } else {
2865 llvm_unreachable("Wrong builtin ID");
2866 }
2867
2868 pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType());
2869 return true;
2870 }
2871
2872 // Vector case.
2873 assert(Call->getArg(0)->getType()->isVectorType() &&
2874 Call->getArg(1)->getType()->isVectorType());
2875 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2876 assert(VT->getElementType() ==
2877 Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());
2878 assert(VT->getNumElements() ==
2879 Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());
2880 assert(VT->getElementType()->isIntegralOrEnumerationType());
2881
2882 const Pointer &RHS = S.Stk.pop<Pointer>();
2883 const Pointer &LHS = S.Stk.pop<Pointer>();
2884 const Pointer &Dst = S.Stk.peek<Pointer>();
2885 PrimType ElemT = *S.getContext().classify(VT->getElementType());
2886 unsigned NumElems = VT->getNumElements();
2887 for (unsigned I = 0; I != NumElems; ++I) {
2888 APSInt Elem1;
2889 APSInt Elem2;
2891 Elem1 = LHS.elem<T>(I).toAPSInt();
2892 Elem2 = RHS.elem<T>(I).toAPSInt();
2893 });
2894
2895 APSInt Result;
2896 if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
2897 Result = APSInt(std::max(Elem1, Elem2),
2898 Call->getType()->isUnsignedIntegerOrEnumerationType());
2899 } else if (BuiltinID == Builtin::BI__builtin_elementwise_min) {
2900 Result = APSInt(std::min(Elem1, Elem2),
2901 Call->getType()->isUnsignedIntegerOrEnumerationType());
2902 } else {
2903 llvm_unreachable("Wrong builtin ID");
2904 }
2905
2907 { Dst.elem<T>(I) = static_cast<T>(Result); });
2908 }
2909 Dst.initializeAllElements();
2910
2911 return true;
2912}
2913
2915 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2916 llvm::function_ref<APInt(const APSInt &, const APSInt &, const APSInt &,
2917 const APSInt &)>
2918 Fn) {
2919 assert(Call->getArg(0)->getType()->isVectorType() &&
2920 Call->getArg(1)->getType()->isVectorType());
2921 const Pointer &RHS = S.Stk.pop<Pointer>();
2922 const Pointer &LHS = S.Stk.pop<Pointer>();
2923 const Pointer &Dst = S.Stk.peek<Pointer>();
2924
2925 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2926 PrimType ElemT = *S.getContext().classify(VT->getElementType());
2927 unsigned NumElems = VT->getNumElements();
2928 const auto *DestVT = Call->getType()->castAs<VectorType>();
2929 PrimType DestElemT = *S.getContext().classify(DestVT->getElementType());
2930 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
2931
2932 unsigned DstElem = 0;
2933 for (unsigned I = 0; I != NumElems; I += 2) {
2934 APSInt Result;
2936 APSInt LoLHS = LHS.elem<T>(I).toAPSInt();
2937 APSInt HiLHS = LHS.elem<T>(I + 1).toAPSInt();
2938 APSInt LoRHS = RHS.elem<T>(I).toAPSInt();
2939 APSInt HiRHS = RHS.elem<T>(I + 1).toAPSInt();
2940 Result = APSInt(Fn(LoLHS, HiLHS, LoRHS, HiRHS), DestUnsigned);
2941 });
2942
2943 INT_TYPE_SWITCH_NO_BOOL(DestElemT,
2944 { Dst.elem<T>(DstElem) = static_cast<T>(Result); });
2945 ++DstElem;
2946 }
2947
2948 Dst.initializeAllElements();
2949 return true;
2950}
2951
2953 const CallExpr *Call) {
2954 assert(Call->getNumArgs() == 2);
2955
2956 const Pointer &RHS = S.Stk.pop<Pointer>();
2957 const Pointer &LHS = S.Stk.pop<Pointer>();
2958 const Pointer &Dst = S.Stk.peek<Pointer>();
2959
2960 const auto *SrcVT = Call->getArg(0)->getType()->castAs<VectorType>();
2961 PrimType SrcElemT = *S.getContext().classify(SrcVT->getElementType());
2962 unsigned SourceLen = SrcVT->getNumElements();
2963 assert((SourceLen % 8) == 0);
2964
2965 const auto *DestVT = Call->getType()->castAs<VectorType>();
2966 PrimType DestElemT = *S.getContext().classify(DestVT->getElementType());
2967 bool DestUnsigned =
2968 DestVT->getElementType()->isUnsignedIntegerOrEnumerationType();
2969
2970 unsigned DstElem = 0;
2971 for (unsigned Lane = 0; Lane != SourceLen; Lane += 8) {
2972 APInt Sum(64, 0);
2973 for (unsigned I = 0; I != 8; ++I) {
2974 INT_TYPE_SWITCH_NO_BOOL(SrcElemT, {
2975 APSInt L = LHS.elem<T>(Lane + I).toAPSInt();
2976 APSInt R = RHS.elem<T>(Lane + I).toAPSInt();
2977 Sum += llvm::APIntOps::abdu(L.extOrTrunc(8), R.extOrTrunc(8)).zext(64);
2978 });
2979 }
2980
2981 INT_TYPE_SWITCH_NO_BOOL(DestElemT, {
2982 Dst.elem<T>(DstElem) = static_cast<T>(APSInt(Sum, DestUnsigned));
2983 });
2984 ++DstElem;
2985 }
2986
2987 Dst.initializeAllElements();
2988 return true;
2989}
2990
2992 const CallExpr *Call) {
2993 assert(Call->getNumArgs() == 3);
2994 uint64_t Imm;
2995 if (!popToUInt64(S, Call->getArg(2), Imm))
2996 return false;
2997
2998 const Pointer &Src2 = S.Stk.pop<Pointer>();
2999 const Pointer &Src1 = S.Stk.pop<Pointer>();
3000 const Pointer &Dst = S.Stk.peek<Pointer>();
3001
3002 const auto *SrcVT = Call->getArg(0)->getType()->castAs<VectorType>();
3003 PrimType SrcElemT = *S.getContext().classify(SrcVT->getElementType());
3004 unsigned SourceLen = SrcVT->getNumElements();
3005
3006 const auto *DestVT = Call->getType()->castAs<VectorType>();
3007 PrimType DestElemT = *S.getContext().classify(DestVT->getElementType());
3008 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
3009
3010 constexpr unsigned LaneSize = 16; // 128-bit lane = 16 bytes
3011
3012 // Phase 1: Shuffle Src2 using all four 2-bit fields of imm8.
3013 // Within each 128-bit lane, for group j (0..3), select a 4-byte block
3014 // from Src2 based on bits [2*j+1:2*j] of imm8.
3015 SmallVector<uint8_t, 64> Shuffled(SourceLen);
3016 for (unsigned I = 0; I < SourceLen; I += LaneSize) {
3017 for (unsigned J = 0; J < 4; ++J) {
3018 unsigned Part = (Imm >> (2 * J)) & 3;
3019 for (unsigned K = 0; K < 4; ++K) {
3020 INT_TYPE_SWITCH_NO_BOOL(SrcElemT, {
3021 Shuffled[I + 4 * J + K] =
3022 static_cast<uint8_t>(Src2.elem<T>(I + 4 * Part + K));
3023 });
3024 }
3025 }
3026 }
3027
3028 // Phase 2: Sliding SAD computation.
3029 // For every group of 4 output u16 values, compute absolute differences
3030 // using overlapping windows into Src1 and the shuffled array.
3031 unsigned Size = SourceLen / 2; // number of output u16 elements
3032 for (unsigned I = 0; I < Size; I += 4) {
3033 unsigned Sad[4] = {0, 0, 0, 0};
3034 for (unsigned J = 0; J < 4; ++J) {
3035 uint8_t A1, A2;
3036 INT_TYPE_SWITCH_NO_BOOL(SrcElemT, {
3037 A1 = static_cast<uint8_t>(Src1.elem<T>(2 * I + J));
3038 A2 = static_cast<uint8_t>(Src1.elem<T>(2 * I + J + 4));
3039 });
3040 uint8_t B0 = Shuffled[2 * I + J];
3041 uint8_t B1 = Shuffled[2 * I + J + 1];
3042 uint8_t B2 = Shuffled[2 * I + J + 2];
3043 uint8_t B3 = Shuffled[2 * I + J + 3];
3044 Sad[0] += (A1 > B0) ? (A1 - B0) : (B0 - A1);
3045 Sad[1] += (A1 > B1) ? (A1 - B1) : (B1 - A1);
3046 Sad[2] += (A2 > B2) ? (A2 - B2) : (B2 - A2);
3047 Sad[3] += (A2 > B3) ? (A2 - B3) : (B3 - A2);
3048 }
3049 for (unsigned R = 0; R < 4; ++R) {
3050 INT_TYPE_SWITCH_NO_BOOL(DestElemT, {
3051 Dst.elem<T>(I + R) =
3052 static_cast<T>(APSInt(APInt(16, Sad[R]), DestUnsigned));
3053 });
3054 }
3055 }
3056
3057 Dst.initializeAllElements();
3058 return true;
3059}
3060
3062 const CallExpr *Call) {
3063 assert(Call->getNumArgs() == 3);
3064 uint64_t Imm;
3065 if (!popToUInt64(S, Call->getArg(2), Imm))
3066 return false;
3067
3068 const Pointer &Src2 = S.Stk.pop<Pointer>();
3069 const Pointer &Src1 = S.Stk.pop<Pointer>();
3070 const Pointer &Dst = S.Stk.peek<Pointer>();
3071
3072 const auto *SrcVT = Call->getArg(0)->getType()->castAs<VectorType>();
3073 PrimType SrcElemT = *S.getContext().classify(SrcVT->getElementType());
3074 unsigned SourceLen = SrcVT->getNumElements();
3075 assert((SourceLen == 16 || SourceLen == 32) &&
3076 "MPSADBW operates on 128-bit or 256-bit vectors");
3077
3078 const auto *DestVT = Call->getType()->castAs<VectorType>();
3079 PrimType DestElemT = *S.getContext().classify(DestVT->getElementType());
3080 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
3081
3082 constexpr unsigned LaneSize = 16; // 128-bit lane = 16 bytes
3083 unsigned NumLanes = SourceLen / LaneSize;
3084
3085 for (unsigned Lane = 0; Lane != NumLanes; ++Lane) {
3086 unsigned Ctrl = (Imm >> (3 * Lane)) & 0x7;
3087 unsigned AOff = ((Ctrl >> 2) & 1) * 4;
3088 unsigned BOff = (Ctrl & 3) * 4;
3089 for (unsigned J = 0; J != 8; ++J) {
3090 uint16_t Sad = 0;
3091 for (unsigned K = 0; K != 4; ++K) {
3092 uint8_t A, B;
3093 INT_TYPE_SWITCH_NO_BOOL(SrcElemT, {
3094 A = static_cast<uint8_t>(
3095 Src1.elem<T>(Lane * LaneSize + AOff + J + K));
3096 B = static_cast<uint8_t>(Src2.elem<T>(Lane * LaneSize + BOff + K));
3097 });
3098 Sad += (A > B) ? (A - B) : (B - A);
3099 }
3100 INT_TYPE_SWITCH_NO_BOOL(DestElemT, {
3101 Dst.elem<T>(Lane * 8 + J) =
3102 static_cast<T>(APSInt(APInt(16, Sad), DestUnsigned));
3103 });
3104 }
3105 }
3106
3107 Dst.initializeAllElements();
3108 return true;
3109}
3110
3112 InterpState &S, CodePtr OpPC, const CallExpr *Call,
3113 llvm::function_ref<APInt(const APSInt &, const APSInt &)> Fn) {
3114 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
3115 PrimType ElemT = *S.getContext().classify(VT->getElementType());
3116 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
3117
3118 const Pointer &RHS = S.Stk.pop<Pointer>();
3119 const Pointer &LHS = S.Stk.pop<Pointer>();
3120 const Pointer &Dst = S.Stk.peek<Pointer>();
3121 unsigned NumElts = VT->getNumElements();
3122 unsigned EltBits = S.getASTContext().getIntWidth(VT->getElementType());
3123 unsigned EltsPerLane = 128 / EltBits;
3124 unsigned Lanes = NumElts * EltBits / 128;
3125 unsigned DestIndex = 0;
3126
3127 for (unsigned Lane = 0; Lane < Lanes; ++Lane) {
3128 unsigned LaneStart = Lane * EltsPerLane;
3129 for (unsigned I = 0; I < EltsPerLane; I += 2) {
3131 APSInt Elem1 = LHS.elem<T>(LaneStart + I).toAPSInt();
3132 APSInt Elem2 = LHS.elem<T>(LaneStart + I + 1).toAPSInt();
3133 APSInt ResL = APSInt(Fn(Elem1, Elem2), DestUnsigned);
3134 Dst.elem<T>(DestIndex++) = static_cast<T>(ResL);
3135 });
3136 }
3137
3138 for (unsigned I = 0; I < EltsPerLane; I += 2) {
3140 APSInt Elem1 = RHS.elem<T>(LaneStart + I).toAPSInt();
3141 APSInt Elem2 = RHS.elem<T>(LaneStart + I + 1).toAPSInt();
3142 APSInt ResR = APSInt(Fn(Elem1, Elem2), DestUnsigned);
3143 Dst.elem<T>(DestIndex++) = static_cast<T>(ResR);
3144 });
3145 }
3146 }
3147 Dst.initializeAllElements();
3148 return true;
3149}
3150
3152 InterpState &S, CodePtr OpPC, const CallExpr *Call,
3153 llvm::function_ref<APFloat(const APFloat &, const APFloat &,
3154 llvm::RoundingMode)>
3155 Fn) {
3156 const Pointer &RHS = S.Stk.pop<Pointer>();
3157 const Pointer &LHS = S.Stk.pop<Pointer>();
3158 const Pointer &Dst = S.Stk.peek<Pointer>();
3159 FPOptions FPO = Call->getFPFeaturesInEffect(S.Ctx.getLangOpts());
3160 llvm::RoundingMode RM = getRoundingMode(FPO);
3161 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
3162
3163 unsigned NumElts = VT->getNumElements();
3164 unsigned EltBits = S.getASTContext().getTypeSize(VT->getElementType());
3165 unsigned NumLanes = NumElts * EltBits / 128;
3166 unsigned NumElemsPerLane = NumElts / NumLanes;
3167 unsigned HalfElemsPerLane = NumElemsPerLane / 2;
3168
3169 for (unsigned L = 0; L != NumElts; L += NumElemsPerLane) {
3170 using T = PrimConv<PT_Float>::T;
3171 for (unsigned E = 0; E != HalfElemsPerLane; ++E) {
3172 APFloat Elem1 = LHS.elem<T>(L + (2 * E) + 0).getAPFloat();
3173 APFloat Elem2 = LHS.elem<T>(L + (2 * E) + 1).getAPFloat();
3174 Dst.elem<T>(L + E) = static_cast<T>(Fn(Elem1, Elem2, RM));
3175 }
3176 for (unsigned E = 0; E != HalfElemsPerLane; ++E) {
3177 APFloat Elem1 = RHS.elem<T>(L + (2 * E) + 0).getAPFloat();
3178 APFloat Elem2 = RHS.elem<T>(L + (2 * E) + 1).getAPFloat();
3179 Dst.elem<T>(L + E + HalfElemsPerLane) =
3180 static_cast<T>(Fn(Elem1, Elem2, RM));
3181 }
3182 }
3183 Dst.initializeAllElements();
3184 return true;
3185}
3186
3188 const CallExpr *Call) {
3189 // Addsub: alternates between subtraction and addition
3190 // Result[i] = (i % 2 == 0) ? (a[i] - b[i]) : (a[i] + b[i])
3191 const Pointer &RHS = S.Stk.pop<Pointer>();
3192 const Pointer &LHS = S.Stk.pop<Pointer>();
3193 const Pointer &Dst = S.Stk.peek<Pointer>();
3194 FPOptions FPO = Call->getFPFeaturesInEffect(S.Ctx.getLangOpts());
3195 llvm::RoundingMode RM = getRoundingMode(FPO);
3196 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
3197 unsigned NumElems = VT->getNumElements();
3198
3199 using T = PrimConv<PT_Float>::T;
3200 for (unsigned I = 0; I != NumElems; ++I) {
3201 APFloat LElem = LHS.elem<T>(I).getAPFloat();
3202 APFloat RElem = RHS.elem<T>(I).getAPFloat();
3203 if (I % 2 == 0) {
3204 // Even indices: subtract
3205 LElem.subtract(RElem, RM);
3206 } else {
3207 // Odd indices: add
3208 LElem.add(RElem, RM);
3209 }
3210 Dst.elem<T>(I) = static_cast<T>(LElem);
3211 }
3212 Dst.initializeAllElements();
3213 return true;
3214}
3215
3217 const CallExpr *Call) {
3218 // PCLMULQDQ: carry-less multiplication of selected 64-bit halves
3219 // imm8 bit 0: selects lower (0) or upper (1) 64 bits of first operand
3220 // imm8 bit 4: selects lower (0) or upper (1) 64 bits of second operand
3221 assert(Call->getArg(0)->getType()->isVectorType() &&
3222 Call->getArg(1)->getType()->isVectorType());
3223
3224 // Extract imm8 argument
3225 APSInt Imm8;
3226 if (!popToAPSInt(S, Call->getArg(2), Imm8))
3227 return false;
3228 bool SelectUpperA = (Imm8 & 0x01) != 0;
3229 bool SelectUpperB = (Imm8 & 0x10) != 0;
3230
3231 const Pointer &RHS = S.Stk.pop<Pointer>();
3232 const Pointer &LHS = S.Stk.pop<Pointer>();
3233 const Pointer &Dst = S.Stk.peek<Pointer>();
3234
3235 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
3236 PrimType ElemT = *S.getContext().classify(VT->getElementType());
3237 unsigned NumElems = VT->getNumElements();
3238 const auto *DestVT = Call->getType()->castAs<VectorType>();
3239 PrimType DestElemT = *S.getContext().classify(DestVT->getElementType());
3240 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
3241
3242 // Process each 128-bit lane (2 elements at a time)
3243 for (unsigned Lane = 0; Lane < NumElems; Lane += 2) {
3244 APSInt A0, A1, B0, B1;
3246 A0 = LHS.elem<T>(Lane + 0).toAPSInt();
3247 A1 = LHS.elem<T>(Lane + 1).toAPSInt();
3248 B0 = RHS.elem<T>(Lane + 0).toAPSInt();
3249 B1 = RHS.elem<T>(Lane + 1).toAPSInt();
3250 });
3251
3252 // Select the appropriate 64-bit values based on imm8
3253 APInt A = SelectUpperA ? A1 : A0;
3254 APInt B = SelectUpperB ? B1 : B0;
3255
3256 // Extend both operands to 128 bits for carry-less multiplication
3257 APInt A128 = A.zext(128);
3258 APInt B128 = B.zext(128);
3259
3260 // Use APIntOps::clmul for carry-less multiplication
3261 APInt Result = llvm::APIntOps::clmul(A128, B128);
3262
3263 // Split the 128-bit result into two 64-bit halves
3264 APSInt ResultLow(Result.extractBits(64, 0), DestUnsigned);
3265 APSInt ResultHigh(Result.extractBits(64, 64), DestUnsigned);
3266
3267 INT_TYPE_SWITCH_NO_BOOL(DestElemT, {
3268 Dst.elem<T>(Lane + 0) = static_cast<T>(ResultLow);
3269 Dst.elem<T>(Lane + 1) = static_cast<T>(ResultHigh);
3270 });
3271 }
3272
3273 Dst.initializeAllElements();
3274 return true;
3275}
3276
3278 InterpState &S, CodePtr OpPC, const CallExpr *Call,
3279 llvm::function_ref<APFloat(const APFloat &, const APFloat &,
3280 const APFloat &, llvm::RoundingMode)>
3281 Fn) {
3282 assert(Call->getNumArgs() == 3);
3283
3284 FPOptions FPO = Call->getFPFeaturesInEffect(S.Ctx.getLangOpts());
3285 llvm::RoundingMode RM = getRoundingMode(FPO);
3286 QualType Arg1Type = Call->getArg(0)->getType();
3287 QualType Arg2Type = Call->getArg(1)->getType();
3288 QualType Arg3Type = Call->getArg(2)->getType();
3289
3290 // Non-vector floating point types.
3291 if (!Arg1Type->isVectorType()) {
3292 assert(!Arg2Type->isVectorType());
3293 assert(!Arg3Type->isVectorType());
3294 (void)Arg2Type;
3295 (void)Arg3Type;
3296
3297 const Floating &Z = S.Stk.pop<Floating>();
3298 const Floating &Y = S.Stk.pop<Floating>();
3299 const Floating &X = S.Stk.pop<Floating>();
3300 APFloat F = Fn(X.getAPFloat(), Y.getAPFloat(), Z.getAPFloat(), RM);
3301 Floating Result = S.allocFloat(X.getSemantics());
3302 Result.copy(F);
3303 S.Stk.push<Floating>(Result);
3304 return true;
3305 }
3306
3307 // Vector type.
3308 assert(Arg1Type->isVectorType() && Arg2Type->isVectorType() &&
3309 Arg3Type->isVectorType());
3310
3311 const VectorType *VecTy = Arg1Type->castAs<VectorType>();
3312 QualType ElemQT = VecTy->getElementType();
3313 unsigned NumElems = VecTy->getNumElements();
3314
3315 assert(ElemQT == Arg2Type->castAs<VectorType>()->getElementType() &&
3316 ElemQT == Arg3Type->castAs<VectorType>()->getElementType());
3317 assert(NumElems == Arg2Type->castAs<VectorType>()->getNumElements() &&
3318 NumElems == Arg3Type->castAs<VectorType>()->getNumElements());
3319 assert(ElemQT->isRealFloatingType());
3320 (void)ElemQT;
3321
3322 const Pointer &VZ = S.Stk.pop<Pointer>();
3323 const Pointer &VY = S.Stk.pop<Pointer>();
3324 const Pointer &VX = S.Stk.pop<Pointer>();
3325 const Pointer &Dst = S.Stk.peek<Pointer>();
3326 for (unsigned I = 0; I != NumElems; ++I) {
3327 using T = PrimConv<PT_Float>::T;
3328 APFloat X = VX.elem<T>(I).getAPFloat();
3329 APFloat Y = VY.elem<T>(I).getAPFloat();
3330 APFloat Z = VZ.elem<T>(I).getAPFloat();
3331 APFloat F = Fn(X, Y, Z, RM);
3332 Dst.elem<Floating>(I) = Floating(F);
3333 }
3335 return true;
3336}
3337
3338/// AVX512 predicated move: "Result = Mask[] ? LHS[] : RHS[]".
3340 const CallExpr *Call) {
3341 const Pointer &RHS = S.Stk.pop<Pointer>();
3342 const Pointer &LHS = S.Stk.pop<Pointer>();
3343 APSInt Mask;
3344 if (!popToAPSInt(S, Call->getArg(0), Mask))
3345 return false;
3346 const Pointer &Dst = S.Stk.peek<Pointer>();
3347
3348 assert(LHS.getNumElems() == RHS.getNumElems());
3349 assert(LHS.getNumElems() == Dst.getNumElems());
3350 unsigned NumElems = LHS.getNumElems();
3351 PrimType ElemT = LHS.getFieldDesc()->getPrimType();
3352 PrimType DstElemT = Dst.getFieldDesc()->getPrimType();
3353
3354 for (unsigned I = 0; I != NumElems; ++I) {
3355 if (ElemT == PT_Float) {
3356 assert(DstElemT == PT_Float);
3357 Dst.elem<Floating>(I) =
3358 Mask[I] ? LHS.elem<Floating>(I) : RHS.elem<Floating>(I);
3359 } else {
3360 APSInt Elem;
3361 INT_TYPE_SWITCH(ElemT, {
3362 Elem = Mask[I] ? LHS.elem<T>(I).toAPSInt() : RHS.elem<T>(I).toAPSInt();
3363 });
3364 INT_TYPE_SWITCH_NO_BOOL(DstElemT,
3365 { Dst.elem<T>(I) = static_cast<T>(Elem); });
3366 }
3367 }
3369
3370 return true;
3371}
3372
3373/// Scalar variant of AVX512 predicated select:
3374/// Result[i] = (Mask bit 0) ? LHS[i] : RHS[i], but only element 0 may change.
3375/// All other elements are taken from RHS.
3377 const CallExpr *Call) {
3378 unsigned N =
3379 Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements();
3380
3381 const Pointer &W = S.Stk.pop<Pointer>();
3382 const Pointer &A = S.Stk.pop<Pointer>();
3383 APSInt U;
3384 if (!popToAPSInt(S, Call->getArg(0), U))
3385 return false;
3386 const Pointer &Dst = S.Stk.peek<Pointer>();
3387
3388 bool TakeA0 = U.getZExtValue() & 1ULL;
3389
3390 for (unsigned I = TakeA0; I != N; ++I)
3391 Dst.elem<Floating>(I) = W.elem<Floating>(I);
3392 if (TakeA0)
3393 Dst.elem<Floating>(0) = A.elem<Floating>(0);
3394
3396 return true;
3397}
3398
3400 InterpState &S, CodePtr OpPC, const CallExpr *Call,
3401 llvm::function_ref<bool(const APInt &A, const APInt &B)> Fn) {
3402 const Pointer &RHS = S.Stk.pop<Pointer>();
3403 const Pointer &LHS = S.Stk.pop<Pointer>();
3404
3405 assert(LHS.getNumElems() == RHS.getNumElems());
3406
3407 unsigned SourceLen = LHS.getNumElems();
3408 QualType ElemQT = getElemType(LHS);
3409 OptPrimType ElemPT = S.getContext().classify(ElemQT);
3410 unsigned LaneWidth = S.getASTContext().getTypeSize(ElemQT);
3411
3412 APInt AWide(LaneWidth * SourceLen, 0);
3413 APInt BWide(LaneWidth * SourceLen, 0);
3414
3415 for (unsigned I = 0; I != SourceLen; ++I) {
3416 APInt ALane;
3417 APInt BLane;
3418
3419 if (ElemQT->isIntegerType()) { // Get value.
3420 INT_TYPE_SWITCH_NO_BOOL(*ElemPT, {
3421 ALane = LHS.elem<T>(I).toAPSInt();
3422 BLane = RHS.elem<T>(I).toAPSInt();
3423 });
3424 } else if (ElemQT->isFloatingType()) { // Get only sign bit.
3425 using T = PrimConv<PT_Float>::T;
3426 ALane = LHS.elem<T>(I).getAPFloat().bitcastToAPInt().isNegative();
3427 BLane = RHS.elem<T>(I).getAPFloat().bitcastToAPInt().isNegative();
3428 } else { // Must be integer or floating type.
3429 return false;
3430 }
3431 AWide.insertBits(ALane, I * LaneWidth);
3432 BWide.insertBits(BLane, I * LaneWidth);
3433 }
3434 pushInteger(S, Fn(AWide, BWide), Call->getType());
3435 return true;
3436}
3437
3439 const CallExpr *Call) {
3440 assert(Call->getNumArgs() == 1);
3441
3442 const Pointer &Source = S.Stk.pop<Pointer>();
3443
3444 unsigned SourceLen = Source.getNumElems();
3445 QualType ElemQT = getElemType(Source);
3446 OptPrimType ElemT = S.getContext().classify(ElemQT);
3447 unsigned ResultLen =
3448 S.getASTContext().getTypeSize(Call->getType()); // Always 32-bit integer.
3449 APInt Result(ResultLen, 0);
3450
3451 for (unsigned I = 0; I != SourceLen; ++I) {
3452 APInt Elem;
3453 if (ElemQT->isIntegerType()) {
3454 INT_TYPE_SWITCH_NO_BOOL(*ElemT, { Elem = Source.elem<T>(I).toAPSInt(); });
3455 } else if (ElemQT->isRealFloatingType()) {
3456 using T = PrimConv<PT_Float>::T;
3457 Elem = Source.elem<T>(I).getAPFloat().bitcastToAPInt();
3458 } else {
3459 return false;
3460 }
3461 Result.setBitVal(I, Elem.isNegative());
3462 }
3463 pushInteger(S, Result, Call->getType());
3464 return true;
3465}
3466
3468 InterpState &S, CodePtr OpPC, const CallExpr *Call,
3469 llvm::function_ref<APInt(const APSInt &, const APSInt &, const APSInt &)>
3470 Fn) {
3471 assert(Call->getNumArgs() == 3);
3472
3473 QualType Arg0Type = Call->getArg(0)->getType();
3474 QualType Arg2Type = Call->getArg(2)->getType();
3475 // Non-vector integer types.
3476 if (!Arg0Type->isVectorType()) {
3477 APSInt Op2;
3478 if (!popToAPSInt(S, Arg2Type, Op2))
3479 return false;
3480 APSInt Op1;
3481 if (!popToAPSInt(S, Call->getArg(1), Op1))
3482 return false;
3483 APSInt Op0;
3484 if (!popToAPSInt(S, Arg0Type, Op0))
3485 return false;
3486 APSInt Result = APSInt(Fn(Op0, Op1, Op2), Op0.isUnsigned());
3487 pushInteger(S, Result, Call->getType());
3488 return true;
3489 }
3490
3491 const auto *VecT = Arg0Type->castAs<VectorType>();
3492 PrimType ElemT = *S.getContext().classify(VecT->getElementType());
3493 unsigned NumElems = VecT->getNumElements();
3494 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
3495
3496 // Vector + Vector + Scalar case.
3497 if (!Arg2Type->isVectorType()) {
3498 APSInt Op2;
3499 if (!popToAPSInt(S, Arg2Type, Op2))
3500 return false;
3501
3502 const Pointer &Op1 = S.Stk.pop<Pointer>();
3503 const Pointer &Op0 = S.Stk.pop<Pointer>();
3504 const Pointer &Dst = S.Stk.peek<Pointer>();
3505 for (unsigned I = 0; I != NumElems; ++I) {
3507 Dst.elem<T>(I) = static_cast<T>(APSInt(
3508 Fn(Op0.elem<T>(I).toAPSInt(), Op1.elem<T>(I).toAPSInt(), Op2),
3509 DestUnsigned));
3510 });
3511 }
3513
3514 return true;
3515 }
3516
3517 // Vector type.
3518 const Pointer &Op2 = S.Stk.pop<Pointer>();
3519 const Pointer &Op1 = S.Stk.pop<Pointer>();
3520 const Pointer &Op0 = S.Stk.pop<Pointer>();
3521 const Pointer &Dst = S.Stk.peek<Pointer>();
3522 for (unsigned I = 0; I != NumElems; ++I) {
3523 APSInt Val0, Val1, Val2;
3525 Val0 = Op0.elem<T>(I).toAPSInt();
3526 Val1 = Op1.elem<T>(I).toAPSInt();
3527 Val2 = Op2.elem<T>(I).toAPSInt();
3528 });
3529 APSInt Result = APSInt(Fn(Val0, Val1, Val2), Val0.isUnsigned());
3531 { Dst.elem<T>(I) = static_cast<T>(Result); });
3532 }
3534
3535 return true;
3536}
3537
3539 const CallExpr *Call,
3540 unsigned ID) {
3541 assert(Call->getNumArgs() == 2);
3542
3543 APSInt ImmAPS;
3544 if (!popToAPSInt(S, Call->getArg(1), ImmAPS))
3545 return false;
3546 uint64_t Index = ImmAPS.getZExtValue();
3547
3548 const Pointer &Src = S.Stk.pop<Pointer>();
3549 if (!Src.getFieldDesc()->isPrimitiveArray())
3550 return false;
3551
3552 const Pointer &Dst = S.Stk.peek<Pointer>();
3553 if (!Dst.getFieldDesc()->isPrimitiveArray())
3554 return false;
3555
3556 unsigned SrcElems = Src.getNumElems();
3557 unsigned DstElems = Dst.getNumElems();
3558
3559 unsigned NumLanes = SrcElems / DstElems;
3560 unsigned Lane = static_cast<unsigned>(Index % NumLanes);
3561 unsigned ExtractPos = Lane * DstElems;
3562
3563 PrimType ElemT = Src.getFieldDesc()->getPrimType();
3564
3565 TYPE_SWITCH(ElemT, {
3566 for (unsigned I = 0; I != DstElems; ++I) {
3567 Dst.elem<T>(I) = Src.elem<T>(ExtractPos + I);
3568 }
3569 });
3570
3572 return true;
3573}
3574
3576 CodePtr OpPC,
3577 const CallExpr *Call,
3578 unsigned ID) {
3579 assert(Call->getNumArgs() == 4);
3580
3581 APSInt MaskAPS;
3582 if (!popToAPSInt(S, Call->getArg(3), MaskAPS))
3583 return false;
3584 const Pointer &Merge = S.Stk.pop<Pointer>();
3585 APSInt ImmAPS;
3586 if (!popToAPSInt(S, Call->getArg(1), ImmAPS))
3587 return false;
3588 const Pointer &Src = S.Stk.pop<Pointer>();
3589
3590 if (!Src.getFieldDesc()->isPrimitiveArray() ||
3591 !Merge.getFieldDesc()->isPrimitiveArray())
3592 return false;
3593
3594 const Pointer &Dst = S.Stk.peek<Pointer>();
3595 if (!Dst.getFieldDesc()->isPrimitiveArray())
3596 return false;
3597
3598 unsigned SrcElems = Src.getNumElems();
3599 unsigned DstElems = Dst.getNumElems();
3600
3601 unsigned NumLanes = SrcElems / DstElems;
3602 unsigned Lane = static_cast<unsigned>(ImmAPS.getZExtValue() % NumLanes);
3603 unsigned Base = Lane * DstElems;
3604
3605 PrimType ElemT = Src.getFieldDesc()->getPrimType();
3606
3607 TYPE_SWITCH(ElemT, {
3608 for (unsigned I = 0; I != DstElems; ++I) {
3609 if (MaskAPS[I])
3610 Dst.elem<T>(I) = Src.elem<T>(Base + I);
3611 else
3612 Dst.elem<T>(I) = Merge.elem<T>(I);
3613 }
3614 });
3615
3617 return true;
3618}
3619
3621 const CallExpr *Call,
3622 unsigned ID) {
3623 assert(Call->getNumArgs() == 3);
3624
3625 APSInt ImmAPS;
3626 if (!popToAPSInt(S, Call->getArg(2), ImmAPS))
3627 return false;
3628 uint64_t Index = ImmAPS.getZExtValue();
3629
3630 const Pointer &SubVec = S.Stk.pop<Pointer>();
3631 if (!SubVec.getFieldDesc()->isPrimitiveArray())
3632 return false;
3633
3634 const Pointer &BaseVec = S.Stk.pop<Pointer>();
3635 if (!BaseVec.getFieldDesc()->isPrimitiveArray())
3636 return false;
3637
3638 const Pointer &Dst = S.Stk.peek<Pointer>();
3639
3640 unsigned BaseElements = BaseVec.getNumElems();
3641 unsigned SubElements = SubVec.getNumElems();
3642
3643 assert(SubElements != 0 && BaseElements != 0 &&
3644 (BaseElements % SubElements) == 0);
3645
3646 unsigned NumLanes = BaseElements / SubElements;
3647 unsigned Lane = static_cast<unsigned>(Index % NumLanes);
3648 unsigned InsertPos = Lane * SubElements;
3649
3650 PrimType ElemT = BaseVec.getFieldDesc()->getPrimType();
3651
3652 TYPE_SWITCH(ElemT, {
3653 for (unsigned I = 0; I != BaseElements; ++I)
3654 Dst.elem<T>(I) = BaseVec.elem<T>(I);
3655 for (unsigned I = 0; I != SubElements; ++I)
3656 Dst.elem<T>(InsertPos + I) = SubVec.elem<T>(I);
3657 });
3658
3660 return true;
3661}
3662
3664 const CallExpr *Call) {
3665 assert(Call->getNumArgs() == 1);
3666
3667 const Pointer &Source = S.Stk.pop<Pointer>();
3668 const Pointer &Dest = S.Stk.peek<Pointer>();
3669
3670 unsigned SourceLen = Source.getNumElems();
3671 QualType ElemQT = getElemType(Source);
3672 OptPrimType ElemT = S.getContext().classify(ElemQT);
3673 unsigned ElemBitWidth = S.getASTContext().getTypeSize(ElemQT);
3674
3675 bool DestUnsigned = Call->getCallReturnType(S.getASTContext())
3676 ->castAs<VectorType>()
3677 ->getElementType()
3679
3680 INT_TYPE_SWITCH_NO_BOOL(*ElemT, {
3681 APSInt MinIndex(ElemBitWidth, DestUnsigned);
3682 APSInt MinVal = Source.elem<T>(0).toAPSInt();
3683
3684 for (unsigned I = 1; I != SourceLen; ++I) {
3685 APSInt Val = Source.elem<T>(I).toAPSInt();
3686 if (MinVal.ugt(Val)) {
3687 MinVal = Val;
3688 MinIndex = I;
3689 }
3690 }
3691
3692 Dest.elem<T>(0) = static_cast<T>(MinVal);
3693 Dest.elem<T>(1) = static_cast<T>(MinIndex);
3694 for (unsigned I = 2; I != SourceLen; ++I) {
3695 Dest.elem<T>(I) = static_cast<T>(APSInt(ElemBitWidth, DestUnsigned));
3696 }
3697 });
3698 Dest.initializeAllElements();
3699 return true;
3700}
3701
3703 const CallExpr *Call, bool MaskZ) {
3704 assert(Call->getNumArgs() == 5);
3705
3706 APSInt UVal;
3707 if (!popToAPSInt(S, Call->getArg(4), UVal))
3708 return false;
3709 APInt U = UVal; // Lane mask
3710 APSInt ImmVal;
3711 if (!popToAPSInt(S, Call->getArg(3), ImmVal))
3712 return false;
3713 APInt Imm = ImmVal; // Ternary truth table
3714 const Pointer &C = S.Stk.pop<Pointer>();
3715 const Pointer &B = S.Stk.pop<Pointer>();
3716 const Pointer &A = S.Stk.pop<Pointer>();
3717 const Pointer &Dst = S.Stk.peek<Pointer>();
3718
3719 unsigned DstLen = A.getNumElems();
3720 QualType ElemQT = getElemType(A);
3721 OptPrimType ElemT = S.getContext().classify(ElemQT);
3722 unsigned LaneWidth = S.getASTContext().getTypeSize(ElemQT);
3723 bool DstUnsigned = ElemQT->isUnsignedIntegerOrEnumerationType();
3724
3725 INT_TYPE_SWITCH_NO_BOOL(*ElemT, {
3726 for (unsigned I = 0; I != DstLen; ++I) {
3727 APInt ALane = A.elem<T>(I).toAPSInt();
3728 APInt BLane = B.elem<T>(I).toAPSInt();
3729 APInt CLane = C.elem<T>(I).toAPSInt();
3730 APInt RLane(LaneWidth, 0);
3731 if (U[I]) { // If lane not masked, compute ternary logic.
3732 for (unsigned Bit = 0; Bit != LaneWidth; ++Bit) {
3733 unsigned ABit = ALane[Bit];
3734 unsigned BBit = BLane[Bit];
3735 unsigned CBit = CLane[Bit];
3736 unsigned Idx = (ABit << 2) | (BBit << 1) | (CBit);
3737 RLane.setBitVal(Bit, Imm[Idx]);
3738 }
3739 Dst.elem<T>(I) = static_cast<T>(APSInt(RLane, DstUnsigned));
3740 } else if (MaskZ) { // If zero masked, zero the lane.
3741 Dst.elem<T>(I) = static_cast<T>(APSInt(RLane, DstUnsigned));
3742 } else { // Just masked, put in A lane.
3743 Dst.elem<T>(I) = static_cast<T>(APSInt(ALane, DstUnsigned));
3744 }
3745 }
3746 });
3747 Dst.initializeAllElements();
3748 return true;
3749}
3750
3752 const CallExpr *Call, unsigned ID) {
3753 assert(Call->getNumArgs() == 2);
3754
3755 APSInt ImmAPS;
3756 if (!popToAPSInt(S, Call->getArg(1), ImmAPS))
3757 return false;
3758 const Pointer &Vec = S.Stk.pop<Pointer>();
3759 if (!Vec.getFieldDesc()->isPrimitiveArray())
3760 return false;
3761
3762 unsigned NumElems = Vec.getNumElems();
3763 unsigned Index =
3764 static_cast<unsigned>(ImmAPS.getZExtValue() & (NumElems - 1));
3765
3766 PrimType ElemT = Vec.getFieldDesc()->getPrimType();
3767 // FIXME(#161685): Replace float+int split with a numeric-only type switch
3768 if (ElemT == PT_Float) {
3769 S.Stk.push<Floating>(Vec.elem<Floating>(Index));
3770 return true;
3771 }
3773 APSInt V = Vec.elem<T>(Index).toAPSInt();
3774 pushInteger(S, V, Call->getType());
3775 });
3776
3777 return true;
3778}
3779
3781 const CallExpr *Call, unsigned ID) {
3782 assert(Call->getNumArgs() == 3);
3783
3784 APSInt ImmAPS;
3785 if (!popToAPSInt(S, Call->getArg(2), ImmAPS))
3786 return false;
3787 APSInt ValAPS;
3788 if (!popToAPSInt(S, Call->getArg(1), ValAPS))
3789 return false;
3790
3791 const Pointer &Base = S.Stk.pop<Pointer>();
3792 if (!Base.getFieldDesc()->isPrimitiveArray())
3793 return false;
3794
3795 const Pointer &Dst = S.Stk.peek<Pointer>();
3796
3797 unsigned NumElems = Base.getNumElems();
3798 unsigned Index =
3799 static_cast<unsigned>(ImmAPS.getZExtValue() & (NumElems - 1));
3800
3801 PrimType ElemT = Base.getFieldDesc()->getPrimType();
3803 for (unsigned I = 0; I != NumElems; ++I)
3804 Dst.elem<T>(I) = Base.elem<T>(I);
3805 Dst.elem<T>(Index) = static_cast<T>(ValAPS);
3806 });
3807
3809 return true;
3810}
3811
3812static bool evalICmpImm(uint8_t Imm, const APSInt &A, const APSInt &B,
3813 bool IsUnsigned) {
3814 switch (Imm & 0x7) {
3815 case 0x00: // _MM_CMPINT_EQ
3816 return (A == B);
3817 case 0x01: // _MM_CMPINT_LT
3818 return IsUnsigned ? A.ult(B) : A.slt(B);
3819 case 0x02: // _MM_CMPINT_LE
3820 return IsUnsigned ? A.ule(B) : A.sle(B);
3821 case 0x03: // _MM_CMPINT_FALSE
3822 return false;
3823 case 0x04: // _MM_CMPINT_NE
3824 return (A != B);
3825 case 0x05: // _MM_CMPINT_NLT
3826 return IsUnsigned ? A.ugt(B) : A.sgt(B);
3827 case 0x06: // _MM_CMPINT_NLE
3828 return IsUnsigned ? A.uge(B) : A.sge(B);
3829 case 0x07: // _MM_CMPINT_TRUE
3830 return true;
3831 default:
3832 llvm_unreachable("Invalid Op");
3833 }
3834}
3835
3837 const CallExpr *Call, unsigned ID,
3838 bool IsUnsigned) {
3839 assert(Call->getNumArgs() == 4);
3840
3841 APSInt Mask;
3842 if (!popToAPSInt(S, Call->getArg(3), Mask))
3843 return false;
3844 APSInt Opcode;
3845 if (!popToAPSInt(S, Call->getArg(2), Opcode))
3846 return false;
3847 unsigned CmpOp = static_cast<unsigned>(Opcode.getZExtValue());
3848 const Pointer &RHS = S.Stk.pop<Pointer>();
3849 const Pointer &LHS = S.Stk.pop<Pointer>();
3850
3851 assert(LHS.getNumElems() == RHS.getNumElems());
3852
3853 APInt RetMask = APInt::getZero(LHS.getNumElems());
3854 unsigned VectorLen = LHS.getNumElems();
3855 PrimType ElemT = LHS.getFieldDesc()->getPrimType();
3856
3857 for (unsigned ElemNum = 0; ElemNum < VectorLen; ++ElemNum) {
3858 APSInt A, B;
3860 A = LHS.elem<T>(ElemNum).toAPSInt();
3861 B = RHS.elem<T>(ElemNum).toAPSInt();
3862 });
3863 RetMask.setBitVal(ElemNum,
3864 Mask[ElemNum] && evalICmpImm(CmpOp, A, B, IsUnsigned));
3865 }
3866 pushInteger(S, RetMask, Call->getType());
3867 return true;
3868}
3869
3871 const CallExpr *Call) {
3872 assert(Call->getNumArgs() == 1);
3873
3874 QualType Arg0Type = Call->getArg(0)->getType();
3875 const auto *VecT = Arg0Type->castAs<VectorType>();
3876 PrimType ElemT = *S.getContext().classify(VecT->getElementType());
3877 unsigned NumElems = VecT->getNumElements();
3878 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
3879 const Pointer &Src = S.Stk.pop<Pointer>();
3880 const Pointer &Dst = S.Stk.peek<Pointer>();
3881
3882 for (unsigned I = 0; I != NumElems; ++I) {
3884 APSInt ElemI = Src.elem<T>(I).toAPSInt();
3885 APInt ConflictMask(ElemI.getBitWidth(), 0);
3886 for (unsigned J = 0; J != I; ++J) {
3887 APSInt ElemJ = Src.elem<T>(J).toAPSInt();
3888 ConflictMask.setBitVal(J, ElemI == ElemJ);
3889 }
3890 Dst.elem<T>(I) = static_cast<T>(APSInt(ConflictMask, DestUnsigned));
3891 });
3892 }
3894 return true;
3895}
3896
3898 const CallExpr *Call,
3899 unsigned ID) {
3900 assert(Call->getNumArgs() == 1);
3901
3902 const Pointer &Vec = S.Stk.pop<Pointer>();
3903 unsigned RetWidth = S.getASTContext().getIntWidth(Call->getType());
3904 APInt RetMask(RetWidth, 0);
3905
3906 unsigned VectorLen = Vec.getNumElems();
3907 PrimType ElemT = Vec.getFieldDesc()->getPrimType();
3908
3909 for (unsigned ElemNum = 0; ElemNum != VectorLen; ++ElemNum) {
3910 APSInt A;
3911 INT_TYPE_SWITCH_NO_BOOL(ElemT, { A = Vec.elem<T>(ElemNum).toAPSInt(); });
3912 unsigned MSB = A[A.getBitWidth() - 1];
3913 RetMask.setBitVal(ElemNum, MSB);
3914 }
3915 pushInteger(S, RetMask, Call->getType());
3916 return true;
3917}
3918
3920 const CallExpr *Call,
3921 unsigned ID) {
3922 assert(Call->getNumArgs() == 1);
3923
3924 APSInt Mask;
3925 if (!popToAPSInt(S, Call->getArg(0), Mask))
3926 return false;
3927
3928 const Pointer &Vec = S.Stk.peek<Pointer>();
3929 unsigned NumElems = Vec.getNumElems();
3930 PrimType ElemT = Vec.getFieldDesc()->getPrimType();
3931
3932 for (unsigned I = 0; I != NumElems; ++I) {
3933 bool BitSet = Mask[I];
3934
3936 ElemT, { Vec.elem<T>(I) = BitSet ? T::from(-1) : T::from(0); });
3937 }
3938
3940
3941 return true;
3942}
3943
3945 const CallExpr *Call,
3946 bool HasRoundingMask) {
3947 APSInt Rounding, MaskInt;
3948 Pointer Src, B, A;
3949
3950 if (HasRoundingMask) {
3951 assert(Call->getNumArgs() == 5);
3952 if (!popToAPSInt(S, Call->getArg(4), Rounding))
3953 return false;
3954 if (!popToAPSInt(S, Call->getArg(3), MaskInt))
3955 return false;
3956 Src = S.Stk.pop<Pointer>();
3957 B = S.Stk.pop<Pointer>();
3958 A = S.Stk.pop<Pointer>();
3959 if (!CheckLoad(S, OpPC, A) || !CheckLoad(S, OpPC, B) ||
3960 !CheckLoad(S, OpPC, Src))
3961 return false;
3962 } else {
3963 assert(Call->getNumArgs() == 2);
3964 B = S.Stk.pop<Pointer>();
3965 A = S.Stk.pop<Pointer>();
3966 if (!CheckLoad(S, OpPC, A) || !CheckLoad(S, OpPC, B))
3967 return false;
3968 }
3969
3970 const auto *DstVTy = Call->getType()->castAs<VectorType>();
3971 unsigned NumElems = DstVTy->getNumElements();
3972 const Pointer &Dst = S.Stk.peek<Pointer>();
3973
3974 // Copy all elements except lane 0 (overwritten below) from A to Dst.
3975 for (unsigned I = 1; I != NumElems; ++I)
3976 Dst.elem<Floating>(I) = A.elem<Floating>(I);
3977
3978 // Convert element 0 from double to float, or use Src if masked off.
3979 if (!HasRoundingMask || (MaskInt.getZExtValue() & 0x1)) {
3980 assert(S.getASTContext().FloatTy == DstVTy->getElementType() &&
3981 "cvtsd2ss requires float element type in destination vector");
3982
3983 Floating Conv = S.allocFloat(
3984 S.getASTContext().getFloatTypeSemantics(DstVTy->getElementType()));
3985 APFloat SrcVal = B.elem<Floating>(0).getAPFloat();
3986 if (!convertDoubleToFloatStrict(SrcVal, Conv, S, Call))
3987 return false;
3988 Dst.elem<Floating>(0) = Conv;
3989 } else {
3990 Dst.elem<Floating>(0) = Src.elem<Floating>(0);
3991 }
3992
3994 return true;
3995}
3996
3998 const CallExpr *Call, bool IsMasked,
3999 bool HasRounding) {
4000 APSInt MaskVal;
4001 Pointer PassThrough;
4002 Pointer Src;
4003 APSInt Rounding;
4004
4005 if (IsMasked) {
4006 // Pop in reverse order.
4007 if (HasRounding) {
4008 if (!popToAPSInt(S, Call->getArg(3), Rounding))
4009 return false;
4010 if (!popToAPSInt(S, Call->getArg(2), MaskVal))
4011 return false;
4012 PassThrough = S.Stk.pop<Pointer>();
4013 Src = S.Stk.pop<Pointer>();
4014 } else {
4015 if (!popToAPSInt(S, Call->getArg(2), MaskVal))
4016 return false;
4017 PassThrough = S.Stk.pop<Pointer>();
4018 Src = S.Stk.pop<Pointer>();
4019 }
4020
4021 if (!CheckLoad(S, OpPC, PassThrough))
4022 return false;
4023 } else {
4024 // Pop source only.
4025 Src = S.Stk.pop<Pointer>();
4026 }
4027
4028 if (!CheckLoad(S, OpPC, Src))
4029 return false;
4030
4031 const auto *RetVTy = Call->getType()->castAs<VectorType>();
4032 unsigned RetElems = RetVTy->getNumElements();
4033 unsigned SrcElems = Src.getNumElems();
4034 const Pointer &Dst = S.Stk.peek<Pointer>();
4035
4036 // Initialize destination with passthrough or zeros.
4037 for (unsigned I = 0; I != RetElems; ++I)
4038 if (IsMasked)
4039 Dst.elem<Floating>(I) = PassThrough.elem<Floating>(I);
4040 else
4041 Dst.elem<Floating>(I) = Floating(APFloat(0.0f));
4042
4043 assert(S.getASTContext().FloatTy == RetVTy->getElementType() &&
4044 "cvtpd2ps requires float element type in return vector");
4045
4046 // Convert double to float for enabled elements (only process source elements
4047 // that exist).
4048 for (unsigned I = 0; I != SrcElems; ++I) {
4049 if (IsMasked && !MaskVal[I])
4050 continue;
4051
4052 APFloat SrcVal = Src.elem<Floating>(I).getAPFloat();
4053
4054 Floating Conv = S.allocFloat(
4055 S.getASTContext().getFloatTypeSemantics(RetVTy->getElementType()));
4056 if (!convertDoubleToFloatStrict(SrcVal, Conv, S, Call))
4057 return false;
4058 Dst.elem<Floating>(I) = Conv;
4059 }
4060
4062 return true;
4063}
4064
4066 InterpState &S, CodePtr OpPC, const CallExpr *Call,
4067 llvm::function_ref<std::pair<unsigned, int>(unsigned, const APInt &)>
4068 GetSourceIndex) {
4069
4070 assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3);
4071
4072 APInt ShuffleMask;
4073 Pointer A, MaskVector, B;
4074 bool IsVectorMask = false;
4075 bool IsSingleOperand = (Call->getNumArgs() == 2);
4076
4077 if (IsSingleOperand) {
4078 QualType MaskType = Call->getArg(1)->getType();
4079 if (MaskType->isVectorType()) {
4080 IsVectorMask = true;
4081 MaskVector = S.Stk.pop<Pointer>();
4082 A = S.Stk.pop<Pointer>();
4083 B = A;
4084 } else if (MaskType->isIntegerType()) {
4085 APSInt MaskVal;
4086 if (!popToAPSInt(S, Call->getArg(1), MaskVal))
4087 return false;
4088 ShuffleMask = MaskVal;
4089 A = S.Stk.pop<Pointer>();
4090 B = A;
4091 } else {
4092 return false;
4093 }
4094 } else {
4095 QualType Arg2Type = Call->getArg(2)->getType();
4096 if (Arg2Type->isVectorType()) {
4097 IsVectorMask = true;
4098 B = S.Stk.pop<Pointer>();
4099 MaskVector = S.Stk.pop<Pointer>();
4100 A = S.Stk.pop<Pointer>();
4101 } else if (Arg2Type->isIntegerType()) {
4102 APSInt MaskVal;
4103 if (!popToAPSInt(S, Call->getArg(2), MaskVal))
4104 return false;
4105 ShuffleMask = MaskVal;
4106 B = S.Stk.pop<Pointer>();
4107 A = S.Stk.pop<Pointer>();
4108 } else {
4109 return false;
4110 }
4111 }
4112
4113 QualType Arg0Type = Call->getArg(0)->getType();
4114 const auto *VecT = Arg0Type->castAs<VectorType>();
4115 PrimType ElemT = *S.getContext().classify(VecT->getElementType());
4116 unsigned NumElems = VecT->getNumElements();
4117
4118 const Pointer &Dst = S.Stk.peek<Pointer>();
4119
4120 PrimType MaskElemT = PT_Uint32;
4121 if (IsVectorMask) {
4122 QualType Arg1Type = Call->getArg(1)->getType();
4123 const auto *MaskVecT = Arg1Type->castAs<VectorType>();
4124 QualType MaskElemType = MaskVecT->getElementType();
4125 MaskElemT = *S.getContext().classify(MaskElemType);
4126 }
4127
4128 for (unsigned DstIdx = 0; DstIdx != NumElems; ++DstIdx) {
4129 if (IsVectorMask) {
4130 INT_TYPE_SWITCH(MaskElemT,
4131 { ShuffleMask = MaskVector.elem<T>(DstIdx).toAPSInt(); });
4132 }
4133
4134 auto [SrcVecIdx, SrcIdx] = GetSourceIndex(DstIdx, ShuffleMask);
4135
4136 if (SrcIdx < 0) {
4137 // Zero out this element
4138 if (ElemT == PT_Float) {
4139 Dst.elem<Floating>(DstIdx) = Floating(
4140 S.getASTContext().getFloatTypeSemantics(VecT->getElementType()));
4141 } else {
4142 INT_TYPE_SWITCH_NO_BOOL(ElemT, { Dst.elem<T>(DstIdx) = T::from(0); });
4143 }
4144 } else {
4145 const Pointer &Src = (SrcVecIdx == 0) ? A : B;
4146 TYPE_SWITCH(ElemT, { Dst.elem<T>(DstIdx) = Src.elem<T>(SrcIdx); });
4147 }
4148 }
4150
4151 return true;
4152}
4153
4155 InterpState &S, CodePtr OpPC, const CallExpr *Call,
4156 llvm::function_ref<std::pair<unsigned, int>(unsigned, unsigned)>
4157 GetSourceIndex) {
4159 S, OpPC, Call,
4160 [&GetSourceIndex](unsigned DstIdx,
4161 const APInt &Mask) -> std::pair<unsigned, int> {
4162 return GetSourceIndex(DstIdx, Mask.getZExtValue());
4163 });
4164}
4165
4167 InterpState &S, CodePtr OpPC, const CallExpr *Call,
4168 llvm::function_ref<APInt(const APInt &, uint64_t)> ShiftOp,
4169 llvm::function_ref<APInt(const APInt &, unsigned)> OverflowOp) {
4170
4171 assert(Call->getNumArgs() == 2);
4172
4173 const Pointer &Count = S.Stk.pop<Pointer>();
4174 const Pointer &Source = S.Stk.pop<Pointer>();
4175
4176 QualType SourceType = Call->getArg(0)->getType();
4177 QualType CountType = Call->getArg(1)->getType();
4178 assert(SourceType->isVectorType() && CountType->isVectorType());
4179
4180 const auto *SourceVecT = SourceType->castAs<VectorType>();
4181 const auto *CountVecT = CountType->castAs<VectorType>();
4182 PrimType SourceElemT = *S.getContext().classify(SourceVecT->getElementType());
4183 PrimType CountElemT = *S.getContext().classify(CountVecT->getElementType());
4184
4185 const Pointer &Dst = S.Stk.peek<Pointer>();
4186
4187 unsigned DestEltWidth =
4188 S.getASTContext().getTypeSize(SourceVecT->getElementType());
4189 bool IsDestUnsigned = SourceVecT->getElementType()->isUnsignedIntegerType();
4190 unsigned DestLen = SourceVecT->getNumElements();
4191 unsigned CountEltWidth =
4192 S.getASTContext().getTypeSize(CountVecT->getElementType());
4193 unsigned NumBitsInQWord = 64;
4194 unsigned NumCountElts = NumBitsInQWord / CountEltWidth;
4195
4196 uint64_t CountLQWord = 0;
4197 for (unsigned EltIdx = 0; EltIdx != NumCountElts; ++EltIdx) {
4198 uint64_t Elt = 0;
4199 INT_TYPE_SWITCH(CountElemT,
4200 { Elt = static_cast<uint64_t>(Count.elem<T>(EltIdx)); });
4201 CountLQWord |= (Elt << (EltIdx * CountEltWidth));
4202 }
4203
4204 for (unsigned EltIdx = 0; EltIdx != DestLen; ++EltIdx) {
4205 APSInt Elt;
4206 INT_TYPE_SWITCH(SourceElemT, { Elt = Source.elem<T>(EltIdx).toAPSInt(); });
4207
4208 APInt Result;
4209 if (CountLQWord < DestEltWidth) {
4210 Result = ShiftOp(Elt, CountLQWord);
4211 } else {
4212 Result = OverflowOp(Elt, DestEltWidth);
4213 }
4214 if (IsDestUnsigned) {
4215 INT_TYPE_SWITCH(SourceElemT, {
4216 Dst.elem<T>(EltIdx) = T::from(Result.getZExtValue());
4217 });
4218 } else {
4219 INT_TYPE_SWITCH(SourceElemT, {
4220 Dst.elem<T>(EltIdx) = T::from(Result.getSExtValue());
4221 });
4222 }
4223 }
4224
4226 return true;
4227}
4228
4230 const CallExpr *Call) {
4231
4232 assert(Call->getNumArgs() == 3);
4233
4234 QualType SourceType = Call->getArg(0)->getType();
4235 QualType ShuffleMaskType = Call->getArg(1)->getType();
4236 QualType ZeroMaskType = Call->getArg(2)->getType();
4237 if (!SourceType->isVectorType() || !ShuffleMaskType->isVectorType() ||
4238 !ZeroMaskType->isIntegerType()) {
4239 return false;
4240 }
4241
4242 Pointer Source, ShuffleMask;
4243 APSInt ZeroMask;
4244 if (!popToAPSInt(S, Call->getArg(2), ZeroMask))
4245 return false;
4246 ShuffleMask = S.Stk.pop<Pointer>();
4247 Source = S.Stk.pop<Pointer>();
4248
4249 const auto *SourceVecT = SourceType->castAs<VectorType>();
4250 const auto *ShuffleMaskVecT = ShuffleMaskType->castAs<VectorType>();
4251 assert(SourceVecT->getNumElements() == ShuffleMaskVecT->getNumElements());
4252 assert(ZeroMask.getBitWidth() == SourceVecT->getNumElements());
4253
4254 PrimType SourceElemT = *S.getContext().classify(SourceVecT->getElementType());
4255 PrimType ShuffleMaskElemT =
4256 *S.getContext().classify(ShuffleMaskVecT->getElementType());
4257
4258 unsigned NumBytesInQWord = 8;
4259 unsigned NumBitsInByte = 8;
4260 unsigned NumBytes = SourceVecT->getNumElements();
4261 unsigned NumQWords = NumBytes / NumBytesInQWord;
4262 unsigned RetWidth = ZeroMask.getBitWidth();
4263 APSInt RetMask(llvm::APInt(RetWidth, 0), /*isUnsigned=*/true);
4264
4265 for (unsigned QWordId = 0; QWordId != NumQWords; ++QWordId) {
4266 APInt SourceQWord(64, 0);
4267 for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {
4268 uint64_t Byte = 0;
4269 INT_TYPE_SWITCH(SourceElemT, {
4270 Byte = static_cast<uint64_t>(
4271 Source.elem<T>(QWordId * NumBytesInQWord + ByteIdx));
4272 });
4273 SourceQWord.insertBits(APInt(8, Byte & 0xFF), ByteIdx * NumBitsInByte);
4274 }
4275
4276 for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {
4277 unsigned SelIdx = QWordId * NumBytesInQWord + ByteIdx;
4278 unsigned M = 0;
4279 INT_TYPE_SWITCH(ShuffleMaskElemT, {
4280 M = static_cast<unsigned>(ShuffleMask.elem<T>(SelIdx)) & 0x3F;
4281 });
4282
4283 if (ZeroMask[SelIdx]) {
4284 RetMask.setBitVal(SelIdx, SourceQWord[M]);
4285 }
4286 }
4287 }
4288
4289 pushInteger(S, RetMask, Call->getType());
4290 return true;
4291}
4292
4294 const CallExpr *Call) {
4295 // Arguments are: vector of floats, rounding immediate
4296 assert(Call->getNumArgs() == 2);
4297
4298 APSInt Imm;
4299 if (!popToAPSInt(S, Call->getArg(1), Imm))
4300 return false;
4301 const Pointer &Src = S.Stk.pop<Pointer>();
4302 const Pointer &Dst = S.Stk.peek<Pointer>();
4303
4304 assert(Src.getFieldDesc()->isPrimitiveArray());
4305 assert(Dst.getFieldDesc()->isPrimitiveArray());
4306
4307 const auto *SrcVTy = Call->getArg(0)->getType()->castAs<VectorType>();
4308 unsigned SrcNumElems = SrcVTy->getNumElements();
4309 const auto *DstVTy = Call->getType()->castAs<VectorType>();
4310 unsigned DstNumElems = DstVTy->getNumElements();
4311
4312 const llvm::fltSemantics &HalfSem =
4314
4315 // imm[2] == 1 means use MXCSR rounding mode.
4316 // In that case, we can only evaluate if the conversion is exact.
4317 int ImmVal = Imm.getZExtValue();
4318 bool UseMXCSR = (ImmVal & 4) != 0;
4319 bool IsFPConstrained =
4320 Call->getFPFeaturesInEffect(S.getASTContext().getLangOpts())
4321 .isFPConstrained();
4322
4323 llvm::RoundingMode RM;
4324 if (!UseMXCSR) {
4325 switch (ImmVal & 3) {
4326 case 0:
4327 RM = llvm::RoundingMode::NearestTiesToEven;
4328 break;
4329 case 1:
4330 RM = llvm::RoundingMode::TowardNegative;
4331 break;
4332 case 2:
4333 RM = llvm::RoundingMode::TowardPositive;
4334 break;
4335 case 3:
4336 RM = llvm::RoundingMode::TowardZero;
4337 break;
4338 default:
4339 llvm_unreachable("Invalid immediate rounding mode");
4340 }
4341 } else {
4342 // For MXCSR, we must check for exactness. We can use any rounding mode
4343 // for the trial conversion since the result is the same if it's exact.
4344 RM = llvm::RoundingMode::NearestTiesToEven;
4345 }
4346
4347 QualType DstElemQT = Dst.getFieldDesc()->getElemQualType();
4348 PrimType DstElemT = *S.getContext().classify(DstElemQT);
4349
4350 for (unsigned I = 0; I != SrcNumElems; ++I) {
4351 Floating SrcVal = Src.elem<Floating>(I);
4352 APFloat DstVal = SrcVal.getAPFloat();
4353
4354 bool LostInfo;
4355 APFloat::opStatus St = DstVal.convert(HalfSem, RM, &LostInfo);
4356
4357 if (UseMXCSR && IsFPConstrained && St != APFloat::opOK) {
4358 S.FFDiag(S.Current->getSource(OpPC),
4359 diag::note_constexpr_dynamic_rounding);
4360 return false;
4361 }
4362
4363 INT_TYPE_SWITCH_NO_BOOL(DstElemT, {
4364 // Convert the destination value's bit pattern to an unsigned integer,
4365 // then reconstruct the element using the target type's 'from' method.
4366 uint64_t RawBits = DstVal.bitcastToAPInt().getZExtValue();
4367 Dst.elem<T>(I) = T::from(RawBits);
4368 });
4369 }
4370
4371 // Zero out remaining elements if the destination has more elements
4372 // (e.g., vcvtps2ph converting 4 floats to 8 shorts).
4373 if (DstNumElems > SrcNumElems) {
4374 for (unsigned I = SrcNumElems; I != DstNumElems; ++I) {
4375 INT_TYPE_SWITCH_NO_BOOL(DstElemT, { Dst.elem<T>(I) = T::from(0); });
4376 }
4377 }
4378
4379 Dst.initializeAllElements();
4380 return true;
4381}
4382
4384 const CallExpr *Call) {
4385 assert(Call->getNumArgs() == 2);
4386
4387 QualType ATy = Call->getArg(0)->getType();
4388 QualType BTy = Call->getArg(1)->getType();
4389 if (!ATy->isVectorType() || !BTy->isVectorType()) {
4390 return false;
4391 }
4392
4393 const Pointer &BPtr = S.Stk.pop<Pointer>();
4394 const Pointer &APtr = S.Stk.pop<Pointer>();
4395 const auto *AVecT = ATy->castAs<VectorType>();
4396 assert(AVecT->getNumElements() ==
4397 BTy->castAs<VectorType>()->getNumElements());
4398
4399 PrimType ElemT = *S.getContext().classify(AVecT->getElementType());
4400
4401 unsigned NumBytesInQWord = 8;
4402 unsigned NumBitsInByte = 8;
4403 unsigned NumBytes = AVecT->getNumElements();
4404 unsigned NumQWords = NumBytes / NumBytesInQWord;
4405 const Pointer &Dst = S.Stk.peek<Pointer>();
4406
4407 for (unsigned QWordId = 0; QWordId != NumQWords; ++QWordId) {
4408 APInt BQWord(64, 0);
4409 for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {
4410 unsigned Idx = QWordId * NumBytesInQWord + ByteIdx;
4411 INT_TYPE_SWITCH(ElemT, {
4412 uint64_t Byte = static_cast<uint64_t>(BPtr.elem<T>(Idx));
4413 BQWord.insertBits(APInt(8, Byte & 0xFF), ByteIdx * NumBitsInByte);
4414 });
4415 }
4416
4417 for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {
4418 unsigned Idx = QWordId * NumBytesInQWord + ByteIdx;
4419 uint64_t Ctrl = 0;
4421 ElemT, { Ctrl = static_cast<uint64_t>(APtr.elem<T>(Idx)) & 0x3F; });
4422
4423 APInt Byte(8, 0);
4424 for (unsigned BitIdx = 0; BitIdx != NumBitsInByte; ++BitIdx) {
4425 Byte.setBitVal(BitIdx, BQWord[(Ctrl + BitIdx) & 0x3F]);
4426 }
4427 INT_TYPE_SWITCH(ElemT,
4428 { Dst.elem<T>(Idx) = T::from(Byte.getZExtValue()); });
4429 }
4430 }
4431
4433
4434 return true;
4435}
4436
4438 const CallExpr *Call,
4439 bool Inverse) {
4440 assert(Call->getNumArgs() == 3);
4441 QualType XType = Call->getArg(0)->getType();
4442 QualType AType = Call->getArg(1)->getType();
4443 QualType ImmType = Call->getArg(2)->getType();
4444 if (!XType->isVectorType() || !AType->isVectorType() ||
4445 !ImmType->isIntegerType()) {
4446 return false;
4447 }
4448
4449 Pointer X, A;
4450 APSInt Imm;
4451 if (!popToAPSInt(S, Call->getArg(2), Imm))
4452 return false;
4453 A = S.Stk.pop<Pointer>();
4454 X = S.Stk.pop<Pointer>();
4455
4456 const Pointer &Dst = S.Stk.peek<Pointer>();
4457 const auto *AVecT = AType->castAs<VectorType>();
4458 assert(XType->castAs<VectorType>()->getNumElements() ==
4459 AVecT->getNumElements());
4460 unsigned NumBytesInQWord = 8;
4461 unsigned NumBytes = AVecT->getNumElements();
4462 unsigned NumBitsInQWord = 64;
4463 unsigned NumQWords = NumBytes / NumBytesInQWord;
4464 unsigned NumBitsInByte = 8;
4465 PrimType AElemT = *S.getContext().classify(AVecT->getElementType());
4466
4467 // computing A*X + Imm
4468 for (unsigned QWordIdx = 0; QWordIdx != NumQWords; ++QWordIdx) {
4469 // Extract the QWords from X, A
4470 APInt XQWord(NumBitsInQWord, 0);
4471 APInt AQWord(NumBitsInQWord, 0);
4472 for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {
4473 unsigned Idx = QWordIdx * NumBytesInQWord + ByteIdx;
4474 uint8_t XByte;
4475 uint8_t AByte;
4476 INT_TYPE_SWITCH(AElemT, {
4477 XByte = static_cast<uint8_t>(X.elem<T>(Idx));
4478 AByte = static_cast<uint8_t>(A.elem<T>(Idx));
4479 });
4480
4481 XQWord.insertBits(APInt(NumBitsInByte, XByte), ByteIdx * NumBitsInByte);
4482 AQWord.insertBits(APInt(NumBitsInByte, AByte), ByteIdx * NumBitsInByte);
4483 }
4484
4485 for (unsigned ByteIdx = 0; ByteIdx != NumBytesInQWord; ++ByteIdx) {
4486 unsigned Idx = QWordIdx * NumBytesInQWord + ByteIdx;
4487 uint8_t XByte =
4488 XQWord.lshr(ByteIdx * NumBitsInByte).getLoBits(8).getZExtValue();
4489 INT_TYPE_SWITCH(AElemT, {
4490 Dst.elem<T>(Idx) = T::from(GFNIAffine(XByte, AQWord, Imm, Inverse));
4491 });
4492 }
4493 }
4494 Dst.initializeAllElements();
4495 return true;
4496}
4497
4499 const CallExpr *Call) {
4500 assert(Call->getNumArgs() == 2);
4501
4502 QualType AType = Call->getArg(0)->getType();
4503 QualType BType = Call->getArg(1)->getType();
4504 if (!AType->isVectorType() || !BType->isVectorType()) {
4505 return false;
4506 }
4507
4508 Pointer A, B;
4509 B = S.Stk.pop<Pointer>();
4510 A = S.Stk.pop<Pointer>();
4511
4512 const Pointer &Dst = S.Stk.peek<Pointer>();
4513 const auto *AVecT = AType->castAs<VectorType>();
4514 assert(AVecT->getNumElements() ==
4515 BType->castAs<VectorType>()->getNumElements());
4516
4517 PrimType AElemT = *S.getContext().classify(AVecT->getElementType());
4518 unsigned NumBytes = A.getNumElems();
4519
4520 for (unsigned ByteIdx = 0; ByteIdx != NumBytes; ++ByteIdx) {
4521 uint8_t AByte, BByte;
4522 INT_TYPE_SWITCH(AElemT, {
4523 AByte = static_cast<uint8_t>(A.elem<T>(ByteIdx));
4524 BByte = static_cast<uint8_t>(B.elem<T>(ByteIdx));
4525 Dst.elem<T>(ByteIdx) = T::from(GFNIMul(AByte, BByte));
4526 });
4527 }
4528
4529 Dst.initializeAllElements();
4530 return true;
4531}
4532
4534 const CallExpr *Call, bool IsSaturating) {
4535 assert(Call->getNumArgs() == 3);
4536
4537 QualType SrcT = Call->getArg(0)->getType();
4538 QualType OpAT = Call->getArg(1)->getType();
4539 QualType OpBT = Call->getArg(2)->getType();
4540 QualType DstT = Call->getType();
4541 if (!SrcT->isVectorType() || !OpAT->isVectorType() || !OpBT->isVectorType() ||
4542 !DstT->isVectorType())
4543 return false;
4544
4545 const auto *SrcVecT = SrcT->castAs<VectorType>();
4546 const auto *OpAVecT = OpAT->castAs<VectorType>();
4547 const auto *OpBVecT = OpBT->castAs<VectorType>();
4548 const auto *DstVecT = DstT->castAs<VectorType>();
4549
4550 assert(OpAVecT->getNumElements() == OpBVecT->getNumElements());
4551
4552 unsigned NumSrcElems = SrcVecT->getNumElements();
4553 unsigned NumOperandElems = OpAVecT->getNumElements();
4554 unsigned ElemsPerLane = NumOperandElems / NumSrcElems;
4555
4556 PrimType SrcElemT = *S.getContext().classify(SrcVecT->getElementType());
4557 PrimType OpAElemT = *S.getContext().classify(OpAVecT->getElementType());
4558 PrimType OpBElemT = *S.getContext().classify(OpBVecT->getElementType());
4559 PrimType DstElemT = *S.getContext().classify(DstVecT->getElementType());
4560
4561 assert(SrcElemT == DstElemT);
4562
4563 const Pointer &OpBPtr = S.Stk.pop<Pointer>();
4564 const Pointer &OpAPtr = S.Stk.pop<Pointer>();
4565 const Pointer &SrcPtr = S.Stk.pop<Pointer>();
4566 const Pointer &Dst = S.Stk.peek<Pointer>();
4567
4568 for (unsigned I = 0; I != NumSrcElems; ++I) {
4569 APSInt Acc;
4570 INT_TYPE_SWITCH_NO_BOOL(SrcElemT, { Acc = SrcPtr.elem<T>(I).toAPSInt(); });
4571 Acc = Acc.sext(64);
4572 for (unsigned J = 0; J != ElemsPerLane; ++J) {
4573 APSInt OpA, OpB;
4575 OpAElemT, { OpA = OpAPtr.elem<T>(ElemsPerLane * I + J).toAPSInt(); });
4577 OpBElemT, { OpB = OpBPtr.elem<T>(ElemsPerLane * I + J).toAPSInt(); });
4578 OpA = APSInt(OpA.extend(64), false);
4579 OpB = APSInt(OpB.extend(64), false);
4580 Acc += OpA * OpB;
4581 }
4582 if (IsSaturating)
4583 Acc = APSInt(Acc.truncSSat(32), false);
4584 else
4585 Acc = APSInt(Acc.trunc(32), false);
4586 INT_TYPE_SWITCH_NO_BOOL(DstElemT,
4587 { Dst.elem<T>(I) = static_cast<T>(Acc); });
4588 }
4590 return true;
4591}
4592
4593// Bit Matrix Multiply and Accumulate (AVX512BMM). Each 256-bit lane holds a
4594// 16x16 bit matrix as 16 x i16 elements; element i is row i and bit j of that
4595// element is entry [i][j]. The accumulator (third argument, src1 in the AMD
4596// ISA) provides the initial value of each result bit, into which the bit-matrix
4597// product of the first two arguments (src2 * src3) is reduced with OR (vbmacor)
4598// or XOR (vbmacxor):
4599// for i in 0..15, j in 0..15:
4600// bit = C[16*i+j]
4601// for k in 0..15: bit OP= A[16*i+k] & B[16*k+j]
4602// dest[16*i+j] = bit
4604 const CallExpr *Call, bool IsXor) {
4605 assert(Call->getNumArgs() == 3);
4606
4607 // AST-based type checks before popping the stack.
4608 QualType AType = Call->getArg(0)->getType();
4609 QualType BType = Call->getArg(1)->getType();
4610 QualType CType = Call->getArg(2)->getType();
4611 if (!AType->isVectorType() || !BType->isVectorType() ||
4612 !CType->isVectorType())
4613 return false;
4614
4615 const Pointer &C = S.Stk.pop<Pointer>();
4616 const Pointer &B = S.Stk.pop<Pointer>();
4617 const Pointer &A = S.Stk.pop<Pointer>();
4618 const Pointer &Dst = S.Stk.peek<Pointer>();
4619
4620 // check if all three primitive arrays are with 16-bit elements.
4621 auto isValid16BitArray = [](const Pointer &P) {
4622 const Descriptor *D = P.getFieldDesc();
4623 if (!D->isPrimitiveArray())
4624 return false;
4625 PrimType PT = D->getPrimType();
4626 return ((PT == PT_Sint16) || (PT == PT_Uint16));
4627 };
4628
4629 if (!isValid16BitArray(A) || !isValid16BitArray(B) || !isValid16BitArray(C))
4630 return false;
4631
4632 PrimType ElemT = A.getFieldDesc()->getPrimType();
4633 unsigned NumElems = A.getNumElems();
4634 assert(NumElems % 16 == 0 && "BMM operates on 256-bit lanes of 16 x i16");
4635 bool DstUnsigned = ElemT == PT_Uint16;
4636
4637 // Lanes are always 16-bit; gather them so the reduction below is untyped.
4638 SmallVector<uint16_t> AVals(NumElems), BVals(NumElems), Acc(NumElems);
4640 for (unsigned I = 0; I != NumElems; ++I) {
4641 AVals[I] = (uint16_t)A.elem<T>(I).toAPSInt().getZExtValue();
4642 BVals[I] = (uint16_t)B.elem<T>(I).toAPSInt().getZExtValue();
4643 Acc[I] = (uint16_t)C.elem<T>(I).toAPSInt().getZExtValue();
4644 }
4645 });
4646
4647 for (unsigned Lane = 0; Lane != NumElems; Lane += 16) {
4648 for (unsigned I = 0; I != 16; ++I) {
4649 uint16_t AVal = AVals[Lane + I], DVal = Acc[Lane + I];
4650 for (unsigned J = 0; J != 16; ++J) {
4651 // Seed the reduction with the accumulator bit, then fold in each
4652 // product term with the same operator (OR for vbmacor, XOR for
4653 // vbmacxor).
4654 unsigned Bit = (DVal >> J) & 1u;
4655 for (unsigned K = 0; K != 16; ++K) {
4656 unsigned Product = ((AVal >> K) & 1u) & ((BVals[Lane + K] >> J) & 1u);
4657 Bit = IsXor ? (Bit ^ Product) : (Bit | Product);
4658 }
4659 DVal = (DVal & ~(uint16_t(1) << J)) | (uint16_t(Bit) << J);
4660 }
4661 Acc[Lane + I] = DVal;
4662 }
4663 }
4664
4666 for (unsigned I = 0; I != NumElems; ++I)
4667 Dst.elem<T>(I) = static_cast<T>(APSInt(APInt(16, Acc[I]), DstUnsigned));
4668 });
4669 Dst.initializeAllElements();
4670 return true;
4671}
4672
4674 uint32_t BuiltinID) {
4675 const ASTContext &ASTCtx = S.getASTContext();
4676
4677 // BuiltinID is the raw ID baked into the bytecode. The "is constant
4678 // evaluated" gate needs the raw ID so that auxiliary-target IDs resolve into
4679 // the correct (aux-target) builtin records.
4680 if (!ASTCtx.BuiltinInfo.isConstantEvaluated(BuiltinID))
4681 return Invalid(S, OpPC);
4682
4683 // Convert an auxiliary x86 target builtin ID to its canonical X86::BI* value
4684 // so the target-specific cases below (and the handlers they call) match. This
4685 // is a cheap integer operation (a single comparison for the common,
4686 // target-independent case); we deliberately avoid re-deriving the ID from the
4687 // call expression, which is comparatively slow.
4688 BuiltinID = ConvertBuiltinIDToX86BuiltinID(ASTCtx, BuiltinID);
4689
4690 const InterpFrame *Frame = S.Current;
4691 switch (BuiltinID) {
4692 case Builtin::BI__builtin_is_constant_evaluated:
4694
4695 case Builtin::BI__builtin_assume:
4696 case Builtin::BI__assume:
4697 return interp__builtin_assume(S, OpPC, Frame, Call);
4698
4699 case Builtin::BI__builtin_strcmp:
4700 case Builtin::BIstrcmp:
4701 case Builtin::BI__builtin_strncmp:
4702 case Builtin::BIstrncmp:
4703 case Builtin::BI__builtin_wcsncmp:
4704 case Builtin::BIwcsncmp:
4705 case Builtin::BI__builtin_wcscmp:
4706 case Builtin::BIwcscmp:
4707 return interp__builtin_strcmp(S, OpPC, Frame, Call, BuiltinID);
4708
4709 case Builtin::BI__builtin_strlen:
4710 case Builtin::BIstrlen:
4711 case Builtin::BI__builtin_wcslen:
4712 case Builtin::BIwcslen:
4713 return interp__builtin_strlen(S, OpPC, Frame, Call, BuiltinID);
4714
4715 case Builtin::BI__builtin_nan:
4716 case Builtin::BI__builtin_nanf:
4717 case Builtin::BI__builtin_nanl:
4718 case Builtin::BI__builtin_nanf16:
4719 case Builtin::BI__builtin_nanf128:
4720 return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/false);
4721
4722 case Builtin::BI__builtin_nans:
4723 case Builtin::BI__builtin_nansf:
4724 case Builtin::BI__builtin_nansl:
4725 case Builtin::BI__builtin_nansf16:
4726 case Builtin::BI__builtin_nansf128:
4727 return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/true);
4728
4729 case Builtin::BI__builtin_huge_val:
4730 case Builtin::BI__builtin_huge_valf:
4731 case Builtin::BI__builtin_huge_vall:
4732 case Builtin::BI__builtin_huge_valf16:
4733 case Builtin::BI__builtin_huge_valf128:
4734 case Builtin::BI__builtin_inf:
4735 case Builtin::BI__builtin_inff:
4736 case Builtin::BI__builtin_infl:
4737 case Builtin::BI__builtin_inff16:
4738 case Builtin::BI__builtin_inff128:
4739 return interp__builtin_inf(S, OpPC, Frame, Call);
4740
4741 case Builtin::BI__builtin_copysign:
4742 case Builtin::BI__builtin_copysignf:
4743 case Builtin::BI__builtin_copysignl:
4744 case Builtin::BI__builtin_copysignf128:
4745 return interp__builtin_copysign(S, OpPC, Frame);
4746
4747 case Builtin::BI__builtin_fmin:
4748 case Builtin::BI__builtin_fminf:
4749 case Builtin::BI__builtin_fminl:
4750 case Builtin::BI__builtin_fminf16:
4751 case Builtin::BI__builtin_fminf128:
4752 return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/false);
4753
4754 case Builtin::BI__builtin_fminimum_num:
4755 case Builtin::BI__builtin_fminimum_numf:
4756 case Builtin::BI__builtin_fminimum_numl:
4757 case Builtin::BI__builtin_fminimum_numf16:
4758 case Builtin::BI__builtin_fminimum_numf128:
4759 return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/true);
4760
4761 case Builtin::BI__builtin_fmax:
4762 case Builtin::BI__builtin_fmaxf:
4763 case Builtin::BI__builtin_fmaxl:
4764 case Builtin::BI__builtin_fmaxf16:
4765 case Builtin::BI__builtin_fmaxf128:
4766 return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/false);
4767
4768 case Builtin::BI__builtin_fmaximum_num:
4769 case Builtin::BI__builtin_fmaximum_numf:
4770 case Builtin::BI__builtin_fmaximum_numl:
4771 case Builtin::BI__builtin_fmaximum_numf16:
4772 case Builtin::BI__builtin_fmaximum_numf128:
4773 return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/true);
4774
4775 case Builtin::BI__builtin_isnan:
4776 return interp__builtin_isnan(S, OpPC, Frame, Call);
4777
4778 case Builtin::BI__builtin_issignaling:
4779 return interp__builtin_issignaling(S, OpPC, Frame, Call);
4780
4781 case Builtin::BI__builtin_isinf:
4782 return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/false, Call);
4783
4784 case Builtin::BI__builtin_isinf_sign:
4785 return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/true, Call);
4786
4787 case Builtin::BI__builtin_isfinite:
4788 return interp__builtin_isfinite(S, OpPC, Frame, Call);
4789
4790 case Builtin::BI__builtin_isnormal:
4791 return interp__builtin_isnormal(S, OpPC, Frame, Call);
4792
4793 case Builtin::BI__builtin_issubnormal:
4794 return interp__builtin_issubnormal(S, OpPC, Frame, Call);
4795
4796 case Builtin::BI__builtin_iszero:
4797 return interp__builtin_iszero(S, OpPC, Frame, Call);
4798
4799 case Builtin::BI__builtin_signbit:
4800 case Builtin::BI__builtin_signbitf:
4801 case Builtin::BI__builtin_signbitl:
4802 return interp__builtin_signbit(S, OpPC, Frame, Call);
4803
4804 case Builtin::BI__builtin_isgreater:
4805 case Builtin::BI__builtin_isgreaterequal:
4806 case Builtin::BI__builtin_isless:
4807 case Builtin::BI__builtin_islessequal:
4808 case Builtin::BI__builtin_islessgreater:
4809 case Builtin::BI__builtin_isunordered:
4810 return interp_floating_comparison(S, OpPC, Call, BuiltinID);
4811
4812 case Builtin::BI__builtin_isfpclass:
4813 return interp__builtin_isfpclass(S, OpPC, Frame, Call);
4814
4815 case Builtin::BI__builtin_fpclassify:
4816 return interp__builtin_fpclassify(S, OpPC, Frame, Call);
4817
4818 case Builtin::BI__builtin_fabs:
4819 case Builtin::BI__builtin_fabsf:
4820 case Builtin::BI__builtin_fabsl:
4821 case Builtin::BI__builtin_fabsf128:
4822 return interp__builtin_fabs(S, OpPC, Frame);
4823
4824 case Builtin::BI__builtin_abs:
4825 case Builtin::BI__builtin_labs:
4826 case Builtin::BI__builtin_llabs:
4827 return interp__builtin_abs(S, OpPC, Frame, Call);
4828
4829 case Builtin::BI__builtin_popcount:
4830 case Builtin::BI__builtin_popcountl:
4831 case Builtin::BI__builtin_popcountll:
4832 case Builtin::BI__builtin_popcountg:
4833 case Builtin::BI__popcnt16: // Microsoft variants of popcount
4834 case Builtin::BI__popcnt:
4835 case Builtin::BI__popcnt64:
4836 return interp__builtin_popcount(S, OpPC, Frame, Call);
4837
4838 case Builtin::BI__builtin_parity:
4839 case Builtin::BI__builtin_parityl:
4840 case Builtin::BI__builtin_parityll:
4842 S, OpPC, Call, [](const APSInt &Val) {
4843 return APInt(Val.getBitWidth(), Val.popcount() % 2);
4844 });
4845 case Builtin::BI__builtin_clrsb:
4846 case Builtin::BI__builtin_clrsbl:
4847 case Builtin::BI__builtin_clrsbll:
4849 S, OpPC, Call, [](const APSInt &Val) {
4850 return APInt(Val.getBitWidth(),
4851 Val.getBitWidth() - Val.getSignificantBits());
4852 });
4853 case Builtin::BI__builtin_bitreverseg:
4854 case Builtin::BI__builtin_bitreverse8:
4855 case Builtin::BI__builtin_bitreverse16:
4856 case Builtin::BI__builtin_bitreverse32:
4857 case Builtin::BI__builtin_bitreverse64:
4859 S, OpPC, Call, [](const APSInt &Val) { return Val.reverseBits(); });
4860
4861 case Builtin::BI__builtin_classify_type:
4862 return interp__builtin_classify_type(S, OpPC, Frame, Call);
4863
4864 case Builtin::BI__builtin_expect:
4865 case Builtin::BI__builtin_expect_with_probability:
4866 return interp__builtin_expect(S, OpPC, Frame, Call);
4867
4868 case Builtin::BI__builtin_rotateleft8:
4869 case Builtin::BI__builtin_rotateleft16:
4870 case Builtin::BI__builtin_rotateleft32:
4871 case Builtin::BI__builtin_rotateleft64:
4872 case Builtin::BI__builtin_stdc_rotate_left:
4873 case Builtin::BIstdc_rotate_left_uc:
4874 case Builtin::BIstdc_rotate_left_us:
4875 case Builtin::BIstdc_rotate_left_ui:
4876 case Builtin::BIstdc_rotate_left_ul:
4877 case Builtin::BIstdc_rotate_left_ull:
4878 case Builtin::BI_rotl8: // Microsoft variants of rotate left
4879 case Builtin::BI_rotl16:
4880 case Builtin::BI_rotl:
4881 case Builtin::BI_lrotl:
4882 case Builtin::BI_rotl64:
4883 case Builtin::BI__builtin_rotateright8:
4884 case Builtin::BI__builtin_rotateright16:
4885 case Builtin::BI__builtin_rotateright32:
4886 case Builtin::BI__builtin_rotateright64:
4887 case Builtin::BI__builtin_stdc_rotate_right:
4888 case Builtin::BIstdc_rotate_right_uc:
4889 case Builtin::BIstdc_rotate_right_us:
4890 case Builtin::BIstdc_rotate_right_ui:
4891 case Builtin::BIstdc_rotate_right_ul:
4892 case Builtin::BIstdc_rotate_right_ull:
4893 case Builtin::BI_rotr8: // Microsoft variants of rotate right
4894 case Builtin::BI_rotr16:
4895 case Builtin::BI_rotr:
4896 case Builtin::BI_lrotr:
4897 case Builtin::BI_rotr64: {
4898 // Determine if this is a rotate right operation
4899 bool IsRotateRight;
4900 switch (BuiltinID) {
4901 case Builtin::BI__builtin_rotateright8:
4902 case Builtin::BI__builtin_rotateright16:
4903 case Builtin::BI__builtin_rotateright32:
4904 case Builtin::BI__builtin_rotateright64:
4905 case Builtin::BI__builtin_stdc_rotate_right:
4906 case Builtin::BIstdc_rotate_right_uc:
4907 case Builtin::BIstdc_rotate_right_us:
4908 case Builtin::BIstdc_rotate_right_ui:
4909 case Builtin::BIstdc_rotate_right_ul:
4910 case Builtin::BIstdc_rotate_right_ull:
4911 case Builtin::BI_rotr8:
4912 case Builtin::BI_rotr16:
4913 case Builtin::BI_rotr:
4914 case Builtin::BI_lrotr:
4915 case Builtin::BI_rotr64:
4916 IsRotateRight = true;
4917 break;
4918 default:
4919 IsRotateRight = false;
4920 break;
4921 }
4922
4924 S, OpPC, Call, [IsRotateRight](const APSInt &Value, APSInt Amount) {
4925 Amount = NormalizeRotateAmount(Value, Amount);
4926 return IsRotateRight ? Value.rotr(Amount.getZExtValue())
4927 : Value.rotl(Amount.getZExtValue());
4928 });
4929 }
4930
4931 case Builtin::BIstdc_leading_zeros_uc:
4932 case Builtin::BIstdc_leading_zeros_us:
4933 case Builtin::BIstdc_leading_zeros_ui:
4934 case Builtin::BIstdc_leading_zeros_ul:
4935 case Builtin::BIstdc_leading_zeros_ull:
4936 case Builtin::BI__builtin_stdc_leading_zeros: {
4937 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4939 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4940 return APInt(ResWidth, Val.countl_zero());
4941 });
4942 }
4943
4944 case Builtin::BIstdc_leading_ones_uc:
4945 case Builtin::BIstdc_leading_ones_us:
4946 case Builtin::BIstdc_leading_ones_ui:
4947 case Builtin::BIstdc_leading_ones_ul:
4948 case Builtin::BIstdc_leading_ones_ull:
4949 case Builtin::BI__builtin_stdc_leading_ones: {
4950 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4952 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4953 return APInt(ResWidth, Val.countl_one());
4954 });
4955 }
4956
4957 case Builtin::BIstdc_trailing_zeros_uc:
4958 case Builtin::BIstdc_trailing_zeros_us:
4959 case Builtin::BIstdc_trailing_zeros_ui:
4960 case Builtin::BIstdc_trailing_zeros_ul:
4961 case Builtin::BIstdc_trailing_zeros_ull:
4962 case Builtin::BI__builtin_stdc_trailing_zeros: {
4963 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4965 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4966 return APInt(ResWidth, Val.countr_zero());
4967 });
4968 }
4969
4970 case Builtin::BIstdc_trailing_ones_uc:
4971 case Builtin::BIstdc_trailing_ones_us:
4972 case Builtin::BIstdc_trailing_ones_ui:
4973 case Builtin::BIstdc_trailing_ones_ul:
4974 case Builtin::BIstdc_trailing_ones_ull:
4975 case Builtin::BI__builtin_stdc_trailing_ones: {
4976 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4978 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4979 return APInt(ResWidth, Val.countr_one());
4980 });
4981 }
4982
4983 case Builtin::BIstdc_first_leading_zero_uc:
4984 case Builtin::BIstdc_first_leading_zero_us:
4985 case Builtin::BIstdc_first_leading_zero_ui:
4986 case Builtin::BIstdc_first_leading_zero_ul:
4987 case Builtin::BIstdc_first_leading_zero_ull:
4988 case Builtin::BI__builtin_stdc_first_leading_zero: {
4989 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
4991 S, OpPC, Call, [ResWidth](const APSInt &Val) {
4992 return APInt(ResWidth, Val.isAllOnes() ? 0 : Val.countl_one() + 1);
4993 });
4994 }
4995
4996 case Builtin::BIstdc_first_leading_one_uc:
4997 case Builtin::BIstdc_first_leading_one_us:
4998 case Builtin::BIstdc_first_leading_one_ui:
4999 case Builtin::BIstdc_first_leading_one_ul:
5000 case Builtin::BIstdc_first_leading_one_ull:
5001 case Builtin::BI__builtin_stdc_first_leading_one: {
5002 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
5004 S, OpPC, Call, [ResWidth](const APSInt &Val) {
5005 return APInt(ResWidth, Val.isZero() ? 0 : Val.countl_zero() + 1);
5006 });
5007 }
5008
5009 case Builtin::BIstdc_first_trailing_zero_uc:
5010 case Builtin::BIstdc_first_trailing_zero_us:
5011 case Builtin::BIstdc_first_trailing_zero_ui:
5012 case Builtin::BIstdc_first_trailing_zero_ul:
5013 case Builtin::BIstdc_first_trailing_zero_ull:
5014 case Builtin::BI__builtin_stdc_first_trailing_zero: {
5015 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
5017 S, OpPC, Call, [ResWidth](const APSInt &Val) {
5018 return APInt(ResWidth, Val.isAllOnes() ? 0 : Val.countr_one() + 1);
5019 });
5020 }
5021
5022 case Builtin::BIstdc_first_trailing_one_uc:
5023 case Builtin::BIstdc_first_trailing_one_us:
5024 case Builtin::BIstdc_first_trailing_one_ui:
5025 case Builtin::BIstdc_first_trailing_one_ul:
5026 case Builtin::BIstdc_first_trailing_one_ull:
5027 case Builtin::BI__builtin_stdc_first_trailing_one: {
5028 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
5030 S, OpPC, Call, [ResWidth](const APSInt &Val) {
5031 return APInt(ResWidth, Val.isZero() ? 0 : Val.countr_zero() + 1);
5032 });
5033 }
5034
5035 case Builtin::BIstdc_count_zeros_uc:
5036 case Builtin::BIstdc_count_zeros_us:
5037 case Builtin::BIstdc_count_zeros_ui:
5038 case Builtin::BIstdc_count_zeros_ul:
5039 case Builtin::BIstdc_count_zeros_ull:
5040 case Builtin::BI__builtin_stdc_count_zeros: {
5041 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
5043 S, OpPC, Call, [ResWidth](const APSInt &Val) {
5044 unsigned BitWidth = Val.getBitWidth();
5045 return APInt(ResWidth, BitWidth - Val.popcount());
5046 });
5047 }
5048
5049 case Builtin::BIstdc_count_ones_uc:
5050 case Builtin::BIstdc_count_ones_us:
5051 case Builtin::BIstdc_count_ones_ui:
5052 case Builtin::BIstdc_count_ones_ul:
5053 case Builtin::BIstdc_count_ones_ull:
5054 case Builtin::BI__builtin_stdc_count_ones: {
5055 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
5057 S, OpPC, Call, [ResWidth](const APSInt &Val) {
5058 return APInt(ResWidth, Val.popcount());
5059 });
5060 }
5061
5062 case Builtin::BIstdc_has_single_bit_uc:
5063 case Builtin::BIstdc_has_single_bit_us:
5064 case Builtin::BIstdc_has_single_bit_ui:
5065 case Builtin::BIstdc_has_single_bit_ul:
5066 case Builtin::BIstdc_has_single_bit_ull:
5067 case Builtin::BI__builtin_stdc_has_single_bit: {
5068 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
5070 S, OpPC, Call, [ResWidth](const APSInt &Val) {
5071 return APInt(ResWidth, Val.popcount() == 1 ? 1 : 0);
5072 });
5073 }
5074
5075 case Builtin::BIstdc_bit_width_uc:
5076 case Builtin::BIstdc_bit_width_us:
5077 case Builtin::BIstdc_bit_width_ui:
5078 case Builtin::BIstdc_bit_width_ul:
5079 case Builtin::BIstdc_bit_width_ull:
5080 case Builtin::BI__builtin_stdc_bit_width: {
5081 unsigned ResWidth = S.getASTContext().getIntWidth(Call->getType());
5083 S, OpPC, Call, [ResWidth](const APSInt &Val) {
5084 unsigned BitWidth = Val.getBitWidth();
5085 return APInt(ResWidth, BitWidth - Val.countl_zero());
5086 });
5087 }
5088
5089 case Builtin::BIstdc_bit_floor_uc:
5090 case Builtin::BIstdc_bit_floor_us:
5091 case Builtin::BIstdc_bit_floor_ui:
5092 case Builtin::BIstdc_bit_floor_ul:
5093 case Builtin::BIstdc_bit_floor_ull:
5094 case Builtin::BI__builtin_stdc_bit_floor:
5096 S, OpPC, Call, [](const APSInt &Val) {
5097 unsigned BitWidth = Val.getBitWidth();
5098 if (Val.isZero())
5099 return APInt::getZero(BitWidth);
5100 return APInt::getOneBitSet(BitWidth,
5101 BitWidth - Val.countl_zero() - 1);
5102 });
5103
5104 case Builtin::BIstdc_bit_ceil_uc:
5105 case Builtin::BIstdc_bit_ceil_us:
5106 case Builtin::BIstdc_bit_ceil_ui:
5107 case Builtin::BIstdc_bit_ceil_ul:
5108 case Builtin::BIstdc_bit_ceil_ull:
5109 case Builtin::BI__builtin_stdc_bit_ceil:
5111 S, OpPC, Call, [](const APSInt &Val) {
5112 unsigned BitWidth = Val.getBitWidth();
5113 if (Val.ule(1))
5114 return APInt(BitWidth, 1);
5115 APInt V = Val;
5116 APInt ValMinusOne = V - 1;
5117 unsigned LeadingZeros = ValMinusOne.countl_zero();
5118 if (LeadingZeros == 0)
5119 return APInt(BitWidth, 0); // overflows; wrap to 0
5120 return APInt::getOneBitSet(BitWidth, BitWidth - LeadingZeros);
5121 });
5122
5123 case Builtin::BI__builtin_ffs:
5124 case Builtin::BI__builtin_ffsl:
5125 case Builtin::BI__builtin_ffsll:
5127 S, OpPC, Call, [](const APSInt &Val) {
5128 return APInt(Val.getBitWidth(),
5129 Val.isZero() ? 0u : Val.countTrailingZeros() + 1u);
5130 });
5131
5132 case Builtin::BIaddressof:
5133 case Builtin::BI__addressof:
5134 case Builtin::BI__builtin_addressof:
5135 assert(isNoopBuiltin(BuiltinID));
5136 return interp__builtin_addressof(S, OpPC, Frame, Call);
5137
5138 case Builtin::BIas_const:
5139 case Builtin::BIforward:
5140 case Builtin::BIforward_like:
5141 case Builtin::BImove:
5142 case Builtin::BImove_if_noexcept:
5143 assert(isNoopBuiltin(BuiltinID));
5144 return interp__builtin_move(S, OpPC, Frame, Call);
5145
5146 case Builtin::BI__builtin_eh_return_data_regno:
5148
5149 case Builtin::BI__builtin_launder:
5150 assert(isNoopBuiltin(BuiltinID));
5151 return true;
5152
5153 case Builtin::BI__builtin_add_overflow:
5154 case Builtin::BI__builtin_sub_overflow:
5155 case Builtin::BI__builtin_mul_overflow:
5156 case Builtin::BI__builtin_sadd_overflow:
5157 case Builtin::BI__builtin_uadd_overflow:
5158 case Builtin::BI__builtin_uaddl_overflow:
5159 case Builtin::BI__builtin_uaddll_overflow:
5160 case Builtin::BI__builtin_usub_overflow:
5161 case Builtin::BI__builtin_usubl_overflow:
5162 case Builtin::BI__builtin_usubll_overflow:
5163 case Builtin::BI__builtin_umul_overflow:
5164 case Builtin::BI__builtin_umull_overflow:
5165 case Builtin::BI__builtin_umulll_overflow:
5166 case Builtin::BI__builtin_saddl_overflow:
5167 case Builtin::BI__builtin_saddll_overflow:
5168 case Builtin::BI__builtin_ssub_overflow:
5169 case Builtin::BI__builtin_ssubl_overflow:
5170 case Builtin::BI__builtin_ssubll_overflow:
5171 case Builtin::BI__builtin_smul_overflow:
5172 case Builtin::BI__builtin_smull_overflow:
5173 case Builtin::BI__builtin_smulll_overflow:
5174 return interp__builtin_overflowop(S, OpPC, Call, BuiltinID);
5175
5176 case Builtin::BI__builtin_addcb:
5177 case Builtin::BI__builtin_addcs:
5178 case Builtin::BI__builtin_addc:
5179 case Builtin::BI__builtin_addcl:
5180 case Builtin::BI__builtin_addcll:
5181 case Builtin::BI__builtin_subcb:
5182 case Builtin::BI__builtin_subcs:
5183 case Builtin::BI__builtin_subc:
5184 case Builtin::BI__builtin_subcl:
5185 case Builtin::BI__builtin_subcll:
5186 return interp__builtin_carryop(S, OpPC, Frame, Call, BuiltinID);
5187
5188 case Builtin::BI__builtin_clz:
5189 case Builtin::BI__builtin_clzl:
5190 case Builtin::BI__builtin_clzll:
5191 case Builtin::BI__builtin_clzs:
5192 case Builtin::BI__builtin_clzg:
5193 case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
5194 case Builtin::BI__lzcnt:
5195 case Builtin::BI__lzcnt64:
5196 return interp__builtin_clz(S, OpPC, Frame, Call, BuiltinID);
5197
5198 case Builtin::BI__builtin_ctz:
5199 case Builtin::BI__builtin_ctzl:
5200 case Builtin::BI__builtin_ctzll:
5201 case Builtin::BI__builtin_ctzs:
5202 case Builtin::BI__builtin_ctzg:
5203 return interp__builtin_ctz(S, OpPC, Frame, Call, BuiltinID);
5204
5205 case Builtin::BI__builtin_elementwise_clzg:
5206 case Builtin::BI__builtin_elementwise_ctzg:
5208 BuiltinID);
5209 case Builtin::BI__builtin_bswapg:
5210 case Builtin::BI__builtin_bswap16:
5211 case Builtin::BI__builtin_bswap32:
5212 case Builtin::BI__builtin_bswap64:
5213 case Builtin::BIstdc_memreverse8u8:
5214 case Builtin::BIstdc_memreverse8u16:
5215 case Builtin::BIstdc_memreverse8u32:
5216 case Builtin::BIstdc_memreverse8u64:
5217 return interp__builtin_bswap(S, OpPC, Frame, Call);
5218
5219 case Builtin::BI__atomic_always_lock_free:
5220 case Builtin::BI__atomic_is_lock_free:
5221 return interp__builtin_atomic_lock_free(S, OpPC, Frame, Call, BuiltinID);
5222
5223 case Builtin::BI__c11_atomic_is_lock_free:
5225
5226 case Builtin::BI__builtin_complex:
5227 return interp__builtin_complex(S, OpPC, Frame, Call);
5228
5229 case Builtin::BI__builtin_is_aligned:
5230 case Builtin::BI__builtin_align_up:
5231 case Builtin::BI__builtin_align_down:
5232 return interp__builtin_is_aligned_up_down(S, OpPC, Frame, Call, BuiltinID);
5233
5234 case Builtin::BI__builtin_assume_aligned:
5235 return interp__builtin_assume_aligned(S, OpPC, Frame, Call);
5236
5237 case clang::X86::BI__builtin_ia32_crc32qi:
5238 return interp__builtin_ia32_crc32(S, OpPC, Frame, Call, 1);
5239 case clang::X86::BI__builtin_ia32_crc32hi:
5240 return interp__builtin_ia32_crc32(S, OpPC, Frame, Call, 2);
5241 case clang::X86::BI__builtin_ia32_crc32si:
5242 return interp__builtin_ia32_crc32(S, OpPC, Frame, Call, 4);
5243 case clang::X86::BI__builtin_ia32_crc32di:
5244 return interp__builtin_ia32_crc32(S, OpPC, Frame, Call, 8);
5245
5246 case clang::X86::BI__builtin_ia32_bextr_u32:
5247 case clang::X86::BI__builtin_ia32_bextr_u64:
5248 case clang::X86::BI__builtin_ia32_bextri_u32:
5249 case clang::X86::BI__builtin_ia32_bextri_u64:
5251 S, OpPC, Call, [](const APSInt &Val, const APSInt &Idx) {
5252 unsigned BitWidth = Val.getBitWidth();
5253 uint64_t Shift = Idx.extractBitsAsZExtValue(8, 0);
5254 uint64_t Length = Idx.extractBitsAsZExtValue(8, 8);
5255 if (Length > BitWidth) {
5256 Length = BitWidth;
5257 }
5258
5259 // Handle out of bounds cases.
5260 if (Length == 0 || Shift >= BitWidth)
5261 return APInt(BitWidth, 0);
5262
5263 uint64_t Result = Val.getZExtValue() >> Shift;
5264 Result &= llvm::maskTrailingOnes<uint64_t>(Length);
5265 return APInt(BitWidth, Result);
5266 });
5267
5268 case clang::X86::BI__builtin_ia32_bzhi_si:
5269 case clang::X86::BI__builtin_ia32_bzhi_di:
5271 S, OpPC, Call, [](const APSInt &Val, const APSInt &Idx) {
5272 unsigned BitWidth = Val.getBitWidth();
5273 uint64_t Index = Idx.extractBitsAsZExtValue(8, 0);
5274 APSInt Result = Val;
5275
5276 if (Index < BitWidth)
5277 Result.clearHighBits(BitWidth - Index);
5278
5279 return Result;
5280 });
5281
5282 case clang::X86::BI__builtin_ia32_ktestcqi:
5283 case clang::X86::BI__builtin_ia32_ktestchi:
5284 case clang::X86::BI__builtin_ia32_ktestcsi:
5285 case clang::X86::BI__builtin_ia32_ktestcdi:
5287 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
5288 return APInt(sizeof(unsigned char) * 8, (~A & B) == 0);
5289 });
5290
5291 case clang::X86::BI__builtin_ia32_ktestzqi:
5292 case clang::X86::BI__builtin_ia32_ktestzhi:
5293 case clang::X86::BI__builtin_ia32_ktestzsi:
5294 case clang::X86::BI__builtin_ia32_ktestzdi:
5296 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
5297 return APInt(sizeof(unsigned char) * 8, (A & B) == 0);
5298 });
5299
5300 case clang::X86::BI__builtin_ia32_kortestcqi:
5301 case clang::X86::BI__builtin_ia32_kortestchi:
5302 case clang::X86::BI__builtin_ia32_kortestcsi:
5303 case clang::X86::BI__builtin_ia32_kortestcdi:
5305 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
5306 return APInt(sizeof(unsigned char) * 8, ~(A | B) == 0);
5307 });
5308
5309 case clang::X86::BI__builtin_ia32_kortestzqi:
5310 case clang::X86::BI__builtin_ia32_kortestzhi:
5311 case clang::X86::BI__builtin_ia32_kortestzsi:
5312 case clang::X86::BI__builtin_ia32_kortestzdi:
5314 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
5315 return APInt(sizeof(unsigned char) * 8, (A | B) == 0);
5316 });
5317
5318 case clang::X86::BI__builtin_ia32_kshiftliqi:
5319 case clang::X86::BI__builtin_ia32_kshiftlihi:
5320 case clang::X86::BI__builtin_ia32_kshiftlisi:
5321 case clang::X86::BI__builtin_ia32_kshiftlidi:
5323 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5324 unsigned Amt = RHS.getZExtValue() & 0xFF;
5325 if (Amt >= LHS.getBitWidth())
5326 return APInt::getZero(LHS.getBitWidth());
5327 return LHS.shl(Amt);
5328 });
5329
5330 case clang::X86::BI__builtin_ia32_kshiftriqi:
5331 case clang::X86::BI__builtin_ia32_kshiftrihi:
5332 case clang::X86::BI__builtin_ia32_kshiftrisi:
5333 case clang::X86::BI__builtin_ia32_kshiftridi:
5335 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5336 unsigned Amt = RHS.getZExtValue() & 0xFF;
5337 if (Amt >= LHS.getBitWidth())
5338 return APInt::getZero(LHS.getBitWidth());
5339 return LHS.lshr(Amt);
5340 });
5341
5342 case clang::X86::BI__builtin_ia32_lzcnt_u16:
5343 case clang::X86::BI__builtin_ia32_lzcnt_u32:
5344 case clang::X86::BI__builtin_ia32_lzcnt_u64:
5346 S, OpPC, Call, [](const APSInt &Src) {
5347 return APInt(Src.getBitWidth(), Src.countLeadingZeros());
5348 });
5349
5350 case clang::X86::BI__builtin_ia32_tzcnt_u16:
5351 case clang::X86::BI__builtin_ia32_tzcnt_u32:
5352 case clang::X86::BI__builtin_ia32_tzcnt_u64:
5354 S, OpPC, Call, [](const APSInt &Src) {
5355 return APInt(Src.getBitWidth(), Src.countTrailingZeros());
5356 });
5357
5358 case clang::X86::BI__builtin_ia32_pdep_si:
5359 case clang::X86::BI__builtin_ia32_pdep_di:
5360 case Builtin::BI__builtin_elementwise_pdep:
5362 llvm::APIntOps::pdep);
5363
5364 case clang::X86::BI__builtin_ia32_pext_si:
5365 case clang::X86::BI__builtin_ia32_pext_di:
5366 case Builtin::BI__builtin_elementwise_pext:
5368 llvm::APIntOps::pext);
5369
5370 case clang::X86::BI__builtin_ia32_addcarryx_u32:
5371 case clang::X86::BI__builtin_ia32_addcarryx_u64:
5373 /*IsAdd=*/true);
5374
5375 case clang::X86::BI__builtin_ia32_subborrow_u32:
5376 case clang::X86::BI__builtin_ia32_subborrow_u64:
5378 /*IsAdd=*/false);
5379
5380 case Builtin::BI__builtin_os_log_format_buffer_size:
5382
5383 case Builtin::BI__builtin_ptrauth_string_discriminator:
5385
5386 case Builtin::BI__builtin_infer_alloc_token:
5388
5389 case Builtin::BI__noop:
5390 pushInteger(S, 0, Call->getType());
5391 return true;
5392
5393 case Builtin::BI__builtin_operator_new:
5394 return interp__builtin_operator_new(S, OpPC, Frame, Call);
5395
5396 case Builtin::BI__builtin_operator_delete:
5397 return interp__builtin_operator_delete(S, OpPC, Frame, Call);
5398
5399 case Builtin::BI__arithmetic_fence:
5401
5402 case Builtin::BI__builtin_reduce_add:
5403 case Builtin::BI__builtin_reduce_mul:
5404 case Builtin::BI__builtin_reduce_and:
5405 case Builtin::BI__builtin_reduce_or:
5406 case Builtin::BI__builtin_reduce_xor:
5407 case Builtin::BI__builtin_reduce_min:
5408 case Builtin::BI__builtin_reduce_max:
5409 return interp__builtin_vector_reduce(S, OpPC, Call, BuiltinID);
5410
5411 case Builtin::BI__builtin_elementwise_popcount:
5413 S, OpPC, Call, [](const APSInt &Src) {
5414 return APInt(Src.getBitWidth(), Src.popcount());
5415 });
5416 case Builtin::BI__builtin_elementwise_bitreverse:
5418 S, OpPC, Call, [](const APSInt &Src) { return Src.reverseBits(); });
5419
5420 case Builtin::BI__builtin_elementwise_abs:
5421 return interp__builtin_elementwise_abs(S, OpPC, Frame, Call, BuiltinID);
5422
5423 case Builtin::BI__builtin_memcpy:
5424 case Builtin::BImemcpy:
5425 case Builtin::BI__builtin_wmemcpy:
5426 case Builtin::BIwmemcpy:
5427 case Builtin::BI__builtin_memmove:
5428 case Builtin::BImemmove:
5429 case Builtin::BI__builtin_wmemmove:
5430 case Builtin::BIwmemmove:
5431 return interp__builtin_memcpy(S, OpPC, Frame, Call, BuiltinID);
5432
5433 case Builtin::BI__builtin_memcmp:
5434 case Builtin::BImemcmp:
5435 case Builtin::BI__builtin_bcmp:
5436 case Builtin::BIbcmp:
5437 case Builtin::BI__builtin_wmemcmp:
5438 case Builtin::BIwmemcmp:
5439 return interp__builtin_memcmp(S, OpPC, Frame, Call, BuiltinID);
5440
5441 case Builtin::BImemchr:
5442 case Builtin::BI__builtin_memchr:
5443 case Builtin::BIstrchr:
5444 case Builtin::BI__builtin_strchr:
5445 case Builtin::BIwmemchr:
5446 case Builtin::BI__builtin_wmemchr:
5447 case Builtin::BIwcschr:
5448 case Builtin::BI__builtin_wcschr:
5449 case Builtin::BI__builtin_char_memchr:
5450 return interp__builtin_memchr(S, OpPC, Call, BuiltinID);
5451
5452 case Builtin::BI__builtin_object_size:
5453 case Builtin::BI__builtin_dynamic_object_size:
5454 return interp__builtin_object_size(S, OpPC, Frame, Call);
5455
5456 case Builtin::BI__builtin_is_within_lifetime:
5458
5459 case Builtin::BI__builtin_elementwise_add_sat:
5461 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5462 return LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS);
5463 });
5464
5465 case Builtin::BI__builtin_elementwise_sub_sat:
5467 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5468 return LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS);
5469 });
5470 case X86::BI__builtin_ia32_extract128i256:
5471 case X86::BI__builtin_ia32_vextractf128_pd256:
5472 case X86::BI__builtin_ia32_vextractf128_ps256:
5473 case X86::BI__builtin_ia32_vextractf128_si256:
5474 return interp__builtin_ia32_extract_vector(S, OpPC, Call, BuiltinID);
5475
5476 case X86::BI__builtin_ia32_extractf32x4_256_mask:
5477 case X86::BI__builtin_ia32_extractf32x4_mask:
5478 case X86::BI__builtin_ia32_extractf32x8_mask:
5479 case X86::BI__builtin_ia32_extractf64x2_256_mask:
5480 case X86::BI__builtin_ia32_extractf64x2_512_mask:
5481 case X86::BI__builtin_ia32_extractf64x4_mask:
5482 case X86::BI__builtin_ia32_extracti32x4_256_mask:
5483 case X86::BI__builtin_ia32_extracti32x4_mask:
5484 case X86::BI__builtin_ia32_extracti32x8_mask:
5485 case X86::BI__builtin_ia32_extracti64x2_256_mask:
5486 case X86::BI__builtin_ia32_extracti64x2_512_mask:
5487 case X86::BI__builtin_ia32_extracti64x4_mask:
5488 return interp__builtin_ia32_extract_vector_masked(S, OpPC, Call, BuiltinID);
5489
5490 case clang::X86::BI__builtin_ia32_pmulhrsw128:
5491 case clang::X86::BI__builtin_ia32_pmulhrsw256:
5492 case clang::X86::BI__builtin_ia32_pmulhrsw512:
5494 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5495 return (llvm::APIntOps::mulsExtended(LHS, RHS).ashr(14) + 1)
5496 .extractBits(16, 1);
5497 });
5498
5499 case clang::X86::BI__builtin_ia32_movmskps:
5500 case clang::X86::BI__builtin_ia32_movmskpd:
5501 case clang::X86::BI__builtin_ia32_pmovmskb128:
5502 case clang::X86::BI__builtin_ia32_pmovmskb256:
5503 case clang::X86::BI__builtin_ia32_movmskps256:
5504 case clang::X86::BI__builtin_ia32_movmskpd256: {
5505 return interp__builtin_ia32_movmsk_op(S, OpPC, Call);
5506 }
5507
5508 case X86::BI__builtin_ia32_psignb128:
5509 case X86::BI__builtin_ia32_psignb256:
5510 case X86::BI__builtin_ia32_psignw128:
5511 case X86::BI__builtin_ia32_psignw256:
5512 case X86::BI__builtin_ia32_psignd128:
5513 case X86::BI__builtin_ia32_psignd256:
5515 S, OpPC, Call, [](const APInt &AElem, const APInt &BElem) {
5516 if (BElem.isZero())
5517 return APInt::getZero(AElem.getBitWidth());
5518 if (BElem.isNegative())
5519 return -AElem;
5520 return AElem;
5521 });
5522
5523 case clang::X86::BI__builtin_ia32_pavgb128:
5524 case clang::X86::BI__builtin_ia32_pavgw128:
5525 case clang::X86::BI__builtin_ia32_pavgb256:
5526 case clang::X86::BI__builtin_ia32_pavgw256:
5527 case clang::X86::BI__builtin_ia32_pavgb512:
5528 case clang::X86::BI__builtin_ia32_pavgw512:
5530 llvm::APIntOps::avgCeilU);
5531
5532 case clang::X86::BI__builtin_ia32_pmaddubsw128:
5533 case clang::X86::BI__builtin_ia32_pmaddubsw256:
5534 case clang::X86::BI__builtin_ia32_pmaddubsw512:
5536 S, OpPC, Call,
5537 [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,
5538 const APSInt &HiRHS) {
5539 unsigned BitWidth = 2 * LoLHS.getBitWidth();
5540 return (LoLHS.zext(BitWidth) * LoRHS.sext(BitWidth))
5541 .sadd_sat((HiLHS.zext(BitWidth) * HiRHS.sext(BitWidth)));
5542 });
5543
5544 case clang::X86::BI__builtin_ia32_pmaddwd128:
5545 case clang::X86::BI__builtin_ia32_pmaddwd256:
5546 case clang::X86::BI__builtin_ia32_pmaddwd512:
5548 S, OpPC, Call,
5549 [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,
5550 const APSInt &HiRHS) {
5551 unsigned BitWidth = 2 * LoLHS.getBitWidth();
5552 return (LoLHS.sext(BitWidth) * LoRHS.sext(BitWidth)) +
5553 (HiLHS.sext(BitWidth) * HiRHS.sext(BitWidth));
5554 });
5555
5556 case clang::X86::BI__builtin_ia32_psadbw128:
5557 case clang::X86::BI__builtin_ia32_psadbw256:
5558 case clang::X86::BI__builtin_ia32_psadbw512:
5559 return interp__builtin_ia32_psadbw(S, OpPC, Call);
5560
5561 case clang::X86::BI__builtin_ia32_dbpsadbw128:
5562 case clang::X86::BI__builtin_ia32_dbpsadbw256:
5563 case clang::X86::BI__builtin_ia32_dbpsadbw512:
5564 return interp__builtin_ia32_dbpsadbw(S, OpPC, Call);
5565
5566 case clang::X86::BI__builtin_ia32_mpsadbw128:
5567 case clang::X86::BI__builtin_ia32_mpsadbw256:
5568 return interp__builtin_ia32_mpsadbw(S, OpPC, Call);
5569
5570 case clang::X86::BI__builtin_ia32_pmulhuw128:
5571 case clang::X86::BI__builtin_ia32_pmulhuw256:
5572 case clang::X86::BI__builtin_ia32_pmulhuw512:
5574 llvm::APIntOps::mulhu);
5575
5576 case clang::X86::BI__builtin_ia32_pmulhw128:
5577 case clang::X86::BI__builtin_ia32_pmulhw256:
5578 case clang::X86::BI__builtin_ia32_pmulhw512:
5580 llvm::APIntOps::mulhs);
5581
5582 case clang::X86::BI__builtin_ia32_psllv2di:
5583 case clang::X86::BI__builtin_ia32_psllv4di:
5584 case clang::X86::BI__builtin_ia32_psllv4si:
5585 case clang::X86::BI__builtin_ia32_psllv8di:
5586 case clang::X86::BI__builtin_ia32_psllv8hi:
5587 case clang::X86::BI__builtin_ia32_psllv8si:
5588 case clang::X86::BI__builtin_ia32_psllv16hi:
5589 case clang::X86::BI__builtin_ia32_psllv16si:
5590 case clang::X86::BI__builtin_ia32_psllv32hi:
5591 case clang::X86::BI__builtin_ia32_psllwi128:
5592 case clang::X86::BI__builtin_ia32_psllwi256:
5593 case clang::X86::BI__builtin_ia32_psllwi512:
5594 case clang::X86::BI__builtin_ia32_pslldi128:
5595 case clang::X86::BI__builtin_ia32_pslldi256:
5596 case clang::X86::BI__builtin_ia32_pslldi512:
5597 case clang::X86::BI__builtin_ia32_psllqi128:
5598 case clang::X86::BI__builtin_ia32_psllqi256:
5599 case clang::X86::BI__builtin_ia32_psllqi512:
5601 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5602 if (RHS.uge(LHS.getBitWidth())) {
5603 return APInt::getZero(LHS.getBitWidth());
5604 }
5605 return LHS.shl(RHS.getZExtValue());
5606 });
5607
5608 case clang::X86::BI__builtin_ia32_psrav4si:
5609 case clang::X86::BI__builtin_ia32_psrav8di:
5610 case clang::X86::BI__builtin_ia32_psrav8hi:
5611 case clang::X86::BI__builtin_ia32_psrav8si:
5612 case clang::X86::BI__builtin_ia32_psrav16hi:
5613 case clang::X86::BI__builtin_ia32_psrav16si:
5614 case clang::X86::BI__builtin_ia32_psrav32hi:
5615 case clang::X86::BI__builtin_ia32_psravq128:
5616 case clang::X86::BI__builtin_ia32_psravq256:
5617 case clang::X86::BI__builtin_ia32_psrawi128:
5618 case clang::X86::BI__builtin_ia32_psrawi256:
5619 case clang::X86::BI__builtin_ia32_psrawi512:
5620 case clang::X86::BI__builtin_ia32_psradi128:
5621 case clang::X86::BI__builtin_ia32_psradi256:
5622 case clang::X86::BI__builtin_ia32_psradi512:
5623 case clang::X86::BI__builtin_ia32_psraqi128:
5624 case clang::X86::BI__builtin_ia32_psraqi256:
5625 case clang::X86::BI__builtin_ia32_psraqi512:
5627 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5628 if (RHS.uge(LHS.getBitWidth())) {
5629 return LHS.ashr(LHS.getBitWidth() - 1);
5630 }
5631 return LHS.ashr(RHS.getZExtValue());
5632 });
5633
5634 case clang::X86::BI__builtin_ia32_psrlv2di:
5635 case clang::X86::BI__builtin_ia32_psrlv4di:
5636 case clang::X86::BI__builtin_ia32_psrlv4si:
5637 case clang::X86::BI__builtin_ia32_psrlv8di:
5638 case clang::X86::BI__builtin_ia32_psrlv8hi:
5639 case clang::X86::BI__builtin_ia32_psrlv8si:
5640 case clang::X86::BI__builtin_ia32_psrlv16hi:
5641 case clang::X86::BI__builtin_ia32_psrlv16si:
5642 case clang::X86::BI__builtin_ia32_psrlv32hi:
5643 case clang::X86::BI__builtin_ia32_psrlwi128:
5644 case clang::X86::BI__builtin_ia32_psrlwi256:
5645 case clang::X86::BI__builtin_ia32_psrlwi512:
5646 case clang::X86::BI__builtin_ia32_psrldi128:
5647 case clang::X86::BI__builtin_ia32_psrldi256:
5648 case clang::X86::BI__builtin_ia32_psrldi512:
5649 case clang::X86::BI__builtin_ia32_psrlqi128:
5650 case clang::X86::BI__builtin_ia32_psrlqi256:
5651 case clang::X86::BI__builtin_ia32_psrlqi512:
5653 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
5654 if (RHS.uge(LHS.getBitWidth())) {
5655 return APInt::getZero(LHS.getBitWidth());
5656 }
5657 return LHS.lshr(RHS.getZExtValue());
5658 });
5659 case clang::X86::BI__builtin_ia32_packsswb128:
5660 case clang::X86::BI__builtin_ia32_packsswb256:
5661 case clang::X86::BI__builtin_ia32_packsswb512:
5662 case clang::X86::BI__builtin_ia32_packssdw128:
5663 case clang::X86::BI__builtin_ia32_packssdw256:
5664 case clang::X86::BI__builtin_ia32_packssdw512:
5665 return interp__builtin_ia32_pack(S, OpPC, Call, [](const APSInt &Src) {
5666 return APInt(Src).truncSSat(Src.getBitWidth() / 2);
5667 });
5668 case clang::X86::BI__builtin_ia32_packusdw128:
5669 case clang::X86::BI__builtin_ia32_packusdw256:
5670 case clang::X86::BI__builtin_ia32_packusdw512:
5671 case clang::X86::BI__builtin_ia32_packuswb128:
5672 case clang::X86::BI__builtin_ia32_packuswb256:
5673 case clang::X86::BI__builtin_ia32_packuswb512:
5674 return interp__builtin_ia32_pack(S, OpPC, Call, [](const APSInt &Src) {
5675 return APInt(Src).truncSSatU(Src.getBitWidth() / 2);
5676 });
5677
5678 case clang::X86::BI__builtin_ia32_selectss_128:
5679 case clang::X86::BI__builtin_ia32_selectsd_128:
5680 case clang::X86::BI__builtin_ia32_selectsh_128:
5681 case clang::X86::BI__builtin_ia32_selectsbf_128:
5683 case clang::X86::BI__builtin_ia32_vprotbi:
5684 case clang::X86::BI__builtin_ia32_vprotdi:
5685 case clang::X86::BI__builtin_ia32_vprotqi:
5686 case clang::X86::BI__builtin_ia32_vprotwi:
5687 case clang::X86::BI__builtin_ia32_prold128:
5688 case clang::X86::BI__builtin_ia32_prold256:
5689 case clang::X86::BI__builtin_ia32_prold512:
5690 case clang::X86::BI__builtin_ia32_prolq128:
5691 case clang::X86::BI__builtin_ia32_prolq256:
5692 case clang::X86::BI__builtin_ia32_prolq512:
5694 S, OpPC, Call,
5695 [](const APSInt &LHS, const APSInt &RHS) { return LHS.rotl(RHS); });
5696
5697 case clang::X86::BI__builtin_ia32_prord128:
5698 case clang::X86::BI__builtin_ia32_prord256:
5699 case clang::X86::BI__builtin_ia32_prord512:
5700 case clang::X86::BI__builtin_ia32_prorq128:
5701 case clang::X86::BI__builtin_ia32_prorq256:
5702 case clang::X86::BI__builtin_ia32_prorq512:
5704 S, OpPC, Call,
5705 [](const APSInt &LHS, const APSInt &RHS) { return LHS.rotr(RHS); });
5706
5707 case Builtin::BI__builtin_elementwise_max:
5708 case Builtin::BI__builtin_elementwise_min:
5709 return interp__builtin_elementwise_maxmin(S, OpPC, Call, BuiltinID);
5710
5711 case clang::X86::BI__builtin_ia32_phaddw128:
5712 case clang::X86::BI__builtin_ia32_phaddw256:
5713 case clang::X86::BI__builtin_ia32_phaddd128:
5714 case clang::X86::BI__builtin_ia32_phaddd256:
5716 S, OpPC, Call,
5717 [](const APSInt &LHS, const APSInt &RHS) { return LHS + RHS; });
5718 case clang::X86::BI__builtin_ia32_phaddsw128:
5719 case clang::X86::BI__builtin_ia32_phaddsw256:
5721 S, OpPC, Call,
5722 [](const APSInt &LHS, const APSInt &RHS) { return LHS.sadd_sat(RHS); });
5723 case clang::X86::BI__builtin_ia32_phsubw128:
5724 case clang::X86::BI__builtin_ia32_phsubw256:
5725 case clang::X86::BI__builtin_ia32_phsubd128:
5726 case clang::X86::BI__builtin_ia32_phsubd256:
5728 S, OpPC, Call,
5729 [](const APSInt &LHS, const APSInt &RHS) { return LHS - RHS; });
5730 case clang::X86::BI__builtin_ia32_phsubsw128:
5731 case clang::X86::BI__builtin_ia32_phsubsw256:
5733 S, OpPC, Call,
5734 [](const APSInt &LHS, const APSInt &RHS) { return LHS.ssub_sat(RHS); });
5735 case clang::X86::BI__builtin_ia32_haddpd:
5736 case clang::X86::BI__builtin_ia32_haddps:
5737 case clang::X86::BI__builtin_ia32_haddpd256:
5738 case clang::X86::BI__builtin_ia32_haddps256:
5740 S, OpPC, Call,
5741 [](const APFloat &LHS, const APFloat &RHS, llvm::RoundingMode RM) {
5742 APFloat F = LHS;
5743 F.add(RHS, RM);
5744 return F;
5745 });
5746 case clang::X86::BI__builtin_ia32_hsubpd:
5747 case clang::X86::BI__builtin_ia32_hsubps:
5748 case clang::X86::BI__builtin_ia32_hsubpd256:
5749 case clang::X86::BI__builtin_ia32_hsubps256:
5751 S, OpPC, Call,
5752 [](const APFloat &LHS, const APFloat &RHS, llvm::RoundingMode RM) {
5753 APFloat F = LHS;
5754 F.subtract(RHS, RM);
5755 return F;
5756 });
5757 case clang::X86::BI__builtin_ia32_addsubpd:
5758 case clang::X86::BI__builtin_ia32_addsubps:
5759 case clang::X86::BI__builtin_ia32_addsubpd256:
5760 case clang::X86::BI__builtin_ia32_addsubps256:
5761 return interp__builtin_ia32_addsub(S, OpPC, Call);
5762
5763 case clang::X86::BI__builtin_ia32_pmuldq128:
5764 case clang::X86::BI__builtin_ia32_pmuldq256:
5765 case clang::X86::BI__builtin_ia32_pmuldq512:
5767 S, OpPC, Call,
5768 [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,
5769 const APSInt &HiRHS) {
5770 return llvm::APIntOps::mulsExtended(LoLHS, LoRHS);
5771 });
5772
5773 case clang::X86::BI__builtin_ia32_pmuludq128:
5774 case clang::X86::BI__builtin_ia32_pmuludq256:
5775 case clang::X86::BI__builtin_ia32_pmuludq512:
5777 S, OpPC, Call,
5778 [](const APSInt &LoLHS, const APSInt &HiLHS, const APSInt &LoRHS,
5779 const APSInt &HiRHS) {
5780 return llvm::APIntOps::muluExtended(LoLHS, LoRHS);
5781 });
5782
5783 case clang::X86::BI__builtin_ia32_pclmulqdq128:
5784 case clang::X86::BI__builtin_ia32_pclmulqdq256:
5785 case clang::X86::BI__builtin_ia32_pclmulqdq512:
5786 return interp__builtin_ia32_pclmulqdq(S, OpPC, Call);
5787 case Builtin::BI__builtin_elementwise_clmul:
5789 llvm::APIntOps::clmul);
5790
5791 case Builtin::BI__builtin_elementwise_fma:
5793 S, OpPC, Call,
5794 [](const APFloat &X, const APFloat &Y, const APFloat &Z,
5795 llvm::RoundingMode RM) {
5796 APFloat F = X;
5797 F.fusedMultiplyAdd(Y, Z, RM);
5798 return F;
5799 });
5800
5801 case X86::BI__builtin_ia32_vpmadd52luq128:
5802 case X86::BI__builtin_ia32_vpmadd52luq256:
5803 case X86::BI__builtin_ia32_vpmadd52luq512:
5805 S, OpPC, Call, [](const APSInt &A, const APSInt &B, const APSInt &C) {
5806 return A + (B.trunc(52) * C.trunc(52)).zext(64);
5807 });
5808 case X86::BI__builtin_ia32_vpmadd52huq128:
5809 case X86::BI__builtin_ia32_vpmadd52huq256:
5810 case X86::BI__builtin_ia32_vpmadd52huq512:
5812 S, OpPC, Call, [](const APSInt &A, const APSInt &B, const APSInt &C) {
5813 return A + llvm::APIntOps::mulhu(B.trunc(52), C.trunc(52)).zext(64);
5814 });
5815
5816 case X86::BI__builtin_ia32_vpshldd128:
5817 case X86::BI__builtin_ia32_vpshldd256:
5818 case X86::BI__builtin_ia32_vpshldd512:
5819 case X86::BI__builtin_ia32_vpshldq128:
5820 case X86::BI__builtin_ia32_vpshldq256:
5821 case X86::BI__builtin_ia32_vpshldq512:
5822 case X86::BI__builtin_ia32_vpshldw128:
5823 case X86::BI__builtin_ia32_vpshldw256:
5824 case X86::BI__builtin_ia32_vpshldw512:
5826 S, OpPC, Call,
5827 [](const APSInt &Hi, const APSInt &Lo, const APSInt &Amt) {
5828 return llvm::APIntOps::fshl(Hi, Lo, Amt);
5829 });
5830
5831 case X86::BI__builtin_ia32_vpshrdd128:
5832 case X86::BI__builtin_ia32_vpshrdd256:
5833 case X86::BI__builtin_ia32_vpshrdd512:
5834 case X86::BI__builtin_ia32_vpshrdq128:
5835 case X86::BI__builtin_ia32_vpshrdq256:
5836 case X86::BI__builtin_ia32_vpshrdq512:
5837 case X86::BI__builtin_ia32_vpshrdw128:
5838 case X86::BI__builtin_ia32_vpshrdw256:
5839 case X86::BI__builtin_ia32_vpshrdw512:
5840 // NOTE: Reversed Hi/Lo operands.
5842 S, OpPC, Call,
5843 [](const APSInt &Lo, const APSInt &Hi, const APSInt &Amt) {
5844 return llvm::APIntOps::fshr(Hi, Lo, Amt);
5845 });
5846 case X86::BI__builtin_ia32_vpconflictsi_128:
5847 case X86::BI__builtin_ia32_vpconflictsi_256:
5848 case X86::BI__builtin_ia32_vpconflictsi_512:
5849 case X86::BI__builtin_ia32_vpconflictdi_128:
5850 case X86::BI__builtin_ia32_vpconflictdi_256:
5851 case X86::BI__builtin_ia32_vpconflictdi_512:
5852 return interp__builtin_ia32_vpconflict(S, OpPC, Call);
5853 case X86::BI__builtin_ia32_compressdf128_mask:
5854 case X86::BI__builtin_ia32_compressdf256_mask:
5855 case X86::BI__builtin_ia32_compressdf512_mask:
5856 case X86::BI__builtin_ia32_compressdi128_mask:
5857 case X86::BI__builtin_ia32_compressdi256_mask:
5858 case X86::BI__builtin_ia32_compressdi512_mask:
5859 case X86::BI__builtin_ia32_compresshi128_mask:
5860 case X86::BI__builtin_ia32_compresshi256_mask:
5861 case X86::BI__builtin_ia32_compresshi512_mask:
5862 case X86::BI__builtin_ia32_compressqi128_mask:
5863 case X86::BI__builtin_ia32_compressqi256_mask:
5864 case X86::BI__builtin_ia32_compressqi512_mask:
5865 case X86::BI__builtin_ia32_compresssf128_mask:
5866 case X86::BI__builtin_ia32_compresssf256_mask:
5867 case X86::BI__builtin_ia32_compresssf512_mask:
5868 case X86::BI__builtin_ia32_compresssi128_mask:
5869 case X86::BI__builtin_ia32_compresssi256_mask:
5870 case X86::BI__builtin_ia32_compresssi512_mask: {
5871 unsigned NumElems =
5872 Call->getArg(0)->getType()->castAs<VectorType>()->getNumElements();
5874 S, OpPC, Call, [NumElems](unsigned DstIdx, const APInt &ShuffleMask) {
5875 APInt CompressMask = ShuffleMask.trunc(NumElems);
5876 if (DstIdx < CompressMask.popcount()) {
5877 while (DstIdx != 0) {
5878 CompressMask = CompressMask & (CompressMask - 1);
5879 DstIdx--;
5880 }
5881 return std::pair<unsigned, int>{
5882 0, static_cast<int>(CompressMask.countr_zero())};
5883 }
5884 return std::pair<unsigned, int>{1, static_cast<int>(DstIdx)};
5885 });
5886 }
5887 case X86::BI__builtin_ia32_expanddf128_mask:
5888 case X86::BI__builtin_ia32_expanddf256_mask:
5889 case X86::BI__builtin_ia32_expanddf512_mask:
5890 case X86::BI__builtin_ia32_expanddi128_mask:
5891 case X86::BI__builtin_ia32_expanddi256_mask:
5892 case X86::BI__builtin_ia32_expanddi512_mask:
5893 case X86::BI__builtin_ia32_expandhi128_mask:
5894 case X86::BI__builtin_ia32_expandhi256_mask:
5895 case X86::BI__builtin_ia32_expandhi512_mask:
5896 case X86::BI__builtin_ia32_expandqi128_mask:
5897 case X86::BI__builtin_ia32_expandqi256_mask:
5898 case X86::BI__builtin_ia32_expandqi512_mask:
5899 case X86::BI__builtin_ia32_expandsf128_mask:
5900 case X86::BI__builtin_ia32_expandsf256_mask:
5901 case X86::BI__builtin_ia32_expandsf512_mask:
5902 case X86::BI__builtin_ia32_expandsi128_mask:
5903 case X86::BI__builtin_ia32_expandsi256_mask:
5904 case X86::BI__builtin_ia32_expandsi512_mask: {
5906 S, OpPC, Call, [](unsigned DstIdx, const APInt &ShuffleMask) {
5907 // Trunc to the sub-mask for the dst index and count the number of
5908 // src elements used prior to that.
5909 APInt ExpandMask = ShuffleMask.trunc(DstIdx + 1);
5910 if (ExpandMask[DstIdx]) {
5911 int SrcIdx = ExpandMask.popcount() - 1;
5912 return std::pair<unsigned, int>{0, SrcIdx};
5913 }
5914 return std::pair<unsigned, int>{1, static_cast<int>(DstIdx)};
5915 });
5916 }
5917 case clang::X86::BI__builtin_ia32_blendpd:
5918 case clang::X86::BI__builtin_ia32_blendpd256:
5919 case clang::X86::BI__builtin_ia32_blendps:
5920 case clang::X86::BI__builtin_ia32_blendps256:
5921 case clang::X86::BI__builtin_ia32_pblendw128:
5922 case clang::X86::BI__builtin_ia32_pblendw256:
5923 case clang::X86::BI__builtin_ia32_pblendd128:
5924 case clang::X86::BI__builtin_ia32_pblendd256:
5926 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
5927 // Bit index for mask.
5928 unsigned MaskBit = (ShuffleMask >> (DstIdx % 8)) & 0x1;
5929 unsigned SrcVecIdx = MaskBit ? 1 : 0; // 1 = TrueVec, 0 = FalseVec
5930 return std::pair<unsigned, int>{SrcVecIdx, static_cast<int>(DstIdx)};
5931 });
5932
5933
5934
5935 case clang::X86::BI__builtin_ia32_blendvpd:
5936 case clang::X86::BI__builtin_ia32_blendvpd256:
5937 case clang::X86::BI__builtin_ia32_blendvps:
5938 case clang::X86::BI__builtin_ia32_blendvps256:
5940 S, OpPC, Call,
5941 [](const APFloat &F, const APFloat &T, const APFloat &C,
5942 llvm::RoundingMode) { return C.isNegative() ? T : F; });
5943
5944 case clang::X86::BI__builtin_ia32_pblendvb128:
5945 case clang::X86::BI__builtin_ia32_pblendvb256:
5947 S, OpPC, Call, [](const APSInt &F, const APSInt &T, const APSInt &C) {
5948 return ((APInt)C).isNegative() ? T : F;
5949 });
5950 case X86::BI__builtin_ia32_ptestz128:
5951 case X86::BI__builtin_ia32_ptestz256:
5952 case X86::BI__builtin_ia32_vtestzps:
5953 case X86::BI__builtin_ia32_vtestzps256:
5954 case X86::BI__builtin_ia32_vtestzpd:
5955 case X86::BI__builtin_ia32_vtestzpd256:
5957 S, OpPC, Call,
5958 [](const APInt &A, const APInt &B) { return (A & B) == 0; });
5959 case X86::BI__builtin_ia32_ptestc128:
5960 case X86::BI__builtin_ia32_ptestc256:
5961 case X86::BI__builtin_ia32_vtestcps:
5962 case X86::BI__builtin_ia32_vtestcps256:
5963 case X86::BI__builtin_ia32_vtestcpd:
5964 case X86::BI__builtin_ia32_vtestcpd256:
5966 S, OpPC, Call,
5967 [](const APInt &A, const APInt &B) { return (~A & B) == 0; });
5968 case X86::BI__builtin_ia32_ptestnzc128:
5969 case X86::BI__builtin_ia32_ptestnzc256:
5970 case X86::BI__builtin_ia32_vtestnzcps:
5971 case X86::BI__builtin_ia32_vtestnzcps256:
5972 case X86::BI__builtin_ia32_vtestnzcpd:
5973 case X86::BI__builtin_ia32_vtestnzcpd256:
5975 S, OpPC, Call, [](const APInt &A, const APInt &B) {
5976 return ((A & B) != 0) && ((~A & B) != 0);
5977 });
5978 case X86::BI__builtin_ia32_selectb_128:
5979 case X86::BI__builtin_ia32_selectb_256:
5980 case X86::BI__builtin_ia32_selectb_512:
5981 case X86::BI__builtin_ia32_selectw_128:
5982 case X86::BI__builtin_ia32_selectw_256:
5983 case X86::BI__builtin_ia32_selectw_512:
5984 case X86::BI__builtin_ia32_selectd_128:
5985 case X86::BI__builtin_ia32_selectd_256:
5986 case X86::BI__builtin_ia32_selectd_512:
5987 case X86::BI__builtin_ia32_selectq_128:
5988 case X86::BI__builtin_ia32_selectq_256:
5989 case X86::BI__builtin_ia32_selectq_512:
5990 case X86::BI__builtin_ia32_selectph_128:
5991 case X86::BI__builtin_ia32_selectph_256:
5992 case X86::BI__builtin_ia32_selectph_512:
5993 case X86::BI__builtin_ia32_selectpbf_128:
5994 case X86::BI__builtin_ia32_selectpbf_256:
5995 case X86::BI__builtin_ia32_selectpbf_512:
5996 case X86::BI__builtin_ia32_selectps_128:
5997 case X86::BI__builtin_ia32_selectps_256:
5998 case X86::BI__builtin_ia32_selectps_512:
5999 case X86::BI__builtin_ia32_selectpd_128:
6000 case X86::BI__builtin_ia32_selectpd_256:
6001 case X86::BI__builtin_ia32_selectpd_512:
6002 return interp__builtin_ia32_select(S, OpPC, Call);
6003
6004 case X86::BI__builtin_ia32_shufps:
6005 case X86::BI__builtin_ia32_shufps256:
6006 case X86::BI__builtin_ia32_shufps512:
6008 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6009 unsigned NumElemPerLane = 4;
6010 unsigned NumSelectableElems = NumElemPerLane / 2;
6011 unsigned BitsPerElem = 2;
6012 unsigned IndexMask = 0x3;
6013 unsigned MaskBits = 8;
6014 unsigned Lane = DstIdx / NumElemPerLane;
6015 unsigned ElemInLane = DstIdx % NumElemPerLane;
6016 unsigned LaneOffset = Lane * NumElemPerLane;
6017 unsigned SrcIdx = ElemInLane >= NumSelectableElems ? 1 : 0;
6018 unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;
6019 unsigned Index = (ShuffleMask >> BitIndex) & IndexMask;
6020 return std::pair<unsigned, int>{SrcIdx,
6021 static_cast<int>(LaneOffset + Index)};
6022 });
6023 case X86::BI__builtin_ia32_shufpd:
6024 case X86::BI__builtin_ia32_shufpd256:
6025 case X86::BI__builtin_ia32_shufpd512:
6027 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6028 unsigned NumElemPerLane = 2;
6029 unsigned NumSelectableElems = NumElemPerLane / 2;
6030 unsigned BitsPerElem = 1;
6031 unsigned IndexMask = 0x1;
6032 unsigned MaskBits = 8;
6033 unsigned Lane = DstIdx / NumElemPerLane;
6034 unsigned ElemInLane = DstIdx % NumElemPerLane;
6035 unsigned LaneOffset = Lane * NumElemPerLane;
6036 unsigned SrcIdx = ElemInLane >= NumSelectableElems ? 1 : 0;
6037 unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;
6038 unsigned Index = (ShuffleMask >> BitIndex) & IndexMask;
6039 return std::pair<unsigned, int>{SrcIdx,
6040 static_cast<int>(LaneOffset + Index)};
6041 });
6042
6043 case X86::BI__builtin_ia32_vgf2p8affineinvqb_v16qi:
6044 case X86::BI__builtin_ia32_vgf2p8affineinvqb_v32qi:
6045 case X86::BI__builtin_ia32_vgf2p8affineinvqb_v64qi:
6046 return interp__builtin_ia32_gfni_affine(S, OpPC, Call, true);
6047 case X86::BI__builtin_ia32_vgf2p8affineqb_v16qi:
6048 case X86::BI__builtin_ia32_vgf2p8affineqb_v32qi:
6049 case X86::BI__builtin_ia32_vgf2p8affineqb_v64qi:
6050 return interp__builtin_ia32_gfni_affine(S, OpPC, Call, false);
6051
6052 case X86::BI__builtin_ia32_vgf2p8mulb_v16qi:
6053 case X86::BI__builtin_ia32_vgf2p8mulb_v32qi:
6054 case X86::BI__builtin_ia32_vgf2p8mulb_v64qi:
6055 return interp__builtin_ia32_gfni_mul(S, OpPC, Call);
6056
6057 case X86::BI__builtin_ia32_bmacor16x16x16_v16hi:
6058 case X86::BI__builtin_ia32_bmacor16x16x16_v32hi:
6059 return interp__builtin_ia32_bmac(S, OpPC, Call, /*IsXor=*/false);
6060 case X86::BI__builtin_ia32_bmacxor16x16x16_v16hi:
6061 case X86::BI__builtin_ia32_bmacxor16x16x16_v32hi:
6062 return interp__builtin_ia32_bmac(S, OpPC, Call, /*IsXor=*/true);
6063
6064 case X86::BI__builtin_ia32_insertps128:
6066 S, OpPC, Call, [](unsigned DstIdx, unsigned Mask) {
6067 // Bits [3:0]: zero mask - if bit is set, zero this element
6068 if ((Mask & (1 << DstIdx)) != 0) {
6069 return std::pair<unsigned, int>{0, -1};
6070 }
6071 // Bits [7:6]: select element from source vector Y (0-3)
6072 // Bits [5:4]: select destination position (0-3)
6073 unsigned SrcElem = (Mask >> 6) & 0x3;
6074 unsigned DstElem = (Mask >> 4) & 0x3;
6075 if (DstIdx == DstElem) {
6076 // Insert element from source vector (B) at this position
6077 return std::pair<unsigned, int>{1, static_cast<int>(SrcElem)};
6078 } else {
6079 // Copy from destination vector (A)
6080 return std::pair<unsigned, int>{0, static_cast<int>(DstIdx)};
6081 }
6082 });
6083 case X86::BI__builtin_ia32_permvarsi256:
6084 case X86::BI__builtin_ia32_permvarsf256:
6085 case X86::BI__builtin_ia32_permvardf512:
6086 case X86::BI__builtin_ia32_permvardi512:
6087 case X86::BI__builtin_ia32_permvarhi128:
6089 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6090 int Offset = ShuffleMask & 0x7;
6091 return std::pair<unsigned, int>{0, Offset};
6092 });
6093 case X86::BI__builtin_ia32_permvarqi128:
6094 case X86::BI__builtin_ia32_permvarhi256:
6095 case X86::BI__builtin_ia32_permvarsi512:
6096 case X86::BI__builtin_ia32_permvarsf512:
6098 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6099 int Offset = ShuffleMask & 0xF;
6100 return std::pair<unsigned, int>{0, Offset};
6101 });
6102 case X86::BI__builtin_ia32_permvardi256:
6103 case X86::BI__builtin_ia32_permvardf256:
6105 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6106 int Offset = ShuffleMask & 0x3;
6107 return std::pair<unsigned, int>{0, Offset};
6108 });
6109 case X86::BI__builtin_ia32_permvarqi256:
6110 case X86::BI__builtin_ia32_permvarhi512:
6112 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6113 int Offset = ShuffleMask & 0x1F;
6114 return std::pair<unsigned, int>{0, Offset};
6115 });
6116 case X86::BI__builtin_ia32_permvarqi512:
6118 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6119 int Offset = ShuffleMask & 0x3F;
6120 return std::pair<unsigned, int>{0, Offset};
6121 });
6122 case X86::BI__builtin_ia32_vpermi2varq128:
6123 case X86::BI__builtin_ia32_vpermi2varpd128:
6125 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6126 int Offset = ShuffleMask & 0x1;
6127 unsigned SrcIdx = (ShuffleMask >> 1) & 0x1;
6128 return std::pair<unsigned, int>{SrcIdx, Offset};
6129 });
6130 case X86::BI__builtin_ia32_vpermi2vard128:
6131 case X86::BI__builtin_ia32_vpermi2varps128:
6132 case X86::BI__builtin_ia32_vpermi2varq256:
6133 case X86::BI__builtin_ia32_vpermi2varpd256:
6135 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6136 int Offset = ShuffleMask & 0x3;
6137 unsigned SrcIdx = (ShuffleMask >> 2) & 0x1;
6138 return std::pair<unsigned, int>{SrcIdx, Offset};
6139 });
6140 case X86::BI__builtin_ia32_vpermi2varhi128:
6141 case X86::BI__builtin_ia32_vpermi2vard256:
6142 case X86::BI__builtin_ia32_vpermi2varps256:
6143 case X86::BI__builtin_ia32_vpermi2varq512:
6144 case X86::BI__builtin_ia32_vpermi2varpd512:
6146 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6147 int Offset = ShuffleMask & 0x7;
6148 unsigned SrcIdx = (ShuffleMask >> 3) & 0x1;
6149 return std::pair<unsigned, int>{SrcIdx, Offset};
6150 });
6151 case X86::BI__builtin_ia32_vpermi2varqi128:
6152 case X86::BI__builtin_ia32_vpermi2varhi256:
6153 case X86::BI__builtin_ia32_vpermi2vard512:
6154 case X86::BI__builtin_ia32_vpermi2varps512:
6156 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6157 int Offset = ShuffleMask & 0xF;
6158 unsigned SrcIdx = (ShuffleMask >> 4) & 0x1;
6159 return std::pair<unsigned, int>{SrcIdx, Offset};
6160 });
6161 case X86::BI__builtin_ia32_vpermi2varqi256:
6162 case X86::BI__builtin_ia32_vpermi2varhi512:
6164 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6165 int Offset = ShuffleMask & 0x1F;
6166 unsigned SrcIdx = (ShuffleMask >> 5) & 0x1;
6167 return std::pair<unsigned, int>{SrcIdx, Offset};
6168 });
6169 case X86::BI__builtin_ia32_vpermi2varqi512:
6171 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6172 int Offset = ShuffleMask & 0x3F;
6173 unsigned SrcIdx = (ShuffleMask >> 6) & 0x1;
6174 return std::pair<unsigned, int>{SrcIdx, Offset};
6175 });
6176 case X86::BI__builtin_ia32_vperm2f128_pd256:
6177 case X86::BI__builtin_ia32_vperm2f128_ps256:
6178 case X86::BI__builtin_ia32_vperm2f128_si256:
6179 case X86::BI__builtin_ia32_permti256: {
6180 unsigned NumElements =
6181 Call->getArg(0)->getType()->castAs<VectorType>()->getNumElements();
6182 unsigned PreservedBitsCnt = NumElements >> 2;
6184 S, OpPC, Call,
6185 [PreservedBitsCnt](unsigned DstIdx, unsigned ShuffleMask) {
6186 unsigned ControlBitsCnt = DstIdx >> PreservedBitsCnt << 2;
6187 unsigned ControlBits = ShuffleMask >> ControlBitsCnt;
6188
6189 if (ControlBits & 0b1000)
6190 return std::make_pair(0u, -1);
6191
6192 unsigned SrcVecIdx = (ControlBits & 0b10) >> 1;
6193 unsigned PreservedBitsMask = (1 << PreservedBitsCnt) - 1;
6194 int SrcIdx = ((ControlBits & 0b1) << PreservedBitsCnt) |
6195 (DstIdx & PreservedBitsMask);
6196 return std::make_pair(SrcVecIdx, SrcIdx);
6197 });
6198 }
6199 case X86::BI__builtin_ia32_pshufb128:
6200 case X86::BI__builtin_ia32_pshufb256:
6201 case X86::BI__builtin_ia32_pshufb512:
6203 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6204 uint8_t Ctlb = static_cast<uint8_t>(ShuffleMask);
6205 if (Ctlb & 0x80)
6206 return std::make_pair(0, -1);
6207
6208 unsigned LaneBase = (DstIdx / 16) * 16;
6209 unsigned SrcOffset = Ctlb & 0x0F;
6210 unsigned SrcIdx = LaneBase + SrcOffset;
6211 return std::make_pair(0, static_cast<int>(SrcIdx));
6212 });
6213
6214 case X86::BI__builtin_ia32_pshuflw:
6215 case X86::BI__builtin_ia32_pshuflw256:
6216 case X86::BI__builtin_ia32_pshuflw512:
6218 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6219 unsigned LaneBase = (DstIdx / 8) * 8;
6220 unsigned LaneIdx = DstIdx % 8;
6221 if (LaneIdx < 4) {
6222 unsigned Sel = (ShuffleMask >> (2 * LaneIdx)) & 0x3;
6223 return std::make_pair(0, static_cast<int>(LaneBase + Sel));
6224 }
6225
6226 return std::make_pair(0, static_cast<int>(DstIdx));
6227 });
6228
6229 case X86::BI__builtin_ia32_pshufhw:
6230 case X86::BI__builtin_ia32_pshufhw256:
6231 case X86::BI__builtin_ia32_pshufhw512:
6233 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6234 unsigned LaneBase = (DstIdx / 8) * 8;
6235 unsigned LaneIdx = DstIdx % 8;
6236 if (LaneIdx >= 4) {
6237 unsigned Sel = (ShuffleMask >> (2 * (LaneIdx - 4))) & 0x3;
6238 return std::make_pair(0, static_cast<int>(LaneBase + 4 + Sel));
6239 }
6240
6241 return std::make_pair(0, static_cast<int>(DstIdx));
6242 });
6243
6244 case X86::BI__builtin_ia32_pshufd:
6245 case X86::BI__builtin_ia32_pshufd256:
6246 case X86::BI__builtin_ia32_pshufd512:
6247 case X86::BI__builtin_ia32_vpermilps:
6248 case X86::BI__builtin_ia32_vpermilps256:
6249 case X86::BI__builtin_ia32_vpermilps512:
6251 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6252 unsigned LaneBase = (DstIdx / 4) * 4;
6253 unsigned LaneIdx = DstIdx % 4;
6254 unsigned Sel = (ShuffleMask >> (2 * LaneIdx)) & 0x3;
6255 return std::make_pair(0, static_cast<int>(LaneBase + Sel));
6256 });
6257
6258 case X86::BI__builtin_ia32_vpermilvarpd:
6259 case X86::BI__builtin_ia32_vpermilvarpd256:
6260 case X86::BI__builtin_ia32_vpermilvarpd512:
6262 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6263 unsigned NumElemPerLane = 2;
6264 unsigned Lane = DstIdx / NumElemPerLane;
6265 unsigned Offset = ShuffleMask & 0b10 ? 1 : 0;
6266 return std::make_pair(
6267 0, static_cast<int>(Lane * NumElemPerLane + Offset));
6268 });
6269
6270 case X86::BI__builtin_ia32_vpermilvarps:
6271 case X86::BI__builtin_ia32_vpermilvarps256:
6272 case X86::BI__builtin_ia32_vpermilvarps512:
6274 S, OpPC, Call, [](unsigned DstIdx, unsigned ShuffleMask) {
6275 unsigned NumElemPerLane = 4;
6276 unsigned Lane = DstIdx / NumElemPerLane;
6277 unsigned Offset = ShuffleMask & 0b11;
6278 return std::make_pair(
6279 0, static_cast<int>(Lane * NumElemPerLane + Offset));
6280 });
6281
6282 case X86::BI__builtin_ia32_vpermilpd:
6283 case X86::BI__builtin_ia32_vpermilpd256:
6284 case X86::BI__builtin_ia32_vpermilpd512:
6286 S, OpPC, Call, [](unsigned DstIdx, unsigned Control) {
6287 unsigned NumElemPerLane = 2;
6288 unsigned BitsPerElem = 1;
6289 unsigned MaskBits = 8;
6290 unsigned IndexMask = 0x1;
6291 unsigned Lane = DstIdx / NumElemPerLane;
6292 unsigned LaneOffset = Lane * NumElemPerLane;
6293 unsigned BitIndex = (DstIdx * BitsPerElem) % MaskBits;
6294 unsigned Index = (Control >> BitIndex) & IndexMask;
6295 return std::make_pair(0, static_cast<int>(LaneOffset + Index));
6296 });
6297
6298 case X86::BI__builtin_ia32_permdf256:
6299 case X86::BI__builtin_ia32_permdi256:
6301 S, OpPC, Call, [](unsigned DstIdx, unsigned Control) {
6302 // permute4x64 operates on 4 64-bit elements
6303 // For element i (0-3), extract bits [2*i+1:2*i] from Control
6304 unsigned Index = (Control >> (2 * DstIdx)) & 0x3;
6305 return std::make_pair(0, static_cast<int>(Index));
6306 });
6307
6308 case X86::BI__builtin_ia32_vpmultishiftqb128:
6309 case X86::BI__builtin_ia32_vpmultishiftqb256:
6310 case X86::BI__builtin_ia32_vpmultishiftqb512:
6311 return interp__builtin_ia32_multishiftqb(S, OpPC, Call);
6312 case X86::BI__builtin_ia32_kandqi:
6313 case X86::BI__builtin_ia32_kandhi:
6314 case X86::BI__builtin_ia32_kandsi:
6315 case X86::BI__builtin_ia32_kanddi:
6317 S, OpPC, Call,
6318 [](const APSInt &LHS, const APSInt &RHS) { return LHS & RHS; });
6319
6320 case X86::BI__builtin_ia32_kandnqi:
6321 case X86::BI__builtin_ia32_kandnhi:
6322 case X86::BI__builtin_ia32_kandnsi:
6323 case X86::BI__builtin_ia32_kandndi:
6325 S, OpPC, Call,
6326 [](const APSInt &LHS, const APSInt &RHS) { return ~LHS & RHS; });
6327
6328 case X86::BI__builtin_ia32_korqi:
6329 case X86::BI__builtin_ia32_korhi:
6330 case X86::BI__builtin_ia32_korsi:
6331 case X86::BI__builtin_ia32_kordi:
6333 S, OpPC, Call,
6334 [](const APSInt &LHS, const APSInt &RHS) { return LHS | RHS; });
6335
6336 case X86::BI__builtin_ia32_kxnorqi:
6337 case X86::BI__builtin_ia32_kxnorhi:
6338 case X86::BI__builtin_ia32_kxnorsi:
6339 case X86::BI__builtin_ia32_kxnordi:
6341 S, OpPC, Call,
6342 [](const APSInt &LHS, const APSInt &RHS) { return ~(LHS ^ RHS); });
6343
6344 case X86::BI__builtin_ia32_kxorqi:
6345 case X86::BI__builtin_ia32_kxorhi:
6346 case X86::BI__builtin_ia32_kxorsi:
6347 case X86::BI__builtin_ia32_kxordi:
6349 S, OpPC, Call,
6350 [](const APSInt &LHS, const APSInt &RHS) { return LHS ^ RHS; });
6351
6352 case X86::BI__builtin_ia32_knotqi:
6353 case X86::BI__builtin_ia32_knothi:
6354 case X86::BI__builtin_ia32_knotsi:
6355 case X86::BI__builtin_ia32_knotdi:
6357 S, OpPC, Call, [](const APSInt &Src) { return ~Src; });
6358
6359 case X86::BI__builtin_ia32_kaddqi:
6360 case X86::BI__builtin_ia32_kaddhi:
6361 case X86::BI__builtin_ia32_kaddsi:
6362 case X86::BI__builtin_ia32_kadddi:
6364 S, OpPC, Call,
6365 [](const APSInt &LHS, const APSInt &RHS) { return LHS + RHS; });
6366
6367 case X86::BI__builtin_ia32_kmovb:
6368 case X86::BI__builtin_ia32_kmovw:
6369 case X86::BI__builtin_ia32_kmovd:
6370 case X86::BI__builtin_ia32_kmovq:
6372 S, OpPC, Call, [](const APSInt &Src) { return Src; });
6373
6374 case X86::BI__builtin_ia32_kunpckhi:
6375 case X86::BI__builtin_ia32_kunpckdi:
6376 case X86::BI__builtin_ia32_kunpcksi:
6378 S, OpPC, Call, [](const APSInt &A, const APSInt &B) {
6379 // Generic kunpack: extract lower half of each operand and concatenate
6380 // Result = A[HalfWidth-1:0] concat B[HalfWidth-1:0]
6381 unsigned BW = A.getBitWidth();
6382 return APSInt(A.trunc(BW / 2).concat(B.trunc(BW / 2)),
6383 A.isUnsigned());
6384 });
6385
6386 case X86::BI__builtin_ia32_phminposuw128:
6387 return interp__builtin_ia32_phminposuw(S, OpPC, Call);
6388
6389 case X86::BI__builtin_ia32_psraq128:
6390 case X86::BI__builtin_ia32_psraq256:
6391 case X86::BI__builtin_ia32_psraq512:
6392 case X86::BI__builtin_ia32_psrad128:
6393 case X86::BI__builtin_ia32_psrad256:
6394 case X86::BI__builtin_ia32_psrad512:
6395 case X86::BI__builtin_ia32_psraw128:
6396 case X86::BI__builtin_ia32_psraw256:
6397 case X86::BI__builtin_ia32_psraw512:
6399 S, OpPC, Call,
6400 [](const APInt &Elt, uint64_t Count) { return Elt.ashr(Count); },
6401 [](const APInt &Elt, unsigned Width) { return Elt.ashr(Width - 1); });
6402
6403 case X86::BI__builtin_ia32_psllq128:
6404 case X86::BI__builtin_ia32_psllq256:
6405 case X86::BI__builtin_ia32_psllq512:
6406 case X86::BI__builtin_ia32_pslld128:
6407 case X86::BI__builtin_ia32_pslld256:
6408 case X86::BI__builtin_ia32_pslld512:
6409 case X86::BI__builtin_ia32_psllw128:
6410 case X86::BI__builtin_ia32_psllw256:
6411 case X86::BI__builtin_ia32_psllw512:
6413 S, OpPC, Call,
6414 [](const APInt &Elt, uint64_t Count) { return Elt.shl(Count); },
6415 [](const APInt &Elt, unsigned Width) { return APInt::getZero(Width); });
6416
6417 case X86::BI__builtin_ia32_psrlq128:
6418 case X86::BI__builtin_ia32_psrlq256:
6419 case X86::BI__builtin_ia32_psrlq512:
6420 case X86::BI__builtin_ia32_psrld128:
6421 case X86::BI__builtin_ia32_psrld256:
6422 case X86::BI__builtin_ia32_psrld512:
6423 case X86::BI__builtin_ia32_psrlw128:
6424 case X86::BI__builtin_ia32_psrlw256:
6425 case X86::BI__builtin_ia32_psrlw512:
6427 S, OpPC, Call,
6428 [](const APInt &Elt, uint64_t Count) { return Elt.lshr(Count); },
6429 [](const APInt &Elt, unsigned Width) { return APInt::getZero(Width); });
6430
6431 case X86::BI__builtin_ia32_pternlogd128_mask:
6432 case X86::BI__builtin_ia32_pternlogd256_mask:
6433 case X86::BI__builtin_ia32_pternlogd512_mask:
6434 case X86::BI__builtin_ia32_pternlogq128_mask:
6435 case X86::BI__builtin_ia32_pternlogq256_mask:
6436 case X86::BI__builtin_ia32_pternlogq512_mask:
6437 return interp__builtin_ia32_pternlog(S, OpPC, Call, /*MaskZ=*/false);
6438 case X86::BI__builtin_ia32_pternlogd128_maskz:
6439 case X86::BI__builtin_ia32_pternlogd256_maskz:
6440 case X86::BI__builtin_ia32_pternlogd512_maskz:
6441 case X86::BI__builtin_ia32_pternlogq128_maskz:
6442 case X86::BI__builtin_ia32_pternlogq256_maskz:
6443 case X86::BI__builtin_ia32_pternlogq512_maskz:
6444 return interp__builtin_ia32_pternlog(S, OpPC, Call, /*MaskZ=*/true);
6445 case Builtin::BI__builtin_elementwise_fshl:
6447 llvm::APIntOps::fshl);
6448 case Builtin::BI__builtin_elementwise_fshr:
6450 llvm::APIntOps::fshr);
6451
6452 case X86::BI__builtin_ia32_shuf_f32x4_256:
6453 case X86::BI__builtin_ia32_shuf_i32x4_256:
6454 case X86::BI__builtin_ia32_shuf_f64x2_256:
6455 case X86::BI__builtin_ia32_shuf_i64x2_256:
6456 case X86::BI__builtin_ia32_shuf_f32x4:
6457 case X86::BI__builtin_ia32_shuf_i32x4:
6458 case X86::BI__builtin_ia32_shuf_f64x2:
6459 case X86::BI__builtin_ia32_shuf_i64x2: {
6460 // Destination and sources A, B all have the same type.
6461 QualType VecQT = Call->getArg(0)->getType();
6462 const auto *VecT = VecQT->castAs<VectorType>();
6463 unsigned NumElems = VecT->getNumElements();
6464 unsigned ElemBits = S.getASTContext().getTypeSize(VecT->getElementType());
6465 unsigned LaneBits = 128u;
6466 unsigned NumLanes = (NumElems * ElemBits) / LaneBits;
6467 unsigned NumElemsPerLane = LaneBits / ElemBits;
6468
6470 S, OpPC, Call,
6471 [NumLanes, NumElemsPerLane](unsigned DstIdx, unsigned ShuffleMask) {
6472 // DstIdx determines source. ShuffleMask selects lane in source.
6473 unsigned BitsPerElem = NumLanes / 2;
6474 unsigned IndexMask = (1u << BitsPerElem) - 1;
6475 unsigned Lane = DstIdx / NumElemsPerLane;
6476 unsigned SrcIdx = (Lane < NumLanes / 2) ? 0 : 1;
6477 unsigned BitIdx = BitsPerElem * Lane;
6478 unsigned SrcLaneIdx = (ShuffleMask >> BitIdx) & IndexMask;
6479 unsigned ElemInLane = DstIdx % NumElemsPerLane;
6480 unsigned IdxToPick = SrcLaneIdx * NumElemsPerLane + ElemInLane;
6481 return std::pair<unsigned, int>{SrcIdx, IdxToPick};
6482 });
6483 }
6484
6485 case X86::BI__builtin_ia32_insertf32x4_256:
6486 case X86::BI__builtin_ia32_inserti32x4_256:
6487 case X86::BI__builtin_ia32_insertf64x2_256:
6488 case X86::BI__builtin_ia32_inserti64x2_256:
6489 case X86::BI__builtin_ia32_insertf32x4:
6490 case X86::BI__builtin_ia32_inserti32x4:
6491 case X86::BI__builtin_ia32_insertf64x2_512:
6492 case X86::BI__builtin_ia32_inserti64x2_512:
6493 case X86::BI__builtin_ia32_insertf32x8:
6494 case X86::BI__builtin_ia32_inserti32x8:
6495 case X86::BI__builtin_ia32_insertf64x4:
6496 case X86::BI__builtin_ia32_inserti64x4:
6497 case X86::BI__builtin_ia32_vinsertf128_ps256:
6498 case X86::BI__builtin_ia32_vinsertf128_pd256:
6499 case X86::BI__builtin_ia32_vinsertf128_si256:
6500 case X86::BI__builtin_ia32_insert128i256:
6501 return interp__builtin_ia32_insert_subvector(S, OpPC, Call, BuiltinID);
6502
6503 case clang::X86::BI__builtin_ia32_vcvtps2ph:
6504 case clang::X86::BI__builtin_ia32_vcvtps2ph256:
6505 return interp__builtin_ia32_vcvtps2ph(S, OpPC, Call);
6506
6507 case X86::BI__builtin_ia32_vec_ext_v4hi:
6508 case X86::BI__builtin_ia32_vec_ext_v16qi:
6509 case X86::BI__builtin_ia32_vec_ext_v8hi:
6510 case X86::BI__builtin_ia32_vec_ext_v4si:
6511 case X86::BI__builtin_ia32_vec_ext_v2di:
6512 case X86::BI__builtin_ia32_vec_ext_v32qi:
6513 case X86::BI__builtin_ia32_vec_ext_v16hi:
6514 case X86::BI__builtin_ia32_vec_ext_v8si:
6515 case X86::BI__builtin_ia32_vec_ext_v4di:
6516 case X86::BI__builtin_ia32_vec_ext_v4sf:
6517 return interp__builtin_ia32_vec_ext(S, OpPC, Call, BuiltinID);
6518
6519 case X86::BI__builtin_ia32_vec_set_v4hi:
6520 case X86::BI__builtin_ia32_vec_set_v16qi:
6521 case X86::BI__builtin_ia32_vec_set_v8hi:
6522 case X86::BI__builtin_ia32_vec_set_v4si:
6523 case X86::BI__builtin_ia32_vec_set_v2di:
6524 case X86::BI__builtin_ia32_vec_set_v32qi:
6525 case X86::BI__builtin_ia32_vec_set_v16hi:
6526 case X86::BI__builtin_ia32_vec_set_v8si:
6527 case X86::BI__builtin_ia32_vec_set_v4di:
6528 return interp__builtin_ia32_vec_set(S, OpPC, Call, BuiltinID);
6529
6530 case X86::BI__builtin_ia32_cvtb2mask128:
6531 case X86::BI__builtin_ia32_cvtb2mask256:
6532 case X86::BI__builtin_ia32_cvtb2mask512:
6533 case X86::BI__builtin_ia32_cvtw2mask128:
6534 case X86::BI__builtin_ia32_cvtw2mask256:
6535 case X86::BI__builtin_ia32_cvtw2mask512:
6536 case X86::BI__builtin_ia32_cvtd2mask128:
6537 case X86::BI__builtin_ia32_cvtd2mask256:
6538 case X86::BI__builtin_ia32_cvtd2mask512:
6539 case X86::BI__builtin_ia32_cvtq2mask128:
6540 case X86::BI__builtin_ia32_cvtq2mask256:
6541 case X86::BI__builtin_ia32_cvtq2mask512:
6542 return interp__builtin_ia32_cvt_vec2mask(S, OpPC, Call, BuiltinID);
6543
6544 case X86::BI__builtin_ia32_cvtmask2b128:
6545 case X86::BI__builtin_ia32_cvtmask2b256:
6546 case X86::BI__builtin_ia32_cvtmask2b512:
6547 case X86::BI__builtin_ia32_cvtmask2w128:
6548 case X86::BI__builtin_ia32_cvtmask2w256:
6549 case X86::BI__builtin_ia32_cvtmask2w512:
6550 case X86::BI__builtin_ia32_cvtmask2d128:
6551 case X86::BI__builtin_ia32_cvtmask2d256:
6552 case X86::BI__builtin_ia32_cvtmask2d512:
6553 case X86::BI__builtin_ia32_cvtmask2q128:
6554 case X86::BI__builtin_ia32_cvtmask2q256:
6555 case X86::BI__builtin_ia32_cvtmask2q512:
6556 return interp__builtin_ia32_cvt_mask2vec(S, OpPC, Call, BuiltinID);
6557
6558 case X86::BI__builtin_ia32_cvtsd2ss:
6559 return interp__builtin_ia32_cvtsd2ss(S, OpPC, Call, false);
6560
6561 case X86::BI__builtin_ia32_cvtsd2ss_round_mask:
6562 return interp__builtin_ia32_cvtsd2ss(S, OpPC, Call, true);
6563
6564 case X86::BI__builtin_ia32_cvtpd2ps:
6565 case X86::BI__builtin_ia32_cvtpd2ps256:
6566 return interp__builtin_ia32_cvtpd2ps(S, OpPC, Call, false, false);
6567 case X86::BI__builtin_ia32_cvtpd2ps_mask:
6568 return interp__builtin_ia32_cvtpd2ps(S, OpPC, Call, true, false);
6569 case X86::BI__builtin_ia32_cvtpd2ps512_mask:
6570 return interp__builtin_ia32_cvtpd2ps(S, OpPC, Call, true, true);
6571
6572 case X86::BI__builtin_ia32_cmpb128_mask:
6573 case X86::BI__builtin_ia32_cmpw128_mask:
6574 case X86::BI__builtin_ia32_cmpd128_mask:
6575 case X86::BI__builtin_ia32_cmpq128_mask:
6576 case X86::BI__builtin_ia32_cmpb256_mask:
6577 case X86::BI__builtin_ia32_cmpw256_mask:
6578 case X86::BI__builtin_ia32_cmpd256_mask:
6579 case X86::BI__builtin_ia32_cmpq256_mask:
6580 case X86::BI__builtin_ia32_cmpb512_mask:
6581 case X86::BI__builtin_ia32_cmpw512_mask:
6582 case X86::BI__builtin_ia32_cmpd512_mask:
6583 case X86::BI__builtin_ia32_cmpq512_mask:
6584 return interp__builtin_ia32_cmp_mask(S, OpPC, Call, BuiltinID,
6585 /*IsUnsigned=*/false);
6586
6587 case X86::BI__builtin_ia32_ucmpb128_mask:
6588 case X86::BI__builtin_ia32_ucmpw128_mask:
6589 case X86::BI__builtin_ia32_ucmpd128_mask:
6590 case X86::BI__builtin_ia32_ucmpq128_mask:
6591 case X86::BI__builtin_ia32_ucmpb256_mask:
6592 case X86::BI__builtin_ia32_ucmpw256_mask:
6593 case X86::BI__builtin_ia32_ucmpd256_mask:
6594 case X86::BI__builtin_ia32_ucmpq256_mask:
6595 case X86::BI__builtin_ia32_ucmpb512_mask:
6596 case X86::BI__builtin_ia32_ucmpw512_mask:
6597 case X86::BI__builtin_ia32_ucmpd512_mask:
6598 case X86::BI__builtin_ia32_ucmpq512_mask:
6599 return interp__builtin_ia32_cmp_mask(S, OpPC, Call, BuiltinID,
6600 /*IsUnsigned=*/true);
6601
6602 case X86::BI__builtin_ia32_vpshufbitqmb128_mask:
6603 case X86::BI__builtin_ia32_vpshufbitqmb256_mask:
6604 case X86::BI__builtin_ia32_vpshufbitqmb512_mask:
6606
6607 case X86::BI__builtin_ia32_pslldqi128_byteshift:
6608 case X86::BI__builtin_ia32_pslldqi256_byteshift:
6609 case X86::BI__builtin_ia32_pslldqi512_byteshift:
6610 // These SLLDQ intrinsics always operate on byte elements (8 bits).
6611 // The lane width is hardcoded to 16 to match the SIMD register size,
6612 // but the algorithm processes one byte per iteration,
6613 // so APInt(8, ...) is correct and intentional.
6615 S, OpPC, Call,
6616 [](unsigned DstIdx, unsigned Shift) -> std::pair<unsigned, int> {
6617 unsigned LaneBase = (DstIdx / 16) * 16;
6618 unsigned LaneIdx = DstIdx % 16;
6619 if (LaneIdx < Shift)
6620 return std::make_pair(0, -1);
6621
6622 return std::make_pair(0,
6623 static_cast<int>(LaneBase + LaneIdx - Shift));
6624 });
6625
6626 case X86::BI__builtin_ia32_psrldqi128_byteshift:
6627 case X86::BI__builtin_ia32_psrldqi256_byteshift:
6628 case X86::BI__builtin_ia32_psrldqi512_byteshift:
6629 // These SRLDQ intrinsics always operate on byte elements (8 bits).
6630 // The lane width is hardcoded to 16 to match the SIMD register size,
6631 // but the algorithm processes one byte per iteration,
6632 // so APInt(8, ...) is correct and intentional.
6634 S, OpPC, Call,
6635 [](unsigned DstIdx, unsigned Shift) -> std::pair<unsigned, int> {
6636 unsigned LaneBase = (DstIdx / 16) * 16;
6637 unsigned LaneIdx = DstIdx % 16;
6638 if (LaneIdx + Shift < 16)
6639 return std::make_pair(0,
6640 static_cast<int>(LaneBase + LaneIdx + Shift));
6641
6642 return std::make_pair(0, -1);
6643 });
6644
6645 case X86::BI__builtin_ia32_palignr128:
6646 case X86::BI__builtin_ia32_palignr256:
6647 case X86::BI__builtin_ia32_palignr512:
6649 S, OpPC, Call, [](unsigned DstIdx, unsigned Shift) {
6650 // Default to -1 → zero-fill this destination element
6651 unsigned VecIdx = 1;
6652 int ElemIdx = -1;
6653
6654 int Lane = DstIdx / 16;
6655 int Offset = DstIdx % 16;
6656
6657 // Elements come from VecB first, then VecA after the shift boundary
6658 unsigned ShiftedIdx = Offset + (Shift & 0xFF);
6659 if (ShiftedIdx < 16) { // from VecB
6660 ElemIdx = ShiftedIdx + (Lane * 16);
6661 } else if (ShiftedIdx < 32) { // from VecA
6662 VecIdx = 0;
6663 ElemIdx = (ShiftedIdx - 16) + (Lane * 16);
6664 }
6665
6666 return std::pair<unsigned, int>{VecIdx, ElemIdx};
6667 });
6668
6669 case X86::BI__builtin_ia32_alignd128:
6670 case X86::BI__builtin_ia32_alignd256:
6671 case X86::BI__builtin_ia32_alignd512:
6672 case X86::BI__builtin_ia32_alignq128:
6673 case X86::BI__builtin_ia32_alignq256:
6674 case X86::BI__builtin_ia32_alignq512: {
6675 unsigned NumElems = Call->getType()->castAs<VectorType>()->getNumElements();
6677 S, OpPC, Call, [NumElems](unsigned DstIdx, unsigned Shift) {
6678 unsigned Imm = Shift & 0xFF;
6679 unsigned EffectiveShift = Imm & (NumElems - 1);
6680 unsigned SourcePos = DstIdx + EffectiveShift;
6681 unsigned VecIdx = SourcePos < NumElems ? 1u : 0u;
6682 unsigned ElemIdx = SourcePos & (NumElems - 1);
6683 return std::pair<unsigned, int>{VecIdx, static_cast<int>(ElemIdx)};
6684 });
6685 }
6686
6687 case clang::X86::BI__builtin_ia32_minps:
6688 case clang::X86::BI__builtin_ia32_minpd:
6689 case clang::X86::BI__builtin_ia32_minph128:
6690 case clang::X86::BI__builtin_ia32_minph256:
6691 case clang::X86::BI__builtin_ia32_minps256:
6692 case clang::X86::BI__builtin_ia32_minpd256:
6693 case clang::X86::BI__builtin_ia32_minps512:
6694 case clang::X86::BI__builtin_ia32_minpd512:
6695 case clang::X86::BI__builtin_ia32_minph512:
6697 S, OpPC, Call,
6698 [](const APFloat &A, const APFloat &B,
6699 std::optional<APSInt>) -> std::optional<APFloat> {
6700 if (A.isNaN() || A.isInfinity() || A.isDenormal() || B.isNaN() ||
6701 B.isInfinity() || B.isDenormal())
6702 return std::nullopt;
6703 if (A.isZero() && B.isZero())
6704 return B;
6705 return llvm::minimum(A, B);
6706 });
6707
6708 case clang::X86::BI__builtin_ia32_minss:
6709 case clang::X86::BI__builtin_ia32_minsd:
6711 S, OpPC, Call,
6712 [](const APFloat &A, const APFloat &B,
6713 std::optional<APSInt> RoundingMode) -> std::optional<APFloat> {
6714 return EvalScalarMinMaxFp(A, B, RoundingMode, /*IsMin=*/true);
6715 },
6716 /*IsScalar=*/true);
6717
6718 case clang::X86::BI__builtin_ia32_minsd_round_mask:
6719 case clang::X86::BI__builtin_ia32_minss_round_mask:
6720 case clang::X86::BI__builtin_ia32_minsh_round_mask:
6721 case clang::X86::BI__builtin_ia32_maxsd_round_mask:
6722 case clang::X86::BI__builtin_ia32_maxss_round_mask:
6723 case clang::X86::BI__builtin_ia32_maxsh_round_mask: {
6724 bool IsMin = BuiltinID == clang::X86::BI__builtin_ia32_minsd_round_mask ||
6725 BuiltinID == clang::X86::BI__builtin_ia32_minss_round_mask ||
6726 BuiltinID == clang::X86::BI__builtin_ia32_minsh_round_mask;
6728 S, OpPC, Call,
6729 [IsMin](const APFloat &A, const APFloat &B,
6730 std::optional<APSInt> RoundingMode) -> std::optional<APFloat> {
6731 return EvalScalarMinMaxFp(A, B, RoundingMode, IsMin);
6732 });
6733 }
6734
6735 case clang::X86::BI__builtin_ia32_maxps:
6736 case clang::X86::BI__builtin_ia32_maxpd:
6737 case clang::X86::BI__builtin_ia32_maxph128:
6738 case clang::X86::BI__builtin_ia32_maxph256:
6739 case clang::X86::BI__builtin_ia32_maxps256:
6740 case clang::X86::BI__builtin_ia32_maxpd256:
6741 case clang::X86::BI__builtin_ia32_maxps512:
6742 case clang::X86::BI__builtin_ia32_maxpd512:
6743 case clang::X86::BI__builtin_ia32_maxph512:
6745 S, OpPC, Call,
6746 [](const APFloat &A, const APFloat &B,
6747 std::optional<APSInt>) -> std::optional<APFloat> {
6748 if (A.isNaN() || A.isInfinity() || A.isDenormal() || B.isNaN() ||
6749 B.isInfinity() || B.isDenormal())
6750 return std::nullopt;
6751 if (A.isZero() && B.isZero())
6752 return B;
6753 return llvm::maximum(A, B);
6754 });
6755
6756 case clang::X86::BI__builtin_ia32_maxss:
6757 case clang::X86::BI__builtin_ia32_maxsd:
6759 S, OpPC, Call,
6760 [](const APFloat &A, const APFloat &B,
6761 std::optional<APSInt> RoundingMode) -> std::optional<APFloat> {
6762 return EvalScalarMinMaxFp(A, B, RoundingMode, /*IsMin=*/false);
6763 },
6764 /*IsScalar=*/true);
6765 case X86::BI__builtin_ia32_vpdpwssd128:
6766 case X86::BI__builtin_ia32_vpdpwssd256:
6767 case X86::BI__builtin_ia32_vpdpwssd512:
6768 case X86::BI__builtin_ia32_vpdpbusd128:
6769 case X86::BI__builtin_ia32_vpdpbusd256:
6770 case X86::BI__builtin_ia32_vpdpbusd512:
6771 return interp__builtin_ia32_vpdp(S, OpPC, Call, false);
6772 case X86::BI__builtin_ia32_vpdpwssds128:
6773 case X86::BI__builtin_ia32_vpdpwssds256:
6774 case X86::BI__builtin_ia32_vpdpwssds512:
6775 case X86::BI__builtin_ia32_vpdpbusds128:
6776 case X86::BI__builtin_ia32_vpdpbusds256:
6777 case X86::BI__builtin_ia32_vpdpbusds512:
6778 return interp__builtin_ia32_vpdp(S, OpPC, Call, true);
6779 default:
6780 S.FFDiag(S.Current->getLocation(OpPC),
6781 diag::note_invalid_subexpr_in_const_expr)
6782 << S.Current->getRange(OpPC);
6783
6784 return false;
6785 }
6786
6787 llvm_unreachable("Unhandled builtin ID");
6788}
6789
6791 ArrayRef<int64_t> ArrayIndices, int64_t &IntResult) {
6794 unsigned N = E->getNumComponents();
6795 assert(N > 0);
6796
6797 unsigned ArrayIndex = 0;
6798 QualType CurrentType = E->getTypeSourceInfo()->getType();
6799 for (unsigned I = 0; I != N; ++I) {
6800 const OffsetOfNode &Node = E->getComponent(I);
6801 switch (Node.getKind()) {
6802 case OffsetOfNode::Field: {
6803 const FieldDecl *MemberDecl = Node.getField();
6804 const auto *RD = CurrentType->getAsRecordDecl();
6805 if (!RD || RD->isInvalidDecl())
6806 return false;
6808 unsigned FieldIndex = MemberDecl->getFieldIndex();
6809 assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");
6810 Result +=
6812 CurrentType = MemberDecl->getType().getNonReferenceType();
6813 break;
6814 }
6815 case OffsetOfNode::Array: {
6816 // When generating bytecode, we put all the index expressions as Sint64 on
6817 // the stack.
6818 int64_t Index = ArrayIndices[ArrayIndex];
6819 if (Index < 0)
6820 return Invalid(S, OpPC);
6821 const ArrayType *AT = S.getASTContext().getAsArrayType(CurrentType);
6822 if (!AT)
6823 return false;
6824 CurrentType = AT->getElementType();
6825 CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType);
6826 int64_t ElemSize = ElementSize.getQuantity();
6827 if (Index != 0 && ElemSize > llvm::maxIntN(64) / Index) {
6828 S.FFDiag(S.Current->getLocation(OpPC),
6829 diag::note_constexpr_offsetof_overflow)
6830 << S.Current->getRange(OpPC);
6831 return false;
6832 }
6833 int64_t Offset = Index * ElemSize;
6834 if (Result.getQuantity() > llvm::maxIntN(64) - Offset) {
6835 S.FFDiag(S.Current->getLocation(OpPC),
6836 diag::note_constexpr_offsetof_overflow)
6837 << S.Current->getRange(OpPC);
6838 return false;
6839 }
6841 ++ArrayIndex;
6842 break;
6843 }
6844 case OffsetOfNode::Base: {
6845 const CXXBaseSpecifier *BaseSpec = Node.getBase();
6846 if (BaseSpec->isVirtual())
6847 return false;
6848
6849 // Find the layout of the class whose base we are looking into.
6850 const auto *RD = CurrentType->getAsCXXRecordDecl();
6851 if (!RD || RD->isInvalidDecl())
6852 return false;
6854
6855 // Find the base class itself.
6856 CurrentType = BaseSpec->getType();
6857 const auto *BaseRD = CurrentType->getAsCXXRecordDecl();
6858 if (!BaseRD)
6859 return false;
6860
6861 // Add the offset to the base.
6862 Result += RL.getBaseClassOffset(BaseRD);
6863 break;
6864 }
6866 llvm_unreachable("Dependent OffsetOfExpr?");
6867 }
6868 }
6869
6870 IntResult = Result.getQuantity();
6871
6872 return true;
6873}
6874
6876 const Pointer &Ptr, const APSInt &IntValue) {
6877
6878 const Record *R = Ptr.getRecord();
6879 assert(R);
6880 assert(R->getNumFields() == 1);
6881
6882 unsigned FieldOffset = R->getField(0u)->Offset;
6883 PtrView FieldPtr = Ptr.view().atField(FieldOffset);
6884 PrimType FieldT = FieldPtr.getFieldDesc()->getPrimType();
6885
6886 INT_TYPE_SWITCH(FieldT,
6887 FieldPtr.deref<T>() = T::from(IntValue.getSExtValue()));
6888 FieldPtr.initialize();
6889 return true;
6890}
6891
6892static void zeroAll(PtrView Dest) {
6893 const Descriptor *Desc = Dest.getFieldDesc();
6894
6895 if (Desc->isPrimitive()) {
6896 TYPE_SWITCH(Desc->getPrimType(), {
6897 Dest.deref<T>().~T();
6898 new (&Dest.deref<T>()) T();
6899 });
6900 return;
6901 }
6902
6903 if (Desc->isRecord()) {
6904 const Record *R = Desc->ElemRecord;
6905 for (const Record::Field &F : R->fields()) {
6906 PtrView FieldPtr = Dest.atField(F.Offset);
6907 zeroAll(FieldPtr);
6908 }
6909 return;
6910 }
6911
6912 if (Desc->isPrimitiveArray()) {
6913 for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
6914 TYPE_SWITCH(Desc->getPrimType(), {
6915 Dest.deref<T>().~T();
6916 new (&Dest.deref<T>()) T();
6917 });
6918 }
6919 return;
6920 }
6921
6922 if (Desc->isCompositeArray()) {
6923 for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
6924 PtrView ElemPtr = Dest.atIndex(I).narrow();
6925 zeroAll(ElemPtr);
6926 }
6927 return;
6928 }
6929}
6930
6931static bool copyComposite(InterpState &S, CodePtr OpPC, PtrView Src,
6932 PtrView Dest, bool Activate);
6933static bool copyRecord(InterpState &S, CodePtr OpPC, PtrView Src, PtrView Dest,
6934 bool Activate = false) {
6935 [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
6936 const Descriptor *DestDesc = Dest.getFieldDesc();
6937
6938 auto copyField = [&](const Record::Field &F, bool Activate) -> bool {
6939 PtrView DestField = Dest.atField(F.Offset);
6940 if (OptPrimType FT = S.Ctx.classify(F.Decl->getType())) {
6941 TYPE_SWITCH(*FT, {
6942 DestField.deref<T>() = Src.atField(F.Offset).deref<T>();
6943 if (Src.atField(F.Offset).isInitialized())
6944 DestField.initialize();
6945 if (Activate)
6946 DestField.activate();
6947 });
6948 return true;
6949 }
6950 // Composite field.
6951 return copyComposite(S, OpPC, Src.atField(F.Offset), DestField, Activate);
6952 };
6953
6954 assert(SrcDesc->isRecord());
6955 assert(SrcDesc->ElemRecord == DestDesc->ElemRecord);
6956 const Record *R = DestDesc->ElemRecord;
6957 for (const Record::Field &F : R->fields()) {
6958 PtrView FP = Src.atField(F.Offset);
6959
6960 if (!CheckMutable(S, OpPC, FP))
6961 return false;
6962
6963 if (R->isUnion()) {
6964 // For unions, only copy the active field. Zero all others.
6965 if (FP.isActive()) {
6966 if (!copyField(F, /*Activate=*/true))
6967 return false;
6968 } else {
6969 PtrView DestField = Dest.atField(F.Offset);
6970 zeroAll(DestField);
6971 }
6972 } else {
6973 if (!copyField(F, Activate))
6974 return false;
6975 }
6976 }
6977
6978 for (const Record::Base &B : R->bases()) {
6979 PtrView DestBase = Dest.atField(B.Offset);
6980 if (!copyRecord(S, OpPC, Src.atField(B.Offset), DestBase, Activate))
6981 return false;
6982 }
6983
6984 Dest.initialize();
6985 return true;
6986}
6987
6988static bool copyComposite(InterpState &S, CodePtr OpPC, PtrView Src,
6989 PtrView Dest, bool Activate = false) {
6990 assert(Src.isLive() && Dest.isLive());
6991
6992 [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
6993 const Descriptor *DestDesc = Dest.getFieldDesc();
6994
6995 assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive());
6996
6997 if (DestDesc->isPrimitiveArray()) {
6998 if (!SrcDesc->isPrimitiveArray())
6999 return false;
7000 // For floating types, check the actual QualType so we don't accidentally
7001 // mix up semantics.
7002 if (SrcDesc->getPrimType() == PT_Float) {
7003 if (!S.getASTContext().hasSimilarType(SrcDesc->getElemQualType(),
7004 DestDesc->getElemQualType()))
7005 return false;
7006 }
7007
7008 assert(SrcDesc->isPrimitiveArray());
7009 assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
7010 assert(SrcDesc->getPrimType() == DestDesc->getPrimType());
7011 PrimType ET = DestDesc->getPrimType();
7012 for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
7013 PtrView DestElem = Dest.atIndex(I);
7014 TYPE_SWITCH(ET, { DestElem.deref<T>() = Src.elem<T>(I); });
7015 DestElem.initializeElement(I);
7016 }
7017 return true;
7018 }
7019
7020 if (DestDesc->isCompositeArray()) {
7021 if (!SrcDesc->isCompositeArray())
7022 return false;
7023 assert(SrcDesc->isCompositeArray());
7024 assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
7025 for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
7026 PtrView SrcElem = Src.atIndex(I).narrow();
7027 PtrView DestElem = Dest.atIndex(I).narrow();
7028 if (!copyComposite(S, OpPC, SrcElem, DestElem, Activate))
7029 return false;
7030 }
7031 return true;
7032 }
7033
7034 if (DestDesc->isRecord()) {
7035 if (!SrcDesc->isRecord())
7036 return false;
7037 return copyRecord(S, OpPC, Src, Dest, Activate);
7038 }
7039 return Invalid(S, OpPC);
7040}
7041
7042bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {
7043 if (!Src.isBlockPointer() || Src.getFieldDesc()->isPrimitive())
7044 return false;
7045 if (!Dest.isBlockPointer() || Dest.getFieldDesc()->isPrimitive())
7046 return false;
7047
7048 return copyComposite(S, OpPC, Src.view(), Dest.view());
7049}
7050
7051} // namespace interp
7052} // 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:263
#define INT_TYPE_SWITCH_NO_BOOL(Expr, B)
Definition PrimType.h:279
#define INT_TYPE_SWITCH(Expr, B)
Definition PrimType.h:244
#define TYPE_SWITCH(Expr, B)
Definition PrimType.h:223
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static QualType getPointeeType(const MemRegion *R)
Enumerates target-specific builtins in their own namespaces within namespace clang.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
CharUnits & getLValueOffset()
Definition APValue.cpp:1011
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:810
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:965
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:927
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:3786
QualType getElementType() const
Definition TypeBase.h:3798
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:2949
Expr * getArg(unsigned Arg)
getArg - Return the specified argument.
Definition Expr.h:3153
CharUnits - This is an opaque type for sizes expressed in character units.
Definition CharUnits.h:38
CharUnits alignmentAtOffset(CharUnits offset) const
Given that this is a non-zero alignment value, what is the alignment at the given offset?
Definition CharUnits.h:207
bool isZero() const
isZero - Test whether the quantity equals zero.
Definition CharUnits.h:122
QuantityType getQuantity() const
getQuantity - Get the raw integer representation of this quantity.
Definition CharUnits.h:185
static CharUnits One()
One - Construct a CharUnits quantity of one.
Definition CharUnits.h:58
static CharUnits fromQuantity(QuantityType Quantity)
fromQuantity - Construct a CharUnits quantity from a raw integer type.
Definition CharUnits.h:63
CharUnits alignTo(const CharUnits &Align) const
alignTo - Returns the next integer (mod 2**64) that is greater than or equal to this quantity and is ...
Definition CharUnits.h:201
static unsigned getMaxSizeBits(const ASTContext &Context)
Determine the maximum number of active bits that an array's size can require, which limits the maximu...
Definition Type.cpp:291
This represents one expression.
Definition Expr.h:112
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition Expr.cpp:283
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3204
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3289
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3440
Represents a function declaration or definition.
Definition Decl.h:2029
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:2533
const OffsetOfNode & getComponent(unsigned Idx) const
Definition Expr.h:2580
TypeSourceInfo * getTypeSourceInfo() const
Definition Expr.h:2573
unsigned getNumComponents() const
Definition Expr.h:2588
Helper class for OffsetOfExpr.
Definition Expr.h:2427
FieldDecl * getField() const
For a field offsetof node, returns the field.
Definition Expr.h:2491
@ Array
An index into an array.
Definition Expr.h:2432
@ Identifier
A field in a dependent type, known only by its name.
Definition Expr.h:2436
@ Field
A field.
Definition Expr.h:2434
@ Base
An implicit indirection through a C++ base class, when the field found is in a base class.
Definition Expr.h:2439
Kind getKind() const
Determine what kind of offsetof node this is.
Definition Expr.h:2481
CXXBaseSpecifier * getBase() const
For a base class node, returns the base specifier.
Definition Expr.h:2501
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3392
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition Type.cpp:2970
bool isNull() const
Return true if this QualType doesn't point to a type yet.
Definition TypeBase.h:1004
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8447
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:8632
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:862
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:8429
bool isBooleanType() const
Definition TypeBase.h:9187
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2293
bool isIncompleteArrayType() const
Definition TypeBase.h:8791
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
Definition Type.cpp:2359
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:8684
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:9094
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9344
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:2531
bool isVectorType() const
Definition TypeBase.h:8823
bool isRealFloatingType() const
Floating point categories.
Definition Type.cpp:2409
bool isFloatingType() const
Definition Type.cpp:2393
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9277
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:4239
unsigned getNumElements() const
Definition TypeBase.h:4254
QualType getElementType() const
Definition TypeBase.h:4253
A memory block, either on the stack or in the heap.
Definition InterpBlock.h:44
const Descriptor * getDescriptor() const
Returns the block's descriptor.
Definition InterpBlock.h:73
bool isDynamic() const
Definition InterpBlock.h:83
Wrapper around boolean types.
Definition Boolean.h:25
static Boolean from(T Value)
Definition Boolean.h:96
Pointer into the code segment.
Definition Source.h:30
const LangOptions & getLangOpts() const
Returns the language options.
Definition Context.cpp:430
OptPrimType classify(QualType T) const
Classifies a type.
Definition Context.cpp:464
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:79
bool initializingBlock(const Block *B) const
DynamicAllocator & getAllocator()
Definition InterpState.h:83
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:405
Pointer narrow() const
Restricts the scope of an array element pointer.
Definition Pointer.h:494
Pointer stripBaseCasts() const
Strip base casts from this Pointer.
Definition Pointer.h:998
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
Definition Pointer.h:471
bool isDummy() const
Checks if the pointer points to a dummy value.
Definition Pointer.h:762
int64_t getIndex() const
Returns the index into an array.
Definition Pointer.h:824
bool isActive() const
Checks if the object is active.
Definition Pointer.h:752
T & deref() const
Dereferences the pointer, if it's live.
Definition Pointer.h:875
unsigned getNumElems() const
Returns the number of elements.
Definition Pointer.h:808
Pointer getArray() const
Returns the parent array.
Definition Pointer.h:561
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition Pointer.h:636
bool isIntegralPointer() const
Definition Pointer.h:680
QualType getType() const
Returns the type of the innermost field.
Definition Pointer.h:574
bool isArrayElement() const
Checks if the pointer points to an array.
Definition Pointer.h:642
void initializeAllElements() const
Initialize all elements of a primitive array at once.
Definition Pointer.cpp:694
void initialize() const
Initializes a field.
Definition Pointer.h:920
bool isLive() const
Checks if the pointer is live.
Definition Pointer.h:522
bool inArray() const
Checks if the innermost field is an array.
Definition Pointer.h:618
T & elem(unsigned I) const
Dereferences the element at index I.
Definition Pointer.h:887
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition Pointer.h:559
std::string toDiagnosticString(const ASTContext &Ctx) const
Converts the pointer to a string usable in diagnostics.
Definition Pointer.cpp:538
bool isZero() const
Checks if the pointer is null.
Definition Pointer.h:508
bool isConstexprUnknown() const
Definition Pointer.h:898
bool isRoot() const
Pointer points directly to a block.
Definition Pointer.h:649
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition Pointer.h:536
static bool pointToSameBlock(const Pointer &A, const Pointer &B)
Checks if both given pointers point to the same block.
Definition Pointer.cpp:812
APValue toAPValue(const ASTContext &ASTCtx) const
Converts the pointer to an APValue.
Definition Pointer.cpp:173
bool isOnePastEnd() const
Checks if the index is one past end.
Definition Pointer.h:832
uint64_t getIntegerRepresentation() const
Definition Pointer.h:453
const FieldDecl * getField() const
Returns the field information.
Definition Pointer.h:693
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
Definition Pointer.h:501
bool isElementPastEnd() const
Checks if the pointer is an out-of-bounds element pointer.
Definition Pointer.h:854
bool isBlockPointer() const
Definition Pointer.h:679
const Block * block() const
Definition Pointer.h:814
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
Definition Pointer.h:564
PtrView view() const
Definition Pointer.h:461
bool isVirtualBaseClass() const
Definition Pointer.h:759
bool isBaseClass() const
Checks if a structure is a base class.
Definition Pointer.h:758
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
Definition Pointer.h:655
Lifetime getLifetime() const
Definition Pointer.h:957
bool isField() const
Checks if the item is a field in an object.
Definition Pointer.h:528
bool isElementInitialized(unsigned Index) const
Like isInitialized(), but for primitive arrays.
Definition Pointer.h:936
const Record * getRecord() const
Returns the record descriptor of a class.
Definition Pointer.h:685
Descriptor * createDescriptor(const DeclTy &D, PrimType T, const Type *SourceTy=nullptr, Descriptor::MetadataSize MDSize=std::nullopt, bool IsConst=false, bool IsTemporary=false, bool IsMutable=false, bool IsVolatile=false)
Creates a descriptor for a primitive type.
Definition Program.h:122
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:76
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
Definition State.cpp:66
Expr::EvalStatus & getEvalStatus() const
Definition State.h:91
DiagnosticBuilder report(SourceLocation Loc, diag::kind DiagId)
Directly reports a diagnostic message.
Definition State.cpp:77
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
Definition State.cpp:21
ASTContext & getASTContext() const
Definition State.h: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:44
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:119
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 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:1236
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:1872
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:3697
static bool interp__builtin_clz(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinOp)
static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinOp)
__builtin_is_aligned() __builtin_align_up() __builtin_align_down() The first parameter is either an i...
static bool interp__builtin_ia32_select_scalar(InterpState &S, const CallExpr *Call)
Scalar variant of AVX512 predicated select: Result[i] = (Mask bit 0) ?
static bool interp__builtin_ia32_addsub(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static bool popToUInt64(const InterpState &S, const Expr *E, uint64_t &Out)
static bool isOneByteCharacterType(QualType T)
Determine if T is a character type for which we guarantee that sizeof(T) == 1.
static bool convertDoubleToFloatStrict(APFloat Src, Floating &Dst, InterpState &S, const Expr *DiagExpr)
static unsigned computePointerOffset(const ASTContext &ASTCtx, const Pointer &Ptr)
Compute the byte offset of Ptr in the full declaration.
static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned ID)
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:878
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:1298
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:2274
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 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_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)
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
@ Result
The result type of a method or function.
Definition TypeBase.h:905
@ AK_Read
Definition State.h:29
OptionalUnsigned< unsigned > UnsignedOrNone
U cast(CodeGen::Address addr)
Definition Address.h:327
__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:640
Track what bits have been initialized to known values and which ones have indeterminate value.
T deref(Bytes Offset) const
Dereferences the value at the given offset.
std::unique_ptr< std::byte[]> Data
A quantity in bits.
A quantity in bytes.
size_t getQuantity() const
Describes a memory block created by an allocation site.
Definition Descriptor.h:123
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition Descriptor.h:260
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition Descriptor.h:274
QualType getElemQualType() const
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
Definition Descriptor.h:267
const ValueDecl * asValueDecl() const
Definition Descriptor.h:216
static constexpr unsigned MaxArrayElemBytes
Maximum number of bytes to be used for array elements.
Definition Descriptor.h:149
QualType getType() const
const Decl * asDecl() const
Definition Descriptor.h:212
static constexpr MetadataSize InlineDescMD
Definition Descriptor.h:145
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:265
const VarDecl * asVarDecl() const
Definition Descriptor.h:220
PrimType getPrimType() const
Definition Descriptor.h:242
bool isRecord() const
Checks if the descriptor is of a record.
Definition Descriptor.h:279
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition Descriptor.h:154
const Expr * asExpr() const
Definition Descriptor.h:213
bool isArray() const
Checks if the descriptor is of an array.
Definition Descriptor.h:277
Mapping from primitive types to their representation.
Definition PrimType.h:150
PtrView atField(unsigned Offset) const
Definition Pointer.h:264
const Descriptor * getFieldDesc() const
Definition Pointer.h:81
PtrView atIndex(unsigned Idx) const
Definition Pointer.h:200
void activate() const
Definition Pointer.cpp:734
PtrView narrow() const
Definition Pointer.h:91
T & elem(unsigned I) const
Definition Pointer.h:246
bool isInitialized() const
Definition Pointer.h:292
void initializeElement(unsigned Index) const
Definition Pointer.cpp:673
void initialize() const
Definition Pointer.cpp:652
bool isActive() const
Definition Pointer.h:46
bool isLive() const
Definition Pointer.h:44
T & deref() const
Definition Pointer.h:235