Permalink
Browse files

[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.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161635 91177308-0d34-0410-b5e6-96231b3b80d8
  • Loading branch information...
1 parent bf74b56 commit 824e07ac8f5c9efdddb4254de0203b9675b1ef0b @jrose-apple jrose-apple committed Aug 9, 2012
@@ -52,11 +52,19 @@ class RegionOffset {
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; }
};
@@ -1038,12 +1038,14 @@ RegionRawOffset ElementRegion::getAsArrayOffset() const {
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 @@ RegionOffset MemRegion::getAsOffset() const {
case ObjCIvarRegionKind:
case CXXTempObjectRegionKind:
goto Finish;
+
case CXXBaseObjectRegionKind: {
const CXXBaseObjectRegion *BOR = cast<CXXBaseObjectRegion>(R);
R = BOR->getSuperRegion();
@@ -1070,8 +1073,14 @@ RegionOffset MemRegion::getAsOffset() const {
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 @@ RegionOffset MemRegion::getAsOffset() const {
}
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 @@ RegionOffset MemRegion::getAsOffset() const {
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);
}
@@ -40,33 +40,42 @@ using llvm::Optional;
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 @@ class BindingKey {
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 @@ class BindingKey {
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 @@ RegionBindings RegionStoreManager::removeSubRegionBindings(RegionBindings B,
// 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);

0 comments on commit 824e07a

Please sign in to comment.