[llvm-commits] [poolalloc] r106474 - in /poolalloc/trunk: include/dsa/DSGraph.h include/dsa/DSNode.h include/dsa/DSSupport.h lib/DSA/BottomUpClosure.cpp lib/DSA/DSGraph.cpp lib/DSA/DataStructure.cpp lib/DSA/Local.cpp lib/DSA/Makefile lib/DSA/Printer.cpp lib/DSA/TopDownClosure.cpp

Will Dietz wdietz2 at illinois.edu
Mon Jun 21 13:52:30 PDT 2010


Author: wdietz2
Date: Mon Jun 21 15:52:30 2010
New Revision: 106474

URL: http://llvm.org/viewvc/llvm-project?rev=106474&view=rev
Log:
Improve var-arg support in DSA

Modified:
    poolalloc/trunk/include/dsa/DSGraph.h
    poolalloc/trunk/include/dsa/DSNode.h
    poolalloc/trunk/include/dsa/DSSupport.h
    poolalloc/trunk/lib/DSA/BottomUpClosure.cpp
    poolalloc/trunk/lib/DSA/DSGraph.cpp
    poolalloc/trunk/lib/DSA/DataStructure.cpp
    poolalloc/trunk/lib/DSA/Local.cpp
    poolalloc/trunk/lib/DSA/Makefile
    poolalloc/trunk/lib/DSA/Printer.cpp
    poolalloc/trunk/lib/DSA/TopDownClosure.cpp

Modified: poolalloc/trunk/include/dsa/DSGraph.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/dsa/DSGraph.h?rev=106474&r1=106473&r2=106474&view=diff
==============================================================================
--- poolalloc/trunk/include/dsa/DSGraph.h (original)
+++ poolalloc/trunk/include/dsa/DSGraph.h Mon Jun 21 15:52:30 2010
@@ -18,6 +18,7 @@
 #include "dsa/DSNode.h"
 #include "dsa/DSCallGraph.h"
 #include "llvm/ADT/EquivalenceClasses.h"
+#include "llvm/Function.h"
 
 #include <list>
 #include <map>
@@ -195,6 +196,7 @@
   // Public data-type declarations...
   typedef DSScalarMap ScalarMapTy;
   typedef std::map<const Function*, DSNodeHandle> ReturnNodesTy;
+  typedef std::map<const Function*, DSNodeHandle> VANodesTy;
   typedef ilist<DSNode> NodeListTy;
 
   /// NodeMapTy - This data type is used when cloning one graph into another to
@@ -218,6 +220,10 @@
   //
   ReturnNodesTy ReturnNodes;
 
+  // VANodes - Special "Variable Argument" Node for each function
+  //
+  VANodesTy VANodes;
+
   // FunctionCalls - This list maintains a single entry for each call
   // instruction in the current graph.  The first entry in the vector is the
   // scalar that holds the return value for the call, the second is the function
@@ -377,6 +383,10 @@
   typedef ReturnNodesTy::const_iterator retnodes_iterator;
   retnodes_iterator retnodes_begin() const { return ReturnNodes.begin(); }
   retnodes_iterator retnodes_end() const { return ReturnNodes.end(); }
+  
+  typedef VANodesTy::const_iterator vanodes_iterator;
+  vanodes_iterator vanodes_begin() const { return VANodes.begin(); }
+  vanodes_iterator vanodes_end() const { return VANodes.end(); }
 
 
   /// getReturnNodes - Return the mapping of functions to their return nodes for
@@ -399,10 +409,28 @@
     return I->second;
   }
 
+  /// getVANodeFor - Return the var-arg node for the specified function.
+  ///
+  DSNodeHandle &getVANodeFor(const Function &F) {
+    VANodesTy::iterator I = VANodes.find(&F);
+    assert(I != VANodes.end() && "Var-arg info for F not in this graph!");
+    return I->second;
+  }
+
+  const DSNodeHandle &getVANodeFor(const Function &F) const {
+    VANodesTy::const_iterator I = VANodes.find(&F);
+    assert(I != VANodes.end() && "Var-arg info for F not in this graph!");
+    return I->second;
+  }
+
   DSNodeHandle& getOrCreateReturnNodeFor(const Function& F) {
     return ReturnNodes[&F];
   }
 
