Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/clang/lib/AST/ByteCode/InterpBuiltin.cpp
213799 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 "Compiler.h"
11
#include "EvalEmitter.h"
12
#include "Interp.h"
13
#include "InterpBuiltinBitCast.h"
14
#include "PrimType.h"
15
#include "clang/AST/OSLog.h"
16
#include "clang/AST/RecordLayout.h"
17
#include "clang/Basic/Builtins.h"
18
#include "clang/Basic/TargetBuiltins.h"
19
#include "clang/Basic/TargetInfo.h"
20
#include "llvm/ADT/StringExtras.h"
21
#include "llvm/Support/ErrorHandling.h"
22
#include "llvm/Support/SipHash.h"
23
24
namespace clang {
25
namespace interp {
26
27
LLVM_ATTRIBUTE_UNUSED static bool isNoopBuiltin(unsigned ID) {
28
switch (ID) {
29
case Builtin::BIas_const:
30
case Builtin::BIforward:
31
case Builtin::BIforward_like:
32
case Builtin::BImove:
33
case Builtin::BImove_if_noexcept:
34
case Builtin::BIaddressof:
35
case Builtin::BI__addressof:
36
case Builtin::BI__builtin_addressof:
37
case Builtin::BI__builtin_launder:
38
return true;
39
default:
40
return false;
41
}
42
return false;
43
}
44
45
static void discard(InterpStack &Stk, PrimType T) {
46
TYPE_SWITCH(T, { Stk.discard<T>(); });
47
}
48
49
static APSInt popToAPSInt(InterpStack &Stk, PrimType T) {
50
INT_TYPE_SWITCH(T, return Stk.pop<T>().toAPSInt());
51
}
52
53
/// Pushes \p Val on the stack as the type given by \p QT.
54
static void pushInteger(InterpState &S, const APSInt &Val, QualType QT) {
55
assert(QT->isSignedIntegerOrEnumerationType() ||
56
QT->isUnsignedIntegerOrEnumerationType());
57
std::optional<PrimType> T = S.getContext().classify(QT);
58
assert(T);
59
60
unsigned BitWidth = S.getASTContext().getTypeSize(QT);
61
62
if (T == PT_IntAPS) {
63
auto Result = S.allocAP<IntegralAP<true>>(BitWidth);
64
Result.copy(Val);
65
S.Stk.push<IntegralAP<true>>(Result);
66
return;
67
}
68
69
if (T == PT_IntAP) {
70
auto Result = S.allocAP<IntegralAP<false>>(BitWidth);
71
Result.copy(Val);
72
S.Stk.push<IntegralAP<false>>(Result);
73
return;
74
}
75
76
if (QT->isSignedIntegerOrEnumerationType()) {
77
int64_t V = Val.getSExtValue();
78
INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });
79
} else {
80
assert(QT->isUnsignedIntegerOrEnumerationType());
81
uint64_t V = Val.getZExtValue();
82
INT_TYPE_SWITCH(*T, { S.Stk.push<T>(T::from(V, BitWidth)); });
83
}
84
}
85
86
template <typename T>
87
static void pushInteger(InterpState &S, T Val, QualType QT) {
88
if constexpr (std::is_same_v<T, APInt>)
89
pushInteger(S, APSInt(Val, !std::is_signed_v<T>), QT);
90
else if constexpr (std::is_same_v<T, APSInt>)
91
pushInteger(S, Val, QT);
92
else
93
pushInteger(S,
94
APSInt(APInt(sizeof(T) * 8, static_cast<uint64_t>(Val),
95
std::is_signed_v<T>),
96
!std::is_signed_v<T>),
97
QT);
98
}
99
100
static void assignInteger(InterpState &S, const Pointer &Dest, PrimType ValueT,
101
const APSInt &Value) {
102
103
if (ValueT == PT_IntAPS) {
104
Dest.deref<IntegralAP<true>>() =
105
S.allocAP<IntegralAP<true>>(Value.getBitWidth());
106
Dest.deref<IntegralAP<true>>().copy(Value);
107
} else if (ValueT == PT_IntAP) {
108
Dest.deref<IntegralAP<false>>() =
109
S.allocAP<IntegralAP<false>>(Value.getBitWidth());
110
Dest.deref<IntegralAP<false>>().copy(Value);
111
} else {
112
INT_TYPE_SWITCH_NO_BOOL(
113
ValueT, { Dest.deref<T>() = T::from(static_cast<T>(Value)); });
114
}
115
}
116
117
static QualType getElemType(const Pointer &P) {
118
const Descriptor *Desc = P.getFieldDesc();
119
QualType T = Desc->getType();
120
if (Desc->isPrimitive())
121
return T;
122
if (T->isPointerType())
123
return T->getAs<PointerType>()->getPointeeType();
124
if (Desc->isArray())
125
return Desc->getElemQualType();
126
if (const auto *AT = T->getAsArrayTypeUnsafe())
127
return AT->getElementType();
128
return T;
129
}
130
131
static void diagnoseNonConstexprBuiltin(InterpState &S, CodePtr OpPC,
132
unsigned ID) {
133
if (!S.diagnosing())
134
return;
135
136
auto Loc = S.Current->getSource(OpPC);
137
if (S.getLangOpts().CPlusPlus11)
138
S.CCEDiag(Loc, diag::note_constexpr_invalid_function)
139
<< /*isConstexpr=*/0 << /*isConstructor=*/0
140
<< S.getASTContext().BuiltinInfo.getQuotedName(ID);
141
else
142
S.CCEDiag(Loc, diag::note_invalid_subexpr_in_const_expr);
143
}
144
145
static bool interp__builtin_is_constant_evaluated(InterpState &S, CodePtr OpPC,
146
const InterpFrame *Frame,
147
const CallExpr *Call) {
148
unsigned Depth = S.Current->getDepth();
149
auto isStdCall = [](const FunctionDecl *F) -> bool {
150
return F && F->isInStdNamespace() && F->getIdentifier() &&
151
F->getIdentifier()->isStr("is_constant_evaluated");
152
};
153
const InterpFrame *Caller = Frame->Caller;
154
// The current frame is the one for __builtin_is_constant_evaluated.
155
// The one above that, potentially the one for std::is_constant_evaluated().
156
if (S.inConstantContext() && !S.checkingPotentialConstantExpression() &&
157
S.getEvalStatus().Diag &&
158
(Depth == 0 || (Depth == 1 && isStdCall(Frame->getCallee())))) {
159
if (Caller && isStdCall(Frame->getCallee())) {
160
const Expr *E = Caller->getExpr(Caller->getRetPC());
161
S.report(E->getExprLoc(),
162
diag::warn_is_constant_evaluated_always_true_constexpr)
163
<< "std::is_constant_evaluated" << E->getSourceRange();
164
} else {
165
S.report(Call->getExprLoc(),
166
diag::warn_is_constant_evaluated_always_true_constexpr)
167
<< "__builtin_is_constant_evaluated" << Call->getSourceRange();
168
}
169
}
170
171
S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
172
return true;
173
}
174
175
// __builtin_assume(int)
176
static bool interp__builtin_assume(InterpState &S, CodePtr OpPC,
177
const InterpFrame *Frame,
178
const CallExpr *Call) {
179
assert(Call->getNumArgs() == 1);
180
discard(S.Stk, *S.getContext().classify(Call->getArg(0)));
181
return true;
182
}
183
184
static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
185
const InterpFrame *Frame,
186
const CallExpr *Call, unsigned ID) {
187
uint64_t Limit = ~static_cast<uint64_t>(0);
188
if (ID == Builtin::BIstrncmp || ID == Builtin::BI__builtin_strncmp ||
189
ID == Builtin::BIwcsncmp || ID == Builtin::BI__builtin_wcsncmp)
190
Limit = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(2)))
191
.getZExtValue();
192
193
const Pointer &B = S.Stk.pop<Pointer>();
194
const Pointer &A = S.Stk.pop<Pointer>();
195
if (ID == Builtin::BIstrcmp || ID == Builtin::BIstrncmp ||
196
ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp)
197
diagnoseNonConstexprBuiltin(S, OpPC, ID);
198
199
if (Limit == 0) {
200
pushInteger(S, 0, Call->getType());
201
return true;
202
}
203
204
if (!CheckLive(S, OpPC, A, AK_Read) || !CheckLive(S, OpPC, B, AK_Read))
205
return false;
206
207
if (A.isDummy() || B.isDummy())
208
return false;
209
210
bool IsWide = ID == Builtin::BIwcscmp || ID == Builtin::BIwcsncmp ||
211
ID == Builtin::BI__builtin_wcscmp ||
212
ID == Builtin::BI__builtin_wcsncmp;
213
assert(A.getFieldDesc()->isPrimitiveArray());
214
assert(B.getFieldDesc()->isPrimitiveArray());
215
216
assert(getElemType(A).getTypePtr() == getElemType(B).getTypePtr());
217
PrimType ElemT = *S.getContext().classify(getElemType(A));
218
219
auto returnResult = [&](int V) -> bool {
220
pushInteger(S, V, Call->getType());
221
return true;
222
};
223
224
unsigned IndexA = A.getIndex();
225
unsigned IndexB = B.getIndex();
226
uint64_t Steps = 0;
227
for (;; ++IndexA, ++IndexB, ++Steps) {
228
229
if (Steps >= Limit)
230
break;
231
const Pointer &PA = A.atIndex(IndexA);
232
const Pointer &PB = B.atIndex(IndexB);
233
if (!CheckRange(S, OpPC, PA, AK_Read) ||
234
!CheckRange(S, OpPC, PB, AK_Read)) {
235
return false;
236
}
237
238
if (IsWide) {
239
INT_TYPE_SWITCH(ElemT, {
240
T CA = PA.deref<T>();
241
T CB = PB.deref<T>();
242
if (CA > CB)
243
return returnResult(1);
244
else if (CA < CB)
245
return returnResult(-1);
246
else if (CA.isZero() || CB.isZero())
247
return returnResult(0);
248
});
249
continue;
250
}
251
252
uint8_t CA = PA.deref<uint8_t>();
253
uint8_t CB = PB.deref<uint8_t>();
254
255
if (CA > CB)
256
return returnResult(1);
257
else if (CA < CB)
258
return returnResult(-1);
259
if (CA == 0 || CB == 0)
260
return returnResult(0);
261
}
262
263
return returnResult(0);
264
}
265
266
static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
267
const InterpFrame *Frame,
268
const CallExpr *Call, unsigned ID) {
269
const Pointer &StrPtr = S.Stk.pop<Pointer>();
270
271
if (ID == Builtin::BIstrlen || ID == Builtin::BIwcslen)
272
diagnoseNonConstexprBuiltin(S, OpPC, ID);
273
274
if (!CheckArray(S, OpPC, StrPtr))
275
return false;
276
277
if (!CheckLive(S, OpPC, StrPtr, AK_Read))
278
return false;
279
280
if (!CheckDummy(S, OpPC, StrPtr, AK_Read))
281
return false;
282
283
assert(StrPtr.getFieldDesc()->isPrimitiveArray());
284
unsigned ElemSize = StrPtr.getFieldDesc()->getElemSize();
285
286
if (ID == Builtin::BI__builtin_wcslen || ID == Builtin::BIwcslen) {
287
[[maybe_unused]] const ASTContext &AC = S.getASTContext();
288
assert(ElemSize == AC.getTypeSizeInChars(AC.getWCharType()).getQuantity());
289
}
290
291
size_t Len = 0;
292
for (size_t I = StrPtr.getIndex();; ++I, ++Len) {
293
const Pointer &ElemPtr = StrPtr.atIndex(I);
294
295
if (!CheckRange(S, OpPC, ElemPtr, AK_Read))
296
return false;
297
298
uint32_t Val;
299
switch (ElemSize) {
300
case 1:
301
Val = ElemPtr.deref<uint8_t>();
302
break;
303
case 2:
304
Val = ElemPtr.deref<uint16_t>();
305
break;
306
case 4:
307
Val = ElemPtr.deref<uint32_t>();
308
break;
309
default:
310
llvm_unreachable("Unsupported char size");
311
}
312
if (Val == 0)
313
break;
314
}
315
316
pushInteger(S, Len, Call->getType());
317
318
return true;
319
}
320
321
static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,
322
const InterpFrame *Frame, const CallExpr *Call,
323
bool Signaling) {
324
const Pointer &Arg = S.Stk.pop<Pointer>();
325
326
if (!CheckLoad(S, OpPC, Arg))
327
return false;
328
329
assert(Arg.getFieldDesc()->isPrimitiveArray());
330
331
// Convert the given string to an integer using StringRef's API.
332
llvm::APInt Fill;
333
std::string Str;
334
assert(Arg.getNumElems() >= 1);
335
for (unsigned I = 0;; ++I) {
336
const Pointer &Elem = Arg.atIndex(I);
337
338
if (!CheckLoad(S, OpPC, Elem))
339
return false;
340
341
if (Elem.deref<int8_t>() == 0)
342
break;
343
344
Str += Elem.deref<char>();
345
}
346
347
// Treat empty strings as if they were zero.
348
if (Str.empty())
349
Fill = llvm::APInt(32, 0);
350
else if (StringRef(Str).getAsInteger(0, Fill))
351
return false;
352
353
const llvm::fltSemantics &TargetSemantics =
354
S.getASTContext().getFloatTypeSemantics(
355
Call->getDirectCallee()->getReturnType());
356
357
Floating Result = S.allocFloat(TargetSemantics);
358
if (S.getASTContext().getTargetInfo().isNan2008()) {
359
if (Signaling)
360
Result.copy(
361
llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
362
else
363
Result.copy(
364
llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
365
} else {
366
// Prior to IEEE 754-2008, architectures were allowed to choose whether
367
// the first bit of their significand was set for qNaN or sNaN. MIPS chose
368
// a different encoding to what became a standard in 2008, and for pre-
369
// 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as
370
// sNaN. This is now known as "legacy NaN" encoding.
371
if (Signaling)
372
Result.copy(
373
llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
374
else
375
Result.copy(
376
llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
377
}
378
379
S.Stk.push<Floating>(Result);
380
return true;
381
}
382
383
static bool interp__builtin_inf(InterpState &S, CodePtr OpPC,
384
const InterpFrame *Frame,
385
const CallExpr *Call) {
386
const llvm::fltSemantics &TargetSemantics =
387
S.getASTContext().getFloatTypeSemantics(
388
Call->getDirectCallee()->getReturnType());
389
390
Floating Result = S.allocFloat(TargetSemantics);
391
Result.copy(APFloat::getInf(TargetSemantics));
392
S.Stk.push<Floating>(Result);
393
return true;
394
}
395
396
static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC,
397
const InterpFrame *Frame) {
398
const Floating &Arg2 = S.Stk.pop<Floating>();
399
const Floating &Arg1 = S.Stk.pop<Floating>();
400
Floating Result = S.allocFloat(Arg1.getSemantics());
401
402
APFloat Copy = Arg1.getAPFloat();
403
Copy.copySign(Arg2.getAPFloat());
404
Result.copy(Copy);
405
S.Stk.push<Floating>(Result);
406
407
return true;
408
}
409
410
static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC,
411
const InterpFrame *Frame, bool IsNumBuiltin) {
412
const Floating &RHS = S.Stk.pop<Floating>();
413
const Floating &LHS = S.Stk.pop<Floating>();
414
Floating Result = S.allocFloat(LHS.getSemantics());
415
416
if (IsNumBuiltin)
417
Result.copy(llvm::minimumnum(LHS.getAPFloat(), RHS.getAPFloat()));
418
else
419
Result.copy(minnum(LHS.getAPFloat(), RHS.getAPFloat()));
420
S.Stk.push<Floating>(Result);
421
return true;
422
}
423
424
static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC,
425
const InterpFrame *Frame, bool IsNumBuiltin) {
426
const Floating &RHS = S.Stk.pop<Floating>();
427
const Floating &LHS = S.Stk.pop<Floating>();
428
Floating Result = S.allocFloat(LHS.getSemantics());
429
430
if (IsNumBuiltin)
431
Result.copy(llvm::maximumnum(LHS.getAPFloat(), RHS.getAPFloat()));
432
else
433
Result.copy(maxnum(LHS.getAPFloat(), RHS.getAPFloat()));
434
S.Stk.push<Floating>(Result);
435
return true;
436
}
437
438
/// Defined as __builtin_isnan(...), to accommodate the fact that it can
439
/// take a float, double, long double, etc.
440
/// But for us, that's all a Floating anyway.
441
static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC,
442
const InterpFrame *Frame,
443
const CallExpr *Call) {
444
const Floating &Arg = S.Stk.pop<Floating>();
445
446
pushInteger(S, Arg.isNan(), Call->getType());
447
return true;
448
}
449
450
static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC,
451
const InterpFrame *Frame,
452
const CallExpr *Call) {
453
const Floating &Arg = S.Stk.pop<Floating>();
454
455
pushInteger(S, Arg.isSignaling(), Call->getType());
456
return true;
457
}
458
459
static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC,
460
const InterpFrame *Frame, bool CheckSign,
461
const CallExpr *Call) {
462
const Floating &Arg = S.Stk.pop<Floating>();
463
bool IsInf = Arg.isInf();
464
465
if (CheckSign)
466
pushInteger(S, IsInf ? (Arg.isNegative() ? -1 : 1) : 0, Call->getType());
467
else
468
pushInteger(S, Arg.isInf(), Call->getType());
469
return true;
470
}
471
472
static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC,
473
const InterpFrame *Frame,
474
const CallExpr *Call) {
475
const Floating &Arg = S.Stk.pop<Floating>();
476
477
pushInteger(S, Arg.isFinite(), Call->getType());
478
return true;
479
}
480
481
static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC,
482
const InterpFrame *Frame,
483
const CallExpr *Call) {
484
const Floating &Arg = S.Stk.pop<Floating>();
485
486
pushInteger(S, Arg.isNormal(), Call->getType());
487
return true;
488
}
489
490
static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC,
491
const InterpFrame *Frame,
492
const CallExpr *Call) {
493
const Floating &Arg = S.Stk.pop<Floating>();
494
495
pushInteger(S, Arg.isDenormal(), Call->getType());
496
return true;
497
}
498
499
static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC,
500
const InterpFrame *Frame,
501
const CallExpr *Call) {
502
const Floating &Arg = S.Stk.pop<Floating>();
503
504
pushInteger(S, Arg.isZero(), Call->getType());
505
return true;
506
}
507
508
static bool interp__builtin_signbit(InterpState &S, CodePtr OpPC,
509
const InterpFrame *Frame,
510
const CallExpr *Call) {
511
const Floating &Arg = S.Stk.pop<Floating>();
512
513
pushInteger(S, Arg.isNegative(), Call->getType());
514
return true;
515
}
516
517
static bool interp_floating_comparison(InterpState &S, CodePtr OpPC,
518
const CallExpr *Call, unsigned ID) {
519
const Floating &RHS = S.Stk.pop<Floating>();
520
const Floating &LHS = S.Stk.pop<Floating>();
521
522
pushInteger(
523
S,
524
[&] {
525
switch (ID) {
526
case Builtin::BI__builtin_isgreater:
527
return LHS > RHS;
528
case Builtin::BI__builtin_isgreaterequal:
529
return LHS >= RHS;
530
case Builtin::BI__builtin_isless:
531
return LHS < RHS;
532
case Builtin::BI__builtin_islessequal:
533
return LHS <= RHS;
534
case Builtin::BI__builtin_islessgreater: {
535
ComparisonCategoryResult cmp = LHS.compare(RHS);
536
return cmp == ComparisonCategoryResult::Less ||
537
cmp == ComparisonCategoryResult::Greater;
538
}
539
case Builtin::BI__builtin_isunordered:
540
return LHS.compare(RHS) == ComparisonCategoryResult::Unordered;
541
default:
542
llvm_unreachable("Unexpected builtin ID: Should be a floating point "
543
"comparison function");
544
}
545
}(),
546
Call->getType());
547
return true;
548
}
549
550
/// First parameter to __builtin_isfpclass is the floating value, the
551
/// second one is an integral value.
552
static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,
553
const InterpFrame *Frame,
554
const CallExpr *Call) {
555
PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType());
556
APSInt FPClassArg = popToAPSInt(S.Stk, FPClassArgT);
557
const Floating &F = S.Stk.pop<Floating>();
558
559
int32_t Result = static_cast<int32_t>(
560
(F.classify() & std::move(FPClassArg)).getZExtValue());
561
pushInteger(S, Result, Call->getType());
562
563
return true;
564
}
565
566
/// Five int values followed by one floating value.
567
/// __builtin_fpclassify(int, int, int, int, int, float)
568
static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
569
const InterpFrame *Frame,
570
const CallExpr *Call) {
571
const Floating &Val = S.Stk.pop<Floating>();
572
573
PrimType IntT = *S.getContext().classify(Call->getArg(0));
574
APSInt Values[5];
575
for (unsigned I = 0; I != 5; ++I)
576
Values[4 - I] = popToAPSInt(S.Stk, IntT);
577
578
unsigned Index;
579
switch (Val.getCategory()) {
580
case APFloat::fcNaN:
581
Index = 0;
582
break;
583
case APFloat::fcInfinity:
584
Index = 1;
585
break;
586
case APFloat::fcNormal:
587
Index = Val.isDenormal() ? 3 : 2;
588
break;
589
case APFloat::fcZero:
590
Index = 4;
591
break;
592
}
593
594
// The last argument is first on the stack.
595
assert(Index <= 4);
596
597
pushInteger(S, Values[Index], Call->getType());
598
return true;
599
}
600
601
// The C standard says "fabs raises no floating-point exceptions,
602
// even if x is a signaling NaN. The returned value is independent of
603
// the current rounding direction mode." Therefore constant folding can
604
// proceed without regard to the floating point settings.
605
// Reference, WG14 N2478 F.10.4.3
606
static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,
607
const InterpFrame *Frame) {
608
const Floating &Val = S.Stk.pop<Floating>();
609
APFloat F = Val.getAPFloat();
610
if (!F.isNegative()) {
611
S.Stk.push<Floating>(Val);
612
return true;
613
}
614
615
Floating Result = S.allocFloat(Val.getSemantics());
616
F.changeSign();
617
Result.copy(F);
618
S.Stk.push<Floating>(Result);
619
return true;
620
}
621
622
static bool interp__builtin_abs(InterpState &S, CodePtr OpPC,
623
const InterpFrame *Frame,
624
const CallExpr *Call) {
625
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
626
APSInt Val = popToAPSInt(S.Stk, ArgT);
627
if (Val ==
628
APSInt(APInt::getSignedMinValue(Val.getBitWidth()), /*IsUnsigned=*/false))
629
return false;
630
if (Val.isNegative())
631
Val.negate();
632
pushInteger(S, Val, Call->getType());
633
return true;
634
}
635
636
static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,
637
const InterpFrame *Frame,
638
const CallExpr *Call) {
639
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
640
APSInt Val = popToAPSInt(S.Stk, ArgT);
641
pushInteger(S, Val.popcount(), Call->getType());
642
return true;
643
}
644
645
static bool interp__builtin_parity(InterpState &S, CodePtr OpPC,
646
const InterpFrame *Frame,
647
const CallExpr *Call) {
648
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
649
APSInt Val = popToAPSInt(S.Stk, ArgT);
650
pushInteger(S, Val.popcount() % 2, Call->getType());
651
return true;
652
}
653
654
static bool interp__builtin_clrsb(InterpState &S, CodePtr OpPC,
655
const InterpFrame *Frame,
656
const CallExpr *Call) {
657
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
658
APSInt Val = popToAPSInt(S.Stk, ArgT);
659
pushInteger(S, Val.getBitWidth() - Val.getSignificantBits(), Call->getType());
660
return true;
661
}
662
663
static bool interp__builtin_bitreverse(InterpState &S, CodePtr OpPC,
664
const InterpFrame *Frame,
665
const CallExpr *Call) {
666
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
667
APSInt Val = popToAPSInt(S.Stk, ArgT);
668
pushInteger(S, Val.reverseBits(), Call->getType());
669
return true;
670
}
671
672
static bool interp__builtin_classify_type(InterpState &S, CodePtr OpPC,
673
const InterpFrame *Frame,
674
const CallExpr *Call) {
675
// This is an unevaluated call, so there are no arguments on the stack.
676
assert(Call->getNumArgs() == 1);
677
const Expr *Arg = Call->getArg(0);
678
679
GCCTypeClass ResultClass =
680
EvaluateBuiltinClassifyType(Arg->getType(), S.getLangOpts());
681
int32_t ReturnVal = static_cast<int32_t>(ResultClass);
682
pushInteger(S, ReturnVal, Call->getType());
683
return true;
684
}
685
686
// __builtin_expect(long, long)
687
// __builtin_expect_with_probability(long, long, double)
688
static bool interp__builtin_expect(InterpState &S, CodePtr OpPC,
689
const InterpFrame *Frame,
690
const CallExpr *Call) {
691
// The return value is simply the value of the first parameter.
692
// We ignore the probability.
693
unsigned NumArgs = Call->getNumArgs();
694
assert(NumArgs == 2 || NumArgs == 3);
695
696
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
697
if (NumArgs == 3)
698
S.Stk.discard<Floating>();
699
discard(S.Stk, ArgT);
700
701
APSInt Val = popToAPSInt(S.Stk, ArgT);
702
pushInteger(S, Val, Call->getType());
703
return true;
704
}
705
706
/// rotateleft(value, amount)
707
static bool interp__builtin_rotate(InterpState &S, CodePtr OpPC,
708
const InterpFrame *Frame,
709
const CallExpr *Call, bool Right) {
710
PrimType AmountT = *S.getContext().classify(Call->getArg(1)->getType());
711
PrimType ValueT = *S.getContext().classify(Call->getArg(0)->getType());
712
713
APSInt Amount = popToAPSInt(S.Stk, AmountT);
714
APSInt Value = popToAPSInt(S.Stk, ValueT);
715
716
APSInt Result;
717
if (Right)
718
Result = APSInt(Value.rotr(Amount.urem(Value.getBitWidth())),
719
/*IsUnsigned=*/true);
720
else // Left.
721
Result = APSInt(Value.rotl(Amount.urem(Value.getBitWidth())),
722
/*IsUnsigned=*/true);
723
724
pushInteger(S, Result, Call->getType());
725
return true;
726
}
727
728
static bool interp__builtin_ffs(InterpState &S, CodePtr OpPC,
729
const InterpFrame *Frame,
730
const CallExpr *Call) {
731
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
732
APSInt Value = popToAPSInt(S.Stk, ArgT);
733
734
uint64_t N = Value.countr_zero();
735
pushInteger(S, N == Value.getBitWidth() ? 0 : N + 1, Call->getType());
736
return true;
737
}
738
739
static bool interp__builtin_addressof(InterpState &S, CodePtr OpPC,
740
const InterpFrame *Frame,
741
const CallExpr *Call) {
742
#ifndef NDEBUG
743
assert(Call->getArg(0)->isLValue());
744
PrimType PtrT = S.getContext().classify(Call->getArg(0)).value_or(PT_Ptr);
745
assert(PtrT == PT_Ptr &&
746
"Unsupported pointer type passed to __builtin_addressof()");
747
#endif
748
return true;
749
}
750
751
static bool interp__builtin_move(InterpState &S, CodePtr OpPC,
752
const InterpFrame *Frame,
753
const CallExpr *Call) {
754
return Call->getDirectCallee()->isConstexpr();
755
}
756
757
static bool interp__builtin_eh_return_data_regno(InterpState &S, CodePtr OpPC,
758
const InterpFrame *Frame,
759
const CallExpr *Call) {
760
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
761
APSInt Arg = popToAPSInt(S.Stk, ArgT);
762
763
int Result = S.getASTContext().getTargetInfo().getEHDataRegisterNumber(
764
Arg.getZExtValue());
765
pushInteger(S, Result, Call->getType());
766
return true;
767
}
768
769
// Two integral values followed by a pointer (lhs, rhs, resultOut)
770
static bool interp__builtin_overflowop(InterpState &S, CodePtr OpPC,
771
const CallExpr *Call,
772
unsigned BuiltinOp) {
773
const Pointer &ResultPtr = S.Stk.pop<Pointer>();
774
if (ResultPtr.isDummy())
775
return false;
776
777
PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
778
PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());
779
APSInt RHS = popToAPSInt(S.Stk, RHST);
780
APSInt LHS = popToAPSInt(S.Stk, LHST);
781
QualType ResultType = Call->getArg(2)->getType()->getPointeeType();
782
PrimType ResultT = *S.getContext().classify(ResultType);
783
bool Overflow;
784
785
APSInt Result;
786
if (BuiltinOp == Builtin::BI__builtin_add_overflow ||
787
BuiltinOp == Builtin::BI__builtin_sub_overflow ||
788
BuiltinOp == Builtin::BI__builtin_mul_overflow) {
789
bool IsSigned = LHS.isSigned() || RHS.isSigned() ||
790
ResultType->isSignedIntegerOrEnumerationType();
791
bool AllSigned = LHS.isSigned() && RHS.isSigned() &&
792
ResultType->isSignedIntegerOrEnumerationType();
793
uint64_t LHSSize = LHS.getBitWidth();
794
uint64_t RHSSize = RHS.getBitWidth();
795
uint64_t ResultSize = S.getASTContext().getTypeSize(ResultType);
796
uint64_t MaxBits = std::max(std::max(LHSSize, RHSSize), ResultSize);
797
798
// Add an additional bit if the signedness isn't uniformly agreed to. We
799
// could do this ONLY if there is a signed and an unsigned that both have
800
// MaxBits, but the code to check that is pretty nasty. The issue will be
801
// caught in the shrink-to-result later anyway.
802
if (IsSigned && !AllSigned)
803
++MaxBits;
804
805
LHS = APSInt(LHS.extOrTrunc(MaxBits), !IsSigned);
806
RHS = APSInt(RHS.extOrTrunc(MaxBits), !IsSigned);
807
Result = APSInt(MaxBits, !IsSigned);
808
}
809
810
// Find largest int.
811
switch (BuiltinOp) {
812
default:
813
llvm_unreachable("Invalid value for BuiltinOp");
814
case Builtin::BI__builtin_add_overflow:
815
case Builtin::BI__builtin_sadd_overflow:
816
case Builtin::BI__builtin_saddl_overflow:
817
case Builtin::BI__builtin_saddll_overflow:
818
case Builtin::BI__builtin_uadd_overflow:
819
case Builtin::BI__builtin_uaddl_overflow:
820
case Builtin::BI__builtin_uaddll_overflow:
821
Result = LHS.isSigned() ? LHS.sadd_ov(RHS, Overflow)
822
: LHS.uadd_ov(RHS, Overflow);
823
break;
824
case Builtin::BI__builtin_sub_overflow:
825
case Builtin::BI__builtin_ssub_overflow:
826
case Builtin::BI__builtin_ssubl_overflow:
827
case Builtin::BI__builtin_ssubll_overflow:
828
case Builtin::BI__builtin_usub_overflow:
829
case Builtin::BI__builtin_usubl_overflow:
830
case Builtin::BI__builtin_usubll_overflow:
831
Result = LHS.isSigned() ? LHS.ssub_ov(RHS, Overflow)
832
: LHS.usub_ov(RHS, Overflow);
833
break;
834
case Builtin::BI__builtin_mul_overflow:
835
case Builtin::BI__builtin_smul_overflow:
836
case Builtin::BI__builtin_smull_overflow:
837
case Builtin::BI__builtin_smulll_overflow:
838
case Builtin::BI__builtin_umul_overflow:
839
case Builtin::BI__builtin_umull_overflow:
840
case Builtin::BI__builtin_umulll_overflow:
841
Result = LHS.isSigned() ? LHS.smul_ov(RHS, Overflow)
842
: LHS.umul_ov(RHS, Overflow);
843
break;
844
}
845
846
// In the case where multiple sizes are allowed, truncate and see if
847
// the values are the same.
848
if (BuiltinOp == Builtin::BI__builtin_add_overflow ||
849
BuiltinOp == Builtin::BI__builtin_sub_overflow ||
850
BuiltinOp == Builtin::BI__builtin_mul_overflow) {
851
// APSInt doesn't have a TruncOrSelf, so we use extOrTrunc instead,
852
// since it will give us the behavior of a TruncOrSelf in the case where
853
// its parameter <= its size. We previously set Result to be at least the
854
// type-size of the result, so getTypeSize(ResultType) <= Resu
855
APSInt Temp = Result.extOrTrunc(S.getASTContext().getTypeSize(ResultType));
856
Temp.setIsSigned(ResultType->isSignedIntegerOrEnumerationType());
857
858
if (!APSInt::isSameValue(Temp, Result))
859
Overflow = true;
860
Result = std::move(Temp);
861
}
862
863
// Write Result to ResultPtr and put Overflow on the stack.
864
assignInteger(S, ResultPtr, ResultT, Result);
865
if (ResultPtr.canBeInitialized())
866
ResultPtr.initialize();
867
868
assert(Call->getDirectCallee()->getReturnType()->isBooleanType());
869
S.Stk.push<Boolean>(Overflow);
870
return true;
871
}
872
873
/// Three integral values followed by a pointer (lhs, rhs, carry, carryOut).
874
static bool interp__builtin_carryop(InterpState &S, CodePtr OpPC,
875
const InterpFrame *Frame,
876
const CallExpr *Call, unsigned BuiltinOp) {
877
const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();
878
PrimType LHST = *S.getContext().classify(Call->getArg(0)->getType());
879
PrimType RHST = *S.getContext().classify(Call->getArg(1)->getType());
880
APSInt CarryIn = popToAPSInt(S.Stk, LHST);
881
APSInt RHS = popToAPSInt(S.Stk, RHST);
882
APSInt LHS = popToAPSInt(S.Stk, LHST);
883
884
APSInt CarryOut;
885
886
APSInt Result;
887
// Copy the number of bits and sign.
888
Result = LHS;
889
CarryOut = LHS;
890
891
bool FirstOverflowed = false;
892
bool SecondOverflowed = false;
893
switch (BuiltinOp) {
894
default:
895
llvm_unreachable("Invalid value for BuiltinOp");
896
case Builtin::BI__builtin_addcb:
897
case Builtin::BI__builtin_addcs:
898
case Builtin::BI__builtin_addc:
899
case Builtin::BI__builtin_addcl:
900
case Builtin::BI__builtin_addcll:
901
Result =
902
LHS.uadd_ov(RHS, FirstOverflowed).uadd_ov(CarryIn, SecondOverflowed);
903
break;
904
case Builtin::BI__builtin_subcb:
905
case Builtin::BI__builtin_subcs:
906
case Builtin::BI__builtin_subc:
907
case Builtin::BI__builtin_subcl:
908
case Builtin::BI__builtin_subcll:
909
Result =
910
LHS.usub_ov(RHS, FirstOverflowed).usub_ov(CarryIn, SecondOverflowed);
911
break;
912
}
913
// It is possible for both overflows to happen but CGBuiltin uses an OR so
914
// this is consistent.
915
CarryOut = (uint64_t)(FirstOverflowed | SecondOverflowed);
916
917
QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
918
PrimType CarryOutT = *S.getContext().classify(CarryOutType);
919
assignInteger(S, CarryOutPtr, CarryOutT, CarryOut);
920
CarryOutPtr.initialize();
921
922
assert(Call->getType() == Call->getArg(0)->getType());
923
pushInteger(S, Result, Call->getType());
924
return true;
925
}
926
927
static bool interp__builtin_clz(InterpState &S, CodePtr OpPC,
928
const InterpFrame *Frame, const CallExpr *Call,
929
unsigned BuiltinOp) {
930
931
std::optional<APSInt> Fallback;
932
if (BuiltinOp == Builtin::BI__builtin_clzg && Call->getNumArgs() == 2) {
933
PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
934
Fallback = popToAPSInt(S.Stk, FallbackT);
935
}
936
PrimType ValT = *S.getContext().classify(Call->getArg(0));
937
const APSInt &Val = popToAPSInt(S.Stk, ValT);
938
939
// When the argument is 0, the result of GCC builtins is undefined, whereas
940
// for Microsoft intrinsics, the result is the bit-width of the argument.
941
bool ZeroIsUndefined = BuiltinOp != Builtin::BI__lzcnt16 &&
942
BuiltinOp != Builtin::BI__lzcnt &&
943
BuiltinOp != Builtin::BI__lzcnt64;
944
945
if (Val == 0) {
946
if (Fallback) {
947
pushInteger(S, *Fallback, Call->getType());
948
return true;
949
}
950
951
if (ZeroIsUndefined)
952
return false;
953
}
954
955
pushInteger(S, Val.countl_zero(), Call->getType());
956
return true;
957
}
958
959
static bool interp__builtin_ctz(InterpState &S, CodePtr OpPC,
960
const InterpFrame *Frame, const CallExpr *Call,
961
unsigned BuiltinID) {
962
std::optional<APSInt> Fallback;
963
if (BuiltinID == Builtin::BI__builtin_ctzg && Call->getNumArgs() == 2) {
964
PrimType FallbackT = *S.getContext().classify(Call->getArg(1));
965
Fallback = popToAPSInt(S.Stk, FallbackT);
966
}
967
PrimType ValT = *S.getContext().classify(Call->getArg(0));
968
const APSInt &Val = popToAPSInt(S.Stk, ValT);
969
970
if (Val == 0) {
971
if (Fallback) {
972
pushInteger(S, *Fallback, Call->getType());
973
return true;
974
}
975
return false;
976
}
977
978
pushInteger(S, Val.countr_zero(), Call->getType());
979
return true;
980
}
981
982
static bool interp__builtin_bswap(InterpState &S, CodePtr OpPC,
983
const InterpFrame *Frame,
984
const CallExpr *Call) {
985
PrimType ReturnT = *S.getContext().classify(Call->getType());
986
PrimType ValT = *S.getContext().classify(Call->getArg(0));
987
const APSInt &Val = popToAPSInt(S.Stk, ValT);
988
assert(Val.getActiveBits() <= 64);
989
990
INT_TYPE_SWITCH(ReturnT,
991
{ S.Stk.push<T>(T::from(Val.byteSwap().getZExtValue())); });
992
return true;
993
}
994
995
/// bool __atomic_always_lock_free(size_t, void const volatile*)
996
/// bool __atomic_is_lock_free(size_t, void const volatile*)
997
static bool interp__builtin_atomic_lock_free(InterpState &S, CodePtr OpPC,
998
const InterpFrame *Frame,
999
const CallExpr *Call,
1000
unsigned BuiltinOp) {
1001
auto returnBool = [&S](bool Value) -> bool {
1002
S.Stk.push<Boolean>(Value);
1003
return true;
1004
};
1005
1006
PrimType ValT = *S.getContext().classify(Call->getArg(0));
1007
const Pointer &Ptr = S.Stk.pop<Pointer>();
1008
const APSInt &SizeVal = popToAPSInt(S.Stk, ValT);
1009
1010
// For __atomic_is_lock_free(sizeof(_Atomic(T))), if the size is a power
1011
// of two less than or equal to the maximum inline atomic width, we know it
1012
// is lock-free. If the size isn't a power of two, or greater than the
1013
// maximum alignment where we promote atomics, we know it is not lock-free
1014
// (at least not in the sense of atomic_is_lock_free). Otherwise,
1015
// the answer can only be determined at runtime; for example, 16-byte
1016
// atomics have lock-free implementations on some, but not all,
1017
// x86-64 processors.
1018
1019
// Check power-of-two.
1020
CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());
1021
if (Size.isPowerOfTwo()) {
1022
// Check against inlining width.
1023
unsigned InlineWidthBits =
1024
S.getASTContext().getTargetInfo().getMaxAtomicInlineWidth();
1025
if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits)) {
1026
1027
// OK, we will inline appropriately-aligned operations of this size,
1028
// and _Atomic(T) is appropriately-aligned.
1029
if (Size == CharUnits::One())
1030
return returnBool(true);
1031
1032
// Same for null pointers.
1033
assert(BuiltinOp != Builtin::BI__c11_atomic_is_lock_free);
1034
if (Ptr.isZero())
1035
return returnBool(true);
1036
1037
if (Ptr.isIntegralPointer()) {
1038
uint64_t IntVal = Ptr.getIntegerRepresentation();
1039
if (APSInt(APInt(64, IntVal, false), true).isAligned(Size.getAsAlign()))
1040
return returnBool(true);
1041
}
1042
1043
const Expr *PtrArg = Call->getArg(1);
1044
// Otherwise, check if the type's alignment against Size.
1045
if (const auto *ICE = dyn_cast<ImplicitCastExpr>(PtrArg)) {
1046
// Drop the potential implicit-cast to 'const volatile void*', getting
1047
// the underlying type.
1048
if (ICE->getCastKind() == CK_BitCast)
1049
PtrArg = ICE->getSubExpr();
1050
}
1051
1052
if (auto PtrTy = PtrArg->getType()->getAs<PointerType>()) {
1053
QualType PointeeType = PtrTy->getPointeeType();
1054
if (!PointeeType->isIncompleteType() &&
1055
S.getASTContext().getTypeAlignInChars(PointeeType) >= Size) {
1056
// OK, we will inline operations on this object.
1057
return returnBool(true);
1058
}
1059
}
1060
}
1061
}
1062
1063
if (BuiltinOp == Builtin::BI__atomic_always_lock_free)
1064
return returnBool(false);
1065
1066
return false;
1067
}
1068
1069
/// bool __c11_atomic_is_lock_free(size_t)
1070
static bool interp__builtin_c11_atomic_is_lock_free(InterpState &S,
1071
CodePtr OpPC,
1072
const InterpFrame *Frame,
1073
const CallExpr *Call) {
1074
PrimType ValT = *S.getContext().classify(Call->getArg(0));
1075
const APSInt &SizeVal = popToAPSInt(S.Stk, ValT);
1076
1077
auto returnBool = [&S](bool Value) -> bool {
1078
S.Stk.push<Boolean>(Value);
1079
return true;
1080
};
1081
1082
CharUnits Size = CharUnits::fromQuantity(SizeVal.getZExtValue());
1083
if (Size.isPowerOfTwo()) {
1084
// Check against inlining width.
1085
unsigned InlineWidthBits =
1086
S.getASTContext().getTargetInfo().getMaxAtomicInlineWidth();
1087
if (Size <= S.getASTContext().toCharUnitsFromBits(InlineWidthBits))
1088
return returnBool(true);
1089
}
1090
1091
return false; // returnBool(false);
1092
}
1093
1094
/// __builtin_complex(Float A, float B);
1095
static bool interp__builtin_complex(InterpState &S, CodePtr OpPC,
1096
const InterpFrame *Frame,
1097
const CallExpr *Call) {
1098
const Floating &Arg2 = S.Stk.pop<Floating>();
1099
const Floating &Arg1 = S.Stk.pop<Floating>();
1100
Pointer &Result = S.Stk.peek<Pointer>();
1101
1102
Result.atIndex(0).deref<Floating>() = Arg1;
1103
Result.atIndex(0).initialize();
1104
Result.atIndex(1).deref<Floating>() = Arg2;
1105
Result.atIndex(1).initialize();
1106
Result.initialize();
1107
1108
return true;
1109
}
1110
1111
/// __builtin_is_aligned()
1112
/// __builtin_align_up()
1113
/// __builtin_align_down()
1114
/// The first parameter is either an integer or a pointer.
1115
/// The second parameter is the requested alignment as an integer.
1116
static bool interp__builtin_is_aligned_up_down(InterpState &S, CodePtr OpPC,
1117
const InterpFrame *Frame,
1118
const CallExpr *Call,
1119
unsigned BuiltinOp) {
1120
PrimType AlignmentT = *S.Ctx.classify(Call->getArg(1));
1121
const APSInt &Alignment = popToAPSInt(S.Stk, AlignmentT);
1122
1123
if (Alignment < 0 || !Alignment.isPowerOf2()) {
1124
S.FFDiag(Call, diag::note_constexpr_invalid_alignment) << Alignment;
1125
return false;
1126
}
1127
unsigned SrcWidth = S.getASTContext().getIntWidth(Call->getArg(0)->getType());
1128
APSInt MaxValue(APInt::getOneBitSet(SrcWidth, SrcWidth - 1));
1129
if (APSInt::compareValues(Alignment, MaxValue) > 0) {
1130
S.FFDiag(Call, diag::note_constexpr_alignment_too_big)
1131
<< MaxValue << Call->getArg(0)->getType() << Alignment;
1132
return false;
1133
}
1134
1135
// The first parameter is either an integer or a pointer (but not a function
1136
// pointer).
1137
PrimType FirstArgT = *S.Ctx.classify(Call->getArg(0));
1138
1139
if (isIntegralType(FirstArgT)) {
1140
const APSInt &Src = popToAPSInt(S.Stk, FirstArgT);
1141
APInt AlignMinusOne = Alignment.extOrTrunc(Src.getBitWidth()) - 1;
1142
if (BuiltinOp == Builtin::BI__builtin_align_up) {
1143
APSInt AlignedVal =
1144
APSInt((Src + AlignMinusOne) & ~AlignMinusOne, Src.isUnsigned());
1145
pushInteger(S, AlignedVal, Call->getType());
1146
} else if (BuiltinOp == Builtin::BI__builtin_align_down) {
1147
APSInt AlignedVal = APSInt(Src & ~AlignMinusOne, Src.isUnsigned());
1148
pushInteger(S, AlignedVal, Call->getType());
1149
} else {
1150
assert(*S.Ctx.classify(Call->getType()) == PT_Bool);
1151
S.Stk.push<Boolean>((Src & AlignMinusOne) == 0);
1152
}
1153
return true;
1154
}
1155
1156
assert(FirstArgT == PT_Ptr);
1157
const Pointer &Ptr = S.Stk.pop<Pointer>();
1158
1159
unsigned PtrOffset = Ptr.getByteOffset();
1160
PtrOffset = Ptr.getIndex();
1161
CharUnits BaseAlignment =
1162
S.getASTContext().getDeclAlign(Ptr.getDeclDesc()->asValueDecl());
1163
CharUnits PtrAlign =
1164
BaseAlignment.alignmentAtOffset(CharUnits::fromQuantity(PtrOffset));
1165
1166
if (BuiltinOp == Builtin::BI__builtin_is_aligned) {
1167
if (PtrAlign.getQuantity() >= Alignment) {
1168
S.Stk.push<Boolean>(true);
1169
return true;
1170
}
1171
// If the alignment is not known to be sufficient, some cases could still
1172
// be aligned at run time. However, if the requested alignment is less or
1173
// equal to the base alignment and the offset is not aligned, we know that
1174
// the run-time value can never be aligned.
1175
if (BaseAlignment.getQuantity() >= Alignment &&
1176
PtrAlign.getQuantity() < Alignment) {
1177
S.Stk.push<Boolean>(false);
1178
return true;
1179
}
1180
1181
S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_compute)
1182
<< Alignment;
1183
return false;
1184
}
1185
1186
assert(BuiltinOp == Builtin::BI__builtin_align_down ||
1187
BuiltinOp == Builtin::BI__builtin_align_up);
1188
1189
// For align_up/align_down, we can return the same value if the alignment
1190
// is known to be greater or equal to the requested value.
1191
if (PtrAlign.getQuantity() >= Alignment) {
1192
S.Stk.push<Pointer>(Ptr);
1193
return true;
1194
}
1195
1196
// The alignment could be greater than the minimum at run-time, so we cannot
1197
// infer much about the resulting pointer value. One case is possible:
1198
// For `_Alignas(32) char buf[N]; __builtin_align_down(&buf[idx], 32)` we
1199
// can infer the correct index if the requested alignment is smaller than
1200
// the base alignment so we can perform the computation on the offset.
1201
if (BaseAlignment.getQuantity() >= Alignment) {
1202
assert(Alignment.getBitWidth() <= 64 &&
1203
"Cannot handle > 64-bit address-space");
1204
uint64_t Alignment64 = Alignment.getZExtValue();
1205
CharUnits NewOffset =
1206
CharUnits::fromQuantity(BuiltinOp == Builtin::BI__builtin_align_down
1207
? llvm::alignDown(PtrOffset, Alignment64)
1208
: llvm::alignTo(PtrOffset, Alignment64));
1209
1210
S.Stk.push<Pointer>(Ptr.atIndex(NewOffset.getQuantity()));
1211
return true;
1212
}
1213
1214
// Otherwise, we cannot constant-evaluate the result.
1215
S.FFDiag(Call->getArg(0), diag::note_constexpr_alignment_adjust) << Alignment;
1216
return false;
1217
}
1218
1219
/// __builtin_assume_aligned(Ptr, Alignment[, ExtraOffset])
1220
static bool interp__builtin_assume_aligned(InterpState &S, CodePtr OpPC,
1221
const InterpFrame *Frame,
1222
const CallExpr *Call) {
1223
assert(Call->getNumArgs() == 2 || Call->getNumArgs() == 3);
1224
1225
std::optional<APSInt> ExtraOffset;
1226
if (Call->getNumArgs() == 3)
1227
ExtraOffset = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(2)));
1228
1229
APSInt Alignment = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(1)));
1230
const Pointer &Ptr = S.Stk.pop<Pointer>();
1231
1232
CharUnits Align = CharUnits::fromQuantity(Alignment.getZExtValue());
1233
1234
// If there is a base object, then it must have the correct alignment.
1235
if (Ptr.isBlockPointer()) {
1236
CharUnits BaseAlignment;
1237
if (const auto *VD = Ptr.getDeclDesc()->asValueDecl())
1238
BaseAlignment = S.getASTContext().getDeclAlign(VD);
1239
else if (const auto *E = Ptr.getDeclDesc()->asExpr())
1240
BaseAlignment = GetAlignOfExpr(S.getASTContext(), E, UETT_AlignOf);
1241
1242
if (BaseAlignment < Align) {
1243
S.CCEDiag(Call->getArg(0),
1244
diag::note_constexpr_baa_insufficient_alignment)
1245
<< 0 << BaseAlignment.getQuantity() << Align.getQuantity();
1246
return false;
1247
}
1248
}
1249
1250
APValue AV = Ptr.toAPValue(S.getASTContext());
1251
CharUnits AVOffset = AV.getLValueOffset();
1252
if (ExtraOffset)
1253
AVOffset -= CharUnits::fromQuantity(ExtraOffset->getZExtValue());
1254
if (AVOffset.alignTo(Align) != AVOffset) {
1255
if (Ptr.isBlockPointer())
1256
S.CCEDiag(Call->getArg(0),
1257
diag::note_constexpr_baa_insufficient_alignment)
1258
<< 1 << AVOffset.getQuantity() << Align.getQuantity();
1259
else
1260
S.CCEDiag(Call->getArg(0),
1261
diag::note_constexpr_baa_value_insufficient_alignment)
1262
<< AVOffset.getQuantity() << Align.getQuantity();
1263
return false;
1264
}
1265
1266
S.Stk.push<Pointer>(Ptr);
1267
return true;
1268
}
1269
1270
static bool interp__builtin_ia32_bextr(InterpState &S, CodePtr OpPC,
1271
const InterpFrame *Frame,
1272
const CallExpr *Call) {
1273
if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1274
!Call->getArg(1)->getType()->isIntegerType())
1275
return false;
1276
1277
PrimType ValT = *S.Ctx.classify(Call->getArg(0));
1278
PrimType IndexT = *S.Ctx.classify(Call->getArg(1));
1279
APSInt Index = popToAPSInt(S.Stk, IndexT);
1280
APSInt Val = popToAPSInt(S.Stk, ValT);
1281
1282
unsigned BitWidth = Val.getBitWidth();
1283
uint64_t Shift = Index.extractBitsAsZExtValue(8, 0);
1284
uint64_t Length = Index.extractBitsAsZExtValue(8, 8);
1285
Length = Length > BitWidth ? BitWidth : Length;
1286
1287
// Handle out of bounds cases.
1288
if (Length == 0 || Shift >= BitWidth) {
1289
pushInteger(S, 0, Call->getType());
1290
return true;
1291
}
1292
1293
uint64_t Result = Val.getZExtValue() >> Shift;
1294
Result &= llvm::maskTrailingOnes<uint64_t>(Length);
1295
pushInteger(S, Result, Call->getType());
1296
return true;
1297
}
1298
1299
static bool interp__builtin_ia32_bzhi(InterpState &S, CodePtr OpPC,
1300
const InterpFrame *Frame,
1301
const CallExpr *Call) {
1302
QualType CallType = Call->getType();
1303
if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1304
!Call->getArg(1)->getType()->isIntegerType() ||
1305
!CallType->isIntegerType())
1306
return false;
1307
1308
PrimType ValT = *S.Ctx.classify(Call->getArg(0));
1309
PrimType IndexT = *S.Ctx.classify(Call->getArg(1));
1310
1311
APSInt Idx = popToAPSInt(S.Stk, IndexT);
1312
APSInt Val = popToAPSInt(S.Stk, ValT);
1313
1314
unsigned BitWidth = Val.getBitWidth();
1315
uint64_t Index = Idx.extractBitsAsZExtValue(8, 0);
1316
1317
if (Index < BitWidth)
1318
Val.clearHighBits(BitWidth - Index);
1319
1320
pushInteger(S, Val, CallType);
1321
return true;
1322
}
1323
1324
static bool interp__builtin_ia32_lzcnt(InterpState &S, CodePtr OpPC,
1325
const InterpFrame *Frame,
1326
const CallExpr *Call) {
1327
QualType CallType = Call->getType();
1328
if (!CallType->isIntegerType() ||
1329
!Call->getArg(0)->getType()->isIntegerType())
1330
return false;
1331
1332
APSInt Val = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
1333
pushInteger(S, Val.countLeadingZeros(), CallType);
1334
return true;
1335
}
1336
1337
static bool interp__builtin_ia32_tzcnt(InterpState &S, CodePtr OpPC,
1338
const InterpFrame *Frame,
1339
const CallExpr *Call) {
1340
QualType CallType = Call->getType();
1341
if (!CallType->isIntegerType() ||
1342
!Call->getArg(0)->getType()->isIntegerType())
1343
return false;
1344
1345
APSInt Val = popToAPSInt(S.Stk, *S.Ctx.classify(Call->getArg(0)));
1346
pushInteger(S, Val.countTrailingZeros(), CallType);
1347
return true;
1348
}
1349
1350
static bool interp__builtin_ia32_pdep(InterpState &S, CodePtr OpPC,
1351
const InterpFrame *Frame,
1352
const CallExpr *Call) {
1353
if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1354
!Call->getArg(1)->getType()->isIntegerType())
1355
return false;
1356
1357
PrimType ValT = *S.Ctx.classify(Call->getArg(0));
1358
PrimType MaskT = *S.Ctx.classify(Call->getArg(1));
1359
1360
APSInt Mask = popToAPSInt(S.Stk, MaskT);
1361
APSInt Val = popToAPSInt(S.Stk, ValT);
1362
1363
unsigned BitWidth = Val.getBitWidth();
1364
APInt Result = APInt::getZero(BitWidth);
1365
for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
1366
if (Mask[I])
1367
Result.setBitVal(I, Val[P++]);
1368
}
1369
pushInteger(S, std::move(Result), Call->getType());
1370
return true;
1371
}
1372
1373
static bool interp__builtin_ia32_pext(InterpState &S, CodePtr OpPC,
1374
const InterpFrame *Frame,
1375
const CallExpr *Call) {
1376
if (Call->getNumArgs() != 2 || !Call->getArg(0)->getType()->isIntegerType() ||
1377
!Call->getArg(1)->getType()->isIntegerType())
1378
return false;
1379
1380
PrimType ValT = *S.Ctx.classify(Call->getArg(0));
1381
PrimType MaskT = *S.Ctx.classify(Call->getArg(1));
1382
1383
APSInt Mask = popToAPSInt(S.Stk, MaskT);
1384
APSInt Val = popToAPSInt(S.Stk, ValT);
1385
1386
unsigned BitWidth = Val.getBitWidth();
1387
APInt Result = APInt::getZero(BitWidth);
1388
for (unsigned I = 0, P = 0; I != BitWidth; ++I) {
1389
if (Mask[I])
1390
Result.setBitVal(P++, Val[I]);
1391
}
1392
pushInteger(S, std::move(Result), Call->getType());
1393
return true;
1394
}
1395
1396
/// (CarryIn, LHS, RHS, Result)
1397
static bool interp__builtin_ia32_addcarry_subborrow(InterpState &S,
1398
CodePtr OpPC,
1399
const InterpFrame *Frame,
1400
const CallExpr *Call,
1401
unsigned BuiltinOp) {
1402
if (Call->getNumArgs() != 4 || !Call->getArg(0)->getType()->isIntegerType() ||
1403
!Call->getArg(1)->getType()->isIntegerType() ||
1404
!Call->getArg(2)->getType()->isIntegerType())
1405
return false;
1406
1407
const Pointer &CarryOutPtr = S.Stk.pop<Pointer>();
1408
1409
PrimType CarryInT = *S.getContext().classify(Call->getArg(0));
1410
PrimType LHST = *S.getContext().classify(Call->getArg(1));
1411
PrimType RHST = *S.getContext().classify(Call->getArg(2));
1412
APSInt RHS = popToAPSInt(S.Stk, RHST);
1413
APSInt LHS = popToAPSInt(S.Stk, LHST);
1414
APSInt CarryIn = popToAPSInt(S.Stk, CarryInT);
1415
1416
bool IsAdd = BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u32 ||
1417
BuiltinOp == clang::X86::BI__builtin_ia32_addcarryx_u64;
1418
1419
unsigned BitWidth = LHS.getBitWidth();
1420
unsigned CarryInBit = CarryIn.ugt(0) ? 1 : 0;
1421
APInt ExResult =
1422
IsAdd ? (LHS.zext(BitWidth + 1) + (RHS.zext(BitWidth + 1) + CarryInBit))
1423
: (LHS.zext(BitWidth + 1) - (RHS.zext(BitWidth + 1) + CarryInBit));
1424
1425
APInt Result = ExResult.extractBits(BitWidth, 0);
1426
APSInt CarryOut =
1427
APSInt(ExResult.extractBits(1, BitWidth), /*IsUnsigned=*/true);
1428
1429
QualType CarryOutType = Call->getArg(3)->getType()->getPointeeType();
1430
PrimType CarryOutT = *S.getContext().classify(CarryOutType);
1431
assignInteger(S, CarryOutPtr, CarryOutT, APSInt(std::move(Result), true));
1432
1433
pushInteger(S, CarryOut, Call->getType());
1434
1435
return true;
1436
}
1437
1438
static bool interp__builtin_os_log_format_buffer_size(InterpState &S,
1439
CodePtr OpPC,
1440
const InterpFrame *Frame,
1441
const CallExpr *Call) {
1442
analyze_os_log::OSLogBufferLayout Layout;
1443
analyze_os_log::computeOSLogBufferLayout(S.getASTContext(), Call, Layout);
1444
pushInteger(S, Layout.size().getQuantity(), Call->getType());
1445
return true;
1446
}
1447
1448
static bool
1449
interp__builtin_ptrauth_string_discriminator(InterpState &S, CodePtr OpPC,
1450
const InterpFrame *Frame,
1451
const CallExpr *Call) {
1452
const auto &Ptr = S.Stk.pop<Pointer>();
1453
assert(Ptr.getFieldDesc()->isPrimitiveArray());
1454
1455
// This should be created for a StringLiteral, so should alway shold at least
1456
// one array element.
1457
assert(Ptr.getFieldDesc()->getNumElems() >= 1);
1458
StringRef R(&Ptr.deref<char>(), Ptr.getFieldDesc()->getNumElems() - 1);
1459
uint64_t Result = getPointerAuthStableSipHash(R);
1460
pushInteger(S, Result, Call->getType());
1461
return true;
1462
}
1463
1464
static bool interp__builtin_operator_new(InterpState &S, CodePtr OpPC,
1465
const InterpFrame *Frame,
1466
const CallExpr *Call) {
1467
// A call to __operator_new is only valid within std::allocate<>::allocate.
1468
// Walk up the call stack to find the appropriate caller and get the
1469
// element type from it.
1470
auto [NewCall, ElemType] = S.getStdAllocatorCaller("allocate");
1471
1472
if (ElemType.isNull()) {
1473
S.FFDiag(Call, S.getLangOpts().CPlusPlus20
1474
? diag::note_constexpr_new_untyped
1475
: diag::note_constexpr_new);
1476
return false;
1477
}
1478
assert(NewCall);
1479
1480
if (ElemType->isIncompleteType() || ElemType->isFunctionType()) {
1481
S.FFDiag(Call, diag::note_constexpr_new_not_complete_object_type)
1482
<< (ElemType->isIncompleteType() ? 0 : 1) << ElemType;
1483
return false;
1484
}
1485
1486
// We only care about the first parameter (the size), so discard all the
1487
// others.
1488
{
1489
unsigned NumArgs = Call->getNumArgs();
1490
assert(NumArgs >= 1);
1491
1492
// The std::nothrow_t arg never gets put on the stack.
1493
if (Call->getArg(NumArgs - 1)->getType()->isNothrowT())
1494
--NumArgs;
1495
auto Args = ArrayRef(Call->getArgs(), Call->getNumArgs());
1496
// First arg is needed.
1497
Args = Args.drop_front();
1498
1499
// Discard the rest.
1500
for (const Expr *Arg : Args)
1501
discard(S.Stk, *S.getContext().classify(Arg));
1502
}
1503
1504
APSInt Bytes = popToAPSInt(S.Stk, *S.getContext().classify(Call->getArg(0)));
1505
CharUnits ElemSize = S.getASTContext().getTypeSizeInChars(ElemType);
1506
assert(!ElemSize.isZero());
1507
// Divide the number of bytes by sizeof(ElemType), so we get the number of
1508
// elements we should allocate.
1509
APInt NumElems, Remainder;
1510
APInt ElemSizeAP(Bytes.getBitWidth(), ElemSize.getQuantity());
1511
APInt::udivrem(Bytes, ElemSizeAP, NumElems, Remainder);
1512
if (Remainder != 0) {
1513
// This likely indicates a bug in the implementation of 'std::allocator'.
1514
S.FFDiag(Call, diag::note_constexpr_operator_new_bad_size)
1515
<< Bytes << APSInt(ElemSizeAP, true) << ElemType;
1516
return false;
1517
}
1518
1519
// NB: The same check we're using in CheckArraySize()
1520
if (NumElems.getActiveBits() >
1521
ConstantArrayType::getMaxSizeBits(S.getASTContext()) ||
1522
NumElems.ugt(Descriptor::MaxArrayElemBytes / ElemSize.getQuantity())) {
1523
// FIXME: NoThrow check?
1524
const SourceInfo &Loc = S.Current->getSource(OpPC);
1525
S.FFDiag(Loc, diag::note_constexpr_new_too_large)
1526
<< NumElems.getZExtValue();
1527
return false;
1528
}
1529
1530
if (!CheckArraySize(S, OpPC, NumElems.getZExtValue()))
1531
return false;
1532
1533
bool IsArray = NumElems.ugt(1);
1534
std::optional<PrimType> ElemT = S.getContext().classify(ElemType);
1535
DynamicAllocator &Allocator = S.getAllocator();
1536
if (ElemT) {
1537
Block *B =
1538
Allocator.allocate(NewCall, *ElemT, NumElems.getZExtValue(),
1539
S.Ctx.getEvalID(), DynamicAllocator::Form::Operator);
1540
assert(B);
1541
S.Stk.push<Pointer>(Pointer(B).atIndex(0));
1542
return true;
1543
}
1544
1545
assert(!ElemT);
1546
1547
// Composite arrays
1548
if (IsArray) {
1549
const Descriptor *Desc =
1550
S.P.createDescriptor(NewCall, ElemType.getTypePtr(),
1551
IsArray ? std::nullopt : Descriptor::InlineDescMD);
1552
Block *B =
1553
Allocator.allocate(Desc, NumElems.getZExtValue(), S.Ctx.getEvalID(),
1554
DynamicAllocator::Form::Operator);
1555
assert(B);
1556
S.Stk.push<Pointer>(Pointer(B).atIndex(0));
1557
return true;
1558
}
1559
1560
// Records. Still allocate them as single-element arrays.
1561
QualType AllocType = S.getASTContext().getConstantArrayType(
1562
ElemType, NumElems, nullptr, ArraySizeModifier::Normal, 0);
1563
1564
const Descriptor *Desc =
1565
S.P.createDescriptor(NewCall, AllocType.getTypePtr(),
1566
IsArray ? std::nullopt : Descriptor::InlineDescMD);
1567
Block *B = Allocator.allocate(Desc, S.getContext().getEvalID(),
1568
DynamicAllocator::Form::Operator);
1569
assert(B);
1570
S.Stk.push<Pointer>(Pointer(B).atIndex(0).narrow());
1571
return true;
1572
}
1573
1574
static bool interp__builtin_operator_delete(InterpState &S, CodePtr OpPC,
1575
const InterpFrame *Frame,
1576
const CallExpr *Call) {
1577
const Expr *Source = nullptr;
1578
const Block *BlockToDelete = nullptr;
1579
1580
if (S.checkingPotentialConstantExpression()) {
1581
S.Stk.discard<Pointer>();
1582
return false;
1583
}
1584
1585
// This is permitted only within a call to std::allocator<T>::deallocate.
1586
if (!S.getStdAllocatorCaller("deallocate")) {
1587
S.FFDiag(Call);
1588
S.Stk.discard<Pointer>();
1589
return true;
1590
}
1591
1592
{
1593
const Pointer &Ptr = S.Stk.pop<Pointer>();
1594
1595
if (Ptr.isZero()) {
1596
S.CCEDiag(Call, diag::note_constexpr_deallocate_null);
1597
return true;
1598
}
1599
1600
Source = Ptr.getDeclDesc()->asExpr();
1601
BlockToDelete = Ptr.block();
1602
1603
if (!BlockToDelete->isDynamic()) {
1604
S.FFDiag(Call, diag::note_constexpr_delete_not_heap_alloc)
1605
<< Ptr.toDiagnosticString(S.getASTContext());
1606
if (const auto *D = Ptr.getFieldDesc()->asDecl())
1607
S.Note(D->getLocation(), diag::note_declared_at);
1608
}
1609
}
1610
assert(BlockToDelete);
1611
1612
DynamicAllocator &Allocator = S.getAllocator();
1613
const Descriptor *BlockDesc = BlockToDelete->getDescriptor();
1614
std::optional<DynamicAllocator::Form> AllocForm =
1615
Allocator.getAllocationForm(Source);
1616
1617
if (!Allocator.deallocate(Source, BlockToDelete, S)) {
1618
// Nothing has been deallocated, this must be a double-delete.
1619
const SourceInfo &Loc = S.Current->getSource(OpPC);
1620
S.FFDiag(Loc, diag::note_constexpr_double_delete);
1621
return false;
1622
}
1623
assert(AllocForm);
1624
1625
return CheckNewDeleteForms(
1626
S, OpPC, *AllocForm, DynamicAllocator::Form::Operator, BlockDesc, Source);
1627
}
1628
1629
static bool interp__builtin_arithmetic_fence(InterpState &S, CodePtr OpPC,
1630
const InterpFrame *Frame,
1631
const CallExpr *Call) {
1632
const Floating &Arg0 = S.Stk.pop<Floating>();
1633
S.Stk.push<Floating>(Arg0);
1634
return true;
1635
}
1636
1637
static bool interp__builtin_vector_reduce(InterpState &S, CodePtr OpPC,
1638
const CallExpr *Call, unsigned ID) {
1639
const Pointer &Arg = S.Stk.pop<Pointer>();
1640
assert(Arg.getFieldDesc()->isPrimitiveArray());
1641
1642
QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1643
assert(Call->getType() == ElemType);
1644
PrimType ElemT = *S.getContext().classify(ElemType);
1645
unsigned NumElems = Arg.getNumElems();
1646
1647
INT_TYPE_SWITCH_NO_BOOL(ElemT, {
1648
T Result = Arg.atIndex(0).deref<T>();
1649
unsigned BitWidth = Result.bitWidth();
1650
for (unsigned I = 1; I != NumElems; ++I) {
1651
T Elem = Arg.atIndex(I).deref<T>();
1652
T PrevResult = Result;
1653
1654
if (ID == Builtin::BI__builtin_reduce_add) {
1655
if (T::add(Result, Elem, BitWidth, &Result)) {
1656
unsigned OverflowBits = BitWidth + 1;
1657
(void)handleOverflow(S, OpPC,
1658
(PrevResult.toAPSInt(OverflowBits) +
1659
Elem.toAPSInt(OverflowBits)));
1660
return false;
1661
}
1662
} else if (ID == Builtin::BI__builtin_reduce_mul) {
1663
if (T::mul(Result, Elem, BitWidth, &Result)) {
1664
unsigned OverflowBits = BitWidth * 2;
1665
(void)handleOverflow(S, OpPC,
1666
(PrevResult.toAPSInt(OverflowBits) *
1667
Elem.toAPSInt(OverflowBits)));
1668
return false;
1669
}
1670
1671
} else if (ID == Builtin::BI__builtin_reduce_and) {
1672
(void)T::bitAnd(Result, Elem, BitWidth, &Result);
1673
} else if (ID == Builtin::BI__builtin_reduce_or) {
1674
(void)T::bitOr(Result, Elem, BitWidth, &Result);
1675
} else if (ID == Builtin::BI__builtin_reduce_xor) {
1676
(void)T::bitXor(Result, Elem, BitWidth, &Result);
1677
} else if (ID == Builtin::BI__builtin_reduce_min) {
1678
if (Elem < Result)
1679
Result = Elem;
1680
} else if (ID == Builtin::BI__builtin_reduce_max) {
1681
if (Elem > Result)
1682
Result = Elem;
1683
} else {
1684
llvm_unreachable("Unhandled vector reduce builtin");
1685
}
1686
}
1687
pushInteger(S, Result.toAPSInt(), Call->getType());
1688
});
1689
1690
return true;
1691
}
1692
1693
/// Can be called with an integer or vector as the first and only parameter.
1694
static bool interp__builtin_elementwise_popcount(InterpState &S, CodePtr OpPC,
1695
const InterpFrame *Frame,
1696
const CallExpr *Call,
1697
unsigned BuiltinID) {
1698
assert(Call->getNumArgs() == 1);
1699
if (Call->getArg(0)->getType()->isIntegerType()) {
1700
PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
1701
APSInt Val = popToAPSInt(S.Stk, ArgT);
1702
1703
if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) {
1704
pushInteger(S, Val.popcount(), Call->getType());
1705
} else {
1706
pushInteger(S, Val.reverseBits(), Call->getType());
1707
}
1708
return true;
1709
}
1710
// Otherwise, the argument must be a vector.
1711
assert(Call->getArg(0)->getType()->isVectorType());
1712
const Pointer &Arg = S.Stk.pop<Pointer>();
1713
assert(Arg.getFieldDesc()->isPrimitiveArray());
1714
const Pointer &Dst = S.Stk.peek<Pointer>();
1715
assert(Dst.getFieldDesc()->isPrimitiveArray());
1716
assert(Arg.getFieldDesc()->getNumElems() ==
1717
Dst.getFieldDesc()->getNumElems());
1718
1719
QualType ElemType = Arg.getFieldDesc()->getElemQualType();
1720
PrimType ElemT = *S.getContext().classify(ElemType);
1721
unsigned NumElems = Arg.getNumElems();
1722
1723
// FIXME: Reading from uninitialized vector elements?
1724
for (unsigned I = 0; I != NumElems; ++I) {
1725
INT_TYPE_SWITCH_NO_BOOL(ElemT, {
1726
if (BuiltinID == Builtin::BI__builtin_elementwise_popcount) {
1727
Dst.atIndex(I).deref<T>() =
1728
T::from(Arg.atIndex(I).deref<T>().toAPSInt().popcount());
1729
} else {
1730
Dst.atIndex(I).deref<T>() = T::from(
1731
Arg.atIndex(I).deref<T>().toAPSInt().reverseBits().getZExtValue());
1732
}
1733
Dst.atIndex(I).initialize();
1734
});
1735
}
1736
1737
return true;
1738
}
1739
1740
static bool interp__builtin_memcpy(InterpState &S, CodePtr OpPC,
1741
const InterpFrame *Frame,
1742
const CallExpr *Call, unsigned ID) {
1743
assert(Call->getNumArgs() == 3);
1744
const ASTContext &ASTCtx = S.getASTContext();
1745
PrimType SizeT = *S.getContext().classify(Call->getArg(2));
1746
APSInt Size = popToAPSInt(S.Stk, SizeT);
1747
const Pointer SrcPtr = S.Stk.pop<Pointer>();
1748
const Pointer DestPtr = S.Stk.pop<Pointer>();
1749
1750
assert(!Size.isSigned() && "memcpy and friends take an unsigned size");
1751
1752
if (ID == Builtin::BImemcpy || ID == Builtin::BImemmove)
1753
diagnoseNonConstexprBuiltin(S, OpPC, ID);
1754
1755
bool Move =
1756
(ID == Builtin::BI__builtin_memmove || ID == Builtin::BImemmove ||
1757
ID == Builtin::BI__builtin_wmemmove || ID == Builtin::BIwmemmove);
1758
bool WChar = ID == Builtin::BIwmemcpy || ID == Builtin::BIwmemmove ||
1759
ID == Builtin::BI__builtin_wmemcpy ||
1760
ID == Builtin::BI__builtin_wmemmove;
1761
1762
// If the size is zero, we treat this as always being a valid no-op.
1763
if (Size.isZero()) {
1764
S.Stk.push<Pointer>(DestPtr);
1765
return true;
1766
}
1767
1768
if (SrcPtr.isZero() || DestPtr.isZero()) {
1769
Pointer DiagPtr = (SrcPtr.isZero() ? SrcPtr : DestPtr);
1770
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
1771
<< /*IsMove=*/Move << /*IsWchar=*/WChar << !SrcPtr.isZero()
1772
<< DiagPtr.toDiagnosticString(ASTCtx);
1773
return false;
1774
}
1775
1776
// Diagnose integral src/dest pointers specially.
1777
if (SrcPtr.isIntegralPointer() || DestPtr.isIntegralPointer()) {
1778
std::string DiagVal = "(void *)";
1779
DiagVal += SrcPtr.isIntegralPointer()
1780
? std::to_string(SrcPtr.getIntegerRepresentation())
1781
: std::to_string(DestPtr.getIntegerRepresentation());
1782
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_null)
1783
<< Move << WChar << DestPtr.isIntegralPointer() << DiagVal;
1784
return false;
1785
}
1786
1787
// Can't read from dummy pointers.
1788
if (DestPtr.isDummy() || SrcPtr.isDummy())
1789
return false;
1790
1791
QualType DestElemType = getElemType(DestPtr);
1792
size_t RemainingDestElems;
1793
if (DestPtr.getFieldDesc()->isArray()) {
1794
RemainingDestElems = DestPtr.isUnknownSizeArray()
1795
? 0
1796
: (DestPtr.getNumElems() - DestPtr.getIndex());
1797
} else {
1798
RemainingDestElems = 1;
1799
}
1800
unsigned DestElemSize = ASTCtx.getTypeSizeInChars(DestElemType).getQuantity();
1801
1802
if (WChar) {
1803
uint64_t WCharSize =
1804
ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();
1805
Size *= APSInt(APInt(Size.getBitWidth(), WCharSize, /*IsSigned=*/false),
1806
/*IsUnsigend=*/true);
1807
}
1808
1809
if (Size.urem(DestElemSize) != 0) {
1810
S.FFDiag(S.Current->getSource(OpPC),
1811
diag::note_constexpr_memcpy_unsupported)
1812
<< Move << WChar << 0 << DestElemType << Size << DestElemSize;
1813
return false;
1814
}
1815
1816
QualType SrcElemType = getElemType(SrcPtr);
1817
size_t RemainingSrcElems;
1818
if (SrcPtr.getFieldDesc()->isArray()) {
1819
RemainingSrcElems = SrcPtr.isUnknownSizeArray()
1820
? 0
1821
: (SrcPtr.getNumElems() - SrcPtr.getIndex());
1822
} else {
1823
RemainingSrcElems = 1;
1824
}
1825
unsigned SrcElemSize = ASTCtx.getTypeSizeInChars(SrcElemType).getQuantity();
1826
1827
if (!ASTCtx.hasSameUnqualifiedType(DestElemType, SrcElemType)) {
1828
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_type_pun)
1829
<< Move << SrcElemType << DestElemType;
1830
return false;
1831
}
1832
1833
if (DestElemType->isIncompleteType() ||
1834
DestPtr.getType()->isIncompleteType()) {
1835
QualType DiagType =
1836
DestElemType->isIncompleteType() ? DestElemType : DestPtr.getType();
1837
S.FFDiag(S.Current->getSource(OpPC),
1838
diag::note_constexpr_memcpy_incomplete_type)
1839
<< Move << DiagType;
1840
return false;
1841
}
1842
1843
if (!DestElemType.isTriviallyCopyableType(ASTCtx)) {
1844
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_nontrivial)
1845
<< Move << DestElemType;
1846
return false;
1847
}
1848
1849
// Check if we have enough elements to read from and write to.
1850
size_t RemainingDestBytes = RemainingDestElems * DestElemSize;
1851
size_t RemainingSrcBytes = RemainingSrcElems * SrcElemSize;
1852
if (Size.ugt(RemainingDestBytes) || Size.ugt(RemainingSrcBytes)) {
1853
APInt N = Size.udiv(DestElemSize);
1854
S.FFDiag(S.Current->getSource(OpPC),
1855
diag::note_constexpr_memcpy_unsupported)
1856
<< Move << WChar << (Size.ugt(RemainingSrcBytes) ? 1 : 2)
1857
<< DestElemType << toString(N, 10, /*Signed=*/false);
1858
return false;
1859
}
1860
1861
// Check for overlapping memory regions.
1862
if (!Move && Pointer::pointToSameBlock(SrcPtr, DestPtr)) {
1863
// Remove base casts.
1864
Pointer SrcP = SrcPtr;
1865
while (SrcP.isBaseClass())
1866
SrcP = SrcP.getBase();
1867
1868
Pointer DestP = DestPtr;
1869
while (DestP.isBaseClass())
1870
DestP = DestP.getBase();
1871
1872
unsigned SrcIndex = SrcP.expand().getIndex() * SrcP.elemSize();
1873
unsigned DstIndex = DestP.expand().getIndex() * DestP.elemSize();
1874
unsigned N = Size.getZExtValue();
1875
1876
if ((SrcIndex <= DstIndex && (SrcIndex + N) > DstIndex) ||
1877
(DstIndex <= SrcIndex && (DstIndex + N) > SrcIndex)) {
1878
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_memcpy_overlap)
1879
<< /*IsWChar=*/false;
1880
return false;
1881
}
1882
}
1883
1884
assert(Size.getZExtValue() % DestElemSize == 0);
1885
if (!DoMemcpy(S, OpPC, SrcPtr, DestPtr, Bytes(Size.getZExtValue()).toBits()))
1886
return false;
1887
1888
S.Stk.push<Pointer>(DestPtr);
1889
return true;
1890
}
1891
1892
/// Determine if T is a character type for which we guarantee that
1893
/// sizeof(T) == 1.
1894
static bool isOneByteCharacterType(QualType T) {
1895
return T->isCharType() || T->isChar8Type();
1896
}
1897
1898
static bool interp__builtin_memcmp(InterpState &S, CodePtr OpPC,
1899
const InterpFrame *Frame,
1900
const CallExpr *Call, unsigned ID) {
1901
assert(Call->getNumArgs() == 3);
1902
PrimType SizeT = *S.getContext().classify(Call->getArg(2));
1903
const APSInt &Size = popToAPSInt(S.Stk, SizeT);
1904
const Pointer &PtrB = S.Stk.pop<Pointer>();
1905
const Pointer &PtrA = S.Stk.pop<Pointer>();
1906
1907
if (ID == Builtin::BImemcmp || ID == Builtin::BIbcmp ||
1908
ID == Builtin::BIwmemcmp)
1909
diagnoseNonConstexprBuiltin(S, OpPC, ID);
1910
1911
if (Size.isZero()) {
1912
pushInteger(S, 0, Call->getType());
1913
return true;
1914
}
1915
1916
bool IsWide =
1917
(ID == Builtin::BIwmemcmp || ID == Builtin::BI__builtin_wmemcmp);
1918
1919
const ASTContext &ASTCtx = S.getASTContext();
1920
QualType ElemTypeA = getElemType(PtrA);
1921
QualType ElemTypeB = getElemType(PtrB);
1922
// FIXME: This is an arbitrary limitation the current constant interpreter
1923
// had. We could remove this.
1924
if (!IsWide && (!isOneByteCharacterType(ElemTypeA) ||
1925
!isOneByteCharacterType(ElemTypeB))) {
1926
S.FFDiag(S.Current->getSource(OpPC),
1927
diag::note_constexpr_memcmp_unsupported)
1928
<< ASTCtx.BuiltinInfo.getQuotedName(ID) << PtrA.getType()
1929
<< PtrB.getType();
1930
return false;
1931
}
1932
1933
if (PtrA.isDummy() || PtrB.isDummy())
1934
return false;
1935
1936
// Now, read both pointers to a buffer and compare those.
1937
BitcastBuffer BufferA(
1938
Bits(ASTCtx.getTypeSize(ElemTypeA) * PtrA.getNumElems()));
1939
readPointerToBuffer(S.getContext(), PtrA, BufferA, false);
1940
// FIXME: The swapping here is UNDOING something we do when reading the
1941
// data into the buffer.
1942
if (ASTCtx.getTargetInfo().isBigEndian())
1943
swapBytes(BufferA.Data.get(), BufferA.byteSize().getQuantity());
1944
1945
BitcastBuffer BufferB(
1946
Bits(ASTCtx.getTypeSize(ElemTypeB) * PtrB.getNumElems()));
1947
readPointerToBuffer(S.getContext(), PtrB, BufferB, false);
1948
// FIXME: The swapping here is UNDOING something we do when reading the
1949
// data into the buffer.
1950
if (ASTCtx.getTargetInfo().isBigEndian())
1951
swapBytes(BufferB.Data.get(), BufferB.byteSize().getQuantity());
1952
1953
size_t MinBufferSize = std::min(BufferA.byteSize().getQuantity(),
1954
BufferB.byteSize().getQuantity());
1955
1956
unsigned ElemSize = 1;
1957
if (IsWide)
1958
ElemSize = ASTCtx.getTypeSizeInChars(ASTCtx.getWCharType()).getQuantity();
1959
// The Size given for the wide variants is in wide-char units. Convert it
1960
// to bytes.
1961
size_t ByteSize = Size.getZExtValue() * ElemSize;
1962
size_t CmpSize = std::min(MinBufferSize, ByteSize);
1963
1964
for (size_t I = 0; I != CmpSize; I += ElemSize) {
1965
if (IsWide) {
1966
INT_TYPE_SWITCH(*S.getContext().classify(ASTCtx.getWCharType()), {
1967
T A = *reinterpret_cast<T *>(BufferA.Data.get() + I);
1968
T B = *reinterpret_cast<T *>(BufferB.Data.get() + I);
1969
if (A < B) {
1970
pushInteger(S, -1, Call->getType());
1971
return true;
1972
} else if (A > B) {
1973
pushInteger(S, 1, Call->getType());
1974
return true;
1975
}
1976
});
1977
} else {
1978
std::byte A = BufferA.Data[I];
1979
std::byte B = BufferB.Data[I];
1980
1981
if (A < B) {
1982
pushInteger(S, -1, Call->getType());
1983
return true;
1984
} else if (A > B) {
1985
pushInteger(S, 1, Call->getType());
1986
return true;
1987
}
1988
}
1989
}
1990
1991
// We compared CmpSize bytes above. If the limiting factor was the Size
1992
// passed, we're done and the result is equality (0).
1993
if (ByteSize <= CmpSize) {
1994
pushInteger(S, 0, Call->getType());
1995
return true;
1996
}
1997
1998
// However, if we read all the available bytes but were instructed to read
1999
// even more, diagnose this as a "read of dereferenced one-past-the-end
2000
// pointer". This is what would happen if we called CheckLoad() on every array
2001
// element.
2002
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_past_end)
2003
<< AK_Read << S.Current->getRange(OpPC);
2004
return false;
2005
}
2006
2007
// __builtin_memchr(ptr, int, int)
2008
// __builtin_strchr(ptr, int)
2009
static bool interp__builtin_memchr(InterpState &S, CodePtr OpPC,
2010
const CallExpr *Call, unsigned ID) {
2011
if (ID == Builtin::BImemchr || ID == Builtin::BIwcschr ||
2012
ID == Builtin::BIstrchr || ID == Builtin::BIwmemchr)
2013
diagnoseNonConstexprBuiltin(S, OpPC, ID);
2014
2015
std::optional<APSInt> MaxLength;
2016
PrimType DesiredT = *S.getContext().classify(Call->getArg(1));
2017
if (Call->getNumArgs() == 3) {
2018
PrimType MaxT = *S.getContext().classify(Call->getArg(2));
2019
MaxLength = popToAPSInt(S.Stk, MaxT);
2020
}
2021
APSInt Desired = popToAPSInt(S.Stk, DesiredT);
2022
const Pointer &Ptr = S.Stk.pop<Pointer>();
2023
2024
if (MaxLength && MaxLength->isZero()) {
2025
S.Stk.push<Pointer>();
2026
return true;
2027
}
2028
2029
if (Ptr.isDummy())
2030
return false;
2031
2032
// Null is only okay if the given size is 0.
2033
if (Ptr.isZero()) {
2034
S.FFDiag(S.Current->getSource(OpPC), diag::note_constexpr_access_null)
2035
<< AK_Read;
2036
return false;
2037
}
2038
2039
QualType ElemTy = Ptr.getFieldDesc()->isArray()
2040
? Ptr.getFieldDesc()->getElemQualType()
2041
: Ptr.getFieldDesc()->getType();
2042
bool IsRawByte = ID == Builtin::BImemchr || ID == Builtin::BI__builtin_memchr;
2043
2044
// Give up on byte-oriented matching against multibyte elements.
2045
if (IsRawByte && !isOneByteCharacterType(ElemTy)) {
2046
S.FFDiag(S.Current->getSource(OpPC),
2047
diag::note_constexpr_memchr_unsupported)
2048
<< S.getASTContext().BuiltinInfo.getQuotedName(ID) << ElemTy;
2049
return false;
2050
}
2051
2052
if (ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr) {
2053
// strchr compares directly to the passed integer, and therefore
2054
// always fails if given an int that is not a char.
2055
if (Desired !=
2056
Desired.trunc(S.getASTContext().getCharWidth()).getSExtValue()) {
2057
S.Stk.push<Pointer>();
2058
return true;
2059
}
2060
}
2061
2062
uint64_t DesiredVal;
2063
if (ID == Builtin::BIwmemchr || ID == Builtin::BI__builtin_wmemchr ||
2064
ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr) {
2065
// wcschr and wmemchr are given a wchar_t to look for. Just use it.
2066
DesiredVal = Desired.getZExtValue();
2067
} else {
2068
DesiredVal = Desired.trunc(S.getASTContext().getCharWidth()).getZExtValue();
2069
}
2070
2071
bool StopAtZero =
2072
(ID == Builtin::BIstrchr || ID == Builtin::BI__builtin_strchr ||
2073
ID == Builtin::BIwcschr || ID == Builtin::BI__builtin_wcschr);
2074
2075
PrimType ElemT =
2076
IsRawByte ? PT_Sint8 : *S.getContext().classify(getElemType(Ptr));
2077
2078
size_t Index = Ptr.getIndex();
2079
size_t Step = 0;
2080
for (;;) {
2081
const Pointer &ElemPtr =
2082
(Index + Step) > 0 ? Ptr.atIndex(Index + Step) : Ptr;
2083
2084
if (!CheckLoad(S, OpPC, ElemPtr))
2085
return false;
2086
2087
uint64_t V;
2088
INT_TYPE_SWITCH_NO_BOOL(
2089
ElemT, { V = static_cast<uint64_t>(ElemPtr.deref<T>().toUnsigned()); });
2090
2091
if (V == DesiredVal) {
2092
S.Stk.push<Pointer>(ElemPtr);
2093
return true;
2094
}
2095
2096
if (StopAtZero && V == 0)
2097
break;
2098
2099
++Step;
2100
if (MaxLength && Step == MaxLength->getZExtValue())
2101
break;
2102
}
2103
2104
S.Stk.push<Pointer>();
2105
return true;
2106
}
2107
2108
static unsigned computeFullDescSize(const ASTContext &ASTCtx,
2109
const Descriptor *Desc) {
2110
2111
if (Desc->isPrimitive())
2112
return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();
2113
2114
if (Desc->isArray())
2115
return ASTCtx.getTypeSizeInChars(Desc->getElemQualType()).getQuantity() *
2116
Desc->getNumElems();
2117
2118
if (Desc->isRecord())
2119
return ASTCtx.getTypeSizeInChars(Desc->getType()).getQuantity();
2120
2121
llvm_unreachable("Unhandled descriptor type");
2122
return 0;
2123
}
2124
2125
static unsigned computePointerOffset(const ASTContext &ASTCtx,
2126
const Pointer &Ptr) {
2127
unsigned Result = 0;
2128
2129
Pointer P = Ptr;
2130
while (P.isArrayElement() || P.isField()) {
2131
P = P.expand();
2132
const Descriptor *D = P.getFieldDesc();
2133
2134
if (P.isArrayElement()) {
2135
unsigned ElemSize =
2136
ASTCtx.getTypeSizeInChars(D->getElemQualType()).getQuantity();
2137
if (P.isOnePastEnd())
2138
Result += ElemSize * P.getNumElems();
2139
else
2140
Result += ElemSize * P.getIndex();
2141
P = P.expand().getArray();
2142
} else if (P.isBaseClass()) {
2143
2144
const auto *RD = cast<CXXRecordDecl>(D->asDecl());
2145
bool IsVirtual = Ptr.isVirtualBaseClass();
2146
P = P.getBase();
2147
const Record *BaseRecord = P.getRecord();
2148
2149
const ASTRecordLayout &Layout =
2150
ASTCtx.getASTRecordLayout(cast<CXXRecordDecl>(BaseRecord->getDecl()));
2151
if (IsVirtual)
2152
Result += Layout.getVBaseClassOffset(RD).getQuantity();
2153
else
2154
Result += Layout.getBaseClassOffset(RD).getQuantity();
2155
} else if (P.isField()) {
2156
const FieldDecl *FD = P.getField();
2157
const ASTRecordLayout &Layout =
2158
ASTCtx.getASTRecordLayout(FD->getParent());
2159
unsigned FieldIndex = FD->getFieldIndex();
2160
uint64_t FieldOffset =
2161
ASTCtx.toCharUnitsFromBits(Layout.getFieldOffset(FieldIndex))
2162
.getQuantity();
2163
Result += FieldOffset;
2164
P = P.getBase();
2165
} else
2166
llvm_unreachable("Unhandled descriptor type");
2167
}
2168
2169
return Result;
2170
}
2171
2172
static bool interp__builtin_object_size(InterpState &S, CodePtr OpPC,
2173
const InterpFrame *Frame,
2174
const CallExpr *Call) {
2175
PrimType KindT = *S.getContext().classify(Call->getArg(1));
2176
[[maybe_unused]] unsigned Kind = popToAPSInt(S.Stk, KindT).getZExtValue();
2177
2178
assert(Kind <= 3 && "unexpected kind");
2179
2180
const Pointer &Ptr = S.Stk.pop<Pointer>();
2181
2182
if (Ptr.isZero())
2183
return false;
2184
2185
const Descriptor *DeclDesc = Ptr.getDeclDesc();
2186
if (!DeclDesc)
2187
return false;
2188
2189
const ASTContext &ASTCtx = S.getASTContext();
2190
2191
unsigned ByteOffset = computePointerOffset(ASTCtx, Ptr);
2192
unsigned FullSize = computeFullDescSize(ASTCtx, DeclDesc);
2193
2194
pushInteger(S, FullSize - ByteOffset, Call->getType());
2195
2196
return true;
2197
}
2198
2199
static bool interp__builtin_is_within_lifetime(InterpState &S, CodePtr OpPC,
2200
const CallExpr *Call) {
2201
2202
if (!S.inConstantContext())
2203
return false;
2204
2205
const Pointer &Ptr = S.Stk.pop<Pointer>();
2206
2207
auto Error = [&](int Diag) {
2208
bool CalledFromStd = false;
2209
const auto *Callee = S.Current->getCallee();
2210
if (Callee && Callee->isInStdNamespace()) {
2211
const IdentifierInfo *Identifier = Callee->getIdentifier();
2212
CalledFromStd = Identifier && Identifier->isStr("is_within_lifetime");
2213
}
2214
S.CCEDiag(CalledFromStd
2215
? S.Current->Caller->getSource(S.Current->getRetPC())
2216
: S.Current->getSource(OpPC),
2217
diag::err_invalid_is_within_lifetime)
2218
<< (CalledFromStd ? "std::is_within_lifetime"
2219
: "__builtin_is_within_lifetime")
2220
<< Diag;
2221
return false;
2222
};
2223
2224
if (Ptr.isZero())
2225
return Error(0);
2226
if (Ptr.isOnePastEnd())
2227
return Error(1);
2228
2229
bool Result = Ptr.getLifetime() != Lifetime::Ended;
2230
if (!Ptr.isActive()) {
2231
Result = false;
2232
} else {
2233
if (!CheckLive(S, OpPC, Ptr, AK_Read))
2234
return false;
2235
if (!CheckMutable(S, OpPC, Ptr))
2236
return false;
2237
if (!CheckDummy(S, OpPC, Ptr, AK_Read))
2238
return false;
2239
}
2240
2241
// Check if we're currently running an initializer.
2242
for (InterpFrame *Frame = S.Current; Frame; Frame = Frame->Caller) {
2243
if (const Function *F = Frame->getFunction();
2244
F && F->isConstructor() && Frame->getThis().block() == Ptr.block()) {
2245
return Error(2);
2246
}
2247
}
2248
if (S.EvaluatingDecl && Ptr.getDeclDesc()->asVarDecl() == S.EvaluatingDecl)
2249
return Error(2);
2250
2251
pushInteger(S, Result, Call->getType());
2252
return true;
2253
}
2254
2255
static bool interp__builtin_elementwise_sat(InterpState &S, CodePtr OpPC,
2256
const CallExpr *Call,
2257
unsigned BuiltinID) {
2258
Call->dumpColor();
2259
assert(Call->getNumArgs() == 2);
2260
2261
// Single integer case.
2262
if (!Call->getArg(0)->getType()->isVectorType()) {
2263
assert(!Call->getArg(1)->getType()->isVectorType());
2264
APSInt RHS = popToAPSInt(
2265
S.Stk, *S.getContext().classify(Call->getArg(1)->getType()));
2266
APSInt LHS = popToAPSInt(
2267
S.Stk, *S.getContext().classify(Call->getArg(0)->getType()));
2268
APInt Result;
2269
if (BuiltinID == Builtin::BI__builtin_elementwise_add_sat) {
2270
Result = LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS);
2271
} else if (BuiltinID == Builtin::BI__builtin_elementwise_sub_sat) {
2272
Result = LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS);
2273
} else {
2274
llvm_unreachable("Wrong builtin ID");
2275
}
2276
2277
pushInteger(S, APSInt(Result, !LHS.isSigned()), Call->getType());
2278
return true;
2279
}
2280
2281
// Vector case.
2282
assert(Call->getArg(0)->getType()->isVectorType() &&
2283
Call->getArg(1)->getType()->isVectorType());
2284
const auto *VT = Call->getArg(0)->getType()->castAs<VectorType>();
2285
assert(VT->getElementType() ==
2286
Call->getArg(1)->getType()->castAs<VectorType>()->getElementType());
2287
assert(VT->getNumElements() ==
2288
Call->getArg(1)->getType()->castAs<VectorType>()->getNumElements());
2289
assert(VT->getElementType()->isIntegralOrEnumerationType());
2290
2291
const Pointer &RHS = S.Stk.pop<Pointer>();
2292
const Pointer &LHS = S.Stk.pop<Pointer>();
2293
const Pointer &Dst = S.Stk.peek<Pointer>();
2294
PrimType ElemT = *S.getContext().classify(VT->getElementType());
2295
unsigned NumElems = VT->getNumElements();
2296
for (unsigned I = 0; I != NumElems; ++I) {
2297
APSInt Elem1;
2298
APSInt Elem2;
2299
INT_TYPE_SWITCH_NO_BOOL(ElemT, {
2300
Elem1 = LHS.atIndex(I).deref<T>().toAPSInt();
2301
Elem2 = RHS.atIndex(I).deref<T>().toAPSInt();
2302
});
2303
2304
APSInt Result;
2305
if (BuiltinID == Builtin::BI__builtin_elementwise_add_sat) {
2306
Result = APSInt(Elem1.isSigned() ? Elem1.sadd_sat(Elem2)
2307
: Elem1.uadd_sat(Elem2),
2308
Call->getType()->isUnsignedIntegerOrEnumerationType());
2309
} else if (BuiltinID == Builtin::BI__builtin_elementwise_sub_sat) {
2310
Result = APSInt(Elem1.isSigned() ? Elem1.ssub_sat(Elem2)
2311
: Elem1.usub_sat(Elem2),
2312
Call->getType()->isUnsignedIntegerOrEnumerationType());
2313
} else {
2314
llvm_unreachable("Wrong builtin ID");
2315
}
2316
2317
INT_TYPE_SWITCH_NO_BOOL(ElemT, {
2318
const Pointer &E = Dst.atIndex(I);
2319
E.deref<T>() = static_cast<T>(Result);
2320
E.initialize();
2321
});
2322
}
2323
2324
return true;
2325
}
2326
2327
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const CallExpr *Call,
2328
uint32_t BuiltinID) {
2329
if (!S.getASTContext().BuiltinInfo.isConstantEvaluated(BuiltinID))
2330
return Invalid(S, OpPC);
2331
2332
const InterpFrame *Frame = S.Current;
2333
switch (BuiltinID) {
2334
case Builtin::BI__builtin_is_constant_evaluated:
2335
return interp__builtin_is_constant_evaluated(S, OpPC, Frame, Call);
2336
2337
case Builtin::BI__builtin_assume:
2338
case Builtin::BI__assume:
2339
return interp__builtin_assume(S, OpPC, Frame, Call);
2340
2341
case Builtin::BI__builtin_strcmp:
2342
case Builtin::BIstrcmp:
2343
case Builtin::BI__builtin_strncmp:
2344
case Builtin::BIstrncmp:
2345
case Builtin::BI__builtin_wcsncmp:
2346
case Builtin::BIwcsncmp:
2347
case Builtin::BI__builtin_wcscmp:
2348
case Builtin::BIwcscmp:
2349
return interp__builtin_strcmp(S, OpPC, Frame, Call, BuiltinID);
2350
2351
case Builtin::BI__builtin_strlen:
2352
case Builtin::BIstrlen:
2353
case Builtin::BI__builtin_wcslen:
2354
case Builtin::BIwcslen:
2355
return interp__builtin_strlen(S, OpPC, Frame, Call, BuiltinID);
2356
2357
case Builtin::BI__builtin_nan:
2358
case Builtin::BI__builtin_nanf:
2359
case Builtin::BI__builtin_nanl:
2360
case Builtin::BI__builtin_nanf16:
2361
case Builtin::BI__builtin_nanf128:
2362
return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/false);
2363
2364
case Builtin::BI__builtin_nans:
2365
case Builtin::BI__builtin_nansf:
2366
case Builtin::BI__builtin_nansl:
2367
case Builtin::BI__builtin_nansf16:
2368
case Builtin::BI__builtin_nansf128:
2369
return interp__builtin_nan(S, OpPC, Frame, Call, /*Signaling=*/true);
2370
2371
case Builtin::BI__builtin_huge_val:
2372
case Builtin::BI__builtin_huge_valf:
2373
case Builtin::BI__builtin_huge_vall:
2374
case Builtin::BI__builtin_huge_valf16:
2375
case Builtin::BI__builtin_huge_valf128:
2376
case Builtin::BI__builtin_inf:
2377
case Builtin::BI__builtin_inff:
2378
case Builtin::BI__builtin_infl:
2379
case Builtin::BI__builtin_inff16:
2380
case Builtin::BI__builtin_inff128:
2381
return interp__builtin_inf(S, OpPC, Frame, Call);
2382
2383
case Builtin::BI__builtin_copysign:
2384
case Builtin::BI__builtin_copysignf:
2385
case Builtin::BI__builtin_copysignl:
2386
case Builtin::BI__builtin_copysignf128:
2387
return interp__builtin_copysign(S, OpPC, Frame);
2388
2389
case Builtin::BI__builtin_fmin:
2390
case Builtin::BI__builtin_fminf:
2391
case Builtin::BI__builtin_fminl:
2392
case Builtin::BI__builtin_fminf16:
2393
case Builtin::BI__builtin_fminf128:
2394
return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/false);
2395
2396
case Builtin::BI__builtin_fminimum_num:
2397
case Builtin::BI__builtin_fminimum_numf:
2398
case Builtin::BI__builtin_fminimum_numl:
2399
case Builtin::BI__builtin_fminimum_numf16:
2400
case Builtin::BI__builtin_fminimum_numf128:
2401
return interp__builtin_fmin(S, OpPC, Frame, /*IsNumBuiltin=*/true);
2402
2403
case Builtin::BI__builtin_fmax:
2404
case Builtin::BI__builtin_fmaxf:
2405
case Builtin::BI__builtin_fmaxl:
2406
case Builtin::BI__builtin_fmaxf16:
2407
case Builtin::BI__builtin_fmaxf128:
2408
return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/false);
2409
2410
case Builtin::BI__builtin_fmaximum_num:
2411
case Builtin::BI__builtin_fmaximum_numf:
2412
case Builtin::BI__builtin_fmaximum_numl:
2413
case Builtin::BI__builtin_fmaximum_numf16:
2414
case Builtin::BI__builtin_fmaximum_numf128:
2415
return interp__builtin_fmax(S, OpPC, Frame, /*IsNumBuiltin=*/true);
2416
2417
case Builtin::BI__builtin_isnan:
2418
return interp__builtin_isnan(S, OpPC, Frame, Call);
2419
2420
case Builtin::BI__builtin_issignaling:
2421
return interp__builtin_issignaling(S, OpPC, Frame, Call);
2422
2423
case Builtin::BI__builtin_isinf:
2424
return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/false, Call);
2425
2426
case Builtin::BI__builtin_isinf_sign:
2427
return interp__builtin_isinf(S, OpPC, Frame, /*Sign=*/true, Call);
2428
2429
case Builtin::BI__builtin_isfinite:
2430
return interp__builtin_isfinite(S, OpPC, Frame, Call);
2431
2432
case Builtin::BI__builtin_isnormal:
2433
return interp__builtin_isnormal(S, OpPC, Frame, Call);
2434
2435
case Builtin::BI__builtin_issubnormal:
2436
return interp__builtin_issubnormal(S, OpPC, Frame, Call);
2437
2438
case Builtin::BI__builtin_iszero:
2439
return interp__builtin_iszero(S, OpPC, Frame, Call);
2440
2441
case Builtin::BI__builtin_signbit:
2442
case Builtin::BI__builtin_signbitf:
2443
case Builtin::BI__builtin_signbitl:
2444
return interp__builtin_signbit(S, OpPC, Frame, Call);
2445
2446
case Builtin::BI__builtin_isgreater:
2447
case Builtin::BI__builtin_isgreaterequal:
2448
case Builtin::BI__builtin_isless:
2449
case Builtin::BI__builtin_islessequal:
2450
case Builtin::BI__builtin_islessgreater:
2451
case Builtin::BI__builtin_isunordered:
2452
return interp_floating_comparison(S, OpPC, Call, BuiltinID);
2453
2454
case Builtin::BI__builtin_isfpclass:
2455
return interp__builtin_isfpclass(S, OpPC, Frame, Call);
2456
2457
case Builtin::BI__builtin_fpclassify:
2458
return interp__builtin_fpclassify(S, OpPC, Frame, Call);
2459
2460
case Builtin::BI__builtin_fabs:
2461
case Builtin::BI__builtin_fabsf:
2462
case Builtin::BI__builtin_fabsl:
2463
case Builtin::BI__builtin_fabsf128:
2464
return interp__builtin_fabs(S, OpPC, Frame);
2465
2466
case Builtin::BI__builtin_abs:
2467
case Builtin::BI__builtin_labs:
2468
case Builtin::BI__builtin_llabs:
2469
return interp__builtin_abs(S, OpPC, Frame, Call);
2470
2471
case Builtin::BI__builtin_popcount:
2472
case Builtin::BI__builtin_popcountl:
2473
case Builtin::BI__builtin_popcountll:
2474
case Builtin::BI__builtin_popcountg:
2475
case Builtin::BI__popcnt16: // Microsoft variants of popcount
2476
case Builtin::BI__popcnt:
2477
case Builtin::BI__popcnt64:
2478
return interp__builtin_popcount(S, OpPC, Frame, Call);
2479
2480
case Builtin::BI__builtin_parity:
2481
case Builtin::BI__builtin_parityl:
2482
case Builtin::BI__builtin_parityll:
2483
return interp__builtin_parity(S, OpPC, Frame, Call);
2484
2485
case Builtin::BI__builtin_clrsb:
2486
case Builtin::BI__builtin_clrsbl:
2487
case Builtin::BI__builtin_clrsbll:
2488
return interp__builtin_clrsb(S, OpPC, Frame, Call);
2489
2490
case Builtin::BI__builtin_bitreverse8:
2491
case Builtin::BI__builtin_bitreverse16:
2492
case Builtin::BI__builtin_bitreverse32:
2493
case Builtin::BI__builtin_bitreverse64:
2494
return interp__builtin_bitreverse(S, OpPC, Frame, Call);
2495
2496
case Builtin::BI__builtin_classify_type:
2497
return interp__builtin_classify_type(S, OpPC, Frame, Call);
2498
2499
case Builtin::BI__builtin_expect:
2500
case Builtin::BI__builtin_expect_with_probability:
2501
return interp__builtin_expect(S, OpPC, Frame, Call);
2502
2503
case Builtin::BI__builtin_rotateleft8:
2504
case Builtin::BI__builtin_rotateleft16:
2505
case Builtin::BI__builtin_rotateleft32:
2506
case Builtin::BI__builtin_rotateleft64:
2507
case Builtin::BI_rotl8: // Microsoft variants of rotate left
2508
case Builtin::BI_rotl16:
2509
case Builtin::BI_rotl:
2510
case Builtin::BI_lrotl:
2511
case Builtin::BI_rotl64:
2512
return interp__builtin_rotate(S, OpPC, Frame, Call, /*Right=*/false);
2513
2514
case Builtin::BI__builtin_rotateright8:
2515
case Builtin::BI__builtin_rotateright16:
2516
case Builtin::BI__builtin_rotateright32:
2517
case Builtin::BI__builtin_rotateright64:
2518
case Builtin::BI_rotr8: // Microsoft variants of rotate right
2519
case Builtin::BI_rotr16:
2520
case Builtin::BI_rotr:
2521
case Builtin::BI_lrotr:
2522
case Builtin::BI_rotr64:
2523
return interp__builtin_rotate(S, OpPC, Frame, Call, /*Right=*/true);
2524
2525
case Builtin::BI__builtin_ffs:
2526
case Builtin::BI__builtin_ffsl:
2527
case Builtin::BI__builtin_ffsll:
2528
return interp__builtin_ffs(S, OpPC, Frame, Call);
2529
2530
case Builtin::BIaddressof:
2531
case Builtin::BI__addressof:
2532
case Builtin::BI__builtin_addressof:
2533
assert(isNoopBuiltin(BuiltinID));
2534
return interp__builtin_addressof(S, OpPC, Frame, Call);
2535
2536
case Builtin::BIas_const:
2537
case Builtin::BIforward:
2538
case Builtin::BIforward_like:
2539
case Builtin::BImove:
2540
case Builtin::BImove_if_noexcept:
2541
assert(isNoopBuiltin(BuiltinID));
2542
return interp__builtin_move(S, OpPC, Frame, Call);
2543
2544
case Builtin::BI__builtin_eh_return_data_regno:
2545
return interp__builtin_eh_return_data_regno(S, OpPC, Frame, Call);
2546
2547
case Builtin::BI__builtin_launder:
2548
assert(isNoopBuiltin(BuiltinID));
2549
return true;
2550
2551
case Builtin::BI__builtin_add_overflow:
2552
case Builtin::BI__builtin_sub_overflow:
2553
case Builtin::BI__builtin_mul_overflow:
2554
case Builtin::BI__builtin_sadd_overflow:
2555
case Builtin::BI__builtin_uadd_overflow:
2556
case Builtin::BI__builtin_uaddl_overflow:
2557
case Builtin::BI__builtin_uaddll_overflow:
2558
case Builtin::BI__builtin_usub_overflow:
2559
case Builtin::BI__builtin_usubl_overflow:
2560
case Builtin::BI__builtin_usubll_overflow:
2561
case Builtin::BI__builtin_umul_overflow:
2562
case Builtin::BI__builtin_umull_overflow:
2563
case Builtin::BI__builtin_umulll_overflow:
2564
case Builtin::BI__builtin_saddl_overflow:
2565
case Builtin::BI__builtin_saddll_overflow:
2566
case Builtin::BI__builtin_ssub_overflow:
2567
case Builtin::BI__builtin_ssubl_overflow:
2568
case Builtin::BI__builtin_ssubll_overflow:
2569
case Builtin::BI__builtin_smul_overflow:
2570
case Builtin::BI__builtin_smull_overflow:
2571
case Builtin::BI__builtin_smulll_overflow:
2572
return interp__builtin_overflowop(S, OpPC, Call, BuiltinID);
2573
2574
case Builtin::BI__builtin_addcb:
2575
case Builtin::BI__builtin_addcs:
2576
case Builtin::BI__builtin_addc:
2577
case Builtin::BI__builtin_addcl:
2578
case Builtin::BI__builtin_addcll:
2579
case Builtin::BI__builtin_subcb:
2580
case Builtin::BI__builtin_subcs:
2581
case Builtin::BI__builtin_subc:
2582
case Builtin::BI__builtin_subcl:
2583
case Builtin::BI__builtin_subcll:
2584
return interp__builtin_carryop(S, OpPC, Frame, Call, BuiltinID);
2585
2586
case Builtin::BI__builtin_clz:
2587
case Builtin::BI__builtin_clzl:
2588
case Builtin::BI__builtin_clzll:
2589
case Builtin::BI__builtin_clzs:
2590
case Builtin::BI__builtin_clzg:
2591
case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
2592
case Builtin::BI__lzcnt:
2593
case Builtin::BI__lzcnt64:
2594
return interp__builtin_clz(S, OpPC, Frame, Call, BuiltinID);
2595
2596
case Builtin::BI__builtin_ctz:
2597
case Builtin::BI__builtin_ctzl:
2598
case Builtin::BI__builtin_ctzll:
2599
case Builtin::BI__builtin_ctzs:
2600
case Builtin::BI__builtin_ctzg:
2601
return interp__builtin_ctz(S, OpPC, Frame, Call, BuiltinID);
2602
2603
case Builtin::BI__builtin_bswap16:
2604
case Builtin::BI__builtin_bswap32:
2605
case Builtin::BI__builtin_bswap64:
2606
return interp__builtin_bswap(S, OpPC, Frame, Call);
2607
2608
case Builtin::BI__atomic_always_lock_free:
2609
case Builtin::BI__atomic_is_lock_free:
2610
return interp__builtin_atomic_lock_free(S, OpPC, Frame, Call, BuiltinID);
2611
2612
case Builtin::BI__c11_atomic_is_lock_free:
2613
return interp__builtin_c11_atomic_is_lock_free(S, OpPC, Frame, Call);
2614
2615
case Builtin::BI__builtin_complex:
2616
return interp__builtin_complex(S, OpPC, Frame, Call);
2617
2618
case Builtin::BI__builtin_is_aligned:
2619
case Builtin::BI__builtin_align_up:
2620
case Builtin::BI__builtin_align_down:
2621
return interp__builtin_is_aligned_up_down(S, OpPC, Frame, Call, BuiltinID);
2622
2623
case Builtin::BI__builtin_assume_aligned:
2624
return interp__builtin_assume_aligned(S, OpPC, Frame, Call);
2625
2626
case clang::X86::BI__builtin_ia32_bextr_u32:
2627
case clang::X86::BI__builtin_ia32_bextr_u64:
2628
case clang::X86::BI__builtin_ia32_bextri_u32:
2629
case clang::X86::BI__builtin_ia32_bextri_u64:
2630
return interp__builtin_ia32_bextr(S, OpPC, Frame, Call);
2631
2632
case clang::X86::BI__builtin_ia32_bzhi_si:
2633
case clang::X86::BI__builtin_ia32_bzhi_di:
2634
return interp__builtin_ia32_bzhi(S, OpPC, Frame, Call);
2635
2636
case clang::X86::BI__builtin_ia32_lzcnt_u16:
2637
case clang::X86::BI__builtin_ia32_lzcnt_u32:
2638
case clang::X86::BI__builtin_ia32_lzcnt_u64:
2639
return interp__builtin_ia32_lzcnt(S, OpPC, Frame, Call);
2640
2641
case clang::X86::BI__builtin_ia32_tzcnt_u16:
2642
case clang::X86::BI__builtin_ia32_tzcnt_u32:
2643
case clang::X86::BI__builtin_ia32_tzcnt_u64:
2644
return interp__builtin_ia32_tzcnt(S, OpPC, Frame, Call);
2645
2646
case clang::X86::BI__builtin_ia32_pdep_si:
2647
case clang::X86::BI__builtin_ia32_pdep_di:
2648
return interp__builtin_ia32_pdep(S, OpPC, Frame, Call);
2649
2650
case clang::X86::BI__builtin_ia32_pext_si:
2651
case clang::X86::BI__builtin_ia32_pext_di:
2652
return interp__builtin_ia32_pext(S, OpPC, Frame, Call);
2653
2654
case clang::X86::BI__builtin_ia32_addcarryx_u32:
2655
case clang::X86::BI__builtin_ia32_addcarryx_u64:
2656
case clang::X86::BI__builtin_ia32_subborrow_u32:
2657
case clang::X86::BI__builtin_ia32_subborrow_u64:
2658
return interp__builtin_ia32_addcarry_subborrow(S, OpPC, Frame, Call,
2659
BuiltinID);
2660
2661
case Builtin::BI__builtin_os_log_format_buffer_size:
2662
return interp__builtin_os_log_format_buffer_size(S, OpPC, Frame, Call);
2663
2664
case Builtin::BI__builtin_ptrauth_string_discriminator:
2665
return interp__builtin_ptrauth_string_discriminator(S, OpPC, Frame, Call);
2666
2667
case Builtin::BI__noop:
2668
pushInteger(S, 0, Call->getType());
2669
return true;
2670
2671
case Builtin::BI__builtin_operator_new:
2672
return interp__builtin_operator_new(S, OpPC, Frame, Call);
2673
2674
case Builtin::BI__builtin_operator_delete:
2675
return interp__builtin_operator_delete(S, OpPC, Frame, Call);
2676
2677
case Builtin::BI__arithmetic_fence:
2678
return interp__builtin_arithmetic_fence(S, OpPC, Frame, Call);
2679
2680
case Builtin::BI__builtin_reduce_add:
2681
case Builtin::BI__builtin_reduce_mul:
2682
case Builtin::BI__builtin_reduce_and:
2683
case Builtin::BI__builtin_reduce_or:
2684
case Builtin::BI__builtin_reduce_xor:
2685
case Builtin::BI__builtin_reduce_min:
2686
case Builtin::BI__builtin_reduce_max:
2687
return interp__builtin_vector_reduce(S, OpPC, Call, BuiltinID);
2688
2689
case Builtin::BI__builtin_elementwise_popcount:
2690
case Builtin::BI__builtin_elementwise_bitreverse:
2691
return interp__builtin_elementwise_popcount(S, OpPC, Frame, Call,
2692
BuiltinID);
2693
2694
case Builtin::BI__builtin_memcpy:
2695
case Builtin::BImemcpy:
2696
case Builtin::BI__builtin_wmemcpy:
2697
case Builtin::BIwmemcpy:
2698
case Builtin::BI__builtin_memmove:
2699
case Builtin::BImemmove:
2700
case Builtin::BI__builtin_wmemmove:
2701
case Builtin::BIwmemmove:
2702
return interp__builtin_memcpy(S, OpPC, Frame, Call, BuiltinID);
2703
2704
case Builtin::BI__builtin_memcmp:
2705
case Builtin::BImemcmp:
2706
case Builtin::BI__builtin_bcmp:
2707
case Builtin::BIbcmp:
2708
case Builtin::BI__builtin_wmemcmp:
2709
case Builtin::BIwmemcmp:
2710
return interp__builtin_memcmp(S, OpPC, Frame, Call, BuiltinID);
2711
2712
case Builtin::BImemchr:
2713
case Builtin::BI__builtin_memchr:
2714
case Builtin::BIstrchr:
2715
case Builtin::BI__builtin_strchr:
2716
case Builtin::BIwmemchr:
2717
case Builtin::BI__builtin_wmemchr:
2718
case Builtin::BIwcschr:
2719
case Builtin::BI__builtin_wcschr:
2720
case Builtin::BI__builtin_char_memchr:
2721
return interp__builtin_memchr(S, OpPC, Call, BuiltinID);
2722
2723
case Builtin::BI__builtin_object_size:
2724
case Builtin::BI__builtin_dynamic_object_size:
2725
return interp__builtin_object_size(S, OpPC, Frame, Call);
2726
2727
case Builtin::BI__builtin_is_within_lifetime:
2728
return interp__builtin_is_within_lifetime(S, OpPC, Call);
2729
2730
case Builtin::BI__builtin_elementwise_add_sat:
2731
case Builtin::BI__builtin_elementwise_sub_sat:
2732
return interp__builtin_elementwise_sat(S, OpPC, Call, BuiltinID);
2733
2734
default:
2735
S.FFDiag(S.Current->getLocation(OpPC),
2736
diag::note_invalid_subexpr_in_const_expr)
2737
<< S.Current->getRange(OpPC);
2738
2739
return false;
2740
}
2741
2742
llvm_unreachable("Unhandled builtin ID");
2743
}
2744
2745
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
2746
ArrayRef<int64_t> ArrayIndices, int64_t &IntResult) {
2747
CharUnits Result;
2748
unsigned N = E->getNumComponents();
2749
assert(N > 0);
2750
2751
unsigned ArrayIndex = 0;
2752
QualType CurrentType = E->getTypeSourceInfo()->getType();
2753
for (unsigned I = 0; I != N; ++I) {
2754
const OffsetOfNode &Node = E->getComponent(I);
2755
switch (Node.getKind()) {
2756
case OffsetOfNode::Field: {
2757
const FieldDecl *MemberDecl = Node.getField();
2758
const RecordType *RT = CurrentType->getAs<RecordType>();
2759
if (!RT)
2760
return false;
2761
const RecordDecl *RD = RT->getDecl();
2762
if (RD->isInvalidDecl())
2763
return false;
2764
const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD);
2765
unsigned FieldIndex = MemberDecl->getFieldIndex();
2766
assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");
2767
Result +=
2768
S.getASTContext().toCharUnitsFromBits(RL.getFieldOffset(FieldIndex));
2769
CurrentType = MemberDecl->getType().getNonReferenceType();
2770
break;
2771
}
2772
case OffsetOfNode::Array: {
2773
// When generating bytecode, we put all the index expressions as Sint64 on
2774
// the stack.
2775
int64_t Index = ArrayIndices[ArrayIndex];
2776
const ArrayType *AT = S.getASTContext().getAsArrayType(CurrentType);
2777
if (!AT)
2778
return false;
2779
CurrentType = AT->getElementType();
2780
CharUnits ElementSize = S.getASTContext().getTypeSizeInChars(CurrentType);
2781
Result += Index * ElementSize;
2782
++ArrayIndex;
2783
break;
2784
}
2785
case OffsetOfNode::Base: {
2786
const CXXBaseSpecifier *BaseSpec = Node.getBase();
2787
if (BaseSpec->isVirtual())
2788
return false;
2789
2790
// Find the layout of the class whose base we are looking into.
2791
const RecordType *RT = CurrentType->getAs<RecordType>();
2792
if (!RT)
2793
return false;
2794
const RecordDecl *RD = RT->getDecl();
2795
if (RD->isInvalidDecl())
2796
return false;
2797
const ASTRecordLayout &RL = S.getASTContext().getASTRecordLayout(RD);
2798
2799
// Find the base class itself.
2800
CurrentType = BaseSpec->getType();
2801
const RecordType *BaseRT = CurrentType->getAs<RecordType>();
2802
if (!BaseRT)
2803
return false;
2804
2805
// Add the offset to the base.
2806
Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));
2807
break;
2808
}
2809
case OffsetOfNode::Identifier:
2810
llvm_unreachable("Dependent OffsetOfExpr?");
2811
}
2812
}
2813
2814
IntResult = Result.getQuantity();
2815
2816
return true;
2817
}
2818
2819
bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,
2820
const Pointer &Ptr, const APSInt &IntValue) {
2821
2822
const Record *R = Ptr.getRecord();
2823
assert(R);
2824
assert(R->getNumFields() == 1);
2825
2826
unsigned FieldOffset = R->getField(0u)->Offset;
2827
const Pointer &FieldPtr = Ptr.atField(FieldOffset);
2828
PrimType FieldT = *S.getContext().classify(FieldPtr.getType());
2829
2830
INT_TYPE_SWITCH(FieldT,
2831
FieldPtr.deref<T>() = T::from(IntValue.getSExtValue()));
2832
FieldPtr.initialize();
2833
return true;
2834
}
2835
2836
static void zeroAll(Pointer &Dest) {
2837
const Descriptor *Desc = Dest.getFieldDesc();
2838
2839
if (Desc->isPrimitive()) {
2840
TYPE_SWITCH(Desc->getPrimType(), {
2841
Dest.deref<T>().~T();
2842
new (&Dest.deref<T>()) T();
2843
});
2844
return;
2845
}
2846
2847
if (Desc->isRecord()) {
2848
const Record *R = Desc->ElemRecord;
2849
for (const Record::Field &F : R->fields()) {
2850
Pointer FieldPtr = Dest.atField(F.Offset);
2851
zeroAll(FieldPtr);
2852
}
2853
return;
2854
}
2855
2856
if (Desc->isPrimitiveArray()) {
2857
for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
2858
TYPE_SWITCH(Desc->getPrimType(), {
2859
Dest.deref<T>().~T();
2860
new (&Dest.deref<T>()) T();
2861
});
2862
}
2863
return;
2864
}
2865
2866
if (Desc->isCompositeArray()) {
2867
for (unsigned I = 0, N = Desc->getNumElems(); I != N; ++I) {
2868
Pointer ElemPtr = Dest.atIndex(I).narrow();
2869
zeroAll(ElemPtr);
2870
}
2871
return;
2872
}
2873
}
2874
2875
static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
2876
Pointer &Dest, bool Activate);
2877
static bool copyRecord(InterpState &S, CodePtr OpPC, const Pointer &Src,
2878
Pointer &Dest, bool Activate = false) {
2879
[[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
2880
const Descriptor *DestDesc = Dest.getFieldDesc();
2881
2882
auto copyField = [&](const Record::Field &F, bool Activate) -> bool {
2883
Pointer DestField = Dest.atField(F.Offset);
2884
if (std::optional<PrimType> FT = S.Ctx.classify(F.Decl->getType())) {
2885
TYPE_SWITCH(*FT, {
2886
DestField.deref<T>() = Src.atField(F.Offset).deref<T>();
2887
if (Src.atField(F.Offset).isInitialized())
2888
DestField.initialize();
2889
if (Activate)
2890
DestField.activate();
2891
});
2892
return true;
2893
}
2894
// Composite field.
2895
return copyComposite(S, OpPC, Src.atField(F.Offset), DestField, Activate);
2896
};
2897
2898
assert(SrcDesc->isRecord());
2899
assert(SrcDesc->ElemRecord == DestDesc->ElemRecord);
2900
const Record *R = DestDesc->ElemRecord;
2901
for (const Record::Field &F : R->fields()) {
2902
if (R->isUnion()) {
2903
// For unions, only copy the active field. Zero all others.
2904
const Pointer &SrcField = Src.atField(F.Offset);
2905
if (SrcField.isActive()) {
2906
if (!copyField(F, /*Activate=*/true))
2907
return false;
2908
} else {
2909
Pointer DestField = Dest.atField(F.Offset);
2910
zeroAll(DestField);
2911
}
2912
} else {
2913
if (!copyField(F, Activate))
2914
return false;
2915
}
2916
}
2917
2918
for (const Record::Base &B : R->bases()) {
2919
Pointer DestBase = Dest.atField(B.Offset);
2920
if (!copyRecord(S, OpPC, Src.atField(B.Offset), DestBase, Activate))
2921
return false;
2922
}
2923
2924
Dest.initialize();
2925
return true;
2926
}
2927
2928
static bool copyComposite(InterpState &S, CodePtr OpPC, const Pointer &Src,
2929
Pointer &Dest, bool Activate = false) {
2930
assert(Src.isLive() && Dest.isLive());
2931
2932
[[maybe_unused]] const Descriptor *SrcDesc = Src.getFieldDesc();
2933
const Descriptor *DestDesc = Dest.getFieldDesc();
2934
2935
assert(!DestDesc->isPrimitive() && !SrcDesc->isPrimitive());
2936
2937
if (DestDesc->isPrimitiveArray()) {
2938
assert(SrcDesc->isPrimitiveArray());
2939
assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
2940
PrimType ET = DestDesc->getPrimType();
2941
for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
2942
Pointer DestElem = Dest.atIndex(I);
2943
TYPE_SWITCH(ET, {
2944
DestElem.deref<T>() = Src.atIndex(I).deref<T>();
2945
DestElem.initialize();
2946
});
2947
}
2948
return true;
2949
}
2950
2951
if (DestDesc->isCompositeArray()) {
2952
assert(SrcDesc->isCompositeArray());
2953
assert(SrcDesc->getNumElems() == DestDesc->getNumElems());
2954
for (unsigned I = 0, N = DestDesc->getNumElems(); I != N; ++I) {
2955
const Pointer &SrcElem = Src.atIndex(I).narrow();
2956
Pointer DestElem = Dest.atIndex(I).narrow();
2957
if (!copyComposite(S, OpPC, SrcElem, DestElem, Activate))
2958
return false;
2959
}
2960
return true;
2961
}
2962
2963
if (DestDesc->isRecord())
2964
return copyRecord(S, OpPC, Src, Dest, Activate);
2965
return Invalid(S, OpPC);
2966
}
2967
2968
bool DoMemcpy(InterpState &S, CodePtr OpPC, const Pointer &Src, Pointer &Dest) {
2969
return copyComposite(S, OpPC, Src, Dest);
2970
}
2971
2972
} // namespace interp
2973
} // namespace clang
2974
2975