void BUDataStructures::CloneAuxIntoGlobal(DSGraph* G) { DSGraph* GG = G->getGlobalsGraph(); ReachabilityCloner RC(GG, G, 0); for(DSGraph::afc_iterator ii = G->afc_begin(), ee = G->afc_end(); ii != ee; ++ii) { //cerr << "Pushing " << ii->getCallSite().getInstruction()->getOperand(0) << "\n"; //If we can, merge with an existing call site for this instruction if (GG->hasNodeForValue(ii->getCallSite().getInstruction()->getOperand(0))) { DSGraph::afc_iterator GGii; for(GGii = GG->afc_begin(); GGii != GG->afc_end(); ++GGii) if (GGii->getCallSite().getInstruction()->getOperand(0) == ii->getCallSite().getInstruction()->getOperand(0)) break; if (GGii != GG->afc_end()) RC.cloneCallSite(*ii).mergeWith(*GGii); else GG->addAuxFunctionCall(RC.cloneCallSite(*ii)); } else { GG->addAuxFunctionCall(RC.cloneCallSite(*ii)); } } }
// // Method: CloneAuxIntoGlobal() // // Description: // This method takes the specified graph and processes each unresolved call // site (a call site for which all targets are not yet known). For each // unresolved call site, it adds it to the globals graph and merges // information about the call site if the globals graph already had the call // site in its own list of unresolved call sites. // void BUDataStructures::CloneAuxIntoGlobal(DSGraph* G) { // // If this DSGraph has no unresolved call sites, do nothing. We do enough // work that wastes time even when the list is empty that this extra check // is probably worth it. // if (G->afc_begin() == G->afc_end()) return; DSGraph* GG = G->getGlobalsGraph(); ReachabilityCloner RC(GG, G, 0); // // Determine which called values are both within the local graph DSCallsites // and the global graph DSCallsites. Note that we require that the global // graph have a DSNode for the called value. // std::map<Value *, DSCallSite *> CommonCallValues; for (DSGraph::afc_iterator ii = G->afc_begin(), ee = G->afc_end(); ii != ee; ++ii) { // // If the globals graph has a DSNode for the LLVM value used in the local // unresolved call site, then it might have a DSCallSite for it, too. // Record this call site as a potential call site that will need to be // merged. // // Otherwise, just add the call site to the globals graph. // Value * V = ii->getCallSite().getCalledValue(); if (GG->hasNodeForValue(V)) { DSCallSite & DS = *ii; CommonCallValues[V] = &DS; } else { GG->addAuxFunctionCall(RC.cloneCallSite(*ii)); } } // // Scan through all the unresolved call sites in the globals graph and see if // the local graph has a call using the same LLVM value. If so, merge the // call sites. // DSGraph::afc_iterator GGii = GG->afc_begin(); for (; GGii != GG->afc_end(); ++GGii) { // // Determine if this unresolved call site is also in the local graph. // If so, then merge it. // Value * CalledValue = GGii->getCallSite().getCalledValue(); std::map<Value *, DSCallSite *>::iterator v; v = CommonCallValues.find (CalledValue); if (v != CommonCallValues.end()) { // // Merge the unresolved call site into the globals graph. // RC.cloneCallSite(*(v->second)).mergeWith(*GGii); // // Mark that this call site was merged by removing the called LLVM value // from the set of values common to both the local and global DSGraphs. // CommonCallValues.erase (v); } } // // We've now merged all DSCallSites that were known both to the local graph // and the globals graph. Now, there are still some local call sites that // need to be *added* to the globals graph; they are in DSCallSites remaining // in CommonCallValues. // std::map<Value *, DSCallSite *>::iterator v = CommonCallValues.begin (); for (; v != CommonCallValues.end(); ++v) { GG->addAuxFunctionCall(RC.cloneCallSite(*(v->second))); } return; }