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