On 2009-09-06 17:30, Ioannis Nousias wrote:> I've tried to write a DFGPrinter based on the CFGPrinter, as you
> suggested, but encountered problems.
>
> The GraphWriter expects
> GraphTraits<GraphType>::nodes_begin()/nodes_end(). The way this is
> implemented in CFG.h, a function is a graph of basic blocks. A
> GraphTraits<Function*> inherits from GraphTraits<BasicBlock*>,
and
> implements those nodes_begin()/nodes_end() wrapper functions. Should I
> modify CFG.h and make now BasicBlock a graph of Instruction(s) ?
>
> The DataFlow.h deals with Value and User. Now BasicBlock is derived from
> Value and Instruction from User, but I don't understand how that helps.
>
> It's a bit confusing to be honest. Can you help?
>
Here are some examples on how to use the dataflow graphs:
Value *V = ...
for(df_iterator<Value*> UI = df_begin(V), UE = df_end(V); UI != UE; ++UI)
{
...
}
typedef SmallPtrSet<const Value*, 16> SmallValueSet;
SmallValueSet DFSet;
const User* U = ...;
for (idf_ext_iterator<const User*, SmallValueSet> I=idf_ext_begin(U,
DFSet), E=idf_ext_end(U, DFSet); I != E; ++I) {
..
}
There is no common root for the dataflow graph from which you can
enumerate all dataflows, but you could take
each instruction in a function that you're interested in, and output a
dataflow graph rooted at that instruction,
unless that instruction was part of some other dataflow graph already.
Perhaps something like:
SmallValueSet PrintedSet;
for (Function::arg_iterator I=F.arg_begin(), E=F.arg_end(); I != E; ++I) {
if (!PrintedSet.count(*I)) {
... print graph rooted at V, add each node printed to
PrintedSet
}
}
for (inst_iterator I=inst_begin(F), E=inst_end(F); I != E; ++I) {
if (!PrintedSet.count(*I)) {
... print graph rooted at V, add each node printed to
PrintedSet
}
}
Best regards,
--Edwin