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

Example Programs


/*********************************************************************/ /* pC++/Sage++ Copyright (C) 1993 */ /* Indiana University University of Oregon University of Rennes */ /*********************************************************************/

#include <stdio.h> #include <malloc.h> #include "sage++user.h"

// this is an example of how to use the sage library // to restructure fortran programs. note: this does // not use any dependence analysis, so it is not // very ambitious. it is just an example of // how to create variable, declare them, creates // expressions , create statements and functions // and install them in a program.

Restructure - addStuffToProgram

void addStuffToProgram( SgProject *project, SgFile *file){

  SgValueExp c1(1), c2(2), c3(3), c100(100);

  SgExpression *pt;

  SgVarRefExp  *e1, *e2, *e3, *e4;

  SgStatement *themain, *first, *firstex, *last;

  SgFuncHedrStmt *ptfunc;

  SgSymbol *ptsymb;

  SgSymbol *i1;

  SgSymbol *i2;

  SgSymbol *i3;

  SgSymbol *i4;

  SgSymbol *anarray;

  SgAssignStmt *stmt, *stmt1;

  SgIfStmt *anif;

  SgStatement *anotherif;

  SgWhileStmt *awhile;

  SgForStmt *afor;

  SgReturnStmt *areturn;

  SgCallStmt *afuncall;

  SgArrayType *typearray;

  SgType basetype(T_FLOAT);

printf("There is %d files in that project\n",project->numberOfFiles());

// get the first statement in the file this is the GLOBAL_BFND, i.e. // the header for the file and not a real statement in the program.

first = (file->firstStatement()); // find the main program. themain = (file->mainProgram()); if(!themain){ printf("no main program here!\n"); return; }

// first create a new function

ptfunc = new SgFuncHedrStmt("funct1");

// next add some parameters.

ptsymb = new SgVariableSymb("var1"); pt = new SgVarRefExp(*ptsymb); ptfunc->AddArg(*pt);

ptsymb = new SgVariableSymb("var2"); pt = new SgVarRefExp(*ptsymb); ptfunc->AddArg(*pt);

// Now insert our function after the file // header. this is a bit hard to read. // x->instertStmtAfter(y) means put y after x.


// lets add a statement to that function // first declare some integer variables.

i1 = new SgVariableSymb("i1"); i1->declareTheSymbol(*ptfunc); e1 = new SgVarRefExp(*i1);

i2 = new SgVariableSymb("i2"); i2->declareTheSymbol(*ptfunc); e2 = new SgVarRefExp(*i2);

i3 = new SgVariableSymb("i3"); i3->declareTheSymbol(*ptfunc); e3 = new SgVarRefExp(*i3); i4 = new SgVariableSymb("i4"); i4->declareTheSymbol(*ptfunc); e4 = new SgVarRefExp(*i4);

// next find the last declaration in the function. // so that we can add statements after it.

firstex = (ptfunc->lastDeclaration());

// make the assignment i1 = i2 + (i3 + 1)*i4

stmt = new SgAssignStmt((*e1), (*e2) + ((*e3) + c1) * (*e4));

// mane another assignment i2 = i3

stmt1 = new SgAssignStmt(*e2,*e3);

// make an if statement: if( then // stmt1 // else // a copy of stmt // endif

anif = new SgIfStmt(c1 > c2 , *stmt1, stmt->copy());

// make another if statement that is a copy of the last.

anotherif = &(anif->copy()); // make a while loop: while (i4 < 2) // a copy of the if statement // endwhile

awhile = new SgWhileStmt( (*e4)< c2 , anif->copy());

// make a do loop: do i1 = 1, 2, 3 // a copy of the while statement // enddo

afor = new SgForStmt(* i1, c1, c2, c3, awhile->copy());

// now a return statement

areturn = new SgReturnStmt();

// now a subroutine call: call funct1(1,2,3)

afuncall = new SgCallStmt(*ptfunc->symbol()); afuncall->addArg(c1.copy()); afuncall->addArg(c2.copy()); afuncall->addArg(c3.copy()); // let insert what we have created into the subroutine. // note these will come out in reverse order of insertion // becuase we keep inserting them after the last declaration.

firstex->insertStmtAfter(*anif); firstex->insertStmtAfter(stmt->copy()); firstex->insertStmtAfter(*awhile); firstex->insertStmtAfter(*afor);

// to do it the other way, find the last statement. // and insert the return at the end.

last = (ptfunc->lastExecutable()); last->insertStmtAfter(*areturn);

// now put the if and the function call in the main // program. themain->insertStmtAfter(*anotherif); themain->insertStmtAfter(*afuncall);

// Let's create an array. basetype was declared as float above. // first we create a type. in sage an array type is its base // type plus its dimensions (ranges).

typearray = new SgArrayType(basetype); typearray->addRange(c1); typearray->addRange(c2); typearray->addRange(c3); // now create the array symbol of this type.

anarray = new SgVariableSymb("Array1",*typearray); anarray->declareTheSymbol(*ptfunc);

// make an array expression Array1(i1, i2, i3)

pt = new SgArrayRefExp(*anarray,*e1,*e2,*e3);

// make an assignment statement // Array1(i1, i2, i3) = i2 + (Array1(i1,i2,i3) + 1)*Array1(i1,i2,i3)

stmt = new SgAssignStmt((*pt), (*e2) + ((*pt) + c1) * (*pt));

// insert it into our subroutine.


// unparse the file file->unparsestdout();

// and save the modified dep file.

file->saveDepFile("debug.dep"); }

Restructure - main

//This main program assumes there is a fortran file called. // x.f which has been parsed with cfp to generate a x.dep file. // also there must be a project file x.proj which // is just one line containing the name x.dep // multiple source files may be added to the project by adding // the corresponding dep file name (one to a line.) // however, sage has not been tested on multiple source // files lately and it probably will not work.

int main(int argc, char **argv){

// better to grab the names from argv. // but lets keep it simple. SgProject project("x.proj"); SgFile file("x.f"); int c;

// first check to see what language the source file is. // each dep file has the language type encoded.

switch (file.languageType()) { case CSrc: // it is C or C++ printf("this is a c program. this example is for fortran \n"); return -1; case ForSrc: // it is a fortran 77 or fortran 90 program. addStuffToProgram(&project, &file); // ProjectUnparse(&project); } return 0; }


/*********************************************************************/ /* pC++/Sage++ Copyright (C) 1993 */ /* Indiana University University of Oregon University of Rennes */ /*********************************************************************/

#include <stdio.h> #include <malloc.h> #define DISTRIBUTION #include "sage++user.h"

#define MAXSUBS 100

struct ftable { char *function_name; SgStatement *function; } ftable;

struct ftable function_table[MAXSUBS]; int totalfunctions; static int event = 0; SgProject *project;

Instrument - Fortran Program Transformations

// Fortran program transformations

SgType *SgTypeInt();

SgSymbol *entry, *eexit, *loop_entry, *loop_exit; char *fnames[] = {"entry_event", "exit_event", "loop_entry_event", "loop_exit_event"};

#define ENTRY_EVENT 0 #define EXIT_EVENT 1 #define LOOP_ENTRY 2 #define LOOP_EXIT 3

#define AFTER 0 #define BEFORE 1

Instrument - InitSymbols

// Initialize the function symbols (used in the instrumentation) void InitSymbols(SgProject *p) { SgFile *f;

f = &(p->file(0)); entry = new SgFunctionSymb(PROCEDURE_NAME,fnames[0], *SgTypeInt(),*(f->firstStatement())); eexit = new SgFunctionSymb(PROCEDURE_NAME,fnames[1], *SgTypeInt(), *(f->firstStatement())); loop_entry= new SgFunctionSymb(PROCEDURE_NAME,fnames[2], *SgTypeInt(), *(f->firstStatement())); loop_exit = new SgFunctionSymb(PROCEDURE_NAME,fnames[3], *SgTypeInt(), *(f->firstStatement())); }

Instrument - InitFunctionTable

// Initialize the function table (used for searching for functions). void InitFunctionTable(SgProject *project) {

int Files = project->numberOfFiles(); int k = 0;

for (int i = 0; i < project->numberOfFiles(); i++) { SgFile *f; f = &(project->file(i)); int num_routines; num_routines = f->numberOfFunctions(); for (int j = 0; j < num_routines; j++){ SgStatement *sub; SgSymbol *subsym;

sub = function_table[k].function = f->functions(j); subsym = sub->symbol(); function_table[k++].function_name = subsym->identifier(); } }

totalfunctions = k; }