+  DSNodeHandle& getOrCreateVANodeFor(const Function& F) {
+    return VANodes[&F];
+  }
+
   /// containsFunction - Return true if this DSGraph contains information for
   /// the specified function.
   bool containsFunction(const Function *F) const {

Modified: poolalloc/trunk/include/dsa/DSNode.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/dsa/DSNode.h?rev=106474&r1=106473&r2=106474&view=diff
==============================================================================
--- poolalloc/trunk/include/dsa/DSNode.h (original)
+++ poolalloc/trunk/include/dsa/DSNode.h Mon Jun 21 15:52:30 2010
@@ -103,7 +103,7 @@
     ExternalNode    = 1 << 11,  // This node comes from an external source
     IntToPtrNode    = 1 << 12,   // This node comes from an int cast
     PtrToIntNode    = 1 << 13,  // This node excapes to an int cast
-    VAStartNode     = 1 << 14,  // This node excapes to an int cast
+    VAStartNode     = 1 << 14,  // This node is from a vastart call
 
     //#ifndef NDEBUG
     DeadNode        = 1 << 15,   // This node is dead and should not be pointed to

Modified: poolalloc/trunk/include/dsa/DSSupport.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/dsa/DSSupport.h?rev=106474&r1=106473&r2=106474&view=diff
==============================================================================
--- poolalloc/trunk/include/dsa/DSSupport.h (original)
+++ poolalloc/trunk/include/dsa/DSSupport.h Mon Jun 21 15:52:30 2010
@@ -25,6 +25,7 @@
 namespace llvm {
 
 class Function;
+class FunctionType;
 class CallInst;
 class Value;
 class GlobalValue;
@@ -158,6 +159,7 @@
   const Function *CalleeF;            // The function called (direct call)
   DSNodeHandle    CalleeN;            // The function node called (indirect call)
   DSNodeHandle    RetVal;             // Returned value
+  DSNodeHandle    VarArgVal;          // Merged var-arg val
   std::vector<DSNodeHandle> CallArgs; // The pointer arguments
 
   static void InitNH(DSNodeHandle &NH, const DSNodeHandle &Src,
@@ -189,22 +191,23 @@
   /// Constructor.  Note - This ctor destroys the argument vector passed in.  On
   /// exit, the argument vector is empty.
   ///
-  DSCallSite(CallSite CS, const DSNodeHandle &rv, DSNode *Callee,
-             std::vector<DSNodeHandle> &Args)
-    : Site(CS), CalleeF(0), CalleeN(Callee), RetVal(rv) {
+  DSCallSite(CallSite CS, const DSNodeHandle &rv, const DSNodeHandle &va,
+             DSNode *Callee, std::vector<DSNodeHandle> &Args)
+    : Site(CS), CalleeF(0), CalleeN(Callee), RetVal(rv), VarArgVal(va) {
     assert(Callee && "Null callee node specified for call site!");
     Args.swap(CallArgs);
   }
-  DSCallSite(CallSite CS, const DSNodeHandle &rv, const Function *Callee,
-             std::vector<DSNodeHandle> &Args)
-    : Site(CS), CalleeF(Callee), RetVal(rv) {
+  DSCallSite(CallSite CS, const DSNodeHandle &rv, const DSNodeHandle &va,
+             const Function *Callee, std::vector<DSNodeHandle> &Args)
+    : Site(CS), CalleeF(Callee), RetVal(rv), VarArgVal(va) {
     assert(Callee && "Null callee function specified for call site!");
     Args.swap(CallArgs);
   }
 
   DSCallSite(const DSCallSite &DSCS)   // Simple copy ctor
     : Site(DSCS.Site), CalleeF(DSCS.CalleeF), CalleeN(DSCS.CalleeN),
-      RetVal(DSCS.RetVal), CallArgs(DSCS.CallArgs) {}
+      RetVal(DSCS.RetVal), VarArgVal(DSCS.VarArgVal),
+      CallArgs(DSCS.CallArgs) {}
 
   /// Mapping copy constructor - This constructor takes a preexisting call site
   /// to copy plus a map that specifies how the links should be transformed.
@@ -215,6 +218,7 @@
     Site = FromCall.Site;
     InitNH(RetVal, FromCall.RetVal, NodeMap);
     InitNH(CalleeN, FromCall.CalleeN, NodeMap);
+    InitNH(VarArgVal, FromCall.VarArgVal, NodeMap);
     CalleeF = FromCall.CalleeF;
 
     CallArgs.resize(FromCall.CallArgs.size());
@@ -227,6 +231,7 @@
     CalleeF  = RHS.CalleeF;
     CalleeN  = RHS.CalleeN;
     RetVal   = RHS.RetVal;
+    VarArgVal = RHS.VarArgVal;
     CallArgs = RHS.CallArgs;
     return *this;
   }
@@ -244,6 +249,8 @@
   CallSite            getCallSite()   const { return Site; }
         DSNodeHandle &getRetVal()           { return RetVal; }
   const DSNodeHandle &getRetVal()     const { return RetVal; }
+        DSNodeHandle &getVAVal()            { return VarArgVal; }
+  const DSNodeHandle &getVAVal()      const { return VarArgVal; }
 
   DSNode *getCalleeNode() const {
     assert(!CalleeF && CalleeN.getNode()); return CalleeN.getNode();
@@ -271,6 +278,7 @@
     if (this != &CS) {
       std::swap(Site, CS.Site);
       std::swap(RetVal, CS.RetVal);
+      std::swap(VarArgVal, CS.VarArgVal);
       std::swap(CalleeN, CS.CalleeN);
       std::swap(CalleeF, CS.CalleeF);
       std::swap(CallArgs, CS.CallArgs);
@@ -282,6 +290,7 @@
   ///
   void mergeWith(DSCallSite &CS) {
     getRetVal().mergeWith(CS.getRetVal());
+    getVAVal().mergeWith(CS.getVAVal());
     unsigned MinArgs = getNumPtrArgs();
     if (CS.getNumPtrArgs() < MinArgs) MinArgs = CS.getNumPtrArgs();
 
@@ -310,13 +319,26 @@
     }
     if (RetVal < CS.RetVal) return true;
     if (RetVal > CS.RetVal) return false;
+    if (VarArgVal < CS.VarArgVal) return true;
+    if (VarArgVal > CS.VarArgVal) return false;
     return CallArgs < CS.CallArgs;
   }
 
   bool operator==(const DSCallSite &CS) const {
     return CalleeF == CS.CalleeF && CalleeN == CS.CalleeN &&
-           RetVal == CS.RetVal && CallArgs == CS.CallArgs;
+           RetVal == CS.RetVal && CallArgs == CS.CallArgs &&
+           VarArgVal == CS.VarArgVal;
   }
+
+  /// FunctionTypeOfCallSite - Helper method to extract the signature of a function
+  /// that is called a given CallSite
+  ///
+  static const FunctionType *FunctionTypeOfCallSite(const CallSite & Site);
+
+  /// isVarArg - Determines if the call this represents is to a variable argument
+  /// function
+  ///
+  bool isVarArg() const;
 };
 
 } // End llvm namespace

Modified: poolalloc/trunk/lib/DSA/BottomUpClosure.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/BottomUpClosure.cpp?rev=106474&r1=106473&r2=106474&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/BottomUpClosure.cpp (original)
+++ poolalloc/trunk/lib/DSA/BottomUpClosure.cpp Mon Jun 21 15:52:30 2010
@@ -58,8 +58,10 @@
 // entry-points correctly.  As a bonus, we can be more aggressive at propagating
 // information upwards, as long as we don't remove unresolved call sites.
 bool BUDataStructures::runOnModuleInternal(Module& M) {
+#if 0
   llvm::errs() << "BU is currently being worked in in very invasive ways.\n"
           << "It is probably broken right now\n";
+#endif
 
   //Find SCCs and make SCC call graph
   callgraph.buildSCCs();
@@ -248,6 +250,7 @@
   for (std::set<DSCallSite>::iterator ii = BadCalls.begin(),
          ee = BadCalls.end(); ii != ee; ++ii) {
     ii->getRetVal().getNode()->markReachableNodes(reachable);
+    ii->getVAVal().getNode()->markReachableNodes(reachable);
     for (unsigned x = 0; x < ii->getNumPtrArgs(); ++x)
       ii->getPtrArg(x).getNode()->markReachableNodes(reachable);
   }
@@ -339,7 +342,7 @@
 
     // Fast path for noop calls.  Note that we don't care about merging globals
     // in the callee with nodes in the caller here.
-    if (CS.getRetVal().isNull() && CS.getNumPtrArgs() == 0) {
+    if (CS.getRetVal().isNull() && CS.getNumPtrArgs() == 0 && !CS.isVarArg()) {
       TempFCs.erase(TempFCs.begin());
       continue;
     }

Modified: poolalloc/trunk/lib/DSA/DSGraph.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/DSGraph.cpp?rev=106474&r1=106473&r2=106474&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/DSGraph.cpp (original)
+++ poolalloc/trunk/lib/DSA/DSGraph.cpp Mon Jun 21 15:52:30 2010
@@ -84,6 +84,7 @@
   AuxFunctionCalls.clear();
   ScalarMap.clear();
   ReturnNodes.clear();
+  VANodes.clear();
 
   // Drop all intra-node references, so that assertions don't fail...
   for (node_iterator NI = node_begin(), E = node_end(); NI != E; ++NI)
@@ -137,8 +138,8 @@
 
 /// cloneInto - Clone the specified DSGraph into the current graph.  The
 /// translated ScalarMap for the old function is filled into the ScalarMap
-/// for the graph, and the translated ReturnNodes map is returned into
-/// ReturnNodes.
+/// for the graph, the translated ReturnNodes map is returned into
+/// ReturnNodes, and the translated VANodes map is return into VANodes.
 ///
 /// The CloneFlags member controls various aspects of the cloning process.
 ///
@@ -208,6 +209,17 @@
                                       DSNodeHandle(MappedRetN,
                                      MappedRet.getOffset()+Ret.getOffset())));
   }
+
+  // Map the VA node pointers over...
+  for (vanodes_iterator I = G->vanodes_begin(),
+         E = G->vanodes_end(); I != E; ++I) {
+    const DSNodeHandle &VarArg = I->second;
+    DSNodeHandle &MappedVarArg = OldNodeMap[VarArg.getNode()];
+    DSNode *MappedVarArgN = MappedVarArg.getNode();
+    VANodes.insert(std::make_pair(I->first,
+                   DSNodeHandle(MappedVarArgN,
+                                MappedVarArg.getOffset()+VarArg.getOffset())));
+  }
 }
 
 /// spliceFrom - Logically perform the operation of cloning the RHS graph into
@@ -235,6 +247,14 @@
     RHS->ReturnNodes.clear();
   }
 
