HomeresearchPeopleGeneral InfoSeminarsResources
| Software & Systems | Home | People | Publications | Links
The Polaris Compiler
FAQ

 

Introduction

This frequently asked question list is intended for students that are required to program with Minipolaris. The objective here is to get beginners up and running as soon as possible rather than present an indepth analysis. Readers are encouraged to refer the MAN pages on the various C++ classes that Minipolaris implements.

Frequently Asked Questions

1. How do I list statements of the Fortran Program that I'm compiling ?
2. How do I list statements of a given type ?
3. How do I list expressions that are present in my program ?
4. How can I identify constants ?
5. How can I replace an Expression with another Expression ?
6. How do I create new Expressions ?
7. How can I create a nested loop of Statements ?
8. When I delete a Statement from my Statement List, my program hangs, why ?
9. How do I modify the Predirectives ?
10. Why do I need a WorkSpace ?

 

1. How do I list statements of the Fortran Program that I'm compiling ?

The functions print() and write() are inherited and are available to almost all classes in MiniPolaris.

Print() outputs all revelant information along with the statment itself whereas Write() outputs only the statement.

Example Code:

StmtList & statement_list=pgm.stmts();
:
:
cout<<endl<<"Using print()";
Iterator <Statement> iterate_statement=statement_list.iterator();
for(iterate_statement.reset();iterate_statement.valid();++iterate_statement)
        {
    cout<<endl;
    Statement & statement=iterate_statement.current();
    statement.print(cout);
    }
int i=5;
cout<<endl<<"Using write()";
for(iterate_statement.reset();iterate_statement.valid();++iterate_statement)
    {
    cout<<endl;
    Statement & statement=iterate_statement.current();
    statement.write(cout,i," ");
    }

 

2. How do I list statements of a given type ?

The function stmts_of_type() available to objects of type StmtList returns an iterator over a give type of statement i.e. CALL STMT, ASSIGNMENT STMT, IF STMT etc. Upto 5 different types of statements can be isolated using this( Do a MAN Statement for a more details )

Example Code:

//This code will print out all statements of type CALL and PRINT

int i=5;
Iterator<Statement> iterate_statement=stl.stmts_of_type(CALL_STMT,PRINT_STMT);
for(iterate_statement.reset();iterate_statement.valid();++iterate_statement)
    {
    cout<<endl;
    Statement & statement=iterate_statement.current();
    statement.write(cout,i," ");
    }

 

3. How do I list expressions that are present in my program ?

A simple way in which expression in a program can be listed is through the use of iterate_expressions() available to objects of type Statement. Alternatively the function arg_list() available to objects of type Expression can also be used to a limited extent once the RHS of an expression is obtained.

Example Code:

// This section of code will iterate through all the expressions in a program
cout<<endl<<"Printing Expressions ";
Iterator<Statement> iterate_statement=stl.iterator();
for(iterate_statement.reset();iterate_statement.valid();++iterate_statement)
    {
    cout<<endl;
    Statement & statement=iterate_statement.current();
    Iterator<Expression> iterate_expression=statement.iterate_expressions();
    for(iterate_expression.reset();iterate_expression.valid();++iterate_expression)
        {
        iterate_expression.current().print(cout); //print the expressions
        }
    }

Note: Recursive techniques need to be employed to pickout the individual identifiers, a technique for doing this is explained in FAQ # 4

4. How can I identify constants ?

To identify constants or parameters as they are known in fortran, the individual identifiers that make up an expression need to be examined. For eg consider the following expression x=y+z.

'x' is the identifier expression on the lhs. 'y' and 'z' are identifier expressions on thr rhs.

The identifier expression Symbol class is then checked against an enumerated type to see if it is indeed a variable of type constant.

Example Code:

//Recursive function that can be used to find constant variables
void find_constant(Expression * expr)
    {
    if (expr->op()==ID_OP)
        {
        Symbol & sym=expr->symbol();
        if(sym.sym_class()==SYMBOLIC_CONSTANT_CLASS)
            {
            cout<<endl<<"Constant :";
            expr->print(cout);
            }
        }
    else
        {
        Iterator<Expression> iterate_expr=expr->arg_list();
        for(iterate_expr.reset();iterate_expr.valid();++iterate_expr)
            {
            find_constant(iterate_expr.current());
            }
        }
    }

 

5. How can I replace an Expression with another Expression and how do I use Assign() and Pull() ?

This can be easily achieved by using a similar recursive function shown in FAQ #4. In addition, a Listable class Mutator which is similar to Iterator is used. Mutators are used when expressions need to be modified or changed. Due to the manner in which expressions are executed in 'C++' certain semantics have to be preserved in using Assign() and Pull() functions. For more detail refer to

