Exemple #1
0
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;
}