There are two common ways of traversing the SUIF IR representation: iterators and walkers. We discuss iterators here and walkers in the next section. The interface of an iterator can be found in suifkernel/iter.h. An iterator is an ordered collection of objects and an interface that allows one to traverse the objects. It has the notion of a current index, which is initialized to the first position of the collection, and provides methods to move the index up and down. The following example shows the use of an iterator:
for (Iter<Expression*> iter = st->get_expression_iterator();
iter.is_valid(); iter.next()) {
Expression *e = iter.current();
}
The important methods in its interface are:
| Method | Meaning |
| length | Returns the number of elements in the whole collection. |
| current | Returns the current element. |
| next | Advances the current position. |
| previous | Sets back the current position. |
| is_valid | Returns T if more elements exist beyond the current index. |
| set_to | Sets the current index to a particular value. |
The SUIF system provides a set of useful templates for constructing iterators and sets of SuifObjects in the suifkernel/utilities.h file.
for (Iter<CallStatement> iter =
object_iterator<CallStatement>(file_set_block);
iter.is_valid(); iter.next())
{
CallStatement *call = &iter.current();
// do something with the call
}
Even though this iterator will give you access to a reference to the desired object, it is a VERY BAD idea to try to modify the object during iteration. Instead consider using the collect_objects defined below to build a list of all the objects to operate on, then make transformations.
list<ProcedureSymbol*>* sym_list = collect_objects<ProcedureSymbol>(root);
for (list<ProcedureSymbol*>::iterator iter = sym_list->begin();
iter != sym_list->end(); iter++)
{
ProcedureSymbol *ps = *iter;
// do something with the procedure symbol
}
// clean up
delete sym_list;
Use this iterator to collect all of the objects that subclass from the given type. You can then use the and modify the returned objects after collecting the objects.
for (Iter<Expression> iter =
collect_instance_objects<Expression>(statement);
iter.is_valid(); iter.next())
{
Expression *exp = &iter.current();
// do something with the OWNED expression
}
Like the Statement::get_child_statement_iterator() method for Statements, this iterator does not dive into the entire ownership tree rooted at the start_object.
for (Iter<Type> iter =
suif_object_ref_iterator<Type>(expression);
iter.is_valid(); iter.next())
{
Type *t = &iter.current();
// do something with the referenced type.
}
This can be used with an iterator over the ownership tree like the object_iterator<>() to find all the SuifObject links in a system.