void World::GetPersistentData(std::vector<PersistentDataItem> *vec, const std::string &key, bool prefix) { vec->clear(); if (!BuildPersistentCache()) return; auto eqrange = persistent_index.equal_range(key); if (prefix) { if (key.empty()) { eqrange.first = persistent_index.begin(); eqrange.second = persistent_index.end(); } else { std::string bound = key; if (bound[bound.size()-1] != '/') bound += "/"; eqrange.first = persistent_index.lower_bound(bound); bound[bound.size()-1]++; eqrange.second = persistent_index.lower_bound(bound); } } for (auto it = eqrange.first; it != eqrange.second; ++it) { auto hfig = df::historical_figure::find(-it->second); if (hfig && hfig->name.has_name) vec->push_back(dataFromHFig(hfig)); } }
std::vector<std::multimap<ReducedFraction, MidiChord>::const_iterator> findChordsForTimeRange( int voice, const ReducedFraction &onTime, const ReducedFraction &offTime, const std::multimap<ReducedFraction, MidiChord> &chords, const ReducedFraction &maxChordLength) { std::vector<std::multimap<ReducedFraction, MidiChord>::const_iterator> result; if (chords.empty()) return result; auto it = chords.lower_bound(offTime); if (it == chords.begin()) return result; --it; while (it->first + maxChordLength > onTime) { const MidiChord &chord = it->second; if (chord.voice == voice) { const auto chordInterval = std::make_pair(it->first, maxNoteOffTime(chord.notes)); const auto durationInterval = std::make_pair(onTime, offTime); if (MidiTuplet::haveIntersection(chordInterval, durationInterval)) result.push_back(it); } if (it == chords.begin()) break; --it; } return result; }
void __stdcall GFGoodSell(const struct SGFGoodSellInfo &gsi, unsigned int iClientID) { returncode = DEFAULT_RETURNCODE; uint iBase; pub::Player::GetBase(iClientID, iBase); multimap<uint, CARGO_MISSION>::iterator start = set_mapCargoMissions.lower_bound(iBase); multimap<uint, CARGO_MISSION>::iterator end = set_mapCargoMissions.upper_bound(iBase); for (; start != end; ++start) { if (start->second.item == gsi.iArchID) { if (start->second.curr_amount < start->second.required_amount) { int needed = start->second.required_amount - start->second.curr_amount; if (needed > gsi.iCount) { start->second.curr_amount += gsi.iCount; needed = start->second.required_amount - start->second.curr_amount; PrintUserCmdText(iClientID, L"%d units remaining to complete mission objective", needed); } else { PrintUserCmdText(iClientID, L"Mission objective completed",needed); } } } } }
void *MemoryPool::pop(size_t s, int loc) { void *addr = nullptr; if ((s > MIN_BLOCK_SIZE) && (s < MAX_BLOCK_SIZE)) { locker_.lock(); // find MemoryPool block which is not smaller than demand size auto pt = pool_.lower_bound(s); if (pt != pool_.end()) { size_t ts = 0; std::tie(ts, addr) = *pt; if (ts < s * 2) { s = ts; pool_.erase(pt); pool_depth_ -= s; } else { addr = nullptr; } } locker_.unlock(); } if (addr == nullptr) { try { #ifdef __CUDA__ SP_DEVICE_CALL(cudaMallocManaged(&addr, s)); #else addr = malloc(s); #endif } catch (std::bad_alloc const &error) { THROW_EXCEPTION_BAD_ALLOC(s); } } return addr; }
void search(const std::string &now, const std::string &end, const std::vector<std::string> &path, const std::multimap<std::string, std::string> &word_map, std::vector<std::vector<std::string> > &ans, int min_size) { if (now == end) { ans.push_back(path); if (path.size() < min_size) { min_size = path.size(); } return; } if (path.size() > min_size) { return; } std::multimap<std::string, std::string>::const_iterator low = word_map.lower_bound(now); std::multimap<std::string, std::string>::const_iterator up = word_map.upper_bound(now); for (std::multimap<std::string, std::string>::const_iterator it = low; it != up; ++ it) { if (std::find(path.begin(), path.end(), it->second) == path.end()) { std::vector<std::string> mypath = path; mypath.push_back(it->second); search(it->second, end, mypath, word_map, ans, min_size); } } }
static void LoadLadspaEffect(wxSortedArrayString &uniq, wxString fname, DL_Array &dls) { wxLogNull logNo; LADSPA_Descriptor_Function mainFn = NULL; // Since we now have builtin VST support, ignore the VST bridge as it // causes duplicate menu entries to appear. wxFileName f(fname); if (f.GetName().CmpNoCase(wxT("vst-bridge")) == 0) { return; } // As a courtesy to some plug-ins that might be bridges to // open other plug-ins, we set the current working // directory to be the plug-in's directory. wxString saveOldCWD = ::wxGetCwd(); wxString prefix = ::wxPathOnly(fname); ::wxSetWorkingDirectory(prefix); wxDynamicLibrary* pDLL = new wxDynamicLibrary(); dls.push_back(pDLL); if (pDLL && pDLL->Load(fname, wxDL_LAZY)) { mainFn = (LADSPA_Descriptor_Function)(pDLL->GetSymbol(wxT(descriptorFnName))); } if (mainFn) { int index = 0; const LADSPA_Descriptor *data; data = mainFn(index); while(data) { wxString uniqid = wxString::Format(wxT("%08x-%s"), data->UniqueID, LAT1CTOWX(data->Label).c_str()); if (uniq.Index(uniqid) == wxNOT_FOUND) { uniq.Add(uniqid); std::set<wxString> categories; #if defined(USE_LIBLRDF) && defined(EFFECT_CATEGORIES) std::multimap<unsigned long, wxString>::const_iterator iter; iter = gPluginCategories.lower_bound(data->UniqueID); for ( ; (iter != gPluginCategories.end() && iter->first == data->UniqueID); ++iter) categories.insert(iter->second); #endif LadspaEffect *effect = new LadspaEffect(data, categories); EffectManager::Get().RegisterEffect(effect); } // Get next plugin index++; data = mainFn(index); } } ::wxSetWorkingDirectory(saveOldCWD); }
int query(float min_price, float max_price, time_t min_timestamp, time_t max_timestamp) { std::multimap<float, Row*>::iterator it1 = price_row_mulmap.lower_bound(min_price); std::multimap<float, Row*>::iterator it2 = price_row_mulmap.upper_bound(max_price); int count = 0; for(; it1 != it2; it1++) { if(it1->second->timestamp >= min_timestamp && it1->second->timestamp <= max_timestamp) count++; } return count; }
std::multimap<ReducedFraction, MidiChord>::const_iterator findFirstChordInRange(const std::multimap<ReducedFraction, MidiChord> &chords, const ReducedFraction &startRangeTick, const ReducedFraction &endRangeTick) { auto iter = chords.lower_bound(startRangeTick); if (iter != chords.end() && iter->first >= endRangeTick) iter = chords.end(); return iter; }
// starting form a list of elements, returns // lists of lists that are all simply connected static void recur_connect_e (const MEdge &e, std::multimap<MEdge,MElement*,Less_Edge> &e2e, std::set<MElement*> &group, std::set<MEdge,Less_Edge> &touched){ if (touched.find(e) != touched.end())return; touched.insert(e); for (std::multimap <MEdge,MElement*,Less_Edge>::iterator it = e2e.lower_bound(e); it != e2e.upper_bound(e) ; ++it){ group.insert(it->second); for (int i=0;i<it->second->getNumEdges();++i){ recur_connect_e (it->second->getEdge(i),e2e,group,touched); } } }
void checkOptions(const DeckKeyword& keyword, std::multimap<std::string , PartiallySupported<T> >& map, const ParseContext& parseContext, ErrorGuard& errorGuard) { // check for partially supported keywords. typename std::multimap<std::string, PartiallySupported<T> >::iterator it, itlow, itup; itlow = map.lower_bound(keyword.name()); itup = map.upper_bound(keyword.name()); for (it = itlow; it != itup; ++it) { const auto& record = keyword.getRecord(0); if (record.getItem(it->second.item).template get<T>(0) != it->second.item_value) { std::string msg = "For keyword '" + it->first + "' only value " + boost::lexical_cast<std::string>(it->second.item_value) + " in item " + it->second.item + " is supported by flow.\n" + "In file " + keyword.getFileName() + ", line " + std::to_string(keyword.getLineNumber()) + "\n"; parseContext.handleError(ParseContext::SIMULATOR_KEYWORD_ITEM_NOT_SUPPORTED, msg, errorGuard); } } }
static void recur_connect(MVertex *v, std::multimap<MVertex*,MEdge> &v2e, std::set<MEdge,Less_Edge> &group, std::set<MVertex*> &touched) { if (touched.find(v) != touched.end())return; touched.insert(v); for (std::multimap <MVertex*,MEdge>::iterator it = v2e.lower_bound(v); it != v2e.upper_bound(v) ; ++it){ group.insert(it->second); for (int i=0;i<it->second.getNumVertices();++i){ recur_connect (it->second.getVertex(i),v2e,group,touched); } } }
void __stdcall GFGoodBuy(struct SGFGoodBuyInfo const &gbi, unsigned int iClientID) { uint iBase; pub::Player::GetBase(iClientID, iBase); multimap<uint, CARGO_MISSION>::iterator start = set_mapCargoMissions.lower_bound(iBase); multimap<uint, CARGO_MISSION>::iterator end = set_mapCargoMissions.upper_bound(iBase); for (; start != end; ++start) { if (start->second.item == gbi.iGoodID) { start->second.curr_amount -= gbi.iCount; if (start->second.curr_amount < 0) { start->second.curr_amount = 0; } } } }
static void recurConnectByMEdge(const MEdge &e, std::multimap<MEdge, MTriangle*, Less_Edge> &e2e, std::set<MTriangle*> &group, std::set<MEdge, Less_Edge> &touched, std::set<MEdge, Less_Edge> &theCut) { if (touched.find(e) != touched.end()) return; touched.insert(e); for (std::multimap <MEdge, MTriangle*, Less_Edge>::iterator it = e2e.lower_bound(e); it != e2e.upper_bound(e); ++it){ group.insert(it->second); for (int i = 0; i < it->second->getNumEdges(); ++i){ MEdge me = it->second->getEdge(i); if (theCut.find(me) != theCut.end()){ touched.insert(me); //break; } else recurConnectByMEdge(me, e2e, group, touched, theCut); } } }
void __stdcall ShipDestroyed(DamageList *_dmg, DWORD *ecx, uint iKill) { returncode = DEFAULT_RETURNCODE; if (iKill) { CShip *cship = (CShip*)ecx[4]; int iRep; pub::SpaceObj::GetRep(cship->get_id(), iRep); uint iAff; pub::Reputation::GetAffiliation(iRep, iAff); Vector vPos; vPos.x = cship->fPosX; vPos.y = cship->fPosY; vPos.z = cship->fPosZ; string scSector = VectorToSectorCoord(cship->iSystem, vPos); multimap<uint, NPC_MISSION>::iterator start = set_mapNpcMissions.lower_bound(iAff); multimap<uint, NPC_MISSION>::iterator end = set_mapNpcMissions.upper_bound(iAff); for (; start != end; ++start) { if (start->second.system == cship->iSystem) { if (start->second.sector.length() && start->second.sector != scSector) continue; if (start->second.curr_amount < start->second.required_amount) { start->second.curr_amount++; // PrintUserCmdText(iClientID, L"%d ships remaining to destroy to complete mission objective", needed); } } } } }
std::vector<TupletInfo> detectTuplets( const std::multimap<ReducedFraction, MidiChord>::iterator &startBarChordIt, const std::multimap<ReducedFraction, MidiChord>::iterator &endBarChordIt, const ReducedFraction &startBarTick, const ReducedFraction &barFraction, std::multimap<ReducedFraction, MidiChord> &chords, const ReducedFraction &basicQuant, int barIndex) { const auto divLengths = Meter::divisionsOfBarForTuplets(barFraction); std::vector<TupletInfo> tuplets; int id = 0; const auto tol = basicQuant / 2; for (const auto &divLen: divLengths) { const auto tupletNumbers = findTupletNumbers(divLen, barFraction); const auto div = barFraction / divLen; const int divCount = div.numerator() / div.denominator(); for (int i = 0; i != divCount; ++i) { const auto startDivTime = startBarTick + divLen * i; const auto endDivTime = startBarTick + divLen * (i + 1); // check which chords can be inside tuplet period // [startDivTime - tol, endDivTime] const auto startDivTimeWithTol = qMax(startBarTick, startDivTime - tol); auto startDivChordIt = MChord::findFirstChordInRange(startDivTimeWithTol, endDivTime, startBarChordIt, endBarChordIt); if (startDivChordIt == endBarChordIt) continue; Q_ASSERT_X(!startDivChordIt->second.isInTuplet, "MIDI tuplets: findTuplets", "Tuplet chord has been already used"); // end iterator, as usual, point to the next - invalid chord auto endDivChordIt = chords.lower_bound(endDivTime); if (!isNextBarOwnershipOk(startDivChordIt, endDivChordIt, chords, barIndex)) continue; // try different tuplets, nested tuplets are not allowed // here chords from next bar can be captured // if their on time < next bar start for (const auto &tupletNumber: tupletNumbers) { if (!isTupletLenAllowed(divLen, tupletNumber, startDivChordIt, endDivChordIt, basicQuant)) { continue; } auto tupletInfo = findTupletApproximation(divLen, tupletNumber, basicQuant, startDivTime, startDivChordIt, endDivChordIt); const auto &opers = midiImportOperations.data()->trackOpers; const int currentTrack = midiImportOperations.currentTrack(); if (opers.simplifyDurations.value(currentTrack)) { if (!haveChordsInTheMiddleBetweenTupletChords( startDivChordIt, endDivChordIt, tupletInfo)) { detectStaccato(tupletInfo); } } tupletInfo.sumLengthOfRests = findSumLengthOfRests(tupletInfo, startBarTick); if (!isTupletAllowed(tupletInfo)) continue; tupletInfo.id = id++; tuplets.push_back(tupletInfo); // tuplet found } // next tuplet type } } return tuplets; }
bool IndexServerConn::HandleMsg(enum IndexServerMsg msg_id) { switch(msg_id) { case TS_MSG_VERSION: return HandShake(); break; case TS_MSG_WIS_VERSION: { int version; if (BytesReceived() < sizeof(uint32_t)) // The message is not completely received return true; if (!ReceiveInt(version)) // Receive the version number of the server index return false; if (version > VERSION) { DPRINT(INFO,"The server at %i have a version %i, while we are only running a %i version", GetIP(), version, VERSION); exit(EXIT_FAILURE); } else if(version < VERSION) { DPRINT(INFO,"This server is running an old version (v%i) !", version); return false; } DPRINT(INFO,"We are running the same version.."); } break; case TS_MSG_JOIN_LEAVE: { int ip; int port; std::string version; if (!ReceiveStr(version)) return false; if (BytesReceived() < 2*sizeof(uint32_t)) // The message is not completely received return true; if (!ReceiveInt(ip)) // Receive the IP of the warmux server return false; if (!ReceiveInt(port)) // Receive the port of the warmux server return false; if (port < 0) // means it disconnected { for (std::multimap<std::string, FakeClient>::iterator serv = fake_clients.lower_bound(version); serv != fake_clients.upper_bound(version); serv++) { if( serv->second.ip == ip && serv->second.port == -port ) { fake_clients.erase(serv); DPRINT(MSG, "A fake server disconnected"); break; } } } else { HostOptions options; std::string game_name; if (!ReceiveStr(game_name)) return false; int passwd; if (!ReceiveInt(passwd)) return false; options.Set(game_name, passwd); fake_clients.insert(std::make_pair(version, FakeClient(ip, port, options))); stats.NewFakeServer(version); } } break; default: DPRINT(INFO,"Bad message!"); return false; } msg_id = TS_NO_MSG; return true; }
VkBool32 VKTS_APIENTRY engineRun() { if (g_engineState != VKTS_ENGINE_INIT_STATE) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Not in initialize state."); return VK_FALSE; } if (engineGetNumberUpdateThreads() < VKTS_MIN_UPDATE_THREADS || engineGetNumberUpdateThreads() > VKTS_MAX_UPDATE_THREADS) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Number of update threads not correct."); return VK_FALSE; } // // Main thread gets all displays and windows attached. // const auto& displayList = _visualGetActiveDisplays(); for (size_t i = 0; i < displayList.size(); i++) { engineAttachDisplayToUpdateThread(displayList[i], g_allUpdateThreads[g_allUpdateThreads.size() - 1]); } const auto& windowList = _visualGetActiveWindows(); for (size_t i = 0; i < windowList.size(); i++) { engineAttachWindowToUpdateThread(windowList[i], g_allUpdateThreads[g_allUpdateThreads.size() - 1]); } // g_engineState = VKTS_ENGINE_UPDATE_STATE; logPrint(VKTS_LOG_INFO, "Engine: Started."); // Task queue creation. TaskQueueSP sendTaskQueue; TaskQueueSP executedTaskQueue; if (g_taskExecutorCount > 0) { sendTaskQueue = TaskQueueSP(new TaskQueue); if (!sendTaskQueue.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create task queue."); return VK_FALSE; } executedTaskQueue = TaskQueueSP(new TaskQueue); if (!executedTaskQueue.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create task queue."); return VK_FALSE; } } // Message dispatcher creation. MessageDispatcherSP messageDispatcher = MessageDispatcherSP(new MessageDispatcher()); if (!messageDispatcher.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create message dispatcher."); return VK_FALSE; } // Object, needed for synchronizing the executors. ExecutorSync executorSync; // // Task executor creation and launching, // SmartPointerVector<TaskExecutorSP> realTaskExecutors; SmartPointerVector<ThreadSP> realTaskThreads; for (uint32_t i = 0; i < g_taskExecutorCount; i++) { auto currentTaskExecutor = TaskExecutorSP(new TaskExecutor(i, executorSync, sendTaskQueue, executedTaskQueue)); if (!currentTaskExecutor.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create current task executor."); return VK_FALSE; } auto currentRealThread = ThreadSP(new std::thread(&TaskExecutor::run, currentTaskExecutor)); if (!currentRealThread.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create current real thread."); return VK_FALSE; } // realTaskExecutors.append(currentTaskExecutor); realTaskThreads.append(currentRealThread); logPrint(VKTS_LOG_INFO, "Engine: Task %d started.", currentTaskExecutor->getIndex()); } // // Update Thread creation and launching. // UpdateThreadExecutorSP mainUpdateThreadExecutor; SmartPointerVector<UpdateThreadExecutorSP> realUpdateThreadExecutors; SmartPointerVector<ThreadSP> realUpdateThreads; int32_t index = 0; for (size_t updateThreadIndex = 0; updateThreadIndex < g_allUpdateThreads.size(); updateThreadIndex++) { const auto& currentUpdateThread = g_allUpdateThreads[updateThreadIndex]; // const auto currentMessageDispatcher = (index == engineGetNumberUpdateThreads() - 1) ? messageDispatcher : MessageDispatcherSP(); // auto currentUpdateThreadContext = UpdateThreadContextSP(new UpdateThreadContext((int32_t) updateThreadIndex, (int32_t) g_allUpdateThreads.size(), g_tickTime, sendTaskQueue, executedTaskQueue)); if (!currentUpdateThreadContext.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create update thread context."); return VK_FALSE; } // for (auto currentDisplayWalker = g_allAttachedDisplays.lower_bound(currentUpdateThread); currentDisplayWalker != g_allAttachedDisplays.upper_bound(currentUpdateThread); currentDisplayWalker++) { currentUpdateThreadContext->attachDisplay(currentDisplayWalker->second); } // for (auto currentWindowWalker = g_allAttachedWindows.lower_bound(currentUpdateThread); currentWindowWalker != g_allAttachedWindows.upper_bound(currentUpdateThread); currentWindowWalker++) { currentUpdateThreadContext->attachWindow(currentWindowWalker->second); } // if (index == engineGetNumberUpdateThreads() - 1) { // Last thread is the main thread. mainUpdateThreadExecutor = UpdateThreadExecutorSP(new UpdateThreadExecutor(index, executorSync, currentUpdateThread, currentUpdateThreadContext, currentMessageDispatcher)); if (!mainUpdateThreadExecutor.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create main update thread executor."); return VK_FALSE; } } else { // Receive queue is the threads send queue. auto currentUpdateThreadExecutor = UpdateThreadExecutorSP(new UpdateThreadExecutor(index, executorSync, currentUpdateThread, currentUpdateThreadContext, currentMessageDispatcher)); if (!currentUpdateThreadExecutor.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create current update thread executor."); return VK_FALSE; } realUpdateThreadExecutors.append(currentUpdateThreadExecutor); logPrint(VKTS_LOG_INFO, "Engine: Thread %d started.", currentUpdateThreadExecutor->getIndex()); auto currentRealThread = ThreadSP(new std::thread(&UpdateThreadExecutor::run, currentUpdateThreadExecutor)); if (!currentRealThread.get()) { logPrint(VKTS_LOG_ERROR, "Engine: Run failed! Could not create current real thread."); return VK_FALSE; } realUpdateThreads.append(currentRealThread); } index++; } // Run last thread and loop. logPrint(VKTS_LOG_INFO, "Engine: Thread %d started.", mainUpdateThreadExecutor->getIndex()); mainUpdateThreadExecutor->run(); // // Stopping everything. // logPrint(VKTS_LOG_INFO, "Engine: Thread %d stopped.", mainUpdateThreadExecutor->getIndex()); // Wait for all threads to finish in the reverse order they were created. for (auto reverseIndex = static_cast<int32_t>(realUpdateThreads.size()) - 1; reverseIndex >= 0; reverseIndex--) { const auto& currentRealThread = realUpdateThreads[reverseIndex]; currentRealThread->join(); logPrint(VKTS_LOG_INFO, "Engine: Thread %d stopped.", reverseIndex); } realUpdateThreadExecutors.clear(); realUpdateThreads.clear(); // if (sendTaskQueue.get()) { // Empty the queue. // As no update thread can feed the queue anymore, it is save to call reset. sendTaskQueue->reset(); // ITaskSP stopTask; logPrint(VKTS_LOG_SEVERE, "Engine: Disabling task queue."); for (uint32_t i = 0; i < g_taskExecutorCount; i++) { // Send an empty task to the queue, to exit the thread. sendTaskQueue->addTask(stopTask); } } // Wait for all tasks to finish in the reverse order they were created. for (auto reverseIndex = static_cast<int32_t>(realTaskThreads.size()) - 1; reverseIndex >= 0; reverseIndex--) { const auto& currentRealThread = realTaskThreads[reverseIndex]; currentRealThread->join(); logPrint(VKTS_LOG_INFO, "Engine: Task %d stopped.", reverseIndex); } realTaskExecutors.clear(); realTaskThreads.clear(); // g_engineState = VKTS_ENGINE_INIT_STATE; logPrint(VKTS_LOG_INFO, "Engine: Stopped."); return VK_TRUE; }
void setTickf(float t) { rtick = fmodf(t, (MYFLT) tickMax); ev_pos = ev.lower_bound( (int) rtick ); }
template <class C, class V> inline bool CubitLoops<C, V>::recursive_make_loop(V* start_vertex, CoEdge* coedge, std::set<CoEdge* >& used_coedges, std::multimap<V*, CoEdge*>& start_coedge_map, std::vector<CoEdge*>& loop) { V* curr_vertex; if (coedge->sense == CUBIT_FORWARD) curr_vertex = coedge->end; else curr_vertex = coedge->start; loop.push_back(coedge); used_coedges.insert(coedge); while (curr_vertex != start_vertex) { typename std::multimap<V*, CoEdge*>::iterator iter; typename std::multimap<V*, CoEdge*>::iterator last; iter = start_coedge_map.lower_bound(curr_vertex); last = start_coedge_map.upper_bound(curr_vertex); std::vector<CoEdge*> possible_coedges; for (/*preinitialized*/; iter != last; iter++) { if (used_coedges.find(iter->second) == used_coedges.end()) possible_coedges.push_back(iter->second); } if (possible_coedges.size() == 0) return false; else if (possible_coedges.size() == 1) { coedge = possible_coedges[0]; loop.push_back(coedge); used_coedges.insert(coedge); if (coedge->sense == CUBIT_FORWARD) curr_vertex = coedge->end; else curr_vertex = coedge->start; } else { for (size_t i=0; i<possible_coedges.size(); i++) { std::vector<CoEdge*> sub_loop; if (recursive_make_loop(curr_vertex, possible_coedges[i], used_coedges, start_coedge_map, sub_loop) ) { loop.insert(loop.end(), sub_loop.begin(), sub_loop.end()); } else { for (size_t j=0; j<sub_loop.size(); j++) used_coedges.erase(sub_loop[j]); coedge = possible_coedges[i]; } } loop.push_back(coedge); used_coedges.insert(coedge); if (coedge->sense == CUBIT_FORWARD) curr_vertex = coedge->end; else curr_vertex = coedge->start; } } return true; }
/// visitGraph - Visit the functions in the specified graph, updating the /// specified lattice values for all of their uses. /// void StructureFieldVisitorBase:: visitGraph(DSGraph &DSG, std::multimap<DSNode*, LatticeValue*> &NodeLVs) { assert(!NodeLVs.empty() && "No lattice values to compute!"); // To visit a graph, first step, we visit the instruction making up each // function in the graph, but ignore calls when processing them. We handle // call nodes explicitly by looking at call nodes in the graph if needed. We // handle instructions before calls to avoid interprocedural analysis if we // can drive lattice values to bottom early. // SFVInstVisitor IV(DSG, Callbacks, NodeLVs); for (DSGraph::retnodes_iterator FI = DSG.retnodes_begin(), E = DSG.retnodes_end(); FI != E; ++FI) for (Function::iterator BB = FI->first->begin(), E = FI->first->end(); BB != E; ++BB) for (BasicBlock::iterator I = BB->begin(), E = BB->end(); I != E; ++I) if (IV.visit(*I) && NodeLVs.empty()) return; // Nothing left to analyze. // Keep track of which actual direct callees are handled. std::set<Function*> CalleesHandled; // Once we have visited all of the instructions in the function bodies, if // there are lattice values that have not been driven to bottom, see if any of // the nodes involved are passed into function calls. If so, we potentially // have to recursively traverse the call graph. for (DSGraph::fc_iterator CS = DSG.fc_begin(), E = DSG.fc_end(); CS != E; ++CS) { // Figure out the mapping from a node in the caller (potentially several) // nodes in the callee. DSGraph::NodeMapTy CallNodeMap; Instruction *TheCall = CS->getCallSite().getInstruction(); // If this is an indirect function call, assume nothing gets passed through // it. FIXME: THIS IS BROKEN! Just get the ECG for the fn ptr if it's not // direct. if (CS->isIndirectCall()) continue; // If this is an external function call, it cannot be involved with this // node, because otherwise the node would be marked incomplete! if (CS->getCalleeFunc()->isExternal()) continue; // If we can handle this function call, remove it from the set of direct // calls found by the visitor. CalleesHandled.insert(CS->getCalleeFunc()); std::vector<DSNodeHandle> Args; DSGraph *CG = &ECG.getDSGraph(*CS->getCalleeFunc()); CG->getFunctionArgumentsForCall(CS->getCalleeFunc(), Args); if (!CS->getRetVal().isNull()) DSGraph::computeNodeMapping(Args[0], CS->getRetVal(), CallNodeMap); for (unsigned i = 0, e = CS->getNumPtrArgs(); i != e; ++i) { if (i == Args.size()-1) break; DSGraph::computeNodeMapping(Args[i+1], CS->getPtrArg(i), CallNodeMap); } Args.clear(); // The mapping we just computed maps from nodes in the callee to nodes in // the caller, so we can't query it efficiently. Instead of going through // the trouble of inverting the map to do this (linear time with the size of // the mapping), we just do a linear search to see if any affected nodes are // passed into this call. bool CallCanModifyDataFlow = false; for (DSGraph::NodeMapTy::iterator MI = CallNodeMap.begin(), E = CallNodeMap.end(); MI != E; ++MI) if (NodeLVs.count(MI->second.getNode())) // Okay, the node is passed in, check to see if the call might do // something interesting to it (i.e. if analyzing the call can produce // anything other than "top"). if ((CallCanModifyDataFlow = NodeCanPossiblyBeInteresting(MI->first, Callbacks))) break; // If this function call cannot impact the analysis (either because the // nodes we are tracking are not passed into the call, or the DSGraph for // the callee tells us that analysis of the callee can't provide interesting // information), ignore it. if (!CallCanModifyDataFlow) continue; // Okay, either compute analysis results for the callee function, or reuse // results previously computed. std::multimap<DSNode*, LatticeValue*> &CalleeFacts = getCalleeFacts(*CG); // Merge all of the facts for the callee into the facts for the caller. If // this reduces anything in the caller to 'bottom', remove them. for (DSGraph::NodeMapTy::iterator MI = CallNodeMap.begin(), E = CallNodeMap.end(); MI != E; ++MI) { // If we have Lattice facts in the caller for this node in the callee, // merge any information from the callee into the caller. // If the node is not accessed in the callee at all, don't update. if (MI->first->getType() == Type::VoidTy) continue; // If there are no data-flow facts live in the caller for this node, don't // both processing it. std::multimap<DSNode*, LatticeValue*>::iterator NLVI = NodeLVs.find(MI->second.getNode()); if (NLVI == NodeLVs.end()) continue; // Iterate over all of the lattice values that have corresponding fields // in the callee, merging in information as we go. Be careful about the // fact that the callee may get passed the address of a substructure and // other funny games. //if (CalleeFacts.count(const_cast<DSNode*>(MI->first)) == 0) { DSNode *CalleeNode = const_cast<DSNode*>(MI->first); unsigned CalleeNodeOffset = MI->second.getOffset(); while (NLVI->first == MI->second.getNode()) { // Figure out what offset in the callee this field would land. unsigned FieldOff = NLVI->second->getFieldOffset()+CalleeNodeOffset; // If the field is not within the callee node, ignore it. if (FieldOff >= CalleeNode->getSize()) { ++NLVI; continue; } // Okay, check to see if we have a lattice value for the field at offset // FieldOff in the callee node. const LatticeValue *CalleeLV = 0; std::multimap<DSNode*, LatticeValue*>::iterator CFI = CalleeFacts.lower_bound(CalleeNode); for (; CFI != CalleeFacts.end() && CFI->first == CalleeNode; ++CFI) if (CFI->second->getFieldOffset() == FieldOff) { CalleeLV = CFI->second; // Found it! break; } // If we don't, the lattice value hit bottom and we should remove the // lattice value in the caller. if (!CalleeLV) { delete NLVI->second; // The lattice value hit bottom. NodeLVs.erase(NLVI++); continue; } // Finally, if we did find a corresponding entry, merge the information // into the caller's lattice value and keep going. if (NLVI->second->mergeInValue(CalleeLV)) { // Okay, merging these two caused the caller value to hit bottom. // Remove it. delete NLVI->second; // The lattice value hit bottom. NodeLVs.erase(NLVI++); } ++NLVI; // We successfully merged in some information! } // If we ran out of facts to prove, just exit. if (NodeLVs.empty()) return; } } // The local analysis pass inconveniently discards many local function calls // from the graph if they are to known functions. Loop over direct function // calls not handled above and visit them as appropriate. while (!IV.DirectCallSites.empty()) { Instruction *Call = *IV.DirectCallSites.begin(); IV.DirectCallSites.erase(IV.DirectCallSites.begin()); // Is this one actually handled by DSA? if (CalleesHandled.count(cast<Function>(Call->getOperand(0)))) continue; // Collect the pointers involved in this call. std::vector<Value*> Pointers; if (isa<PointerType>(Call->getType())) Pointers.push_back(Call); for (unsigned i = 1, e = Call->getNumOperands(); i != e; ++i) if (isa<PointerType>(Call->getOperand(i)->getType())) Pointers.push_back(Call->getOperand(i)); // If this is an intrinsic function call, figure out which one. unsigned IID = cast<Function>(Call->getOperand(0))->getIntrinsicID(); for (unsigned i = 0, e = Pointers.size(); i != e; ++i) { // If any of our lattice values are passed into this call, which is // specially handled by the local analyzer, inform the lattice function. DSNode *N = DSG.getNodeForValue(Pointers[i]).getNode(); for (std::multimap<DSNode*, LatticeValue*>::iterator LVI = NodeLVs.lower_bound(N); LVI != NodeLVs.end() && LVI->first == N;) { bool AtBottom = false; switch (IID) { default: AtBottom = LVI->second->visitRecognizedCall(*Call); break; case Intrinsic::memset: if (Callbacks & Visit::Stores) AtBottom = LVI->second->visitMemSet(*cast<CallInst>(Call)); break; } if (AtBottom) { delete LVI->second; NodeLVs.erase(LVI++); } else { ++LVI; } } } } }