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