[cfe-dev] Help with APValue comparisons

Sean Silva silvas at purdue.edu
Fri Jun 15 13:38:11 PDT 2012


>   case Float:
>     return A.getFloat().bitwiseIsEqual(B.getFloat());

I don't think that this comparison is correct for IEEE floating point
numbers. For example, two bit-identical NaN's will compare equal, when they
should compare not-equal. I haven't used APFloat before, but from browsing
the Doxygen, I think the comparison should be:

    A.getFloat().compare(B.getFloat()) == cmpEqual

--Sean Silva

On Fri, Jun 15, 2012 at 12:38 AM, Andy Gibbs <andyg1001 at hotmail.co.uk>wrote:

> Hi Jordan,
>
> Thanks for your pointers.  I've implemented an "isEqual" function as below.
> If you have time, would you mind having a quick skim through please to see
> if I've caught the right idea.  At the moment, it holds up to the testing I
> have performed so far, but I'm always working on more test-cases!
>
> At this point, my concern is not that isEqual may not fully distinguish two
> APValues that *are* equal, more that it should never say two APValues are
> equal when they aren't.  False negatives are much less of an issue than
> false positives!
>
> I haven't implemented equality checking for member pointers, yet.  Again,
> this is due to a lack of understand on exactly how to implement this check
> (it seems even the dump / printPretty functions have not been fully
> implemented for this type).
>
> If you think my approach is valid, then I will post a tentative patch for
> http://llvm.org/bugs/show_bug.cgi?id=12850.
>
> Many, many thanks
>
> Andy
>
>
> // static member function of APValue
> bool APValue::isEqual(const APValue &A, const APValue &B) {
>  if (A.getKind() != B.getKind())
>    return false;
>
>  switch (A.getKind()) {
>    case Uninitialized:
>      return true;
>
>    case Int:
>      return (A.getInt() == B.getInt());
>
>    case Float:
>      return A.getFloat().bitwiseIsEqual(B.getFloat());
>
>    case ComplexInt:
>      return (A.getComplexIntReal() == B.getComplexIntReal()) &&
>             (A.getComplexIntImag() == B.getComplexIntImag());
>
>    case ComplexFloat:
>      return A.getComplexFloatReal().bitwiseIsEqual(B.getComplexFloatReal())
> &&
>
> A.getComplexFloatImag().bitwiseIsEqual(B.getComplexFloatImag());
>
>    case Vector: {
>      unsigned len = A.getVectorLength();
>      if (len != B.getVectorLength()) return false;
>      for (unsigned i = 0; i != len; ++i) {
>        if (!isEqual(A.getVectorElt(i), B.getVectorElt(i)))
>          return false;
>      }
>      return true;
>    }
>
>    case Array: {
>      unsigned len = A.getArraySize();
>      if (len != B.getArraySize()) return false;
>
>      APValue FillerA, FillerB;
>      if (A.hasArrayFiller()) FillerA = A.getArrayFiller();
>      if (B.hasArrayFiller()) FillerB = B.getArrayFiller();
>
>      // Two arrays are equal if their initialised elements are equal,
>      // but also where one array is more initialised than another, where
>      // those additional initialised elements are equal to the filler
>      // of the other.  If they both contain uninitialised elements, the
>      // fillers must also match.
>      for (unsigned i = 0, a = A.getArrayInitializedElts(),
>                           b = B.getArrayInitializedElts(); i != len; ++i) {
>        if (!isEqual(
>              (i < a) ? A.getArrayInitializedElt(i) : FillerA,
>              (i < b) ? B.getArrayInitializedElt(i) : FillerB))
>          return false;
>        if (i >= a && i >= b) // all the initialised elements *and* the
>          break;              // fillers have been compared; we're equal!
>      }
>      return true;
>    }
>
>    case Struct: {
>      unsigned bases = A.getStructNumBases();
>      if (bases != B.getStructNumBases()) return false;
>
>      unsigned fields = A.getStructNumFields();
>      if (fields != B.getStructNumFields()) return false;
>
>      for (unsigned i = 0; i != bases; ++i) {
>        if (!isEqual(A.getStructBase(i), B.getStructBase(i)))
>          return false;
>      }
>
>      for (unsigned i = 0; i != fields; ++i) {
>        if (!isEqual(A.getStructField(i), B.getStructField(i)))
>          return false;
>      }
>
>      return true;
>    }
>
>    case Union:
>      return (A.getUnionField() == B.getUnionField()) &&
>             (isEqual(A.getUnionValue(), B.getUnionValue()));
>
>    case AddrLabelDiff:
>      return (A.getAddrLabelDiffLHS() == B.getAddrLabelDiffLHS()) &&
>             (A.getAddrLabelDiffRHS() == B.getAddrLabelDiffRHS());
>
>    case LValue: {
>      LValueBase BaseA = A.getLValueBase();
>      LValueBase BaseB = B.getLValueBase();
>
>      // null pointers are not comparable
>      if (!BaseA || !BaseB || BaseA.isNull() || BaseB.isNull()) return
> false;
>
>      bool IsValueDecl = BaseA.is<const ValueDecl*>();
>      if (IsValueDecl != BaseB.is<const ValueDecl*>()) return false;
>
>      QualType ElemTy;
>      if (IsValueDecl) {
>        const ValueDecl *VD = BaseA.get<const ValueDecl*>();
>        ElemTy = VD->getType();
>        if (VD != BaseB.get<const ValueDecl*>()) return false;
>      } else {
>        const Expr *E = BaseA.get<const Expr*>();
>        ElemTy = E->getType();
>        if (E != BaseB.get<const Expr*>()) return false;
>      }
>
>      bool HasPath = A.hasLValuePath();
>      if (HasPath != B.hasLValuePath()) return false;
>
>      if (!HasPath) {
>        return A.getLValueOffset() == B.getLValueOffset();
>      }
>
>      ArrayRef<LValuePathEntry> PathA = A.getLValuePath();
>      ArrayRef<LValuePathEntry> PathB = B.getLValuePath();
>      if (PathA.size() != PathB.size()) return false;
>
>      for (unsigned I = 0, N = PathA.size(); I != N; ++I) {
>        if (ElemTy->getAs<RecordType>()) {
>          const Decl *BaseOrMemberA =
> BaseOrMemberType::getFromOpaqueValue(PathA[I].BaseOrMember).getPointer();
>          const Decl *BaseOrMemberB =
> BaseOrMemberType::getFromOpaqueValue(PathB[I].BaseOrMember).getPointer();
>
>          if (BaseOrMemberA != BaseOrMemberB) return false;
>          if (const CXXRecordDecl *RD =
> dyn_cast<CXXRecordDecl>(BaseOrMemberA)) {
>            const Type *T = RD->getTypeForDecl();
>            assert(T && "getTypeForDecl did not return a valid value");
>            ElemTy = QualType(T, 0);
>          } else {
>            const ValueDecl *VD = cast<ValueDecl>(BaseOrMemberA);
>            ElemTy = VD->getType();
>          }
>        } else {
>          if (PathA[I].ArrayIndex != PathB[I].ArrayIndex) return false;
>
>          assert(dyn_cast<ArrayType>(ElemTy) && "Unexpected ElemTy");
>          ElemTy = dyn_cast<ArrayType>(ElemTy)->getElementType();
>        }
>      }
>
>      return true;
>    }
>
>    case MemberPointer:
>      llvm_unreachable("isEqual unimplemented for this APValue kind!");
>      return false;
>  }
>  llvm_unreachable("Unknown APValue kind!");
>  return false;
> }
>
>
> _______________________________________________
> cfe-dev mailing list
> cfe-dev at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/cfe-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20120615/8d4fa652/attachment.html>


More information about the cfe-dev mailing list