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