Example #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));
    }
  }
}
Example #2
0
// run - Calculate the top down data structure graphs for each function in the
// program.
//
bool TDDataStructures::runOnModule(Module &M) {

  init(useEQBU ? &getAnalysis<EquivBUDataStructures>()
       : &getAnalysis<BUDataStructures>(),
       true, true, true, false);
  // Figure out which functions must not mark their arguments complete because
  // they are accessible outside this compilation unit.  Currently, these
  // arguments are functions which are reachable by incomplete or external
  // nodes in the globals graph.
  const DSScalarMap &GGSM = GlobalsGraph->getScalarMap();
  DenseSet<DSNode*> Visited;
  for (DSScalarMap::global_iterator I=GGSM.global_begin(), E=GGSM.global_end();
       I != E; ++I) {
    DSNode *N = GGSM.find(*I)->second.getNode();
    if (N->isIncompleteNode() || N->isExternalNode())
      markReachableFunctionsExternallyAccessible(N, Visited);
  }

  // Loop over unresolved call nodes.  Any functions passed into (but not
  // returned!) from unresolvable call nodes may be invoked outside of the
  // current module.
  for (DSGraph::afc_iterator I = GlobalsGraph->afc_begin(),
         E = GlobalsGraph->afc_end(); I != E; ++I)
    for (unsigned arg = 0, e = I->getNumPtrArgs(); arg != e; ++arg)
      markReachableFunctionsExternallyAccessible(I->getPtrArg(arg).getNode(),
                                                 Visited);
  Visited.clear();

  // Clear Aux of Globals Graph to be refilled in later by post-TD unresolved
  // functions
  GlobalsGraph->getAuxFunctionCalls().clear();

  // Functions without internal linkage are definitely externally callable!
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration() && !I->hasInternalLinkage() && !I->hasPrivateLinkage())
      ExternallyCallable.insert(I);

  // Debug code to print the functions that are externally callable
#if 0
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (ExternallyCallable.count(I)) {
      errs() << "ExternallyCallable: " << I->getNameStr() << "\n";
    }
#endif

  // We want to traverse the call graph in reverse post-order.  To do this, we
  // calculate a post-order traversal, then reverse it.
  DenseSet<DSGraph*> VisitedGraph;
  std::vector<DSGraph*> PostOrder;

{TIME_REGION(XXX, "td:Compute postorder");

  // Calculate top-down from main...
  if (Function *F = M.getFunction("main"))
    ComputePostOrder(*F, VisitedGraph, PostOrder);

  // Next calculate the graphs for each unreachable function...
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration())
      ComputePostOrder(*I, VisitedGraph, PostOrder);

  VisitedGraph.clear();   // Release memory!
}

{TIME_REGION(XXX, "td:Inline stuff");

  // Visit each of the graphs in reverse post-order now!
  while (!PostOrder.empty()) {
    InlineCallersIntoGraph(PostOrder.back());
    PostOrder.pop_back();
  }
}

  // Free the IndCallMap.
  while (!IndCallMap.empty()) {
    delete IndCallMap.begin()->second;
    IndCallMap.erase(IndCallMap.begin());
  }

  formGlobalECs();

  ExternallyCallable.clear();
  GlobalsGraph->removeTriviallyDeadNodes();
  GlobalsGraph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
  GlobalsGraph->computeIntPtrFlags();

  // Make sure each graph has updated external information about globals
  // in the globals graph.
  VisitedGraph.clear();
  for (Module::iterator F = M.begin(); F != M.end(); ++F) {
    if (!(F->isDeclaration())){
      DSGraph *Graph  = getOrCreateGraph(F);
      if (!VisitedGraph.insert(Graph).second) continue;

      cloneGlobalsInto(Graph, DSGraph::DontCloneCallNodes |
                        DSGraph::DontCloneAuxCallNodes);

      Graph->computeExternalFlags(DSGraph::DontMarkFormalsExternal);
      Graph->computeIntPtrFlags();
      // Clean up uninteresting nodes
      Graph->removeDeadNodes(0);

    }
  }

  // CBU contains the correct call graph.
  // Restore it, so that subsequent passes and clients can get it.
  restoreCorrectCallGraph();

  /// Added by Zhiyuan: print out the DSGraph.
  if (llvm::DebugFlag) {
    print(errs(), &M);
  }
  return false;
}
Example #3
0
// run - Calculate the top down data structure graphs for each function in the
// program.
//
bool TDDataStructures::runOnModule(Module &M) {
  
  init(useEQBU ? &getAnalysis<EquivBUDataStructures>()
       : &getAnalysis<BUDataStructures>(), 
       true, true, true, false);

  // Figure out which functions must not mark their arguments complete because
  // they are accessible outside this compilation unit.  Currently, these
  // arguments are functions which are reachable by global variables in the
  // globals graph.
  const DSScalarMap &GGSM = GlobalsGraph->getScalarMap();
  hash_set<DSNode*> Visited;
  for (DSScalarMap::global_iterator I=GGSM.global_begin(), E=GGSM.global_end();
       I != E; ++I) {
    DSNode *N = GGSM.find(*I)->second.getNode();
    if (N->NodeType.isIncompleteNode())
      markReachableFunctionsExternallyAccessible(N, Visited);
  }

  // Loop over unresolved call nodes.  Any functions passed into (but not
  // returned!) from unresolvable call nodes may be invoked outside of the
  // current module.
  for (DSGraph::afc_iterator I = GlobalsGraph->afc_begin(),
         E = GlobalsGraph->afc_end(); I != E; ++I)
    for (unsigned arg = 0, e = I->getNumPtrArgs(); arg != e; ++arg)
      markReachableFunctionsExternallyAccessible(I->getPtrArg(arg).getNode(),
                                                 Visited);
  Visited.clear();

  // Clear Aux of Globals Graph to be refilled in later by post-TD unresolved 
  // functions
  GlobalsGraph->getAuxFunctionCalls().clear();

  // Functions without internal linkage also have unknown incoming arguments!
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration() && !I->hasInternalLinkage())
      ArgsRemainIncomplete.insert(I);

  // We want to traverse the call graph in reverse post-order.  To do this, we
  // calculate a post-order traversal, then reverse it.
  hash_set<DSGraph*> VisitedGraph;
  std::vector<DSGraph*> PostOrder;

{TIME_REGION(XXX, "td:Compute postorder");

  // Calculate top-down from main...
  if (Function *F = M.getFunction("main"))
    ComputePostOrder(F, VisitedGraph, PostOrder);

  // Next calculate the graphs for each unreachable function...
  for (Module::iterator I = M.begin(), E = M.end(); I != E; ++I)
    if (!I->isDeclaration())
      ComputePostOrder(I, VisitedGraph, PostOrder);

  VisitedGraph.clear();   // Release memory!
}

{TIME_REGION(XXX, "td:Inline stuff");

  // Visit each of the graphs in reverse post-order now!
  while (!PostOrder.empty()) {
    InlineCallersIntoGraph(PostOrder.back());
    PostOrder.pop_back();
  }
}

  // Free the IndCallMap.
  while (!IndCallMap.empty()) {
    delete IndCallMap.begin()->second;
    IndCallMap.erase(IndCallMap.begin());
  }

  formGlobalECs();

  ArgsRemainIncomplete.clear();
  GlobalsGraph->removeTriviallyDeadNodes();

  return false;
}
Example #4
0
//
// 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;
}