[cfe-commits] r161635 - in /cfe/trunk: include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h lib/StaticAnalyzer/Core/MemRegion.cpp lib/StaticAnalyzer/Core/RegionStore.cpp

Jordan Rose jordan_rose at apple.com
Thu Aug 9 15:55:37 PDT 2012


Author: jrose
Date: Thu Aug  9 17:55:37 2012
New Revision: 161635

URL: http://llvm.org/viewvc/llvm-project?rev=161635&view=rev
Log:
[analyzer] Cache the "concrete offset base" for regions with symbolic offsets.

This makes it faster to access and invalidate bindings with symbolic offsets
by only computing this information once.

No intended functionality change.

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
    cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h?rev=161635&r1=161634&r2=161635&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h Thu Aug  9 17:55:37 2012
@@ -52,11 +52,19 @@
   int64_t Offset;
 
 public:
+  enum { Symbolic = INT64_MAX };
+
   RegionOffset() : R(0) {}
   RegionOffset(const MemRegion *r, int64_t off) : R(r), Offset(off) {}
 
   const MemRegion *getRegion() const { return R; }
-  int64_t getOffset() const { return Offset; }
+
+  bool hasSymbolicOffset() const { return Offset == Symbolic; }
+
+  int64_t getOffset() const {
+    assert(!hasSymbolicOffset());
+    return Offset;
+  }
 
   bool isValid() const { return R; }
 };

