[llvm-commits] [poolalloc] r107703 - in /poolalloc/trunk: include/dsa/DataStructure.h lib/DSA/DSTest.cpp lib/DSA/Printer.cpp
Will Dietz
wdietz2 at illinois.edu
Tue Jul 6 14:30:46 PDT 2010
Author: wdietz2
Date: Tue Jul 6 16:30:46 2010
New Revision: 107703
URL: http://llvm.org/viewvc/llvm-project?rev=107703&view=rev
Log:
Added "DSTest" code to facilitate tests querying DSA information.
Added:
poolalloc/trunk/lib/DSA/DSTest.cpp
Modified:
poolalloc/trunk/include/dsa/DataStructure.h
poolalloc/trunk/lib/DSA/Printer.cpp
Modified: poolalloc/trunk/include/dsa/DataStructure.h
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/include/dsa/DataStructure.h?rev=107703&r1=107702&r2=107703&view=diff
==============================================================================
--- poolalloc/trunk/include/dsa/DataStructure.h (original)
+++ poolalloc/trunk/include/dsa/DataStructure.h Tue Jul 6 16:30:46 2010
@@ -98,6 +98,10 @@
void print(llvm::raw_ostream &O, const Module *M) const;
void dumpCallGraph() const;
+ /// printTestInfo - Print answers to queries made by tests
+ ///
+ void printTestInfo(llvm::raw_ostream &O, const Module *M) const;
+
virtual void releaseMemory();
virtual bool hasDSGraph(const Function &F) const {
Added: poolalloc/trunk/lib/DSA/DSTest.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/DSTest.cpp?rev=107703&view=auto
==============================================================================
--- poolalloc/trunk/lib/DSA/DSTest.cpp (added)
+++ poolalloc/trunk/lib/DSA/DSTest.cpp Tue Jul 6 16:30:46 2010
@@ -0,0 +1,320 @@
+//===- DSTest.cpp - Code for quering DSA results for testing --------------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file was developed by the LLVM research group and is distributed under
+// the University of Illinois Open Source License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a few basic operations that allow tests to query
+// properties of the DSGraph, with an emphasis on making results something
+// that is can be easily verified by 'grep' or similar basic commands.
+//
+//===----------------------------------------------------------------------===//
+
+#define DEBUG_TYPE "dsgraph-test"
+
+#include "dsa/DataStructure.h"
+#include "dsa/DSGraph.h"
+#include "dsa/DSNode.h"
+#include "llvm/Module.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/raw_ostream.h"
+#include "llvm/ValueSymbolTable.h"
+#include "llvm/Assembly/Writer.h"
+using namespace llvm;
+
+namespace {
+ //FIXME: being able to separate -print-node-for-value options with commas would be nice...
+ cl::list<std::string> PrintNodesForValues("print-node-for-value", cl::ReallyHidden);
+ cl::opt<bool> OnlyPrintFlags("print-only-flags", cl::ReallyHidden);
+ cl::opt<bool> OnlyPrintValues("print-only-values", cl::ReallyHidden);
+ cl::opt<bool> OnlyPrintTypes("print-only-types", cl::ReallyHidden);
+}
+
+/// NodeValue -- represents a particular node in a DSGraph
+/// constructed from a serialized string representation of a value
+///
+/// FIXME: Make this integrated into cl parsing, as mentioned:
+/// http://llvm.org/docs/CommandLine.html#customparser
+///
+/// Supported formats (so far)
+/// graph:value[:offset]*
+/// Examples:
+/// "value" specifies 'value' in the globals graph
+/// "func:value" specifies 'value' in graph for function 'func'
+/// "func:value:0" the node pointed to at offset 0 from the above
+/// "func:value:0:1" the node pointed to at offset 1 from the above
+/// ..etc
+/// We are also robust to "@value" and "@func" notation for convenience
+/// FIXME: Support querying special nodes like return nodes, VANodes, etc
+class NodeValue {
+ // Containing Function, if applicable.
+ Function *F;
+ // Value in that graph's scalarmap that we base off of
+ // (note that the NH we have below could be indexed a few times
+ // from this value, only corresponds directly if no offsets)
+ Value *V;
+ // DSNodehandle
+ DSNodeHandle NH;
+
+ // String version (that we were given)
+ StringRef serialized;
+
+ // Parsed list of offsets
+ typedef SmallVector<unsigned,3> OffsetVectorTy;
+ OffsetVectorTy offsets;
+
+ NodeValue() {};
+ void operator=(const NodeValue&);
+ NodeValue(const NodeValue&);
+
+ void initialize(const Module *M, const DataStructures *DS) {
+ parseValue(M);
+ assert(V && "Failed to parse value?");
+ if (isa<GlobalValue>(V)) {
+ DSGraph *G = DS->getGlobalsGraph();
+ assert(G->hasNodeForValue(V) && "Node not in specified graph!");
+ NH = G->getNodeForValue(V);
+ } else {
+ assert(F && "No function?");
+ DSGraph *G = DS->getDSGraph(*F);
+ assert(G->hasNodeForValue(V) && "Node not in specified graph!");
+ NH = G->getNodeForValue(V);
+ }
+ // Handle offsets, if any
+ // For each offset in the offsets vector, follow the link at that offset
+ for (OffsetVectorTy::const_iterator I = offsets.begin(), E = offsets.end();
+ I != E; ++I ) {
+ assert(!NH.isNull() && "Null NodeHandle?");
+ assert(NH.hasLink(*I) && "Handle doesn't have link?");
+ // Follow the offset
+ NH = NH.getLink(*I);
+ }
+ }
+
+ /// parseValue -- sets value for the string we were constructed on,
+ /// using the provided module as the context to find the value
+ void parseValue(const Module *M) {
+ unsigned count = serialized.count(':');
+ if (count == 0) {
+ // Global case
+ // format: "[@]value"
+ StringRef globalName = stripAtIfRequired(serialized);
+
+ V = M->getNamedValue(globalName);
+ assert(V && "Unable to find specified global!");
+ } else { // count >= 1
+ // Function-specific case
+ // format: "[@]func:value"
+ // format: "[@]func:value:offset0:offset1:offset2"
+
+ std::pair<StringRef,StringRef> split = serialized.split(':');
+ StringRef func = stripAtIfRequired(split.first);
+ StringRef value = split.second;
+
+ if (count > 1) {
+ //If we have more semicolons, split them off to get the value and offsets
+ std::pair<StringRef,StringRef> tmp = value.split(':');
+ value = tmp.first;
+ StringRef offStrings = tmp.second;
+
+ //Small detour--parse offsets into vector
+ unsigned offset;
+ while(offStrings.count(':') > 0) {
+ tmp = offStrings.split(':');
+ assert(!tmp.first.getAsInteger(0,offset) && "failed to parse offset!");
+ offsets.push_back(offset);
+ offStrings = tmp.second;
+ }
+ assert(!offStrings.getAsInteger(0,offset) && "failed to parse offset!");
+ offsets.push_back(offset);
+ }
+ // Now back to your regularly scheduled programming...
+
+ // First, find the function
+ F = M->getFunction(func);
+ assert(F && "Unable to find function specified!");
+
+ // Now we try to find the value...
+ // FIXME: This only works for named values, things like "%1" don't work.
+ // That might not be a deal breaker, but should be clear.
+ V = F->getValueSymbolTable().lookup(value);
+
+ assert(V && "Unable to find value in specified function!");
+
+ }
+
+ assert(V && "Parsing value failed!");
+ }
+
+ /// stripAtIfRequired -- removes the leading '@' character if one exists
+ ///
+ StringRef stripAtIfRequired(StringRef v) {
+ if (!v.startswith("@"))
+ return v;
+
+ assert(v.size() > 1 && "String too short");
+
+ return v.substr(1);
+ }
+public:
+ /// Constructor (from string)
+ NodeValue(std::string & raw, const Module * M, const DataStructures *DS)
+ : F(NULL), V(NULL), serialized(raw) {
+ initialize(M,DS);
+ assert(V && NH.getNode() && "Parse failed!");
+ };
+
+ /// Accessors
+ DSNodeHandle & getNodeH() { return NH; }
+ DSGraph * getGraph() { return getNode()->getParentGraph(); }
+ // FIXME: These two (value/function) aren't used presently, and furthermore
+ // are a bit confusing in the context of offsets. Make this not lame.
+ Value * getValue() { return V; }
+ Function * getFunction() { return F; }
+
+ //Helper to fetch the node from the nodehandle
+ DSNode * getNode() {
+ assert(NH.getNode() && "NULL node?");
+ return NH.getNode();
+ }
+};
+
+/// printAllValuesForNode -- prints all values for a given node, without a newline
+/// (meant to be a helper)
+static void printAllValuesForNode(llvm::raw_ostream &O, NodeValue &NV) {
+ // We only consider other values that are in the graph
+ // containing the specified node (by design)
+
+ // Look for values that have an equivalent NH
+ DSNodeHandle &NH = NV.getNodeH();
+ const DSGraph::ScalarMapTy &SM = NV.getGraph()->getScalarMap();
+ bool first = true;
+
+ for (DSGraph::ScalarMapTy::const_iterator I = SM.begin(), E = SM.end();
+ I != E; ++I )
+ if (NH == I->second) {
+ //Found one!
+ const Value *V = I->first;
+
+ //Print them out, separated by commas
+ if (!first) O << ",";
+ first = false;
+
+ // Print out name, if it has one.
+ // FIXME: Get "%0, "%1", naming like the .ll has?
+ if (V->hasName())
+ O << V->getName();
+ else
+ O << "<tmp>";
+ }
+
+ //FIXME: Search globals in this graph too (not just scalarMap)?
+}
+
+// printTypesForNode --prints all the types for the given NodeValue, without a newline
+// (meant to be called as a helper)
+static void printTypesForNode(llvm::raw_ostream &O, NodeValue &NV) {
+ DSNode *N = NV.getNode();
+ Module *M = NV.getFunction()->getParent();
+
+ if (N->isNodeCompletelyFolded()) {
+ O << "Folded";
+ }
+
+ // Go through all the types, and just dump them.
+ // FIXME: Lifted from Printer.cpp, probably should be shared
+ if (N->type_begin() != N->type_end())
+ for (DSNode::TyMapTy::const_iterator ii = N->type_begin(),
+ ee = N->type_end(); ii != ee; ++ii) {
+ O << ii->first << ": ";
+ if (ii->second) {
+ bool first = true;
+ for (svset<const Type*>::const_iterator ni = ii->second->begin(),
+ ne = ii->second->end(); ni != ne; ++ni) {
+ if (!first) O << ",";
+ WriteTypeSymbolic(O, *ni, M);
+ first = false;
+ }
+ }
+ else
+ O << "VOID";
+ O << " ";
+ }
+ else
+ O << "VOID";
+
+ if (N->isArrayNode())
+ O << " array";
+}
+
+static void printFlags(llvm::raw_ostream &O, DSNode *N) {
+ // FIXME: This code is lifted directly from Printer.cpp
+ // Probably would be good to make this code shared...
+ // Leaving it separate for now to minimize invasiveness
+ if (unsigned NodeType = N->getNodeFlags()) {
+ if (NodeType & DSNode::AllocaNode ) O << "S";
+ if (NodeType & DSNode::HeapNode ) O << "H";
+ if (NodeType & DSNode::GlobalNode ) O << "G";
+ if (NodeType & DSNode::UnknownNode ) O << "U";
+ if (NodeType & DSNode::IncompleteNode ) O << "I";
+ if (NodeType & DSNode::ModifiedNode ) O << "M";
+ if (NodeType & DSNode::ReadNode ) O << "R";
+ if (NodeType & DSNode::ExternalNode ) O << "E";
+ if (NodeType & DSNode::IntToPtrNode ) O << "P";
+ if (NodeType & DSNode::PtrToIntNode ) O << "2";
+ if (NodeType & DSNode::VAStartNode ) O << "V";
+ }
+}
+
+/// printNodes -- print the node specified by NV
+///
+/// Format:
+/// (can a type include '{}'s, etc?)
+/// "flags:{value(s)}:{type(s)}"
+///
+/// Additionally, the user can specify to print just one piece
+static void printNode(llvm::raw_ostream &O, NodeValue &NV) {
+ assert(
+ ((!OnlyPrintFlags && !OnlyPrintValues)||
+ (!OnlyPrintFlags && !OnlyPrintTypes) ||
+ (!OnlyPrintValues && !OnlyPrintTypes)) &&
+ "Only one \"Only\" option allowed!");
+
+ if (OnlyPrintFlags) {
+ printFlags(O,NV.getNode());
+ } else if (OnlyPrintValues) {
+ printAllValuesForNode(O, NV);
+ } else if (OnlyPrintTypes) {
+ printTypesForNode(O,NV);
+ } else {
+ //Print all of them
+ printFlags(O,NV.getNode());
+ O << ":{";
+ printAllValuesForNode(O, NV);
+ O << "}:{";
+ printTypesForNode(O,NV);
+ O << "}";
+ }
+
+ O << "\n";
+}
+
+/// printTestInfo -- runs through the user-specified testing arguments (if any)
+/// and prints the requested information.
+void DataStructures::printTestInfo(llvm::raw_ostream &O, const Module *M) const {
+
+ // For each node the user indicated, print the node.
+ // See 'printNode' for more details.
+ for (cl::list<std::string>::iterator I = PrintNodesForValues.begin(),
+ E = PrintNodesForValues.end(); I != E; ++I ) {
+ // Make sense of what the user gave us
+ NodeValue NV(*I, M, this);
+ // Print corresponding node
+ printNode(O, NV);
+ }
+}
+
Modified: poolalloc/trunk/lib/DSA/Printer.cpp
URL: http://llvm.org/viewvc/llvm-project/poolalloc/trunk/lib/DSA/Printer.cpp?rev=107703&r1=107702&r2=107703&view=diff
==============================================================================
--- poolalloc/trunk/lib/DSA/Printer.cpp (original)
+++ poolalloc/trunk/lib/DSA/Printer.cpp Tue Jul 6 16:30:46 2010
@@ -34,6 +34,7 @@
cl::list<std::string> OnlyPrint("dsa-only-print", cl::ReallyHidden);
cl::opt<bool> DontPrintAnything("dont-print-ds", cl::ReallyHidden);
cl::opt<bool> LimitPrint("dsa-limit-print", cl::Hidden);
+ cl::opt<bool> PrintDSATest("dstest", cl::ReallyHidden);
STATISTIC (MaxGraphSize , "Maximum graph size");
STATISTIC (NumFoldedNodes , "Number of folded nodes (in final graph)");
}
@@ -401,6 +402,10 @@
// print - Print out the analysis results...
void DataStructures::print(llvm::raw_ostream &O, const Module *M) const {
if (DontPrintAnything) return;
+ if (PrintDSATest) {
+ printTestInfo(O, M);
+ return;
+ }
printCollection(*this, O, M, printname);
//dumpCallGraph();
}
More information about the llvm-commits
mailing list