@@ -77,6 +77,14 @@ QualType APValue::LValueBase::getDynamicAllocType() const {
77
77
return QualType::getFromOpaquePtr (DynamicAllocType);
78
78
}
79
79
80
+ void APValue::LValueBase::profile (llvm::FoldingSetNodeID &ID) const {
81
+ ID.AddPointer (Ptr.getOpaqueValue ());
82
+ if (is<TypeInfoLValue>() || is<DynamicAllocLValue>())
83
+ return ;
84
+ ID.AddInteger (Local.CallIndex );
85
+ ID.AddInteger (Local.Version );
86
+ }
87
+
80
88
namespace clang {
81
89
bool operator ==(const APValue::LValueBase &LHS,
82
90
const APValue::LValueBase &RHS) {
@@ -95,6 +103,10 @@ APValue::LValuePathEntry::LValuePathEntry(BaseOrMemberType BaseOrMember) {
95
103
Value = reinterpret_cast <uintptr_t >(BaseOrMember.getOpaqueValue ());
96
104
}
97
105
106
+ void APValue::LValuePathEntry::profile (llvm::FoldingSetNodeID &ID) const {
107
+ ID.AddInteger (Value);
108
+ }
109
+
98
110
namespace {
99
111
struct LVBase {
100
112
APValue::LValueBase Base;
@@ -402,6 +414,147 @@ void APValue::swap(APValue &RHS) {
402
414
std::swap (Data, RHS.Data );
403
415
}
404
416
417
+ void APValue::profile (llvm::FoldingSetNodeID &ID) const {
418
+ ID.AddInteger (Kind);
419
+
420
+ switch (Kind) {
421
+ case None:
422
+ case Indeterminate:
423
+ return ;
424
+
425
+ case AddrLabelDiff:
426
+ ID.AddPointer (getAddrLabelDiffLHS ()->getLabel ()->getCanonicalDecl ());
427
+ ID.AddPointer (getAddrLabelDiffRHS ()->getLabel ()->getCanonicalDecl ());
428
+ return ;
429
+
430
+ case Struct:
431
+ ID.AddInteger (getStructNumBases ());
432
+ for (unsigned I = 0 , N = getStructNumBases (); I != N; ++I)
433
+ getStructBase (I).profile (ID);
434
+ ID.AddInteger (getStructNumFields ());
435
+ for (unsigned I = 0 , N = getStructNumFields (); I != N; ++I)
436
+ getStructField (I).profile (ID);
437
+ return ;
438
+
439
+ case Union:
440
+ if (!getUnionField ()) {
441
+ ID.AddPointer (nullptr );
442
+ return ;
443
+ }
444
+ ID.AddPointer (getUnionField ()->getCanonicalDecl ());
445
+ getUnionValue ().profile (ID);
446
+ return ;
447
+
448
+ case Array: {
449
+ ID.AddInteger (getArraySize ());
450
+ if (getArraySize () == 0 )
451
+ return ;
452
+
453
+ // The profile should not depend on whether the array is expanded or
454
+ // not, but we don't want to profile the array filler many times for
455
+ // a large array. So treat all equal trailing elements as the filler.
456
+ // Elements are profiled in reverse order to support this, and the
457
+ // first profiled element is followed by a count. For example:
458
+ //
459
+ // ['a', 'c', 'x', 'x', 'x'] is profiled as
460
+ // [5, 'x', 3, 'c', 'a']
461
+ llvm::FoldingSetNodeID FillerID;
462
+ (hasArrayFiller () ? getArrayFiller () :
463
+ getArrayInitializedElt (getArrayInitializedElts () -
464
+ 1 )).profile (FillerID);
465
+ ID.AddNodeID (FillerID);
466
+ unsigned NumFillers = getArraySize () - getArrayInitializedElts ();
467
+ unsigned N = getArrayInitializedElts ();
468
+
469
+ // Count the number of elements equal to the last one. This loop ends
470
+ // by adding an integer indicating the number of such elements, with
471
+ // N set to the number of elements left to profile.
472
+ while (true ) {
473
+ if (N == 0 ) {
474
+ // All elements are fillers.
475
+ assert (NumFillers == getArraySize ());
476
+ ID.AddInteger (NumFillers);
477
+ break ;
478
+ }
479
+
480
+ // No need to check if the last element is equal to the last
481
+ // element.
482
+ if (N != getArraySize ()) {
483
+ llvm::FoldingSetNodeID ElemID;
484
+ getArrayInitializedElt (N - 1 ).profile (ElemID);
485
+ if (ElemID != FillerID) {
486
+ ID.AddInteger (NumFillers);
487
+ ID.AddNodeID (ElemID);
488
+ --N;
489
+ break ;
490
+ }
491
+ }
492
+
493
+ // This is a filler.
494
+ ++NumFillers;
495
+ --N;
496
+ }
497
+
498
+ // Emit the remaining elements.
499
+ for (; N != 0 ; --N)
500
+ getArrayInitializedElt (N - 1 ).profile (ID);
501
+ return ;
502
+ }
503
+
504
+ case Vector:
505
+ ID.AddInteger (getVectorLength ());
506
+ for (unsigned I = 0 , N = getVectorLength (); I != N; ++I)
507
+ getVectorElt (I).profile (ID);
508
+ return ;
509
+
510
+ case Int:
511
+ // We don't need to include the sign bit; it's implied by the type.
512
+ getInt ().APInt ::Profile (ID);
513
+ return ;
514
+
515
+ case Float:
516
+ getFloat ().Profile (ID);
517
+ return ;
518
+
519
+ case FixedPoint:
520
+ // We don't need to include the fixed-point semantics; they're
521
+ // implied by the type.
522
+ getFixedPoint ().getValue ().APInt ::Profile (ID);
523
+ return ;
524
+
525
+ case ComplexFloat:
526
+ getComplexFloatReal ().Profile (ID);
527
+ getComplexFloatImag ().Profile (ID);
528
+ return ;
529
+
530
+ case ComplexInt:
531
+ getComplexIntReal ().APInt ::Profile (ID);
532
+ getComplexIntImag ().APInt ::Profile (ID);
533
+ return ;
534
+
535
+ case LValue:
536
+ getLValueBase ().profile (ID);
537
+ ID.AddInteger (getLValueOffset ().getQuantity ());
538
+ ID.AddInteger (isNullPointer ());
539
+ ID.AddInteger (isLValueOnePastTheEnd ());
540
+ // For uniqueness, we only need to profile the entries corresponding
541
+ // to union members, but we don't have the type here so we don't know
542
+ // how to interpret the entries.
543
+ for (LValuePathEntry E : getLValuePath ())
544
+ E.profile (ID);
545
+ return ;
546
+
547
+ case MemberPointer:
548
+ ID.AddPointer (getMemberPointerDecl ());
549
+ ID.AddInteger (isMemberPointerToDerivedMember ());
550
+ for (const CXXRecordDecl *D : getMemberPointerPath ())
551
+ ID.AddPointer (D);
552
+ return ;
553
+ }
554
+
555
+ llvm_unreachable (" Unknown APValue kind!" );
556
+ }
557
+
405
558
static double GetApproxValue (const llvm::APFloat &F) {
406
559
llvm::APFloat V = F;
407
560
bool ignored;
0 commit comments