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