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