Instrument - InsertFCallNode

// Inserting a call to the instrumentation library void InsertFCallNode(int event_type, SgStatement *s, int how) { SgSymbol *symb; switch (event_type) { case ENTRY_EVENT: symb = entry; break; case EXIT_EVENT: symb = eexit; break; case LOOP_ENTRY: symb = loop_entry; break; case LOOP_EXIT : symb = loop_exit; break; }

SgCallStmt *c; SgValueExp *ev;

c = new SgCallStmt(*symb); ev = new SgValueExp(event); c->addArg(*ev); delete(ev);


switch (how) { case BEFORE: s->insertStmtBefore(*c); break; case AFTER: s->insertStmtAfter(*c); break; } }

Instrument - FixLoops

// Fixing the loops in the subroutine (massaging the program) void FixLoops(SgStatement* s) { SgStatement *br; SgForStmt *f;

for (br = s->lexNext(); ; br = br->lexNext()) { if (f = isSgForStmt(br)) if (! f->isEnddoLoop()) f->convertLoop(); if (br == s->lastNodeOfStmt()) break; } }

Instrument - FInstrumentSub

// Instrumentation running within a subroutine. void FInstrumentSub(SgStatement* s) { SgStatement *br;

for (br = s->lexNext(); ; br = br->lexNext()) { switch (br->variant()){ case FOR_NODE: InsertFCallNode(LOOP_ENTRY, br, BEFORE); InsertFCallNode(LOOP_EXIT, br->lastNodeOfStmt(), AFTER); break; default: break; } if (br == s->lastNodeOfStmt()) break; } }

Instrument - FInitialize

// Basic initialization extern "C" void FInitialize(SgProject *project) { InitSymbols(project); InitFunctionTable(project); }

Instrument - FInstrument

// Instrumentation call (search for function symbol based on function name) extern "C" void FInstrument(char *name) { SgStatement *sub;

for(int i=0; i < totalfunctions; i++) { if (strcmp(name, function_table[i].function_name) == 0) break; }

sub = function_table[i].function; FixLoops(sub); InsertFCallNode(ENTRY_EVENT, sub->lastDeclaration(), AFTER); InsertFCallNode(EXIT_EVENT, sub->lastExecutable(), AFTER); FInstrumentSub(function_table[i].function); }

Instrument - ProjectUnparse

extern "C" void ProjectUnparse(SgProject *project) { for (int i = 0; i < project->numberOfFiles(); i++) { SgFile *f; f = &(project->file(i)); f->unparsestdout(); } }

Instrument - UnparseSub

extern "C" void UnparseSub(char *name){ SgStatement *sub;

for(int i=0; i < totalfunctions; i++) { if (strcmp(name, function_table[i].function_name) == 0) break; }

sub = function_table[i].function; sub->unparsestdout(); }

Instrument - VistaInstrument

// needs to be filled in (used for instrumentation for animation) void VistaInstrument(SgStatement *s) { SgStatement *br; SgExprListExp *l; SgExpression *e; SgExpression *a;

for (br = s->lexNext(); ; br = br->lexNext()) { for (l = isSgExprListExp(br->expr(0)); l ; l = l->next()){ e = l->value(); } if (br == s->lastNodeOfStmt()) break; } }

Instrument - FAnalyze

// Instrumenting the entire program.

