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