summaryrefslogtreecommitdiffstats
path: root/lib/Checker/SymbolManager.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Checker/SymbolManager.cpp')
-rw-r--r--lib/Checker/SymbolManager.cpp139
1 files changed, 109 insertions, 30 deletions
diff --git a/lib/Checker/SymbolManager.cpp b/lib/Checker/SymbolManager.cpp
index c2b557e..3b1bb6d 100644
--- a/lib/Checker/SymbolManager.cpp
+++ b/lib/Checker/SymbolManager.cpp
@@ -28,22 +28,22 @@ static void print(llvm::raw_ostream& os, BinaryOperator::Opcode Op) {
default:
assert(false && "operator printing not implemented");
break;
- case BinaryOperator::Mul: os << '*' ; break;
- case BinaryOperator::Div: os << '/' ; break;
- case BinaryOperator::Rem: os << '%' ; break;
- case BinaryOperator::Add: os << '+' ; break;
- case BinaryOperator::Sub: os << '-' ; break;
- case BinaryOperator::Shl: os << "<<" ; break;
- case BinaryOperator::Shr: os << ">>" ; break;
- case BinaryOperator::LT: os << "<" ; break;
- case BinaryOperator::GT: os << '>' ; break;
- case BinaryOperator::LE: os << "<=" ; break;
- case BinaryOperator::GE: os << ">=" ; break;
- case BinaryOperator::EQ: os << "==" ; break;
- case BinaryOperator::NE: os << "!=" ; break;
- case BinaryOperator::And: os << '&' ; break;
- case BinaryOperator::Xor: os << '^' ; break;
- case BinaryOperator::Or: os << '|' ; break;
+ case BO_Mul: os << '*' ; break;
+ case BO_Div: os << '/' ; break;
+ case BO_Rem: os << '%' ; break;
+ case BO_Add: os << '+' ; break;
+ case BO_Sub: os << '-' ; break;
+ case BO_Shl: os << "<<" ; break;
+ case BO_Shr: os << ">>" ; break;
+ case BO_LT: os << "<" ; break;
+ case BO_GT: os << '>' ; break;
+ case BO_LE: os << "<=" ; break;
+ case BO_GE: os << ">=" ; break;
+ case BO_EQ: os << "==" ; break;
+ case BO_NE: os << "!=" ; break;
+ case BO_And: os << '&' ; break;
+ case BO_Xor: os << '^' ; break;
+ case BO_Or: os << '|' ; break;
}
}
@@ -78,6 +78,11 @@ void SymbolExtent::dumpToStream(llvm::raw_ostream& os) const {
os << "extent_$" << getSymbolID() << '{' << getRegion() << '}';
}
+void SymbolMetadata::dumpToStream(llvm::raw_ostream& os) const {
+ os << "meta_$" << getSymbolID() << '{'
+ << getRegion() << ',' << T.getAsString() << '}';
+}
+
void SymbolRegionValue::dumpToStream(llvm::raw_ostream& os) const {
os << "reg_$" << getSymbolID() << "<" << R << ">";
}
@@ -150,6 +155,24 @@ SymbolManager::getExtentSymbol(const SubRegion *R) {
return cast<SymbolExtent>(SD);
}
+const SymbolMetadata*
+SymbolManager::getMetadataSymbol(const MemRegion* R, const Stmt* S, QualType T,
+ unsigned Count, const void* SymbolTag) {
+
+ llvm::FoldingSetNodeID profile;
+ SymbolMetadata::Profile(profile, R, S, T, Count, SymbolTag);
+ void* InsertPos;
+ SymExpr *SD = DataSet.FindNodeOrInsertPos(profile, InsertPos);
+ if (!SD) {
+ SD = (SymExpr*) BPAlloc.Allocate<SymbolMetadata>();
+ new (SD) SymbolMetadata(SymbolCounter, R, S, T, Count, SymbolTag);
+ DataSet.InsertNode(SD, InsertPos);
+ ++SymbolCounter;
+ }
+
+ return cast<SymbolMetadata>(SD);
+}
+
const SymIntExpr *SymbolManager::getSymIntExpr(const SymExpr *lhs,
BinaryOperator::Opcode op,
const llvm::APSInt& v,
@@ -191,21 +214,34 @@ QualType SymbolConjured::getType(ASTContext&) const {
}
QualType SymbolDerived::getType(ASTContext& Ctx) const {
- return R->getValueType(Ctx);
+ return R->getValueType();
}
QualType SymbolExtent::getType(ASTContext& Ctx) const {
return Ctx.getSizeType();
}
+QualType SymbolMetadata::getType(ASTContext&) const {
+ return T;
+}
+
QualType SymbolRegionValue::getType(ASTContext& C) const {
- return R->getValueType(C);
+ return R->getValueType();
}
SymbolManager::~SymbolManager() {}
bool SymbolManager::canSymbolicate(QualType T) {
- return Loc::IsLocType(T) || (T->isIntegerType() && T->isScalarType());
+ if (Loc::IsLocType(T))
+ return true;
+
+ if (T->isIntegerType())
+ return T->isScalarType();
+
+ if (T->isRecordType())
+ return true;
+
+ return false;
}
void SymbolReaper::markLive(SymbolRef sym) {
@@ -213,6 +249,11 @@ void SymbolReaper::markLive(SymbolRef sym) {
TheDead.erase(sym);
}
+void SymbolReaper::markInUse(SymbolRef sym) {
+ if (isa<SymbolMetadata>(sym))
+ MetadataInUse.insert(sym);
+}
+
bool SymbolReaper::maybeDead(SymbolRef sym) {
if (isLive(sym))
return false;
@@ -221,6 +262,31 @@ bool SymbolReaper::maybeDead(SymbolRef sym) {
return true;
}
+static bool IsLiveRegion(SymbolReaper &Reaper, const MemRegion *MR) {
+ MR = MR->getBaseRegion();
+
+ if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(MR))
+ return Reaper.isLive(SR->getSymbol());
+
+ if (const VarRegion *VR = dyn_cast<VarRegion>(MR))
+ return Reaper.isLive(VR);
+
+ // FIXME: This is a gross over-approximation. What we really need is a way to
+ // tell if anything still refers to this region. Unlike SymbolicRegions,
+ // AllocaRegions don't have associated symbols, though, so we don't actually
+ // have a way to track their liveness.
+ if (isa<AllocaRegion>(MR))
+ return true;
+
+ if (isa<CXXThisRegion>(MR))
+ return true;
+
+ if (isa<MemSpaceRegion>(MR))
+ return true;
+
+ return false;
+}
+
bool SymbolReaper::isLive(SymbolRef sym) {
if (TheLiving.count(sym))
return true;
@@ -234,11 +300,21 @@ bool SymbolReaper::isLive(SymbolRef sym) {
}
if (const SymbolExtent *extent = dyn_cast<SymbolExtent>(sym)) {
- const MemRegion *Base = extent->getRegion()->getBaseRegion();
- if (const VarRegion *VR = dyn_cast<VarRegion>(Base))
- return isLive(VR);
- if (const SymbolicRegion *SR = dyn_cast<SymbolicRegion>(Base))
- return isLive(SR->getSymbol());
+ if (IsLiveRegion(*this, extent->getRegion())) {
+ markLive(sym);
+ return true;
+ }
+ return false;
+ }
+
+ if (const SymbolMetadata *metadata = dyn_cast<SymbolMetadata>(sym)) {
+ if (MetadataInUse.count(sym)) {
+ if (IsLiveRegion(*this, metadata->getRegion())) {
+ markLive(sym);
+ MetadataInUse.erase(sym);
+ return true;
+ }
+ }
return false;
}
@@ -248,16 +324,19 @@ bool SymbolReaper::isLive(SymbolRef sym) {
}
bool SymbolReaper::isLive(const Stmt* ExprVal) const {
- return LCtx->getLiveVariables()->isLive(Loc, ExprVal);
+ return LCtx->getAnalysisContext()->getRelaxedLiveVariables()->
+ isLive(Loc, ExprVal);
}
bool SymbolReaper::isLive(const VarRegion *VR) const {
- const StackFrameContext *SFC = VR->getStackFrame();
+ const StackFrameContext *VarContext = VR->getStackFrame();
+ const StackFrameContext *CurrentContext = LCtx->getCurrentStackFrame();
+
+ if (VarContext == CurrentContext)
+ return LCtx->getAnalysisContext()->getRelaxedLiveVariables()->
+ isLive(Loc, VR->getDecl());
- if (SFC == LCtx->getCurrentStackFrame())
- return LCtx->getLiveVariables()->isLive(Loc, VR->getDecl());
- else
- return SFC->isParentOf(LCtx->getCurrentStackFrame());
+ return VarContext->isParentOf(CurrentContext);
}
SymbolVisitor::~SymbolVisitor() {}
OpenPOWER on IntegriCloud