void FAnalyze(SgProject *project) { char s[32];

printf ("Project has %d number of files\n", project->numberOfFiles()); for (int i = 0; i < project->numberOfFiles(); i++) { SgFile *f;

f = &(project->file(i)); printf("Source file %s has", project->fileName(i)); int num_routines;

num_routines = f->numberOfFunctions(); printf ("%d routines\n", num_routines); for (int j = 0; j < num_routines; j++) { SgStatement *sub; SgStatement *exe; sub = f->functions(j); exe = sub->lastDeclaration(); InsertFCallNode(ENTRY_EVENT, exe, AFTER); FixLoops(sub); // FInstrumentSub(sub); } f->unparsestdout(); printf ("\n Done unparsing\n"); }

for (i = 0; i < project->numberOfFiles(); i++) { SgFile *f;

f = &(project->file(i)); printf("Source file %s has", project->fileName(i)); int num_routines;

num_routines = f->numberOfFunctions(); printf ("%d routines\n", num_routines); for (int j = 0; j < num_routines; j++) { SgStatement *sub;

sub = f->functions(j); VistaInstrument(sub); } f->unparsestdout(); printf ("\n Done unparsing\n"); }


Instrument - pC++ Program Transformations

// pC++ program transformations.

SgSymbol *timer_clear, *timer_start, *timer_stop, *timer_elapsed;

char *cnames[] = {"Test_CMMD_node_timer_clear", "Test_CMMD_node_timer_start", "Test_CMMD_node_timer_stop", "Test_CMMD_node_timer_elapsed"};

#define TIMER_CLEAR 0 #define TIMER_START 1 #define TIMER_STOP 2 #define TIMER_ELAPSED 3

Instrument - isReferenceToMethodOfElement

// Basic help routines (all obtained from the compiler) // Should be made part of the library. SgSymbol * isReferenceToMethodOfElement(SgExpression *expr) { SgVarRefExp *varef; SgFunctionCallExp *fcall; SgSymbol *symb; SgMemberFuncSymb *symbm; SgFieldSymb *symbf; if (!expr) return NULL; if (varef = isSgVarRefExp(expr)) { symb = varef->symbol(); } if (fcall = isSgFunctionCallExp(expr)) { symb = fcall->symbol(); } if (symbm = isSgMemberFuncSymb(symb)) { if (symbm->isMethodOfElement()) return symbm; else return NULL; } if (symbf = isSgFieldSymb(symb)) { if (symbf->isMethodOfElement()) return symbf; else return NULL; } return 0; }

Instrument - isReferenceToClassOfElement

SgSymbol *isReferenceToClassOfElement(SgDerivedCollectionType *type,SgExpression *expr)

  SgVarRefExp *varef;

  SgFunctionCallExp *fcall;

  SgSymbol *symb,*elsymb;

  SgMemberFuncSymb *symbm;

  SgFieldSymb *symbf;

  SgType *elmetype;

  SgDerivedType *eltype;

if (!expr || !type) return NULL; elmetype = type->elementClass(); if (!elmetype) return NULL; if (elmetype->isTheElementType()) return NULL; if (eltype = isSgDerivedType(elmetype)) { if (!(elsymb = eltype->typeName())) { return NULL; } } else return NULL;

if (varef = isSgVarRefExp(expr)) { symb = varef->symbol(); } if (fcall = isSgFunctionCallExp(expr)) { symb = fcall->symbol(); }

if (symbm = isSgMemberFuncSymb(symb)) { if (symbm->className() == elsymb) return symbm; else return NULL; } if (symbf = isSgFieldSymb(symb)) { if (symbf->structureName() == elsymb) return symbf; else return NULL; } return NULL; }

Instrument - inMethodOfTheElement

int inMethodOfTheElement(SgStatement *where) { SgFuncHedrStmt *fh; SgMemberFuncSymb *symb;

if (!where) return 0;

if (where->variant() == GLOBAL) return 0;

if (fh = isSgFuncHedrStmt(where)) { if (symb = isSgMemberFuncSymb(fh->symbol())) { return symb->isMethodOfElement(); } } return inMethodOfTheElement(where->controlParent()); }

Instrument - whichFunctionAmI

SgFuncHedrStmt * whichFunctionAmI(SgStatement *where) { SgFuncHedrStmt *fh; SgMemberFuncSymb *symb;

if (!where) return NULL;

if (where->variant() == GLOBAL) return NULL;

if (fh = isSgFuncHedrStmt(where)) { return fh; } return whichFunctionAmI(where->controlParent()); }

Instrument - isReferenceToCollection

// // where is used to disambiguate this // SgDerivedCollectionType * isReferenceToCollection(SgExpression *expr, SgStatement *where) { SgType *type = NULL; SgExpression *lhs; SgVarRefExp *varef; SgPointerType *tpt; SgReferenceType *tref; SgDerivedCollectionType *dstype; SgArrayRefExp *array; SgSymbol *symb; SgFunctionCallExp *func;

if (!expr) return NULL; switch (expr->variant()) { case RECORD_REF: case POINTST_OP: case DEREF_OP: lhs = expr->lhs(); break; case VAR_REF: case ARRAY_REF: case FUNC_CALL: lhs = expr; break; default : // default should be to try to generate a copy for the expression // and see if expression becomes call the function again. return NULL; } if (!lhs) return NULL; if (varef = isSgVarRefExp(lhs)) { if (varef->symbol()) type = varef->symbol()->type(); } else if (isSgThisExp(lhs)) { if (inMethodOfTheElement(where)) return 0; // this refer to the element type = lhs->type(); } else if (array = isSgArrayRefExp(lhs)) { symb = array->symbol(); if (symb) type = symb->type(); if (type) type = type->internalBaseType(); } else if (func = isSgFunctionCallExp(lhs)) { symb = func->symbol(); if (symb) type = symb->type(); } else if (isSgPointerDerefExp(lhs)) { type = isReferenceToCollection(lhs,where); } else if (isSgExprListExp(lhs)) { type = isReferenceToCollection(lhs->lhs(),where); } else return NULL; if (!type) return NULL; switch (expr->variant()) { case FUNC_CALL: case ARRAY_REF: case VAR_REF: case RECORD_REF: if (dstype = isSgDerivedCollectionType(type)) return dstype; if (tref = isSgReferenceType(type)) { type = tref->baseType(); if (dstype = isSgDerivedCollectionType(type)) return dstype; } break; case DEREF_OP: case POINTST_OP: if (tpt = isSgPointerType(type)) { type = tpt->baseType(); if (dstype = isSgDerivedCollectionType(type)) return dstype; if (tref = isSgReferenceType(type)) { type = tref->baseType(); if (dstype = isSgDerivedCollectionType(type)) return dstype; } } break; } return NULL; }

Instrument - ListCollections

// Simple routines to look into a pC++ program. void ListCollections(SgFile *file) { SgStatement *s; SgCollectionStmt *c;

for (s = file->firstStatement(); s ; s = s->lexNext()){ if (c = isSgCollectionStmt(s)){ c->unparsestdout(); } } }

Instrument - ListCollectionInstances

void ListCollectionInstances(SgFile *file) { SgType *type; SgDerivedCollectionType *c;

for (type = file->firstType(); type ; type = type->next()){ if (c = isSgDerivedCollectionType(type)){ SgStatement *s;

printf("%s<%s>\n",c->collectionName()->identifier(), c->elementClass()->symbol()->identifier()); } } }

Instrument - ListCollectionInvocations

void ListCollectionInvocations(SgFile *f) { SgStatement *br; SgExprListExp *l; SgExpression *e; SgStatement *s; SgDerivedCollectionType *a; SgSymbol *b;

s = f->firstStatement(); for (br = s; br; br = br->lexNext()) for (l = isSgExprListExp(br->expr(0)); l ; l = l->next()){ e = l->value(); switch (e->variant()) { case DEREF_OP: case RECORD_REF: case POINTST_OP: a = isReferenceToCollection(e, br); b = isReferenceToMethodOfElement(e->rhs()); if (a && !b) b = isReferenceToClassOfElement(a, e->rhs()); if (a && b) br->unparsestdout(); } } }

Instrument - CAnalyze

void CAnalyze(SgProject *project){

for (int i = 0; i < project->numberOfFiles(); i++) { SgFile *f; f = &(project->file(i)); ListCollections(f); ListCollectionInstances(f); printf("Source file %s has ", project->fileName(i)); int num_routines; num_routines = f->numberOfFunctions(); printf ("%d routines\n", num_routines); ListCollectionInvocations(f); } }

Instrument - CInitSymbols

// Initializing the timer function symbols. void CInitSymbols(SgProject *p) { SgFile *f;

f = &(p->file(0)); timer_clear = new SgFunctionSymb(FUNCTION_NAME,cnames[0], *SgTypeInt(),*(f->firstStatement())); timer_start = new SgFunctionSymb(FUNCTION_NAME,cnames[1], *SgTypeInt(), *(f->firstStatement())); timer_stop = new SgFunctionSymb(FUNCTION_NAME,cnames[2], *SgTypeInt(), *(f->firstStatement())); timer_elapsed = new SgFunctionSymb(FUNCTION_NAME,cnames[3], *SgTypeInt(), *(f->firstStatement())); }

Instrument - CInitialize

extern "C" void CInitialize(SgProject *project) { CInitSymbols(project); InitFunctionTable(project); }

Instrument - InsertCCallNode

// Insert a C function call statement void InsertCCallNode(int event_type, SgStatement *s, int how) { SgSymbol *symb; switch (event_type) { case TIMER_CLEAR: symb = timer_clear; break; case TIMER_START: symb = timer_start; break; case TIMER_STOP: symb = timer_stop; break; case TIMER_ELAPSED: symb = timer_elapsed; break; }

SgFunctionCallExp *func; SgExprListExp *exp; SgCExpStmt *c;

func = new SgFunctionCallExp(*symb); exp = new SgExprListExp(); exp->setValue(*func); c = new SgCExpStmt (*exp);

switch (how) { case BEFORE: s->insertStmtBefore(*c); break; case AFTER: s->insertStmtAfter(*c); break; } }

