clang 22.0.0git
InterpBuiltin.cpp
Go to the documentation of this file.
1//===--- InterpBuiltin.cpp - Interpreter for the constexpr VM ---*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
9#include "Boolean.h"
10#include "EvalEmitter.h"
11#include "Interp.h"
13#include "PrimType.h"
14#include "clang/AST/OSLog.h"
19#include "llvm/ADT/StringExtras.h"
20#include "llvm/Support/ErrorHandling.h"
21#include "llvm/Support/SipHash.h"
22
23namespace clang {
24namespace interp {
25
26LLVM_ATTRIBUTE_UNUSED static bool isNoopBuiltin(unsigned ID) {
27 switch (ID) {
28 case Builtin::BIas_const:
29 case Builtin::BIforward:
30 case Builtin::BIforward_like:
31 case Builtin::BImove:
32 case Builtin::BImove_if_noexcept:
33 case Builtin::BIaddressof:
34 case Builtin::BI__addressof:
35 case Builtin::BI__builtin_addressof:
36 case Builtin::BI__builtin_launder:
37 return true;
38 default:
39 return false;
40 }
41 return false;
42}
43
44static void discard(InterpStack &Stk, PrimType T) {
45 TYPE_SWITCH(T, { Stk.discard<T>(); });
46}
47
49 INT_TYPE_SWITCH(T, return Stk.pop<T>().toAPSInt());
50}
51
52/// Pushes \p Val on the stack as the type given by \p QT.
53static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {
57 assert(T);
58
59 unsigned BitWidth = S.getASTContext().getTypeSize(QT);
60
61 if (T == PT_IntAPS) {
62 auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
63 Result.copy(Val);
65 return;
66 }
67
68 if (T == PT_IntAP) {
69 auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
70 Result.copy(Val);
72 return;
73 }
74
76 int64_t V = Val.getSExtValue();
77 INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });
78 } else {
80 uint64_t V = Val.getZExtValue();
81 INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });
82 }
83}
84
85template <typename T>
86static void pushInteger(InterpState &S, T Val, QualType QT) {
87 if constexpr (std::is_same_v<T, APInt>)
88 pushInteger(S, APSInt(Val, !std::is_signed_v<T>), QT);
89 else if constexpr (std::is_same_v<T, APSInt>)
90 pushInteger(S, Val, QT);
91 else
93 APSInt(APInt(sizeof(T) * 8, static_cast<uint64_t>(Val),
94 std::is_signed_v<T>),
95 !std::is_signed_v<T>),
96 QT);
97}
98
99static void assignInteger(InterpState &S, const Pointer &Dest, PrimType ValueT,
100 const APSInt &Value) {
101
102 if (ValueT == PT_IntAPS) {
103 Dest.deref<IntegralAP<true>>() =
104 S.allocAP<IntegralAP<true>>(Value.getBitWidth());
105 Dest.deref<IntegralAP<true>>().copy(Value);
106 } else if (ValueT == PT_IntAP) {
107 Dest.deref<IntegralAP<false>>() =
108 S.allocAP<IntegralAP<false>>(Value.getBitWidth());
109 Dest.deref<IntegralAP<false>>().copy(Value);
110 } else {
112 ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); });
113 }
114}
115
116static QualType getElemType(const Pointer &P) {
117 const Descriptor *Desc = P.getFieldDesc();
118 QualType T = Desc->getType();
119 if (Desc->isPrimitive())
120 return T;
121 if (T->isPointerType())
122 return T->getAs<PointerType>()->getPointeeType();
123 if (Desc->isArray())
124 return Desc->getElemQualType();
125 if (const auto *AT = T->getAsArrayTypeUnsafe())
126 return AT->getElementType();
127 return T;
128}
129
131 unsigned ID) {
132 if (!S.diagnosing())
133 return;
134
135 auto Loc = S.Current->getSource(OpPC);
136 if (S.getLangOpts().CPlusPlus11)
137 S.CCEDiag(Loc, diag::note_constexpr_invalid_function)
138 << /*isConstexpr=*/0 << /*isConstructor=*/0
140 else
141 S.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
142}
143
144static llvm::APSInt convertBoolVectorToInt(const Pointer &Val) {
145 assert(Val.getFieldDesc()->isPrimitiveArray() &&
147 "Not a boolean vector");
148 unsigned NumElems = Val.getNumElems();
149
150 // Each element is one bit, so create an integer with NumElts bits.
151 llvm::APSInt Result(NumElems, 0);
152 for (unsigned I = 0; I != NumElems; ++I) {
153 if (Val.elem<bool>(I))
154 Result.setBit(I);
155 }
156
157 return Result;
158}
159
161 const InterpFrame *Frame,
162 const CallExpr *Call) {
163 unsigned Depth = S.Current->getDepth();
164 auto isStdCall = [](const FunctionDecl *F) -> bool {
165 return F && F->isInStdNamespace() && F->getIdentifier() &&
166 F->getIdentifier()->isStr("is_constant_evaluated");
167 };
168 const InterpFrame *Caller = Frame->Caller;
169 // The current frame is the one for __builtin_is_constant_evaluated.
170 // The one above that, potentially the one for std::is_constant_evaluated().
172 S.getEvalStatus().Diag &&
173 (Depth == 0 || (Depth == 1 && isStdCall(Frame->getCallee())))) {
174 if (Caller && isStdCall(Frame->getCallee())) {
175 const Expr *E = Caller->getExpr(Caller->getRetPC());
176 S.report(E->getExprLoc(),
177 diag::warn_is_constant_evaluated_always_true_constexpr)
178 << "std::is_constant_evaluated" << E->getSourceRange();
179 } else {
180 S.report(Call->getExprLoc(),
181 diag::warn_is_constant_evaluated_always_true_constexpr)
182 << "__builtin_is_constant_evaluated" << Call->getSourceRange();
183 }
184 }
185
187 return true;
188}
189
190// __builtin_assume(int)
192 const InterpFrame *Frame,
193 const CallExpr *Call) {
194 assert(Call->getNumArgs() == 1);
195 discard(S.Stk, *S.getContext().classify(Call->getArg(0)));
196 return true;
197}
198
200 const InterpFrame *Frame,
201 const CallExpr *Call, unsigned ID) {
202 uint64_t Limit = ~static_cast<uint64_t>(0);
203 if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp ||
204 ID == Builtin::BIwcsncmp || ID == Builtin::BI__builtin_wcsncmp)
205 Limit = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)))
206 .getZExtValue();
207
208 const Pointer &B = S.Stk.pop<Pointer>();
209 const Pointer &A = S.Stk.pop<Pointer>();
210 if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp ||
211 ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp)
212 diagnoseNonConstexprBuiltin(S, OpPC, ID);
213
214 if (Limit == 0) {
215 pushInteger(S, 0, Call->getType());
216 return true;
217 }
218
219 if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))
220 return false;
221
222 if (A.isDummy() || B.isDummy())
223 return false;
224 if (!A.isBlockPointer() || !B.isBlockPointer())
225 return false;
226
227 bool IsWide = ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp ||
228 ID == Builtin::BI__builtin_wcscmp ||
229 ID == Builtin::BI__builtin_wcsncmp;
230 assert(A.getFieldDesc()->isPrimitiveArray());
231 assert(B.getFieldDesc()->isPrimitiveArray());
232
233 // Different element types shouldn't happen, but with casts they can.
235 return false;
236
237 PrimType ElemT = *S.getContext().classify(getElemType(A));
238
239 auto returnResult = [&](int V) -> bool {
240 pushInteger(S, V, Call->getType());
241 return true;
242 };
243
244 unsigned IndexA = A.getIndex();
245 unsigned IndexB = B.getIndex();
246 uint64_t Steps = 0;
247 for (;; ++IndexA, ++IndexB, ++Steps) {
248
249 if (Steps >= Limit)
250 break;
251 const Pointer &PA = A.atIndex(IndexA);
252 const Pointer &PB = B.atIndex(IndexB);
253 if (!CheckRange(S, OpPC, PA, AK_Read) ||
254 !CheckRange(S, OpPC, PB, AK_Read)) {
255 return false;
256 }
257
258 if (IsWide) {
259 INT_TYPE_SWITCH(ElemT, {
260 T CA = PA.deref<T>();
261 T CB = PB.deref<T>();
262 if (CA > CB)
263 return returnResult(1);
264 if (CA < CB)
265 return returnResult(-1);
266 if (CA.isZero() || CB.isZero())
267 return returnResult(0);
268 });
269 continue;
270 }
271
272 uint8_t CA = PA.deref<uint8_t>();
273 uint8_t CB = PB.deref<uint8_t>();
274
275 if (CA > CB)
276 return returnResult(1);
277 if (CA < CB)
278 return returnResult(-1);
279 if (CA == 0 || CB == 0)
280 return returnResult(0);
281 }
282
283 return returnResult(0);
284}
285
287 const InterpFrame *Frame,
288 const CallExpr *Call, unsigned ID) {
289 const Pointer &StrPtr = S.Stk.pop<Pointer>();
290
291 if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen)
292 diagnoseNonConstexprBuiltin(S, OpPC, ID);
293
294 if (!CheckArray(S, OpPC, StrPtr))
295 return false;
296
297 if (!CheckLive(S, OpPC, StrPtr, AK_Read))
298 return false;
299
300 if (!CheckDummy(S, OpPC, StrPtr.block(), AK_Read))
301 return false;
302
303 if (!StrPtr.getFieldDesc()->isPrimitiveArray())
304 return false;
305
306 assert(StrPtr.getFieldDesc()->isPrimitiveArray());
307 unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize();
308
309 if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) {
310 [[maybe_unused]] const ASTContext &AC = S.getASTContext();
311 assert(ElemSize == AC.getTypeSizeInChars(AC.getWCharType()).getQuantity());
312 }
313
314 size_t Len = 0;
315 for (size_t I = StrPtr.getIndex();; ++I, ++Len) {
316 const Pointer &ElemPtr = StrPtr.atIndex(I);
317
318 if (!CheckRange(S, OpPC, ElemPtr, AK_Read))
319 return false;
320
321 uint32_t Val;
322 switch (ElemSize) {
323 case 1:
324 Val = ElemPtr.deref<uint8_t>();
325 break;
326 case 2:
327 Val = ElemPtr.deref<uint16_t>();
328 break;
329 case 4:
330 Val = ElemPtr.deref<uint32_t>();
331 break;
332 default:
333 llvm_unreachable("Unsupported char size");
334 }
335 if (Val == 0)
336 break;
337 }
338
339 pushInteger(S, Len, Call->getType());
340
341 return true;
342}
343
345 const InterpFrame *Frame, const CallExpr *Call,
346 bool Signaling) {
347 const Pointer &Arg = S.Stk.pop<Pointer>();
348
349 if (!CheckLoad(S, OpPC, Arg))
350 return false;
351
352 assert(Arg.getFieldDesc()->isPrimitiveArray());
353
354 // Convert the given string to an integer using StringRef's API.
355 llvm::APInt Fill;
356 std::string Str;
357 assert(Arg.getNumElems() >= 1);
358 for (unsigned I = 0;; ++I) {
359 const Pointer &Elem = Arg.atIndex(I);
360
361 if (!CheckLoad(S, OpPC, Elem))
362 return false;
363
364 if (Elem.deref<int8_t>() == 0)
365 break;
366
367 Str += Elem.deref<char>();
368 }
369
370 // Treat empty strings as if they were zero.
371 if (Str.empty())
372 Fill = llvm::APInt(32, 0);
373 else if (StringRef(Str).getAsInteger(0, Fill))
374 return false;
375
376 const llvm::fltSemantics &TargetSemantics =
378 Call->getDirectCallee()->getReturnType());
379
380 Floating Result = S.allocFloat(TargetSemantics);
382 if (Signaling)
383 Result.copy(
384 llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
385 else
386 Result.copy(
387 llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
388 } else {
389 // Prior to IEEE 754-2008, architectures were allowed to choose whether
390 // the first bit of their significand was set for qNaN or sNaN. MIPS chose
391 // a different encoding to what became a standard in 2008, and for pre-
392 // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as
393 // sNaN. This is now known as "legacy NaN" encoding.
394 if (Signaling)
395 Result.copy(
396 llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
397 else
398 Result.copy(
399 llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
400 }
401
403 return true;
404}
405
407 const InterpFrame *Frame,
408 const CallExpr *Call) {
409 const llvm::fltSemantics &TargetSemantics =
411 Call->getDirectCallee()->getReturnType());
412
413 Floating Result = S.allocFloat(TargetSemantics);
414 Result.copy(APFloat::getInf(TargetSemantics));
416 return true;
417}
418
420 const InterpFrame *Frame) {
421 const Floating &Arg2 = S.Stk.pop<Floating>();
422 const Floating &Arg1 = S.Stk.pop<Floating>();
423 Floating Result = S.allocFloat(Arg1.getSemantics());
424
425 APFloat Copy = Arg1.getAPFloat();
426 Copy.copySign(Arg2.getAPFloat());
427 Result.copy(Copy);
429
430 return true;
431}
432
434 const InterpFrame *Frame, bool IsNumBuiltin) {
435 const Floating &RHS = S.Stk.pop<Floating>();
436 const Floating &LHS = S.Stk.pop<Floating>();
437 Floating Result = S.allocFloat(LHS.getSemantics());
438
439 if (IsNumBuiltin)
440 Result.copy(llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()));
441 else
442 Result.copy(minnum(LHS.getAPFloat(), RHS.getAPFloat()));
444 return true;
445}
446
448 const InterpFrame *Frame, bool IsNumBuiltin) {
449 const Floating &RHS = S.Stk.pop<Floating>();
450 const Floating &LHS = S.Stk.pop<Floating>();
451 Floating Result = S.allocFloat(LHS.getSemantics());
452
453 if (IsNumBuiltin)
454 Result.copy(llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()));
455 else
456 Result.copy(maxnum(LHS.getAPFloat(), RHS.getAPFloat()));
458 return true;
459}
460
461/// Defined as __builtin_isnan(...), to accommodate the fact that it can
462/// take a float, double, long double, etc.
463/// But for us, that's all a Floating anyway.
465 const InterpFrame *Frame,
466 const CallExpr *Call) {
467 const Floating &Arg = S.Stk.pop<Floating>();
468
469 pushInteger(S, Arg.isNan(), Call->getType());
470 return true;
471}
472
474 const InterpFrame *Frame,
475 const CallExpr *Call) {
476 const Floating &Arg = S.Stk.pop<Floating>();
477
478 pushInteger(S, Arg.isSignaling(), Call->getType());
479 return true;
480}
481
483 const InterpFrame *Frame, bool CheckSign,
484 const CallExpr *Call) {
485 const Floating &Arg = S.Stk.pop<Floating>();
486 APFloat F = Arg.getAPFloat();
487 bool IsInf = F.isInfinity();
488
489 if (CheckSign)
490 pushInteger(S, IsInf ? (F.isNegative() ? -1 : 1) : 0, Call->getType());
491 else
492 pushInteger(S, IsInf, Call->getType());
493 return true;
494}
495
497 const InterpFrame *Frame,
498 const CallExpr *Call) {
499 const Floating &Arg = S.Stk.pop<Floating>();
500
501 pushInteger(S, Arg.isFinite(), Call->getType());
502 return true;
503}
504
506 const InterpFrame *Frame,
507 const CallExpr *Call) {
508 const Floating &Arg = S.Stk.pop<Floating>();
509
510 pushInteger(S, Arg.isNormal(), Call->getType());
511 return true;
512}
513
515 const InterpFrame *Frame,
516 const CallExpr *Call) {
517 const Floating &Arg = S.Stk.pop<Floating>();
518
519 pushInteger(S, Arg.isDenormal(), Call->getType());
520 return true;
521}
522
524 const InterpFrame *Frame,
525 const CallExpr *Call) {
526 const Floating &Arg = S.Stk.pop<Floating>();
527
528 pushInteger(S, Arg.isZero(), Call->getType());
529 return true;
530}
531
533 const InterpFrame *Frame,
534 const CallExpr *Call) {
535 const Floating &Arg = S.Stk.pop<Floating>();
536
537 pushInteger(S, Arg.isNegative(), Call->getType());
538 return true;
539}
540
542 const CallExpr *Call, unsigned ID) {
543 const Floating &RHS = S.Stk.pop<Floating>();
544 const Floating &LHS = S.Stk.pop<Floating>();
545
547 S,
548 [&] {
549 switch (ID) {
550 case Builtin::BI__builtin_isgreater:
551 return LHS > RHS;
552 case Builtin::BI__builtin_isgreaterequal:
553 return LHS >= RHS;
554 case Builtin::BI__builtin_isless:
555 return LHS < RHS;
556 case Builtin::BI__builtin_islessequal:
557 return LHS <= RHS;
558 case Builtin::BI__builtin_islessgreater: {
559 ComparisonCategoryResult cmp = LHS.compare(RHS);
560 return cmp == ComparisonCategoryResult::Less ||
562 }
563 case Builtin::BI__builtin_isunordered:
565 default:
566 llvm_unreachable("Unexpected builtin ID: Should be a floating point "
567 "comparison function");
568 }
569 }(),
570 Call->getType());
571 return true;
572}
573
574/// First parameter to __builtin_isfpclass is the floating value, the
575/// second one is an integral value.
577 const InterpFrame *Frame,
578 const CallExpr *Call) {
579 PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType());
580 APSInt FPClassArg = popToAPSInt(S.Stk, FPClassArgT);
581 const Floating &F = S.Stk.pop<Floating>();
582
583 int32_t Result = static_cast<int32_t>(
584 (F.classify() & std::move(FPClassArg)).getZExtValue());
585 pushInteger(S, Result, Call->getType());
586
587 return true;
588}
589
590/// Five int values followed by one floating value.
591/// __builtin_fpclassify(int, int, int, int, int, float)
593 const InterpFrame *Frame,
594 const CallExpr *Call) {
595 const Floating &Val = S.Stk.pop<Floating>();
596
597 PrimType IntT = *S.getContext().classify(Call->getArg(0));
598 APSInt Values[5];
599 for (unsigned I = 0; I != 5; ++I)
600 Values[4 - I] = popToAPSInt(S.Stk, IntT);
601
602 unsigned Index;
603 switch (Val.getCategory()) {
604 case APFloat::fcNaN:
605 Index = 0;
606 break;
607 case APFloat::fcInfinity:
608 Index = 1;
609 break;
610 case APFloat::fcNormal:
611 Index = Val.isDenormal() ? 3 : 2;
612 break;
613 case APFloat::fcZero:
614 Index = 4;
615 break;
616 }
617
618 // The last argument is first on the stack.
619 assert(Index <= 4);
620
621 pushInteger(S, Values[Index], Call->getType());
622 return true;
623}
624
625static inline Floating abs(InterpState &S, const Floating &In) {
626 if (!In.isNegative())
627 return In;
628
629 Floating Output = S.allocFloat(In.getSemantics());
630 APFloat New = In.getAPFloat();
631 New.changeSign();
632 Output.copy(New);
633 return Output;
634}
635
636// The C standard says "fabs raises no floating-point exceptions,
637// even if x is a signaling NaN. The returned value is independent of
638// the current rounding direction mode." Therefore constant folding can
639// proceed without regard to the floating point settings.
640// Reference, WG14 N2478 F.10.4.3
642 const InterpFrame *Frame) {
643 const Floating &Val = S.Stk.pop<Floating>();
644 S.Stk.push<Floating>(abs(S, Val));
645 return true;
646}
647
649 const InterpFrame *Frame,
650 const CallExpr *Call) {
651 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
652 APSInt Val = popToAPSInt(S.Stk, ArgT);
653 if (Val ==
654 APSInt(APInt::getSignedMinValue(Val.getBitWidth()), /*IsUnsigned=*/false))
655 return false;
656 if (Val.isNegative())
657 Val.negate();
658 pushInteger(S, Val, Call->getType());
659 return true;
660}
661
663 const InterpFrame *Frame,
664 const CallExpr *Call) {
665 APSInt Val;
666 if (Call->getArg(0)->getType()->isExtVectorBoolType()) {
667 const Pointer &Arg = S.Stk.pop<Pointer>();
668 Val = convertBoolVectorToInt(Arg);
669 } else {
670 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
671 Val = popToAPSInt(S.Stk, ArgT);
672 }
673 pushInteger(S, Val.popcount(), Call->getType());
674 return true;
675}
676
678 const InterpFrame *Frame,
679 const CallExpr *Call) {
680 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
681 APSInt Val = popToAPSInt(S.Stk, ArgT);
682 pushInteger(S, Val.popcount() % 2, Call->getType());
683 return true;
684}
685
687 const InterpFrame *Frame,
688 const CallExpr *Call) {
689 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
690 APSInt Val = popToAPSInt(S.Stk, ArgT);
691 pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType());
692 return true;
693}
694
696 const InterpFrame *Frame,
697 const CallExpr *Call) {
698 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
699 APSInt Val = popToAPSInt(S.Stk, ArgT);
700 pushInteger(S, Val.reverseBits(), Call->getType());
701 return true;
702}
703
705 const InterpFrame *Frame,
706 const CallExpr *Call) {
707 // This is an unevaluated call, so there are no arguments on the stack.
708 assert(Call->getNumArgs() == 1);
709 const Expr *Arg = Call->getArg(0);
710
711 GCCTypeClass ResultClass =
713 int32_t ReturnVal = static_cast<int32_t>(ResultClass);
714 pushInteger(S, ReturnVal, Call->getType());
715 return true;
716}
717
718// __builtin_expect(long, long)
719// __builtin_expect_with_probability(long, long, double)
721 const InterpFrame *Frame,
722 const CallExpr *Call) {
723 // The return value is simply the value of the first parameter.
724 // We ignore the probability.
725 unsigned NumArgs = Call->getNumArgs();
726 assert(NumArgs == 2 || NumArgs == 3);
727
728 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
729 if (NumArgs == 3)
730 S.Stk.discard<Floating>();
731 discard(S.Stk, ArgT);
732
733 APSInt Val = popToAPSInt(S.Stk, ArgT);
734 pushInteger(S, Val, Call->getType());
735 return true;
736}
737
738/// rotateleft(value, amount)
740 const InterpFrame *Frame,
741 const CallExpr *Call, bool Right) {
742 PrimType AmountT = *S.getContext().classify(Call->getArg(1)->getType());
743 PrimType ValueT = *S.getContext().classify(Call->getArg(0)->getType());
744
745 APSInt Amount = popToAPSInt(S.Stk, AmountT);
746 APSInt Value = popToAPSInt(S.Stk, ValueT);
747
749 if (Right)
750 Result = APSInt(Value.rotr(Amount.urem(Value.getBitWidth())),
751 /*IsUnsigned=*/true);
752 else // Left.
753 Result = APSInt(Value.rotl(Amount.urem(Value.getBitWidth())),
754 /*IsUnsigned=*/true);
755
756 pushInteger(S, Result, Call->getType());
757 return true;
758}
759
761 const InterpFrame *Frame,
762 const CallExpr *Call) {
763 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
764 APSInt Value = popToAPSInt(S.Stk, ArgT);
765
766 uint64_t N = Value.countr_zero();
767 pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType());
768 return true;
769}
770
772 const InterpFrame *Frame,
773 const CallExpr *Call) {
774#ifndef NDEBUG
775 assert(Call->getArg(0)->isLValue());
776 PrimType PtrT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr);
777 assert(PtrT == PT_Ptr &&
778 "Unsupported pointer type passed to __builtin_addressof()");
779#endif
780 return true;
781}
782
784 const InterpFrame *Frame,
785 const CallExpr *Call) {
786 return Call->getDirectCallee()->isConstexpr();
787}
788
790 const InterpFrame *Frame,
791 const CallExpr *Call) {
792 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
793 APSInt Arg = popToAPSInt(S.Stk, ArgT);
794
796 Arg.getZExtValue());
797 pushInteger(S, Result, Call->getType());
798 return true;
799}
800
801// Two integral values followed by a pointer (lhs, rhs, resultOut)
803 const CallExpr *Call,
804 unsigned BuiltinOp) {
805 const Pointer &ResultPtr = S.Stk.pop<Pointer>();
806 if (ResultPtr.isDummy())
807 return false;
808
809 PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
810 PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());
811 APSInt RHS = popToAPSInt(S.Stk, RHST);
812 APSInt LHS = popToAPSInt(S.Stk, LHST);
813 QualType ResultType = Call->getArg(2)->getType()->getPointeeType();
814 PrimType ResultT = *S.getContext().classify(ResultType);
815 bool Overflow;
816
818 if (BuiltinOp == Builtin::BI__builtin_add_overflow ||
819 BuiltinOp == Builtin::BI__builtin_sub_overflow ||
820 BuiltinOp == Builtin::BI__builtin_mul_overflow) {
821 bool IsSigned = LHS.isSigned() || RHS.isSigned() ||
823 bool AllSigned = LHS.isSigned() && RHS.isSigned() &&
825 uint64_t LHSSize = LHS.getBitWidth();
826 uint64_t RHSSize = RHS.getBitWidth();
827 uint64_t ResultSize = S.getASTContext().getTypeSize(ResultType);
828 uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize);
829
830 // Add an additional bit if the signedness isn't uniformly agreed to. We
831 // could do this ONLY if there is a signed and an unsigned that both have
832 // MaxBits, but the code to check that is pretty nasty. The issue will be
833 // caught in the shrink-to-result later anyway.
834 if (IsSigned && !AllSigned)
835 ++MaxBits;
836
837 LHS = APSInt(LHS.extOrTrunc(MaxBits), !IsSigned);
838 RHS = APSInt(RHS.extOrTrunc(MaxBits), !IsSigned);
839 Result = APSInt(MaxBits, !IsSigned);
840 }
841
842 // Find largest int.
843 switch (BuiltinOp) {
844 default:
845 llvm_unreachable("Invalid value for BuiltinOp");
846 case Builtin::BI__builtin_add_overflow:
847 case Builtin::BI__builtin_sadd_overflow:
848 case Builtin::BI__builtin_saddl_overflow:
849 case Builtin::BI__builtin_saddll_overflow:
850 case Builtin::BI__builtin_uadd_overflow:
851 case Builtin::BI__builtin_uaddl_overflow:
852 case Builtin::BI__builtin_uaddll_overflow:
853 Result = LHS.isSigned() ? LHS.sadd_ov(RHS, Overflow)
854 : LHS.uadd_ov(RHS, Overflow);
855 break;
856 case Builtin::BI__builtin_sub_overflow:
857 case Builtin::BI__builtin_ssub_overflow:
858 case Builtin::BI__builtin_ssubl_overflow:
859 case Builtin::BI__builtin_ssubll_overflow:
860 case Builtin::BI__builtin_usub_overflow:
861 case Builtin::BI__builtin_usubl_overflow:
862 case Builtin::BI__builtin_usubll_overflow:
863 Result = LHS.isSigned() ? LHS.ssub_ov(RHS, Overflow)
864 : LHS.usub_ov(RHS, Overflow);
865 break;
866 case Builtin::BI__builtin_mul_overflow:
867 case Builtin::BI__builtin_smul_overflow:
868 case Builtin::BI__builtin_smull_overflow:
869 case Builtin::BI__builtin_smulll_overflow:
870 case Builtin::BI__builtin_umul_overflow:
871 case Builtin::BI__builtin_umull_overflow:
872 case Builtin::BI__builtin_umulll_overflow:
873 Result = LHS.isSigned() ? LHS.smul_ov(RHS, Overflow)
874 : LHS.umul_ov(RHS, Overflow);
875 break;
876 }
877
878 // In the case where multiple sizes are allowed, truncate and see if
879 // the values are the same.
880 if (BuiltinOp == Builtin::BI__builtin_add_overflow ||
881 BuiltinOp == Builtin::BI__builtin_sub_overflow ||
882 BuiltinOp == Builtin::BI__builtin_mul_overflow) {
883 // APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead,
884 // since it will give us the behavior of a TruncOrSelf in the case where
885 // its parameter <= its size. We previously set Result to be at least the
886 // type-size of the result, so getTypeSize(ResultType) <= Resu
887 APSInt Temp = Result.extOrTrunc(S.getASTContext().getTypeSize(ResultType));
888 Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType());
889
890 if (!APSInt::isSameValue(Temp, Result))
891 Overflow = true;
892 Result = std::move(Temp);
893 }
894
895 // Write Result to ResultPtr and put Overflow on the stack.
896 assignInteger(S, ResultPtr, ResultT, Result);
897 if (ResultPtr.canBeInitialized())
898 ResultPtr.initialize();
899
900 assert(Call->getDirectCallee()->getReturnType()->isBooleanType());
901 S.Stk.push<Boolean>(Overflow);
902 return true;
903}
904
905/// Three integral values followed by a pointer (lhs, rhs, carry, carryOut).
907 const InterpFrame *Frame,
908 const CallExpr *Call, unsigned BuiltinOp) {
909 const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();
910 PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());
911 PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
912 APSInt CarryIn = popToAPSInt(S.Stk, LHST);
913 APSInt RHS = popToAPSInt(S.Stk, RHST);
914 APSInt LHS = popToAPSInt(S.Stk, LHST);
915
916 if (CarryOutPtr.isDummy())
917 return false;
918
919 APSInt CarryOut;
920
922 // Copy the number of bits and sign.
923 Result = LHS;
924 CarryOut = LHS;
925
926 bool FirstOverflowed = false;
927 bool SecondOverflowed = false;
928 switch (BuiltinOp) {
929 default:
930 llvm_unreachable("Invalid value for BuiltinOp");
931 case Builtin::BI__builtin_addcb:
932 case Builtin::BI__builtin_addcs:
933 case Builtin::BI__builtin_addc:
934 case Builtin::BI__builtin_addcl:
935 case Builtin::BI__builtin_addcll:
936 Result =
937 LHS.uadd_ov(RHS, FirstOverflowed).uadd_ov(CarryIn, SecondOverflowed);
938 break;
939 case Builtin::BI__builtin_subcb:
940 case Builtin::BI__builtin_subcs:
941 case Builtin::BI__builtin_subc:
942 case Builtin::BI__builtin_subcl:
943 case Builtin::BI__builtin_subcll:
944 Result =
945 LHS.usub_ov(RHS, FirstOverflowed).usub_ov(CarryIn, SecondOverflowed);
946 break;
947 }
948 // It is possible for both overflows to happen but CGBuiltin uses an OR so
949 // this is consistent.
950 CarryOut = (uint64_t)(FirstOverflowed | SecondOverflowed);
951
952 QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
953 PrimType CarryOutT = *S.getContext().classify(CarryOutType);
954 assignInteger(S, CarryOutPtr, CarryOutT, CarryOut);
955 CarryOutPtr.initialize();
956
957 assert(Call->getType() == Call->getArg(0)->getType());
958 pushInteger(S, Result, Call->getType());
959 return true;
960}
961
963 const InterpFrame *Frame, const CallExpr *Call,
964 unsigned BuiltinOp) {
965
966 std::optional<APSInt> Fallback;
967 if (BuiltinOp == Builtin::BI__builtin_clzg && Call->getNumArgs() == 2) {
968 PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
969 Fallback = popToAPSInt(S.Stk, FallbackT);
970 }
971 APSInt Val;
972 if (Call->getArg(0)->getType()->isExtVectorBoolType()) {
973 const Pointer &Arg = S.Stk.pop<Pointer>();
974 Val = convertBoolVectorToInt(Arg);
975 } else {
976 PrimType ValT = *S.getContext().classify(Call->getArg(0));
977 Val = popToAPSInt(S.Stk, ValT);
978 }
979
980 // When the argument is 0, the result of GCC builtins is undefined, whereas
981 // for Microsoft intrinsics, the result is the bit-width of the argument.
982 bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&
983 BuiltinOp != Builtin::BI__lzcnt &&
984 BuiltinOp != Builtin::BI__lzcnt64;
985
986 if (Val == 0) {
987 if (Fallback) {
988 pushInteger(S, *Fallback, Call->getType());
989 return true;
990 }
991
992 if (ZeroIsUndefined)
993 return false;
994 }
995
996 pushInteger(S, Val.countl_zero(), Call->getType());
997 return true;
998}
999
1001 const InterpFrame *Frame, const CallExpr *Call,
1002 unsigned BuiltinID) {
1003 std::optional<APSInt> Fallback;
1004 if (BuiltinID == Builtin::BI__builtin_ctzg && Call->getNumArgs() == 2) {
1005 PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
1006 Fallback = popToAPSInt(S.Stk, FallbackT);
1007 }
1008 APSInt Val;
1009 if (Call->getArg(0)->getType()->isExtVectorBoolType()) {
1010 const Pointer &Arg = S.Stk.pop<Pointer>();
1011 Val = convertBoolVectorToInt(Arg);
1012 } else {
1013 PrimType ValT = *S.getContext().classify(Call->getArg(0));
1014 Val = popToAPSInt(S.Stk, ValT);
1015 }
1016
1017 if (Val == 0) {
1018 if (Fallback) {
1019 pushInteger(S, *Fallback, Call->getType());
1020 return true;
1021 }
1022 return false;
1023 }
1024
1025 pushInteger(S, Val.countr_zero(), Call->getType());
1026 return true;
1027}
1028
1030 const InterpFrame *Frame,
1031 const CallExpr *Call) {
1032 PrimType ReturnT = *S.getContext().classify(Call->getType());
1033 PrimType ValT = *S.getContext().classify(Call->getArg(0));
1034 const APSInt &Val = popToAPSInt(S.Stk, ValT);
1035 assert(Val.getActiveBits() <= 64);
1036
1037 INT_TYPE_SWITCH(ReturnT,
1038 { S.Stk.push<T>(T::from(Val.byteSwap().getZExtValue())); });
1039 return true;
1040}
1041
1042/// bool __atomic_always_lock_free(size_t, void const volatile*)
1043/// bool __atomic_is_lock_free(size_t, void const volatile*)
1045 const InterpFrame *Frame,
1046 const CallExpr *Call,
1047 unsigned BuiltinOp) {
1048 auto returnBool = [&S](bool Value) -> bool {
1049 S.Stk.push<Boolean>(Value);
1050 return true;
1051 };
1052
1053 PrimType ValT = *S.getContext().classify(Call->getArg(0));
1054 const Pointer &Ptr = S.Stk.pop<Pointer>();
1055 const APSInt &SizeVal = popToAPSInt(S.Stk, ValT);
1056
1057 // For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power
1058 // of two less than or equal to the maximum inline atomic width, we know it
1059 // is lock-free. If the size isn't a power of two, or greater than the
1060 // maximum alignment where we promote atomics, we know it is not lock-free
1061 // (at least not in the sense of atomic_is_lock_free). Otherwise,
1062 // the answer can only be determined at runtime; for example, 16-byte
1063 // atomics have lock-free implementations on some, but not all,
1064 // x86-64 processors.
1065
1066 // Check power-of-two.
1067 CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());
1068 if (Size.isPowerOfTwo()) {
1069 // Check against inlining width.
1070 unsigned InlineWidthBits =
1072 if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits)) {
1073
1074 // OK, we will inline appropriately-aligned operations of this size,
1075 // and _Atomic(T) is appropriately-aligned.
1076 if (Size == CharUnits::One())
1077 return returnBool(true);
1078
1079 // Same for null pointers.
1080 assert(BuiltinOp != Builtin::BI__c11_atomic_is_lock_free);
1081 if (Ptr.isZero())
1082 return returnBool(true);
1083
1084 if (Ptr.isIntegralPointer()) {
1085 uint64_t IntVal = Ptr.getIntegerRepresentation();
1086 if (APSInt(APInt(64, IntVal, false), true).isAligned(Size.getAsAlign()))
1087 return returnBool(true);
1088 }
1089
1090 const Expr *PtrArg = Call->getArg(1);
1091 // Otherwise, check if the type's alignment against Size.
1092 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(PtrArg)) {
1093 // Drop the potential implicit-cast to 'const volatile void*', getting
1094 // the underlying type.
1095 if (ICE->getCastKind() == CK_BitCast)
1096 PtrArg = ICE->getSubExpr();
1097 }
1098
1099 if (const auto *PtrTy = PtrArg->getType()->getAs<PointerType>()) {
1100 QualType PointeeType = PtrTy->getPointeeType();
1101 if (!PointeeType->isIncompleteType() &&
1102 S.getASTContext().getTypeAlignInChars(PointeeType) >= Size) {
1103 // OK, we will inline operations on this object.
1104 return returnBool(true);
1105 }
1106 }
1107 }
1108 }
1109
1110 if (BuiltinOp == Builtin::BI__atomic_always_lock_free)
1111 return returnBool(false);
1112
1113 return false;
1114}
1115
1116/// bool __c11_atomic_is_lock_free(size_t)
1118 CodePtr OpPC,
1119 const InterpFrame *Frame,
1120 const CallExpr *Call) {
1121 PrimType ValT = *S.getContext().classify(Call->getArg(0));
1122 const APSInt &SizeVal = popToAPSInt(S.Stk, ValT);
1123
1124 auto returnBool = [&S](bool Value) -> bool {
1125 S.Stk.push<Boolean>(Value);
1126 return true;
1127 };
1128
1129 CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());
1130 if (Size.isPowerOfTwo()) {
1131 // Check against inlining width.
1132 unsigned InlineWidthBits =
1134 if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits))
1135 return returnBool(true);
1136 }
1137
1138 return false; // returnBool(false);
1139}
1140
1141/// __builtin_complex(Float A, float B);
1143 const InterpFrame *Frame,
1144 const CallExpr *Call) {
1145 const Floating &Arg2 = S.Stk.pop<Floating>();
1146 const Floating &Arg1 = S.Stk.pop<Floating>();
1147 Pointer &Result = S.Stk.peek<Pointer>();
1148
1149 Result.elem<Floating>(0) = Arg1;
1150 Result.elem<Floating>(1) = Arg2;
1151 Result.initializeAllElements();
1152
1153 return true;
1154}
1155
1156/// __builtin_is_aligned()
1157/// __builtin_align_up()
1158/// __builtin_align_down()
1159/// The first parameter is either an integer or a pointer.
1160/// The second parameter is the requested alignment as an integer.
1162 const InterpFrame *Frame,
1163 const CallExpr *Call,
1164 unsigned BuiltinOp) {
1165 PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1));
1166 const APSInt &Alignment = popToAPSInt(S.Stk, AlignmentT);
1167
1168 if (Alignment < 0 || !Alignment.isPowerOf2()) {
1169 S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment;
1170 return false;
1171 }
1172 unsigned SrcWidth = S.getASTContext().getIntWidth(Call->getArg(0)->getType());
1173 APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1));
1174 if (APSInt::compareValues(Alignment, MaxValue) > 0) {
1175 S.FFDiag(Call, diag::note_constexpr_alignment_too_big)
1176 << MaxValue << Call->getArg(0)->getType() << Alignment;
1177 return false;
1178 }
1179
1180 // The first parameter is either an integer or a pointer (but not a function
1181 // pointer).
1182 PrimType FirstArgT = *S.Ctx.classify(Call->getArg(0));
1183
1184 if (isIntegralType(FirstArgT)) {
1185 const APSInt &Src = popToAPSInt(S.Stk, FirstArgT);
1186 APInt AlignMinusOne = Alignment.extOrTrunc(Src.getBitWidth()) - 1;
1187 if (BuiltinOp == Builtin::BI__builtin_align_up) {
1188 APSInt AlignedVal =
1189 APSInt((Src + AlignMinusOne) & ~AlignMinusOne, Src.isUnsigned());
1190 pushInteger(S, AlignedVal, Call->getType());
1191 } else if (BuiltinOp == Builtin::BI__builtin_align_down) {
1192 APSInt AlignedVal = APSInt(Src & ~AlignMinusOne, Src.isUnsigned());
1193 pushInteger(S, AlignedVal, Call->getType());
1194 } else {
1195 assert(*S.Ctx.classify(Call->getType()) == PT_Bool);
1196 S.Stk.push<Boolean>((Src & AlignMinusOne) == 0);
1197 }
1198 return true;
1199 }
1200
1201 assert(FirstArgT == PT_Ptr);
1202 const Pointer &Ptr = S.Stk.pop<Pointer>();
1203
1204 unsigned PtrOffset = Ptr.getByteOffset();
1205 PtrOffset = Ptr.getIndex();
1206 CharUnits BaseAlignment =
1208 CharUnits PtrAlign =
1209 BaseAlignment.alignmentAtOffset(CharUnits::fromQuantity(PtrOffset));
1210
1211 if (BuiltinOp == Builtin::BI__builtin_is_aligned) {
1212 if (PtrAlign.getQuantity() >= Alignment) {
1213 S.Stk.push<Boolean>(true);
1214 return true;
1215 }
1216 // If the alignment is not known to be sufficient, some cases could still
1217 // be aligned at run time. However, if the requested alignment is less or
1218 // equal to the base alignment and the offset is not aligned, we know that
1219 // the run-time value can never be aligned.
1220 if (BaseAlignment.getQuantity() >= Alignment &&
1221 PtrAlign.getQuantity() < Alignment) {
1222 S.Stk.push<Boolean>(false);
1223 return true;
1224 }
1225
1226 S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_compute)
1227 << Alignment;
1228 return false;
1229 }
1230
1231 assert(BuiltinOp == Builtin::BI__builtin_align_down ||
1232 BuiltinOp == Builtin::BI__builtin_align_up);
1233
1234 // For align_up/align_down, we can return the same value if the alignment
1235 // is known to be greater or equal to the requested value.
1236 if (PtrAlign.getQuantity() >= Alignment) {
1237 S.Stk.push<Pointer>(Ptr);
1238 return true;
1239 }
1240
1241 // The alignment could be greater than the minimum at run-time, so we cannot
1242 // infer much about the resulting pointer value. One case is possible:
1243 // For `_Alignas(32) char buf[N]; __builtin_align_down(&buf[idx], 32)` we
1244 // can infer the correct index if the requested alignment is smaller than
1245 // the base alignment so we can perform the computation on the offset.
1246 if (BaseAlignment.getQuantity() >= Alignment) {
1247 assert(Alignment.getBitWidth() <= 64 &&
1248 "Cannot handle > 64-bit address-space");
1249 uint64_t Alignment64 = Alignment.getZExtValue();
1250 CharUnits NewOffset =
1251 CharUnits::fromQuantity(BuiltinOp == Builtin::BI__builtin_align_down
1252 ? llvm::alignDown(PtrOffset, Alignment64)
1253 : llvm::alignTo(PtrOffset, Alignment64));
1254
1255 S.Stk.push<Pointer>(Ptr.atIndex(NewOffset.getQuantity()));
1256 return true;
1257 }
1258
1259 // Otherwise, we cannot constant-evaluate the result.
1260 S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_adjust) << Alignment;
1261 return false;
1262}
1263
1264/// __builtin_assume_aligned(Ptr, Alignment[, ExtraOffset])
1266 const InterpFrame *Frame,
1267 const CallExpr *Call) {
1268 assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3);
1269
1270 std::optional<APSInt> ExtraOffset;
1271 if (Call->getNumArgs() == 3)
1272 ExtraOffset = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(2)));
1273
1274 APSInt Alignment = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)));
1275 const Pointer &Ptr = S.Stk.pop<Pointer>();
1276
1277 CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue());
1278
1279 // If there is a base object, then it must have the correct alignment.
1280 if (Ptr.isBlockPointer()) {
1281 CharUnits BaseAlignment;
1282 if (const auto *VD = Ptr.getDeclDesc()->asValueDecl())
1283 BaseAlignment = S.getASTContext().getDeclAlign(VD);
1284 else if (const auto *E = Ptr.getDeclDesc()->asExpr())
1285 BaseAlignment = GetAlignOfExpr(S.getASTContext(), E, UETT_AlignOf);
1286
1287 if (BaseAlignment < Align) {
1288 S.CCEDiag(Call->getArg(0),
1289 diag::note_constexpr_baa_insufficient_alignment)
1290 << 0 << BaseAlignment.getQuantity() << Align.getQuantity();
1291 return false;
1292 }
1293 }
1294
1295 APValue AV = Ptr.toAPValue(S.getASTContext());
1296 CharUnits AVOffset = AV.getLValueOffset();
1297 if (ExtraOffset)
1298 AVOffset -= CharUnits::fromQuantity(ExtraOffset->getZExtValue());
1299 if (AVOffset.alignTo(Align) != AVOffset) {
1300 if (Ptr.isBlockPointer())
1301 S.CCEDiag(Call->getArg(0),
1302 diag::note_constexpr_baa_insufficient_alignment)
1303 << 1 << AVOffset.getQuantity() << Align.getQuantity();
1304 else
1305 S.CCEDiag(Call->getArg(0),
1306 diag::note_constexpr_baa_value_insufficient_alignment)
1307 << AVOffset.getQuantity() << Align.getQuantity();
1308 return false;
1309 }
1310
1311 S.Stk.push<Pointer>(Ptr);
1312 return true;
1313}
1314
1316 const InterpFrame *Frame,
1317 const CallExpr *Call) {
1318 if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1319 !Call->getArg(1)->getType()->isIntegerType())
1320 return false;
1321
1322 PrimType ValT = *S.Ctx.classify(Call->getArg(0));
1323 PrimType IndexT = *S.Ctx.classify(Call->getArg(1));
1324 APSInt Index = popToAPSInt(S.Stk, IndexT);
1325 APSInt Val = popToAPSInt(S.Stk, ValT);
1326
1327 unsigned BitWidth = Val.getBitWidth();
1328 uint64_t Shift = Index.extractBitsAsZExtValue(8, 0);
1329 uint64_t Length = Index.extractBitsAsZExtValue(8, 8);
1330 Length = Length > BitWidth ? BitWidth : Length;
1331
1332 // Handle out of bounds cases.
1333 if (Length == 0 || Shift >= BitWidth) {
1334 pushInteger(S, 0, Call->getType());
1335 return true;
1336 }
1337
1338 uint64_t Result = Val.getZExtValue() >> Shift;
1339 Result &= llvm::maskTrailingOnes<uint64_t>(Length);
1340 pushInteger(S, Result, Call->getType());
1341 return true;
1342}
1343
1345 const InterpFrame *Frame,
1346 const CallExpr *Call) {
1347 QualType CallType = Call->getType();
1348 if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1349 !Call->getArg(1)->getType()->isIntegerType() ||
1350 !CallType->isIntegerType())
1351 return false;
1352
1353 PrimType ValT = *S.Ctx.classify(Call->getArg(0));
1354 PrimType IndexT = *S.Ctx.classify(Call->getArg(1));
1355
1356 APSInt Idx = popToAPSInt(S.Stk, IndexT);
1357 APSInt Val = popToAPSInt(S.Stk, ValT);
1358
1359 unsigned BitWidth = Val.getBitWidth();
1360 uint64_t Index = Idx.extractBitsAsZExtValue(8, 0);
1361
1362 if (Index < BitWidth)
1363 Val.clearHighBits(BitWidth - Index);
1364
1365 pushInteger(S, Val, CallType);
1366 return true;
1367}
1368
1370 const InterpFrame *Frame,
1371 const CallExpr *Call) {
1372 QualType CallType = Call->getType();
1373 if (!CallType->isIntegerType() ||
1374 !Call->getArg(0)->getType()->isIntegerType())
1375 return false;
1376
1377 APSInt Val = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
1378 pushInteger(S, Val.countLeadingZeros(), CallType);
1379 return true;
1380}
1381
1383 const InterpFrame *Frame,
1384 const CallExpr *Call) {
1385 QualType CallType = Call->getType();
1386 if (!CallType->isIntegerType() ||
1387 !Call->getArg(0)->getType()->isIntegerType())
1388 return false;
1389
1390 APSInt Val = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
1391 pushInteger(S, Val.countTrailingZeros(), CallType);
1392 return true;
1393}
1394
1396 const InterpFrame *Frame,
1397 const CallExpr *Call) {
1398 if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1399 !Call->getArg(1)->getType()->isIntegerType())
1400 return false;
1401
1402 PrimType ValT = *S.Ctx.classify(Call->getArg(0));
1403 PrimType MaskT = *S.Ctx.classify(Call->getArg(1));
1404
1405 APSInt Mask = popToAPSInt(S.Stk, MaskT);
1406 APSInt Val = popToAPSInt(S.Stk, ValT);
1407
1408 unsigned BitWidth = Val.getBitWidth();
1409 APInt Result = APInt::getZero(BitWidth);
1410 for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
1411 if (Mask[I])
1412 Result.setBitVal(I, Val[P++]);
1413 }
1414 pushInteger(S, std::move(Result), Call->getType());
1415 return true;
1416}
1417
1419 const InterpFrame *Frame,
1420 const CallExpr *Call) {
1421 if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1422 !Call->getArg(1)->getType()->isIntegerType())
1423 return false;
1424
1425 PrimType ValT = *S.Ctx.classify(Call->getArg(0));
1426 PrimType MaskT = *S.Ctx.classify(Call->getArg(1));
1427
1428 APSInt Mask = popToAPSInt(S.Stk, MaskT);
1429 APSInt Val = popToAPSInt(S.Stk, ValT);
1430
1431 unsigned BitWidth = Val.getBitWidth();
1432 APInt Result = APInt::getZero(BitWidth);
1433 for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
1434 if (Mask[I])
1435 Result.setBitVal(P++, Val[I]);
1436 }
1437 pushInteger(S, std::move(Result), Call->getType());
1438 return true;
1439}
1440
1441/// (CarryIn, LHS, RHS, Result)
1443 CodePtr OpPC,
1444 const InterpFrame *Frame,
1445 const CallExpr *Call,
1446 unsigned BuiltinOp) {
1447 if (Call->getNumArgs() != 4 || !Call->getArg(0)->getType()->isIntegerType() ||
1448 !Call->getArg(1)->getType()->isIntegerType() ||
1449 !Call->getArg(2)->getType()->isIntegerType())
1450 return false;
1451
1452 const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();
1453
1454 PrimType CarryInT = *S.getContext().classify(Call->getArg(0));
1455 PrimType LHST = *S.getContext().classify(Call->getArg(1));
1456 PrimType RHST = *S.getContext().classify(Call->getArg(2));
1457 APSInt RHS = popToAPSInt(S.Stk, RHST);
1458 APSInt LHS = popToAPSInt(S.Stk, LHST);
1459 APSInt CarryIn = popToAPSInt(S.Stk, CarryInT);
1460
1461 bool IsAdd = BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u32 ||
1462 BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u64;
1463
1464 unsigned BitWidth = LHS.getBitWidth();
1465 unsigned CarryInBit = CarryIn.ugt(0) ? 1 : 0;
1466 APInt ExResult =
1467 IsAdd ? (LHS.zext(BitWidth + 1) + (RHS.zext(BitWidth + 1) + CarryInBit))
1468 : (LHS.zext(BitWidth + 1) - (RHS.zext(BitWidth + 1) + CarryInBit));
1469
1470 APInt Result = ExResult.extractBits(BitWidth, 0);
1471 APSInt CarryOut =
1472 APSInt(ExResult.extractBits(1, BitWidth), /*IsUnsigned=*/true);
1473
1474 QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
1475 PrimType CarryOutT = *S.getContext().classify(CarryOutType);
1476 assignInteger(S, CarryOutPtr, CarryOutT, APSInt(std::move(Result), true));
1477
1478 pushInteger(S, CarryOut, Call->getType());
1479
1480 return true;
1481}
1482
1484 CodePtr OpPC,
1485 const InterpFrame *Frame,
1486 const CallExpr *Call) {
1489 pushInteger(S, Layout.size().getQuantity(), Call->getType());
1490 return true;
1491}
1492
1493static bool
1495 const InterpFrame *Frame,
1496 const CallExpr *Call) {
1497 const auto &Ptr = S.Stk.pop<Pointer>();
1498 assert(Ptr.getFieldDesc()->isPrimitiveArray());
1499
1500 // This should be created for a StringLiteral, so should alway shold at least
1501 // one array element.
1502 assert(Ptr.getFieldDesc()->getNumElems() >= 1);
1503 StringRef R(&Ptr.deref<char>(), Ptr.getFieldDesc()->getNumElems() - 1);
1504 uint64_t Result = getPointerAuthStableSipHash(R);
1505 pushInteger(S, Result, Call->getType());
1506 return true;
1507}
1508
1510 const InterpFrame *Frame,
1511 const CallExpr *Call) {
1512 // A call to __operator_new is only valid within std::allocate<>::allocate.
1513 // Walk up the call stack to find the appropriate caller and get the
1514 // element type from it.
1515 auto [NewCall, ElemType] = S.getStdAllocatorCaller("allocate");
1516
1517 if (ElemType.isNull()) {
1518 S.FFDiag(Call, S.getLangOpts().CPlusPlus20
1519 ? diag::note_constexpr_new_untyped
1520 : diag::note_constexpr_new);
1521 return false;
1522 }
1523 assert(NewCall);
1524
1525 if (ElemType->isIncompleteType() || ElemType->isFunctionType()) {
1526 S.FFDiag(Call, diag::note_constexpr_new_not_complete_object_type)
1527 << (ElemType->isIncompleteType() ? 0 : 1) << ElemType;
1528 return false;
1529 }
1530
1531 // We only care about the first parameter (the size), so discard all the
1532 // others.
1533 {
1534 unsigned NumArgs = Call->getNumArgs();
1535 assert(NumArgs >= 1);
1536
1537 // The std::nothrow_t arg never gets put on the stack.
1538 if (Call->getArg(NumArgs - 1)->getType()->isNothrowT())
1539 --NumArgs;
1540 auto Args = ArrayRef(Call->getArgs(), Call->getNumArgs());
1541 // First arg is needed.
1542 Args = Args.drop_front();
1543
1544 // Discard the rest.
1545 for (const Expr *Arg : Args)
1546 discard(S.Stk, *S.getContext().classify(Arg));
1547 }
1548
1549 APSInt Bytes = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(0)));
1550 CharUnits ElemSize = S.getASTContext().getTypeSizeInChars(ElemType);
1551 assert(!ElemSize.isZero());
1552 // Divide the number of bytes by sizeof(ElemType), so we get the number of
1553 // elements we should allocate.
1554 APInt NumElems, Remainder;
1555 APInt ElemSizeAP(Bytes.getBitWidth(), ElemSize.getQuantity());
1556 APInt::udivrem(Bytes, ElemSizeAP, NumElems, Remainder);
1557 if (Remainder != 0) {
1558 // This likely indicates a bug in the implementation of 'std::allocator'.
1559 S.FFDiag(Call, diag::note_constexpr_operator_new_bad_size)
1560 << Bytes << APSInt(ElemSizeAP, true) << ElemType;
1561 return false;
1562 }
1563
1564 // NB: The same check we're using in CheckArraySize()
1565 if (NumElems.getActiveBits() >
1567 NumElems.ugt(Descriptor::MaxArrayElemBytes / ElemSize.getQuantity())) {
1568 // FIXME: NoThrow check?
1569 const SourceInfo &Loc = S.Current->getSource(OpPC);
1570 S.FFDiag(Loc, diag::note_constexpr_new_too_large)
1571 << NumElems.getZExtValue();
1572 return false;
1573 }
1574
1575 if (!CheckArraySize(S, OpPC, NumElems.getZExtValue()))
1576 return false;
1577
1578 bool IsArray = NumElems.ugt(1);
1579 OptPrimType ElemT = S.getContext().classify(ElemType);
1580 DynamicAllocator &Allocator = S.getAllocator();
1581 if (ElemT) {
1582 Block *B =
1583 Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(),
1585 assert(B);
1586 S.Stk.push<Pointer>(Pointer(B).atIndex(0));
1587 return true;
1588 }
1589
1590 assert(!ElemT);
1591
1592 // Composite arrays
1593 if (IsArray) {
1594 const Descriptor *Desc =
1595 S.P.createDescriptor(NewCall, ElemType.getTypePtr(), std::nullopt);
1596 Block *B =
1597 Allocator.allocate(Desc, NumElems.getZExtValue(), S.Ctx.getEvalID(),
1599 assert(B);
1600 S.Stk.push<Pointer>(Pointer(B).atIndex(0));
1601 return true;
1602 }
1603
1604 // Records. Still allocate them as single-element arrays.
1606 ElemType, NumElems, nullptr, ArraySizeModifier::Normal, 0);
1607
1608 const Descriptor *Desc = S.P.createDescriptor(NewCall, AllocType.getTypePtr(),
1610 Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(),
1612 assert(B);
1613 S.Stk.push<Pointer>(Pointer(B).atIndex(0).narrow());
1614 return true;
1615}
1616
1618 const InterpFrame *Frame,
1619 const CallExpr *Call) {
1620 const Expr *Source = nullptr;
1621 const Block *BlockToDelete = nullptr;
1622
1624 S.Stk.discard<Pointer>();
1625 return false;
1626 }
1627
1628 // This is permitted only within a call to std::allocator<T>::deallocate.
1629 if (!S.getStdAllocatorCaller("deallocate")) {
1630 S.FFDiag(Call);
1631 S.Stk.discard<Pointer>();
1632 return true;
1633 }
1634
1635 {
1636 const Pointer &Ptr = S.Stk.pop<Pointer>();
1637
1638 if (Ptr.isZero()) {
1639 S.CCEDiag(Call, diag::note_constexpr_deallocate_null);
1640 return true;
1641 }
1642
1643 Source = Ptr.getDeclDesc()->asExpr();
1644 BlockToDelete = Ptr.block();
1645
1646 if (!BlockToDelete->isDynamic()) {
1647 S.FFDiag(Call, diag::note_constexpr_delete_not_heap_alloc)
1649 if (const auto *D = Ptr.getFieldDesc()->asDecl())
1650 S.Note(D->getLocation(), diag::note_declared_at);
1651 }
1652 }
1653 assert(BlockToDelete);
1654
1655 DynamicAllocator &Allocator = S.getAllocator();
1656 const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
1657 std::optional<DynamicAllocator::Form> AllocForm =
1658 Allocator.getAllocationForm(Source);
1659
1660 if (!Allocator.deallocate(Source, BlockToDelete, S)) {
1661 // Nothing has been deallocated, this must be a double-delete.
1662 const SourceInfo &Loc = S.Current->getSource(OpPC);
1663 S.FFDiag(Loc, diag::note_constexpr_double_delete);
1664 return false;
1665 }
1666 assert(AllocForm);
1667
1668 return CheckNewDeleteForms(
1669 S, OpPC, *AllocForm, DynamicAllocator::Form::Operator, BlockDesc, Source);
1670}
1671
1673 const InterpFrame *Frame,
1674 const CallExpr *Call) {
1675 const Floating &Arg0 = S.Stk.pop<Floating>();
1676 S.Stk.push<Floating>(Arg0);
1677 return true;
1678}
1679
1681 const CallExpr *Call, unsigned ID) {
1682 const Pointer &Arg = S.Stk.pop<Pointer>();
1683 assert(Arg.getFieldDesc()->isPrimitiveArray());
1684
1685 QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1686 assert(Call->getType() == ElemType);
1687 PrimType ElemT = *S.getContext().classify(ElemType);
1688 unsigned NumElems = Arg.getNumElems();
1689
1691 T Result = Arg.elem<T>(0);
1692 unsigned BitWidth = Result.bitWidth();
1693 for (unsigned I = 1; I != NumElems; ++I) {
1694 T Elem = Arg.elem<T>(I);
1695 T PrevResult = Result;
1696
1697 if (ID == Builtin::BI__builtin_reduce_add) {
1698 if (T::add(Result, Elem, BitWidth, &Result)) {
1699 unsigned OverflowBits = BitWidth + 1;
1700 (void)handleOverflow(S, OpPC,
1701 (PrevResult.toAPSInt(OverflowBits) +
1702 Elem.toAPSInt(OverflowBits)));
1703 return false;
1704 }
1705 } else if (ID == Builtin::BI__builtin_reduce_mul) {
1706 if (T::mul(Result, Elem, BitWidth, &Result)) {
1707 unsigned OverflowBits = BitWidth * 2;
1708 (void)handleOverflow(S, OpPC,
1709 (PrevResult.toAPSInt(OverflowBits) *
1710 Elem.toAPSInt(OverflowBits)));
1711 return false;
1712 }
1713
1714 } else if (ID == Builtin::BI__builtin_reduce_and) {
1715 (void)T::bitAnd(Result, Elem, BitWidth, &Result);
1716 } else if (ID == Builtin::BI__builtin_reduce_or) {
1717 (void)T::bitOr(Result, Elem, BitWidth, &Result);
1718 } else if (ID == Builtin::BI__builtin_reduce_xor) {
1719 (void)T::bitXor(Result, Elem, BitWidth, &Result);
1720 } else if (ID == Builtin::BI__builtin_reduce_min) {
1721 if (Elem < Result)
1722 Result = Elem;
1723 } else if (ID == Builtin::BI__builtin_reduce_max) {
1724 if (Elem > Result)
1725 Result = Elem;
1726 } else {
1727 llvm_unreachable("Unhandled vector reduce builtin");
1728 }
1729 }
1730 pushInteger(S, Result.toAPSInt(), Call->getType());
1731 });
1732
1733 return true;
1734}
1735
1737 const InterpFrame *Frame,
1738 const CallExpr *Call,
1739 unsigned BuiltinID) {
1740 assert(Call->getNumArgs() == 1);
1741 QualType Ty = Call->getArg(0)->getType();
1742 if (Ty->isIntegerType()) {
1743 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
1744 APSInt Val = popToAPSInt(S.Stk, ArgT);
1745
1746 pushInteger(S, Val.abs(), Call->getType());
1747 return true;
1748 }
1749
1750 if (Ty->isFloatingType()) {
1751 Floating Val = S.Stk.pop<Floating>();
1752 Floating Result = abs(S, Val);
1753 S.Stk.push<Floating>(Result);
1754 return true;
1755 }
1756
1757 // Otherwise, the argument must be a vector.
1758 assert(Call->getArg(0)->getType()->isVectorType());
1759 const Pointer &Arg = S.Stk.pop<Pointer>();
1760 assert(Arg.getFieldDesc()->isPrimitiveArray());
1761 const Pointer &Dst = S.Stk.peek<Pointer>();
1762 assert(Dst.getFieldDesc()->isPrimitiveArray());
1763 assert(Arg.getFieldDesc()->getNumElems() ==
1764 Dst.getFieldDesc()->getNumElems());
1765
1766 QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1767 PrimType ElemT = *S.getContext().classify(ElemType);
1768 unsigned NumElems = Arg.getNumElems();
1769 // we can either have a vector of integer or a vector of floating point
1770 for (unsigned I = 0; I != NumElems; ++I) {
1771 if (ElemType->isIntegerType()) {
1773 Dst.elem<T>(I) = T::from(static_cast<T>(
1774 APSInt(Arg.elem<T>(I).toAPSInt().abs(),
1776 });
1777 } else {
1778 Floating Val = Arg.elem<Floating>(I);
1779 Dst.elem<Floating>(I) = abs(S, Val);
1780 }
1781 }
1783
1784 return true;
1785}
1786
1787/// Can be called with an integer or vector as the first and only parameter.
1789 const InterpFrame *Frame,
1790 const CallExpr *Call,
1791 unsigned BuiltinID) {
1792 assert(Call->getNumArgs() == 1);
1793 if (Call->getArg(0)->getType()->isIntegerType()) {
1794 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
1795 APSInt Val = popToAPSInt(S.Stk, ArgT);
1796
1797 if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) {
1798 pushInteger(S, Val.popcount(), Call->getType());
1799 } else {
1800 pushInteger(S, Val.reverseBits(), Call->getType());
1801 }
1802 return true;
1803 }
1804 // Otherwise, the argument must be a vector.
1805 assert(Call->getArg(0)->getType()->isVectorType());
1806 const Pointer &Arg = S.Stk.pop<Pointer>();
1807 assert(Arg.getFieldDesc()->isPrimitiveArray());
1808 const Pointer &Dst = S.Stk.peek<Pointer>();
1809 assert(Dst.getFieldDesc()->isPrimitiveArray());
1810 assert(Arg.getFieldDesc()->getNumElems() ==
1811 Dst.getFieldDesc()->getNumElems());
1812
1813 QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1814 PrimType ElemT = *S.getContext().classify(ElemType);
1815 unsigned NumElems = Arg.getNumElems();
1816
1817 // FIXME: Reading from uninitialized vector elements?
1818 for (unsigned I = 0; I != NumElems; ++I) {
1820 if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) {
1821 Dst.elem<T>(I) = T::from(Arg.elem<T>(I).toAPSInt().popcount());
1822 } else {
1823 Dst.elem<T>(I) =
1824 T::from(Arg.elem<T>(I).toAPSInt().reverseBits().getZExtValue());
1825 }
1826 });
1827 }
1829
1830 return true;
1831}
1832
1833/// Can be called with an integer or vector as the first and only parameter.
1835 CodePtr OpPC,
1836 const InterpFrame *Frame,
1837 const CallExpr *Call,
1838 unsigned BuiltinID) {
1839 const bool HasZeroArg = Call->getNumArgs() == 2;
1840 const bool IsCTTZ = BuiltinID == Builtin::BI__builtin_elementwise_cttz;
1841 assert(Call->getNumArgs() == 1 || HasZeroArg);
1842 if (Call->getArg(0)->getType()->isIntegerType()) {
1843 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
1844 APSInt Val = popToAPSInt(S.Stk, ArgT);
1845 std::optional<APSInt> ZeroVal;
1846 if (HasZeroArg) {
1847 ZeroVal = Val;
1848 Val = popToAPSInt(S.Stk, ArgT);
1849 }
1850
1851 if (Val.isZero()) {
1852 if (ZeroVal) {
1853 pushInteger(S, *ZeroVal, Call->getType());
1854 return true;
1855 }
1856 // If we haven't been provided the second argument, the result is
1857 // undefined
1858 S.FFDiag(S.Current->getSource(OpPC),
1859 diag::note_constexpr_countzeroes_zero)
1860 << /*IsTrailing=*/IsCTTZ;
1861 return false;
1862 }
1863
1864 if (BuiltinID == Builtin::BI__builtin_elementwise_ctlz) {
1865 pushInteger(S, Val.countLeadingZeros(), Call->getType());
1866 } else {
1867 pushInteger(S, Val.countTrailingZeros(), Call->getType());
1868 }
1869 return true;
1870 }
1871 // Otherwise, the argument must be a vector.
1872 const ASTContext &ASTCtx = S.getASTContext();
1873 Pointer ZeroArg;
1874 if (HasZeroArg) {
1875 assert(Call->getArg(1)->getType()->isVectorType() &&
1876 ASTCtx.hasSameUnqualifiedType(Call->getArg(0)->getType(),
1877 Call->getArg(1)->getType()));
1878 (void)ASTCtx;
1879 ZeroArg = S.Stk.pop<Pointer>();
1880 assert(ZeroArg.getFieldDesc()->isPrimitiveArray());
1881 }
1882 assert(Call->getArg(0)->getType()->isVectorType());
1883 const Pointer &Arg = S.Stk.pop<Pointer>();
1884 assert(Arg.getFieldDesc()->isPrimitiveArray());
1885 const Pointer &Dst = S.Stk.peek<Pointer>();
1886 assert(Dst.getFieldDesc()->isPrimitiveArray());
1887 assert(Arg.getFieldDesc()->getNumElems() ==
1888 Dst.getFieldDesc()->getNumElems());
1889
1890 QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1891 PrimType ElemT = *S.getContext().classify(ElemType);
1892 unsigned NumElems = Arg.getNumElems();
1893
1894 // FIXME: Reading from uninitialized vector elements?
1895 for (unsigned I = 0; I != NumElems; ++I) {
1897 APInt EltVal = Arg.atIndex(I).deref<T>().toAPSInt();
1898 if (EltVal.isZero()) {
1899 if (HasZeroArg) {
1900 Dst.atIndex(I).deref<T>() = ZeroArg.atIndex(I).deref<T>();
1901 } else {
1902 // If we haven't been provided the second argument, the result is
1903 // undefined
1904 S.FFDiag(S.Current->getSource(OpPC),
1905 diag::note_constexpr_countzeroes_zero)
1906 << /*IsTrailing=*/IsCTTZ;
1907 return false;
1908 }
1909 } else if (IsCTTZ) {
1910 Dst.atIndex(I).deref<T>() = T::from(EltVal.countTrailingZeros());
1911 } else {
1912 Dst.atIndex(I).deref<T>() = T::from(EltVal.countLeadingZeros());
1913 }
1914 Dst.atIndex(I).initialize();
1915 });
1916 }
1917
1918 return true;
1919}
1920
1922 const InterpFrame *Frame,
1923 const CallExpr *Call, unsigned ID) {
1924 assert(Call->getNumArgs() == 3);
1925 const ASTContext &ASTCtx = S.getASTContext();
1926 PrimType SizeT = *S.getContext().classify(Call->getArg(2));
1927 APSInt Size = popToAPSInt(S.Stk, SizeT);
1928 const Pointer SrcPtr = S.Stk.pop<Pointer>();
1929 const Pointer DestPtr = S.Stk.pop<Pointer>();
1930
1931 assert(!Size.isSigned() && "memcpy and friends take an unsigned size");
1932
1933 if (ID == Builtin::BImemcpy || ID == Builtin::BImemmove)
1934 diagnoseNonConstexprBuiltin(S, OpPC, ID);
1935
1936 bool Move =
1937 (ID == Builtin::BI__builtin_memmove || ID == Builtin::BImemmove ||
1938 ID == Builtin::BI__builtin_wmemmove || ID == Builtin::BIwmemmove);
1939 bool WChar = ID == Builtin::BIwmemcpy || ID == Builtin::BIwmemmove ||
1940 ID == Builtin::BI__builtin_wmemcpy ||
1941 ID == Builtin::BI__builtin_wmemmove;
1942
1943 // If the size is zero, we treat this as always being a valid no-op.
1944 if (Size.isZero()) {
1945 S.Stk.push<Pointer>(DestPtr);
1946 return true;
1947 }
1948
1949 if (SrcPtr.isZero() || DestPtr.isZero()) {
1950 Pointer DiagPtr = (SrcPtr.isZero() ? SrcPtr : DestPtr);
1951 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
1952 << /*IsMove=*/Move << /*IsWchar=*/WChar << !SrcPtr.isZero()
1953 << DiagPtr.toDiagnosticString(ASTCtx);
1954 return false;
1955 }
1956
1957 // Diagnose integral src/dest pointers specially.
1958 if (SrcPtr.isIntegralPointer() || DestPtr.isIntegralPointer()) {
1959 std::string DiagVal = "(void *)";
1960 DiagVal += SrcPtr.isIntegralPointer()
1961 ? std::to_string(SrcPtr.getIntegerRepresentation())
1962 : std::to_string(DestPtr.getIntegerRepresentation());
1963 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
1964 << Move << WChar << DestPtr.isIntegralPointer() << DiagVal;
1965 return false;
1966 }
1967
1968 // Can't read from dummy pointers.
1969 if (DestPtr.isDummy() || SrcPtr.isDummy())
1970 return false;
1971
1972 if (DestPtr.getType()->isIncompleteType()) {
1973 S.FFDiag(S.Current->getSource(OpPC),
1974 diag::note_constexpr_memcpy_incomplete_type)
1975 << Move << DestPtr.getType();
1976 return false;
1977 }
1978 if (SrcPtr.getType()->isIncompleteType()) {
1979 S.FFDiag(S.Current->getSource(OpPC),
1980 diag::note_constexpr_memcpy_incomplete_type)
1981 << Move << SrcPtr.getType();
1982 return false;
1983 }
1984
1985 QualType DestElemType = getElemType(DestPtr);
1986 if (DestElemType->isIncompleteType()) {
1987 S.FFDiag(S.Current->getSource(OpPC),
1988 diag::note_constexpr_memcpy_incomplete_type)
1989 << Move << DestElemType;
1990 return false;
1991 }
1992
1993 size_t RemainingDestElems;
1994 if (DestPtr.getFieldDesc()->isArray()) {
1995 RemainingDestElems = DestPtr.isUnknownSizeArray()
1996 ? 0
1997 : (DestPtr.getNumElems() - DestPtr.getIndex());
1998 } else {
1999 RemainingDestElems = 1;
2000 }
2001 unsigned DestElemSize = ASTCtx.getTypeSizeInChars(DestElemType).getQuantity();
2002
2003 if (WChar) {
2004 uint64_t WCharSize =
2005 ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();
2006 Size *= APSInt(APInt(Size.getBitWidth(), WCharSize, /*IsSigned=*/false),
2007 /*IsUnsigend=*/true);
2008 }
2009
2010 if (Size.urem(DestElemSize) != 0) {
2011 S.FFDiag(S.Current->getSource(OpPC),
2012 diag::note_constexpr_memcpy_unsupported)
2013 << Move << WChar << 0 << DestElemType << Size << DestElemSize;
2014 return false;
2015 }
2016
2017 QualType SrcElemType = getElemType(SrcPtr);
2018 size_t RemainingSrcElems;
2019 if (SrcPtr.getFieldDesc()->isArray()) {
2020 RemainingSrcElems = SrcPtr.isUnknownSizeArray()
2021 ? 0
2022 : (SrcPtr.getNumElems() - SrcPtr.getIndex());
2023 } else {
2024 RemainingSrcElems = 1;
2025 }
2026 unsigned SrcElemSize = ASTCtx.getTypeSizeInChars(SrcElemType).getQuantity();
2027
2028 if (!ASTCtx.hasSameUnqualifiedType(DestElemType, SrcElemType)) {
2029 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_type_pun)
2030 << Move << SrcElemType << DestElemType;
2031 return false;
2032 }
2033
2034 if (!DestElemType.isTriviallyCopyableType(ASTCtx)) {
2035 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_nontrivial)
2036 << Move << DestElemType;
2037 return false;
2038 }
2039
2040 // Check if we have enough elements to read from and write to.
2041 size_t RemainingDestBytes = RemainingDestElems * DestElemSize;
2042 size_t RemainingSrcBytes = RemainingSrcElems * SrcElemSize;
2043 if (Size.ugt(RemainingDestBytes) || Size.ugt(RemainingSrcBytes)) {
2044 APInt N = Size.udiv(DestElemSize);
2045 S.FFDiag(S.Current->getSource(OpPC),
2046 diag::note_constexpr_memcpy_unsupported)
2047 << Move << WChar << (Size.ugt(RemainingSrcBytes) ? 1 : 2)
2048 << DestElemType << toString(N, 10, /*Signed=*/false);
2049 return false;
2050 }
2051
2052 // Check for overlapping memory regions.
2053 if (!Move && Pointer::pointToSameBlock(SrcPtr, DestPtr)) {
2054 // Remove base casts.
2055 Pointer SrcP = SrcPtr;
2056 while (SrcP.isBaseClass())
2057 SrcP = SrcP.getBase();
2058
2059 Pointer DestP = DestPtr;
2060 while (DestP.isBaseClass())
2061 DestP = DestP.getBase();
2062
2063 unsigned SrcIndex = SrcP.expand().getIndex() * SrcP.elemSize();
2064 unsigned DstIndex = DestP.expand().getIndex() * DestP.elemSize();
2065 unsigned N = Size.getZExtValue();
2066
2067 if ((SrcIndex <= DstIndex && (SrcIndex + N) > DstIndex) ||
2068 (DstIndex <= SrcIndex && (DstIndex + N) > SrcIndex)) {
2069 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_overlap)
2070 << /*IsWChar=*/false;
2071 return false;
2072 }
2073 }
2074
2075 assert(Size.getZExtValue() % DestElemSize == 0);
2076 if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size.getZExtValue()).toBits()))
2077 return false;
2078
2079 S.Stk.push<Pointer>(DestPtr);
2080 return true;
2081}
2082
2083/// Determine if T is a character type for which we guarantee that
2084/// sizeof(T) == 1.
2086 return T->isCharType() || T->isChar8Type();
2087}
2088
2090 const InterpFrame *Frame,
2091 const CallExpr *Call, unsigned ID) {
2092 assert(Call->getNumArgs() == 3);
2093 PrimType SizeT = *S.getContext().classify(Call->getArg(2));
2094 const APSInt &Size = popToAPSInt(S.Stk, SizeT);
2095 const Pointer &PtrB = S.Stk.pop<Pointer>();
2096 const Pointer &PtrA = S.Stk.pop<Pointer>();
2097
2098 if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp ||
2099 ID == Builtin::BIwmemcmp)
2100 diagnoseNonConstexprBuiltin(S, OpPC, ID);
2101
2102 if (Size.isZero()) {
2103 pushInteger(S, 0, Call->getType());
2104 return true;
2105 }
2106
2107 bool IsWide =
2108 (ID == Builtin::BIwmemcmp || ID == Builtin::BI__builtin_wmemcmp);
2109
2110 const ASTContext &ASTCtx = S.getASTContext();
2111 QualType ElemTypeA = getElemType(PtrA);
2112 QualType ElemTypeB = getElemType(PtrB);
2113 // FIXME: This is an arbitrary limitation the current constant interpreter
2114 // had. We could remove this.
2115 if (!IsWide && (!isOneByteCharacterType(ElemTypeA) ||
2116 !isOneByteCharacterType(ElemTypeB))) {
2117 S.FFDiag(S.Current->getSource(OpPC),
2118 diag::note_constexpr_memcmp_unsupported)
2119 << ASTCtx.BuiltinInfo.getQuotedName(ID) << PtrA.getType()
2120 << PtrB.getType();
2121 return false;
2122 }
2123
2124 if (PtrA.isDummy() || PtrB.isDummy())
2125 return false;
2126
2127 // Now, read both pointers to a buffer and compare those.
2128 BitcastBuffer BufferA(
2129 Bits(ASTCtx.getTypeSize(ElemTypeA) * PtrA.getNumElems()));
2130 readPointerToBuffer(S.getContext(), PtrA, BufferA, false);
2131 // FIXME: The swapping here is UNDOING something we do when reading the
2132 // data into the buffer.
2133 if (ASTCtx.getTargetInfo().isBigEndian())
2134 swapBytes(BufferA.Data.get(), BufferA.byteSize().getQuantity());
2135
2136 BitcastBuffer BufferB(
2137 Bits(ASTCtx.getTypeSize(ElemTypeB) * PtrB.getNumElems()));
2138 readPointerToBuffer(S.getContext(), PtrB, BufferB, false);
2139 // FIXME: The swapping here is UNDOING something we do when reading the
2140 // data into the buffer.
2141 if (ASTCtx.getTargetInfo().isBigEndian())
2142 swapBytes(BufferB.Data.get(), BufferB.byteSize().getQuantity());
2143
2144 size_t MinBufferSize = std::min(BufferA.byteSize().getQuantity(),
2145 BufferB.byteSize().getQuantity());
2146
2147 unsigned ElemSize = 1;
2148 if (IsWide)
2149 ElemSize = ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();
2150 // The Size given for the wide variants is in wide-char units. Convert it
2151 // to bytes.
2152 size_t ByteSize = Size.getZExtValue() * ElemSize;
2153 size_t CmpSize = std::min(MinBufferSize, ByteSize);
2154
2155 for (size_t I = 0; I != CmpSize; I += ElemSize) {
2156 if (IsWide) {
2158 T A = *reinterpret_cast<T *>(BufferA.Data.get() + I);
2159 T B = *reinterpret_cast<T *>(BufferB.Data.get() + I);
2160 if (A < B) {
2161 pushInteger(S, -1, Call->getType());
2162 return true;
2163 }
2164 if (A > B) {
2165 pushInteger(S, 1, Call->getType());
2166 return true;
2167 }
2168 });
2169 } else {
2170 std::byte A = BufferA.Data[I];
2171 std::byte B = BufferB.Data[I];
2172
2173 if (A < B) {
2174 pushInteger(S, -1, Call->getType());
2175 return true;
2176 }
2177 if (A > B) {
2178 pushInteger(S, 1, Call->getType());
2179 return true;
2180 }
2181 }
2182 }
2183
2184 // We compared CmpSize bytes above. If the limiting factor was the Size
2185 // passed, we're done and the result is equality (0).
2186 if (ByteSize <= CmpSize) {
2187 pushInteger(S, 0, Call->getType());
2188 return true;
2189 }
2190
2191 // However, if we read all the available bytes but were instructed to read
2192 // even more, diagnose this as a "read of dereferenced one-past-the-end
2193 // pointer". This is what would happen if we called CheckLoad() on every array
2194 // element.
2195 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)
2196 << AK_Read << S.Current->getRange(OpPC);
2197 return false;
2198}
2199
2200// __builtin_memchr(ptr, int, int)
2201// __builtin_strchr(ptr, int)
2203 const CallExpr *Call, unsigned ID) {
2204 if (ID == Builtin::BImemchr || ID == Builtin::BIwcschr ||
2205 ID == Builtin::BIstrchr || ID == Builtin::BIwmemchr)
2206 diagnoseNonConstexprBuiltin(S, OpPC, ID);
2207
2208 std::optional<APSInt> MaxLength;
2209 PrimType DesiredT = *S.getContext().classify(Call->getArg(1));
2210 if (Call->getNumArgs() == 3) {
2211 PrimType MaxT = *S.getContext().classify(Call->getArg(2));
2212 MaxLength = popToAPSInt(S.Stk, MaxT);
2213 }
2214 APSInt Desired = popToAPSInt(S.Stk, DesiredT);
2215 const Pointer &Ptr = S.Stk.pop<Pointer>();
2216
2217 if (MaxLength && MaxLength->isZero()) {
2218 S.Stk.push<Pointer>();
2219 return true;
2220 }
2221
2222 if (Ptr.isDummy()) {
2223 if (Ptr.getType()->isIncompleteType())
2224 S.FFDiag(S.Current->getSource(OpPC),
2225 diag::note_constexpr_ltor_incomplete_type)
2226 << Ptr.getType();
2227 return false;
2228 }
2229
2230 // Null is only okay if the given size is 0.
2231 if (Ptr.isZero()) {
2232 S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)
2233 << AK_Read;
2234 return false;
2235 }
2236
2237 QualType ElemTy = Ptr.getFieldDesc()->isArray()
2238 ? Ptr.getFieldDesc()->getElemQualType()
2239 : Ptr.getFieldDesc()->getType();
2240 bool IsRawByte = ID == Builtin::BImemchr || ID == Builtin::BI__builtin_memchr;
2241
2242 // Give up on byte-oriented matching against multibyte elements.
2243 if (IsRawByte && !isOneByteCharacterType(ElemTy)) {
2244 S.FFDiag(S.Current->getSource(OpPC),
2245 diag::note_constexpr_memchr_unsupported)
2246 << S.getASTContext().BuiltinInfo.getQuotedName(ID) << ElemTy;
2247 return false;
2248 }
2249
2250 if (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr) {
2251 // strchr compares directly to the passed integer, and therefore
2252 // always fails if given an int that is not a char.
2253 if (Desired !=
2254 Desired.trunc(S.getASTContext().getCharWidth()).getSExtValue()) {
2255 S.Stk.push<Pointer>();
2256 return true;
2257 }
2258 }
2259
2260 uint64_t DesiredVal;
2261 if (ID == Builtin::BIwmemchr || ID == Builtin::BI__builtin_wmemchr ||
2262 ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr) {
2263 // wcschr and wmemchr are given a wchar_t to look for. Just use it.
2264 DesiredVal = Desired.getZExtValue();
2265 } else {
2266 DesiredVal = Desired.trunc(S.getASTContext().getCharWidth()).getZExtValue();
2267 }
2268
2269 bool StopAtZero =
2270 (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr ||
2271 ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr);
2272
2273 PrimType ElemT =
2274 IsRawByte ? PT_Sint8 : *S.getContext().classify(getElemType(Ptr));
2275
2276 size_t Index = Ptr.getIndex();
2277 size_t Step = 0;
2278 for (;;) {
2279 const Pointer &ElemPtr =
2280 (Index + Step) > 0 ? Ptr.atIndex(Index + Step) : Ptr;
2281
2282 if (!CheckLoad(S, OpPC, ElemPtr))
2283 return false;
2284
2285 uint64_t V;
2287 ElemT, { V = static_cast<uint64_t>(ElemPtr.deref<T>().toUnsigned()); });
2288
2289 if (V == DesiredVal) {
2290 S.Stk.push<Pointer>(ElemPtr);
2291 return true;
2292 }
2293
2294 if (StopAtZero && V == 0)
2295 break;
2296
2297 ++Step;
2298 if (MaxLength && Step == MaxLength->getZExtValue())
2299 break;
2300 }
2301
2302 S.Stk.push<Pointer>();
2303 return true;
2304}
2305
2306static std::optional<unsigned> computeFullDescSize(const ASTContext &ASTCtx,
2307 const Descriptor *Desc) {
2308 if (Desc->isPrimitive())
2309 return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();
2310 if (Desc->isArray())
2311 return ASTCtx.getTypeSizeInChars(Desc->getElemQualType()).getQuantity() *
2312 Desc->getNumElems();
2313 if (Desc->isRecord()) {
2314 // Can't use Descriptor::getType() as that may return a pointer type. Look
2315 // at the decl directly.
2316 return ASTCtx
2318 ASTCtx.getCanonicalTagType(Desc->ElemRecord->getDecl()))
2319 .getQuantity();
2320 }
2321
2322 return std::nullopt;
2323}
2324
2325/// Compute the byte offset of \p Ptr in the full declaration.
2326static unsigned computePointerOffset(const ASTContext &ASTCtx,
2327 const Pointer &Ptr) {
2328 unsigned Result = 0;
2329
2330 Pointer P = Ptr;
2331 while (P.isField() || P.isArrayElement()) {
2332 P = P.expand();
2333 const Descriptor *D = P.getFieldDesc();
2334
2335 if (P.isArrayElement()) {
2336 unsigned ElemSize =
2338 if (P.isOnePastEnd())
2339 Result += ElemSize * P.getNumElems();
2340 else
2341 Result += ElemSize * P.getIndex();
2342 P = P.expand().getArray();
2343 } else if (P.isBaseClass()) {
2344 const auto *RD = cast<CXXRecordDecl>(D->asDecl());
2345 bool IsVirtual = Ptr.isVirtualBaseClass();
2346 P = P.getBase();
2347 const Record *BaseRecord = P.getRecord();
2348
2349 const ASTRecordLayout &Layout =
2350 ASTCtx.getASTRecordLayout(cast<CXXRecordDecl>(BaseRecord->getDecl()));
2351 if (IsVirtual)
2352 Result += Layout.getVBaseClassOffset(RD).getQuantity();
2353 else
2354 Result += Layout.getBaseClassOffset(RD).getQuantity();
2355 } else if (P.isField()) {
2356 const FieldDecl *FD = P.getField();
2357 const ASTRecordLayout &Layout =
2358 ASTCtx.getASTRecordLayout(FD->getParent());
2359 unsigned FieldIndex = FD->getFieldIndex();
2360 uint64_t FieldOffset =
2361 ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex))
2362 .getQuantity();
2363 Result += FieldOffset;
2364 P = P.getBase();
2365 } else
2366 llvm_unreachable("Unhandled descriptor type");
2367 }
2368
2369 return Result;
2370}
2371
2372/// Does Ptr point to the last subobject?
2373static bool pointsToLastObject(const Pointer &Ptr) {
2374 Pointer P = Ptr;
2375 while (!P.isRoot()) {
2376
2377 if (P.isArrayElement()) {
2378 P = P.expand().getArray();
2379 continue;
2380 }
2381 if (P.isBaseClass()) {
2382 if (P.getRecord()->getNumFields() > 0)
2383 return false;
2384 P = P.getBase();
2385 continue;
2386 }
2387
2388 Pointer Base = P.getBase();
2389 if (const Record *R = Base.getRecord()) {
2390 assert(P.getField());
2391 if (P.getField()->getFieldIndex() != R->getNumFields() - 1)
2392 return false;
2393 }
2394 P = Base;
2395 }
2396
2397 return true;
2398}
2399
2400/// Does Ptr point to the last object AND to a flexible array member?
2401static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const Pointer &Ptr) {
2402 auto isFlexibleArrayMember = [&](const Descriptor *FieldDesc) {
2404 FAMKind StrictFlexArraysLevel =
2405 Ctx.getLangOpts().getStrictFlexArraysLevel();
2406
2407 if (StrictFlexArraysLevel == FAMKind::Default)
2408 return true;
2409
2410 unsigned NumElems = FieldDesc->getNumElems();
2411 if (NumElems == 0 && StrictFlexArraysLevel != FAMKind::IncompleteOnly)
2412 return true;
2413
2414 if (NumElems == 1 && StrictFlexArraysLevel == FAMKind::OneZeroOrIncomplete)
2415 return true;
2416 return false;
2417 };
2418
2419 const Descriptor *FieldDesc = Ptr.getFieldDesc();
2420 if (!FieldDesc->isArray())
2421 return false;
2422
2423 return Ptr.isDummy() && pointsToLastObject(Ptr) &&
2424 isFlexibleArrayMember(FieldDesc);
2425}
2426
2428 const InterpFrame *Frame,
2429 const CallExpr *Call) {
2430 const ASTContext &ASTCtx = S.getASTContext();
2431 PrimType KindT = *S.getContext().classify(Call->getArg(1));
2432 // From the GCC docs:
2433 // Kind is an integer constant from 0 to 3. If the least significant bit is
2434 // clear, objects are whole variables. If it is set, a closest surrounding
2435 // subobject is considered the object a pointer points to. The second bit
2436 // determines if maximum or minimum of remaining bytes is computed.
2437 unsigned Kind = popToAPSInt(S.Stk, KindT).getZExtValue();
2438 assert(Kind <= 3 && "unexpected kind");
2439 bool UseFieldDesc = (Kind & 1u);
2440 bool ReportMinimum = (Kind & 2u);
2441 const Pointer &Ptr = S.Stk.pop<Pointer>();
2442
2443 if (Call->getArg(0)->HasSideEffects(ASTCtx)) {
2444 // "If there are any side effects in them, it returns (size_t) -1
2445 // for type 0 or 1 and (size_t) 0 for type 2 or 3."
2446 pushInteger(S, Kind <= 1 ? -1 : 0, Call->getType());
2447 return true;
2448 }
2449
2450 if (Ptr.isZero() || !Ptr.isBlockPointer())
2451 return false;
2452
2453 // We can't load through pointers.
2454 if (Ptr.isDummy() && Ptr.getType()->isPointerType())
2455 return false;
2456
2457 bool DetermineForCompleteObject = Ptr.getFieldDesc() == Ptr.getDeclDesc();
2458 const Descriptor *DeclDesc = Ptr.getDeclDesc();
2459 assert(DeclDesc);
2460
2461 if (!UseFieldDesc || DetermineForCompleteObject) {
2462 // Lower bound, so we can't fall back to this.
2463 if (ReportMinimum && !DetermineForCompleteObject)
2464 return false;
2465
2466 // Can't read beyond the pointer decl desc.
2467 if (!UseFieldDesc && !ReportMinimum && DeclDesc->getType()->isPointerType())
2468 return false;
2469 } else {
2470 if (isUserWritingOffTheEnd(ASTCtx, Ptr.expand())) {
2471 // If we cannot determine the size of the initial allocation, then we
2472 // can't given an accurate upper-bound. However, we are still able to give
2473 // conservative lower-bounds for Type=3.
2474 if (Kind == 1)
2475 return false;
2476 }
2477 }
2478
2479 const Descriptor *Desc = UseFieldDesc ? Ptr.getFieldDesc() : DeclDesc;
2480 assert(Desc);
2481
2482 std::optional<unsigned> FullSize = computeFullDescSize(ASTCtx, Desc);
2483 if (!FullSize)
2484 return false;
2485
2486 unsigned ByteOffset;
2487 if (UseFieldDesc) {
2488 if (Ptr.isBaseClass())
2489 ByteOffset = computePointerOffset(ASTCtx, Ptr.getBase()) -
2490 computePointerOffset(ASTCtx, Ptr);
2491 else
2492 ByteOffset =
2493 computePointerOffset(ASTCtx, Ptr) -
2494 computePointerOffset(ASTCtx, Ptr.expand().atIndex(0).narrow());
2495 } else
2496 ByteOffset = computePointerOffset(ASTCtx, Ptr);
2497
2498 assert(ByteOffset <= *FullSize);
2499 unsigned Result = *FullSize - ByteOffset;
2500
2501 pushInteger(S, Result, Call->getType());
2502 return true;
2503}
2504
2506 const CallExpr *Call) {
2507
2508 if (!S.inConstantContext())
2509 return false;
2510
2511 const Pointer &Ptr = S.Stk.pop<Pointer>();
2512
2513 auto Error = [&](int Diag) {
2514 bool CalledFromStd = false;
2515 const auto *Callee = S.Current->getCallee();
2516 if (Callee && Callee->isInStdNamespace()) {
2517 const IdentifierInfo *Identifier = Callee->getIdentifier();
2518 CalledFromStd = Identifier && Identifier->isStr("is_within_lifetime");
2519 }
2520 S.CCEDiag(CalledFromStd
2522 : S.Current->getSource(OpPC),
2523 diag::err_invalid_is_within_lifetime)
2524 << (CalledFromStd ? "std::is_within_lifetime"
2525 : "__builtin_is_within_lifetime")
2526 << Diag;
2527 return false;
2528 };
2529
2530 if (Ptr.isZero())
2531 return Error(0);
2532 if (Ptr.isOnePastEnd())
2533 return Error(1);
2534
2535 bool Result = Ptr.getLifetime() != Lifetime::Ended;
2536 if (!Ptr.isActive()) {
2537 Result = false;
2538 } else {
2539 if (!CheckLive(S, OpPC, Ptr, AK_Read))
2540 return false;
2541 if (!CheckMutable(S, OpPC, Ptr))
2542 return false;
2543 if (!CheckDummy(S, OpPC, Ptr.block(), AK_Read))
2544 return false;
2545 }
2546
2547 // Check if we're currently running an initializer.
2548 if (llvm::is_contained(S.InitializingBlocks, Ptr.block()))
2549 return Error(2);
2550 if (S.EvaluatingDecl && Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl)
2551 return Error(2);
2552
2553 pushInteger(S, Result, Call->getType());
2554 return true;
2555}
2556
2558 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2559 llvm::function_ref<APInt(const APSInt &, const APSInt &)> Fn) {
2560 assert(Call->getNumArgs() == 2);
2561
2562 // Single integer case.
2563 if (!Call->getArg(0)->getType()->isVectorType()) {
2564 assert(!Call->getArg(1)->getType()->isVectorType());
2565 APSInt RHS = popToAPSInt(
2566 S.Stk, *S.getContext().classify(Call->getArg(1)->getType()));
2567 APSInt LHS = popToAPSInt(
2568 S.Stk, *S.getContext().classify(Call->getArg(0)->getType()));
2569 APInt Result = Fn(LHS, RHS);
2570 pushInteger(S, APSInt(std::move(Result), !LHS.isSigned()), Call->getType());
2571 return true;
2572 }
2573
2574 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2575 assert(VT->getElementType()->isIntegralOrEnumerationType());
2576 PrimType ElemT = *S.getContext().classify(VT->getElementType());
2577 unsigned NumElems = VT->getNumElements();
2578 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
2579
2580 // Vector + Scalar case.
2581 if (!Call->getArg(1)->getType()->isVectorType()) {
2582 assert(Call->getArg(1)->getType()->isIntegralOrEnumerationType());
2583
2584 APSInt RHS = popToAPSInt(
2585 S.Stk, *S.getContext().classify(Call->getArg(1)->getType()));
2586 const Pointer &LHS = S.Stk.pop<Pointer>();
2587 const Pointer &Dst = S.Stk.peek<Pointer>();
2588
2589 for (unsigned I = 0; I != NumElems; ++I) {
2591 Dst.elem<T>(I) = static_cast<T>(
2592 APSInt(Fn(LHS.elem<T>(I).toAPSInt(), RHS), DestUnsigned));
2593 });
2594 }
2596 return true;
2597 }
2598
2599 // Vector case.
2600 assert(Call->getArg(0)->getType()->isVectorType() &&
2601 Call->getArg(1)->getType()->isVectorType());
2602 assert(VT->getElementType() ==
2603 Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());
2604 assert(VT->getNumElements() ==
2605 Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());
2606 assert(VT->getElementType()->isIntegralOrEnumerationType());
2607
2608 const Pointer &RHS = S.Stk.pop<Pointer>();
2609 const Pointer &LHS = S.Stk.pop<Pointer>();
2610 const Pointer &Dst = S.Stk.peek<Pointer>();
2611 for (unsigned I = 0; I != NumElems; ++I) {
2613 APSInt Elem1 = LHS.elem<T>(I).toAPSInt();
2614 APSInt Elem2 = RHS.elem<T>(I).toAPSInt();
2615 Dst.elem<T>(I) = static_cast<T>(APSInt(Fn(Elem1, Elem2), DestUnsigned));
2616 });
2617 }
2619
2620 return true;
2621}
2622
2624 const CallExpr *Call,
2625 unsigned BuiltinID) {
2626 assert(Call->getNumArgs() == 2);
2627
2628 QualType Arg0Type = Call->getArg(0)->getType();
2629
2630 // TODO: Support floating-point types.
2631 if (!(Arg0Type->isIntegerType() ||
2632 (Arg0Type->isVectorType() &&
2633 Arg0Type->castAs<VectorType>()->getElementType()->isIntegerType())))
2634 return false;
2635
2636 if (!Arg0Type->isVectorType()) {
2637 assert(!Call->getArg(1)->getType()->isVectorType());
2638 APSInt RHS = popToAPSInt(
2639 S.Stk, *S.getContext().classify(Call->getArg(1)->getType()));
2640 APSInt LHS = popToAPSInt(
2641 S.Stk, *S.getContext().classify(Call->getArg(0)->getType()));
2642 APInt Result;
2643 if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
2644 Result = std::max(LHS, RHS);
2645 } else if (BuiltinID == Builtin::BI__builtin_elementwise_min) {
2646 Result = std::min(LHS, RHS);
2647 } else {
2648 llvm_unreachable("Wrong builtin ID");
2649 }
2650
2651 pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType());
2652 return true;
2653 }
2654
2655 // Vector case.
2656 assert(Call->getArg(0)->getType()->isVectorType() &&
2657 Call->getArg(1)->getType()->isVectorType());
2658 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2659 assert(VT->getElementType() ==
2660 Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());
2661 assert(VT->getNumElements() ==
2662 Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());
2663 assert(VT->getElementType()->isIntegralOrEnumerationType());
2664
2665 const Pointer &RHS = S.Stk.pop<Pointer>();
2666 const Pointer &LHS = S.Stk.pop<Pointer>();
2667 const Pointer &Dst = S.Stk.peek<Pointer>();
2668 PrimType ElemT = *S.getContext().classify(VT->getElementType());
2669 unsigned NumElems = VT->getNumElements();
2670 for (unsigned I = 0; I != NumElems; ++I) {
2671 APSInt Elem1;
2672 APSInt Elem2;
2674 Elem1 = LHS.elem<T>(I).toAPSInt();
2675 Elem2 = RHS.elem<T>(I).toAPSInt();
2676 });
2677
2678 APSInt Result;
2679 if (BuiltinID == Builtin::BI__builtin_elementwise_max) {
2680 Result = APSInt(std::max(Elem1, Elem2),
2681 Call->getType()->isUnsignedIntegerOrEnumerationType());
2682 } else if (BuiltinID == Builtin::BI__builtin_elementwise_min) {
2683 Result = APSInt(std::min(Elem1, Elem2),
2684 Call->getType()->isUnsignedIntegerOrEnumerationType());
2685 } else {
2686 llvm_unreachable("Wrong builtin ID");
2687 }
2688
2690 { Dst.elem<T>(I) = static_cast<T>(Result); });
2691 }
2692 Dst.initializeAllElements();
2693
2694 return true;
2695}
2696
2698 const CallExpr *Call,
2699 unsigned BuiltinID) {
2700 assert(Call->getArg(0)->getType()->isVectorType() &&
2701 Call->getArg(1)->getType()->isVectorType());
2702 const Pointer &RHS = S.Stk.pop<Pointer>();
2703 const Pointer &LHS = S.Stk.pop<Pointer>();
2704 const Pointer &Dst = S.Stk.peek<Pointer>();
2705
2706 const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2707 PrimType ElemT = *S.getContext().classify(VT->getElementType());
2708 unsigned SourceLen = VT->getNumElements();
2709
2710 PrimType DstElemT = *S.getContext().classify(
2711 Call->getType()->castAs<VectorType>()->getElementType());
2712 unsigned DstElem = 0;
2713 for (unsigned I = 0; I != SourceLen; I += 2) {
2714 APSInt Elem1;
2715 APSInt Elem2;
2717 Elem1 = LHS.elem<T>(I).toAPSInt();
2718 Elem2 = RHS.elem<T>(I).toAPSInt();
2719 });
2720
2721 APSInt Result;
2722 switch (BuiltinID) {
2723 case clang::X86::BI__builtin_ia32_pmuludq128:
2724 case clang::X86::BI__builtin_ia32_pmuludq256:
2725 case clang::X86::BI__builtin_ia32_pmuludq512:
2726 Result = APSInt(llvm::APIntOps::muluExtended(Elem1, Elem2),
2727 /*IsUnsigned=*/true);
2728 break;
2729 case clang::X86::BI__builtin_ia32_pmuldq128:
2730 case clang::X86::BI__builtin_ia32_pmuldq256:
2731 case clang::X86::BI__builtin_ia32_pmuldq512:
2732 Result = APSInt(llvm::APIntOps::mulsExtended(Elem1, Elem2),
2733 /*IsUnsigned=*/false);
2734 break;
2735 }
2736 INT_TYPE_SWITCH_NO_BOOL(DstElemT,
2737 { Dst.elem<T>(DstElem) = static_cast<T>(Result); });
2738 ++DstElem;
2739 }
2740
2741 Dst.initializeAllElements();
2742 return true;
2743}
2744
2746 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2747 llvm::function_ref<APFloat(const APFloat &, const APFloat &,
2748 const APFloat &, llvm::RoundingMode)>
2749 Fn) {
2750 assert(Call->getNumArgs() == 3);
2751
2752 FPOptions FPO = Call->getFPFeaturesInEffect(S.Ctx.getLangOpts());
2753 llvm::RoundingMode RM = getRoundingMode(FPO);
2754 const QualType Arg1Type = Call->getArg(0)->getType();
2755 const QualType Arg2Type = Call->getArg(1)->getType();
2756 const QualType Arg3Type = Call->getArg(2)->getType();
2757
2758 // Non-vector floating point types.
2759 if (!Arg1Type->isVectorType()) {
2760 assert(!Arg2Type->isVectorType());
2761 assert(!Arg3Type->isVectorType());
2762 (void)Arg2Type;
2763 (void)Arg3Type;
2764
2765 const Floating &Z = S.Stk.pop<Floating>();
2766 const Floating &Y = S.Stk.pop<Floating>();
2767 const Floating &X = S.Stk.pop<Floating>();
2768 APFloat F = Fn(X.getAPFloat(), Y.getAPFloat(), Z.getAPFloat(), RM);
2769 Floating Result = S.allocFloat(X.getSemantics());
2770 Result.copy(F);
2771 S.Stk.push<Floating>(Result);
2772 return true;
2773 }
2774
2775 // Vector type.
2776 assert(Arg1Type->isVectorType() && Arg2Type->isVectorType() &&
2777 Arg3Type->isVectorType());
2778
2779 const VectorType *VecT = Arg1Type->castAs<VectorType>();
2780 const QualType ElemT = VecT->getElementType();
2781 unsigned NumElems = VecT->getNumElements();
2782
2783 assert(ElemT == Arg2Type->castAs<VectorType>()->getElementType() &&
2784 ElemT == Arg3Type->castAs<VectorType>()->getElementType());
2785 assert(NumElems == Arg2Type->castAs<VectorType>()->getNumElements() &&
2786 NumElems == Arg3Type->castAs<VectorType>()->getNumElements());
2787 assert(ElemT->isRealFloatingType());
2788 (void)ElemT;
2789
2790 const Pointer &VZ = S.Stk.pop<Pointer>();
2791 const Pointer &VY = S.Stk.pop<Pointer>();
2792 const Pointer &VX = S.Stk.pop<Pointer>();
2793 const Pointer &Dst = S.Stk.peek<Pointer>();
2794 for (unsigned I = 0; I != NumElems; ++I) {
2795 using T = PrimConv<PT_Float>::T;
2796 APFloat X = VX.elem<T>(I).getAPFloat();
2797 APFloat Y = VY.elem<T>(I).getAPFloat();
2798 APFloat Z = VZ.elem<T>(I).getAPFloat();
2799 APFloat F = Fn(X, Y, Z, RM);
2800 Dst.elem<Floating>(I) = Floating(F);
2801 }
2803 return true;
2804}
2805
2806/// AVX512 predicated move: "Result = Mask[] ? LHS[] : RHS[]".
2808 const CallExpr *Call) {
2809 const Pointer &RHS = S.Stk.pop<Pointer>();
2810 const Pointer &LHS = S.Stk.pop<Pointer>();
2811 PrimType MaskT = *S.getContext().classify(Call->getArg(0));
2812 APSInt Mask = popToAPSInt(S.Stk, MaskT);
2813 const Pointer &Dst = S.Stk.peek<Pointer>();
2814
2815 assert(LHS.getNumElems() == RHS.getNumElems());
2816 assert(LHS.getNumElems() == Dst.getNumElems());
2817 unsigned NumElems = LHS.getNumElems();
2818 PrimType ElemT = LHS.getFieldDesc()->getPrimType();
2819 PrimType DstElemT = Dst.getFieldDesc()->getPrimType();
2820
2821 for (unsigned I = 0; I != NumElems; ++I) {
2822 if (ElemT == PT_Float) {
2823 assert(DstElemT == PT_Float);
2824 Dst.elem<Floating>(I) =
2825 Mask[I] ? LHS.elem<Floating>(I) : RHS.elem<Floating>(I);
2826 } else {
2827 APSInt Elem;
2828 INT_TYPE_SWITCH(ElemT, {
2829 Elem = Mask[I] ? LHS.elem<T>(I).toAPSInt() : RHS.elem<T>(I).toAPSInt();
2830 });
2831 INT_TYPE_SWITCH_NO_BOOL(DstElemT,
2832 { Dst.elem<T>(I) = static_cast<T>(Elem); });
2833 }
2834 }
2836
2837 return true;
2838}
2839
2841 const CallExpr *Call) {
2842 PrimType MaskT = *S.getContext().classify(Call->getArg(2));
2843 APSInt Mask = popToAPSInt(S.Stk, MaskT);
2844 const Pointer &TrueVec = S.Stk.pop<Pointer>();
2845 const Pointer &FalseVec = S.Stk.pop<Pointer>();
2846 const Pointer &Dst = S.Stk.peek<Pointer>();
2847
2848 assert(FalseVec.getNumElems() == TrueVec.getNumElems());
2849 assert(FalseVec.getNumElems() == Dst.getNumElems());
2850 unsigned NumElems = FalseVec.getNumElems();
2851 PrimType ElemT = FalseVec.getFieldDesc()->getPrimType();
2852 PrimType DstElemT = Dst.getFieldDesc()->getPrimType();
2853
2854 for (unsigned I = 0; I != NumElems; ++I) {
2855 bool MaskBit = Mask[I % 8];
2856 if (ElemT == PT_Float) {
2857 assert(DstElemT == PT_Float);
2858 Dst.elem<Floating>(I) =
2859 MaskBit ? TrueVec.elem<Floating>(I) : FalseVec.elem<Floating>(I);
2860 } else {
2861 assert(DstElemT == ElemT);
2862 INT_TYPE_SWITCH_NO_BOOL(DstElemT, {
2863 Dst.elem<T>(I) =
2864 static_cast<T>(MaskBit ? TrueVec.elem<T>(I).toAPSInt()
2865 : FalseVec.elem<T>(I).toAPSInt());
2866 });
2867 }
2868 }
2869 Dst.initializeAllElements();
2870
2871 return true;
2872}
2873
2875 InterpState &S, CodePtr OpPC, const CallExpr *Call,
2876 llvm::function_ref<APInt(const APSInt &, const APSInt &, const APSInt &)>
2877 Fn) {
2878 assert(Call->getNumArgs() == 3);
2879
2880 QualType Arg0Type = Call->getArg(0)->getType();
2881 QualType Arg1Type = Call->getArg(1)->getType();
2882 QualType Arg2Type = Call->getArg(2)->getType();
2883
2884 // Non-vector integer types.
2885 if (!Arg0Type->isVectorType()) {
2886 const APSInt &Op2 = popToAPSInt(S.Stk, *S.getContext().classify(Arg2Type));
2887 const APSInt &Op1 = popToAPSInt(S.Stk, *S.getContext().classify(Arg1Type));
2888 const APSInt &Op0 = popToAPSInt(S.Stk, *S.getContext().classify(Arg0Type));
2889 APSInt Result = APSInt(Fn(Op0, Op1, Op2), Op0.isUnsigned());
2890 pushInteger(S, Result, Call->getType());
2891 return true;
2892 }
2893
2894 const auto *VecT = Arg0Type->castAs<VectorType>();
2895 const PrimType &ElemT = *S.getContext().classify(VecT->getElementType());
2896 unsigned NumElems = VecT->getNumElements();
2897 bool DestUnsigned = Call->getType()->isUnsignedIntegerOrEnumerationType();
2898
2899 // Vector + Vector + Scalar case.
2900 if (!Arg2Type->isVectorType()) {
2901 APSInt Op2 = popToAPSInt(
2902 S.Stk, *S.getContext().classify(Call->getArg(2)->getType()));
2903
2904 const Pointer &Op1 = S.Stk.pop<Pointer>();
2905 const Pointer &Op0 = S.Stk.pop<Pointer>();
2906 const Pointer &Dst = S.Stk.peek<Pointer>();
2907 for (unsigned I = 0; I != NumElems; ++I) {
2909 Dst.elem<T>(I) = static_cast<T>(APSInt(
2910 Fn(Op0.elem<T>(I).toAPSInt(), Op1.elem<T>(I).toAPSInt(), Op2),
2911 DestUnsigned));
2912 });
2913 }
2915
2916 return true;
2917 }
2918
2919 // Vector type.
2920 const Pointer &Op2 = S.Stk.pop<Pointer>();
2921 const Pointer &Op1 = S.Stk.pop<Pointer>();
2922 const Pointer &Op0 = S.Stk.pop<Pointer>();
2923 const Pointer &Dst = S.Stk.peek<Pointer>();
2924 for (unsigned I = 0; I != NumElems; ++I) {
2925 APSInt Val0, Val1, Val2;
2927 Val0 = Op0.elem<T>(I).toAPSInt();
2928 Val1 = Op1.elem<T>(I).toAPSInt();
2929 Val2 = Op2.elem<T>(I).toAPSInt();
2930 });
2931 APSInt Result = APSInt(Fn(Val0, Val1, Val2), Val0.isUnsigned());
2933 { Dst.elem<T>(I) = static_cast<T>(Result); });
2934 }
2936
2937 return true;
2938}
2939
2941 uint32_t BuiltinID) {
2942 if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID))
2943 return Invalid(S, OpPC);
2944
2945 const InterpFrame *Frame = S.Current;
2946 switch (BuiltinID) {
2947 case Builtin::BI__builtin_is_constant_evaluated:
2949
2950 case Builtin::BI__builtin_assume:
2951 case Builtin::BI__assume:
2952 return interp__builtin_assume(S, OpPC, Frame, Call);
2953
2954 case Builtin::BI__builtin_strcmp:
2955 case Builtin::BIstrcmp:
2956 case Builtin::BI__builtin_strncmp:
2957 case Builtin::BIstrncmp:
2958 case Builtin::BI__builtin_wcsncmp:
2959 case Builtin::BIwcsncmp:
2960 case Builtin::BI__builtin_wcscmp:
2961 case Builtin::BIwcscmp:
2962 return interp__builtin_strcmp(S, OpPC, Frame, Call, BuiltinID);
2963
2964 case Builtin::BI__builtin_strlen:
2965 case Builtin::BIstrlen:
2966 case Builtin::BI__builtin_wcslen:
2967 case Builtin::BIwcslen:
2968 return interp__builtin_strlen(S, OpPC, Frame, Call, BuiltinID);
2969
2970 case Builtin::BI__builtin_nan:
2971 case Builtin::BI__builtin_nanf:
2972 case Builtin::BI__builtin_nanl:
2973 case Builtin::BI__builtin_nanf16:
2974 case Builtin::BI__builtin_nanf128:
2975 return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/false);
2976
2977 case Builtin::BI__builtin_nans:
2978 case Builtin::BI__builtin_nansf:
2979 case Builtin::BI__builtin_nansl:
2980 case Builtin::BI__builtin_nansf16:
2981 case Builtin::BI__builtin_nansf128:
2982 return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/true);
2983
2984 case Builtin::BI__builtin_huge_val:
2985 case Builtin::BI__builtin_huge_valf:
2986 case Builtin::BI__builtin_huge_vall:
2987 case Builtin::BI__builtin_huge_valf16:
2988 case Builtin::BI__builtin_huge_valf128:
2989 case Builtin::BI__builtin_inf:
2990 case Builtin::BI__builtin_inff:
2991 case Builtin::BI__builtin_infl:
2992 case Builtin::BI__builtin_inff16:
2993 case Builtin::BI__builtin_inff128:
2994 return interp__builtin_inf(S, OpPC, Frame, Call);
2995
2996 case Builtin::BI__builtin_copysign:
2997 case Builtin::BI__builtin_copysignf:
2998 case Builtin::BI__builtin_copysignl:
2999 case Builtin::BI__builtin_copysignf128:
3000 return interp__builtin_copysign(S, OpPC, Frame);
3001
3002 case Builtin::BI__builtin_fmin:
3003 case Builtin::BI__builtin_fminf:
3004 case Builtin::BI__builtin_fminl:
3005 case Builtin::BI__builtin_fminf16:
3006 case Builtin::BI__builtin_fminf128:
3007 return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/false);
3008
3009 case Builtin::BI__builtin_fminimum_num:
3010 case Builtin::BI__builtin_fminimum_numf:
3011 case Builtin::BI__builtin_fminimum_numl:
3012 case Builtin::BI__builtin_fminimum_numf16:
3013 case Builtin::BI__builtin_fminimum_numf128:
3014 return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/true);
3015
3016 case Builtin::BI__builtin_fmax:
3017 case Builtin::BI__builtin_fmaxf:
3018 case Builtin::BI__builtin_fmaxl:
3019 case Builtin::BI__builtin_fmaxf16:
3020 case Builtin::BI__builtin_fmaxf128:
3021 return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/false);
3022
3023 case Builtin::BI__builtin_fmaximum_num:
3024 case Builtin::BI__builtin_fmaximum_numf:
3025 case Builtin::BI__builtin_fmaximum_numl:
3026 case Builtin::BI__builtin_fmaximum_numf16:
3027 case Builtin::BI__builtin_fmaximum_numf128:
3028 return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/true);
3029
3030 case Builtin::BI__builtin_isnan:
3031 return interp__builtin_isnan(S, OpPC, Frame, Call);
3032
3033 case Builtin::BI__builtin_issignaling:
3034 return interp__builtin_issignaling(S, OpPC, Frame, Call);
3035
3036 case Builtin::BI__builtin_isinf:
3037 return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/false, Call);
3038
3039 case Builtin::BI__builtin_isinf_sign:
3040 return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/true, Call);
3041
3042 case Builtin::BI__builtin_isfinite:
3043 return interp__builtin_isfinite(S, OpPC, Frame, Call);
3044
3045 case Builtin::BI__builtin_isnormal:
3046 return interp__builtin_isnormal(S, OpPC, Frame, Call);
3047
3048 case Builtin::BI__builtin_issubnormal:
3049 return interp__builtin_issubnormal(S, OpPC, Frame, Call);
3050
3051 case Builtin::BI__builtin_iszero:
3052 return interp__builtin_iszero(S, OpPC, Frame, Call);
3053
3054 case Builtin::BI__builtin_signbit:
3055 case Builtin::BI__builtin_signbitf:
3056 case Builtin::BI__builtin_signbitl:
3057 return interp__builtin_signbit(S, OpPC, Frame, Call);
3058
3059 case Builtin::BI__builtin_isgreater:
3060 case Builtin::BI__builtin_isgreaterequal:
3061 case Builtin::BI__builtin_isless:
3062 case Builtin::BI__builtin_islessequal:
3063 case Builtin::BI__builtin_islessgreater:
3064 case Builtin::BI__builtin_isunordered:
3065 return interp_floating_comparison(S, OpPC, Call, BuiltinID);
3066
3067 case Builtin::BI__builtin_isfpclass:
3068 return interp__builtin_isfpclass(S, OpPC, Frame, Call);
3069
3070 case Builtin::BI__builtin_fpclassify:
3071 return interp__builtin_fpclassify(S, OpPC, Frame, Call);
3072
3073 case Builtin::BI__builtin_fabs:
3074 case Builtin::BI__builtin_fabsf:
3075 case Builtin::BI__builtin_fabsl:
3076 case Builtin::BI__builtin_fabsf128:
3077 return interp__builtin_fabs(S, OpPC, Frame);
3078
3079 case Builtin::BI__builtin_abs:
3080 case Builtin::BI__builtin_labs:
3081 case Builtin::BI__builtin_llabs:
3082 return interp__builtin_abs(S, OpPC, Frame, Call);
3083
3084 case Builtin::BI__builtin_popcount:
3085 case Builtin::BI__builtin_popcountl:
3086 case Builtin::BI__builtin_popcountll:
3087 case Builtin::BI__builtin_popcountg:
3088 case Builtin::BI__popcnt16: // Microsoft variants of popcount
3089 case Builtin::BI__popcnt:
3090 case Builtin::BI__popcnt64:
3091 return interp__builtin_popcount(S, OpPC, Frame, Call);
3092
3093 case Builtin::BI__builtin_parity:
3094 case Builtin::BI__builtin_parityl:
3095 case Builtin::BI__builtin_parityll:
3096 return interp__builtin_parity(S, OpPC, Frame, Call);
3097
3098 case Builtin::BI__builtin_clrsb:
3099 case Builtin::BI__builtin_clrsbl:
3100 case Builtin::BI__builtin_clrsbll:
3101 return interp__builtin_clrsb(S, OpPC, Frame, Call);
3102
3103 case Builtin::BI__builtin_bitreverse8:
3104 case Builtin::BI__builtin_bitreverse16:
3105 case Builtin::BI__builtin_bitreverse32:
3106 case Builtin::BI__builtin_bitreverse64:
3107 return interp__builtin_bitreverse(S, OpPC, Frame, Call);
3108
3109 case Builtin::BI__builtin_classify_type:
3110 return interp__builtin_classify_type(S, OpPC, Frame, Call);
3111
3112 case Builtin::BI__builtin_expect:
3113 case Builtin::BI__builtin_expect_with_probability:
3114 return interp__builtin_expect(S, OpPC, Frame, Call);
3115
3116 case Builtin::BI__builtin_rotateleft8:
3117 case Builtin::BI__builtin_rotateleft16:
3118 case Builtin::BI__builtin_rotateleft32:
3119 case Builtin::BI__builtin_rotateleft64:
3120 case Builtin::BI_rotl8: // Microsoft variants of rotate left
3121 case Builtin::BI_rotl16:
3122 case Builtin::BI_rotl:
3123 case Builtin::BI_lrotl:
3124 case Builtin::BI_rotl64:
3125 return interp__builtin_rotate(S, OpPC, Frame, Call, /*Right=*/false);
3126
3127 case Builtin::BI__builtin_rotateright8:
3128 case Builtin::BI__builtin_rotateright16:
3129 case Builtin::BI__builtin_rotateright32:
3130 case Builtin::BI__builtin_rotateright64:
3131 case Builtin::BI_rotr8: // Microsoft variants of rotate right
3132 case Builtin::BI_rotr16:
3133 case Builtin::BI_rotr:
3134 case Builtin::BI_lrotr:
3135 case Builtin::BI_rotr64:
3136 return interp__builtin_rotate(S, OpPC, Frame, Call, /*Right=*/true);
3137
3138 case Builtin::BI__builtin_ffs:
3139 case Builtin::BI__builtin_ffsl:
3140 case Builtin::BI__builtin_ffsll:
3141 return interp__builtin_ffs(S, OpPC, Frame, Call);
3142
3143 case Builtin::BIaddressof:
3144 case Builtin::BI__addressof:
3145 case Builtin::BI__builtin_addressof:
3146 assert(isNoopBuiltin(BuiltinID));
3147 return interp__builtin_addressof(S, OpPC, Frame, Call);
3148
3149 case Builtin::BIas_const:
3150 case Builtin::BIforward:
3151 case Builtin::BIforward_like:
3152 case Builtin::BImove:
3153 case Builtin::BImove_if_noexcept:
3154 assert(isNoopBuiltin(BuiltinID));
3155 return interp__builtin_move(S, OpPC, Frame, Call);
3156
3157 case Builtin::BI__builtin_eh_return_data_regno:
3159
3160 case Builtin::BI__builtin_launder:
3161 assert(isNoopBuiltin(BuiltinID));
3162 return true;
3163
3164 case Builtin::BI__builtin_add_overflow:
3165 case Builtin::BI__builtin_sub_overflow:
3166 case Builtin::BI__builtin_mul_overflow:
3167 case Builtin::BI__builtin_sadd_overflow:
3168 case Builtin::BI__builtin_uadd_overflow:
3169 case Builtin::BI__builtin_uaddl_overflow:
3170 case Builtin::BI__builtin_uaddll_overflow:
3171 case Builtin::BI__builtin_usub_overflow:
3172 case Builtin::BI__builtin_usubl_overflow:
3173 case Builtin::BI__builtin_usubll_overflow:
3174 case Builtin::BI__builtin_umul_overflow:
3175 case Builtin::BI__builtin_umull_overflow:
3176 case Builtin::BI__builtin_umulll_overflow:
3177 case Builtin::BI__builtin_saddl_overflow:
3178 case Builtin::BI__builtin_saddll_overflow:
3179 case Builtin::BI__builtin_ssub_overflow:
3180 case Builtin::BI__builtin_ssubl_overflow:
3181 case Builtin::BI__builtin_ssubll_overflow:
3182 case Builtin::BI__builtin_smul_overflow:
3183 case Builtin::BI__builtin_smull_overflow:
3184 case Builtin::BI__builtin_smulll_overflow:
3185 return interp__builtin_overflowop(S, OpPC, Call, BuiltinID);
3186
3187 case Builtin::BI__builtin_addcb:
3188 case Builtin::BI__builtin_addcs:
3189 case Builtin::BI__builtin_addc:
3190 case Builtin::BI__builtin_addcl:
3191 case Builtin::BI__builtin_addcll:
3192 case Builtin::BI__builtin_subcb:
3193 case Builtin::BI__builtin_subcs:
3194 case Builtin::BI__builtin_subc:
3195 case Builtin::BI__builtin_subcl:
3196 case Builtin::BI__builtin_subcll:
3197 return interp__builtin_carryop(S, OpPC, Frame, Call, BuiltinID);
3198
3199 case Builtin::BI__builtin_clz:
3200 case Builtin::BI__builtin_clzl:
3201 case Builtin::BI__builtin_clzll:
3202 case Builtin::BI__builtin_clzs:
3203 case Builtin::BI__builtin_clzg:
3204 case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
3205 case Builtin::BI__lzcnt:
3206 case Builtin::BI__lzcnt64:
3207 return interp__builtin_clz(S, OpPC, Frame, Call, BuiltinID);
3208
3209 case Builtin::BI__builtin_ctz:
3210 case Builtin::BI__builtin_ctzl:
3211 case Builtin::BI__builtin_ctzll:
3212 case Builtin::BI__builtin_ctzs:
3213 case Builtin::BI__builtin_ctzg:
3214 return interp__builtin_ctz(S, OpPC, Frame, Call, BuiltinID);
3215
3216 case Builtin::BI__builtin_elementwise_ctlz:
3217 case Builtin::BI__builtin_elementwise_cttz:
3219 BuiltinID);
3220
3221 case Builtin::BI__builtin_bswap16:
3222 case Builtin::BI__builtin_bswap32:
3223 case Builtin::BI__builtin_bswap64:
3224 return interp__builtin_bswap(S, OpPC, Frame, Call);
3225
3226 case Builtin::BI__atomic_always_lock_free:
3227 case Builtin::BI__atomic_is_lock_free:
3228 return interp__builtin_atomic_lock_free(S, OpPC, Frame, Call, BuiltinID);
3229
3230 case Builtin::BI__c11_atomic_is_lock_free:
3232
3233 case Builtin::BI__builtin_complex:
3234 return interp__builtin_complex(S, OpPC, Frame, Call);
3235
3236 case Builtin::BI__builtin_is_aligned:
3237 case Builtin::BI__builtin_align_up:
3238 case Builtin::BI__builtin_align_down:
3239 return interp__builtin_is_aligned_up_down(S, OpPC, Frame, Call, BuiltinID);
3240
3241 case Builtin::BI__builtin_assume_aligned:
3242 return interp__builtin_assume_aligned(S, OpPC, Frame, Call);
3243
3244 case clang::X86::BI__builtin_ia32_bextr_u32:
3245 case clang::X86::BI__builtin_ia32_bextr_u64:
3246 case clang::X86::BI__builtin_ia32_bextri_u32:
3247 case clang::X86::BI__builtin_ia32_bextri_u64:
3248 return interp__builtin_ia32_bextr(S, OpPC, Frame, Call);
3249
3250 case clang::X86::BI__builtin_ia32_bzhi_si:
3251 case clang::X86::BI__builtin_ia32_bzhi_di:
3252 return interp__builtin_ia32_bzhi(S, OpPC, Frame, Call);
3253
3254 case clang::X86::BI__builtin_ia32_lzcnt_u16:
3255 case clang::X86::BI__builtin_ia32_lzcnt_u32:
3256 case clang::X86::BI__builtin_ia32_lzcnt_u64:
3257 return interp__builtin_ia32_lzcnt(S, OpPC, Frame, Call);
3258
3259 case clang::X86::BI__builtin_ia32_tzcnt_u16:
3260 case clang::X86::BI__builtin_ia32_tzcnt_u32:
3261 case clang::X86::BI__builtin_ia32_tzcnt_u64:
3262 return interp__builtin_ia32_tzcnt(S, OpPC, Frame, Call);
3263
3264 case clang::X86::BI__builtin_ia32_pdep_si:
3265 case clang::X86::BI__builtin_ia32_pdep_di:
3266 return interp__builtin_ia32_pdep(S, OpPC, Frame, Call);
3267
3268 case clang::X86::BI__builtin_ia32_pext_si:
3269 case clang::X86::BI__builtin_ia32_pext_di:
3270 return interp__builtin_ia32_pext(S, OpPC, Frame, Call);
3271
3272 case clang::X86::BI__builtin_ia32_addcarryx_u32:
3273 case clang::X86::BI__builtin_ia32_addcarryx_u64:
3274 case clang::X86::BI__builtin_ia32_subborrow_u32:
3275 case clang::X86::BI__builtin_ia32_subborrow_u64:
3277 BuiltinID);
3278
3279 case Builtin::BI__builtin_os_log_format_buffer_size:
3281
3282 case Builtin::BI__builtin_ptrauth_string_discriminator:
3284
3285 case Builtin::BI__noop:
3286 pushInteger(S, 0, Call->getType());
3287 return true;
3288
3289 case Builtin::BI__builtin_operator_new:
3290 return interp__builtin_operator_new(S, OpPC, Frame, Call);
3291
3292 case Builtin::BI__builtin_operator_delete:
3293 return interp__builtin_operator_delete(S, OpPC, Frame, Call);
3294
3295 case Builtin::BI__arithmetic_fence:
3297
3298 case Builtin::BI__builtin_reduce_add:
3299 case Builtin::BI__builtin_reduce_mul:
3300 case Builtin::BI__builtin_reduce_and:
3301 case Builtin::BI__builtin_reduce_or:
3302 case Builtin::BI__builtin_reduce_xor:
3303 case Builtin::BI__builtin_reduce_min:
3304 case Builtin::BI__builtin_reduce_max:
3305 return interp__builtin_vector_reduce(S, OpPC, Call, BuiltinID);
3306
3307 case Builtin::BI__builtin_elementwise_popcount:
3308 case Builtin::BI__builtin_elementwise_bitreverse:
3310 BuiltinID);
3311
3312 case Builtin::BI__builtin_elementwise_abs:
3313 return interp__builtin_elementwise_abs(S, OpPC, Frame, Call, BuiltinID);
3314
3315 case Builtin::BI__builtin_memcpy:
3316 case Builtin::BImemcpy:
3317 case Builtin::BI__builtin_wmemcpy:
3318 case Builtin::BIwmemcpy:
3319 case Builtin::BI__builtin_memmove:
3320 case Builtin::BImemmove:
3321 case Builtin::BI__builtin_wmemmove:
3322 case Builtin::BIwmemmove:
3323 return interp__builtin_memcpy(S, OpPC, Frame, Call, BuiltinID);
3324
3325 case Builtin::BI__builtin_memcmp:
3326 case Builtin::BImemcmp:
3327 case Builtin::BI__builtin_bcmp:
3328 case Builtin::BIbcmp:
3329 case Builtin::BI__builtin_wmemcmp:
3330 case Builtin::BIwmemcmp:
3331 return interp__builtin_memcmp(S, OpPC, Frame, Call, BuiltinID);
3332
3333 case Builtin::BImemchr:
3334 case Builtin::BI__builtin_memchr:
3335 case Builtin::BIstrchr:
3336 case Builtin::BI__builtin_strchr:
3337 case Builtin::BIwmemchr:
3338 case Builtin::BI__builtin_wmemchr:
3339 case Builtin::BIwcschr:
3340 case Builtin::BI__builtin_wcschr:
3341 case Builtin::BI__builtin_char_memchr:
3342 return interp__builtin_memchr(S, OpPC, Call, BuiltinID);
3343
3344 case Builtin::BI__builtin_object_size:
3345 case Builtin::BI__builtin_dynamic_object_size:
3346 return interp__builtin_object_size(S, OpPC, Frame, Call);
3347
3348 case Builtin::BI__builtin_is_within_lifetime:
3350
3351 case Builtin::BI__builtin_elementwise_add_sat:
3353 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
3354 return LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS);
3355 });
3356
3357 case Builtin::BI__builtin_elementwise_sub_sat:
3359 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
3360 return LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS);
3361 });
3362
3363 case clang::X86::BI__builtin_ia32_pavgb128:
3364 case clang::X86::BI__builtin_ia32_pavgw128:
3365 case clang::X86::BI__builtin_ia32_pavgb256:
3366 case clang::X86::BI__builtin_ia32_pavgw256:
3367 case clang::X86::BI__builtin_ia32_pavgb512:
3368 case clang::X86::BI__builtin_ia32_pavgw512:
3370 llvm::APIntOps::avgCeilU);
3371
3372 case clang::X86::BI__builtin_ia32_pmulhuw128:
3373 case clang::X86::BI__builtin_ia32_pmulhuw256:
3374 case clang::X86::BI__builtin_ia32_pmulhuw512:
3376 llvm::APIntOps::mulhu);
3377
3378 case clang::X86::BI__builtin_ia32_pmulhw128:
3379 case clang::X86::BI__builtin_ia32_pmulhw256:
3380 case clang::X86::BI__builtin_ia32_pmulhw512:
3382 llvm::APIntOps::mulhs);
3383
3384 case clang::X86::BI__builtin_ia32_psllv2di:
3385 case clang::X86::BI__builtin_ia32_psllv4di:
3386 case clang::X86::BI__builtin_ia32_psllv4si:
3387 case clang::X86::BI__builtin_ia32_psllv8di:
3388 case clang::X86::BI__builtin_ia32_psllv8hi:
3389 case clang::X86::BI__builtin_ia32_psllv8si:
3390 case clang::X86::BI__builtin_ia32_psllv16hi:
3391 case clang::X86::BI__builtin_ia32_psllv16si:
3392 case clang::X86::BI__builtin_ia32_psllv32hi:
3393 case clang::X86::BI__builtin_ia32_psllwi128:
3394 case clang::X86::BI__builtin_ia32_psllwi256:
3395 case clang::X86::BI__builtin_ia32_psllwi512:
3396 case clang::X86::BI__builtin_ia32_pslldi128:
3397 case clang::X86::BI__builtin_ia32_pslldi256:
3398 case clang::X86::BI__builtin_ia32_pslldi512:
3399 case clang::X86::BI__builtin_ia32_psllqi128:
3400 case clang::X86::BI__builtin_ia32_psllqi256:
3401 case clang::X86::BI__builtin_ia32_psllqi512:
3403 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
3404 if (RHS.uge(LHS.getBitWidth())) {
3405 return APInt::getZero(LHS.getBitWidth());
3406 }
3407 return LHS.shl(RHS.getZExtValue());
3408 });
3409
3410 case clang::X86::BI__builtin_ia32_psrav4si:
3411 case clang::X86::BI__builtin_ia32_psrav8di:
3412 case clang::X86::BI__builtin_ia32_psrav8hi:
3413 case clang::X86::BI__builtin_ia32_psrav8si:
3414 case clang::X86::BI__builtin_ia32_psrav16hi:
3415 case clang::X86::BI__builtin_ia32_psrav16si:
3416 case clang::X86::BI__builtin_ia32_psrav32hi:
3417 case clang::X86::BI__builtin_ia32_psravq128:
3418 case clang::X86::BI__builtin_ia32_psravq256:
3419 case clang::X86::BI__builtin_ia32_psrawi128:
3420 case clang::X86::BI__builtin_ia32_psrawi256:
3421 case clang::X86::BI__builtin_ia32_psrawi512:
3422 case clang::X86::BI__builtin_ia32_psradi128:
3423 case clang::X86::BI__builtin_ia32_psradi256:
3424 case clang::X86::BI__builtin_ia32_psradi512:
3425 case clang::X86::BI__builtin_ia32_psraqi128:
3426 case clang::X86::BI__builtin_ia32_psraqi256:
3427 case clang::X86::BI__builtin_ia32_psraqi512:
3429 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
3430 if (RHS.uge(LHS.getBitWidth())) {
3431 return LHS.ashr(LHS.getBitWidth() - 1);
3432 }
3433 return LHS.ashr(RHS.getZExtValue());
3434 });
3435
3436 case clang::X86::BI__builtin_ia32_psrlv2di:
3437 case clang::X86::BI__builtin_ia32_psrlv4di:
3438 case clang::X86::BI__builtin_ia32_psrlv4si:
3439 case clang::X86::BI__builtin_ia32_psrlv8di:
3440 case clang::X86::BI__builtin_ia32_psrlv8hi:
3441 case clang::X86::BI__builtin_ia32_psrlv8si:
3442 case clang::X86::BI__builtin_ia32_psrlv16hi:
3443 case clang::X86::BI__builtin_ia32_psrlv16si:
3444 case clang::X86::BI__builtin_ia32_psrlv32hi:
3445 case clang::X86::BI__builtin_ia32_psrlwi128:
3446 case clang::X86::BI__builtin_ia32_psrlwi256:
3447 case clang::X86::BI__builtin_ia32_psrlwi512:
3448 case clang::X86::BI__builtin_ia32_psrldi128:
3449 case clang::X86::BI__builtin_ia32_psrldi256:
3450 case clang::X86::BI__builtin_ia32_psrldi512:
3451 case clang::X86::BI__builtin_ia32_psrlqi128:
3452 case clang::X86::BI__builtin_ia32_psrlqi256:
3453 case clang::X86::BI__builtin_ia32_psrlqi512:
3455 S, OpPC, Call, [](const APSInt &LHS, const APSInt &RHS) {
3456 if (RHS.uge(LHS.getBitWidth())) {
3457 return APInt::getZero(LHS.getBitWidth());
3458 }
3459 return LHS.lshr(RHS.getZExtValue());
3460 });
3461
3462 case clang::X86::BI__builtin_ia32_vprotbi:
3463 case clang::X86::BI__builtin_ia32_vprotdi:
3464 case clang::X86::BI__builtin_ia32_vprotqi:
3465 case clang::X86::BI__builtin_ia32_vprotwi:
3466 case clang::X86::BI__builtin_ia32_prold128:
3467 case clang::X86::BI__builtin_ia32_prold256:
3468 case clang::X86::BI__builtin_ia32_prold512:
3469 case clang::X86::BI__builtin_ia32_prolq128:
3470 case clang::X86::BI__builtin_ia32_prolq256:
3471 case clang::X86::BI__builtin_ia32_prolq512:
3473 S, OpPC, Call,
3474 [](const APSInt &LHS, const APSInt &RHS) { return LHS.rotl(RHS); });
3475
3476 case clang::X86::BI__builtin_ia32_prord128:
3477 case clang::X86::BI__builtin_ia32_prord256:
3478 case clang::X86::BI__builtin_ia32_prord512:
3479 case clang::X86::BI__builtin_ia32_prorq128:
3480 case clang::X86::BI__builtin_ia32_prorq256:
3481 case clang::X86::BI__builtin_ia32_prorq512:
3483 S, OpPC, Call,
3484 [](const APSInt &LHS, const APSInt &RHS) { return LHS.rotr(RHS); });
3485
3486 case Builtin::BI__builtin_elementwise_max:
3487 case Builtin::BI__builtin_elementwise_min:
3488 return interp__builtin_elementwise_maxmin(S, OpPC, Call, BuiltinID);
3489
3490 case clang::X86::BI__builtin_ia32_pmuldq128:
3491 case clang::X86::BI__builtin_ia32_pmuldq256:
3492 case clang::X86::BI__builtin_ia32_pmuldq512:
3493 case clang::X86::BI__builtin_ia32_pmuludq128:
3494 case clang::X86::BI__builtin_ia32_pmuludq256:
3495 case clang::X86::BI__builtin_ia32_pmuludq512:
3496 return interp__builtin_ia32_pmul(S, OpPC, Call, BuiltinID);
3497
3498 case Builtin::BI__builtin_elementwise_fma:
3500 S, OpPC, Call,
3501 [](const APFloat &X, const APFloat &Y, const APFloat &Z,
3502 llvm::RoundingMode RM) {
3503 APFloat F = X;
3504 F.fusedMultiplyAdd(Y, Z, RM);
3505 return F;
3506 });
3507
3508 case X86::BI__builtin_ia32_vpshldd128:
3509 case X86::BI__builtin_ia32_vpshldd256:
3510 case X86::BI__builtin_ia32_vpshldd512:
3511 case X86::BI__builtin_ia32_vpshldq128:
3512 case X86::BI__builtin_ia32_vpshldq256:
3513 case X86::BI__builtin_ia32_vpshldq512:
3514 case X86::BI__builtin_ia32_vpshldw128:
3515 case X86::BI__builtin_ia32_vpshldw256:
3516 case X86::BI__builtin_ia32_vpshldw512:
3518 S, OpPC, Call,
3519 [](const APSInt &Hi, const APSInt &Lo, const APSInt &Amt) {
3520 return llvm::APIntOps::fshl(Hi, Lo, Amt);
3521 });
3522
3523 case X86::BI__builtin_ia32_vpshrdd128:
3524 case X86::BI__builtin_ia32_vpshrdd256:
3525 case X86::BI__builtin_ia32_vpshrdd512:
3526 case X86::BI__builtin_ia32_vpshrdq128:
3527 case X86::BI__builtin_ia32_vpshrdq256:
3528 case X86::BI__builtin_ia32_vpshrdq512:
3529 case X86::BI__builtin_ia32_vpshrdw128:
3530 case X86::BI__builtin_ia32_vpshrdw256:
3531 case X86::BI__builtin_ia32_vpshrdw512:
3532 // NOTE: Reversed Hi/Lo operands.
3534 S, OpPC, Call,
3535 [](const APSInt &Lo, const APSInt &Hi, const APSInt &Amt) {
3536 return llvm::APIntOps::fshr(Hi, Lo, Amt);
3537 });
3538
3539 case clang::X86::BI__builtin_ia32_blendpd:
3540 case clang::X86::BI__builtin_ia32_blendpd256:
3541 case clang::X86::BI__builtin_ia32_blendps:
3542 case clang::X86::BI__builtin_ia32_blendps256:
3543 case clang::X86::BI__builtin_ia32_pblendw128:
3544 case clang::X86::BI__builtin_ia32_pblendw256:
3545 case clang::X86::BI__builtin_ia32_pblendd128:
3546 case clang::X86::BI__builtin_ia32_pblendd256:
3547 return interp__builtin_blend(S, OpPC, Call);
3548
3549 case clang::X86::BI__builtin_ia32_blendvpd:
3550 case clang::X86::BI__builtin_ia32_blendvpd256:
3551 case clang::X86::BI__builtin_ia32_blendvps:
3552 case clang::X86::BI__builtin_ia32_blendvps256:
3554 S, OpPC, Call,
3555 [](const APFloat &F, const APFloat &T, const APFloat &C,
3556 llvm::RoundingMode) { return C.isNegative() ? T : F; });
3557
3558 case clang::X86::BI__builtin_ia32_pblendvb128:
3559 case clang::X86::BI__builtin_ia32_pblendvb256:
3561 S, OpPC, Call, [](const APSInt &F, const APSInt &T, const APSInt &C) {
3562 return ((APInt)C).isNegative() ? T : F;
3563 });
3564
3565 case X86::BI__builtin_ia32_selectb_128:
3566 case X86::BI__builtin_ia32_selectb_256:
3567 case X86::BI__builtin_ia32_selectb_512:
3568 case X86::BI__builtin_ia32_selectw_128:
3569 case X86::BI__builtin_ia32_selectw_256:
3570 case X86::BI__builtin_ia32_selectw_512:
3571 case X86::BI__builtin_ia32_selectd_128:
3572 case X86::BI__builtin_ia32_selectd_256:
3573 case X86::BI__builtin_ia32_selectd_512:
3574 case X86::BI__builtin_ia32_selectq_128:
3575 case X86::BI__builtin_ia32_selectq_256:
3576 case X86::BI__builtin_ia32_selectq_512:
3577 case X86::BI__builtin_ia32_selectph_128:
3578 case X86::BI__builtin_ia32_selectph_256:
3579 case X86::BI__builtin_ia32_selectph_512:
3580 case X86::BI__builtin_ia32_selectpbf_128:
3581 case X86::BI__builtin_ia32_selectpbf_256:
3582 case X86::BI__builtin_ia32_selectpbf_512:
3583 case X86::BI__builtin_ia32_selectps_128:
3584 case X86::BI__builtin_ia32_selectps_256:
3585 case X86::BI__builtin_ia32_selectps_512:
3586 case X86::BI__builtin_ia32_selectpd_128:
3587 case X86::BI__builtin_ia32_selectpd_256:
3588 case X86::BI__builtin_ia32_selectpd_512:
3589 return interp__builtin_select(S, OpPC, Call);
3590
3591 case Builtin::BI__builtin_elementwise_fshl:
3593 llvm::APIntOps::fshl);
3594 case Builtin::BI__builtin_elementwise_fshr:
3596 llvm::APIntOps::fshr);
3597
3598 default:
3599 S.FFDiag(S.Current->getLocation(OpPC),
3600 diag::note_invalid_subexpr_in_const_expr)
3601 << S.Current->getRange(OpPC);
3602
3603 return false;
3604 }
3605
3606 llvm_unreachable("Unhandled builtin ID");
3607}
3608
3610 ArrayRef<int64_t> ArrayIndices, int64_t &IntResult) {
3612 unsigned N = E->getNumComponents();
3613 assert(N > 0);
3614
3615 unsigned ArrayIndex = 0;
3616 QualType CurrentType = E->getTypeSourceInfo()->getType();
3617 for (unsigned I = 0; I != N; ++I) {
3618 const OffsetOfNode &Node = E->getComponent(I);
3619 switch (Node.getKind()) {
3620 case OffsetOfNode::Field: {
3621 const FieldDecl *MemberDecl = Node.getField();
3622 const auto *RD = CurrentType->getAsRecordDecl();
3623 if (!RD || RD->isInvalidDecl())
3624 return false;
3626 unsigned FieldIndex = MemberDecl->getFieldIndex();
3627 assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");
3628 Result +=
3630 CurrentType = MemberDecl->getType().getNonReferenceType();
3631 break;
3632 }
3633 case OffsetOfNode::Array: {
3634 // When generating bytecode, we put all the index expressions as Sint64 on
3635 // the stack.
3636 int64_t Index = ArrayIndices[ArrayIndex];
3637 const ArrayType *AT = S.getASTContext().getAsArrayType(CurrentType);
3638 if (!AT)
3639 return false;
3640 CurrentType = AT->getElementType();
3641 CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType);
3642 Result += Index * ElementSize;
3643 ++ArrayIndex;
3644 break;
3645 }
3646 case OffsetOfNode::Base: {
3647 const CXXBaseSpecifier *BaseSpec = Node.getBase();
3648 if (BaseSpec->isVirtual())
3649 return false;
3650
3651 // Find the layout of the class whose base we are looking into.
3652 const auto *RD = CurrentType->getAsCXXRecordDecl();
3653 if (!RD || RD->isInvalidDecl())
3654 return false;
3656
3657 // Find the base class itself.
3658 CurrentType = BaseSpec->getType();
3659 const auto *BaseRD = CurrentType->getAsCXXRecordDecl();
3660 if (!BaseRD)
3661 return false;
3662
3663 // Add the offset to the base.
3664 Result += RL.getBaseClassOffset(BaseRD);
3665 break;
3666 }
3668 llvm_unreachable("Dependent OffsetOfExpr?");
3669 }
3670 }
3671
3672 IntResult = Result.getQuantity();
3673
3674 return true;
3675}
3676
3678 const Pointer &Ptr, const APSInt &IntValue) {
3679
3680 const Record *R = Ptr.getRecord();
3681 assert(R);
3682 assert(R->getNumFields() == 1);
3683
3684 unsigned FieldOffset = R->getField(0u)->Offset;
3685 const Pointer &FieldPtr = Ptr.atField(FieldOffset);
3686 PrimType FieldT = *S.getContext().classify(FieldPtr.getType());
3687
3688 INT_TYPE_SWITCH(FieldT,
3689 FieldPtr.deref<T>() = T::from(IntValue.getSExtValue()));
3690 FieldPtr.initialize();
3691 return true;
3692}
3693
3694static void zeroAll(Pointer &Dest) {
3695 const Descriptor *Desc = Dest.getFieldDesc();
3696
3697 if (Desc->isPrimitive()) {
3698 TYPE_SWITCH(Desc->getPrimType(), {
3699 Dest.deref<T>().~T();
3700 new (&Dest.deref<T>()) T();
3701 });
3702 return;
3703 }
3704
3705 if (Desc->isRecord()) {
3706 const Record *R = Desc->ElemRecord;
3707 for (const Record::Field &F : R->fields()) {
3708 Pointer FieldPtr = Dest.atField(F.Offset);
3709 zeroAll(FieldPtr);
3710 }
3711 return;
3712 }
3713
3714 if (Desc->isPrimitiveArray()) {
3715 for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
3716 TYPE_SWITCH(Desc->getPrimType(), {
3717 Dest.deref<T>().~T();
3718 new (&Dest.deref<T>()) T();
3719 });
3720 }
3721 return;
3722 }
3723
3724 if (Desc->isCompositeArray()) {
3725 for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
3726 Pointer ElemPtr = Dest.atIndex(I).narrow();
3727 zeroAll(ElemPtr);
3728 }
3729 return;
3730 }
3731}
3732
3733static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
3734 Pointer &Dest, bool Activate);
3735static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,
3736 Pointer &Dest, bool Activate = false) {
3737 [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
3738 const Descriptor *DestDesc = Dest.getFieldDesc();
3739
3740 auto copyField = [&](const Record::Field &F, bool Activate) -> bool {
3741 Pointer DestField = Dest.atField(F.Offset);
3742 if (OptPrimType FT = S.Ctx.classify(F.Decl->getType())) {
3743 TYPE_SWITCH(*FT, {
3744 DestField.deref<T>() = Src.atField(F.Offset).deref<T>();
3745 if (Src.atField(F.Offset).isInitialized())
3746 DestField.initialize();
3747 if (Activate)
3748 DestField.activate();
3749 });
3750 return true;
3751 }
3752 // Composite field.
3753 return copyComposite(S, OpPC, Src.atField(F.Offset), DestField, Activate);
3754 };
3755
3756 assert(SrcDesc->isRecord());
3757 assert(SrcDesc->ElemRecord == DestDesc->ElemRecord);
3758 const Record *R = DestDesc->ElemRecord;
3759 for (const Record::Field &F : R->fields()) {
3760 if (R->isUnion()) {
3761 // For unions, only copy the active field. Zero all others.
3762 const Pointer &SrcField = Src.atField(F.Offset);
3763 if (SrcField.isActive()) {
3764 if (!copyField(F, /*Activate=*/true))
3765 return false;
3766 } else {
3767 if (!CheckMutable(S, OpPC, Src.atField(F.Offset)))
3768 return false;
3769 Pointer DestField = Dest.atField(F.Offset);
3770 zeroAll(DestField);
3771 }
3772 } else {
3773 if (!copyField(F, Activate))
3774 return false;
3775 }
3776 }
3777
3778 for (const Record::Base &B : R->bases()) {
3779 Pointer DestBase = Dest.atField(B.Offset);
3780 if (!copyRecord(S, OpPC, Src.atField(B.Offset), DestBase, Activate))
3781 return false;
3782 }
3783
3784 Dest.initialize();
3785 return true;
3786}
3787
3788static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
3789 Pointer &Dest, bool Activate = false) {
3790 assert(Src.isLive() && Dest.isLive());
3791
3792 [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
3793 const Descriptor *DestDesc = Dest.getFieldDesc();
3794
3795 assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive());
3796
3797 if (DestDesc->isPrimitiveArray()) {
3798 assert(SrcDesc->isPrimitiveArray());
3799 assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
3800 PrimType ET = DestDesc->getPrimType();
3801 for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
3802 Pointer DestElem = Dest.atIndex(I);
3803 TYPE_SWITCH(ET, {
3804 DestElem.deref<T>() = Src.elem<T>(I);
3805 DestElem.initialize();
3806 });
3807 }
3808 return true;
3809 }
3810
3811 if (DestDesc->isCompositeArray()) {
3812 assert(SrcDesc->isCompositeArray());
3813 assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
3814 for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
3815 const Pointer &SrcElem = Src.atIndex(I).narrow();
3816 Pointer DestElem = Dest.atIndex(I).narrow();
3817 if (!copyComposite(S, OpPC, SrcElem, DestElem, Activate))
3818 return false;
3819 }
3820 return true;
3821 }
3822
3823 if (DestDesc->isRecord())
3824 return copyRecord(S, OpPC, Src, Dest, Activate);
3825 return Invalid(S, OpPC);
3826}
3827
3828bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {
3829 return copyComposite(S, OpPC, Src, Dest);
3830}
3831
3832} // namespace interp
3833} // namespace clang
#define V(N, I)
Defines enum values for all the target-independent builtin functions.
llvm::APSInt APSInt
Definition Compiler.cpp:23
GCCTypeClass
Values returned by __builtin_classify_type, chosen to match the values produced by GCC's builtin.
CharUnits GetAlignOfExpr(const ASTContext &Ctx, const Expr *E, UnaryExprOrTypeTrait ExprKind)
GCCTypeClass EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts)
EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way as GCC.
static bool isOneByteCharacterType(QualType T)
static bool isUserWritingOffTheEnd(const ASTContext &Ctx, const LValue &LVal)
Attempts to detect a user writing into a piece of memory that's impossible to figure out the size of ...
TokenType getType() const
Returns the token's type, e.g.
#define X(type, name)
Definition Value.h:97
static DiagnosticBuilder Diag(DiagnosticsEngine *Diags, const LangOptions &Features, FullSourceLoc TokLoc, const char *TokBegin, const char *TokRangeBegin, const char *TokRangeEnd, unsigned DiagID)
Produce a diagnostic highlighting some portion of a literal.
#define INT_TYPE_SWITCH_NO_BOOL(Expr, B)
Definition PrimType.h:247
#define INT_TYPE_SWITCH(Expr, B)
Definition PrimType.h:228
#define TYPE_SWITCH(Expr, B)
Definition PrimType.h:207
static std::string toString(const clang::SanitizerSet &Sanitizers)
Produce a string containing comma-separated names of sanitizers in Sanitizers set.
static QualType getPointeeType(const MemRegion *R)
Enumerates target-specific builtins in their own namespaces within namespace clang.
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition APValue.h:122
CharUnits & getLValueOffset()
Definition APValue.cpp:993
Holds long-lived AST nodes (such as types and decls) that can be referred to throughout the semantic ...
Definition ASTContext.h:188
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.
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:739
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:891
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)...
bool hasSameUnqualifiedType(QualType T1, QualType T2) const
Determine whether the given types are equivalent after cvr-qualifiers have been removed.
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.
const TargetInfo & getTargetInfo() const
Definition ASTContext.h:856
CharUnits toCharUnitsFromBits(int64_t BitSize) const
Convert a size in bits to a size in characters.
CanQualType getCanonicalTagType(const TagDecl *TD) const
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:3720
QualType getElementType() const
Definition TypeBase.h:3732
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:431
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:2879
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:254
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:273
QualType getType() const
Definition Expr.h:144
Represents a member of a struct/union/class.
Definition Decl.h:3157
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition Decl.h:3242
const RecordDecl * getParent() const
Returns the parent of this field declaration, which is the struct in which this field is defined.
Definition Decl.h:3393
Represents a function declaration or definition.
Definition Decl.h:1999
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.
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
Definition Expr.h:2529
const OffsetOfNode & getComponent(unsigned Idx) const
Definition Expr.h:2576
TypeSourceInfo * getTypeSourceInfo() const
Definition Expr.h:2569
unsigned getNumComponents() const
Definition Expr.h:2584
Helper class for OffsetOfExpr.
Definition Expr.h:2423
FieldDecl * getField() const
For a field offsetof node, returns the field.
Definition Expr.h:2487
@ Array
An index into an array.
Definition Expr.h:2428
@ Identifier
A field in a dependent type, known only by its name.
Definition Expr.h:2432
@ Field
A field.
Definition Expr.h:2430
@ Base
An implicit indirection through a C++ base class, when the field found is in a base class.
Definition Expr.h:2435
Kind getKind() const
Determine what kind of offsetof node this is.
Definition Expr.h:2477
CXXBaseSpecifier * getBase() const
For a base class node, returns the base specifier.
Definition Expr.h:2497
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition TypeBase.h:3328
A (possibly-)qualified type.
Definition TypeBase.h:937
bool isTriviallyCopyableType(const ASTContext &Context) const
Return true if this is a trivially copyable type (C++0x [basic.types]p9)
Definition Type.cpp:2867
const Type * getTypePtr() const
Retrieves a pointer to the underlying (unqualified) type.
Definition TypeBase.h:8285
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:8470
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition Stmt.cpp:334
unsigned getMaxAtomicInlineWidth() const
Return the maximum width lock-free atomic operation which can be inlined given the supported features...
Definition TargetInfo.h:853
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:8267
bool isBooleanType() const
Definition TypeBase.h:9008
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition Type.cpp:2225
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
Definition Type.cpp:2273
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:8522
bool isIntegerType() const
isIntegerType() does not include complex integers (a GCC extension).
Definition TypeBase.h:8922
const T * castAs() const
Member-template castAs<specific type>.
Definition TypeBase.h:9168
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition Type.cpp:752
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition Type.cpp:2436
bool isVectorType() const
Definition TypeBase.h:8661
bool isFloatingType() const
Definition Type.cpp:2304
const T * getAs() const
Member-template getAs<specific type>'.
Definition TypeBase.h:9101
QualType getType() const
Definition Decl.h:722
Represents a GCC generic vector type.
Definition TypeBase.h:4173
unsigned getNumElements() const
Definition TypeBase.h:4188
QualType getElementType() const
Definition TypeBase.h:4187
A memory block, either on the stack or in the heap.
Definition InterpBlock.h:44
const Descriptor * getDescriptor() const
Returns the block's descriptor.
Definition InterpBlock.h:73
bool isDynamic() const
Definition InterpBlock.h:83
Wrapper around boolean types.
Definition Boolean.h:25
static Boolean from(T Value)
Definition Boolean.h:97
Pointer into the code segment.
Definition Source.h:30
const LangOptions & getLangOpts() const
Returns the language options.
Definition Context.cpp:276
OptPrimType classify(QualType T) const
Classifies a type.
Definition Context.cpp:310
unsigned getEvalID() const
Definition Context.h:141
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:122
llvm::FPClassTest classify() const
Definition Floating.h:153
bool isSignaling() const
Definition Floating.h:148
bool isNormal() const
Definition Floating.h:151
ComparisonCategoryResult compare(const Floating &RHS) const
Definition Floating.h:156
bool isZero() const
Definition Floating.h:143
bool isNegative() const
Definition Floating.h:142
bool isFinite() const
Definition Floating.h:150
bool isDenormal() const
Definition Floating.h:152
APFloat::fltCategory getCategory() const
Definition Floating.h:154
APFloat getAPFloat() const
Definition Floating.h:63
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:26
const Expr * getExpr(CodePtr PC) const
InterpFrame * Caller
The frame of the previous function.
Definition InterpFrame.h:29
SourceInfo getSource(CodePtr PC) const
Map a location to a source.
CodePtr getRetPC() const
Returns the return address of the frame.
SourceLocation getLocation(CodePtr PC) const
SourceRange getRange(CodePtr PC) const
unsigned getDepth() const
const FunctionDecl * getCallee() const override
Returns the caller.
Stack frame storing temporaries and parameters.
Definition InterpStack.h:25
T pop()
Returns the value from the top of the stack and removes it.
Definition InterpStack.h:39
void push(Tys &&...Args)
Constructs a value in place on the top of the stack.
Definition InterpStack.h:33
void discard()
Discards the top value from the stack.
Definition InterpStack.h:50
T & peek() const
Returns a reference to the value on the top of the stack.
Definition InterpStack.h:62
Interpreter context.
Definition InterpState.h:43
Expr::EvalStatus & getEvalStatus() const override
Definition InterpState.h:67
Context & getContext() const
DynamicAllocator & getAllocator()
Context & Ctx
Interpreter Context.
Floating allocFloat(const llvm::fltSemantics &Sem)
llvm::SmallVector< const Block * > InitializingBlocks
List of blocks we're currently running either constructors or destructors for.
ASTContext & getASTContext() const override
Definition InterpState.h:70
InterpStack & Stk
Temporary stack.
const VarDecl * EvaluatingDecl
Declaration we're initializing/evaluting, if any.
InterpFrame * Current
The current frame.
T allocAP(unsigned BitWidth)
StdAllocatorCaller getStdAllocatorCaller(StringRef Name) const
Program & P
Reference to the module containing all bytecode.
PrimType value_or(PrimType PT) const
Definition PrimType.h:68
A pointer to a memory block, live or dead.
Definition Pointer.h:91
Pointer narrow() const
Restricts the scope of an array element pointer.
Definition Pointer.h:188
bool isInitialized() const
Checks if an object was initialized.
Definition Pointer.cpp:432
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
Definition Pointer.h:156
bool isDummy() const
Checks if the pointer points to a dummy value.
Definition Pointer.h:544
int64_t getIndex() const
Returns the index into an array.
Definition Pointer.h:609
bool isActive() const
Checks if the object is active.
Definition Pointer.h:533
Pointer atField(unsigned Off) const
Creates a pointer to a field.
Definition Pointer.h:173
T & deref() const
Dereferences the pointer, if it's live.
Definition Pointer.h:660
unsigned getNumElems() const
Returns the number of elements.
Definition Pointer.h:593
Pointer getArray() const
Returns the parent array.
Definition Pointer.h:313
bool isUnknownSizeArray() const
Checks if the structure is an array of unknown size.
Definition Pointer.h:412
void activate() const
Activats a field.
Definition Pointer.cpp:560
bool isIntegralPointer() const
Definition Pointer.h:466
QualType getType() const
Returns the type of the innermost field.
Definition Pointer.h:333
bool isArrayElement() const
Checks if the pointer points to an array.
Definition Pointer.h:418
void initializeAllElements() const
Initialize all elements of a primitive array at once.
Definition Pointer.cpp:530
bool isLive() const
Checks if the pointer is live.
Definition Pointer.h:265
T & elem(unsigned I) const
Dereferences the element at index I.
Definition Pointer.h:676
Pointer getBase() const
Returns a pointer to the object of which this pointer is a field.
Definition Pointer.h:304
uint64_t getByteOffset() const
Returns the byte offset from the start.
Definition Pointer.h:582
std::string toDiagnosticString(const ASTContext &Ctx) const
Converts the pointer to a string usable in diagnostics.
Definition Pointer.cpp:419
bool isZero() const
Checks if the pointer is null.
Definition Pointer.h:254
bool isRoot() const
Pointer points directly to a block.
Definition Pointer.h:434
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition Pointer.h:279
static bool pointToSameBlock(const Pointer &A, const Pointer &B)
Checks if both given pointers point to the same block.
Definition Pointer.cpp:636
APValue toAPValue(const ASTContext &ASTCtx) const
Converts the pointer to an APValue.
Definition Pointer.cpp:167
bool isOnePastEnd() const
Checks if the index is one past end.
Definition Pointer.h:626
uint64_t getIntegerRepresentation() const
Definition Pointer.h:143
const FieldDecl * getField() const
Returns the field information.
Definition Pointer.h:478
Pointer expand() const
Expands a pointer to the containing array, undoing narrowing.
Definition Pointer.h:221
bool isBlockPointer() const
Definition Pointer.h:465
const Block * block() const
Definition Pointer.h:599
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
Definition Pointer.h:323
bool isVirtualBaseClass() const
Definition Pointer.h:540
bool isBaseClass() const
Checks if a structure is a base class.
Definition Pointer.h:539
size_t elemSize() const
Returns the element size of the innermost field.
Definition Pointer.h:355
bool canBeInitialized() const
If this pointer has an InlineDescriptor we can use to initialize.
Definition Pointer.h:441
Lifetime getLifetime() const
Definition Pointer.h:719
void initialize() const
Initializes a field.
Definition Pointer.cpp:483
bool isField() const
Checks if the item is a field in an object.
Definition Pointer.h:271
const Record * getRecord() const
Returns the record descriptor of a class.
Definition Pointer.h:471
Descriptor * createDescriptor(const DeclTy &D, PrimType T, const Type *SourceTy=nullptr, Descriptor::MetadataSize MDSize=std::nullopt, bool IsConst=false, bool IsTemporary=false, bool IsMutable=false, bool IsVolatile=false)
Creates a descriptor for a primitive type.
Definition Program.h:119
Structure/Class descriptor.
Definition Record.h:25
const RecordDecl * getDecl() const
Returns the underlying declaration.
Definition Record.h:53
bool isUnion() const
Checks if the record is a union.
Definition Record.h:57
const Field * getField(const FieldDecl *FD) const
Returns a field.
Definition Record.cpp:47
llvm::iterator_range< const_base_iter > bases() const
Definition Record.h:92
unsigned getNumFields() const
Definition Record.h:88
llvm::iterator_range< const_field_iter > fields() const
Definition Record.h:84
Describes the statement/declaration an opcode was generated from.
Definition Source.h:73
OptionalDiagnostic Note(SourceLocation Loc, diag::kind DiagId)
Add a note to a prior diagnostic.
Definition State.cpp:63
DiagnosticBuilder report(SourceLocation Loc, diag::kind DiagId)
Directly reports a diagnostic message.
Definition State.cpp:74
OptionalDiagnostic FFDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation could not be folded (FF => FoldFailure)
Definition State.cpp:21
const LangOptions & getLangOpts() const
Definition State.cpp:115
OptionalDiagnostic CCEDiag(SourceLocation Loc, diag::kind DiagId=diag::note_invalid_subexpr_in_const_expr, unsigned ExtraNotes=0)
Diagnose that the evaluation does not produce a C++11 core constant expression.
Definition State.cpp:42
bool checkingPotentialConstantExpression() const
Are we checking whether the expression is a potential constant expression?
Definition State.h:99
Defines the clang::TargetInfo interface.
bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E, OSLogBufferLayout &layout)
Definition OSLog.cpp:192
static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC, const CallExpr *Call)
static void assignInteger(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_ia32_pdep(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, bool IsNumBuiltin)
static bool interp__builtin_elementwise_maxmin(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned BuiltinID)
static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_elementwise_triop(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< APInt(const APSInt &, const APSInt &, const APSInt &)> Fn)
static bool interp__builtin_ia32_tzcnt(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
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:1103
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)
Definition Interp.h:406
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:1553
static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, bool IsNumBuiltin)
static bool interp__builtin_blend(InterpState &S, CodePtr OpPC, const CallExpr *Call)
bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC, const Pointer &Ptr, const APSInt &IntValue)
Sets the given integral value to the pointer, which is of a std::{weak,partial,strong}...
static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC, const InterpFrame *Frame)
static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned ID)
static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinOp)
bool __atomic_always_lock_free(size_t, void const volatile*) bool __atomic_is_lock_free(size_t,...
static llvm::APSInt convertBoolVectorToInt(const Pointer &Val)
static bool interp__builtin_move(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_clz(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinOp)
bool CheckMutable(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if a pointer points to a mutable field.
Definition Interp.cpp:594
static bool interp__builtin_ia32_lzcnt(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_parity(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
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_bitreverse(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, bool Right)
rotateleft(value, amount)
static bool Activate(InterpState &S, CodePtr OpPC)
Definition Interp.h:1984
static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinOp)
(CarryIn, LHS, RHS, Result)
static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool isOneByteCharacterType(QualType T)
Determine if T is a character type for which we guarantee that sizeof(T) == 1.
static unsigned computePointerOffset(const ASTContext &ASTCtx, const Pointer &Ptr)
Compute the byte offset of Ptr in the full declaration.
static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned ID)
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a value can be loaded from a block.
Definition Interp.cpp:793
static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned BuiltinOp)
static bool interp__builtin_inf(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
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 &Result)
Interpret an offsetof operation.
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
Definition Interp.cpp:519
static bool pointsToLastObject(const Pointer &Ptr)
Does Ptr point to the last subobject?
static bool interp__builtin_select(InterpState &S, CodePtr OpPC, const CallExpr *Call)
AVX512 predicated move: "Result = Mask[] ? LHS[] : RHS[]".
static bool interp__builtin_ia32_pmul(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned BuiltinID)
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:414
static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
Five int values followed by one floating value.
static bool interp__builtin_abs(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp_floating_comparison(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
static bool handleOverflow(InterpState &S, CodePtr OpPC, const T &SrcValue)
Definition Interp.h:153
llvm::APInt APInt
Definition FixedPoint.h:19
static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest, bool Activate)
static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest, bool Activate=false)
static bool interp__builtin_c11_atomic_is_lock_free(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
bool __c11_atomic_is_lock_free(size_t)
static void zeroAll(Pointer &Dest)
static bool interp__builtin_elementwise_int_binop(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< APInt(const APSInt &, const APSInt &)> Fn)
static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_arithmetic_fence(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
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);
bool CheckDummy(InterpState &S, CodePtr OpPC, const Block *B, AccessKinds AK)
Checks if a pointer is a dummy pointer.
Definition Interp.cpp:1154
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_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_memchr(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
static 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:406
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_elementwise_popcount(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.
static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
bool Error(InterpState &S, CodePtr OpPC)
Do nothing and just abort execution.
Definition Interp.h:3290
static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC, const CallExpr *Call, unsigned ID)
static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned ID)
static bool interp__builtin_elementwise_triop_fp(InterpState &S, CodePtr OpPC, const CallExpr *Call, llvm::function_ref< APFloat(const APFloat &, const APFloat &, const APFloat &, llvm::RoundingMode)> Fn)
static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_object_size(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinOp)
Three integral values followed by a pointer (lhs, rhs, carry, carryOut).
bool CheckArraySize(InterpState &S, CodePtr OpPC, uint64_t NumElems)
Definition Interp.h:3657
static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, unsigned BuiltinID)
static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static APSInt popToAPSInt(InterpStack &Stk, PrimType T)
static std::optional< unsigned > computeFullDescSize(const ASTContext &ASTCtx, const Descriptor *Desc)
static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
First parameter to __builtin_isfpclass is the floating value, the second one is an integral value.
static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_nan(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call, bool Signaling)
static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest)
Copy the contents of Src into Dest.
constexpr bool isIntegralType(PrimType T)
Definition PrimType.h:124
static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static LLVM_ATTRIBUTE_UNUSED bool isNoopBuiltin(unsigned ID)
static void diagnoseNonConstexprBuiltin(InterpState &S, CodePtr OpPC, unsigned ID)
llvm::APSInt APSInt
Definition FixedPoint.h:20
static QualType getElemType(const Pointer &P)
static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static void swapBytes(std::byte *M, size_t N)
The JSON file list parser is used to communicate input to InstallAPI.
if(T->getSizeExpr()) TRY_TO(TraverseStmt(const_cast< Expr * >(T -> getSizeExpr())))
ComparisonCategoryResult
An enumeration representing the possible results of a three-way comparison.
@ Result
The result type of a method or function.
Definition TypeBase.h:905
@ AK_Read
Definition State.h:27
const FunctionProtoType * T
U cast(CodeGen::Address addr)
Definition Address.h:327
SmallVectorImpl< PartialDiagnosticAt > * Diag
Diag - If this is non-null, it will be filled in with a stack of notes indicating why evaluation fail...
Definition Expr.h:633
Track what bits have been initialized to known values and which ones have indeterminate value.
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:122
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition Descriptor.h:249
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition Descriptor.h:263
QualType getElemQualType() const
bool isCompositeArray() const
Checks if the descriptor is of an array of composites.
Definition Descriptor.h:256
const ValueDecl * asValueDecl() const
Definition Descriptor.h:214
static constexpr unsigned MaxArrayElemBytes
Maximum number of bytes to be used for array elements.
Definition Descriptor.h:148
QualType getType() const
const Decl * asDecl() const
Definition Descriptor.h:210
static constexpr MetadataSize InlineDescMD
Definition Descriptor.h:144
unsigned getElemSize() const
returns the size of an element when the structure is viewed as an array.
Definition Descriptor.h:244
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition Descriptor.h:254
const VarDecl * asVarDecl() const
Definition Descriptor.h:218
PrimType getPrimType() const
Definition Descriptor.h:236
bool isRecord() const
Checks if the descriptor is of a record.
Definition Descriptor.h:268
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition Descriptor.h:153
const Expr * asExpr() const
Definition Descriptor.h:211
bool isArray() const
Checks if the descriptor is of an array.
Definition Descriptor.h:266
Mapping from primitive types to their representation.
Definition PrimType.h:134