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