Instrument - CTimingInstrumentSub

// Instrument a pC++ function for timing collection invocations.

void CTimingInstrumentSub(SgStatement *s){

SgStatement *br; SgExprListExp *l; SgExpression *e; SgDerivedCollectionType *a; SgSymbol *b;

for (br = s->lastDeclaration(); ; br = br->lexNext()) { for (l = isSgExprListExp(br->expr(0)); l ; l = l->next()){ e = l->value();

switch(e->variant()){ case DEREF_OP: case POINTST_OP: case RECORD_REF: a = isReferenceToCollection(e, br); b = isReferenceToMethodOfElement(e->rhs()); if (a && !b) b = isReferenceToClassOfElement(a, e->rhs());

if (a && isSgCExpStmt(br)) { InsertCCallNode(TIMER_START, br, BEFORE); InsertCCallNode(TIMER_STOP, br, AFTER); InsertCCallNode(TIMER_ELAPSED, br->lexNext(), AFTER); } } } if (br == s->lastNodeOfStmt()) break; } }

Instrument - CTimingInstrument

// Instrumentation based on function name.

extern "C" void CTimingInstrument(char *name){

for(int i=0; i < totalfunctions; i++) { if (strcmp(name, function_table[i].function_name) == 0) break; }

CTimingInstrumentSub(function_table[i].function); }

Instrument - OpenProject

extern "C" void OpenProject(char *proj) { project = new SgProject (proj); }

Instrument - IsFortran

#define TRUE 1 #define FALSE 0

extern "C" int IsFortran() { SgFile *file;

file = &(project->file(0)); if (file->languageType() == ForSrc) return TRUE; else return FALSE; }

Instrument - IsC

extern "C" int IsC() { SgFile *file;

file = &(project->file(0)); if (file->languageType() == CSrc) return TRUE; else return FALSE; }

Expand Syntax

/*********************************************************************/ /* pC++/Sage++ Copyright (C) 1993 */ /* Indiana University University of Oregon University of Rennes */ /*********************************************************************/

/****************************************************************** ** A Simple application of Sage++ that analyzes pC++ programs and does ** one simple source transformation to eliminate some extra communication ** and expand some syntax. ** ** pC++ has distributed data-structures called Collections that are ** homogenous and they contain classes as elements. In a pC++ program to ** refer to any particular element an array like syntax is used. To refer ** to a field within an element that resides on someother processor is ** expensive at present. The reason being when a reference to a nonlocal ** element occurs the whole element is brought in and then the particular ** field that is required is extracted from it. ** ** This application analyzes pC++ program for "Collection Array ** References" and transforms them so that the communication for getting ** fields of non local elements is not more than the "length" of the ** field. ** ** As an example consider the following pC++ program and in ** Processor_Main are some potential non local references. ** ** class Simple{ ** public: ** int foo; ** float bar[10]; ** void hello() {printf("hello world\n");}; ** }; ** ** #include "distarray.h" ** ** Collection DistBlkVector: SuperKernel ** { ** public: ** DistBlkVector(Distribution *T, Align *A); ** MethodOfElement: ** virtual void hello(); ** }; ** ** ** DistBlkVector::DistBlkVector(Template *T, Align *A):SuperKernel(T, A) ** {} ** ** ** void Processor_Main() ** { ** int i,j; ** Processors P; ** Distribution T(GRIDSIZE,&P,BLOCK); ** Align A(GRIDSIZE,"[ALIGN(V[i],T[i])]"); ** Distribution T1(GRIDSIZE,GRIDSIZE&P,BLOCK, BLOCK); ** Align A1(GRIDSIZE,"[ALIGN(V[i][j],T[i][j])]"); ** DistBlkVector<Simple> x(&T,&A); ** DistBlkVector<Simple> y(&T,&A); ** ** x(i)->foo; // xformed to x.Get_ElementPart_Int(i, <foo-offset>, <sizeof (int)>) ** x(i)->hello(); ** ** y(i,j)->bar // xformed to y.GetElementPart(i, <bar-offset>, 10 * <sizeof (float)>) ** y(i,j)->hello(); ** ** } ** *****************************************************************/

#include <stdio.h> #include <malloc.h> #include <sage++user.h>

// Make the dummy var table into a class and clean it up. #define MAXDUMMYVAR 20

SgSymbol *DummyVar[MAXDUMMYVAR]; SgType *DummyVarType[MAXDUMMYVAR]; SgExpression *DummyVarExpr[MAXDUMMYVAR];

int TotalDummyVars = 0;

SgFunctionSymb *GetElementPart, *GetElemInt, *GetElemFloat, *GetElemDouble; SgVariableSymb *addr1, *addr2;

void SearchInExpForCollectionArrayRef(SgStatement *br, SgExpression *e, int & level); void ReplaceWithGetElemPart(SgStatement *br, SgExpression *e, SgDerivedCollectionType *a, SgSymbol *b, int level); int MatchingDummyVar(SgType *x);

Expand Syntax - isReferenceToElementField

SgSymbol * isReferenceToElementField(SgExpression *expr) { SgVarRefExp *varef; SgArrayRefExp *aref; SgSymbol *symb; SgFieldSymb *symbf;

if (!expr) return NULL; if (varef = isSgVarRefExp(expr)) { symb = varef->symbol(); if (symbf = isSgFieldSymb(symb)) return symbf; } else if (aref = isSgArrayRefExp(expr)) { symb = aref->symbol(); if (symbf = isSgFieldSymb(symb)) return symbf; } return NULL; }

Expand Syntax - isArrayRefOfCollection

// Looks into the expression for collection Array References // Returns the type of the collection if it finds one.

SgDerivedCollectionType * isArrayRefOfCollection(SgExpression *expr) { SgType *type = NULL; SgExpression *lhs; SgVarRefExp *varef; SgDerivedCollectionType *dstype; if (!expr) return NULL; switch (expr->variant()) { case FUNCTION_OP: lhs = expr->lhs(); break; default : return NULL; } if (!lhs) return NULL; if (varef = isSgVarRefExp(lhs)) { if (varef->symbol()) type = varef->symbol()->type(); } if (!type) return NULL; if (dstype = isSgDerivedCollectionType(type)) return dstype; return NULL; }

Expand Syntax - ExpandSyntax

void ExpandSyntax(SgFile *f) { SgStatement *br; SgExprListExp *l; SgExpression *e; SgStatement *s; int lvl = 0;

s = f->firstStatement(); for (br = s; br; br = br->lexNext()) if (isSgCExpStmt(br)) { for (l = isSgExprListExp(br->expr(0)); l ; l = l->next()) { e = l->value(); SearchInExpForCollectionArrayRef(br,e, lvl); lvl = 0; } } }

Expand Syntax - SearchInExpForCollectionArrayRef

// Need the level stuff to handle multiple references collection field // references in one statement.

