| Introduction | Projects and Files | Statements | Expressions | Symbols | Types |
| Attributes | Labels | Non-Member Functions | Constructing Declarations | Example Programs | Index |
It is possible to add information to the Sage nodes using attributes. An attribute has two values:
#define DEPENDENCE_ATTRIBUTE -1001
#define INDUCTION_ATTRIBUTE -1002
#define ACCESS_ATTRIBUTE -1003
#define DEPGRAPH_ATTRIBUTE -1004
#define USEDLIST_ATTRIBUTE -1005
#define DEFINEDLIST_ATTRIBUTE -1006
#define NOGARBAGE_ATTRIBUTE -1007
#define GARBAGE_ATTRIBUTE -1008
#define ANNOTATION_EXPR_ATTRIBUTE -1009
Please see section Data Dependence Computations For Fortran for examples of how to use attributes.
Represents the base class of attributes.
class SgAttribute{
private:
// the attribute data;
int type; // a label;
void *data; // the data;
int dataSize; // the size of the data in bytes to allow data to be copied;
SgAttribute *next; // to the next attribute of a statements (do that way
// or not??);
// link to sage node, allow to go from an attribute to sage stuffs;
typenode typeNode; // indicates if SgStatement, SgExpression, ...
// ptToSage is pointed to;
void *ptToSage; // pointer to SgStatement, SgExpression, ... ;
int fileNumber; // the file methods;
// the methods to access the structure of an attributes;
public:
SgAttribute(int t, void *pt, int size, SgStatement &st, int filenum);
SgAttribute(int t, void *pt, int size, SgSymbol &st, int filenum);
SgAttribute(int t, void *pt, int size, SgExpression &st, int filenum);
SgAttribute(int t, void *pt, int size, SgType &st, int filenum);
~SgAttribute();
int getAttributeType();
void setAttributeType(int t);
void *getAttributeData();
void *setAttributeData(void *d);
int getAttributeSize();
void setAttributeSize(int s);
typenode getTypeNode();
void *getPtToSage();
void setPtToSage(void *sa);
void resetPtToSage();
void setPtToSage(SgStatement &st);
void setPtToSage(SgSymbol &st);
void setPtToSage(SgExpression &st);
void setPtToSage(SgType &st);
SgStatement *getStatement();
SgExpression *getExpression();
SgSymbol *getSgSymbol();
SgType *getType();
int getfileNumber();
SgAttribute *copy();
SgAttribute *getNext();
void setNext(SgAttribute *s);
int listLenght();
SgAttribute *getInlist(int num);
void save(FILE *file);
void save(FILE *file, void (*savefunction)(void *dat,FILE *f));
};
SgAttribute(int t, void *pt, int size, SgStatement &st, int filenum)
t
is the type of the attribute, pt a pointer to the data and
size the size of the data (in bytes). This last parameter is
useful if no function is given for reading and saving the attributes.
The parameter st is the statement the attribute is attached to.
When an attribute is created this way, it does not appear in the
attributes list of the SgStatement node, but it can be added using the
addAttribute(SgAttribute *att) method.
SgAttribute(int t, void *pt, int size, SgSymbol &st, int filenum)
SgAttribute(int t, void *pt, int size, SgExpression &st, int filenum)
SgAttribute(int t, void *pt, int size, SgType &st, int filenum)
void *setAttributeData(void *d)
enum typenode {BIFNODE, LLNODE, SYMBNODE, TYPENODE,...}
corresponding respectively to SgStatement, SgExpression, SgSymbol,
and SgType.
getTypeNode(), this value can be casted to the
right type.
NULL.
void setPtToSage(SgStatement &st)
getTypeNode().
void setPtToSage(SgSymbol &st)
void setPtToSage(SgExpression &st)
NULL.
From the user's point of view, the preferred way to handle attributes
is by using the attribute methods of SgStatement, SgExpression, SgSymbol,
and SgType classes. The SgAttribute class is provided for those, who
need non-standard functionality. In particular, the SgAttribute
constructors should not be used directly. Instead,
addAttribute and getAttribute methods should be used.
For example, one might be tempted to write a code fragment like that:
SgExpression * CurrentExpression;
MyExprPtr = new MyExpr ( ... );
...
SgAttribute *MyAttribute = new SgAttribute ( MY_TYPE,
(void *) MyExprPtr,
sizeof(MyExpr) ,
*CurrentExpression , 0 );
MyExprPtr->SetAttribute ( MyAttribute );
CurrentExpression->addAttribute ( MyAttribute );
Instead, this code should be written as:
SgExpression * CurrentExpression;
MyExprPtr = new MyExpr ( ... );
...
CurrentExpression->addAttribute ( MY_TYPE, (void *) MyExprPtr,
sizeof(MyExpr) );
MyAttribute = CurrentExpression->getAttribute( 0, MY_TYPE )
MyExprPtr->SetAttribute ( MyAttribute );
The following piece of code adds an attribute to all the statements of all the files in a project.
.....
#define MY_ATTRIBUTE_TYPE 2
.....
nbfile = project->numberOfFiles();
for (i=0; i< nbfile; i++)
{
file = &(project->file(i));
first = file->firstStatement();
temp = first;
while (temp)
{
str = new char[256];
sprintf(str,"this_is_an_attribute_added_statement_line_%d",
temp->lineNumber());
temp->addAttribute(MY_ATTRIBUTE_TYPE,(void *) str, strlen(str));
temp = temp->lexNext();
}
}
How to retrieve the attributes from the statement list.
for (i=0; i< nbfile; i++)
{
file = &(project->file(i));
first = file->firstStatement();
temp = first;
while (temp)
{
for (j=0; j< temp->numberOfAttributes(); j++)
printf("Found attribute type %d ---> %s\n",
temp->attributeType(j),
(char *) temp->attributeValue(j));
temp = temp->lexNext();
}
}
How to retrieve the attributes directly from the file:
SgFile *file;
nba = file->numberOfAttributes();
for (i=0 ; i< nba; i++)
{
att = file->attribute(i);
}
How to save the attribute:
for (i=0; i< nbfile; i++)
{
sprintf(nam,"attribute%d.dump",i);
file = &(project->file(i));
file->saveAttributes(nam);
}
How to read the attribute:
for (i=0; i< nbfile; i++)
{
sprintf(nam,"attribute%d.dump",i);
file = &(project->file(i));
file->readAttributes(nam);
}
How to save using a user function:
void saveatt (void *dat,FILE *f)
{
if (!dat || !f)
return;
fprintf(f,"%s\n",dat);
}
........
for (i=0; i< nbfile; i++)
{
sprintf(nam,"attribute%d.dump",i);
file = &(project->file(i));
file->saveAttributes(nam,saveatt);
}
How to read using a user function:
void *readatt (FILE *f)
{
char *data;
if (!f)
return NULL;
data = new char[256];
fscanf(f,"%s",data);
return (void *) data;
}
........
for (i=0; i< nbfile; i++)
{
sprintf(nam,"attribute%d.dump",i);
file = &(project->file(i));
file->readAttributes(nam,readatt);
}
Attribute methods provided for the SgFile class.
The following methods of class SgFile are provided:
void saveAttributes(char *file)
getAttributeSize().
void saveAttributes(char *file, void (*savefunction)(void *dat, FILE *f))
void readAttributes(char *file)
saveAttributes(char *file).
void readAttributes(char *file, void * (*readfunction)(FILE *f))
saveAttributes(char *file, void (*savefunction)(void *dat,FILE *f)).
ith attribute of the file ($code{i=0,1, ...})
No special initialization routines are necessary to use the attribute system.
However, only one .dep file can be processed at a time.
The selection of the file is done by the SgProject method
project->file(i) which sets the current file. As a consequence,
when adding an attribute to a node (for instance an SgStatement object) the
file that the node belongs to must be the current file. This limitation is
consistent with the multi-file behavior of Sage.
Warning: if the .dep file is modified before being saved,
the saving of the attributes must be done last so the node numbers are
consistent. Saving the database in a file modifies the identifiers of
Sage nodes.
Below is a description of the garbage collection method in SgFile:
int expressionGarbageCollection(int deleteExpressionNode, int verbose)
int deleteExpressionNode
int verbose
Because the system cannot be aware of all the SgExpression nodes in
the system (for instance node created but not yet referenced in the
data base), it is possible to avoid the deletion of those nodes by
adding an attribute with type NOGARBAGE_ATTRIBUTE.
Attribute methods provided for use with SgStatement, SgExpression, SgType, and SgSymbol objects.
Attributes can be attached to SgStatement, SgExpression, SgType, or SgSymbol objects. The following methods are available:
int numberOfAttributes(int type)
type attached to the
object. The parameter type acts as a filter.
ith attribute
(i=0,1,..) attached to the node. Returns NULL
if the node does not exist.
ith attribute (i=0,1,..)
attached to the node. Returns 0 if the node does not exist.
void *attributeValue(int i,int type)
attributeValue(int i) but only consider the
attribute of type type.
ith attribute (i=0,1,..) in the attribute
list of the object. The data field is returned so it can be deleted if
appropriate.
void addAttribute(int type, void *a, int size)
NULL.
void addAttribute(void *a, int size)
void addAttribute(SgAttribute *at)
SgAttribute *getAttribute(int i)
ith (i=0,1,..) attribute of an object.
SgAttribute *getAttribute(int i,int type)
ith attribute of type type attached
to the object.
Sage provides data dependence computation for Fortran using the Omega Test. The information is provided using the attribute mechanism in Sage.
To initialize the data dependences in Sage, two function are available:
void doDependenceAnalysisOnTheFullFile(SgFile *file, int printdep,
int printannotation, int verbose)
void doDependenceAnalysisForAFunction(SgFile *file, SgStatement *func,
int printdep, int printannotation,
int verbose)
The first function computes the data dependence for a full file, and the second applies only on a function basis. These two functions also initialize the annotation system. The parameters are the following :
SgFile *file : the current file
SgStatement *func : the function
int printdep : display the data dependences if not zero
int printannotation : display the annotation found if not zero
int verbose : display the current function name
In order for dependence analysis to work, the following file needs to be included:
#include "depInterfaceExt.h"
and the program must be linked with the library:
sage/Sage++/extentions/SageAnalysisTool/libDep.a
For example, here is the structure of a program (the full example
can be found in
sage/Sage++/extentions/DemoDataDep/analyze.c)
.......
#include "sage++user.h"
#include "depInterfaceExt.h"
.......
main(){
.........
project = new SgProject(ifi);
file = &(project->file(0));
........
if (file->languageType() != ForSrc)
{
Message("This is not a Fortran file; exiting",0);
exit(1);
}
doDependenceAnalysisOnTheFullFile(file,0,0,0);
.......
}
Attributes are used to store the information in the database. Please note, however, that the data dependence graph attributes cannot yet be saved to a file.
DEPENDENCE_ATTRIBUTE
SgStatement *stmt; // a statement
depNode *dep;
int i, nbatt;
nbatt = stmt->numberOfAttributes(DEPENDENCE_ATTRIBUTE);
for (i=0; i< nbatt; i++)
{
dep = (depNode *) stmt->attributeValue(i,DEPENDENCE_ATTRIBUTE);
...........
}
// the dep node class
class depNode {
.....
public:
SgStatement *stmtin; // source statement of the dependence
SgStatement *stmtout; // sink statement of the dependence
SgExpression *varin; // source expression of the dependence
SgExpression *varout; // sink expression of the dependence
int typedep; // WRONGDEP: ????
// ARRAYDEP: dependence on an array ref
// PRIVATEDEP: The scalar variable
// (varin->symbol())
// referenced can be privatized
// REDUCTIONDEP: The scalar variable
// (varin->symbol())
// is subject to a reduction
// computation.
// SCALARDEP: The scalar reference was not
// found to be a reduction or
// private.
int kinddep; // The type of the dependence: ddflow, ddanti,
// or ddoutput
int lenghtvect; // length of the vector data dep
int distance[MAXNESTEDLOOP]; // distance if known (0 is the
// outermost loop)
int knowndist[MAXNESTEDLOOP];// indicate if the distance is known
// here is an example how to use these two last vectors:
// for (i=1;i<= lenghtvect; i++)
// {
// if (knowndist[i])
// printf("%d", distance[i]);
// else
// {
// if (distance[i] & DEPZERO)
// {
// printf("0");
// }
// if (distance[i] & DEPGREATER)
// {
// printf("+");
// }
// if (distance[i] & DEPLESS)
// {
// printf("-");
// }
// }
// if (i< lenghtvect)
// printf(", ");
// }
depNode(SgStatement *sin,SgStatement *sout,
SgExpression *vin,SgExpression *vout,
int tdep, int kdep,
int *dist, int *kdist, int le);
~depNode();
void setNext(depNode *n); // set the next dependence node in the list
depNode *nextNode(); // next dependence node in the list
void displayDep(); // display the dependence
}
INDUCTION_ATTRIBUTE
int j;
SgStatement *loop; // a loop statement
Set *inducset; // this is a set structure
// (see sage/Sage++/extentions/SageAnalysisTool/Set.h)
PT_INDUCVAR *ind;
inducset = (Set *) loop->attributeValue(0,INDUCTION_ATTRIBUTE);
for (j=0; j < inducset->size(); j++)
{
ind = (PT_INDUCVAR) inducset->getElement(j);
.....
}
struct inducvar {
int constante; // indicate if constant or induction
SgStatement *stmt; // the loop it is coming from;
SgExpression *var; // this is a SgVarRef node;
SgExpression *stride; // the stride;
SgExpression *lbound; // the lower bound
SgExpression *ubound; // the upper bound
Set *reachdef; // not used currently;
int level; // internal info;
int loopnum; // internal info;
int include; // internal info;
}
typedef struct inducvar *PT_INDUCVAR;
ACCESS_ATTRIBUTE
int i;
SgStatement *loop; // a loop statement
Set *accesset; // this is a set structure
//(see sage/Sage++/extentions/SageAnalysisTool/Set.h)
PT_ACCESSARRAY el;
accesset = (Set *) loop->attributeValue(0,ACCESS_ATTRIBUTE);
for (i=0 ; i< accesset->size(); i++)
{
el = (PT_ACCESSARRAY) accesset->getElement(i);
.......
}
struct arrayAccess {
SgStatement *stmt; // The statement the
// access is coming from
SgExpression *var; // The access expression
int linear[MAXDIMARRAY][MAXNESTEDLOOP]; // matrix of access
int isLinear[MAXDIMARRAY]; // flag for each line
// to indicate if it
// is linear or not
int cst[MAXNESTEDLOOP]; // constante value
// here is an example of storage
// do i = 1,n
// do j = 1,n
// a(2*i+3, 4*i + 5*j + 6) = ...
// enddo
// enddo
// gives the following values of sets;
//
// isLinear linear cst
// [0] = 1 [0][0] = 2 [0][1] = 0 [0] = 3
// [1] = 1 [1][0] = 4 [1][1] = 5 [1] = 6
//
int nbdim; // the dimension of the array access
// (or an upper bound)
int size; // the number of induction var that
// enclosed the statement ( 2 for the
// previous example)
int type; // internal info
int rw; // if different from zero this is an
// access in read otherwise in write
int scalar; // if different from zero then this
// is a scalar variable access
int level; // internal info
}
typedef struct arrayAccess *PT_ACCESSARRAY;
DEPGRAPH_ATTRIBUTE
if (doloop = isSgForStmt(temp))
{
depg = (depGraph *) doloop->attributeValue(0,DEPGRAPH_ATTRIBUTE);
if (depg)
{
// some computation here using the dep graph;
}
}
class depGraph {
depNode *current; // list of dependence (also stored in
// the DEPENDENCE_ATTRIBUTE)
depNode *first; // first depNode
depNode *last; // last depNode
public:
SgFile *file; // the file
Set *arrayRef; // same as ACCESS_ATTRIBUTE
Set *induc; // same as INDUCTION_ATTRIBUTE
SgSymbol *tsymb[MAXNESTEDLOOP]; // array of the loop nest symbol
// (internal use)
int loopnum; // internal use
SgStatement *func; // the function the loop belongs to
SgStatement *loop; // the outermost loop
int perfectNestedLevel; // number of perfectly nested level
int nbstmt; // internal use
SgStatement **tabstat; // internal use
int *tabtag; //internal use
depGraph(SgFile *fi, SgStatement *f,SgStatement *l);
~depGraph();
void addAnEdge(SgStatement *sin,SgStatement *sout,
SgExpression *vin,SgExpression *vout,
int tdep, int kdep,
int *dist, int *kdist,int le);
depNode *firstNode(); // set current on the first depNode
nextEdge(); // set current on next depNode;
void display(); // display the data dependence;
void scalarRefAnalysis(SgStatement *loop); // do the scalar analysis
void redoScalarRefAnalysis(SgStatement *loop); // redo the scalar
// analysis for an enclosed loop
// useful to parallelize innermost
// loops for instance
// more there for internal purpose;
};
USEDLIST_ATTRIBUTE
SgStatement *stmt; // a statement
SgExpression *use, *varaccess; // this is an expression list node;
for (use = (SgExpression *) stmt->attributeValue(0,USEDLIST_ATTRIBUTE);
use; use = use->rhs())
{
varaccess = use->lhs();
......
if (isSgArrayRefExp(varaccess)) // for instance
{
......
}
}
DEFINEDLIST_ATTRIBUTE
SgStatement *stmt; // a statement
SgExpression *def; // this is an expression list node;
def = (SgExpression *) stmt->attributeValue(0,DEFINEDLIST_ATTRIBUTE);