diff options
Diffstat (limited to 'lib/Analysis/RegionStore.cpp')
-rw-r--r-- | lib/Analysis/RegionStore.cpp | 138 |
1 files changed, 131 insertions, 7 deletions
diff --git a/lib/Analysis/RegionStore.cpp b/lib/Analysis/RegionStore.cpp index 006b613528..f2410643fd 100644 --- a/lib/Analysis/RegionStore.cpp +++ b/lib/Analysis/RegionStore.cpp @@ -52,6 +52,17 @@ template<> struct GRStateTrait<RegionExtentsTy> }; } +// KillSet GDM stuff. +typedef llvm::ImmutableSet<const MemRegion*> RegionKillSetTy; +static int RegionKillSetTyIndex = 0; +namespace clang { + template<> struct GRStateTrait<RegionKillSetTy> + : public GRStatePartialTrait<RegionKillSetTy> { + static void* GDMIndex() { return &RegionKillSetTyIndex; } + }; +} + + namespace { class VISIBILITY_HIDDEN RegionStoreManager : public StoreManager { @@ -116,10 +127,15 @@ public: assert (false && "Not implemented."); return 0; } - + + /// RemoveDeadBindings - Scans a RegionStore for dead values. It returns + /// a new Store with these values removed, and populates LSymbols and + /// DSymbols with the known set of live and dead symbols respectively. Store RemoveDeadBindings(Store store, Stmt* Loc, const LiveVariables& Live, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots, LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols); + + void UpdateLiveSymbols(SVal X, LiveSymbolsTy& LSymbols); Store BindDecl(Store store, const VarDecl* VD, SVal* InitVal, unsigned Count); @@ -605,22 +621,130 @@ const GRState* RegionStoreManager::setExtent(const GRState* St, } +void RegionStoreManager::UpdateLiveSymbols(SVal X, LiveSymbolsTy& LSymbols) { + for (SVal::symbol_iterator SI=X.symbol_begin(),SE=X.symbol_end();SI!=SE;++SI) + LSymbols.insert(*SI); +} + Store RegionStoreManager::RemoveDeadBindings(Store store, Stmt* Loc, const LiveVariables& Live, llvm::SmallVectorImpl<const MemRegion*>& RegionRoots, LiveSymbolsTy& LSymbols, DeadSymbolsTy& DSymbols) { RegionBindingsTy B = GetRegionBindings(store); - typedef SVal::symbol_iterator symbol_iterator; + + // Lazily constructed backmap from MemRegions to SubRegions. + typedef llvm::ImmutableSet<const MemRegion*> SubRegionsTy; + typedef llvm::ImmutableMap<const MemRegion*, SubRegionsTy> SubRegionsMapTy; + + // FIXME: As a future optimization we can modifiy BumpPtrAllocator to have + // the ability to reuse memory. This way we can keep TmpAlloc around as + // an instance variable of RegionStoreManager (avoiding repeated malloc + // overhead). + llvm::BumpPtrAllocator TmpAlloc; + + // Factory objects. + SubRegionsMapTy::Factory SubRegMapF(TmpAlloc); + SubRegionsTy::Factory SubRegF(TmpAlloc); + + // The backmap from regions to subregions. + SubRegionsMapTy SubRegMap = SubRegMapF.GetEmptyMap(); + + // Do a pass over the regions in the store. For VarRegions we check if + // the variable is still live and if so add it to the list of live roots. + // For other regions we populate our region backmap. + for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { + const MemRegion* R = I.getKey(); + if (const VarRegion* VR = dyn_cast<VarRegion>(R)) { + if (Live.isLive(Loc, VR->getDecl())) + RegionRoots.push_back(VR); // This is a live "root". + } + else { + // Get the super region for R. + const MemRegion* SuperR = cast<SubRegion>(R)->getSuperRegion(); + // Get the current set of subregions for SuperR. + const SubRegionsTy* SRptr = SubRegMap.lookup(SuperR); + SubRegionsTy SR = SRptr ? *SRptr : SubRegF.GetEmptySet(); + // Add R to the subregions of SuperR. + SubRegMap = SubRegMapF.Add(SubRegMap, SuperR, SubRegF.Add(SR, R)); + + // Finally, check if SuperR is a VarRegion. We need to do this + // to also mark SuperR as a root (as it may not have a value directly + // bound to it in the store). + if (const VarRegion* VR = dyn_cast<VarRegion>(SuperR)) { + if (Live.isLive(Loc, VR->getDecl())) + RegionRoots.push_back(VR); // This is a live "root". + } + } + } + + // Process the worklist of RegionRoots. This performs a "mark-and-sweep" + // of the store. We want to find all live symbols and dead regions. + llvm::SmallPtrSet<const MemRegion*, 10> Marked; + + while (!RegionRoots.empty()) { + // Dequeue the next region on the worklist. + const MemRegion* R = RegionRoots.back(); + RegionRoots.pop_back(); - // FIXME: Mark all region binding value's symbol as live. We also omit symbols - // in SymbolicRegions. + // Check if we have already processed this region. + if (Marked.count(R)) continue; + + // Mark this region as processed. This is needed for termination in case + // a region is referenced more than once. + Marked.insert(R); + + // Mark the symbol for any live SymbolicRegion as "live". This means we + // should continue to track that symbol. + if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R)) + LSymbols.insert(SymR->getSymbol()); + + // Get the data binding for R (if any). + RegionBindingsTy::data_type* Xptr = B.lookup(R); + if (Xptr) { + SVal X = *Xptr; + UpdateLiveSymbols(X, LSymbols); // Update the set of live symbols. + + // If X is a region, then add it the RegionRoots. + if (loc::MemRegionVal* RegionX = dyn_cast<loc::MemRegionVal>(&X)) + RegionRoots.push_back(RegionX->getRegion()); + } + + // Get the subregions of R. These are RegionRoots as well since they + // represent values that are also bound to R. + const SubRegionsTy* SRptr = SubRegMap.lookup(R); + if (!SRptr) continue; + SubRegionsTy SR = *SRptr; + + for (SubRegionsTy::iterator I=SR.begin(), E=SR.end(); I!=E; ++I) + RegionRoots.push_back(*I); + } + + // We have now scanned the store, marking reachable regions and symbols + // as live. We now remove all the regions that are dead from the store + // as well as update DSymbols with the set symbols that are now dead. + for (RegionBindingsTy::iterator I = B.begin(), E = B.end(); I != E; ++I) { + const MemRegion* R = I.getKey(); + + // If this region live? Is so, none of its symbols are dead. + if (Marked.count(R)) + continue; + + // Remove this dead region from the store. + store = Remove(store, loc::MemRegionVal(R)); + + // Mark all non-live symbols that this region references as dead. + if (const SymbolicRegion* SymR = dyn_cast<SymbolicRegion>(R)) { + SymbolID Sym = SymR->getSymbol(); + if (!LSymbols.count(Sym)) DSymbols.insert(Sym); + } + SVal X = I.getData(); - for (symbol_iterator SI=X.symbol_begin(), SE=X.symbol_end(); SI!=SE; ++SI) - LSymbols.insert(*SI); + SVal::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); + for (; SI != SE; ++SI) { if (!LSymbols.count(*SI)) DSymbols.insert(*SI); } } - + return store; } |