void SearchInExpForCollectionArrayRef(SgStatement *br, SgExpression *e, int & level) {

if (e == NULL) return; if (e->variant() == POINTST_OP) { SgDerivedCollectionType *a; SgSymbol *b; a = isArrayRefOfCollection(e->lhs()); b = isReferenceToElementField(e->rhs()); if (a && b) { ReplaceWithGetElemPart(br, e, a, b, level); level = level + 1; } } else { SearchInExpForCollectionArrayRef(br, e->lhs(), level); SearchInExpForCollectionArrayRef(br, e->rhs(), level); } }

Expand Syntax - ReplaceWithGetElemPart

void ReplaceWithGetElemPart(SgStatement *br, SgExpression *e, SgDerivedCollectionType *a, SgSymbol *b, int level) {

SgBasicBlockStmt bgn; SgControlEndStmt nd; SgStatement *ext, *brnext; int matchingdummy; SgType *btype; matchingdummy = MatchingDummyVar(a->elementClass()); if (!matchingdummy) Message("Dummy variable has not been created!\n", 0); br->insertStmtBefore(bgn, *(br->controlParent())); brnext = br->lexNext(); ext = br->extractStmt();

SgExpression dummy(RECORD_REF); dummy.setLhs(*DummyVarExpr[matchingdummy]); dummy.setRhs(*(e->rhs())); char addr1str[16], addr2str[16]; if (level == 0) { strcpy(addr1str, "addr1"); strcpy(addr2str, "addr2"); } else { sprintf(addr1str, "addr1_%d", level); sprintf(addr2str, "addr2_%d", level); }

SgPointerType p(*SgTypeInt()); SgVariableSymb addr1(addr1str,p); SgVariableSymb addr2(addr2str,p); SgVarRefExp addr1ref(addr1), addr2ref(addr2); SgTypeArray *arrtype; if ((arrtype = isSgTypeArray(b->type())) && isSgArrayRefExp(e->rhs())) btype = arrtype->baseType(); else btype = b->type();

SgFunctionSymb *fsymb;

if (btype->equivalentToType(*SgTypeInt())) fsymb = GetElemInt; else if (btype->equivalentToType(*SgTypeFloat())) fsymb = GetElemFloat; else if (btype->equivalentToType(*SgTypeDouble())) fsymb = GetElemDouble; else fsymb = GetElementPart; SgFunctionCallExp func(*fsymb); func.addArg(*(e->lhs()->rhs())); func.addArg(addr2ref - addr1ref); // sizeof will be wrong for array's like x(i)->foo where foo // is an array so do more work. Handle only one, two and three dimension // cases.

// Need to work harder here. What about stuff like x(i)->foo[10] where the // field foo is a 2d array.

if ((arrtype = isSgTypeArray(b->type())) && isSgVarRefExp(e->rhs())) { if (arrtype->dimension() == 1) func.addArg(SgSizeOfOp(dummy) * arrtype->sizeInDim(0)->copy()); else if (arrtype->dimension() == 2) func.addArg(SgSizeOfOp(dummy) * arrtype->sizeInDim(0)->copy() * arrtype->sizeInDim(1)->copy()); else if (arrtype->dimension() == 3) func.addArg(SgSizeOfOp(dummy) * arrtype->sizeInDim(0)->copy() * arrtype->sizeInDim(1)->copy() * arrtype->sizeInDim(2)->copy()); } else func.addArg(SgSizeOfOp(dummy)); SgVarRefExp *collref; collref = isSgVarRefExp(e->lhs()->lhs()); e->setVariant(RECORD_REF); e->setLhs(*collref); e->setRhs(func); SgExpression x1(ASSGN_OP); x1.setLhs(addr1ref); x1.setRhs(SgAddrOp(*DummyVarExpr[matchingdummy])); SgExprListExp exp1(x1); SgCExpStmt addr1assgn(exp1); SgExpression x2(ASSGN_OP); x2.setLhs(addr2ref); x2.setRhs(SgAddrOp(dummy)); SgExprListExp exp2(x2); SgCExpStmt addr2assgn(exp2); bgn.insertStmtAfter(addr1assgn); addr1assgn.insertStmtAfter(addr2assgn); addr2assgn.insertStmtAfter(*ext); ext->insertStmtAfter(nd); addr1.declareTheSymbol(bgn); addr2.declareTheSymbol(bgn); }

Expand Syntax - MatchingDummyVar

int MatchingDummyVar(SgType *x) { for (int i=0; i < TotalDummyVars; i++) if (DummyVarType[i]->equivalentToType(*x)) return i; return 0; }

Expand Syntax - InDummyVarTable

int InDummyVarTable(SgType *x) {

for (int i=0; i < MAXDUMMYVAR; i++) if (DummyVarType[i] != NULL) if (DummyVarType[i]->equivalentToType(*x)) return TRUE;

return FALSE; }

Expand Syntax - Init

void Init( SgFile *f) { char strin[256]; SgStatement *fr; SgPointerType *p; SgSymbol *symb;

fr = f->firstStatement();

p = new SgPointerType(*SgTypeInt()); GetElementPart = new SgFunctionSymb(FUNCTION_NAME, "Get_ElementPart", *p, *fr); GetElemInt = new SgFunctionSymb(FUNCTION_NAME, "Get_ElementPart_Int", *p, *fr); GetElemFloat = new SgFunctionSymb(FUNCTION_NAME, "Get_ElementPart_Float", *p, *fr); GetElemDouble = new SgFunctionSymb(FUNCTION_NAME, "Get_ElementPart_Double", *p, *fr);

for (int i=0; i < MAXDUMMYVAR; i++) { DummyVar[i] = NULL; DummyVarType[i] = NULL; DummyVarExpr[i] = NULL; }

SgType *type; SgDerivedCollectionType *ct;

for (i=0,type = f->firstType(); type; type = type->next()) { if (ct = isSgDerivedCollectionType(type)) { SgType *elementype; elementype = ct->elementClass(); if (!InDummyVarTable(elementype)) { SgClassStmt *fordef;

sprintf(strin, "Dummy_%d", i); DummyVar[i] = new SgVariableSymb(strin, *elementype, *fr); DummyVar[i]->declareTheSymbol(*fr); DummyVarType[i] = elementype; DummyVarExpr[i] = new SgVarRefExp(*DummyVar[i]); fordef = new SgClassStmt(*elementype->symbol()); fr->insertStmtAfter(*fordef);

i++; } } }

TotalDummyVars = i; }

Expand Syntax - CAnalyze

void CAnalyze(SgProject * project){

for (int i = 0; i < project->numberOfFiles(); i++) { SgFile *f;

f = &(project->file(i)); Init(f); ExpandSyntax(f); } }

Expand Syntax - ProjectUnparse

void ProjectUnparse(SgProject *project) { for (int i = 0; i < project->numberOfFiles(); i++) { SgFile *f; f = &(project->file(i)); f->unparsestdout(); } }

Expand Syntax - main

main(int argc, char **argv){

SgProject project("simple.proj"); SgFile file("simple.pc"); int c;

switch (file.languageType()) { case CSrc: #if 1 CAnalyze(&project); ProjectUnparse(&project); #endif break;

case ForSrc: printf("Wrong language!\n"); exit(-1); } }

Dump Info

/*********************************************************************/ /* pC++/Sage++ Copyright (C) 1993 */ /* Indiana University University of Oregon University of Rennes */ /*********************************************************************/

