void Environment::print(raw_ostream &Out, const char *NL, const char *Sep) const { bool isFirst = true; for (Environment::iterator I = begin(), E = end(); I != E; ++I) { const EnvironmentEntry &En = I.getKey(); if (isFirst) { Out << NL << NL << "Expressions:" << NL; isFirst = false; } else { Out << NL; } const Stmt *S = En.getStmt(); Out << " (" << (const void*) En.getLocationContext() << ',' << (const void*) S << ") "; LangOptions LO; // FIXME. S->printPretty(Out, 0, PrintingPolicy(LO)); Out << " : " << I.getData(); } }
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; }
void GRState::print(llvm::raw_ostream& Out, const char* nl, const char* sep) const { // Print the store. GRStateManager &Mgr = getStateManager(); Mgr.getStoreManager().print(getStore(), Out, nl, sep); CFG &C = *getAnalysisContext().getCFG(); // Print Subexpression bindings. bool isFirst = true; for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { if (C.isBlkExpr(I.getKey())) continue; if (isFirst) { Out << nl << nl << "Sub-Expressions:" << nl; isFirst = false; } else { Out << nl; } Out << " (" << (void*) I.getKey() << ") "; LangOptions LO; // FIXME. I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); Out << " : " << I.getData(); } // Print block-expression bindings. isFirst = true; for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { if (!C.isBlkExpr(I.getKey())) continue; if (isFirst) { Out << nl << nl << "Block-level Expressions:" << nl; isFirst = false; } else { Out << nl; } Out << " (" << (void*) I.getKey() << ") "; LangOptions LO; // FIXME. I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); Out << " : " << I.getData(); } Mgr.getConstraintManager().print(this, Out, nl, sep); // Print checker-specific data. for (std::vector<Printer*>::iterator I = Mgr.Printers.begin(), E = Mgr.Printers.end(); I != E; ++I) { (*I)->Print(Out, this, nl, sep); } }
// 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; }
void Environment::printAux(raw_ostream &Out, bool printLocations, const char *NL, const char *Sep) const{ bool isFirst = true; for (Environment::iterator I = begin(), E = end(); I != E; ++I) { const EnvironmentEntry &En = I.getKey(); if (IsLocation(En)) { if (!printLocations) continue; } else { if (printLocations) continue; } if (isFirst) { Out << NL << NL << (printLocations ? "Load/Store locations:" : "Expressions:") << NL; isFirst = false; } else { Out << NL; } const Stmt *S = En.getStmt(); if (printLocations) { S = (Stmt*) (((uintptr_t) S) & ((uintptr_t) ~0x1)); } Out << " (" << (void*) En.getLocationContext() << ',' << (void*) S << ") "; LangOptions LO; // FIXME. S->printPretty(Out, 0, PrintingPolicy(LO)); Out << " : " << I.getData(); } }
// 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; }
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; }
void ProgramState::print(raw_ostream &Out, CFG &C, const char *NL, const char *Sep) const { // Print the store. ProgramStateManager &Mgr = getStateManager(); Mgr.getStoreManager().print(getStore(), Out, NL, Sep); // Print Subexpression bindings. bool isFirst = true; // FIXME: All environment printing should be moved inside Environment. for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { if (C.isBlkExpr(I.getKey()) || IsEnvLoc(I.getKey())) continue; if (isFirst) { Out << NL << NL << "Sub-Expressions:" << NL; isFirst = false; } else { Out << NL; } Out << " (" << (void*) I.getKey() << ") "; LangOptions LO; // FIXME. I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); Out << " : " << I.getData(); } // Print block-expression bindings. isFirst = true; for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { if (!C.isBlkExpr(I.getKey())) continue; if (isFirst) { Out << NL << NL << "Block-level Expressions:" << NL; isFirst = false; } else { Out << NL; } Out << " (" << (void*) I.getKey() << ") "; LangOptions LO; // FIXME. I.getKey()->printPretty(Out, 0, PrintingPolicy(LO)); Out << " : " << I.getData(); } // Print locations. isFirst = true; for (Environment::iterator I = Env.begin(), E = Env.end(); I != E; ++I) { if (!IsEnvLoc(I.getKey())) continue; if (isFirst) { Out << NL << NL << "Load/store locations:" << NL; isFirst = false; } else { Out << NL; } const Stmt *S = (Stmt*) (((uintptr_t) I.getKey()) & ((uintptr_t) ~0x1)); Out << " (" << (void*) S << ") "; LangOptions LO; // FIXME. S->printPretty(Out, 0, PrintingPolicy(LO)); Out << " : " << I.getData(); } Mgr.getConstraintManager().print(this, Out, NL, Sep); // Print checker-specific data. Mgr.getOwningEngine()->printState(Out, this, NL, Sep); }
// 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; }