Coverage Report

Created: 2023-11-11 10:31

/Users/buildslave/jenkins/workspace/coverage/llvm-project/clang/lib/AST/Interp/InterpBuiltin.cpp
Line
Count
Source (jump to first uncovered line)
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 "Boolean.h"
9
#include "Interp.h"
10
#include "PrimType.h"
11
#include "clang/AST/RecordLayout.h"
12
#include "clang/Basic/Builtins.h"
13
#include "clang/Basic/TargetInfo.h"
14
15
namespace clang {
16
namespace interp {
17
18
template <typename T>
19
1.38k
static T getParam(const InterpFrame *Frame, unsigned Index) {
20
1.38k
  assert(Frame->getFunction()->getNumParams() > Index);
21
1.38k
  unsigned Offset = Frame->getFunction()->getParamOffset(Index);
22
1.38k
  return Frame->getParam<T>(Offset);
23
1.38k
}
InterpBuiltin.cpp:clang::interp::Pointer clang::interp::getParam<clang::interp::Pointer>(clang::interp::InterpFrame const*, unsigned int)
Line
Count
Source
19
859
static T getParam(const InterpFrame *Frame, unsigned Index) {
20
859
  assert(Frame->getFunction()->getNumParams() > Index);
21
859
  unsigned Offset = Frame->getFunction()->getParamOffset(Index);
22
859
  return Frame->getParam<T>(Offset);
23
859
}
InterpBuiltin.cpp:clang::interp::Floating clang::interp::getParam<clang::interp::Floating>(clang::interp::InterpFrame const*, unsigned int)
Line
Count
Source
19
525
static T getParam(const InterpFrame *Frame, unsigned Index) {
20
525
  assert(Frame->getFunction()->getNumParams() > Index);
21
525
  unsigned Offset = Frame->getFunction()->getParamOffset(Index);
22
525
  return Frame->getParam<T>(Offset);
23
525
}
24
25
1.28k
PrimType getIntPrimType(const InterpState &S) {
26
1.28k
  const TargetInfo &TI = S.getCtx().getTargetInfo();
27
1.28k
  unsigned IntWidth = TI.getIntWidth();
28
29
1.28k
  if (IntWidth == 32)
30
1.04k
    return PT_Sint32;
31
232
  else if (IntWidth == 16)
32
232
    return PT_Sint16;
33
0
  llvm_unreachable("Int isn't 16 or 32 bit?");
34
0
}
35
36
/// Peek an integer value from the stack into an APSInt.
37
371
static APSInt peekToAPSInt(InterpStack &Stk, PrimType T, size_t Offset = 0) {
38
371
  if (Offset == 0)
39
319
    Offset = align(primSize(T));
40
41
371
  APSInt R;
42
371
  INT_TYPE_SWITCH(T, {
43
371
    T Val = Stk.peek<T>(Offset);
44
371
    R = APSInt(
45
371
        APInt(Val.bitWidth(), static_cast<uint64_t>(Val), T::isSigned()));
46
371
  });
47
48
371
  return R;
49
371
}
50
51
/// Pushes \p Val to the stack, as a target-dependent 'int'.
52
588
static void pushInt(InterpState &S, int32_t Val) {
53
588
  PrimType IntType = getIntPrimType(S);
54
588
  if (IntType == PT_Sint32)
55
480
    S.Stk.push<Integral<32, true>>(Integral<32, true>::from(Val));
56
108
  else if (IntType == PT_Sint16)
57
108
    S.Stk.push<Integral<16, true>>(Integral<16, true>::from(Val));
58
0
  else
59
0
    llvm_unreachable("Int isn't 16 or 32 bit?");
60
588
}
61
62
588
static bool retInt(InterpState &S, CodePtr OpPC, APValue &Result) {
63
588
  PrimType IntType = getIntPrimType(S);
64
588
  if (IntType == PT_Sint32)
65
480
    return Ret<PT_Sint32>(S, OpPC, Result);
66
108
  else if (IntType == PT_Sint16)
67
108
    return Ret<PT_Sint16>(S, OpPC, Result);
68
0
  llvm_unreachable("Int isn't 16 or 32 bit?");
69
0
}
70
71
195
static void pushSizeT(InterpState &S, uint64_t Val) {
72
195
  const TargetInfo &TI = S.getCtx().getTargetInfo();
73
195
  unsigned SizeTWidth = TI.getTypeWidth(TI.getSizeType());
74
75
195
  switch (SizeTWidth) {
76
96
  case 64:
77
96
    S.Stk.push<Integral<64, false>>(Integral<64, false>::from(Val));
78
96
    break;
79
66
  case 32:
80
66
    S.Stk.push<Integral<32, false>>(Integral<32, false>::from(Val));
81
66
    break;
82
33
  case 16:
83
33
    S.Stk.push<Integral<16, false>>(Integral<16, false>::from(Val));
84
33
    break;
85
0
  default:
86
0
    llvm_unreachable("We don't handle this size_t size.");
87
195
  }
88
195
}
89
90
195
static bool retSizeT(InterpState &S, CodePtr OpPC, APValue &Result) {
91
195
  const TargetInfo &TI = S.getCtx().getTargetInfo();
92
195
  unsigned SizeTWidth = TI.getTypeWidth(TI.getSizeType());
93
94
195
  switch (SizeTWidth) {
95
96
  case 64:
96
96
    return Ret<PT_Uint64>(S, OpPC, Result);
97
66
  case 32:
98
66
    return Ret<PT_Uint32>(S, OpPC, Result);
99
33
  case 16:
100
33
    return Ret<PT_Uint16>(S, OpPC, Result);
101
195
  }
102
103
0
  llvm_unreachable("size_t isn't 64 or 32 bit?");
104
0
}
105
106
static bool interp__builtin_strcmp(InterpState &S, CodePtr OpPC,
107
185
                                   const InterpFrame *Frame) {
108
185
  const Pointer &A = getParam<Pointer>(Frame, 0);
109
185
  const Pointer &B = getParam<Pointer>(Frame, 1);
110
111
185
  if (!CheckLive(S, OpPC, A, AK_Read) || 
!CheckLive(S, OpPC, B, AK_Read)170
)
112
30
    return false;
113
114
155
  assert(A.getFieldDesc()->isPrimitiveArray());
115
155
  assert(B.getFieldDesc()->isPrimitiveArray());
116
117
155
  unsigned IndexA = A.getIndex();
118
155
  unsigned IndexB = B.getIndex();
119
155
  int32_t Result = 0;
120
1.61k
  for (;; 
++IndexA, ++IndexB1.46k
) {
121
1.61k
    const Pointer &PA = A.atIndex(IndexA);
122
1.61k
    const Pointer &PB = B.atIndex(IndexB);
123
1.61k
    if (!CheckRange(S, OpPC, PA, AK_Read) ||
124
1.61k
        
!CheckRange(S, OpPC, PB, AK_Read)1.60k
) {
125
15
      return false;
126
15
    }
127
1.60k
    uint8_t CA = PA.deref<uint8_t>();
128
1.60k
    uint8_t CB = PB.deref<uint8_t>();
129
130
1.60k
    if (CA > CB) {
131
40
      Result = 1;
132
40
      break;
133
1.56k
    } else if (CA < CB) {
134
30
      Result = -1;
135
30
      break;
136
30
    }
137
1.53k
    if (CA == 0 || 
CB == 01.46k
)
138
70
      break;
139
1.53k
  }
140
141
140
  pushInt(S, Result);
142
140
  return true;
143
155
}
144
145
static bool interp__builtin_strlen(InterpState &S, CodePtr OpPC,
146
358
                                   const InterpFrame *Frame) {
147
358
  const Pointer &StrPtr = getParam<Pointer>(Frame, 0);
148
149
358
  if (!CheckArray(S, OpPC, StrPtr))
150
0
    return false;
151
152
358
  if (!CheckLive(S, OpPC, StrPtr, AK_Read))
153
0
    return false;
154
155
358
  if (!CheckDummy(S, OpPC, StrPtr))
156
115
    return false;
157
158
243
  assert(StrPtr.getFieldDesc()->isPrimitiveArray());
159
160
243
  size_t Len = 0;
161
1.03k
  for (size_t I = StrPtr.getIndex();; 
++I, ++Len796
) {
162
1.03k
    const Pointer &ElemPtr = StrPtr.atIndex(I);
163
164
1.03k
    if (!CheckRange(S, OpPC, ElemPtr, AK_Read))
165
48
      return false;
166
167
991
    uint8_t Val = ElemPtr.deref<uint8_t>();
168
991
    if (Val == 0)
169
195
      break;
170
991
  }
171
172
195
  pushSizeT(S, Len);
173
195
  return true;
174
243
}
175
176
static bool interp__builtin_nan(InterpState &S, CodePtr OpPC,
177
                                const InterpFrame *Frame, const Function *F,
178
131
                                bool Signaling) {
179
131
  const Pointer &Arg = getParam<Pointer>(Frame, 0);
180
181
131
  if (!CheckLoad(S, OpPC, Arg))
182
0
    return false;
183
184
131
  assert(Arg.getFieldDesc()->isPrimitiveArray());
185
186
  // Convert the given string to an integer using StringRef's API.
187
131
  llvm::APInt Fill;
188
131
  std::string Str;
189
131
  assert(Arg.getNumElems() >= 1);
190
240
  
for (unsigned I = 0;; 131
++I109
) {
191
240
    const Pointer &Elem = Arg.atIndex(I);
192
193
240
    if (!CheckLoad(S, OpPC, Elem))
194
5
      return false;
195
196
235
    if (Elem.deref<int8_t>() == 0)
197
126
      break;
198
199
109
    Str += Elem.deref<char>();
200
109
  }
201
202
  // Treat empty strings as if they were zero.
203
126
  if (Str.empty())
204
107
    Fill = llvm::APInt(32, 0);
205
19
  else if (StringRef(Str).getAsInteger(0, Fill))
206
5
    return false;
207
208
121
  const llvm::fltSemantics &TargetSemantics =
209
121
      S.getCtx().getFloatTypeSemantics(F->getDecl()->getReturnType());
210
211
121
  Floating Result;
212
121
  if (S.getCtx().getTargetInfo().isNan2008()) {
213
121
    if (Signaling)
214
44
      Result = Floating(
215
44
          llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
216
77
    else
217
77
      Result = Floating(
218
77
          llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
219
121
  } else {
220
    // Prior to IEEE 754-2008, architectures were allowed to choose whether
221
    // the first bit of their significand was set for qNaN or sNaN. MIPS chose
222
    // a different encoding to what became a standard in 2008, and for pre-
223
    // 2008 revisions, MIPS interpreted sNaN-2008 as qNan and qNaN-2008 as
224
    // sNaN. This is now known as "legacy NaN" encoding.
225
0
    if (Signaling)
226
0
      Result = Floating(
227
0
          llvm::APFloat::getQNaN(TargetSemantics, /*Negative=*/false, &Fill));
228
0
    else
229
0
      Result = Floating(
230
0
          llvm::APFloat::getSNaN(TargetSemantics, /*Negative=*/false, &Fill));
231
0
  }
232
233
121
  S.Stk.push<Floating>(Result);
234
121
  return true;
235
126
}
236
237
static bool interp__builtin_inf(InterpState &S, CodePtr OpPC,
238
102
                                const InterpFrame *Frame, const Function *F) {
239
102
  const llvm::fltSemantics &TargetSemantics =
240
102
      S.getCtx().getFloatTypeSemantics(F->getDecl()->getReturnType());
241
242
102
  S.Stk.push<Floating>(Floating::getInf(TargetSemantics));
243
102
  return true;
244
102
}
245
246
static bool interp__builtin_copysign(InterpState &S, CodePtr OpPC,
247
                                     const InterpFrame *Frame,
248
32
                                     const Function *F) {
249
32
  const Floating &Arg1 = getParam<Floating>(Frame, 0);
250
32
  const Floating &Arg2 = getParam<Floating>(Frame, 1);
251
252
32
  APFloat Copy = Arg1.getAPFloat();
253
32
  Copy.copySign(Arg2.getAPFloat());
254
32
  S.Stk.push<Floating>(Floating(Copy));
255
256
32
  return true;
257
32
}
258
259
static bool interp__builtin_fmin(InterpState &S, CodePtr OpPC,
260
132
                                 const InterpFrame *Frame, const Function *F) {
261
132
  const Floating &LHS = getParam<Floating>(Frame, 0);
262
132
  const Floating &RHS = getParam<Floating>(Frame, 1);
263
264
132
  Floating Result;
265
266
  // When comparing zeroes, return -0.0 if one of the zeroes is negative.
267
132
  if (LHS.isZero() && 
RHS.isZero()32
&&
RHS.isNegative()20
)
268
10
    Result = RHS;
269
122
  else if (LHS.isNan() || 
RHS < LHS97
)
270
49
    Result = RHS;
271
73
  else
272
73
    Result = LHS;
273
274
132
  S.Stk.push<Floating>(Result);
275
132
  return true;
276
132
}
277
278
static bool interp__builtin_fmax(InterpState &S, CodePtr OpPC,
279
                                 const InterpFrame *Frame,
280
96
                                 const Function *Func) {
281
96
  const Floating &LHS = getParam<Floating>(Frame, 0);
282
96
  const Floating &RHS = getParam<Floating>(Frame, 1);
283
284
96
  Floating Result;
285
286
  // When comparing zeroes, return +0.0 if one of the zeroes is positive.
287
96
  if (LHS.isZero() && 
RHS.isZero()32
&&
LHS.isNegative()20
)
288
10
    Result = RHS;
289
86
  else if (LHS.isNan() || 
RHS > LHS70
)
290
40
    Result = RHS;
291
46
  else
292
46
    Result = LHS;
293
294
96
  S.Stk.push<Floating>(Result);
295
96
  return true;
296
96
}
297
298
/// Defined as __builtin_isnan(...), to accommodate the fact that it can
299
/// take a float, double, long double, etc.
300
/// But for us, that's all a Floating anyway.
301
static bool interp__builtin_isnan(InterpState &S, CodePtr OpPC,
302
8
                                  const InterpFrame *Frame, const Function *F) {
303
8
  const Floating &Arg = S.Stk.peek<Floating>();
304
305
8
  pushInt(S, Arg.isNan());
306
8
  return true;
307
8
}
308
309
static bool interp__builtin_issignaling(InterpState &S, CodePtr OpPC,
310
                                        const InterpFrame *Frame,
311
20
                                        const Function *F) {
312
20
  const Floating &Arg = S.Stk.peek<Floating>();
313
314
20
  pushInt(S, Arg.isSignaling());
315
20
  return true;
316
20
}
317
318
static bool interp__builtin_isinf(InterpState &S, CodePtr OpPC,
319
                                  const InterpFrame *Frame, const Function *F,
320
10
                                  bool CheckSign) {
321
10
  const Floating &Arg = S.Stk.peek<Floating>();
322
10
  bool IsInf = Arg.isInf();
323
324
10
  if (CheckSign)
325
0
    pushInt(S, IsInf ? (Arg.isNegative() ? -1 : 1) : 0);
326
10
  else
327
10
    pushInt(S, Arg.isInf());
328
10
  return true;
329
10
}
330
331
static bool interp__builtin_isfinite(InterpState &S, CodePtr OpPC,
332
                                     const InterpFrame *Frame,
333
10
                                     const Function *F) {
334
10
  const Floating &Arg = S.Stk.peek<Floating>();
335
336
10
  pushInt(S, Arg.isFinite());
337
10
  return true;
338
10
}
339
340
static bool interp__builtin_isnormal(InterpState &S, CodePtr OpPC,
341
                                     const InterpFrame *Frame,
342
10
                                     const Function *F) {
343
10
  const Floating &Arg = S.Stk.peek<Floating>();
344
345
10
  pushInt(S, Arg.isNormal());
346
10
  return true;
347
10
}
348
349
static bool interp__builtin_issubnormal(InterpState &S, CodePtr OpPC,
350
                                        const InterpFrame *Frame,
351
9
                                        const Function *F) {
352
9
  const Floating &Arg = S.Stk.peek<Floating>();
353
354
9
  pushInt(S, Arg.isDenormal());
355
9
  return true;
356
9
}
357
358
static bool interp__builtin_iszero(InterpState &S, CodePtr OpPC,
359
                                   const InterpFrame *Frame,
360
10
                                   const Function *F) {
361
10
  const Floating &Arg = S.Stk.peek<Floating>();
362
363
10
  pushInt(S, Arg.isZero());
364
10
  return true;
365
10
}
366
367
/// First parameter to __builtin_isfpclass is the floating value, the
368
/// second one is an integral value.
369
static bool interp__builtin_isfpclass(InterpState &S, CodePtr OpPC,
370
                                      const InterpFrame *Frame,
371
                                      const Function *Func,
372
194
                                      const CallExpr *Call) {
373
194
  PrimType FPClassArgT = *S.getContext().classify(Call->getArg(1)->getType());
374
194
  APSInt FPClassArg = peekToAPSInt(S.Stk, FPClassArgT);
375
194
  const Floating &F =
376
194
      S.Stk.peek<Floating>(align(primSize(FPClassArgT) + primSize(PT_Float)));
377
378
194
  int32_t Result =
379
194
      static_cast<int32_t>((F.classify() & FPClassArg).getZExtValue());
380
194
  pushInt(S, Result);
381
382
194
  return true;
383
194
}
384
385
/// Five int values followed by one floating value.
386
static bool interp__builtin_fpclassify(InterpState &S, CodePtr OpPC,
387
                                       const InterpFrame *Frame,
388
52
                                       const Function *Func) {
389
52
  const Floating &Val = S.Stk.peek<Floating>();
390
391
52
  unsigned Index;
392
52
  switch (Val.getCategory()) {
393
10
  case APFloat::fcNaN:
394
10
    Index = 0;
395
10
    break;
396
10
  case APFloat::fcInfinity:
397
10
    Index = 1;
398
10
    break;
399
22
  case APFloat::fcNormal:
400
22
    Index = Val.isDenormal() ? 
313
:
29
;
401
22
    break;
402
10
  case APFloat::fcZero:
403
10
    Index = 4;
404
10
    break;
405
52
  }
406
407
  // The last argument is first on the stack.
408
52
  assert(Index <= 4);
409
52
  unsigned IntSize = primSize(getIntPrimType(S));
410
52
  unsigned Offset =
411
52
      align(primSize(PT_Float)) + ((1 + (4 - Index)) * align(IntSize));
412
413
52
  APSInt I = peekToAPSInt(S.Stk, getIntPrimType(S), Offset);
414
52
  pushInt(S, I.getZExtValue());
415
52
  return true;
416
52
}
417
418
// The C standard says "fabs raises no floating-point exceptions,
419
// even if x is a signaling NaN. The returned value is independent of
420
// the current rounding direction mode."  Therefore constant folding can
421
// proceed without regard to the floating point settings.
422
// Reference, WG14 N2478 F.10.4.3
423
static bool interp__builtin_fabs(InterpState &S, CodePtr OpPC,
424
                                 const InterpFrame *Frame,
425
5
                                 const Function *Func) {
426
5
  const Floating &Val = getParam<Floating>(Frame, 0);
427
428
5
  S.Stk.push<Floating>(Floating::abs(Val));
429
5
  return true;
430
5
}
431
432
static bool interp__builtin_popcount(InterpState &S, CodePtr OpPC,
433
                                     const InterpFrame *Frame,
434
                                     const Function *Func,
435
125
                                     const CallExpr *Call) {
436
125
  PrimType ArgT = *S.getContext().classify(Call->getArg(0)->getType());
437
125
  APSInt Val = peekToAPSInt(S.Stk, ArgT);
438
125
  pushInt(S, Val.popcount());
439
125
  return true;
440
125
}
441
442
bool InterpretBuiltin(InterpState &S, CodePtr OpPC, const Function *F,
443
1.50k
                      const CallExpr *Call) {
444
1.50k
  InterpFrame *Frame = S.Current;
445
1.50k
  APValue Dummy;
446
447
1.50k
  switch (F->getBuiltinID()) {
448
8
  case Builtin::BI__builtin_is_constant_evaluated:
449
8
    S.Stk.push<Boolean>(Boolean::from(S.inConstantContext()));
450
8
    return Ret<PT_Bool>(S, OpPC, Dummy);
451
8
  case Builtin::BI__builtin_assume:
452
8
    return RetVoid(S, OpPC, Dummy);
453
185
  case Builtin::BI__builtin_strcmp:
454
185
    if (interp__builtin_strcmp(S, OpPC, Frame))
455
140
      return retInt(S, OpPC, Dummy);
456
45
    break;
457
358
  case Builtin::BI__builtin_strlen:
458
358
    if (interp__builtin_strlen(S, OpPC, Frame))
459
195
      return retSizeT(S, OpPC, Dummy);
460
163
    break;
461
163
  case Builtin::BI__builtin_nan:
462
82
  case Builtin::BI__builtin_nanf:
463
87
  case Builtin::BI__builtin_nanl:
464
87
  case Builtin::BI__builtin_nanf16:
465
87
  case Builtin::BI__builtin_nanf128:
466
87
    if (interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/false))
467
77
      return Ret<PT_Float>(S, OpPC, Dummy);
468
10
    break;
469
34
  case Builtin::BI__builtin_nans:
470
39
  case Builtin::BI__builtin_nansf:
471
44
  case Builtin::BI__builtin_nansl:
472
44
  case Builtin::BI__builtin_nansf16:
473
44
  case Builtin::BI__builtin_nansf128:
474
44
    if (interp__builtin_nan(S, OpPC, Frame, F, /*Signaling=*/true))
475
44
      return Ret<PT_Float>(S, OpPC, Dummy);
476
0
    break;
477
478
0
  case Builtin::BI__builtin_huge_val:
479
0
  case Builtin::BI__builtin_huge_valf:
480
0
  case Builtin::BI__builtin_huge_vall:
481
0
  case Builtin::BI__builtin_huge_valf16:
482
0
  case Builtin::BI__builtin_huge_valf128:
483
82
  case Builtin::BI__builtin_inf:
484
92
  case Builtin::BI__builtin_inff:
485
102
  case Builtin::BI__builtin_infl:
486
102
  case Builtin::BI__builtin_inff16:
487
102
  case Builtin::BI__builtin_inff128:
488
102
    if (interp__builtin_inf(S, OpPC, Frame, F))
489
102
      return Ret<PT_Float>(S, OpPC, Dummy);
490
0
    break;
491
32
  case Builtin::BI__builtin_copysign:
492
32
  case Builtin::BI__builtin_copysignf:
493
32
  case Builtin::BI__builtin_copysignl:
494
32
  case Builtin::BI__builtin_copysignf128:
495
32
    if (interp__builtin_copysign(S, OpPC, Frame, F))
496
32
      return Ret<PT_Float>(S, OpPC, Dummy);
497
0
    break;
498
499
59
  case Builtin::BI__builtin_fmin:
500
82
  case Builtin::BI__builtin_fminf:
501
109
  case Builtin::BI__builtin_fminl:
502
132
  case Builtin::BI__builtin_fminf16:
503
132
  case Builtin::BI__builtin_fminf128:
504
132
    if (interp__builtin_fmin(S, OpPC, Frame, F))
505
132
      return Ret<PT_Float>(S, OpPC, Dummy);
506
0
    break;
507
508
23
  case Builtin::BI__builtin_fmax:
509
46
  case Builtin::BI__builtin_fmaxf:
510
73
  case Builtin::BI__builtin_fmaxl:
511
96
  case Builtin::BI__builtin_fmaxf16:
512
96
  case Builtin::BI__builtin_fmaxf128:
513
96
    if (interp__builtin_fmax(S, OpPC, Frame, F))
514
96
      return Ret<PT_Float>(S, OpPC, Dummy);
515
0
    break;
516
517
8
  case Builtin::BI__builtin_isnan:
518
8
    if (interp__builtin_isnan(S, OpPC, Frame, F))
519
8
      return retInt(S, OpPC, Dummy);
520
0
    break;
521
20
  case Builtin::BI__builtin_issignaling:
522
20
    if (interp__builtin_issignaling(S, OpPC, Frame, F))
523
20
      return retInt(S, OpPC, Dummy);
524
0
    break;
525
526
10
  case Builtin::BI__builtin_isinf:
527
10
    if (interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/false))
528
10
      return retInt(S, OpPC, Dummy);
529
0
    break;
530
531
0
  case Builtin::BI__builtin_isinf_sign:
532
0
    if (interp__builtin_isinf(S, OpPC, Frame, F, /*Sign=*/true))
533
0
      return retInt(S, OpPC, Dummy);
534
0
    break;
535
536
10
  case Builtin::BI__builtin_isfinite:
537
10
    if (interp__builtin_isfinite(S, OpPC, Frame, F))
538
10
      return retInt(S, OpPC, Dummy);
539
0
    break;
540
10
  case Builtin::BI__builtin_isnormal:
541
10
    if (interp__builtin_isnormal(S, OpPC, Frame, F))
542
10
      return retInt(S, OpPC, Dummy);
543
0
    break;
544
9
  case Builtin::BI__builtin_issubnormal:
545
9
    if (interp__builtin_issubnormal(S, OpPC, Frame, F))
546
9
      return retInt(S, OpPC, Dummy);
547
0
    break;
548
10
  case Builtin::BI__builtin_iszero:
549
10
    if (interp__builtin_iszero(S, OpPC, Frame, F))
550
10
      return retInt(S, OpPC, Dummy);
551
0
    break;
552
194
  case Builtin::BI__builtin_isfpclass:
553
194
    if (interp__builtin_isfpclass(S, OpPC, Frame, F, Call))
554
194
      return retInt(S, OpPC, Dummy);
555
0
    break;
556
52
  case Builtin::BI__builtin_fpclassify:
557
52
    if (interp__builtin_fpclassify(S, OpPC, Frame, F))
558
52
      return retInt(S, OpPC, Dummy);
559
0
    break;
560
561
5
  case Builtin::BI__builtin_fabs:
562
5
  case Builtin::BI__builtin_fabsf:
563
5
  case Builtin::BI__builtin_fabsl:
564
5
  case Builtin::BI__builtin_fabsf128:
565
5
    if (interp__builtin_fabs(S, OpPC, Frame, F))
566
5
      return Ret<PT_Float>(S, OpPC, Dummy);
567
0
    break;
568
569
45
  case Builtin::BI__builtin_popcount:
570
85
  case Builtin::BI__builtin_popcountl:
571
125
  case Builtin::BI__builtin_popcountll:
572
125
  case Builtin::BI__popcnt16: // Microsoft variants of popcount
573
125
  case Builtin::BI__popcnt:
574
125
  case Builtin::BI__popcnt64:
575
125
    if (interp__builtin_popcount(S, OpPC, Frame, F, Call))
576
125
      return retInt(S, OpPC, Dummy);
577
0
    break;
578
579
0
  default:
580
0
    return false;
581
1.50k
  }
582
583
218
  return false;
584
1.50k
}
585
586
bool InterpretOffsetOf(InterpState &S, CodePtr OpPC, const OffsetOfExpr *E,
587
                       llvm::ArrayRef<int64_t> ArrayIndices,
588
109
                       int64_t &IntResult) {
589
109
  CharUnits Result;
590
109
  unsigned N = E->getNumComponents();
591
109
  assert(N > 0);
592
593
109
  unsigned ArrayIndex = 0;
594
109
  QualType CurrentType = E->getTypeSourceInfo()->getType();
595
293
  for (unsigned I = 0; I != N; 
++I184
) {
596
184
    const OffsetOfNode &Node = E->getComponent(I);
597
184
    switch (Node.getKind()) {
598
113
    case OffsetOfNode::Field: {
599
113
      const FieldDecl *MemberDecl = Node.getField();
600
113
      const RecordType *RT = CurrentType->getAs<RecordType>();
601
113
      if (!RT)
602
0
        return false;
603
113
      RecordDecl *RD = RT->getDecl();
604
113
      if (RD->isInvalidDecl())
605
0
        return false;
606
113
      const ASTRecordLayout &RL = S.getCtx().getASTRecordLayout(RD);
607
113
      unsigned FieldIndex = MemberDecl->getFieldIndex();
608
113
      assert(FieldIndex < RL.getFieldCount() && "offsetof field in wrong type");
609
113
      Result += S.getCtx().toCharUnitsFromBits(RL.getFieldOffset(FieldIndex));
610
113
      CurrentType = MemberDecl->getType().getNonReferenceType();
611
113
      break;
612
113
    }
613
2
    case OffsetOfNode::Array: {
614
      // When generating bytecode, we put all the index expressions as Sint64 on
615
      // the stack.
616
2
      int64_t Index = ArrayIndices[ArrayIndex];
617
2
      const ArrayType *AT = S.getCtx().getAsArrayType(CurrentType);
618
2
      if (!AT)
619
0
        return false;
620
2
      CurrentType = AT->getElementType();
621
2
      CharUnits ElementSize = S.getCtx().getTypeSizeInChars(CurrentType);
622
2
      Result += Index * ElementSize;
623
2
      ++ArrayIndex;
624
2
      break;
625
2
    }
626
69
    case OffsetOfNode::Base: {
627
69
      const CXXBaseSpecifier *BaseSpec = Node.getBase();
628
69
      if (BaseSpec->isVirtual())
629
0
        return false;
630
631
      // Find the layout of the class whose base we are looking into.
632
69
      const RecordType *RT = CurrentType->getAs<RecordType>();
633
69
      if (!RT)
634
0
        return false;
635
69
      const RecordDecl *RD = RT->getDecl();
636
69
      if (RD->isInvalidDecl())
637
0
        return false;
638
69
      const ASTRecordLayout &RL = S.getCtx().getASTRecordLayout(RD);
639
640
      // Find the base class itself.
641
69
      CurrentType = BaseSpec->getType();
642
69
      const RecordType *BaseRT = CurrentType->getAs<RecordType>();
643
69
      if (!BaseRT)
644
0
        return false;
645
646
      // Add the offset to the base.
647
69
      Result += RL.getBaseClassOffset(cast<CXXRecordDecl>(BaseRT->getDecl()));
648
69
      break;
649
69
    }
650
0
    case OffsetOfNode::Identifier:
651
0
      llvm_unreachable("Dependent OffsetOfExpr?");
652
184
    }
653
184
  }
654
655
109
  IntResult = Result.getQuantity();
656
657
109
  return true;
658
109
}
659
660
bool SetThreeWayComparisonField(InterpState &S, CodePtr OpPC,
661
9
                                const Pointer &Ptr, const APSInt &IntValue) {
662
663
9
  const Record *R = Ptr.getRecord();
664
9
  assert(R);
665
9
  assert(R->getNumFields() == 1);
666
667
9
  unsigned FieldOffset = R->getField(0u)->Offset;
668
9
  const Pointer &FieldPtr = Ptr.atField(FieldOffset);
669
9
  PrimType FieldT = *S.getContext().classify(FieldPtr.getType());
670
671
9
  INT_TYPE_SWITCH(FieldT,
672
9
                  FieldPtr.deref<T>() = T::from(IntValue.getSExtValue()));
673
9
  FieldPtr.initialize();
674
9
  return true;
675
9
}
676
677
} // namespace interp
678
} // namespace clang