#include <stdio.h> #include <malloc.h> #include "sage++user.h"

// This program demonstrates the functions that access the // contents of the parsed program stored in the .dep files. // It is very simple. It traverses the program file in lexical // order and examines each statement and prints out the // information stored in the file about the statement.


Dump Info - variants

// each object in the .dep file has an integer "variant" to // describe its type. There is a standard defined name for // each and that may be retrieved from the array "tag" below. #define MAXTAGS 1000 static char *tag[MAXTAGS]; void initVariantNames(){ for(int i = 0; i < MAXTAGS; i++) tag[i] = NULL; #include "../h/tag.h" } void printVariantName(int i){ if((i >= 0 && i < MAXTAGS) && tag[i]) printf("%s", tag[i]); else printf("not a known node variant"); }

Dump Info - ProjectUnparse

// the unparse operation regenerates source code. // The function below prints the entire project to // stdout. note: the current unparser will only print // to stdout. in the near future we will have a version // that will print to a string buffer.

void ProjectUnparse(SgProject *project) { for (int i = 0; i < project->numberOfFiles(); i++) { SgFile *f; f = &(project->file(i)); f->unparsestdout(); } }

Dump Info - classifyStatements

// some forward declarations.

void doExpr(SgExpression *e); void doSymb(SgSymbol *s); void doType(SgType *t); void doRoutineHeader(SgStatement *s); void doIfStmts(SgStatement *s); void doLoopStmts(SgStatement *s); void doIOStmts(SgStatement *s); void doGoToStmt(SgStatement *s); void doVarDecl(SgStatement *s); void doFullType(SgType *t); void doSymbAttribs(SgSymbol *s);

// this function traverses the list of statements in a file. // for each statement it prints out all the information available // in the .dep data base.

