Environment EnvironmentManager::RemoveDeadBindings(Environment Env, const Stmt *S, SymbolReaper &SymReaper, const GRState *ST, llvm::SmallVectorImpl<const MemRegion*> &DRoots) { CFG &C = *Env.getAnalysisContext().getCFG(); // We construct a new Environment object entirely, as this is cheaper than // individually removing all the subexpression bindings (which will greatly // outnumber block-level expression bindings). Environment NewEnv = getInitialEnvironment(&Env.getAnalysisContext()); // Iterate over the block-expr bindings. for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { const Stmt *BlkExpr = I.getKey(); // Not a block-level expression? if (!C.isBlkExpr(BlkExpr)) continue; const SVal &X = I.getData(); if (SymReaper.isLive(S, BlkExpr)) { // Copy the binding to the new map. NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X); // If the block expr's value is a memory region, then mark that region. if (isa<loc::MemRegionVal>(X)) { const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); DRoots.push_back(R); // Mark the super region of the RX as live. // e.g.: int x; char *y = (char*) &x; if (*y) ... // 'y' => element region. 'x' is its super region. // We only add one level super region for now. // FIXME: maybe multiple level of super regions should be added. if (const SubRegion *SR = dyn_cast<SubRegion>(R)) DRoots.push_back(SR->getSuperRegion()); } // Mark all symbols in the block expr's value live. MarkLiveCallback cb(SymReaper); ST->scanReachableSymbols(X, cb); continue; } // Otherwise the expression is dead with a couple exceptions. // Do not misclean LogicalExpr or ConditionalOperator. It is dead at the // beginning of itself, but we need its UndefinedVal to determine its // SVal. if (X.isUndef() && cast<UndefinedVal>(X).getData()) NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X); } return NewEnv; }
// removeDeadBindings: // - Remove subexpression bindings. // - Remove dead block expression bindings. // - Keep live block expression bindings: // - Mark their reachable symbols live in SymbolReaper, // see ScanReachableSymbols. // - Mark the region in DRoots if the binding is a loc::MemRegionVal. Environment EnvironmentManager::removeDeadBindings(Environment Env, SymbolReaper &SymReaper, ProgramStateRef ST) { // We construct a new Environment object entirely, as this is cheaper than // individually removing all the subexpression bindings (which will greatly // outnumber block-level expression bindings). Environment NewEnv = getInitialEnvironment(); MarkLiveCallback CB(SymReaper); ScanReachableSymbols RSScaner(ST, CB); llvm::ImmutableMapRef<EnvironmentEntry,SVal> EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(), F.getTreeFactory()); // Iterate over the block-expr bindings. for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { const EnvironmentEntry &BlkExpr = I.getKey(); const SVal &X = I.getData(); if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) { // Copy the binding to the new map. EBMapRef = EBMapRef.add(BlkExpr, X); // If the block expr's value is a memory region, then mark that region. if (Optional<loc::MemRegionVal> R = X.getAs<loc::MemRegionVal>()) SymReaper.markLive(R->getRegion()); // Mark all symbols in the block expr's value live. RSScaner.scan(X); continue; } else { SymExpr::symbol_iterator SI = X.symbol_begin(), SE = X.symbol_end(); for (; SI != SE; ++SI) SymReaper.maybeDead(*SI); } } NewEnv.ExprBindings = EBMapRef.asImmutableMap(); return NewEnv; }
Environment EnvironmentManager::RemoveDeadBindings(Environment Env, SymbolReaper &SymReaper, const GRState *ST, llvm::SmallVectorImpl<const MemRegion*> &DRoots) { CFG &C = *SymReaper.getLocationContext()->getCFG(); // We construct a new Environment object entirely, as this is cheaper than // individually removing all the subexpression bindings (which will greatly // outnumber block-level expression bindings). Environment NewEnv = getInitialEnvironment(); // Iterate over the block-expr bindings. for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { const Stmt *BlkExpr = I.getKey(); const SVal &X = I.getData(); // Block-level expressions in callers are assumed always live. if (isBlockExprInCallers(BlkExpr, SymReaper.getLocationContext())) { NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X); if (isa<loc::MemRegionVal>(X)) { const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); DRoots.push_back(R); } // Mark all symbols in the block expr's value live. MarkLiveCallback cb(SymReaper); ST->scanReachableSymbols(X, cb); continue; } // Not a block-level expression? if (!C.isBlkExpr(BlkExpr)) continue; if (SymReaper.isLive(BlkExpr)) { // Copy the binding to the new map. NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X); // If the block expr's value is a memory region, then mark that region. if (isa<loc::MemRegionVal>(X)) { const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); DRoots.push_back(R); } // Mark all symbols in the block expr's value live. MarkLiveCallback cb(SymReaper); ST->scanReachableSymbols(X, cb); continue; } // Otherwise the expression is dead with a couple exceptions. // Do not misclean LogicalExpr or ConditionalOperator. It is dead at the // beginning of itself, but we need its UndefinedVal to determine its // SVal. if (X.isUndef() && cast<UndefinedVal>(X).getData()) NewEnv.ExprBindings = F.Add(NewEnv.ExprBindings, BlkExpr, X); } return NewEnv; }
// removeDeadBindings: // - Remove subexpression bindings. // - Remove dead block expression bindings. // - Keep live block expression bindings: // - Mark their reachable symbols live in SymbolReaper, // see ScanReachableSymbols. // - Mark the region in DRoots if the binding is a loc::MemRegionVal. Environment EnvironmentManager::removeDeadBindings(Environment Env, SymbolReaper &SymReaper, const ProgramState *ST) { // We construct a new Environment object entirely, as this is cheaper than // individually removing all the subexpression bindings (which will greatly // outnumber block-level expression bindings). Environment NewEnv = getInitialEnvironment(); SmallVector<std::pair<EnvironmentEntry, SVal>, 10> deferredLocations; MarkLiveCallback CB(SymReaper); ScanReachableSymbols RSScaner(ST, CB); llvm::ImmutableMapRef<EnvironmentEntry,SVal> EBMapRef(NewEnv.ExprBindings.getRootWithoutRetain(), F.getTreeFactory()); // Iterate over the block-expr bindings. for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { const EnvironmentEntry &BlkExpr = I.getKey(); // For recorded locations (used when evaluating loads and stores), we // consider them live only when their associated normal expression is // also live. // NOTE: This assumes that loads/stores that evaluated to UnknownVal // still have an entry in the map. if (IsLocation(BlkExpr)) { deferredLocations.push_back(std::make_pair(BlkExpr, I.getData())); continue; } const SVal &X = I.getData(); if (SymReaper.isLive(BlkExpr.getStmt(), BlkExpr.getLocationContext())) { // Copy the binding to the new map. EBMapRef = EBMapRef.add(BlkExpr, X); // If the block expr's value is a memory region, then mark that region. if (isa<loc::MemRegionVal>(X)) { const MemRegion *R = cast<loc::MemRegionVal>(X).getRegion(); SymReaper.markLive(R); } // Mark all symbols in the block expr's value live. RSScaner.scan(X); continue; } // Otherwise the expression is dead with a couple exceptions. // Do not misclean LogicalExpr or ConditionalOperator. It is dead at the // beginning of itself, but we need its UndefinedVal to determine its // SVal. if (X.isUndef() && cast<UndefinedVal>(X).getData()) EBMapRef = EBMapRef.add(BlkExpr, X); } // Go through he deferred locations and add them to the new environment if // the correspond Stmt* is in the map as well. for (SmallVectorImpl<std::pair<EnvironmentEntry, SVal> >::iterator I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) { const EnvironmentEntry &En = I->first; const Stmt *S = (Stmt*) (((uintptr_t) En.getStmt()) & (uintptr_t) ~0x1); if (EBMapRef.lookup(EnvironmentEntry(S, En.getLocationContext()))) EBMapRef = EBMapRef.add(En, I->second); } NewEnv.ExprBindings = EBMapRef.asImmutableMap(); return NewEnv; }
// removeDeadBindings: // - Remove subexpression bindings. // - Remove dead block expression bindings. // - Keep live block expression bindings: // - Mark their reachable symbols live in SymbolReaper, // see ScanReachableSymbols. // - Mark the region in DRoots if the binding is a loc::MemRegionVal. Environment EnvironmentManager::removeDeadBindings(Environment Env, SymbolReaper &SymReaper, const GRState *ST, llvm::SmallVectorImpl<const MemRegion*> &DRoots) { CFG &C = *SymReaper.getLocationContext()->getCFG(); // We construct a new Environment object entirely, as this is cheaper than // individually removing all the subexpression bindings (which will greatly // outnumber block-level expression bindings). Environment NewEnv = getInitialEnvironment(); llvm::SmallVector<std::pair<const Stmt*, SVal>, 10> deferredLocations; // Iterate over the block-expr bindings. for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { const Stmt *BlkExpr = I.getKey(); // For recorded locations (used when evaluating loads and stores), we // consider them live only when their associated normal expression is // also live. // NOTE: This assumes that loads/stores that evaluated to UnknownVal // still have an entry in the map. if (IsLocation(BlkExpr)) { deferredLocations.push_back(std::make_pair(BlkExpr, I.getData())); continue; } const SVal &X = I.getData(); // Block-level expressions in callers are assumed always live. if (isBlockExprInCallers(BlkExpr, SymReaper.getLocationContext())) { NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, BlkExpr, X); if (isa<loc::MemRegionVal>(X)) { const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); DRoots.push_back(R); } // Mark all symbols in the block expr's value live. MarkLiveCallback cb(SymReaper); ST->scanReachableSymbols(X, cb); continue; } // Not a block-level expression? if (!C.isBlkExpr(BlkExpr)) continue; if (SymReaper.isLive(BlkExpr)) { // Copy the binding to the new map. NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, BlkExpr, X); // If the block expr's value is a memory region, then mark that region. if (isa<loc::MemRegionVal>(X)) { const MemRegion* R = cast<loc::MemRegionVal>(X).getRegion(); DRoots.push_back(R); } // Mark all symbols in the block expr's value live. MarkLiveCallback cb(SymReaper); ST->scanReachableSymbols(X, cb); continue; } // Otherwise the expression is dead with a couple exceptions. // Do not misclean LogicalExpr or ConditionalOperator. It is dead at the // beginning of itself, but we need its UndefinedVal to determine its // SVal. if (X.isUndef() && cast<UndefinedVal>(X).getData()) NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, BlkExpr, X); } // Go through he deferred locations and add them to the new environment if // the correspond Stmt* is in the map as well. for (llvm::SmallVectorImpl<std::pair<const Stmt*, SVal> >::iterator I = deferredLocations.begin(), E = deferredLocations.end(); I != E; ++I) { const Stmt *S = (Stmt*) (((uintptr_t) I->first) & (uintptr_t) ~0x1); if (NewEnv.ExprBindings.lookup(S)) NewEnv.ExprBindings = F.add(NewEnv.ExprBindings, I->first, I->second); } return NewEnv; }