Introduction Projects and Files Statements Expressions Symbols Types
Attributes Labels Non-Member Functions Constructing Declarations Example Programs Index

Attributes

It is possible to add information to the Sage nodes using attributes. An attribute has two values:

  1. a type: user supplied types must be positive integers; negative integers are reserved for the system; the reserved types are:
         #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 
    

  2. data: the data field is a pointer to void that can be used to store any information.

Please see section Data Dependence Computations For Fortran for examples of how to use attributes.


SgAttribute

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));
  
};

Member Functions

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)

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)

SgAttribute Usage

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 );

Example Programs

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); }


SgFile Attributes

Attribute methods provided for the SgFile class.

The following methods of class SgFile are provided:

void saveAttributes(char *file)

void saveAttributes(char *file, void (*savefunction)(void *dat, FILE *f))

void readAttributes(char *file)

void readAttributes(char *file, void * (*readfunction)(FILE *f))

int numberOfAttributes()

SgAttribute *attribute(int i)

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.

Garbage Collection

Below is a description of the garbage collection method in SgFile:

int expressionGarbageCollection(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.


General Attributes

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 numberOfAttributes(int type)

void *attributeValue(int i)

int attributeType(int i)

void *attributeValue(int i,int type)

void *deleteAttribute(int i)

void addAttribute(int type, void *a, int size)

void addAttribute(int type)

void addAttribute(void *a, int size)

void addAttribute(SgAttribute *at)

SgAttribute *getAttribute(int i)

SgAttribute *getAttribute(int i,int type)


Data Dependence Computations For Fortran

Sage provides data dependence computation for Fortran using the Omega Test. The information is provided using the attribute mechanism in Sage.

Data Dependency Initialization

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 :

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);
   .......
}

Retrieving Data Dependence Information

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

INDUCTION_ATTRIBUTE

ACCESS_ATTRIBUTE

DEPGRAPH_ATTRIBUTE

USEDLIST_ATTRIBUTE

DEFINEDLIST_ATTRIBUTE


Exit Sage++ User's Guide