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