man Iterator

Note: There are no manual pages on Mutator

Example Code:

//Recursive function that can be used to replace an expression with an
//other one.
Expression * replace_expression (Expression * expr, Expression * old_expr, Expression * new_expr)
{
if (expr->op()==ID_OP)
    {
    Symbol & sym=expr->symbol();
    if(expr==old_expr)
        {
        return(new_expr->clone());
        }
    }
else
    {
    Mutator<Expression> mutate_expr=expr->arg_list();
    for(mutate_expr.reset();mutate_expr.valid();++mutate_expr)
        {
        mutate.assign()=replace_expression(mutate_expr.pull(),
        old_expr,new_expr);
        }
    }
return expr;
}

 

6. How do I create new Expressions ?

In Minipolaris, expressions cannot be created directly and must be created via functions that are availbe to objects of type Expression. The following example will illustrate this

Example Code:

//The objective is to create a new expression using other 2 expressions
//The code below will generate an expression of the type "result=operand_1 + operand_2"
Expression * operand_1=constant(1);
Expression * operand_2=constant(2);
BinaryExpr * result = new BinaryExpr(ADD_OP,
    expr_type(ADD_OP, operand_1->type(), operand_2->type()), operand_1, operand_2);

 

7. How can I create a nested loop of Statements ?

This is an example of code that is analogous to nested loops shown below

for(int i=1;i<maximum;i++)
    for(int j=i-1;j<=maximum;j++)

Such loops become necessary when modifications made in a Statement have to be propagated through to the rest of the program. eg: constant propagation.

Example Code:

StmtList & statement_list=pgm.stmts();
Statement * firsto=statement_list.first_ref();
Statement * lasto=statement_list.last_ref();
const char * first_tag=firsto->tag();
const char * last_tag=lasto->tag();
Statement * stmto=stl.first_ref();
for(;strcmp(last_tag,stmto->next_ref()->tag());stmto=stmto->next_ref())
    {
    :
    :
    for(;strcmp(last_tag,stmti->tag());stmti=stmti->next_ref())
        {
        :
        :
        }
    }

 

8. When I delete a Statement from my Statement List, my program hangs, why ?

A common mistake made by most programmers is to delete an item that it currently being pointed to by an iterator or pointer. Doing so will result in an assertion failed error or possibly a machine core dump. There are several ways of avoiding this and a simple method is outlined below. It involves the use of flags.

//Consider the following example code which WILL result in an ERROR
StmtList & statement_list=pgm.stmts();
Iterator<Statement> iterate_statement=statement_list.iterator();
for(iterate_statement.reset();iterate_statement.valid();++iterate statement)
    {
    :
    :
    if(condition=TRUE)
    statement_list(iterate_statement.current());
    }

The reason why the above technique generates an error is that when the statement is deleted from the StatementList, the current iterator is pointing to void as the statement it was pointing to has been deleted.

As the code below suggests, a simple flag can be set when a condition for deletion of a statement is met. After the iterator has had a chance to point to the next statement, then through the use of prev_ref(), the previous statement can be safely deleted.

//Consider the following example code which NOT hang
int delete_ok=0;
StmtList & statement_list=pgm.stmts();
Iterator<Statement> iterate_statement=statement_list.iterator();
for(iterate_statement.reset();iterate_statement.valid();++iterate statement)
    {
    if(delete_ok==1)
        {
        stl.del(iterate_statement.current().prev_ref());
        delete_ok=0;
        }
    :
    :
    if(condition=TRUE)
    delete_ok=1;
    }

 

9. How do I modify the predirectives ?

The predirectives are stored as a list for each statement. The example below illustrates how this list can be modified.

Example Code:

Iterator<Statement> iterate_statement=stl.iteator();
for (iterate_statement.reset();iterate_statement.valid();++iterate_statement)
    {
    Statement & stmt=iterate_statement.current();
    strstream p;
    p<<"C --Addition to Predirective"<<ends;
    StringElem *x= new StringElem(p.str());
    List<StringElem> & pre_dirs=stmt.pre_directives();
    pre_dirs.ins_last(x);
    delete[] p.str();
    }

 

10. Why do I need a WorkSpace ?

A problem you will likely encounter is the inability to find what BasicBlock a randomly chosen Statement belongs to. Since you define the BasicBlock class, it is easy to include references to Statements and other objects. However, you do not define class Statement, so you cannot put a direct reference to the containing BasicBlock.

