next up previous
Next: Acknowledgments. Up: Specifying the flow problem Previous: Transfer functions

Storing the analysis information

When the flow values converge, we want to use or store the resulting dataflow information. The framework makes a final pass over the program with the last boolean set to true. This flag is a member of the FlowProblem class and is used inside the transfer functions. For example, if we are implementing reaching definitions, then we may want to print out the list of definitions that reach each identifier. We override the flow_id method, but only do something special when the last flag is set:

void reaching_defs::flow_id(FlowVal * v, idNode * the_id, Point p)
{
  my_flowval * rv = (my_flowval *)v;

  if (last() && (p == Exit)) {
    cout << the_id->name() << " at " << the_id->coord() << " reached by defs at:
" << endl;

    for (int i = 0; i < rv->bits().size(); ++i)
      if (rv->bits[i]) {
        // Look up the def corresponding to bit i
      }
  }
  flow_expr(v, the_id, p);
}

Notice that we also call the transfer function for the superclass to make sure that the flow values continue to be properly propagated.

In order to store the information for later use, we have three options. First, we can store the flow values directly on the node using the kill or gen members. This is a little tricky, though, because we may still need the gen and kill sets. Second, we can store the information we want in an auxiliary data structure. For example, we could construct a map from idNodes to their reaching definitions. Finally, C-Breeze has a general annotation mechanism: each node has a list of Annote objects. To use this mechanism, create a subclass of Annote and use it to store the information. The add the object to the node using the annotations() method on Node.



 
next up previous
Next: Acknowledgments. Up: Specifying the flow problem Previous: Transfer functions
Calvin Lin
2002-01-31