+  // Same for the VA nodes
+  if (VANodes.empty()) {
+    VANodes.swap(RHS->VANodes);
+  } else {
+    VANodes.insert(RHS->VANodes.begin(), RHS->VANodes.end());
+    RHS->VANodes.clear();
+  }
+
  // Merge the scalar map in.
   ScalarMap.spliceFrom(RHS->ScalarMap);
 }
@@ -242,11 +262,12 @@
 /// getFunctionArgumentsForCall - Given a function that is currently in this
 /// graph, return the DSNodeHandles that correspond to the pointer-compatible
 /// function arguments.  The vector is filled in with the return value (or
-/// null if it is not pointer compatible), followed by all of the
-/// pointer-compatible arguments.
+/// null if it is not pointer compatible), a vararg node (null if not
+/// applicable) followed by all of the pointer-compatible arguments.
 void DSGraph::getFunctionArgumentsForCall(const Function *F,
                                        std::vector<DSNodeHandle> &Args) const {
   Args.push_back(getReturnNodeFor(*F));
+  Args.push_back(getVANodeFor(*F));
   for (Function::const_arg_iterator AI = F->arg_begin(), E = F->arg_end();
        AI != E; ++AI)
     if (isa<PointerType>(AI->getType())) {
@@ -287,6 +308,8 @@
       for (unsigned i = 0, e = CS.getNumPtrArgs(); i != e; ++i)
         if (PathExistsToClonedNode(CS.getPtrArg(i).getNode()))
           return true;
+      if (PathExistsToClonedNode(CS.getVAVal().getNode()))
+        return true;
       return false;
     }
   };
