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))
.
i
th 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.
i
th attribute
(i=0,1,..
) attached to the node. Returns NULL
if the node does not exist.
i
th 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
.
i
th 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)
i
th (i=0,1,..
) attribute of an object.
SgAttribute *getAttribute
(int i,int type)
i
th 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);