void classifyStatements(SgFile *f){ SgStatement *line; SgStatement *s; int i,j;

// grab the first statement in the file. s = f->firstStatement();

// follow the statements in lexical order. // an alternative is to follow them in scope order // using a recursive traversal, but this is simpler // for what we want to do here.

for (line = s; line; line = line->lexNext()){ printf("---------------------------------------------------------------------\n"); // print the line to the standard out. // note: if the statement controls other blocks // nested within, it will print the entire block // of "control children". line->unparsestdout();

// print out the variant tag, i.e. the type of statement. printf("STMT[%d] at line %d has variant:", line->id(), line->lineNumber()); printVariantName(line->variant()); printf("\n");

// is this a labeled statement? if so print the label. if(line->hasLabel()){ SgLabel *lab = line->label(); printf("has label[%d]\n", lab->id()); }

// are there comments that precede this statement? // if so print them out. if(line->comments()) printf("comments befor this line:\n%s", line->comments()); // for each type of statement call the appropriate special case // function. switch(line->variant()){ case GLOBAL: printf("The head-of-fole global node. not really a statement\n"); break; case PROG_HEDR: case PROC_HEDR: case FUNC_HEDR: printf(" a new routine.\n"); doRoutineHeader(line); break; case BASIC_BLOCK : printf(" a beginning of a control block for C programs \n"); break; case CONTROL_END: printf(" end of a control block for stmt %d\n", (line->controlParent())->id()); break; case IF_NODE: case ELSEIF_NODE: case ARITHIF_NODE: case LOGIF_NODE: doIfStmts(line); break; case LOOP_NODE: case FOR_NODE: case FORALL_NODE: case WHILE_NODE: doLoopStmts(line); break; case EXIT_NODE: // note the use of the special cast function // we are casting to a subtype but this is o.k. // with this function. {SgExitStmt * exst = isSgExitStmt(line); printf("an exit statement. exit from:\n"); doSymb(exst->constructName()); } break; case ASSIGN_STAT: { SgAssignStmt *ass = isSgAssignStmt(line); printf("an assignment\n"); // print out the two expressions on each side of = printf("left hand side:\n"); doExpr(ass->lhs()); printf("\nright hand side:\n"); doExpr(ass->rhs()); printf("\n"); } break; case PROC_STAT: { int i; SgCallStmt *call = isSgCallStmt(line); // a "call f(...) statement. extract the passed // arguement expressions and print them. printf("a subroutine call. passed args are\n"); for(i = 0; i < call->numberOfArgs(); i++){ printf("argument %d:\n", i); doExpr(call->arg(i)); printf("\n"); } } break; case WHERE_NODE: case ALLDO_NODE: case IDENTIFY: case FORMAT_STAT: case STOP_STAT: break; case RETURN_STAT: break; case GOTO_NODE: case ASSGOTO_NODE: case COMGOTO_NODE: doGoToStmt(line); break; case VAR_DECL: case INTENT_STMT: case OPTIONAL_STMT: case PUBLIC_STMT: case PRIVATE_STMT: case DIM_STAT: case ALLOCATABLE_STMT: case POINTER_STMT: case TARGET_STMT: case MODULE_PROC_STMT: case EXTERN_STAT: case COMM_STAT: case NAMELIST_STAT: case EQUI_STAT: case PARAM_DECL: case IMPL_DECL: case SAVE_DECL: case DATA_DECL: doVarDecl(line); break; case PAUSE_NODE: break; case STOP_NODE: break; case ASSLAB_STAT: break; case COMMENT_STAT: break; case CONT_STAT: printf(" continue statement: end of cntl for stmt %d\n", (line->controlParent())->id()); break; case ENTRY_STAT: case STMTFN_STAT: case BLOCK_DATA: case INTRIN_STAT: case PROC_COM: /* process common */ case ATTR_DECL: /* attribute declaration */ printf("another fortran statement\n"); break; // the statements below are all valid, and will be // treated in example when I have more time. case READ_STAT: case WRITE_STAT: case PRINT_STAT: case BACKSPACE_STAT: case REWIND_STAT : case ENDFILE_STAT: case INQUIRE_STAT: case OPEN_STAT: case CLOSE_STAT: case OTHERIO_STAT: doIOStmts(line); break; case INCLUDE_STAT: case ALLOCATE_STMT: case NULLIFY_STMT: case DEALLOCATE_STMT: case SEQUENCE_STMT: case CYCLE_STMT: case EXIT_STMT: case CONTAINS_STMT: case WHERE_BLOCK_STMT: case MODULE_STMT: case USE_STMT: case INTERFACE_STMT: case OVERLOADED_ASSIGN_STAT: case POINTER_ASSIGN_STAT: case OVERLOADED_PROC_STAT: printf("yet another fortran 90 statement.\n"); break; case DECOMPOSITION_STMT: /* Old Fortran D stuff */ case ALIGN_STMT: case DISTRIBUTE_STMT: case REDUCE_STMT: printf("Old Fortran D. not treated here..needs update\n"); break; case CDOALL_NODE: /* added for Cedar Fortran */ case SDOALL_NODE: case DOACROSS_NODE: case CDOACROSS_NODE: printf("Cedar Fortran. who cares anymore. \n"); break; case PARDO_NODE: /* Following added for PCF Fortran */ case PARSECTIONS_NODE: case SECTION_NODE: case GUARDS_NODE: case LOCK_NODE: case UNLOCK_NODE: case CRITSECTION_NODE: case POST_NODE: case WAIT_NODE: case CLEAR_NODE: case POSTSEQ_NODE: case WAITSEQ_NODE: case SETSEQ_NODE: case ASSIGN_NODE: case RELEASE_NODE: case PRIVATE_NODE: case SCOMMON_NODE: case PARREGION_NODE: case PDO_NODE: case PSECTIONS_NODE: case SINGLEPROCESS_NODE: case SKIPPASTEOF_NODE: printf("Old pcf fortran. needs update. who cares anymore. \n"); break; default: printf("unknown statement. not treated here..I am tired.\n"); break; } printf("---------------------------------------------------------------------\n"); } }

Dump Info - doRoutineHeader

// print out the name and formal parameters for this subroutine,
// function or main program header.

void doRoutineHeader(SgStatement *s){ SgProgHedrStmt * prog; SgProcHedrStmt * subr; SgFuncHedrStmt * func; int i; SgSymbol *sy;

if(subr = isSgProcHedrStmt (s)){ printf("symbol:%s", (subr->name()).identifier()); printf(" which is a suroutine.\n"); printf("parameter list:\n"); for(i = 0; i < subr->numberOfParameters(); i++){ sy = subr->parameter(i); printf("parameter(%d):", i); doSymb(sy); printf(" of type: "); doFullType(sy->type()); doSymbAttribs(sy); printf("\n"); } } else if(func = isSgFuncHedrStmt (s)){ printf("symbol:%s", (func->name()).identifier()); printf("which is a function of type "); doFullType((func->name()).type()); printf("\n"); printf("parameter list:\n"); for(i = 0; i < func->numberOfParameters(); i++){ sy = func->parameter(i); printf("parameter(%d):", i); doSymb(sy); printf(" of type: "); doFullType(sy->type()); doSymbAttribs(sy); printf("\n"); } } }

Dump Info - doIfStmts

// this routine handles the different types of "if" statements. // not finished. void doIfStmts(SgStatement *s){ SgLogIfStmt * logif; SgIfStmt * ifst; SgArithIfStmt * arithif;

if (logif = isSgLogIfStmt (s)){ printf("logical if: condition EXPR[%d] ", logif->conditional()->id()); (logif->conditional())->unparsestdout(); printf(" :if true do STMT[%d]\n", (logif->body())->id()); } else if(ifst = isSgIfStmt (s)){} else if(arithif = isSgArithIfStmt (s)){} }

Dump Info - doLoopStmts

// this routine handles the different types of loop statements. // only does do loops now. more later.

void doLoopStmts(SgStatement *s){ SgForStmt * doloop; SgWhileStmt * whileloop; SgExpression *e; if (doloop = isSgForStmt(s)){ printf("a DO LOOP: control var:"); doSymb(doloop->symbol()); printf("\n lower bound = "); if(e = doloop->start()) e->unparsestdout(); printf(" , upper bound = "); if(e = doloop->end()) e->unparsestdout(); if(e = doloop->step()){ printf(" , step = "); e->unparsestdout(); } printf(" \n"); if(doloop->endOfLoop()){ printf("end of loop label[%d]\n",(doloop->endOfLoop())->id()); } } else if(whileloop = isSgWhileStmt (s)){} else printf("not finished\n"); }

Dump Info - doIOStmts

// print out info about I/O statements. // not done. void doIOStmts(SgStatement *s){ SgIOStmt * iost; SgInputOutputStmt * inoust; SgIOControlStmt * iocntl; if (iost = isSgIOStmt(s)){} else if(inoust = isSgInputOutputStmt (s)){} else if(iocntl = isSgIOControlStmt(s)){}; }

// print out the information about the different types of // goto statements. // not done. only does standard goto's.

Dump Info - doGoToStmt

void doGoToStmt(SgStatement *s){ SgGotoStmt * gotostmt; SgAssignedGotoStmt * assgoto; SgComputedGotoStmt * compgoto; if(gotostmt = isSgGotoStmt(s)){ printf("garden variety goto: branch to stmt with label [ %d ]\n", gotostmt->branchLabel()->id());

} else if(assgoto = isSgAssignedGotoStmt(s)){} else if(compgoto = isSgComputedGotoStmt(s)){} }

Dump Info - doVarDecl

// this does variable declarations. // there are lots of different forms that a // declaration can take. this just does the standard // types now. not done yet.

void doVarDecl(SgStatement *s){ SgVarDeclStmt * var; SgVarListDeclStmt * varlist; SgStructureDeclStmt * strucdecl; SgNestedVarListDeclStmt* declst; SgParameterStmt * parm; SgImplicitStmt * implic; if (var = isSgVarDeclStmt(s)){ int i; printf("Variables declared here are:\n"); for(i = 0; i < var->numberOfSymbols(); i++){ SgSymbol *s; s = var->symbol(i); doSymb(s); printf(" of type: "); if(s->type()) doFullType(s->type()); printf("\n"); } } else if (varlist = isSgVarListDeclStmt (s)){} /* else if (strucdecl = isSgStructureDeclStmt (s)){} */ else if ( declst = isSgNestedVarListDeclStmt (s)){} else if ( parm = isSgParameterStmt (s)){} else if ( implic = isSgImplicitStmt (s)){} else printf("not here!\n"); }

Dump Info - doSymb

void doSymb(SgSymbol *s){ printf("SYMB[%d]:%s",s->id(),s->identifier()); }

Dump Info - doSymbAttribs

void doSymbAttribs(SgSymbol *s){ int i; if(s->attributes()){ i = s->attributes(); printf(" attributes =( "); if(i & ALLOCATABLE_BIT ){ printf(" allocatable,"); } if(i & DIMENSION_BIT ){ printf(" dim,"); } if(i & EXTERNAL_BIT ){ printf(" extern,"); } if(i & IN_BIT ){ printf(" in,"); } if(i & INOUT_BIT ){ printf(" inout,"); } if(i & INTRINSIC_BIT ){ printf(" intrinsic,"); } if(i & OPTIONAL_BIT ){ printf(" optional,"); } if(i & OUT_BIT ){ printf(" out,"); } if(i & PARAMETER_BIT ){ printf(" parameter,"); } if(i & POINTER_BIT ){ printf(" pointer,"); } if(i & PRIVATE_BIT ){ printf(" private,"); } if(i & PUBLIC_BIT ){ printf(" public,"); } if(i & SAVE_BIT ){ printf(" save,"); } if(i & SEQUENCE_BIT ){ printf(" seq,"); } if(i & RECURSIVE_BIT ){ printf(" recur,"); } if(i & TARGET_BIT ){ printf(" target,"); } printf(")"); } }

Dump Info - doFullType

// given a type, traverse it and generate full infomration void doFullType(SgType *t){ SgArrayType *arrayt; SgPointerType *ptr; SgReferenceType *ref; // only for C++ SgDerivedType *deriv; SgDescriptType *descr; // only for C and C++ SgDerivedCollectionType *col; // only for pC++ int i,n;

if(arrayt = isSgArrayType(t)){ printf("dimension("); n = arrayt->dimension(); for(i = 0; i < n; i++){ (arrayt->sizeInDim(i))->unparsestdout(); if(i < n-1) printf(", "); } printf(") "); } else{ switch(t->variant()){ case T_INT: printf("integer "); break; case T_FLOAT: printf("real "); break; case T_DOUBLE: printf("double precision "); break; case T_CHAR: printf("character "); break; case T_BOOL: printf("boolean "); break; case T_STRING: printf("string "); break; case T_RECORD: printf("record.. more later "); break; case T_UNKNOWN: printf("unknown "); break; case T_COMPLEX: printf("complex "); break; case LOCAL: case INPUT: case OUTPUT: case IO: printf("do these later\n"); break; } } if(t->hasBaseType()){ printf("of "); doFullType(t->baseType()); } }