@@ -378,13 +401,16 @@
     // Merge the return value with the return value of the context.
     Args[0].mergeWith(CS.getRetVal());
 
+    // Merge var-arg node
+    Args[1].mergeWith(CS.getVAVal());
+
     // Resolve all of the function arguments.
     for (unsigned i = 0, e = CS.getNumPtrArgs(); i != e; ++i) {
-      if (i == Args.size()-1)
+      if (i == Args.size()-2)
         break;
 
       // Add the link from the argument scalar to the provided value.
-      Args[i+1].mergeWith(CS.getPtrArg(i));
+      Args[i+2].mergeWith(CS.getPtrArg(i));
     }
     return;
   }
@@ -398,13 +424,17 @@
   if (!CS.getRetVal().isNull())
     RC.merge(CS.getRetVal(), Args[0]);
 
+  // Map the variable arguments
+  if (!CS.getVAVal().isNull())
+    RC.merge(CS.getVAVal(), Args[1]);
+
   // Map over all of the arguments.
   for (unsigned i = 0, e = CS.getNumPtrArgs(); i != e; ++i) {
-    if (i == Args.size()-1)
+    if (i == Args.size()-2)
       break;
 
     // Add the link from the argument scalar to the provided value.
-    RC.merge(CS.getPtrArg(i), Args[i+1]);
+    RC.merge(CS.getPtrArg(i), Args[i+2]);
   }
 
   // We generally don't want to copy global nodes or aux calls from the callee
@@ -479,34 +509,42 @@
     if (isa<PointerType>(I->getType()))
       Args.push_back(getNodeForValue(I));
 
-  return DSCallSite(CallSite(), getReturnNodeFor(F), &F, Args);
+  return DSCallSite(CallSite(), getReturnNodeFor(F), getVANodeFor(F), &F, Args);
 }
 
 /// getDSCallSiteForCallSite - Given an LLVM CallSite object that is live in
 /// the context of this graph, return the DSCallSite for it.
 DSCallSite DSGraph::getDSCallSiteForCallSite(CallSite CS) const {
-  DSNodeHandle RetVal;
+  DSNodeHandle RetVal, VarArg;
   Instruction *I = CS.getInstruction();
   if (isa<PointerType>(I->getType()))
     RetVal = getNodeForValue(I);
 
+  //FIXME: Here we trust the signature of the callsite to determine which arguments
+  //are var-arg and which are fixed.  Apparently we can't assume this, but I'm not sure
+  //of a better way.  For now, this assumption is known limitation.
+  const FunctionType *CalleeFuncType = DSCallSite::FunctionTypeOfCallSite(CS);
+  unsigned NumFixedArgs = CalleeFuncType->getNumParams();
+
   std::vector<DSNodeHandle> Args;
   Args.reserve(CS.arg_end()-CS.arg_begin());
 
   // Calculate the arguments vector...
   for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I)
     if (isa<PointerType>((*I)->getType())) {
-      if (isa<ConstantPointerNull>(*I))
-        Args.push_back(DSNodeHandle());
-      else
-        Args.push_back(getNodeForValue(*I));
+      const DSNodeHandle ArgNode = getNodeForValue(*I);
+      if (I - CS.arg_begin() < NumFixedArgs) {
+        Args.push_back(ArgNode);
+      } else {
+        VarArg.mergeWith(ArgNode);
+      }
     }
 
   // Add a new function call entry...
   if (Function *F = CS.getCalledFunction())
-    return DSCallSite(CS, RetVal, F, Args);
+    return DSCallSite(CS, RetVal, VarArg, F, Args);
   else
-    return DSCallSite(CS, RetVal,
+    return DSCallSite(CS, RetVal, VarArg,
                       getNodeForValue(CS.getCalledValue()).getNode(), Args);
 }
 
@@ -535,6 +573,8 @@
   // Then the return value is certainly incomplete!
   markIncompleteNode(Call.getRetVal().getNode());
 