Modified: cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp?rev=161635&r1=161634&r2=161635&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/MemRegion.cpp Thu Aug  9 17:55:37 2012
@@ -1038,12 +1038,14 @@
 
 RegionOffset MemRegion::getAsOffset() const {
   const MemRegion *R = this;
+  const MemRegion *SymbolicOffsetBase = 0;
   int64_t Offset = 0;
 
   while (1) {
     switch (R->getKind()) {
     default:
-      return RegionOffset();
+      return RegionOffset(R, RegionOffset::Symbolic);
+
     case SymbolicRegionKind:
     case AllocaRegionKind:
     case CompoundLiteralRegionKind:
@@ -1053,6 +1055,7 @@
     case ObjCIvarRegionKind:
     case CXXTempObjectRegionKind:
       goto Finish;
+
     case CXXBaseObjectRegionKind: {
       const CXXBaseObjectRegion *BOR = cast<CXXBaseObjectRegion>(R);
       R = BOR->getSuperRegion();
@@ -1070,8 +1073,14 @@
       const CXXRecordDecl *Child = Ty->getAsCXXRecordDecl();
       if (!Child) {
         // We cannot compute the offset of the base class.
-        return RegionOffset();
+        SymbolicOffsetBase = R;
       }
+
+      // Don't bother calculating precise offsets if we already have a
+      // symbolic offset somewhere in the chain.
+      if (SymbolicOffsetBase)
+        continue;
+
       const ASTRecordLayout &Layout = getContext().getASTRecordLayout(Child);
 
       CharUnits BaseOffset;
@@ -1087,29 +1096,46 @@
     }
     case ElementRegionKind: {
       const ElementRegion *ER = cast<ElementRegion>(R);
-      QualType EleTy = ER->getValueType();
+      R = ER->getSuperRegion();
 
-      if (!IsCompleteType(getContext(), EleTy))
-        return RegionOffset();
+      QualType EleTy = ER->getValueType();
+      if (!IsCompleteType(getContext(), EleTy)) {
+        // We cannot compute the offset of the base class.
+        SymbolicOffsetBase = R;
+        continue;
+      }
 
       SVal Index = ER->getIndex();
       if (const nonloc::ConcreteInt *CI=dyn_cast<nonloc::ConcreteInt>(&Index)) {
+        // Don't bother calculating precise offsets if we already have a
+        // symbolic offset somewhere in the chain. 
+        if (SymbolicOffsetBase)
+          continue;
+
         int64_t i = CI->getValue().getSExtValue();
         // This type size is in bits.
         Offset += i * getContext().getTypeSize(EleTy);
       } else {
         // We cannot compute offset for non-concrete index.
-        return RegionOffset();
+        SymbolicOffsetBase = R;
       }
-      R = ER->getSuperRegion();
       break;
     }
     case FieldRegionKind: {
       const FieldRegion *FR = cast<FieldRegion>(R);
+      R = FR->getSuperRegion();
+
       const RecordDecl *RD = FR->getDecl()->getParent();
-      if (!RD->isCompleteDefinition())
+      if (!RD->isCompleteDefinition()) {
         // We cannot compute offset for incomplete type.
-        return RegionOffset();
+        SymbolicOffsetBase = R;
+      }
+
+      // Don't bother calculating precise offsets if we already have a
+      // symbolic offset somewhere in the chain.
+      if (SymbolicOffsetBase)
+        continue;
+
       // Get the field number.
       unsigned idx = 0;
       for (RecordDecl::field_iterator FI = RD->field_begin(), 
@@ -1120,13 +1146,14 @@
       const ASTRecordLayout &Layout = getContext().getASTRecordLayout(RD);
       // This is offset in bits.
       Offset += Layout.getFieldOffset(idx);
-      R = FR->getSuperRegion();
       break;
     }
     }
   }
 
  Finish:
+  if (SymbolicOffsetBase)
+    return RegionOffset(SymbolicOffsetBase, RegionOffset::Symbolic);
   return RegionOffset(R, Offset);
 }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=161635&r1=161634&r2=161635&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Thu Aug  9 17:55:37 2012
@@ -40,33 +40,42 @@
 namespace {
 class BindingKey {
 public:
-  enum Kind { Direct = 0x0, Default = 0x1 };
+  enum Kind { Default = 0x0, Direct = 0x1 };
 private:
-  enum { SYMBOLIC = UINT64_MAX };
+  enum { Symbolic = 0x2 };
 
-  llvm::PointerIntPair<const MemRegion *, 1, Kind> P;
-  uint64_t Offset;
+  llvm::PointerIntPair<const MemRegion *, 2> P;
+  uint64_t Data;
 
-  explicit BindingKey(const MemRegion *r, Kind k)
-    : P(r, k), Offset(SYMBOLIC) {}
+  explicit BindingKey(const MemRegion *r, const MemRegion *Base, Kind k)
+    : P(r, k | Symbolic), Data(reinterpret_cast<uintptr_t>(Base)) {
+    assert(r && Base && "Must have known regions.");
+    assert(getConcreteOffsetRegion() == Base && "Failed to store base region");
+  }
   explicit BindingKey(const MemRegion *r, uint64_t offset, Kind k)
-    : P(r, k), Offset(offset) {}
+    : P(r, k), Data(offset) {
+    assert(r && "Must have known regions.");
+    assert(getOffset() == offset && "Failed to store offset");
+  }
 public:
 
-  bool isDirect() const { return P.getInt() == Direct; }
-  bool hasSymbolicOffset() const { return Offset == SYMBOLIC; }
+  bool isDirect() const { return P.getInt() & Direct; }
+  bool hasSymbolicOffset() const { return P.getInt() & Symbolic; }
 
   const MemRegion *getRegion() const { return P.getPointer(); }
   uint64_t getOffset() const {
     assert(!hasSymbolicOffset());
-    return Offset;
+    return Data;
   }
 
-  const MemRegion *getConcreteOffsetRegion() const;
+  const MemRegion *getConcreteOffsetRegion() const {
+    assert(hasSymbolicOffset());
+    return reinterpret_cast<const MemRegion *>(static_cast<uintptr_t>(Data));
+  }
 
   void Profile(llvm::FoldingSetNodeID& ID) const {
     ID.AddPointer(P.getOpaqueValue());
-    ID.AddInteger(Offset);
+    ID.AddInteger(Data);
   }
 
   static BindingKey Make(const MemRegion *R, Kind k);
@@ -76,12 +85,12 @@
       return true;
     if (P.getOpaqueValue() > X.P.getOpaqueValue())
       return false;
-    return Offset < X.Offset;
+    return Data < X.Data;
   }
 
   bool operator==(const BindingKey &X) const {
     return P.getOpaqueValue() == X.P.getOpaqueValue() &&
-           Offset == X.Offset;
+           Data == X.Data;
   }
 
   bool isValid() const {
@@ -92,27 +101,10 @@
 
 BindingKey BindingKey::Make(const MemRegion *R, Kind k) {
   const RegionOffset &RO = R->getAsOffset();
-  if (RO.isValid())
-    return BindingKey(RO.getRegion(), RO.getOffset(), k);
-
-  return BindingKey(R, k);
-}
-
-const MemRegion *BindingKey::getConcreteOffsetRegion() const {
-  const MemRegion *R = getRegion();
-  if (!hasSymbolicOffset())
-    return R;
-
-  RegionOffset RO;
-  do {
-    const SubRegion *SR = dyn_cast<SubRegion>(R);
-    if (!SR)
-      break;
-    R = SR->getSuperRegion();
-    RO = R->getAsOffset();
-  } while (!RO.isValid());
+  if (RO.hasSymbolicOffset())
+    return BindingKey(R, RO.getRegion(), k);
 
-  return R;
+  return BindingKey(RO.getRegion(), RO.getOffset(), k);
 }
 
 namespace llvm {
@@ -561,7 +553,6 @@
   // by changing the data structure used for RegionBindings.
 
   BindingKey SRKey = BindingKey::Make(R, BindingKey::Default);
-  assert(SRKey.isValid());
   if (SRKey.hasSymbolicOffset()) {
     const SubRegion *Base = cast<SubRegion>(SRKey.getConcreteOffsetRegion());
     B = removeSubRegionBindings(B, Base);





More information about the cfe-commits mailing list