clang 20.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//===----------------------------------------------------------------------===//
8#include "../ExprConstShared.h"
9#include "Boolean.h"
10#include "Interp.h"
11#include "PrimType.h"
12#include "clang/AST/OSLog.h"
16#include "llvm/Support/SipHash.h"
17
18namespace clang {
19namespace interp {
20
21static unsigned callArgSize(const InterpState &S, const CallExpr *C) {
22 unsigned O = 0;
23
24 for (const Expr *E : C->arguments()) {
25 O += align(primSize(*S.getContext().classify(E)));
26 }
27
28 return O;
29}
30
31template <typename T>
32static T getParam(const InterpFrame *Frame, unsigned Index) {
33 assert(Frame->getFunction()->getNumParams() > Index);
34 unsigned Offset = Frame->getFunction()->getParamOffset(Index);
35 return Frame->getParam<T>(Offset);
36}
37
39 const TargetInfo &TI = S.getCtx().getTargetInfo();
40 unsigned IntWidth = TI.getIntWidth();
41
42 if (IntWidth == 32)
43 return PT_Sint32;
44 else if (IntWidth == 16)
45 return PT_Sint16;
46 llvm_unreachable("Int isn't 16 or 32 bit?");
47}
48
50 const TargetInfo &TI = S.getCtx().getTargetInfo();
51 unsigned LongWidth = TI.getLongWidth();
52
53 if (LongWidth == 64)
54 return PT_Sint64;
55 else if (LongWidth == 32)
56 return PT_Sint32;
57 else if (LongWidth == 16)
58 return PT_Sint16;
59 llvm_unreachable("long isn't 16, 32 or 64 bit?");
60}
61
62/// Peek an integer value from the stack into an APSInt.
63static APSInt peekToAPSInt(InterpStack &Stk, PrimType T, size_t Offset = 0) {
64 if (Offset == 0)
65 Offset = align(primSize(T));
66
67 APSInt R;
68 INT_TYPE_SWITCH(T, R = Stk.peek<T>(Offset).toAPSInt());
69
70 return R;
71}
72
73/// Pushes \p Val on the stack as the type given by \p QT.
74static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {
77 std::optional<PrimType> T = S.getContext().classify(QT);
78 assert(T);
79
81 int64_t V = Val.getSExtValue();
82 INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V)); });
83 } else {
85 uint64_t V = Val.getZExtValue();
86 INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V)); });
87 }
88}
89
90template <typename T>
91static void pushInteger(InterpState &S, T Val, QualType QT) {
92 if constexpr (std::is_same_v<T, APInt>)
93 pushInteger(S, APSInt(Val, !std::is_signed_v<T>), QT);
94 else
96 APSInt(APInt(sizeof(T) * 8, static_cast<uint64_t>(Val),
97 std::is_signed_v<T>),
98 !std::is_signed_v<T>),
99 QT);
100}
101
102static void assignInteger(Pointer &Dest, PrimType ValueT, const APSInt &Value) {
104 ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); });
105}
106
108 std::optional<PrimType> &T) {
109 if (!T)
110 return RetVoid(S, OpPC, Result);
111
112#define RET_CASE(X) \
113 case X: \
114 return Ret<X>(S, OpPC, Result);
115 switch (*T) {
128 default:
129 llvm_unreachable("Unsupported return type for builtin function");
130 }
131#undef RET_CASE
132}
133
135 const InterpFrame *Frame,
136 const CallExpr *Call) {
137 // The current frame is the one for __builtin_is_constant_evaluated.
138 // The one above that, potentially the one for std::is_constant_evaluated().
139 if (S.inConstantContext() && !S.checkingPotentialConstantExpression() &&
140 Frame->Caller && S.getEvalStatus().Diag) {
141 auto isStdCall = [](const FunctionDecl *F) -> bool {
142 return F && F->isInStdNamespace() && F->getIdentifier() &&
143 F->getIdentifier()->isStr("is_constant_evaluated");
144 };
145 const InterpFrame *Caller = Frame->Caller;
146
147 if (Caller->Caller && isStdCall(Caller->getCallee())) {
148 const Expr *E = Caller->Caller->getExpr(Caller->getRetPC());
149 S.report(E->getExprLoc(),
150 diag::warn_is_constant_evaluated_always_true_constexpr)
151 << "std::is_constant_evaluated" << E->getSourceRange();
152 } else {
153 const Expr *E = Frame->Caller->getExpr(Frame->getRetPC());
154 S.report(E->getExprLoc(),
155 diag::warn_is_constant_evaluated_always_true_constexpr)
156 << "__builtin_is_constant_evaluated" << E->getSourceRange();
157 }
158 }
159
160 S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
161 return true;
162}
163
165 const InterpFrame *Frame,
166 const CallExpr *Call) {
167 const Pointer &A = getParam<Pointer>(Frame, 0);
168 const Pointer &B = getParam<Pointer>(Frame, 1);
169
170 if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))
171 return false;
172
173 if (A.isDummy() || B.isDummy())
174 return false;
175
176 assert(A.getFieldDesc()->isPrimitiveArray());
177 assert(B.getFieldDesc()->isPrimitiveArray());
178
179 unsigned IndexA = A.getIndex();
180 unsigned IndexB = B.getIndex();
181 int32_t Result = 0;
182 for (;; ++IndexA, ++IndexB) {
183 const Pointer &PA = A.atIndex(IndexA);
184 const Pointer &PB = B.atIndex(IndexB);
185 if (!CheckRange(S, OpPC, PA, AK_Read) ||
186 !CheckRange(S, OpPC, PB, AK_Read)) {
187 return false;
188 }
189 uint8_t CA = PA.deref<uint8_t>();
190 uint8_t CB = PB.deref<uint8_t>();
191
192 if (CA > CB) {
193 Result = 1;
194 break;
195 } else if (CA < CB) {
196 Result = -1;
197 break;
198 }
199 if (CA == 0 || CB == 0)
200 break;
201 }
202
203 pushInteger(S, Result, Call->getType());
204 return true;
205}
206
208 const InterpFrame *Frame,
209 const CallExpr *Call) {
210 const Pointer &StrPtr = getParam<Pointer>(Frame, 0);
211
212 if (!CheckArray(S, OpPC, StrPtr))
213 return false;
214
215 if (!CheckLive(S, OpPC, StrPtr, AK_Read))
216 return false;
217
218 if (!CheckDummy(S, OpPC, StrPtr, AK_Read))
219 return false;
220
221 assert(StrPtr.getFieldDesc()->isPrimitiveArray());
222
223 size_t Len = 0;
224 for (size_t I = StrPtr.getIndex();; ++I, ++Len) {
225 const Pointer &ElemPtr = StrPtr.atIndex(I);
226
227 if (!CheckRange(S, OpPC, ElemPtr, AK_Read))
228 return false;
229
230 uint8_t Val = ElemPtr.deref<uint8_t>();
231 if (Val == 0)
232 break;
233 }
234
235 pushInteger(S, Len, Call->getType());
236
237 return true;
238}
239
241 const InterpFrame *Frame, const Function *F,
242 bool Signaling) {
243 const Pointer &Arg = getParam<Pointer>(Frame, 0);
244
245 if (!CheckLoad(S, OpPC, Arg))
246 return false;
247
248 assert(Arg.getFieldDesc()->isPrimitiveArray());
249
250 // Convert the given string to an integer using StringRef's API.
251 llvm::APInt Fill;
252 std::string Str;
253 assert(Arg.getNumElems() >= 1);
254 for (unsigned I = 0;; ++I) {
255 const Pointer &Elem = Arg.atIndex(I);
256
257 if (!CheckLoad(S, OpPC, Elem))
258 return false;
259
260 if (Elem.deref<int8_t>() == 0)
261 break;
262
263 Str += Elem.deref<char>();
264 }
265
266 // Treat empty strings as if they were zero.
267 if (Str.empty())
268 Fill = llvm::APInt(32, 0);
269 else if (StringRef(Str).getAsInteger(0, Fill))
270 return false;
271
272 const llvm::fltSemantics &TargetSemantics =
273 S.getCtx().getFloatTypeSemantics(F->getDecl()->getReturnType());
274
276 if (S.getCtx().getTargetInfo().isNan2008()) {
277 if (Signaling)
279 llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
280 else
282 llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
283 } else {
284 // Prior to IEEE 754-2008, architectures were allowed to choose whether
285 // the first bit of their significand was set for qNaN or sNaN. MIPS chose
286 // a different encoding to what became a standard in 2008, and for pre-
287 // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as
288 // sNaN. This is now known as "legacy NaN" encoding.
289 if (Signaling)
291 llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
292 else
294 llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
295 }
296
297 S.Stk.push<Floating>(Result);
298 return true;
299}
300
302 const InterpFrame *Frame, const Function *F) {
303 const llvm::fltSemantics &TargetSemantics =
304 S.getCtx().getFloatTypeSemantics(F->getDecl()->getReturnType());
305
306 S.Stk.push<Floating>(Floating::getInf(TargetSemantics));
307 return true;
308}
309
311 const InterpFrame *Frame,
312 const Function *F) {
313 const Floating &Arg1 = getParam<Floating>(Frame, 0);
314 const Floating &Arg2 = getParam<Floating>(Frame, 1);
315
316 APFloat Copy = Arg1.getAPFloat();
317 Copy.copySign(Arg2.getAPFloat());
318 S.Stk.push<Floating>(Floating(Copy));
319
320 return true;
321}
322
324 const InterpFrame *Frame, const Function *F) {
325 const Floating &LHS = getParam<Floating>(Frame, 0);
326 const Floating &RHS = getParam<Floating>(Frame, 1);
327
329
330 // When comparing zeroes, return -0.0 if one of the zeroes is negative.
331 if (LHS.isZero() && RHS.isZero() && RHS.isNegative())
332 Result = RHS;
333 else if (LHS.isNan() || RHS < LHS)
334 Result = RHS;
335 else
336 Result = LHS;
337
338 S.Stk.push<Floating>(Result);
339 return true;
340}
341
343 const InterpFrame *Frame,
344 const Function *Func) {
345 const Floating &LHS = getParam<Floating>(Frame, 0);
346 const Floating &RHS = getParam<Floating>(Frame, 1);
347
349
350 // When comparing zeroes, return +0.0 if one of the zeroes is positive.
351 if (LHS.isZero() && RHS.isZero() && LHS.isNegative())
352 Result = RHS;
353 else if (LHS.isNan() || RHS > LHS)
354 Result = RHS;
355 else
356 Result = LHS;
357
358 S.Stk.push<Floating>(Result);
359 return true;
360}
361
362/// Defined as __builtin_isnan(...), to accommodate the fact that it can
363/// take a float, double, long double, etc.
364/// But for us, that's all a Floating anyway.
366 const InterpFrame *Frame, const Function *F,
367 const CallExpr *Call) {
368 const Floating &Arg = S.Stk.peek<Floating>();
369
370 pushInteger(S, Arg.isNan(), Call->getType());
371 return true;
372}
373
375 const InterpFrame *Frame,
376 const Function *F,
377 const CallExpr *Call) {
378 const Floating &Arg = S.Stk.peek<Floating>();
379
380 pushInteger(S, Arg.isSignaling(), Call->getType());
381 return true;
382}
383
385 const InterpFrame *Frame, const Function *F,
386 bool CheckSign, const CallExpr *Call) {
387 const Floating &Arg = S.Stk.peek<Floating>();
388 bool IsInf = Arg.isInf();
389
390 if (CheckSign)
391 pushInteger(S, IsInf ? (Arg.isNegative() ? -1 : 1) : 0, Call->getType());
392 else
393 pushInteger(S, Arg.isInf(), Call->getType());
394 return true;
395}
396
398 const InterpFrame *Frame,
399 const Function *F, const CallExpr *Call) {
400 const Floating &Arg = S.Stk.peek<Floating>();
401
402 pushInteger(S, Arg.isFinite(), Call->getType());
403 return true;
404}
405
407 const InterpFrame *Frame,
408 const Function *F, const CallExpr *Call) {
409 const Floating &Arg = S.Stk.peek<Floating>();
410
411 pushInteger(S, Arg.isNormal(), Call->getType());
412 return true;
413}
414
416 const InterpFrame *Frame,
417 const Function *F,
418 const CallExpr *Call) {
419 const Floating &Arg = S.Stk.peek<Floating>();
420
421 pushInteger(S, Arg.isDenormal(), Call->getType());
422 return true;
423}
424
426 const InterpFrame *Frame, const Function *F,
427 const CallExpr *Call) {
428 const Floating &Arg = S.Stk.peek<Floating>();
429
430 pushInteger(S, Arg.isZero(), Call->getType());
431 return true;
432}
433
434/// First parameter to __builtin_isfpclass is the floating value, the
435/// second one is an integral value.
437 const InterpFrame *Frame,
438 const Function *Func,
439 const CallExpr *Call) {
440 PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType());
441 APSInt FPClassArg = peekToAPSInt(S.Stk, FPClassArgT);
442 const Floating &F =
443 S.Stk.peek<Floating>(align(primSize(FPClassArgT) + primSize(PT_Float)));
444
445 int32_t Result =
446 static_cast<int32_t>((F.classify() & FPClassArg).getZExtValue());
447 pushInteger(S, Result, Call->getType());
448
449 return true;
450}
451
452/// Five int values followed by one floating value.
454 const InterpFrame *Frame,
455 const Function *Func,
456 const CallExpr *Call) {
457 const Floating &Val = S.Stk.peek<Floating>();
458
459 unsigned Index;
460 switch (Val.getCategory()) {
461 case APFloat::fcNaN:
462 Index = 0;
463 break;
464 case APFloat::fcInfinity:
465 Index = 1;
466 break;
467 case APFloat::fcNormal:
468 Index = Val.isDenormal() ? 3 : 2;
469 break;
470 case APFloat::fcZero:
471 Index = 4;
472 break;
473 }
474
475 // The last argument is first on the stack.
476 assert(Index <= 4);
477 unsigned IntSize = primSize(getIntPrimType(S));
478 unsigned Offset =
479 align(primSize(PT_Float)) + ((1 + (4 - Index)) * align(IntSize));
480
481 APSInt I = peekToAPSInt(S.Stk, getIntPrimType(S), Offset);
482 pushInteger(S, I, Call->getType());
483 return true;
484}
485
486// The C standard says "fabs raises no floating-point exceptions,
487// even if x is a signaling NaN. The returned value is independent of
488// the current rounding direction mode." Therefore constant folding can
489// proceed without regard to the floating point settings.
490// Reference, WG14 N2478 F.10.4.3
492 const InterpFrame *Frame,
493 const Function *Func) {
494 const Floating &Val = getParam<Floating>(Frame, 0);
495
496 S.Stk.push<Floating>(Floating::abs(Val));
497 return true;
498}
499
501 const InterpFrame *Frame,
502 const Function *Func,
503 const CallExpr *Call) {
504 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
505 APSInt Val = peekToAPSInt(S.Stk, ArgT);
506 pushInteger(S, Val.popcount(), Call->getType());
507 return true;
508}
509
511 const InterpFrame *Frame,
512 const Function *Func, const CallExpr *Call) {
513 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
514 APSInt Val = peekToAPSInt(S.Stk, ArgT);
515 pushInteger(S, Val.popcount() % 2, Call->getType());
516 return true;
517}
518
520 const InterpFrame *Frame,
521 const Function *Func, const CallExpr *Call) {
522 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
523 APSInt Val = peekToAPSInt(S.Stk, ArgT);
524 pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType());
525 return true;
526}
527
529 const InterpFrame *Frame,
530 const Function *Func,
531 const CallExpr *Call) {
532 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
533 APSInt Val = peekToAPSInt(S.Stk, ArgT);
534 pushInteger(S, Val.reverseBits(), Call->getType());
535 return true;
536}
537
539 const InterpFrame *Frame,
540 const Function *Func,
541 const CallExpr *Call) {
542 // This is an unevaluated call, so there are no arguments on the stack.
543 assert(Call->getNumArgs() == 1);
544 const Expr *Arg = Call->getArg(0);
545
546 GCCTypeClass ResultClass =
548 int32_t ReturnVal = static_cast<int32_t>(ResultClass);
549 pushInteger(S, ReturnVal, Call->getType());
550 return true;
551}
552
553// __builtin_expect(long, long)
554// __builtin_expect_with_probability(long, long, double)
556 const InterpFrame *Frame,
557 const Function *Func, const CallExpr *Call) {
558 // The return value is simply the value of the first parameter.
559 // We ignore the probability.
560 unsigned NumArgs = Call->getNumArgs();
561 assert(NumArgs == 2 || NumArgs == 3);
562
563 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
564 unsigned Offset = align(primSize(getLongPrimType(S))) * 2;
565 if (NumArgs == 3)
566 Offset += align(primSize(PT_Float));
567
568 APSInt Val = peekToAPSInt(S.Stk, ArgT, Offset);
569 pushInteger(S, Val, Call->getType());
570 return true;
571}
572
573/// rotateleft(value, amount)
575 const InterpFrame *Frame,
576 const Function *Func, const CallExpr *Call,
577 bool Right) {
578 PrimType AmountT = *S.getContext().classify(Call->getArg(1)->getType());
579 PrimType ValueT = *S.getContext().classify(Call->getArg(0)->getType());
580
581 APSInt Amount = peekToAPSInt(S.Stk, AmountT);
583 S.Stk, ValueT, align(primSize(AmountT)) + align(primSize(ValueT)));
584
586 if (Right)
587 Result = APSInt(Value.rotr(Amount.urem(Value.getBitWidth())),
588 /*IsUnsigned=*/true);
589 else // Left.
590 Result = APSInt(Value.rotl(Amount.urem(Value.getBitWidth())),
591 /*IsUnsigned=*/true);
592
593 pushInteger(S, Result, Call->getType());
594 return true;
595}
596
598 const InterpFrame *Frame, const Function *Func,
599 const CallExpr *Call) {
600 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
601 APSInt Value = peekToAPSInt(S.Stk, ArgT);
602
603 uint64_t N = Value.countr_zero();
604 pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType());
605 return true;
606}
607
609 const InterpFrame *Frame,
610 const Function *Func,
611 const CallExpr *Call) {
612 assert(Call->getArg(0)->isLValue());
613 PrimType PtrT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr);
614
615 if (PtrT == PT_FnPtr) {
616 const FunctionPointer &Arg = S.Stk.peek<FunctionPointer>();
617 S.Stk.push<FunctionPointer>(Arg);
618 } else if (PtrT == PT_Ptr) {
619 const Pointer &Arg = S.Stk.peek<Pointer>();
620 S.Stk.push<Pointer>(Arg);
621 } else {
622 assert(false && "Unsupported pointer type passed to __builtin_addressof()");
623 }
624 return true;
625}
626
628 const InterpFrame *Frame, const Function *Func,
629 const CallExpr *Call) {
630
631 PrimType ArgT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr);
632
633 TYPE_SWITCH(ArgT, const T &Arg = S.Stk.peek<T>(); S.Stk.push<T>(Arg););
634
635 return Func->getDecl()->isConstexpr();
636}
637
639 const InterpFrame *Frame,
640 const Function *Func,
641 const CallExpr *Call) {
642 PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
643 APSInt Arg = peekToAPSInt(S.Stk, ArgT);
644
645 int Result =
646 S.getCtx().getTargetInfo().getEHDataRegisterNumber(Arg.getZExtValue());
647 pushInteger(S, Result, Call->getType());
648 return true;
649}
650
651/// Just takes the first Argument to the call and puts it on the stack.
652static bool noopPointer(InterpState &S, CodePtr OpPC, const InterpFrame *Frame,
653 const Function *Func, const CallExpr *Call) {
654 const Pointer &Arg = S.Stk.peek<Pointer>();
655 S.Stk.push<Pointer>(Arg);
656 return true;
657}
658
659// Two integral values followed by a pointer (lhs, rhs, resultOut)
661 const InterpFrame *Frame,
662 const Function *Func,
663 const CallExpr *Call) {
664 Pointer &ResultPtr = S.Stk.peek<Pointer>();
665 if (ResultPtr.isDummy())
666 return false;
667
668 unsigned BuiltinOp = Func->getBuiltinID();
669 PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
670 PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());
671 APSInt RHS = peekToAPSInt(S.Stk, RHST,
672 align(primSize(PT_Ptr)) + align(primSize(RHST)));
673 APSInt LHS = peekToAPSInt(S.Stk, LHST,
674 align(primSize(PT_Ptr)) + align(primSize(RHST)) +
675 align(primSize(LHST)));
676 QualType ResultType = Call->getArg(2)->getType()->getPointeeType();
677 PrimType ResultT = *S.getContext().classify(ResultType);
678 bool Overflow;
679
681 if (BuiltinOp == Builtin::BI__builtin_add_overflow ||
682 BuiltinOp == Builtin::BI__builtin_sub_overflow ||
683 BuiltinOp == Builtin::BI__builtin_mul_overflow) {
684 bool IsSigned = LHS.isSigned() || RHS.isSigned() ||
686 bool AllSigned = LHS.isSigned() && RHS.isSigned() &&
688 uint64_t LHSSize = LHS.getBitWidth();
689 uint64_t RHSSize = RHS.getBitWidth();
690 uint64_t ResultSize = S.getCtx().getTypeSize(ResultType);
691 uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize);
692
693 // Add an additional bit if the signedness isn't uniformly agreed to. We
694 // could do this ONLY if there is a signed and an unsigned that both have
695 // MaxBits, but the code to check that is pretty nasty. The issue will be
696 // caught in the shrink-to-result later anyway.
697 if (IsSigned && !AllSigned)
698 ++MaxBits;
699
700 LHS = APSInt(LHS.extOrTrunc(MaxBits), !IsSigned);
701 RHS = APSInt(RHS.extOrTrunc(MaxBits), !IsSigned);
702 Result = APSInt(MaxBits, !IsSigned);
703 }
704
705 // Find largest int.
706 switch (BuiltinOp) {
707 default:
708 llvm_unreachable("Invalid value for BuiltinOp");
709 case Builtin::BI__builtin_add_overflow:
710 case Builtin::BI__builtin_sadd_overflow:
711 case Builtin::BI__builtin_saddl_overflow:
712 case Builtin::BI__builtin_saddll_overflow:
713 case Builtin::BI__builtin_uadd_overflow:
714 case Builtin::BI__builtin_uaddl_overflow:
715 case Builtin::BI__builtin_uaddll_overflow:
716 Result = LHS.isSigned() ? LHS.sadd_ov(RHS, Overflow)
717 : LHS.uadd_ov(RHS, Overflow);
718 break;
719 case Builtin::BI__builtin_sub_overflow:
720 case Builtin::BI__builtin_ssub_overflow:
721 case Builtin::BI__builtin_ssubl_overflow:
722 case Builtin::BI__builtin_ssubll_overflow:
723 case Builtin::BI__builtin_usub_overflow:
724 case Builtin::BI__builtin_usubl_overflow:
725 case Builtin::BI__builtin_usubll_overflow:
726 Result = LHS.isSigned() ? LHS.ssub_ov(RHS, Overflow)
727 : LHS.usub_ov(RHS, Overflow);
728 break;
729 case Builtin::BI__builtin_mul_overflow:
730 case Builtin::BI__builtin_smul_overflow:
731 case Builtin::BI__builtin_smull_overflow:
732 case Builtin::BI__builtin_smulll_overflow:
733 case Builtin::BI__builtin_umul_overflow:
734 case Builtin::BI__builtin_umull_overflow:
735 case Builtin::BI__builtin_umulll_overflow:
736 Result = LHS.isSigned() ? LHS.smul_ov(RHS, Overflow)
737 : LHS.umul_ov(RHS, Overflow);
738 break;
739 }
740
741 // In the case where multiple sizes are allowed, truncate and see if
742 // the values are the same.
743 if (BuiltinOp == Builtin::BI__builtin_add_overflow ||
744 BuiltinOp == Builtin::BI__builtin_sub_overflow ||
745 BuiltinOp == Builtin::BI__builtin_mul_overflow) {
746 // APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead,
747 // since it will give us the behavior of a TruncOrSelf in the case where
748 // its parameter <= its size. We previously set Result to be at least the
749 // type-size of the result, so getTypeSize(ResultType) <= Resu
750 APSInt Temp = Result.extOrTrunc(S.getCtx().getTypeSize(ResultType));
751 Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType());
752
753 if (!APSInt::isSameValue(Temp, Result))
754 Overflow = true;
755 Result = Temp;
756 }
757
758 // Write Result to ResultPtr and put Overflow on the stacl.
759 assignInteger(ResultPtr, ResultT, Result);
760 ResultPtr.initialize();
761 assert(Func->getDecl()->getReturnType()->isBooleanType());
762 S.Stk.push<Boolean>(Overflow);
763 return true;
764}
765
766/// Three integral values followed by a pointer (lhs, rhs, carry, carryOut).
768 const InterpFrame *Frame,
769 const Function *Func,
770 const CallExpr *Call) {
771 unsigned BuiltinOp = Func->getBuiltinID();
772 PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());
773 PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
774 PrimType CarryT = *S.getContext().classify(Call->getArg(2)->getType());
775 APSInt RHS = peekToAPSInt(S.Stk, RHST,
776 align(primSize(PT_Ptr)) + align(primSize(CarryT)) +
777 align(primSize(RHST)));
778 APSInt LHS =
779 peekToAPSInt(S.Stk, LHST,
780 align(primSize(PT_Ptr)) + align(primSize(RHST)) +
781 align(primSize(CarryT)) + align(primSize(LHST)));
782 APSInt CarryIn = peekToAPSInt(
783 S.Stk, LHST, align(primSize(PT_Ptr)) + align(primSize(CarryT)));
784 APSInt CarryOut;
785
787 // Copy the number of bits and sign.
788 Result = LHS;
789 CarryOut = LHS;
790
791 bool FirstOverflowed = false;
792 bool SecondOverflowed = false;
793 switch (BuiltinOp) {
794 default:
795 llvm_unreachable("Invalid value for BuiltinOp");
796 case Builtin::BI__builtin_addcb:
797 case Builtin::BI__builtin_addcs:
798 case Builtin::BI__builtin_addc:
799 case Builtin::BI__builtin_addcl:
800 case Builtin::BI__builtin_addcll:
801 Result =
802 LHS.uadd_ov(RHS, FirstOverflowed).uadd_ov(CarryIn, SecondOverflowed);
803 break;
804 case Builtin::BI__builtin_subcb:
805 case Builtin::BI__builtin_subcs:
806 case Builtin::BI__builtin_subc:
807 case Builtin::BI__builtin_subcl:
808 case Builtin::BI__builtin_subcll:
809 Result =
810 LHS.usub_ov(RHS, FirstOverflowed).usub_ov(CarryIn, SecondOverflowed);
811 break;
812 }
813 // It is possible for both overflows to happen but CGBuiltin uses an OR so
814 // this is consistent.
815 CarryOut = (uint64_t)(FirstOverflowed | SecondOverflowed);
816
817 Pointer &CarryOutPtr = S.Stk.peek<Pointer>();
818 QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
819 PrimType CarryOutT = *S.getContext().classify(CarryOutType);
820 assignInteger(CarryOutPtr, CarryOutT, CarryOut);
821 CarryOutPtr.initialize();
822
823 assert(Call->getType() == Call->getArg(0)->getType());
824 pushInteger(S, Result, Call->getType());
825 return true;
826}
827
829 const InterpFrame *Frame, const Function *Func,
830 const CallExpr *Call) {
831 unsigned CallSize = callArgSize(S, Call);
832 unsigned BuiltinOp = Func->getBuiltinID();
833 PrimType ValT = *S.getContext().classify(Call->getArg(0));
834 const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize);
835
836 // When the argument is 0, the result of GCC builtins is undefined, whereas
837 // for Microsoft intrinsics, the result is the bit-width of the argument.
838 bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&
839 BuiltinOp != Builtin::BI__lzcnt &&
840 BuiltinOp != Builtin::BI__lzcnt64;
841
842 if (Val == 0) {
843 if (Func->getBuiltinID() == Builtin::BI__builtin_clzg &&
844 Call->getNumArgs() == 2) {
845 // We have a fallback parameter.
846 PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
847 const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT);
848 pushInteger(S, Fallback, Call->getType());
849 return true;
850 }
851
852 if (ZeroIsUndefined)
853 return false;
854 }
855
856 pushInteger(S, Val.countl_zero(), Call->getType());
857 return true;
858}
859
861 const InterpFrame *Frame, const Function *Func,
862 const CallExpr *Call) {
863 unsigned CallSize = callArgSize(S, Call);
864 PrimType ValT = *S.getContext().classify(Call->getArg(0));
865 const APSInt &Val = peekToAPSInt(S.Stk, ValT, CallSize);
866
867 if (Val == 0) {
868 if (Func->getBuiltinID() == Builtin::BI__builtin_ctzg &&
869 Call->getNumArgs() == 2) {
870 // We have a fallback parameter.
871 PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
872 const APSInt &Fallback = peekToAPSInt(S.Stk, FallbackT);
873 pushInteger(S, Fallback, Call->getType());
874 return true;
875 }
876 return false;
877 }
878
879 pushInteger(S, Val.countr_zero(), Call->getType());
880 return true;
881}
882
884 const InterpFrame *Frame,
885 const Function *Func, const CallExpr *Call) {
886 PrimType ReturnT = *S.getContext().classify(Call->getType());
887 PrimType ValT = *S.getContext().classify(Call->getArg(0));
888 const APSInt &Val = peekToAPSInt(S.Stk, ValT);
889 assert(Val.getActiveBits() <= 64);
890
891 INT_TYPE_SWITCH(ReturnT,
892 { S.Stk.push<T>(T::from(Val.byteSwap().getZExtValue())); });
893 return true;
894}
895
896/// bool __atomic_always_lock_free(size_t, void const volatile*)
897/// bool __atomic_is_lock_free(size_t, void const volatile*)
898/// bool __c11_atomic_is_lock_free(size_t)
900 const InterpFrame *Frame,
901 const Function *Func,
902 const CallExpr *Call) {
903 unsigned BuiltinOp = Func->getBuiltinID();
904
905 PrimType ValT = *S.getContext().classify(Call->getArg(0));
906 unsigned SizeValOffset = 0;
907 if (BuiltinOp != Builtin::BI__c11_atomic_is_lock_free)
908 SizeValOffset = align(primSize(ValT)) + align(primSize(PT_Ptr));
909 const APSInt &SizeVal = peekToAPSInt(S.Stk, ValT, SizeValOffset);
910
911 auto returnBool = [&S](bool Value) -> bool {
912 S.Stk.push<Boolean>(Value);
913 return true;
914 };
915
916 // For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power
917 // of two less than or equal to the maximum inline atomic width, we know it
918 // is lock-free. If the size isn't a power of two, or greater than the
919 // maximum alignment where we promote atomics, we know it is not lock-free
920 // (at least not in the sense of atomic_is_lock_free). Otherwise,
921 // the answer can only be determined at runtime; for example, 16-byte
922 // atomics have lock-free implementations on some, but not all,
923 // x86-64 processors.
924
925 // Check power-of-two.
926 CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());
927 if (Size.isPowerOfTwo()) {
928 // Check against inlining width.
929 unsigned InlineWidthBits =
930 S.getCtx().getTargetInfo().getMaxAtomicInlineWidth();
931 if (Size <= S.getCtx().toCharUnitsFromBits(InlineWidthBits)) {
932
933 // OK, we will inline appropriately-aligned operations of this size,
934 // and _Atomic(T) is appropriately-aligned.
935 if (BuiltinOp == Builtin::BI__c11_atomic_is_lock_free ||
936 Size == CharUnits::One())
937 return returnBool(true);
938
939 // Same for null pointers.
940 assert(BuiltinOp != Builtin::BI__c11_atomic_is_lock_free);
941 const Pointer &Ptr = S.Stk.peek<Pointer>();
942 if (Ptr.isZero())
943 return returnBool(true);
944
945 if (Ptr.isIntegralPointer()) {
946 uint64_t IntVal = Ptr.getIntegerRepresentation();
947 if (APSInt(APInt(64, IntVal, false), true).isAligned(Size.getAsAlign()))
948 return returnBool(true);
949 }
950
951 const Expr *PtrArg = Call->getArg(1);
952 // Otherwise, check if the type's alignment against Size.
953 if (const auto *ICE = dyn_cast<ImplicitCastExpr>(PtrArg)) {
954 // Drop the potential implicit-cast to 'const volatile void*', getting
955 // the underlying type.
956 if (ICE->getCastKind() == CK_BitCast)
957 PtrArg = ICE->getSubExpr();
958 }
959
960 if (auto PtrTy = PtrArg->getType()->getAs<PointerType>()) {
961 QualType PointeeType = PtrTy->getPointeeType();
962 if (!PointeeType->isIncompleteType() &&
963 S.getCtx().getTypeAlignInChars(PointeeType) >= Size) {
964 // OK, we will inline operations on this object.
965 return returnBool(true);
966 }
967 }
968 }
969 }
970
971 if (BuiltinOp == Builtin::BI__atomic_always_lock_free)
972 return returnBool(false);
973
974 return false;
975}
976
977/// __builtin_complex(Float A, float B);
979 const InterpFrame *Frame,
980 const Function *Func,
981 const CallExpr *Call) {
982 const Floating &Arg2 = S.Stk.peek<Floating>();
983 const Floating &Arg1 = S.Stk.peek<Floating>(align(primSize(PT_Float)) * 2);
984 Pointer &Result = S.Stk.peek<Pointer>(align(primSize(PT_Float)) * 2 +
986
987 Result.atIndex(0).deref<Floating>() = Arg1;
988 Result.atIndex(0).initialize();
989 Result.atIndex(1).deref<Floating>() = Arg2;
990 Result.atIndex(1).initialize();
991 Result.initialize();
992
993 return true;
994}
995
996/// __builtin_is_aligned()
997/// __builtin_align_up()
998/// __builtin_align_down()
999/// The first parameter is either an integer or a pointer.
1000/// The second parameter is the requested alignment as an integer.
1002 const InterpFrame *Frame,
1003 const Function *Func,
1004 const CallExpr *Call) {
1005 unsigned BuiltinOp = Func->getBuiltinID();
1006 unsigned CallSize = callArgSize(S, Call);
1007
1008 PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1));
1009 const APSInt &Alignment = peekToAPSInt(S.Stk, AlignmentT);
1010
1011 if (Alignment < 0 || !Alignment.isPowerOf2()) {
1012 S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment;
1013 return false;
1014 }
1015 unsigned SrcWidth = S.getCtx().getIntWidth(Call->getArg(0)->getType());
1016 APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1));
1017 if (APSInt::compareValues(Alignment, MaxValue) > 0) {
1018 S.FFDiag(Call, diag::note_constexpr_alignment_too_big)
1019 << MaxValue << Call->getArg(0)->getType() << Alignment;
1020 return false;
1021 }
1022
1023 // The first parameter is either an integer or a pointer (but not a function
1024 // pointer).
1025 PrimType FirstArgT = *S.Ctx.classify(Call->getArg(0));
1026
1027 if (isIntegralType(FirstArgT)) {
1028 const APSInt &Src = peekToAPSInt(S.Stk, FirstArgT, CallSize);
1029 APSInt Align = Alignment.extOrTrunc(Src.getBitWidth());
1030 if (BuiltinOp == Builtin::BI__builtin_align_up) {
1031 APSInt AlignedVal =
1032 APSInt((Src + (Align - 1)) & ~(Align - 1), Src.isUnsigned());
1033 pushInteger(S, AlignedVal, Call->getType());
1034 } else if (BuiltinOp == Builtin::BI__builtin_align_down) {
1035 APSInt AlignedVal = APSInt(Src & ~(Align - 1), Src.isUnsigned());
1036 pushInteger(S, AlignedVal, Call->getType());
1037 } else {
1038 assert(*S.Ctx.classify(Call->getType()) == PT_Bool);
1039 S.Stk.push<Boolean>((Src & (Align - 1)) == 0);
1040 }
1041 return true;
1042 }
1043
1044 assert(FirstArgT == PT_Ptr);
1045 const Pointer &Ptr = S.Stk.peek<Pointer>(CallSize);
1046
1047 unsigned PtrOffset = Ptr.getByteOffset();
1048 PtrOffset = Ptr.getIndex();
1049 CharUnits BaseAlignment =
1050 S.getCtx().getDeclAlign(Ptr.getDeclDesc()->asValueDecl());
1051 CharUnits PtrAlign =
1052 BaseAlignment.alignmentAtOffset(CharUnits::fromQuantity(PtrOffset));
1053
1054 if (BuiltinOp == Builtin::BI__builtin_is_aligned) {
1055 if (PtrAlign.getQuantity() >= Alignment) {
1056 S.Stk.push<Boolean>(true);
1057 return true;
1058 }
1059 // If the alignment is not known to be sufficient, some cases could still
1060 // be aligned at run time. However, if the requested alignment is less or
1061 // equal to the base alignment and the offset is not aligned, we know that
1062 // the run-time value can never be aligned.
1063 if (BaseAlignment.getQuantity() >= Alignment &&
1064 PtrAlign.getQuantity() < Alignment) {
1065 S.Stk.push<Boolean>(false);
1066 return true;
1067 }
1068
1069 S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_compute)
1070 << Alignment;
1071 return false;
1072 }
1073
1074 assert(BuiltinOp == Builtin::BI__builtin_align_down ||
1075 BuiltinOp == Builtin::BI__builtin_align_up);
1076
1077 // For align_up/align_down, we can return the same value if the alignment
1078 // is known to be greater or equal to the requested value.
1079 if (PtrAlign.getQuantity() >= Alignment) {
1080 S.Stk.push<Pointer>(Ptr);
1081 return true;
1082 }
1083
1084 // The alignment could be greater than the minimum at run-time, so we cannot
1085 // infer much about the resulting pointer value. One case is possible:
1086 // For `_Alignas(32) char buf[N]; __builtin_align_down(&buf[idx], 32)` we
1087 // can infer the correct index if the requested alignment is smaller than
1088 // the base alignment so we can perform the computation on the offset.
1089 if (BaseAlignment.getQuantity() >= Alignment) {
1090 assert(Alignment.getBitWidth() <= 64 &&
1091 "Cannot handle > 64-bit address-space");
1092 uint64_t Alignment64 = Alignment.getZExtValue();
1093 CharUnits NewOffset =
1094 CharUnits::fromQuantity(BuiltinOp == Builtin::BI__builtin_align_down
1095 ? llvm::alignDown(PtrOffset, Alignment64)
1096 : llvm::alignTo(PtrOffset, Alignment64));
1097
1098 S.Stk.push<Pointer>(Ptr.atIndex(NewOffset.getQuantity()));
1099 return true;
1100 }
1101
1102 // Otherwise, we cannot constant-evaluate the result.
1103 S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_adjust) << Alignment;
1104 return false;
1105}
1106
1108 CodePtr OpPC,
1109 const InterpFrame *Frame,
1110 const Function *Func,
1111 const CallExpr *Call) {
1114 pushInteger(S, Layout.size().getQuantity(), Call->getType());
1115 return true;
1116}
1117
1119 InterpState &S, CodePtr OpPC, const InterpFrame *Frame,
1120 const Function *Func, const CallExpr *Call) {
1121 const auto &Ptr = S.Stk.peek<Pointer>();
1122 assert(Ptr.getFieldDesc()->isPrimitiveArray());
1123
1124 StringRef R(&Ptr.deref<char>(), Ptr.getFieldDesc()->getNumElems() - 1);
1125 uint64_t Result = getPointerAuthStableSipHash(R);
1126 pushInteger(S, Result, Call->getType());
1127 return true;
1128}
1129
1131 const CallExpr *Call) {
1132 const InterpFrame *Frame = S.Current;
1133 APValue Dummy;
1134
1135 std::optional<PrimType> ReturnT = S.getContext().classify(Call);
1136
1137 switch (F->getBuiltinID()) {
1138 case Builtin::BI__builtin_is_constant_evaluated:
1140 return false;
1141 break;
1142 case Builtin::BI__builtin_assume:
1143 case Builtin::BI__assume:
1144 break;
1145 case Builtin::BI__builtin_strcmp:
1146 if (!interp__builtin_strcmp(S, OpPC, Frame, Call))
1147 return false;
1148 break;
1149 case Builtin::BI__builtin_strlen:
1150 if (!interp__builtin_strlen(S, OpPC, Frame, Call))
1151 return false;
1152 break;
1153 case Builtin::BI__builtin_nan:
1154 case Builtin::BI__builtin_nanf:
1155 case Builtin::BI__builtin_nanl:
1156 case Builtin::BI__builtin_nanf16:
1157 case Builtin::BI__builtin_nanf128:
1158 if (!interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/false))
1159 return false;
1160 break;
1161 case Builtin::BI__builtin_nans:
1162 case Builtin::BI__builtin_nansf:
1163 case Builtin::BI__builtin_nansl:
1164 case Builtin::BI__builtin_nansf16:
1165 case Builtin::BI__builtin_nansf128:
1166 if (!interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/true))
1167 return false;
1168 break;
1169
1170 case Builtin::BI__builtin_huge_val:
1171 case Builtin::BI__builtin_huge_valf:
1172 case Builtin::BI__builtin_huge_vall:
1173 case Builtin::BI__builtin_huge_valf16:
1174 case Builtin::BI__builtin_huge_valf128:
1175 case Builtin::BI__builtin_inf:
1176 case Builtin::BI__builtin_inff:
1177 case Builtin::BI__builtin_infl:
1178 case Builtin::BI__builtin_inff16:
1179 case Builtin::BI__builtin_inff128:
1180 if (!interp__builtin_inf(S, OpPC, Frame, F))
1181 return false;
1182 break;
1183 case Builtin::BI__builtin_copysign:
1184 case Builtin::BI__builtin_copysignf:
1185 case Builtin::BI__builtin_copysignl:
1186 case Builtin::BI__builtin_copysignf128:
1187 if (!interp__builtin_copysign(S, OpPC, Frame, F))
1188 return false;
1189 break;
1190
1191 case Builtin::BI__builtin_fmin:
1192 case Builtin::BI__builtin_fminf:
1193 case Builtin::BI__builtin_fminl:
1194 case Builtin::BI__builtin_fminf16:
1195 case Builtin::BI__builtin_fminf128:
1196 if (!interp__builtin_fmin(S, OpPC, Frame, F))
1197 return false;
1198 break;
1199
1200 case Builtin::BI__builtin_fmax:
1201 case Builtin::BI__builtin_fmaxf:
1202 case Builtin::BI__builtin_fmaxl:
1203 case Builtin::BI__builtin_fmaxf16:
1204 case Builtin::BI__builtin_fmaxf128:
1205 if (!interp__builtin_fmax(S, OpPC, Frame, F))
1206 return false;
1207 break;
1208
1209 case Builtin::BI__builtin_isnan:
1210 if (!interp__builtin_isnan(S, OpPC, Frame, F, Call))
1211 return false;
1212 break;
1213 case Builtin::BI__builtin_issignaling:
1214 if (!interp__builtin_issignaling(S, OpPC, Frame, F, Call))
1215 return false;
1216 break;
1217
1218 case Builtin::BI__builtin_isinf:
1219 if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false, Call))
1220 return false;
1221 break;
1222
1223 case Builtin::BI__builtin_isinf_sign:
1224 if (!interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true, Call))
1225 return false;
1226 break;
1227
1228 case Builtin::BI__builtin_isfinite:
1229 if (!interp__builtin_isfinite(S, OpPC, Frame, F, Call))
1230 return false;
1231 break;
1232 case Builtin::BI__builtin_isnormal:
1233 if (!interp__builtin_isnormal(S, OpPC, Frame, F, Call))
1234 return false;
1235 break;
1236 case Builtin::BI__builtin_issubnormal:
1237 if (!interp__builtin_issubnormal(S, OpPC, Frame, F, Call))
1238 return false;
1239 break;
1240 case Builtin::BI__builtin_iszero:
1241 if (!interp__builtin_iszero(S, OpPC, Frame, F, Call))
1242 return false;
1243 break;
1244 case Builtin::BI__builtin_isfpclass:
1245 if (!interp__builtin_isfpclass(S, OpPC, Frame, F, Call))
1246 return false;
1247 break;
1248 case Builtin::BI__builtin_fpclassify:
1249 if (!interp__builtin_fpclassify(S, OpPC, Frame, F, Call))
1250 return false;
1251 break;
1252
1253 case Builtin::BI__builtin_fabs:
1254 case Builtin::BI__builtin_fabsf:
1255 case Builtin::BI__builtin_fabsl:
1256 case Builtin::BI__builtin_fabsf128:
1257 if (!interp__builtin_fabs(S, OpPC, Frame, F))
1258 return false;
1259 break;
1260
1261 case Builtin::BI__builtin_popcount:
1262 case Builtin::BI__builtin_popcountl:
1263 case Builtin::BI__builtin_popcountll:
1264 case Builtin::BI__builtin_popcountg:
1265 case Builtin::BI__popcnt16: // Microsoft variants of popcount
1266 case Builtin::BI__popcnt:
1267 case Builtin::BI__popcnt64:
1268 if (!interp__builtin_popcount(S, OpPC, Frame, F, Call))
1269 return false;
1270 break;
1271
1272 case Builtin::BI__builtin_parity:
1273 case Builtin::BI__builtin_parityl:
1274 case Builtin::BI__builtin_parityll:
1275 if (!interp__builtin_parity(S, OpPC, Frame, F, Call))
1276 return false;
1277 break;
1278
1279 case Builtin::BI__builtin_clrsb:
1280 case Builtin::BI__builtin_clrsbl:
1281 case Builtin::BI__builtin_clrsbll:
1282 if (!interp__builtin_clrsb(S, OpPC, Frame, F, Call))
1283 return false;
1284 break;
1285
1286 case Builtin::BI__builtin_bitreverse8:
1287 case Builtin::BI__builtin_bitreverse16:
1288 case Builtin::BI__builtin_bitreverse32:
1289 case Builtin::BI__builtin_bitreverse64:
1290 if (!interp__builtin_bitreverse(S, OpPC, Frame, F, Call))
1291 return false;
1292 break;
1293
1294 case Builtin::BI__builtin_classify_type:
1295 if (!interp__builtin_classify_type(S, OpPC, Frame, F, Call))
1296 return false;
1297 break;
1298
1299 case Builtin::BI__builtin_expect:
1300 case Builtin::BI__builtin_expect_with_probability:
1301 if (!interp__builtin_expect(S, OpPC, Frame, F, Call))
1302 return false;
1303 break;
1304
1305 case Builtin::BI__builtin_rotateleft8:
1306 case Builtin::BI__builtin_rotateleft16:
1307 case Builtin::BI__builtin_rotateleft32:
1308 case Builtin::BI__builtin_rotateleft64:
1309 case Builtin::BI_rotl8: // Microsoft variants of rotate left
1310 case Builtin::BI_rotl16:
1311 case Builtin::BI_rotl:
1312 case Builtin::BI_lrotl:
1313 case Builtin::BI_rotl64:
1314 if (!interp__builtin_rotate(S, OpPC, Frame, F, Call, /*Right=*/false))
1315 return false;
1316 break;
1317
1318 case Builtin::BI__builtin_rotateright8:
1319 case Builtin::BI__builtin_rotateright16:
1320 case Builtin::BI__builtin_rotateright32:
1321 case Builtin::BI__builtin_rotateright64:
1322 case Builtin::BI_rotr8: // Microsoft variants of rotate right
1323 case Builtin::BI_rotr16:
1324 case Builtin::BI_rotr:
1325 case Builtin::BI_lrotr:
1326 case Builtin::BI_rotr64:
1327 if (!interp__builtin_rotate(S, OpPC, Frame, F, Call, /*Right=*/true))
1328 return false;
1329 break;
1330
1331 case Builtin::BI__builtin_ffs:
1332 case Builtin::BI__builtin_ffsl:
1333 case Builtin::BI__builtin_ffsll:
1334 if (!interp__builtin_ffs(S, OpPC, Frame, F, Call))
1335 return false;
1336 break;
1337 case Builtin::BIaddressof:
1338 case Builtin::BI__addressof:
1339 case Builtin::BI__builtin_addressof:
1340 if (!interp__builtin_addressof(S, OpPC, Frame, F, Call))
1341 return false;
1342 break;
1343
1344 case Builtin::BIas_const:
1345 case Builtin::BIforward:
1346 case Builtin::BIforward_like:
1347 case Builtin::BImove:
1348 case Builtin::BImove_if_noexcept:
1349 if (!interp__builtin_move(S, OpPC, Frame, F, Call))
1350 return false;
1351 break;
1352
1353 case Builtin::BI__builtin_eh_return_data_regno:
1355 return false;
1356 break;
1357
1358 case Builtin::BI__builtin_launder:
1359 if (!noopPointer(S, OpPC, Frame, F, Call))
1360 return false;
1361 break;
1362
1363 case Builtin::BI__builtin_add_overflow:
1364 case Builtin::BI__builtin_sub_overflow:
1365 case Builtin::BI__builtin_mul_overflow:
1366 case Builtin::BI__builtin_sadd_overflow:
1367 case Builtin::BI__builtin_uadd_overflow:
1368 case Builtin::BI__builtin_uaddl_overflow:
1369 case Builtin::BI__builtin_uaddll_overflow:
1370 case Builtin::BI__builtin_usub_overflow:
1371 case Builtin::BI__builtin_usubl_overflow:
1372 case Builtin::BI__builtin_usubll_overflow:
1373 case Builtin::BI__builtin_umul_overflow:
1374 case Builtin::BI__builtin_umull_overflow:
1375 case Builtin::BI__builtin_umulll_overflow:
1376 case Builtin::BI__builtin_saddl_overflow:
1377 case Builtin::BI__builtin_saddll_overflow:
1378 case Builtin::BI__builtin_ssub_overflow:
1379 case Builtin::BI__builtin_ssubl_overflow:
1380 case Builtin::BI__builtin_ssubll_overflow:
1381 case Builtin::BI__builtin_smul_overflow:
1382 case Builtin::BI__builtin_smull_overflow:
1383 case Builtin::BI__builtin_smulll_overflow:
1384 if (!interp__builtin_overflowop(S, OpPC, Frame, F, Call))
1385 return false;
1386 break;
1387
1388 case Builtin::BI__builtin_addcb:
1389 case Builtin::BI__builtin_addcs:
1390 case Builtin::BI__builtin_addc:
1391 case Builtin::BI__builtin_addcl:
1392 case Builtin::BI__builtin_addcll:
1393 case Builtin::BI__builtin_subcb:
1394 case Builtin::BI__builtin_subcs:
1395 case Builtin::BI__builtin_subc:
1396 case Builtin::BI__builtin_subcl:
1397 case Builtin::BI__builtin_subcll:
1398 if (!interp__builtin_carryop(S, OpPC, Frame, F, Call))
1399 return false;
1400 break;
1401
1402 case Builtin::BI__builtin_clz:
1403 case Builtin::BI__builtin_clzl:
1404 case Builtin::BI__builtin_clzll:
1405 case Builtin::BI__builtin_clzs:
1406 case Builtin::BI__builtin_clzg:
1407 case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
1408 case Builtin::BI__lzcnt:
1409 case Builtin::BI__lzcnt64:
1410 if (!interp__builtin_clz(S, OpPC, Frame, F, Call))
1411 return false;
1412 break;
1413
1414 case Builtin::BI__builtin_ctz:
1415 case Builtin::BI__builtin_ctzl:
1416 case Builtin::BI__builtin_ctzll:
1417 case Builtin::BI__builtin_ctzs:
1418 case Builtin::BI__builtin_ctzg:
1419 if (!interp__builtin_ctz(S, OpPC, Frame, F, Call))
1420 return false;
1421 break;
1422
1423 case Builtin::BI__builtin_bswap16:
1424 case Builtin::BI__builtin_bswap32:
1425 case Builtin::BI__builtin_bswap64:
1426 if (!interp__builtin_bswap(S, OpPC, Frame, F, Call))
1427 return false;
1428 break;
1429
1430 case Builtin::BI__atomic_always_lock_free:
1431 case Builtin::BI__atomic_is_lock_free:
1432 case Builtin::BI__c11_atomic_is_lock_free:
1433 if (!interp__builtin_atomic_lock_free(S, OpPC, Frame, F, Call))
1434 return false;
1435 break;
1436
1437 case Builtin::BI__builtin_complex:
1438 if (!interp__builtin_complex(S, OpPC, Frame, F, Call))
1439 return false;
1440 break;
1441
1442 case Builtin::BI__builtin_is_aligned:
1443 case Builtin::BI__builtin_align_up:
1444 case Builtin::BI__builtin_align_down:
1446 return false;
1447 break;
1448
1449 case Builtin::BI__builtin_os_log_format_buffer_size:
1451 return false;
1452 break;
1453
1454 case Builtin::BI__builtin_ptrauth_string_discriminator:
1456 return false;
1457 break;
1458
1459 default:
1460 S.FFDiag(S.Current->getLocation(OpPC),
1461 diag::note_invalid_subexpr_in_const_expr)
1462 << S.Current->getRange(OpPC);
1463
1464 return false;
1465 }
1466
1467 return retPrimValue(S, OpPC, Dummy, ReturnT);
1468}
1469
1471 llvm::ArrayRef<int64_t> ArrayIndices,
1472 int64_t &IntResult) {
1474 unsigned N = E->getNumComponents();
1475 assert(N > 0);
1476
1477 unsigned ArrayIndex = 0;
1478 QualType CurrentType = E->getTypeSourceInfo()->getType();
1479 for (unsigned I = 0; I != N; ++I) {
1480 const OffsetOfNode &Node = E->getComponent(I);
1481 switch (Node.getKind()) {
1482 case OffsetOfNode::Field: {
1483 const FieldDecl *MemberDecl = Node.getField();
1484 const RecordType *RT = CurrentType->getAs<RecordType>();
1485 if (!RT)
1486 return false;
1487 const RecordDecl *RD = RT->getDecl();
1488 if (RD->isInvalidDecl())
1489 return false;
1490 const ASTRecordLayout &RL = S.getCtx().getASTRecordLayout(RD);
1491 unsigned FieldIndex = MemberDecl->getFieldIndex();
1492 assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");
1493 Result += S.getCtx().toCharUnitsFromBits(RL.getFieldOffset(FieldIndex));
1494 CurrentType = MemberDecl->getType().getNonReferenceType();
1495 break;
1496 }
1497 case OffsetOfNode::Array: {
1498 // When generating bytecode, we put all the index expressions as Sint64 on
1499 // the stack.
1500 int64_t Index = ArrayIndices[ArrayIndex];
1501 const ArrayType *AT = S.getCtx().getAsArrayType(CurrentType);
1502 if (!AT)
1503 return false;
1504 CurrentType = AT->getElementType();
1505 CharUnits ElementSize = S.getCtx().getTypeSizeInChars(CurrentType);
1506 Result += Index * ElementSize;
1507 ++ArrayIndex;
1508 break;
1509 }
1510 case OffsetOfNode::Base: {
1511 const CXXBaseSpecifier *BaseSpec = Node.getBase();
1512 if (BaseSpec->isVirtual())
1513 return false;
1514
1515 // Find the layout of the class whose base we are looking into.
1516 const RecordType *RT = CurrentType->getAs<RecordType>();
1517 if (!RT)
1518 return false;
1519 const RecordDecl *RD = RT->getDecl();
1520 if (RD->isInvalidDecl())
1521 return false;
1522 const ASTRecordLayout &RL = S.getCtx().getASTRecordLayout(RD);
1523
1524 // Find the base class itself.
1525 CurrentType = BaseSpec->getType();
1526 const RecordType *BaseRT = CurrentType->getAs<RecordType>();
1527 if (!BaseRT)
1528 return false;
1529
1530 // Add the offset to the base.
1531 Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));
1532 break;
1533 }
1535 llvm_unreachable("Dependent OffsetOfExpr?");
1536 }
1537 }
1538
1539 IntResult = Result.getQuantity();
1540
1541 return true;
1542}
1543
1545 const Pointer &Ptr, const APSInt &IntValue) {
1546
1547 const Record *R = Ptr.getRecord();
1548 assert(R);
1549 assert(R->getNumFields() == 1);
1550
1551 unsigned FieldOffset = R->getField(0u)->Offset;
1552 const Pointer &FieldPtr = Ptr.atField(FieldOffset);
1553 PrimType FieldT = *S.getContext().classify(FieldPtr.getType());
1554
1555 INT_TYPE_SWITCH(FieldT,
1556 FieldPtr.deref<T>() = T::from(IntValue.getSExtValue()));
1557 FieldPtr.initialize();
1558 return true;
1559}
1560
1561bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {
1562 assert(Src.isLive() && Dest.isLive());
1563
1564 [[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
1565 const Descriptor *DestDesc = Dest.getFieldDesc();
1566
1567 assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive());
1568
1569 if (DestDesc->isPrimitiveArray()) {
1570 assert(SrcDesc->isPrimitiveArray());
1571 assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
1572 PrimType ET = DestDesc->getPrimType();
1573 for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
1574 Pointer DestElem = Dest.atIndex(I);
1575 TYPE_SWITCH(ET, {
1576 DestElem.deref<T>() = Src.atIndex(I).deref<T>();
1577 DestElem.initialize();
1578 });
1579 }
1580 return true;
1581 }
1582
1583 if (DestDesc->isRecord()) {
1584 assert(SrcDesc->isRecord());
1585 assert(SrcDesc->ElemRecord == DestDesc->ElemRecord);
1586 const Record *R = DestDesc->ElemRecord;
1587 for (const Record::Field &F : R->fields()) {
1588 Pointer DestField = Dest.atField(F.Offset);
1589 if (std::optional<PrimType> FT = S.Ctx.classify(F.Decl->getType())) {
1590 TYPE_SWITCH(*FT, {
1591 DestField.deref<T>() = Src.atField(F.Offset).deref<T>();
1592 DestField.initialize();
1593 });
1594 } else {
1595 return Invalid(S, OpPC);
1596 }
1597 }
1598 return true;
1599 }
1600
1601 // FIXME: Composite types.
1602
1603 return Invalid(S, OpPC);
1604}
1605
1606} // namespace interp
1607} // namespace clang
#define V(N, I)
Definition: ASTContext.h:3338
DynTypedNode Node
Defines enum values for all the target-independent builtin functions.
Expr * E
GCCTypeClass
Values returned by __builtin_classify_type, chosen to match the values produced by GCC's builtin.
GCCTypeClass EvaluateBuiltinClassifyType(QualType T, const LangOptions &LangOpts)
EvaluateBuiltinClassifyType - Evaluate __builtin_classify_type the same way as GCC.
#define RET_CASE(X)
#define INT_TYPE_SWITCH_NO_BOOL(Expr, B)
Definition: PrimType.h:162
#define INT_TYPE_SWITCH(Expr, B)
Definition: PrimType.h:143
#define TYPE_SWITCH(Expr, B)
Definition: PrimType.h:122
APValue - This class implements a discriminated union of [uninitialized] [APSInt] [APFloat],...
Definition: APValue.h:122
ASTRecordLayout - This class contains layout information for one RecordDecl, which is a struct/union/...
Definition: RecordLayout.h:38
unsigned getFieldCount() const
getFieldCount - Get the number of fields in the layout.
Definition: RecordLayout.h:196
uint64_t getFieldOffset(unsigned FieldNo) const
getFieldOffset - Get the offset of the given field index, in bits.
Definition: RecordLayout.h:200
CharUnits getBaseClassOffset(const CXXRecordDecl *Base) const
getBaseClassOffset - Get the offset, in chars, for the given base class.
Definition: RecordLayout.h:249
Represents an array type, per C99 6.7.5.2 - Array Declarators.
Definition: Type.h:3540
QualType getElementType() const
Definition: Type.h:3552
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:2830
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
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
bool isInvalidDecl() const
Definition: DeclBase.h:594
This represents one expression.
Definition: Expr.h:110
SourceLocation getExprLoc() const LLVM_READONLY
getExprLoc - Return the preferred location for the arrow when diagnosing a problem with a generic exp...
Definition: Expr.cpp:277
QualType getType() const
Definition: Expr.h:142
Represents a member of a struct/union/class.
Definition: Decl.h:3030
unsigned getFieldIndex() const
Returns the index of this field within its record, as appropriate for passing to ASTRecordLayout::get...
Definition: Decl.cpp:4632
Represents a function declaration or definition.
Definition: Decl.h:1932
QualType getReturnType() const
Definition: Decl.h:2717
OffsetOfExpr - [C99 7.17] - This represents an expression of the form offsetof(record-type,...
Definition: Expr.h:2475
Helper class for OffsetOfExpr.
Definition: Expr.h:2369
@ Array
An index into an array.
Definition: Expr.h:2374
@ Identifier
A field in a dependent type, known only by its name.
Definition: Expr.h:2378
@ Field
A field.
Definition: Expr.h:2376
@ Base
An implicit indirection through a C++ base class, when the field found is in a base class.
Definition: Expr.h:2381
PointerType - C99 6.7.5.1 - Pointer Declarators.
Definition: Type.h:3161
A (possibly-)qualified type.
Definition: Type.h:941
QualType getNonReferenceType() const
If Type is a reference type (e.g., const int&), returns the type that the reference refers to ("const...
Definition: Type.h:7944
Represents a struct/union/class.
Definition: Decl.h:4141
A helper class that allows the use of isa/cast/dyncast to detect TagType objects of structs/unions/cl...
Definition: Type.h:5936
RecordDecl * getDecl() const
Definition: Type.h:5946
SemaDiagnosticBuilder Diag(SourceLocation Loc, unsigned DiagID, bool DeferHint=false)
Emit a diagnostic.
Definition: SemaBase.cpp:60
const LangOptions & getLangOpts() const
Definition: Sema.h:593
SourceRange getSourceRange() const LLVM_READONLY
SourceLocation tokens are not useful in isolation - they are low level value objects created/interpre...
Definition: Stmt.cpp:326
Exposes information about the current target.
Definition: TargetInfo.h:218
unsigned getIntWidth() const
getIntWidth/Align - Return the size of 'signed int' and 'unsigned int' for this target,...
Definition: TargetInfo.h:509
unsigned getLongWidth() const
getLongWidth/Align - Return the size of 'signed long' and 'unsigned long' for this target,...
Definition: TargetInfo.h:514
bool isSignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is signed or an enumeration types whose underlying ty...
Definition: Type.cpp:2167
bool isUnsignedIntegerOrEnumerationType() const
Determines whether this is an integer type that is unsigned or an enumeration types whose underlying ...
Definition: Type.cpp:2217
QualType getPointeeType() const
If this is a pointer, ObjC object pointer, or block pointer, this returns the respective pointee.
Definition: Type.cpp:705
bool isIncompleteType(NamedDecl **Def=nullptr) const
Types are partitioned into 3 broad categories (C99 6.2.5p1): object types, function types,...
Definition: Type.cpp:2362
const T * getAs() const
Member-template getAs<specific type>'.
Definition: Type.h:8516
QualType getType() const
Definition: Decl.h:678
Wrapper around boolean types.
Definition: Boolean.h:25
static Boolean from(T Value)
Definition: Boolean.h:93
Pointer into the code segment.
Definition: Source.h:30
bool isInf() const
Definition: Floating.h:97
const APFloat & getAPFloat() const
Definition: Floating.h:40
llvm::FPClassTest classify() const
Definition: Floating.h:101
bool isSignaling() const
Definition: Floating.h:96
bool isNormal() const
Definition: Floating.h:99
bool isNan() const
Definition: Floating.h:95
bool isZero() const
Definition: Floating.h:91
bool isNegative() const
Definition: Floating.h:89
static Floating getInf(const llvm::fltSemantics &Sem)
Definition: Floating.h:37
bool isFinite() const
Definition: Floating.h:98
bool isDenormal() const
Definition: Floating.h:100
static Floating abs(const Floating &F)
Definition: Floating.h:159
APFloat::fltCategory getCategory() const
Definition: Floating.h:102
Base class for stack frames, shared between VM and walker.
Definition: Frame.h:25
Bytecode function.
Definition: Function.h:77
const FunctionDecl * getDecl() const
Returns the original FunctionDecl.
Definition: Function.h:92
unsigned getBuiltinID() const
Definition: Function.h:181
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
CodePtr getRetPC() const
Returns the return address of the frame.
Definition: InterpFrame.h:112
const FunctionDecl * getCallee() const override
Returns the caller.
Stack frame storing temporaries and parameters.
Definition: InterpStack.h:27
T & peek() const
Returns a reference to the value on the top of the stack.
Definition: InterpStack.h:68
Interpreter context.
Definition: InterpState.h:36
A pointer to a memory block, live or dead.
Definition: Pointer.h:80
Pointer atIndex(uint64_t Idx) const
Offsets a pointer inside an array.
Definition: Pointer.h:144
bool isDummy() const
Checks if the pointer points to a dummy value.
Definition: Pointer.h:517
int64_t getIndex() const
Returns the index into an array.
Definition: Pointer.h:562
Pointer atField(unsigned Off) const
Creates a pointer to a field.
Definition: Pointer.h:163
T & deref() const
Dereferences the pointer, if it's live.
Definition: Pointer.h:609
unsigned getNumElems() const
Returns the number of elements.
Definition: Pointer.h:553
bool isIntegralPointer() const
Definition: Pointer.h:447
QualType getType() const
Returns the type of the innermost field.
Definition: Pointer.h:334
bool isLive() const
Checks if the pointer is live.
Definition: Pointer.h:265
bool isZero() const
Checks if the pointer is null.
Definition: Pointer.h:256
const Descriptor * getDeclDesc() const
Accessor for information about the declaration site.
Definition: Pointer.h:279
uint64_t getIntegerRepresentation() const
Definition: Pointer.h:131
const Descriptor * getFieldDesc() const
Accessors for information about the innermost field.
Definition: Pointer.h:324
void initialize() const
Initializes a field.
Definition: Pointer.cpp:307
unsigned getByteOffset() const
Returns the byte offset from the start.
Definition: Pointer.h:544
const Record * getRecord() const
Returns the record descriptor of a class.
Definition: Pointer.h:451
Structure/Class descriptor.
Definition: Record.h:25
const Field * getField(const FieldDecl *FD) const
Returns a field.
Definition: Record.cpp:39
unsigned getNumFields() const
Definition: Record.h:81
llvm::iterator_range< const_field_iter > fields() const
Definition: Record.h:77
Defines the clang::TargetInfo interface.
bool computeOSLogBufferLayout(clang::ASTContext &Ctx, const clang::CallExpr *E, OSLogBufferLayout &layout)
Definition: OSLog.cpp:181
static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
bool __atomic_always_lock_free(size_t, void const volatile*) bool __atomic_is_lock_free(size_t,...
llvm::APFloat APFloat
Definition: Floating.h:23
static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
static APSInt peekToAPSInt(InterpStack &Stk, PrimType T, size_t Offset=0)
Peek an integer value from the stack into an APSInt.
static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
llvm::APInt APInt
Definition: Integral.h:29
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E, llvm::ArrayRef< int64_t > ArrayIndices, int64_t &Result)
Interpret an offsetof operation.
static bool interp__builtin_nan(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F, bool Signaling)
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}_ordering type.
static bool interp__builtin_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func)
static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
Three integral values followed by a pointer (lhs, rhs, carry, carryOut).
static bool interp__builtin_inf(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F)
static unsigned callArgSize(const InterpState &S, const CallExpr *C)
static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F, const CallExpr *Call)
static bool interp__builtin_os_log_format_buffer_size(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
static bool interp__builtin_clz(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
__builtin_is_aligned() __builtin_align_up() __builtin_align_down() The first parameter is either an i...
static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
bool CheckLoad(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a value can be loaded from a block.
Definition: Interp.cpp:514
static T getParam(const InterpFrame *Frame, unsigned Index)
PrimType getIntPrimType(const InterpState &S)
constexpr size_t align(size_t Size)
Aligns a size to the pointer alignment.
Definition: PrimType.h:104
bool CheckRange(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is in range.
Definition: Interp.cpp:353
bool CheckLive(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is live and accessible.
Definition: Interp.cpp:272
static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
static bool retPrimValue(InterpState &S, CodePtr OpPC, APValue &Result, std::optional< PrimType > &T)
static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
PrimType
Enumeration of the primitive types of the VM.
Definition: PrimType.h:33
static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F, const CallExpr *Call)
static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F, const CallExpr *Call)
static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func)
static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F, bool CheckSign, const CallExpr *Call)
static bool interp__builtin_move(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
static bool noopPointer(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
Just takes the first Argument to the call and puts it on the stack.
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_issignaling(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F, const CallExpr *Call)
PrimType getLongPrimType(const InterpState &S)
bool CheckArray(InterpState &S, CodePtr OpPC, const Pointer &Ptr)
Checks if the array is offsetable.
Definition: Interp.cpp:264
static bool interp__builtin_complex(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
__builtin_complex(Float A, float B);
static bool interp__builtin_parity(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
bool CheckDummy(InterpState &S, CodePtr OpPC, const Pointer &Ptr, AccessKinds AK)
Checks if a pointer is a dummy pointer.
Definition: Interp.cpp:786
static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F, const CallExpr *Call)
size_t primSize(PrimType Type)
Returns the size of a primitive type in bytes.
Definition: PrimType.cpp:23
static void assignInteger(Pointer &Dest, PrimType ValueT, const APSInt &Value)
static bool interp__builtin_expect(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const CallExpr *Call)
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F, const CallExpr *Call)
Interpret a builtin function.
llvm::APSInt APSInt
Definition: Floating.h:24
static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F)
static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
Five int values followed by one floating value.
static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F, const CallExpr *Call)
Defined as __builtin_isnan(...), to accommodate the fact that it can take a float,...
bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest)
Copy the contents of Src into Dest.
static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call, bool Right)
rotateleft(value, amount)
constexpr bool isIntegralType(PrimType T)
Definition: PrimType.h:72
static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *F)
static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
First parameter to __builtin_isfpclass is the floating value, the second one is an integral value.
static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
bool RetVoid(InterpState &S, CodePtr &PC, APValue &Result)
Definition: Interp.h:309
static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC, const InterpFrame *Frame, const Function *Func, const CallExpr *Call)
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
@ AK_Read
Definition: State.h:27
const FunctionProtoType * T
Describes a memory block created by an allocation site.
Definition: Descriptor.h:107
unsigned getNumElems() const
Returns the number of elements stored in the block.
Definition: Descriptor.h:233
bool isPrimitive() const
Checks if the descriptor is of a primitive.
Definition: Descriptor.h:247
const ValueDecl * asValueDecl() const
Definition: Descriptor.h:198
bool isPrimitiveArray() const
Checks if the descriptor is of an array of primitives.
Definition: Descriptor.h:238
PrimType getPrimType() const
Definition: Descriptor.h:220
bool isRecord() const
Checks if the descriptor is of a record.
Definition: Descriptor.h:252
const Record *const ElemRecord
Pointer to the record, if block contains records.
Definition: Descriptor.h:137