+  markIncompleteNode(Call.getVAVal().getNode());
+
   // All objects pointed to by function arguments are incomplete!
   for (unsigned i = 0, e = Call.getNumPtrArgs(); i != e; ++i)
     markIncompleteNode(Call.getPtrArg(i).getNode());
@@ -552,7 +592,7 @@
 //
 void DSGraph::markIncompleteNodes(unsigned Flags) {
   // Mark any incoming arguments as incomplete.
-  if (Flags & DSGraph::MarkFormalArgs)
+  if (Flags & DSGraph::MarkFormalArgs) {
     for (ReturnNodesTy::iterator FI = ReturnNodes.begin(), E =ReturnNodes.end();
          FI != E; ++FI) {
       const Function &F = *FI->first;
@@ -562,6 +602,11 @@
           markIncompleteNode(getNodeForValue(I).getNode());
       markIncompleteNode(FI->second.getNode());
     }
+    // Mark all vanodes as incomplete (they are also arguments)
+    for (vanodes_iterator I = vanodes_begin(), E = vanodes_end();
+        I != E; ++I)
+      markIncompleteNode(I->second.getNode());
+  }
 
   // Mark stuff passed into functions calls as being incomplete.
   if (!shouldPrintAuxCalls())
@@ -667,6 +712,7 @@
     // to it, remove the edge to the node (killing the node).
     //
     killIfUselessEdge(CS.getRetVal());
+    killIfUselessEdge(CS.getVAVal());
     for (unsigned a = 0, e = CS.getNumPtrArgs(); a != e; ++a)
       killIfUselessEdge(CS.getPtrArg(a));
 
@@ -883,6 +929,8 @@
   if (CanReachAliveNodes(CS.getRetVal().getNode(), Alive, Visited,
                          IgnoreGlobals))
     return true;
+  if (CanReachAliveNodes(CS.getVAVal().getNode(), Alive, Visited, IgnoreGlobals))
+    return true;
   if (CS.isIndirectCall() &&
       CanReachAliveNodes(CS.getCalleeNode(), Alive, Visited, IgnoreGlobals))
     return true;
@@ -1059,6 +1107,7 @@
 #endif
   }
   AssertNodeInGraph(CS.getRetVal().getNode());
+  AssertNodeInGraph(CS.getVAVal().getNode());
   for (unsigned j = 0, e = CS.getNumPtrArgs(); j != e; ++j)
     AssertNodeInGraph(CS.getPtrArg(j).getNode());
 }
@@ -1099,6 +1148,9 @@
       if (isa<PointerType>(AI->getType()))
         assert(!getNodeForValue(AI).isNull() &&
                "Pointer argument must be in the scalar map!");
+    if (F.isVarArg())
+      assert(VANodes.find(&F) != VANodes.end() &&
+          "VarArg function missing VANode!");
   }
 }
 
@@ -1186,6 +1238,7 @@
     CalleeGraph.getCallSiteForArguments(const_cast<Function&>(Callee));
 
   computeNodeMapping(CalleeArgs.getRetVal(), CS.getRetVal(), NodeMap);
+  computeNodeMapping(CalleeArgs.getVAVal(), CS.getVAVal(), NodeMap);
 
   unsigned NumArgs = CS.getNumPtrArgs();
   if (NumArgs > CalleeArgs.getNumPtrArgs())

Modified: poolalloc/trunk/lib/DSA/DataStructure.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/DataStructure.cpp?rev=106474&r1=106473&r2=106474&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/DataStructure.cpp (original)
+++ poolalloc/trunk/lib/DSA/DataStructure.cpp Mon Jun 21 15:52:30 2010
@@ -813,6 +813,7 @@
 void ReachabilityCloner::mergeCallSite(DSCallSite &DestCS,
                                        const DSCallSite &SrcCS) {
   merge(DestCS.getRetVal(), SrcCS.getRetVal());
+  merge(DestCS.getVAVal(), SrcCS.getVAVal());
   unsigned MinArgs = DestCS.getNumPtrArgs();
   if (SrcCS.getNumPtrArgs() < MinArgs) MinArgs = SrcCS.getNumPtrArgs();
 
@@ -830,11 +831,13 @@
   if (SrcCS.isDirectCall())
     return DSCallSite(SrcCS.getCallSite(),
                       getClonedNH(SrcCS.getRetVal()),
+                      getClonedNH(SrcCS.getVAVal()),
                       SrcCS.getCalleeFunc(),
                       Args);
   else
     return DSCallSite(SrcCS.getCallSite(),
                       getClonedNH(SrcCS.getRetVal()),
+                      getClonedNH(SrcCS.getVAVal()),
                       getClonedNH(SrcCS.getCalleeNode()).getNode(),
                       Args);
 }
@@ -853,6 +856,39 @@
   NH = RC.getClonedNH(Src);
 }
 
