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