ExecutionState &BumpMergingSearcher::selectState() { entry: // out of base states, pick one to pop if (baseSearcher->empty()) { std::map<llvm::Instruction*, ExecutionState*>::iterator it = statesAtMerge.begin(); ExecutionState *es = it->second; statesAtMerge.erase(it); ++es->pc; baseSearcher->addState(es); } ExecutionState &es = baseSearcher->selectState(); if (Instruction *mp = getMergePoint(es)) { std::map<llvm::Instruction*, ExecutionState*>::iterator it = statesAtMerge.find(mp); baseSearcher->removeState(&es); if (it==statesAtMerge.end()) { statesAtMerge.insert(std::make_pair(mp, &es)); } else { ExecutionState *mergeWith = it->second; if (mergeWith->merge(es)) { // hack, because we are terminating the state we need to let // the baseSearcher know about it again baseSearcher->addState(&es); executor.terminateState(es); } else { it->second = &es; // the bump ++mergeWith->pc; baseSearcher->addState(mergeWith); } } goto entry; } else { return es; } }
ExecutionState &MergingSearcher::selectState() { while (!baseSearcher->empty()) { ExecutionState &es = baseSearcher->selectState(); if (getMergePoint(es)) { baseSearcher->removeState(&es, &es); statesAtMerge.insert(&es); } else { return es; } } // build map of merge point -> state list std::map<Instruction*, std::vector<ExecutionState*> > merges; for (std::set<ExecutionState*>::const_iterator it = statesAtMerge.begin(), ie = statesAtMerge.end(); it != ie; ++it) { ExecutionState &state = **it; Instruction *mp = getMergePoint(state); merges[mp].push_back(&state); } if (DebugLogMerge) std::cerr << "-- all at merge --\n"; for (std::map<Instruction*, std::vector<ExecutionState*> >::iterator it = merges.begin(), ie = merges.end(); it != ie; ++it) { if (DebugLogMerge) { std::cerr << "\tmerge: " << it->first << " ["; for (std::vector<ExecutionState*>::iterator it2 = it->second.begin(), ie2 = it->second.end(); it2 != ie2; ++it2) { ExecutionState *state = *it2; std::cerr << state << ", "; } std::cerr << "]\n"; } // merge states std::set<ExecutionState*> toMerge(it->second.begin(), it->second.end()); while (!toMerge.empty()) { ExecutionState *base = *toMerge.begin(); toMerge.erase(toMerge.begin()); std::set<ExecutionState*> toErase; for (std::set<ExecutionState*>::iterator it = toMerge.begin(), ie = toMerge.end(); it != ie; ++it) { ExecutionState *mergeWith = *it; if (base->merge(*mergeWith)) { toErase.insert(mergeWith); } } if (DebugLogMerge && !toErase.empty()) { std::cerr << "\t\tmerged: " << base << " with ["; for (std::set<ExecutionState*>::iterator it = toErase.begin(), ie = toErase.end(); it != ie; ++it) { if (it!=toErase.begin()) std::cerr << ", "; std::cerr << *it; } std::cerr << "]\n"; } for (std::set<ExecutionState*>::iterator it = toErase.begin(), ie = toErase.end(); it != ie; ++it) { std::set<ExecutionState*>::iterator it2 = toMerge.find(*it); assert(it2!=toMerge.end()); executor.terminateState(**it); toMerge.erase(it2); } // step past merge and toss base back in pool statesAtMerge.erase(statesAtMerge.find(base)); ++base->pc; baseSearcher->addState(base); } } if (DebugLogMerge) std::cerr << "-- merge complete, continuing --\n"; return selectState(); }