+/// FunctionTypeOfCallSite - Helper method to extract the signature of a function
+/// that is called a given CallSite
+///
+const FunctionType *DSCallSite::FunctionTypeOfCallSite(const CallSite & Site) {
+  Value *Callee = Site.getCalledValue();
+
+  // Direct call, simple
+  if (Function *F = dyn_cast<Function>(Callee))
+    return F->getFunctionType();
+
+  // Indirect call, extract the type
+  const FunctionType *CalleeFuncType = NULL;
+
+  const PointerType *CalleeType = dyn_cast<PointerType>(Callee->getType());
+  if (!CalleeType) {
+    assert(0 && "Call through a non-pointer type?");
+  } else {
+    CalleeFuncType = dyn_cast<FunctionType>(CalleeType->getElementType());
+    assert(CalleeFuncType &&
+        "Call through pointer to non-function?");
+  }
+
+  return CalleeFuncType;
+}
+
+/// isVarArg - Determines if the call this represents is to a variable argument
+/// function
+///
+bool DSCallSite::isVarArg() const {
+  const FunctionType *FT = FunctionTypeOfCallSite(Site);
+  return FT->isVarArg();
+}
+
 /// remapLinks - Change all of the Links in the current node according to the
 /// specified mapping.
 ///
@@ -897,6 +933,8 @@
         return true;
       if (CS.isDirectCall() || PathExistsToClonedNode(CS.getCalleeNode()))
         return true;
+      if (PathExistsToClonedNode(CS.getVAVal().getNode()))
+        return true;
       for (unsigned i = 0, e = CS.getNumPtrArgs(); i != e; ++i)
         if (PathExistsToClonedNode(CS.getPtrArg(i).getNode()))
           return true;
@@ -990,6 +1028,7 @@
 
 void DSCallSite::markReachableNodes(DenseSet<const DSNode*> &Nodes) const {
   getRetVal().getNode()->markReachableNodes(Nodes);
+  getVAVal().getNode()->markReachableNodes(Nodes);
   if (isIndirectCall()) getCalleeNode()->markReachableNodes(Nodes);
 
   for (unsigned i = 0, e = getNumPtrArgs(); i != e; ++i)

Modified: poolalloc/trunk/lib/DSA/Local.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/Local.cpp?rev=106474&r1=106473&r2=106474&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/Local.cpp (original)
+++ poolalloc/trunk/lib/DSA/Local.cpp Mon Jun 21 15:52:30 2010
@@ -29,6 +29,7 @@
 #include "llvm/Support/Timer.h"
 #include "llvm/ADT/Statistic.h"
 #include "llvm/ADT/DenseSet.h"
+#include "llvm/ADT/Triple.h"
 
 #include <fstream>
 
@@ -148,6 +149,8 @@
 
     bool visitIntrinsic(CallSite CS, Function* F);
     void visitCallSite(CallSite CS);
+    void visitVAStartInst(CallSite CS);
+    void visitVAStartNode(DSNode* N);
 
   public:
     GraphBuilder(Function &f, DSGraph &g, DataStructures& DSi)
@@ -168,6 +171,9 @@
       // the graph
       g.getOrCreateReturnNodeFor(f);
 
+      // Create a node to handle information about variable arguments
+      g.getOrCreateVANodeFor(f);
+
       visit(f);  // Single pass over the function
 
       // If there are any constant globals referenced in this function, merge
@@ -391,6 +397,7 @@
 }
 
 void GraphBuilder::visitVAArgInst(VAArgInst &I) {
+  assert(0 && "What frontend generates this?");
   //FIXME: also updates the argument
   DSNodeHandle Ptr = getValueDest(I.getOperand(0));
   if (Ptr.isNull()) return;
@@ -604,45 +611,105 @@
   visitCallSite(&II);
 }
 
