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