Fortunately, Polaris provides a class WorkSpace which provides a method to attach information to a previously defined class, such as Statement. To see the manual page, type

man WorkSpace

Example Code:

//
// Cog.h
//
// Sample use of WorkSpace, associating information about a Cog with a
// Sprocket (fictional types.) In this case, we know the following :
//
// Sprocket :
// o already defined in the base (so we can't change it, but we
// want to use it.)
// o derived from type Listable (so it has a WorkSpaceStack)
//
// Cog :
// o user defined
// o contains one or more references to Sprocket type objects
//
// In our system, we want to know what Cog contains a particular Sprocket,
// but since we cannot change the Sprocket class, we need to store this
// in a WorkSpace object.
//
// Cog :
// o user defined
// o contains one or more references to Sprocket type objects
//
// In our system, we want to know what Cog contains a particular Sprocket,
// but since we cannot change the Sprocket class, we need to store this
// in a WorkSpace object.
//
// the following declarations would belong in Cog.h -- the header file for
// the class Cog
// add these includes at the top
#include "WorkSpace.h"
#include "WorkSpaceStack.h"
class Cog : public Listable
{
// blah blah blah
// this is where you would define type Cog
};
 

// this should be defined at the bottom, after you define the class Cog :
class CogWork : public WorkSpace
{
private:
Cog * _cog;
public:
CogWork(CogWork & other) : _cog(other._cog), WorkSpace(other) { }
CogWork(int tag, Cog * cog) : _cog(cog), WorkSpace(tag) { }
Cog * cog() { return (Cog *) _cog; }
INLINE Listable *listable_clone() const;
// Needed for Listable class.
INLINE void print(ostream &o) const;
// Needed for Listable class.
INLINE int structures_OK() const;
}
};

INLINE Listable * CogWork::listable_clone() const
{
return new CogWork((CogWork &) *this);
 };

INLINE int CogWork::structures_OK() const
{
return 1;
}

INLINE void CogWork::print(ostream &o) const
{
o << "CogWork : [ " << _cog << " ]";
}

 
//
// Cog.cc
//
// Sample use of WorkSpace, associating information about a Cog with a
// Sprocket (fictional types.) In this case, we know the following :
//
// Sprocket :
// o already defined in the base (so we can't change it, but we
// want to use it.)
// o derived from type Listable (so it has a WorkSpaceStack)
//
// Cog :
// o user defined
// o contains one or more references to Sprocket type objects
//
// In our system, we want to know what Cog contains a particular Sprocket,
// but since we cannot change the Sprocket class, we need to store this
// in a WorkSpace object.
//
// the following code shows and example of how to associate a Cog with a
// Sprocket, then later how to find the Cog given a random Sprocket
#include "Cog.h"
// etc.
// this would be some function called from the driver most likely
ReturnType pass_function(ProgramUnit & pgm)
{
// PASStag will be a unique integer used by this entire pass of the
// compiler -- so it should be set only once
int PASStag = create_pass_tag();
// .
// .
// .
// lots of code in which you are creating Cogs and putting references
// to sprockets in them
// .
// .
// .
// now, say you have the objects :
// Sprocket & mysprocket;
// Cog * mycog; // mycog = new Cog(...) earlier
// and you have stored references to mysprocket in mycog (so it is no
// problem finding mysprocket given mycog)
// to store a reference to mycog within mysprocket, create a WorkSpace
// object and store it on the stack.
mysprocket.work_stack().push(new CogWork(PASStag, mycog));
// .
// .
// .
// lots of code in which you do lots of wonderful things with Cogs
// .
// .
// .
// now, say you have a the object :
// Sprocket & randomsprocket;
// and you want to find the Cog which was originally associated with
// it above :
CogWork * cog_workspace =
(CogWork *) randomsprocket.work_stack().top_ref(PASStag);
Cog * the_cog = cog_workspace.cog();
// .
// .
// .
// much more brilliant code
// .
// .
// .
// now you are ready to finish your pass, so you need to clean up all
// references to Cogs from the Sprockets :
pgm.clean_workspace(PASStag);
return fantastic_result;
}


 


Parasol Home | Research | People | General info | Seminars | Resources  

Parasol Lab, 301 Harvey R. Bright Bldg, 3112 TAMU, College Station, TX 77843-3112 
Contact Webmaster      Phone 979.458.0722     Fax 979.458.0718 
Dwight Look College of Engineering
Department of Computer Science and Engineering | Dwight Look College of Engineering | Texas A&M University
    
Privacy statement: Computer Science and Engineering Engineering TAMU