+void GraphBuilder::visitVAStartInst(CallSite CS) {
+  // Build out DSNodes for the va_list depending on the target arch
+  // And assosiate the right node with the VANode for this function
+  // so it can be merged with the right arguments from callsites
+
+  DSNodeHandle RetNH = getValueDest(*CS.arg_begin());
+
+  if (DSNode *N = RetNH.getNode())
+    visitVAStartNode(N);
+  else
+  {
+    //
+    // Sometimes the argument to the vastart is casted and has no DSNode.
+    // Peer past the cast.
+    //
+    Value * Operand = CS.getInstruction()->getOperand(1);
+    if (CastInst * CI = dyn_cast<CastInst>(Operand))
+      Operand = CI->getOperand (0);
+    const DSNodeHandle & CastNH = getValueDest(Operand);
+    visitVAStartNode(CastNH.getNode());
+    //We assert out here because it's not clear when this happens
+    assert(0 && "When does this happen?");
+  }
+}
+
+void GraphBuilder::visitVAStartNode(DSNode* N) {
+  assert(FB && "No function for this graph?");
+  Module *M = FB->getParent();
+  assert(M && "No module for function");
+  Triple TargetTriple(M->getTargetTriple());
+  Triple::ArchType Arch = TargetTriple.getArch();
+
+  // Fetch the VANode associated with the func containing the call to va_start
+  DSNodeHandle & VANH = G.getVANodeFor(*FB);
+  // Make sure this NodeHandle has a node to go with it
+  if (VANH.isNull()) VANH.mergeWith(createNode());
+
+  // Create a dsnode for an array of pointers to the VAInfo for this func
+  DSNode * VAArray = createNode();
+  VAArray->setArrayMarker();
+  VAArray->foldNodeCompletely();
+  VAArray->setLink(0,VANH);
+
+  //VAStart modifies its argument
+  N->setModifiedMarker();
+
+  // For the architectures we support, build dsnodes that match
+  // how we know va_list is used.
+  switch (Arch) {
+    case Triple::x86:
+      // On x86, we have:
+      // va_list as a pointer to an array of pointers to the variable arguments
+      N->growSize(1);
+      N->setLink(0, VAArray);
+      break;
+    case Triple::x86_64:
+      // On x86_64, we have va_list as a struct {i32, i32, i8*, i8* }
+      // The first i8* is where arguments generally go, but the second i8* can be used
+      // also to pass arguments by register.
+      // We model this by having both the i8*'s point to an array of pointers to the arguments.
+      N->growSize(24); //sizeof the va_list struct mentioned above
+      N->setLink(8,VAArray); //first i8*
+      N->setLink(16,VAArray); //second i8*
+      break;
+    default:
+      // FIXME: For now we abort if we don't know how to handle this arch
+      // Either add support for other architectures, or at least mark the
+      // nodes unknown/incomplete or whichever results in the correct
+      // conservative behavior in the general case
+      assert(0 && "VAstart not supported on this architecture!");
+      //XXX: This might be good enough in those cases that we don't know
+      //what the arch does
+      N->setIncompleteMarker()->setUnknownMarker()->foldNodeCompletely();
+  }
+
+  //XXX: We used to set the alloca marker for the DSNode passed to va_start.
+  //Seems to me that you could allocate the va_list on the heap, so ignoring for now.
+  N->setModifiedMarker()->setVAStartMarker();
+}
+
 /// returns true if the intrinsic is handled
 bool GraphBuilder::visitIntrinsic(CallSite CS, Function *F) {
   ++NumIntrinsicCall;
   switch (F->getIntrinsicID()) {
   case Intrinsic::vastart: {
-    // Mark the memory written by the vastart intrinsic as incomplete
-    DSNodeHandle RetNH = getValueDest(*CS.arg_begin());
-    if (DSNode *N = RetNH.getNode()) {
-      N->setModifiedMarker()->setAllocaMarker()->setIncompleteMarker()
-       ->setVAStartMarker()->setUnknownMarker()->foldNodeCompletely();
-    }
-
-    if (RetNH.hasLink(0)) {
-      DSNodeHandle Link = RetNH.getLink(0);
-      if (DSNode *N = Link.getNode()) {
-        N->setModifiedMarker()->setAllocaMarker()->setIncompleteMarker()
-         ->setVAStartMarker()->setUnknownMarker()->foldNodeCompletely();
-      }
-    } else {
-      //
-      // Sometimes the argument to the vastart is casted and has no DSNode.
-      // Peer past the cast.
-      //
-      Value * Operand = CS.getInstruction()->getOperand(1);
-      if (CastInst * CI = dyn_cast<CastInst>(Operand))
-        Operand = CI->getOperand (0);
-      RetNH = getValueDest(Operand);
-      if (DSNode *N = RetNH.getNode()) {
-        N->setModifiedMarker()->setAllocaMarker()->setIncompleteMarker()
-         ->setVAStartMarker()->setUnknownMarker()->foldNodeCompletely();
-      }
-    }
-
+    visitVAStartInst(CS);
     return true;
   }
-  case Intrinsic::vacopy:
-    getValueDest(CS.getInstruction()).
-      mergeWith(getValueDest(*(CS.arg_begin())));
+  case Intrinsic::vacopy: {
+    // Simply merge the two arguments to va_copy.
+    // This results in loss of precision on the temporaries used to manipulate
+    // the va_list, and so isn't a big deal.  In theory we would build a
+    // separate graph for this (like the one created in visitVAStartNode)
+    // and only merge the node containing the variable arguments themselves.
+    DSNodeHandle destNH = getValueDest(CS.getArgument(0));
+    DSNodeHandle srcNH = getValueDest(CS.getArgument(1));
+    destNH.mergeWith(srcNH);
     return true;
+  }
   case Intrinsic::stacksave: {
     DSNode * Node = createNode();
     Node->setAllocaMarker()->setIncompleteMarker()->setUnknownMarker();
@@ -813,23 +880,64 @@
     }
   }
 
+  //NOTE: This code is identical to 'DSGraph::getDSCallSiteForCallSite',
+  //the reason it's duplicated apparently is so we can increment the
+  //stats 'NumIndirectCall' and 'NumDirectCall'.
+  //FIXME: refactor so we don't have this duplication
+
+  //Get the FunctionType for the called function
+  const FunctionType *CalleeFuncType = DSCallSite::FunctionTypeOfCallSite(CS);
+  unsigned NumFixedArgs = CalleeFuncType->getNumParams();
+
+  // Sanity check--this really, really shouldn't happen
+  if (!CalleeFuncType->isVarArg())
+    assert(CS.arg_size() == NumFixedArgs &&
+        "Too many arguments/incorrect function signature!");
+
   std::vector<DSNodeHandle> Args;
   Args.reserve(CS.arg_end()-CS.arg_begin());
+  DSNodeHandle VarArgNH;
 
   // Calculate the arguments vector...
-  for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end(); I != E; ++I)
-    if (isa<PointerType>((*I)->getType()))
-      Args.push_back(getValueDest(*I));
+  if (!CalleeFuncType->isVarArg()) {
+    // Add all pointer arguments
+    for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
+        I != E; ++I) {
+      if (isa<PointerType>((*I)->getType()))
+        Args.push_back(getValueDest(*I));
+      if (I - CS.arg_begin() >= NumFixedArgs) {
+        errs() << "WARNING: Call contains too many arguments:\n";
+        CS.getInstruction()->dump();
+        assert(0 && "Failing for now");
+      }
+    }
+  } else {
+    // Add all fixed pointer arguments, then merge the rest together
+    for (CallSite::arg_iterator I = CS.arg_begin(), E = CS.arg_end();
+        I != E; ++I)
+      if (isa<PointerType>((*I)->getType())) {
+        DSNodeHandle ArgNode = getValueDest(*I);
+        if (I - CS.arg_begin() < NumFixedArgs) {
+          Args.push_back(ArgNode);
+        } else {
+          VarArgNH.mergeWith(ArgNode);
+        }
+      }
+  }
 
   // Add a new function call entry...
   if (CalleeNode) {
     ++NumIndirectCall;
-    G.getFunctionCalls().push_back(DSCallSite(CS, RetVal, CalleeNode, Args));
+    G.getFunctionCalls().push_back(DSCallSite(CS, RetVal, VarArgNH, CalleeNode,
+                                              Args));
   } else {
     ++NumDirectCall;
-    G.getFunctionCalls().push_back(DSCallSite(CS, RetVal, cast<Function>(Callee),
+    G.getFunctionCalls().push_back(DSCallSite(CS, RetVal, VarArgNH,
+                                              cast<Function>(Callee),
                                               Args));
   }
+
+
 }
 
 // visitInstruction - For all other instruction types, if we have any arguments

Modified: poolalloc/trunk/lib/DSA/Makefile
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/Makefile?rev=106474&r1=106473&r2=106474&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/Makefile (original)
+++ poolalloc/trunk/lib/DSA/Makefile Mon Jun 21 15:52:30 2010
@@ -17,6 +17,13 @@
 endif
 endif
 
+#Bah. Confirmed on llvm-dev, there's no good way for us to do this.
+#Essentially we're tasked with linking in the pieces that our plugin
+#makes use of--but /not/ the tool we're using does /not/ make use of.
+#It's dirty, but apparently what we're stuck with since we're a plugin
+LDFLAGS = $(LLVM_OBJ_ROOT)/lib/Support/$(BuildMode)/Triple.o
+
 include $(LEVEL)/Makefile.common
 
 CFlags += -Wno-deprecated
+

Modified: poolalloc/trunk/lib/DSA/Printer.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/Printer.cpp?rev=106474&r1=106473&r2=106474&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/Printer.cpp (original)
+++ poolalloc/trunk/lib/DSA/Printer.cpp Mon Jun 21 15:52:30 2010
@@ -91,6 +91,7 @@
     if (NodeType & DSNode::ExternalNode   ) OS << "E";
     if (NodeType & DSNode::IntToPtrNode   ) OS << "P";
     if (NodeType & DSNode::PtrToIntNode   ) OS << "2";
+    if (NodeType & DSNode::VAStartNode    ) OS << "V";
 
 #ifndef NDEBUG
     if (NodeType & DSNode::DeadNode       ) OS << "<dead>";
@@ -98,6 +99,15 @@
     OS << "\n";
   }
 