Dump Info - classifyExpressions

// help functions for classifyExpression void doExpr(SgExpression *e){ printf("EXPR[%d]:",e->id()); e->unparsestdout(); }

int lhsId(SgExpression *e){ if(e->lhs()) return (e->lhs())->id(); else return -1; } int rhsId(SgExpression *e){ if(e->rhs()) return (e->rhs())->id(); else return -1; } int symbId(SgExpression *e){ if(e->symbol()) return (e->symbol())->id(); else return -1; } char * symbName(SgExpression *e){ if(e->symbol()) return (e->symbol())->identifier(); else return ""; } int typeId(SgExpression *e){ if(e->type()) return (e->type())->id(); else return -1; }

void classifyExpressions(SgFile *f){ SgExpression *e; for(e = f->firstExpression(); e; e = e->nextInExprTable()){ SgValueExp *valexp = isSgValueExp(e); printf("EXPR[%3d] ", e->id()); switch(e->variant()){ case INT_VAL: printf("integer value:%d ", valexp->intValue()); break; case FLOAT_VAL: printf("real value:%f ", valexp->floatValue()); break; case DOUBLE_VAL: printf("double value:%f ", valexp->doubleValue()); break; case BOOL_VAL: printf("bool value:%i ", valexp->intValue()); break; case CHAR_VAL: printf("char value:%c ", valexp->charValue()); break; case STRING_VAL: printf("string value:%s ", valexp->stringValue()); break; case COMPLEX_VAL: printf("complex: real part id=%d im part id=%d ", lhsId(e),rhsId(e)); break; case KEYWORD_VAL: /* Strings to be printed with quotes */ break; case CONST_REF: printf("constant ref: symb[%d]:%s type[%d] ", symbId(e), symbName(e), typeId(e)); break; case VAR_REF: printf("variable ref: symb[%d]:%s type[%d] ", symbId(e), symbName(e), typeId(e)); break; case ARRAY_REF: printf("array ref: symb[%d]:%s type[%d] subscript list id (%d) ", symbId(e), symbName(e), typeId(e), lhsId(e)); break; case RECORD_REF: case LABEL_REF: break; case VAR_LIST: case EXPR_LIST: case RANGE_LIST: printf("this item [%d] next list [%d] ", lhsId(e), rhsId(e)); break; case CASE_CHOICE: case DEF_CHOICE: case VARIANT_CHOICE: break; case DDOT: case RANGE_OP: case UPPER_OP: case LOWER_OP: case EQ_OP: case LT_OP: case GT_OP: case NOTEQL_OP: case LTEQL_OP: case GTEQL_OP: case ADD_OP: case SUBT_OP: case OR_OP: case MULT_OP: case DIV_OP: case MOD_OP: case AND_OP: case EXP_OP: case ARRAY_MULT: case CONCAT_OP: /* cancatenation of strings */ case XOR_OP: /* .XOR. in fortran */ case EQV_OP: /* .EQV. in fortran */ case NEQV_OP: /* .NEQV. in fortran */ printf("left oprnd[%d] right oprnd[%d] ", lhsId(e), rhsId(e)); break; case MINUS_OP: /* unary operations */ case NOT_OP: printf("operand [%d] ", lhsId(e)); break; case STAR_RANGE: /* operations with no operands 360.. */ break; case PROC_CALL: case FUNC_CALL: case CONSTRUCTOR_REF: case ACCESS_REF: case CONS: case ACCESS: case IOACCESS: case CONTROL_LIST: case SEQ: case SPEC_PAIR: case COMM_LIST: case STMT_STR: case EQUI_LIST: case IMPL_TYPE: case STMTFN_DECL: case BIT_COMPLEMENT_OP: case EXPR_IF: case EXPR_IF_BODY: case FUNCTION_REF: case UNARY_ADD_OP: case SIZE_OP: case INTEGER_DIV_OP: case SUB_OP: case NAMELIST_LIST: case ORDERED_OP: /* Following added for PCF FORTRAN */ case EXTEND_OP: case MAXPARALLEL_OP: case SAMETYPE_OP: case TYPE_REF: /* Added for FORTRAN 90 */ case STRUCTURE_CONSTRUCTOR: case ARRAY_CONSTRUCTOR: case SECTION_REF: case VECTOR_SUBSCRIPT: case SECTION_OPERANDS: case KEYWORD_ARG: case OVERLOADED_CALL: case INTERFACE_REF: case RENAME_NODE: case TYPE_NODE: case PAREN_OP: case PARAMETER_OP: case PUBLIC_OP: case PRIVATE_OP: case ALLOCATABLE_OP: case DIMENSION_OP: case EXTERNAL_OP: case IN_OP: case OUT_OP: case INOUT_OP: case INTRINSIC_OP: case POINTER_OP: case OPTIONAL_OP: case SAVE_OP: case TARGET_OP: case ONLY_NODE: case LEN_OP: case TYPE_OP: default: break; } printf(" variant: "); printVariantName(e->variant()); printf(" expr is: "); e->unparsestdout(); printf("\n"); } }

Dump Info - classifySymbols

void classifySymbols(SgFile *f){ SgSymbol *s; SgVariableSymb *vs; SgConstantSymb *cs; SgFunctionSymb *fs; SgLabelVarSymb *lvs; SgExternalSymb *exts; SgConstructSymb *cnsts; SgInterfaceSymb *ifs; SgModuleSymb *mods; for(s = f->firstSymbol(); s; s = s->next()){ printf("SYMB[%d]: %s = %s scope=STMT[%d] type:", s->id(),tag[s->variant()], s->identifier(), (s->scope())?(s->scope())->id(): -1); if(s->type()) doFullType(s->type()); doSymbAttribs(s); printf("\n"); switch(s->variant()){ case CONST_NAME: case VARIABLE_NAME: case PROGRAM_NAME: case PROCEDURE_NAME: case LABEL_VAR: /* dest of assigned goto stmt */ case FUNCTION_NAME: case LABEL_NAME: /* new added for VPC */ case ROUTINE_NAME: /*added for external statement*/ case CONSTRUCT_NAME: case INTERFACE_NAME: case MODULE_NAME: printf(" need work\n"); break; default: printf("forgot one\n"); break; } } }

Dump Info - main

int main(int argc, char **argv){

SgProject project("x.proj"); SgFile file("x.f"); int c;


switch (file.languageType()) { case CSrc: printf("this is a c program. this example is for fortran \n"); return -1; case ForSrc: classifyStatements(&file); printf("**************************************************\n"); printf("**** Expression Table ****************************\n"); printf("**************************************************\n"); classifyExpressions(&file); printf("**************************************************\n"); printf("**** Symbol Table *******************************\n"); printf("**************************************************\n"); classifySymbols(&file); } return 0; }

Exit Sage++ User's Guide