diff --git a/lib/Analysis/DataStructure/BottomUpClosure.cpp b/lib/Analysis/DataStructure/BottomUpClosure.cpp index defd80e308f..08c86c5e124 100644 --- a/lib/Analysis/DataStructure/BottomUpClosure.cpp +++ b/lib/Analysis/DataStructure/BottomUpClosure.cpp @@ -16,8 +16,7 @@ using std::map; static RegisterAnalysis X("budatastructure", "Bottom-up Data Structure Analysis Closure"); -// TODO: FIXME -namespace DataStructureAnalysis { +namespace DataStructureAnalysis { // TODO: FIXME: Eliminate // isPointerType - Return true if this first class type is big enough to hold // a pointer. // @@ -60,14 +59,12 @@ static void ResolveArguments(DSCallSite &Call, Function &F, map &ValueMap) { // Resolve all of the function arguments... Function::aiterator AI = F.abegin(); - for (unsigned i = 0, e = Call.getNumPtrArgs(); i != e; ++i) { + for (unsigned i = 0, e = Call.getNumPtrArgs(); i != e; ++i, ++AI) { // Advance the argument iterator to the first pointer argument... while (!isPointerType(AI->getType())) ++AI; // Add the link from the argument scalar to the provided value - DSNodeHandle &NN = ValueMap[AI]; - NN.addEdgeTo(Call.getPtrArg(i)); - ++AI; + ValueMap[AI].mergeWith(Call.getPtrArg(i)); } } @@ -118,8 +115,7 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) { DEBUG(std::cerr << "\t[BU] Self Inlining: " << F.getName() << "\n"); // Handle the return value if present... - if (Call.getRetVal().getNode()) - Graph->getRetNode().mergeWith(Call.getRetVal()); + Graph->getRetNode().mergeWith(Call.getRetVal()); // Resolve the arguments in the call to the actual values... ResolveArguments(Call, F, Graph->getValueMap()); @@ -143,11 +139,12 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) { // Record that the original DSCallSite was a call site of FI. // This may or may not have been known when the DSCallSite was // originally created. +#if 1 /// FIXME: Reenable std::vector &CallSitesForFunc = CallSites[&FI]; CallSitesForFunc.push_back(Call); CallSitesForFunc.back().setResolvingCaller(&F); CallSitesForFunc.back().setCallee(0); - +#endif // Clone the callee's graph into the current graph, keeping // track of where scalars in the old graph _used_ to point, // and of the new nodes matching nodes of the old graph. @@ -163,8 +160,8 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) { // Resolve the arguments in the call to the actual values... ResolveArguments(Call, FI, OldValMap); - if (Call.getRetVal().getNode())// Handle the return value if present - RetVal.mergeWith(Call.getRetVal()); + // Handle the return value if present... + RetVal.mergeWith(Call.getRetVal()); // Erase the entry in the Callees vector Callees.erase(Callees.begin()+c--); @@ -172,9 +169,10 @@ DSGraph &BUDataStructures::calculateGraph(Function &F) { } else if (FI.getName() == "printf" || FI.getName() == "sscanf" || FI.getName() == "fprintf" || FI.getName() == "open" || FI.getName() == "sprintf") { - // FIXME: These special cases should go away when we can define - // functions that take a variable number of arguments. + // FIXME: These special cases (eg printf) should go away when we can + // define functions that take a variable number of arguments. + // FIXME: at the very least, this should update mod/ref info // Erase the entry in the globals vector Callees.erase(Callees.begin()+c--); } diff --git a/lib/Analysis/DataStructure/DataStructure.cpp b/lib/Analysis/DataStructure/DataStructure.cpp index 44ecd01ab7e..2aadc000f6c 100644 --- a/lib/Analysis/DataStructure/DataStructure.cpp +++ b/lib/Analysis/DataStructure/DataStructure.cpp @@ -16,8 +16,7 @@ using std::vector; -// TODO: FIXME -namespace DataStructureAnalysis { +namespace DataStructureAnalysis { // TODO: FIXME // isPointerType - Return true if this first class type is big enough to hold // a pointer. // @@ -538,14 +537,15 @@ void DSNode::remapLinks(std::map &OldNodeMap) { // cloneInto - Clone the specified DSGraph into the current graph, returning the // Return node of the graph. The translated ValueMap for the old function is -// filled into the OldValMap member. If StripLocals is set to true, Scalar and -// Alloca markers are removed from the graph, as the graph is being cloned into -// a calling function's graph. +// filled into the OldValMap member. If StripAllocas is set to true, Alloca +// markers are removed from the graph, as the graph is being cloned into a +// calling function's graph. // DSNodeHandle DSGraph::cloneInto(const DSGraph &G, std::map &OldValMap, std::map &OldNodeMap, - bool StripScalars, bool StripAllocas) { + bool StripScalars, // FIXME: Kill StripScalars + bool StripAllocas) { assert(OldNodeMap.empty() && "Returned OldNodeMap should be empty!"); unsigned FN = Nodes.size(); // First new node... @@ -564,8 +564,7 @@ DSNodeHandle DSGraph::cloneInto(const DSGraph &G, Nodes[i]->remapLinks(OldNodeMap); // Remove local markers as specified - unsigned char StripBits = (StripScalars ? DSNode::ScalarNode : 0) | - (StripAllocas ? DSNode::AllocaNode : 0); + unsigned char StripBits = StripAllocas ? DSNode::AllocaNode : 0; if (StripBits) for (unsigned i = FN, e = Nodes.size(); i != e; ++i) Nodes[i]->NodeType &= ~StripBits; @@ -574,7 +573,8 @@ DSNodeHandle DSGraph::cloneInto(const DSGraph &G, for (std::map::const_iterator I = G.ValueMap.begin(), E = G.ValueMap.end(); I != E; ++I) { DSNodeHandle &H = OldValMap[I->first]; - H = DSNodeHandle(OldNodeMap[I->second.getNode()], I->second.getOffset()); + H.setNode(OldNodeMap[I->second.getNode()]); + H.setOffset(I->second.getOffset()); if (isa(I->first)) { // Is this a global? std::map::iterator GVI = ValueMap.find(I->first); @@ -655,11 +655,8 @@ void DSGraph::markIncompleteNodes(bool markFormalArgs) { // Mark any incoming arguments as incomplete... if (markFormalArgs && Func) for (Function::aiterator I = Func->abegin(), E = Func->aend(); I != E; ++I) - if (isPointerType(I->getType()) && ValueMap.find(I) != ValueMap.end()) { - DSNodeHandle &INH = ValueMap[I]; - if (INH.getNode() && INH.hasLink(0)) - markIncompleteNode(ValueMap[I].getLink(0)->getNode()); - } + if (isPointerType(I->getType()) && ValueMap.find(I) != ValueMap.end()) + markIncompleteNode(ValueMap[I].getNode()); // Mark stuff passed into functions calls as being incomplete... for (unsigned i = 0, e = FunctionCalls.size(); i != e; ++i) { @@ -667,17 +664,16 @@ void DSGraph::markIncompleteNodes(bool markFormalArgs) { // Then the return value is certainly incomplete! markIncompleteNode(Call.getRetVal().getNode()); - // The call does not make the function argument incomplete... - - // All arguments to the function call are incomplete though! + // All objects pointed to by function arguments are incomplete though! for (unsigned i = 0, e = Call.getNumPtrArgs(); i != e; ++i) markIncompleteNode(Call.getPtrArg(i).getNode()); } - // Mark all of the nodes pointed to by global or cast nodes as incomplete... + // Mark all of the nodes pointed to by global nodes as incomplete... for (unsigned i = 0, e = Nodes.size(); i != e; ++i) if (Nodes[i]->NodeType & DSNode::GlobalNode) { DSNode *N = Nodes[i]; + // FIXME: Make more efficient by looking over Links directly for (unsigned i = 0, e = N->getSize(); i != e; ++i) if (DSNodeHandle *DSNH = N->getLink(i)) markIncompleteNode(DSNH->getNode()); @@ -706,9 +702,7 @@ bool DSGraph::isNodeDead(DSNode *N) { return true; // Is it a function node or some other trivially unused global? - if (N->NodeType != 0 && - (N->NodeType & ~DSNode::GlobalNode) == 0 && - N->getSize() == 0 && + if ((N->NodeType & ~DSNode::GlobalNode) == 0 && N->getSize() == 0 && N->getReferrers().size() == N->getGlobals().size()) { // Remove the globals from the ValueMap, so that the referrer count will go @@ -758,6 +752,7 @@ static void markAlive(DSNode *N, std::set &Alive) { if (N == 0) return; Alive.insert(N); + // FIXME: Make more efficient by looking over Links directly for (unsigned i = 0, e = N->getSize(); i != e; ++i) if (DSNodeHandle *DSNH = N->getLink(i)) if (!Alive.count(DSNH->getNode())) @@ -887,7 +882,7 @@ static void markGlobalsAlive(DSGraph &G, std::set &Alive, markGlobalsIteration(GlobalNodes, Calls, Alive, FilterCalls); // Free up references to dead globals from the ValueMap - std::set::iterator I=GlobalNodes.begin(), E=GlobalNodes.end(); + std::set::iterator I = GlobalNodes.begin(), E = GlobalNodes.end(); for( ; I != E; ++I) if (Alive.count(*I) == 0) removeRefsToGlobal(*I, G.getValueMap()); @@ -931,19 +926,20 @@ void DSGraph::removeDeadNodes(bool KeepAllGlobals, bool KeepCalls) { markAlive(FunctionCalls[i].getCallee().getNode(), Alive); } -#if 0 - for (unsigned i = 0, e = OrigFunctionCalls.size(); i != e; ++i) - for (unsigned j = 0, e = OrigFunctionCalls[i].size(); j != e; ++j) - markAlive(OrigFunctionCalls[i][j].getNode(), Alive); -#endif + // Mark all nodes reachable by scalar nodes as alive... + for (std::map::iterator I = ValueMap.begin(), + E = ValueMap.end(); I != E; ++I) + markAlive(I->second.getNode(), Alive); - // Mark all nodes reachable by scalar nodes (and global nodes, if - // keeping them was specified) as alive... - unsigned char keepBits = DSNode::ScalarNode | - (KeepAllGlobals ? DSNode::GlobalNode : 0); - for (unsigned i = 0, e = Nodes.size(); i != e; ++i) - if (Nodes[i]->NodeType & keepBits) - markAlive(Nodes[i], Alive); +#if 0 + // Marge all nodes reachable by global nodes, as alive. Isn't this covered by + // the ValueMap? + // + if (KeepAllGlobals) + for (unsigned i = 0, e = Nodes.size(); i != e; ++i) + if (Nodes[i]->NodeType & DSNode::GlobalNode) + markAlive(Nodes[i], Alive); +#endif // The return value is alive as well... markAlive(RetNode.getNode(), Alive); @@ -952,7 +948,7 @@ void DSGraph::removeDeadNodes(bool KeepAllGlobals, bool KeepCalls) { // This also marks all nodes reachable from such nodes as alive. // Of course, if KeepAllGlobals is specified, they would be live already. if (!KeepAllGlobals) - markGlobalsAlive(*this, Alive, ! KeepCalls); + markGlobalsAlive(*this, Alive, !KeepCalls); // Loop over all unreachable nodes, dropping their references... vector DeadNodes; diff --git a/lib/Analysis/DataStructure/Local.cpp b/lib/Analysis/DataStructure/Local.cpp index dddd54ad492..456eb2f3335 100644 --- a/lib/Analysis/DataStructure/Local.cpp +++ b/lib/Analysis/DataStructure/Local.cpp @@ -61,7 +61,6 @@ namespace { vector &Nodes; DSNodeHandle &RetNode; // Node that gets returned... map &ValueMap; - map GlobalScalarValueMap; vector &FunctionCalls; public: @@ -107,23 +106,21 @@ namespace { /// createNode - Create a new DSNode, ensuring that it is properly added to /// the graph. /// - DSNode *createNode(DSNode::NodeTy NodeType, const Type *Ty); + DSNode *createNode(DSNode::NodeTy NodeType, const Type *Ty = 0) { + DSNode *N = new DSNode(NodeType, Ty); // Create the node + Nodes.push_back(N); // Add node to nodes list + return N; + } - /// getValueNode - Return a DSNode that corresponds the the specified LLVM - /// value. This either returns the already existing node, or creates a new - /// one and adds it to the graph, if none exists. + /// setDestTo - Set the ValueMap entry for the specified value to point to + /// the specified destination. If the Value already points to a node, make + /// sure to merge the two destinations together. /// - DSNodeHandle &getValueNode(Value &V); + void setDestTo(Value &V, const DSNodeHandle &NH); - /// getValueDest - Return the DSNode that the actual value points to. This - /// is the same thing as: getLink(getValueNode(V)) + /// getValueDest - Return the DSNode that the actual value points to. /// - DSNodeHandle &getValueDest(Value &V); - - /// getGlobalNode - Just like getValueNode, except the global node itself is - /// returned, not a scalar node pointing to a global. - /// - DSNodeHandle &getGlobalNode(GlobalValue &V); + DSNodeHandle getValueDest(Value &V); /// getLink - This method is used to return the specified link in the /// specified node if one exists. If a link does not already exist (it's @@ -148,78 +145,34 @@ DSGraph::DSGraph(Function &F) : Func(&F) { // -// createNode - Create a new DSNode, ensuring that it is properly added to the -// graph. -// -DSNode *GraphBuilder::createNode(DSNode::NodeTy NodeType, const Type *Ty) { - DSNode *N = new DSNode(NodeType, Ty); - Nodes.push_back(N); - return N; -} - - -// getGlobalNode - Just like getValueNode, except the global node itself is -// returned, not a scalar node pointing to a global. -// -DSNodeHandle &GraphBuilder::getGlobalNode(GlobalValue &V) { - DSNodeHandle &NH = ValueMap[&V]; - if (NH.getNode()) return NH; // Already have a node? Just return it... - - // Create a new global node for this global variable... - DSNode *G = createNode(DSNode::GlobalNode, V.getType()->getElementType()); - G->addGlobal(&V); - - // If this node has outgoing edges, make sure to recycle the same node for - // each use. For functions and other global variables, this is unneccesary, - // so avoid excessive merging by cloning these nodes on demand. - // - NH.setNode(G); - return NH; -} - - -// getValueNode - Return a DSNode that corresponds the the specified LLVM value. -// This either returns the already existing node, or creates a new one and adds -// it to the graph, if none exists. -// -DSNodeHandle &GraphBuilder::getValueNode(Value &V) { - assert(isPointerType(V.getType()) && "Should only use pointer scalars!"); - - if (GlobalValue *GV = dyn_cast(&V)) { - // The GlobalScalarValueMap keeps track of the scalar nodes that point to - // global values... The ValueMap contains pointers to the global memory - // object itself, not the scalar constant that points to the memory. - // - DSNodeHandle &NH = GlobalScalarValueMap[GV]; - if (NH.getNode()) return NH; - - // If this is a global value, create the global pointed to. - DSNode *N = createNode(DSNode::ScalarNode, V.getType()); - NH.setOffset(0); - NH.setNode(N); - - N->addEdgeTo(0, getGlobalNode(*GV)); - return NH; - - } else { - DSNodeHandle &NH = ValueMap[&V]; - if (NH.getNode()) - return NH; // Already have a node? Just return it... - - // Otherwise we need to create a new scalar node... - DSNode *N = createNode(DSNode::ScalarNode, V.getType()); - - NH.setOffset(0); - NH.setNode(N); - return NH; - } -} - -/// getValueDest - Return the DSNode that the actual value points to. This is -/// the same thing as: getLink(getValueNode(V), 0) +/// getValueDest - Return the DSNode that the actual value points to. /// -DSNodeHandle &GraphBuilder::getValueDest(Value &V) { - return getLink(getValueNode(V)); +DSNodeHandle GraphBuilder::getValueDest(Value &V) { + if (Constant *C = dyn_cast(&V)) { + // FIXME: Return null NH for constants like 10 or null + // FIXME: Handle constant exprs here. + + return 0; // Constant doesn't point to anything. + } + + DSNodeHandle &NH = ValueMap[&V]; + if (NH.getNode()) + return NH; // Already have a node? Just return it... + + // Otherwise we need to create a new node to point to... + DSNode *N; + if (GlobalValue *GV = dyn_cast(&V)) { + // Create a new global node for this global variable... + N = createNode(DSNode::GlobalNode, GV->getType()->getElementType()); + N->addGlobal(GV); + } else { + // Otherwise just create a shadow node + N = createNode(DSNode::ShadowNode); + } + + NH.setNode(N); // Remember that we are pointing to it... + NH.setOffset(0); + return NH; } @@ -235,12 +188,25 @@ DSNodeHandle &GraphBuilder::getLink(const DSNodeHandle &node, unsigned LinkNo) { if (Link) return *Link; // If the link hasn't been created yet, make and return a new shadow node - DSNode *N = createNode(DSNode::ShadowNode, 0); + DSNode *N = createNode(DSNode::ShadowNode); Node.setLink(LinkNo, N); return *Node.getLink(LinkNo); } +/// setDestTo - Set the ValueMap entry for the specified value to point to the +/// specified destination. If the Value already points to a node, make sure to +/// merge the two destinations together. +/// +void GraphBuilder::setDestTo(Value &V, const DSNodeHandle &NH) { + DSNodeHandle &AINH = ValueMap[&V]; + if (AINH.getNode() == 0) // Not pointing to anything yet? + AINH = NH; // Just point directly to NH + else + AINH.mergeWith(NH); +} + + //===----------------------------------------------------------------------===// // Specific instruction type handler implementations... // @@ -249,10 +215,7 @@ DSNodeHandle &GraphBuilder::getLink(const DSNodeHandle &node, unsigned LinkNo) { /// object, pointing the scalar to it. /// void GraphBuilder::handleAlloc(AllocationInst &AI, DSNode::NodeTy NodeType) { - DSNode *New = createNode(NodeType, 0); - - // Make the scalar point to the new node... - getValueNode(AI).addEdgeTo(New); + setDestTo(AI, createNode(NodeType)); } // PHINode - Make the scalar for the PHI node point to all of the things the @@ -261,14 +224,14 @@ void GraphBuilder::handleAlloc(AllocationInst &AI, DSNode::NodeTy NodeType) { void GraphBuilder::visitPHINode(PHINode &PN) { if (!isPointerType(PN.getType())) return; // Only pointer PHIs - DSNodeHandle &ScalarDest = getValueDest(PN); + DSNodeHandle &PNDest = ValueMap[&PN]; for (unsigned i = 0, e = PN.getNumIncomingValues(); i != e; ++i) - if (!isa(PN.getIncomingValue(i))) - ScalarDest.mergeWith(getValueDest(*PN.getIncomingValue(i))); + PNDest.mergeWith(getValueDest(*PN.getIncomingValue(i))); } void GraphBuilder::visitGetElementPtrInst(GetElementPtrInst &GEP) { DSNodeHandle Value = getValueDest(*GEP.getOperand(0)); + if (Value.getNode() == 0) return; unsigned Offset = 0; const PointerType *PTy = cast(GEP.getOperand(0)->getType()); @@ -278,7 +241,7 @@ void GraphBuilder::visitGetElementPtrInst(GetElementPtrInst &GEP) { // If the node had to be folded... exit quickly if (TopTypeRec.Ty == Type::VoidTy) { - getValueNode(GEP).addEdgeTo(Value); // GEP result points to folded node + setDestTo(GEP, Value); // GEP result points to folded node return; } @@ -297,7 +260,7 @@ void GraphBuilder::visitGetElementPtrInst(GetElementPtrInst &GEP) { if (Value.getOffset()) { // Value is now the pointer we want to GEP to be... Value.getNode()->foldNodeCompletely(); - getValueNode(GEP).addEdgeTo(Value); // GEP result points to folded node + setDestTo(GEP, Value); // GEP result points to folded node return; } else { // This is a pointer to the first byte of the node. Make sure that we @@ -346,56 +309,51 @@ void GraphBuilder::visitGetElementPtrInst(GetElementPtrInst &GEP) { Value.setOffset(Value.getOffset()+Offset); // Value is now the pointer we want to GEP to be... - getValueNode(GEP).addEdgeTo(Value); + setDestTo(GEP, Value); } void GraphBuilder::visitLoadInst(LoadInst &LI) { - DSNodeHandle &Ptr = getValueDest(*LI.getOperand(0)); + DSNodeHandle Ptr = getValueDest(*LI.getOperand(0)); + if (Ptr.getNode() == 0) return; + + // Make that the node is read from... Ptr.getNode()->NodeType |= DSNode::Read; // Ensure a typerecord exists... Ptr.getNode()->getTypeRec(LI.getType(), Ptr.getOffset()); - + if (isPointerType(LI.getType())) - getValueNode(LI).addEdgeTo(getLink(Ptr)); + setDestTo(LI, getLink(Ptr)); } void GraphBuilder::visitStoreInst(StoreInst &SI) { - DSNodeHandle &Dest = getValueDest(*SI.getOperand(1)); - Dest.getNode()->NodeType |= DSNode::Modified; const Type *StoredTy = SI.getOperand(0)->getType(); + DSNodeHandle Dest = getValueDest(*SI.getOperand(1)); + if (Dest.getNode() == 0) return; + + // Make that the node is written to... + Dest.getNode()->NodeType |= DSNode::Modified; // Ensure a typerecord exists... Dest.getNode()->getTypeRec(StoredTy, Dest.getOffset()); // Avoid adding edges from null, or processing non-"pointer" stores - if (isPointerType(StoredTy) && - !isa(SI.getOperand(0))) { + if (isPointerType(StoredTy)) Dest.addEdgeTo(getValueDest(*SI.getOperand(0))); - } } void GraphBuilder::visitReturnInst(ReturnInst &RI) { - if (RI.getNumOperands() && isPointerType(RI.getOperand(0)->getType()) && - !isa(RI.getOperand(0))) { - DSNodeHandle &Value = getValueDest(*RI.getOperand(0)); - Value.mergeWith(RetNode); - RetNode = Value; - } + if (RI.getNumOperands() && isPointerType(RI.getOperand(0)->getType())) + RetNode.mergeWith(getValueDest(*RI.getOperand(0))); } void GraphBuilder::visitCallInst(CallInst &CI) { // Set up the return value... DSNodeHandle RetVal; if (isPointerType(CI.getType())) - RetVal = getLink(getValueNode(CI)); + RetVal = getValueDest(CI); - DSNodeHandle Callee; - // Special case for a direct call, avoid creating spurious scalar node... - if (GlobalValue *GV = dyn_cast(CI.getOperand(0))) - Callee = getGlobalNode(*GV); - else - Callee = getLink(getValueNode(*CI.getOperand(0))); + DSNodeHandle Callee = getValueDest(*CI.getOperand(0)); std::vector Args; Args.reserve(CI.getNumOperands()-1); @@ -403,7 +361,7 @@ void GraphBuilder::visitCallInst(CallInst &CI) { // Calculate the arguments vector... for (unsigned i = 1, e = CI.getNumOperands(); i != e; ++i) if (isPointerType(CI.getOperand(i)->getType())) - Args.push_back(getLink(getValueNode(*CI.getOperand(i)))); + Args.push_back(getValueDest(*CI.getOperand(i))); // Add a new function call entry... FunctionCalls.push_back(DSCallSite(CI, RetVal, Callee, Args)); @@ -411,8 +369,12 @@ void GraphBuilder::visitCallInst(CallInst &CI) { /// Handle casts... void GraphBuilder::visitCastInst(CastInst &CI) { - if (isPointerType(CI.getType()) && isPointerType(CI.getOperand(0)->getType())) - getValueNode(CI).addEdgeTo(getLink(getValueNode(*CI.getOperand(0)))); + if (isPointerType(CI.getType())) { + if (isPointerType(CI.getOperand(0)->getType())) + setDestTo(CI, getValueDest(*CI.getOperand(0))); + else + ; // FIXME: "Other" node + } } diff --git a/lib/Analysis/DataStructure/Printer.cpp b/lib/Analysis/DataStructure/Printer.cpp index 35f491dd5cf..fd6006c2a5d 100644 --- a/lib/Analysis/DataStructure/Printer.cpp +++ b/lib/Analysis/DataStructure/Printer.cpp @@ -36,7 +36,6 @@ static string getCaption(const DSNode *N, const DSGraph *G) { OS << "\n"; } - if (N->NodeType & DSNode::ScalarNode) OS << "S"; if (N->NodeType & DSNode::AllocaNode) OS << "A"; if (N->NodeType & DSNode::NewNode ) OS << "N"; if (N->NodeType & DSNode::GlobalNode) OS << "G"; @@ -49,15 +48,6 @@ static string getCaption(const DSNode *N, const DSGraph *G) { OS << "\n"; } - if ((N->NodeType & DSNode::ScalarNode) && G) { - const std::map &VM = G->getValueMap(); - for (std::map::const_iterator I = VM.begin(), - E = VM.end(); I != E; ++I) - if (I->second.getNode() == N) { - WriteAsOperand(OS, I->first, false, true, M); - OS << "\n"; - } - } return OS.str(); } @@ -94,6 +84,23 @@ struct DOTGraphTraits : public DefaultDOTGraphTraits { /// static void addCustomGraphFeatures(const DSGraph *G, GraphWriter &GW) { + // Add scalar nodes to the graph... + const std::map &VM = G->getValueMap(); + for (std::map::const_iterator I = VM.begin(); + I != VM.end(); ++I) + if (!isa(I->first)) { + std::stringstream OS; + WriteAsOperand(OS, I->first, false, true, G->getFunction().getParent()); + GW.emitSimpleNode(I->first, "plaintext=circle", OS.str()); + + // Add edge from return node to real destination + int EdgeDest = I->second.getOffset(); + if (EdgeDest == 0) EdgeDest = -1; + GW.emitEdge(I->first, -1, I->second.getNode(), + EdgeDest, "arrowtail=tee,color=gray63"); + } + + // Output the returned value pointer... if (G->getRetNode().getNode() != 0) { // Output the return node...