+  //Indicate if this is a VANode for some function
+  for (DSGraph::vanodes_iterator I = G->vanodes_begin(), E = G->vanodes_end();
+      I != E; ++I) {
+    DSNodeHandle VANode = I->second;
+    if (N == VANode.getNode()) {
+      OS << "(VANode for " << I->first->getNameStr() << ")\n";
+    }
+  }
+
   EquivalenceClasses<const GlobalValue*> *GlobalECs = 0;
   if (G) GlobalECs = &G->getGlobalECs();
 
@@ -257,6 +267,8 @@
         GW.emitEdge(&Call, 0, N, EdgeDest, "color=gray63,tailclip=false");
       }
 
+      // FIXME: visualize the VANode?
+
       // Print out the callee...
       if (Call.isIndirectCall()) {
         DSNode *N = Call.getCalleeNode();

Modified: poolalloc/trunk/lib/DSA/TopDownClosure.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/TopDownClosure.cpp?rev=106474&r1=106473&r2=106474&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/TopDownClosure.cpp (original)
+++ poolalloc/trunk/lib/DSA/TopDownClosure.cpp Mon Jun 21 15:52:30 2010
@@ -355,8 +355,8 @@
       // merged into it.  The actual callee function doesn't matter here, so we
       // just pass it something to keep the ctor happy.
       std::vector<DSNodeHandle> ArgDummyVec;
-      DSCallSite DummyCS(CI->getCallSite(), DSNodeHandle(), Callees[0]/*dummy*/,
-                         ArgDummyVec);
+      DSCallSite DummyCS(CI->getCallSite(), DSNodeHandle(), DSNodeHandle(),
+                         Callees[0]/*dummy*/, ArgDummyVec);
       IndCallGraph->getFunctionCalls().push_back(DummyCS);
 
       IndCallRecI = IndCallMap.insert(IndCallRecI,





More information about the llvm-commits mailing list