diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/chill.cc | 3 | ||||
-rw-r--r-- | src/chill_ast.cc | 6493 | ||||
-rw-r--r-- | src/chillmodule.cc | 6 | ||||
-rw-r--r-- | src/dep.cc | 133 | ||||
-rwxr-xr-x | src/ir_clang.cc | 3239 | ||||
-rw-r--r-- | src/ir_rose.cc | 1699 | ||||
-rw-r--r-- | src/ir_rose_utils.cc | 62 | ||||
-rw-r--r-- | src/irtools.cc | 525 | ||||
-rw-r--r-- | src/loop.cc | 3500 | ||||
-rw-r--r-- | src/loop_basic.cc | 477 | ||||
-rw-r--r-- | src/loop_datacopy.cc | 282 | ||||
-rw-r--r-- | src/loop_unroll.cc | 118 | ||||
-rw-r--r-- | src/omegatools.cc | 3007 |
13 files changed, 16809 insertions, 2735 deletions
diff --git a/src/chill.cc b/src/chill.cc index 6ca0c4c..b91d383 100644 --- a/src/chill.cc +++ b/src/chill.cc @@ -9,7 +9,6 @@ #include "loop.hh" #include <omega.h> #include "ir_code.hh" -#include "ir_rose.hh" #include "chillmodule.hh" // Python wrapper functions for CHiLL @@ -76,8 +75,6 @@ int main( int argc, char* argv[] ) lnum_start = get_loop_num_start(); lnum_end = get_loop_num_end(); DEBUG_PRINT("calling ROSE code gen? loop num %d\n", lnum); - finalize_loop(lnum_start, lnum_end); - ((IR_roseCode*)(ir_code))->finalizeRose(); delete ir_code; } Py_Finalize(); diff --git a/src/chill_ast.cc b/src/chill_ast.cc new file mode 100644 index 0000000..93afd97 --- /dev/null +++ b/src/chill_ast.cc @@ -0,0 +1,6493 @@ + + + +#include "chill_ast.hh" + +using namespace std; + +int chillAST_node::chill_scalar_counter = 0; +int chillAST_node::chill_array_counter = 1; + + +const char* Chill_AST_Node_Names[] = { + "Unknown AST node type", + "SourceFile", + "TypedefDecl", + "VarDecl", + // "ParmVarDecl", not used any more + "FunctionDecl", + "RecordDecl", + "MacroDefinition", + "CompoundStmt", + "ForStmt", + "TernaryOperator", + "BinaryOperator", + "UnaryOperator", + "ArraySubscriptExpr", + "MemberExpr", + "DeclRefExpr", + "IntegerLiteral", + "FloatingLiteral", + "ImplicitCastExpr", // not sure we need this + "ReturnStmt", + "CallExpr", + "DeclStmt", + "ParenExpr", + "CStyleCastExpr", + "CStyleAddressOf", + "IfStmt", + "SizeOf", + "Malloc", + "Free", + "NoOp", +// CUDA specific + "CudaMalloc", + "CudaFree", + "CudaMemcpy", + "CudaKernelCall", + "CudaSyncthreads", + "fake1", + "fake2", + "fake3" +}; + +char *parseUnderlyingType( char *sometype ) { + int len = strlen(sometype); + //fprintf(stderr, "parseUnderlyingType( %s )\n", sometype); + char *underlying = strdup(sometype); + char *p; + char *start = underlying; + + // ugly. we want to turn "float *" into "float" but "struct abc *" into struct abc. + // there are probably many more cases. have an approved list? TODO + if (strstr(underlying, "struct ")) start += 7; // (length("struct ")) + //fprintf(stderr, "sometype '%s' start '%s'\n", sometype, start); + if (p = index(start, ' ')) *p = '\0'; // end at first space leak + if (p = index(start, '[')) *p = '\0'; // leak + if (p = index(start, '*')) *p = '\0'; // leak + + return underlying; +} + +void printSymbolTable( chillAST_SymbolTable *st ) { + //printf("%d entries\n", st->size()); + if (!st) return; + for (int i=0; i<st->size(); i++) { printf("%d ", i ); (*st)[i]->printName(); printf("\n"); } + if (st->size() )printf("\n"); + fflush(stdout); +} + +void printSymbolTableMoreInfo( chillAST_SymbolTable *st ) { + //printf("%d entries\n", st->size()); + if (!st) return; + for (int i=0; i<st->size(); i++) { printf("%d ", i ); (*st)[i]->print(); printf("\n"); } + if (st->size() )printf("\n"); + fflush(stdout); +} + + +bool symbolTableHasVariableNamed( chillAST_SymbolTable *table, const char *name ) { + if (!table) return false; // ?? + int numvars = table->size(); + for (int i=0; i<numvars; i++) { + chillAST_VarDecl *vd = (*table)[i]; + if (!strcmp(name, vd->varname)) return true; // need to check type? + } + return false; +} + + + +chillAST_VarDecl *symbolTableFindVariableNamed( chillAST_SymbolTable *table, const char *name ){ // fwd decl TODO too many similar named functions + if (!table) return NULL; // ?? + + // see if name has a dot or arrow (->) indicating that it is a structure/class + const char *cdot = strstr( name, "." ); + const char *carrow = strstr(name, "->"); // initial 'c' for const - can't change those + + char *varname; + char *subpart = NULL; + + if (cdot || carrow) { + fprintf(stderr, "symbolTableFindVariableNamed(), name '%s' looks like a struct\n", name); + + // so, look for the first part in the symbol table. + // warning, this could be looking for a->b.c.d->e.f->g + varname = strdup( name ); + + char *dot = strstr(varname, "." ); + char *arrow = strstr( varname, "->" ); + if (dot != NULL && arrow != NULL ) { // dot AND arrow, + fprintf(stderr, "chillast.cc symbolTableFindVariableNamed(), name '%s' has both dot and arrow? TODO\n"); + exit(-1); + } + else if (dot != NULL && !arrow) { // just dot(s). dot points to the first one + //fprintf(stderr, "name '%s' has dot(s)\n", varname); + *dot = '\0'; // end string at the dot + subpart = &(dot[1]); + fprintf(stderr, "will now look for a struct/class named %s that has member %s\n", varname, subpart); + + } + else if (arrow != NULL && !dot) { // just arrow(s) arrow points to the first one + //fprintf(stderr, "name '%s' has arrow(s)\n", varname); + *arrow = '\0'; // end string at the arrow + subpart = &(arrow[2]); + fprintf(stderr, "will now look for a struct/class named %s that has member %s\n", varname, subpart); + } + else { // impossible + fprintf(stderr, "chillast.cc symbolTableFindVariableNamed(), varname '%s', looks like a struct, but I can't figure it out\n", varname); + exit(-1); + } + } + else { + varname = strdup(name); + } + + int numvars = table->size(); + for (int i=0; i<numvars; i++) { + chillAST_VarDecl *vd = (*table)[i]; + if (!strcmp(varname, vd->varname)) { + fprintf(stderr, "found variable named %s\n", varname); + + if (!subpart) return vd; // need to check type? + + // OK, we have a variable, which looks like a struct/class, and a subpart that is some member names + //fprintf(stderr, "but I don't know how to check if it has member %s\n", subpart); + + char *dot = strstr(subpart, "." ); + char *arrow = strstr(subpart, "->" ); + + if (!dot && !arrow) { // whew, only one level of struct + //fprintf(stderr, "whew, only one level of struct\n"); + + // make sure this variable definition is a struct + if (vd->isAStruct()) { + //fprintf(stderr, "%s is a struct of type %s\n", varname, vd->getTypeString()); + if (vd->isVarDecl()) { + chillAST_RecordDecl *rd = vd->getStructDef(); + if (rd) { + //fprintf(stderr, "has a recordDecl\n"); + + chillAST_VarDecl *sp = rd->findSubpart( subpart ); + if (sp) fprintf(stderr, "found a struct member named %s\n", subpart); + else fprintf(stderr, "DIDN'T FIND a struct member named %s\n", subpart); + return sp; // return the subpart?? + } + else { + fprintf(stderr, "no recordDecl\n"); + exit(-1); + } + } + else { + fprintf(stderr, "NOT a VarDecl???\n"); // impossible + } + } + else { + fprintf(stderr, "false alarm. %s is a variable, but doesn't have subparts\n", varname); + return NULL; // false alarm. a variable of the correct name exists, but is not a struct + } + } + + fprintf(stderr, "chillast.cc symbolTableFindVariableNamed(), name '%s' can't figure out multiple levels of struct yet!\n"); + + exit(-1); + } + } + return NULL; +} + + + +char *ulhack( char *brackets ) // remove UL from numbers, MODIFIES the argument! +{ + //fprintf(stderr, "ulhack( \"%s\" -> ", brackets); + // another hack. remove "UL" from integers + int len = strlen(brackets); + for (int i=0; i< len-2; i++) { + if (isdigit(brackets[i])) { + if (brackets[i+1] == 'U' && brackets[i+2] == 'L') { + // remove + for (int j=i+3; j<len; j++) brackets[j-2] = brackets[j]; + len -=2; + brackets[len] = '\0'; + } + } + } + //fprintf(stderr, "\"%s\" )\n", brackets); + return brackets; +} + + +char *restricthack( char *typeinfo ) // remove __restrict__ , MODIFIES the argument! +{ + //if (!isRestrict( typeinfo )) return typeinfo; + + // there is a "__restrict__ " somewhere embedded. remove it. + // duplicate work + std::string r( "__restrict__" ); + std::string t( typeinfo ); + size_t index = t.find( r ); + + if (index == std::string::npos) return typeinfo; + + char *c = &( typeinfo[index] ); + char *after = c + 12; + if (*after == ' ') after++; + + //fprintf(stderr, "after = '%s'\n", after); + + while (*after != '\0') *c++ = *after++; + *c = '\0'; + + return typeinfo; + +} + + + + + +char *parseArrayParts( char *sometype ) { + int len = strlen(sometype); + char *arraypart = (char *)calloc(1 + strlen(sometype), sizeof(char));// leak + + int c = 0; + for (int i=0; i<strlen(sometype); ) { + if ( sometype[i] == '*') arraypart[c++] = '*'; + if ( sometype[i] == '[') { + while (sometype[i] != ']') { + arraypart[c++] = sometype[i++]; + } + arraypart[c++] = ']'; + } + i += 1; + } + ulhack(arraypart); + restricthack( arraypart ); + + //fprintf(stderr, "parseArrayParts( %s ) => %s\n", sometype, arraypart); + return arraypart; +} + + + + + + + +char *splitTypeInfo( char *underlyingtype ) { // return the bracketed part of a type + char *ap = ulhack(parseArrayParts( underlyingtype )); // return this + + // now need to remove all that from the underlyingtype to get + char *arraypart = strdup(""); // leak + if (index(underlyingtype, '[')) { + // looks like an array + free(arraypart); + char *start = index(underlyingtype, '['); // wrong. can have int *buh[32] + arraypart = strdup( start ); + if (*(start-1) == ' ') start--; // hack + *start = '\0'; + + // ugly. very leaky + strcpy( underlyingtype, parseUnderlyingType( underlyingtype )); + + // ulhack( arraypart ); + } + return ap; // leak unless caller frees this +} + + + +bool isRestrict( const char *sometype ) { // does not modify sometype + string r( "__restrict__" ); + string t( sometype ); + return (std::string::npos != t.find( r ) ); +} + + + +bool streq( const char *a, const char *b) { return !strcmp(a,b); }; // slightly less ugly // TODO enums + +void chillindent( int howfar, FILE *fp ) { for (int i=0; i<howfar; i++) fprintf(fp, " "); } + + + +chillAST_VarDecl * chillAST_node::findVariableNamed( const char *name ) { // generic, recursive + fprintf(stderr, "nodetype %s findVariableNamed( %s )\n", getTypeString(), name ); + if (hasSymbolTable()) { // look in my symbol table if I have one + fprintf(stderr, "%s has a symbol table\n", getTypeString()); + chillAST_VarDecl *vd = symbolTableFindVariableNamed( getSymbolTable(), name); + if (vd) { + fprintf(stderr, "found it\n"); + return vd; // found locally + } + fprintf(stderr, "%s has a symbol table but couldn't find %s\n", getTypeString(), name ); + } + if (!parent) { + fprintf(stderr, "%s has no parent\n", getTypeString()); + return NULL; // no more recursion available + } + // recurse upwards + //fprintf(stderr, "recursing from %s up to parent %p\n", getTypeString(), parent); + fprintf(stderr, "recursing from %s up to parent\n", getTypeString()); + return parent->findVariableNamed( name ); +} + + +chillAST_RecordDecl * chillAST_node::findRecordDeclNamed( const char *name ) { // recursive + fprintf(stderr, "%s::findRecordDeclNamed( %s )\n", getTypeString(), name); + // look in children + int numchildren = children.size(); + fprintf(stderr, "%d children\n", numchildren); + for (int i=0; i<numchildren; i++) { + fprintf(stderr, "child %d %s\n", i, children[i]->getTypeString()); + if (children[i]->isRecordDecl()) { + chillAST_RecordDecl *RD = (chillAST_RecordDecl *)children[i]; + fprintf(stderr, "it is a recordDecl named '%s' vs '%s'\n", RD->getName(), name); + if (!strcmp( RD->getName(), name )) { + fprintf(stderr, "FOUND IT\n"); + return RD; + } + } + } + + if (!parent) return NULL; // no more recursion available + // recurse upwards + return parent->findRecordDeclNamed( name ); +} + + +void chillAST_node::printPreprocBEFORE( int indent, FILE *fp ) { + int numstmts = preprocessinginfo.size(); + //if (0 != numstmts) { + // fprintf(fp, "chillAST_node::printPreprocBEFORE() %d statements\n", numstmts); + //} + + + for (int i=0; i< numstmts; i++) { + //fprintf(fp, "stmt %d %d\n", i, preprocessinginfo[i]->position); + if (preprocessinginfo[i]->position == CHILL_PREPROCESSING_LINEBEFORE || + preprocessinginfo[i]->position == CHILL_PREPROCESSING_IMMEDIATELYBEFORE) { + //fprintf(stderr, "before %d\n", preprocessinginfo[i]->position); + preprocessinginfo[i]->print(indent, fp); + } + } +} + +void chillAST_node::printPreprocAFTER( int indent, FILE *fp ) { + for (int i=0; i< preprocessinginfo.size(); i++) { + if (preprocessinginfo[i]->position == CHILL_PREPROCESSING_LINEAFTER || + preprocessinginfo[i]->position == CHILL_PREPROCESSING_TOTHERIGHT) { + //fprintf(stderr, "after %d\n", preprocessinginfo[i]->position); + preprocessinginfo[i]->print(indent, fp); + } + } +} + + +chillAST_SourceFile::chillAST_SourceFile::chillAST_SourceFile() { + SourceFileName = strdup("No Source File"); + asttype = CHILLAST_NODETYPE_SOURCEFILE; + parent = NULL; // top node + metacomment = NULL; + global_symbol_table = NULL; + global_typedef_table = NULL; + FileToWrite = NULL; + frontend = strdup("unknown"); + isFromSourceFile = true; + filename = NULL; +}; + +chillAST_SourceFile::chillAST_SourceFile(const char *filename ) { + SourceFileName = strdup(filename); + asttype = CHILLAST_NODETYPE_SOURCEFILE; + parent = NULL; // top node + metacomment = NULL; + global_symbol_table = NULL; + global_typedef_table = NULL; + FileToWrite = NULL; + frontend = strdup("unknown"); + isFromSourceFile = true; + filename = NULL; +}; + +void chillAST_SourceFile::print( int indent, FILE *fp ) { + //fprintf(stderr, "chillAST_SourceFile::print()\n"); + fflush(fp); + fprintf(fp, "\n// this source derived from CHILL AST originally from file '%s' as parsed by frontend compiler %s\n\n", SourceFileName, frontend); + std::vector< char * > includedfiles; + int sofar = 0; + + //fprintf(fp, "#define __rose_lt(x,y) ((x)<(y)?(x):(y))\n#define __rose_gt(x,y) ((x)>(y)?(x):(y))\n"); // help diff figure out what's going on + + int numchildren = children.size(); + //fprintf(stderr, "// sourcefile has %d children\n", numchildren); + //fprintf(stderr, "they are\n"); + //for (int i=0; i<numchildren; i++) { + // fprintf(stderr, "%s ", children[i]->getTypeString()); + // if (children[i]->isFunctionDecl()) { + // fprintf(stderr, "%s ", ((chillAST_FunctionDecl *)children[i])->functionName); + // } + // fprintf(stderr, "\n"); + //} + + for (int i=0; i<numchildren; i++) { + //fprintf(fp, "\n// child %d of type %s:\n", i, children[i]->getTypeString()); + if (children[i]->isFromSourceFile) { + if (children[i]->isFunctionDecl()) { + fprintf(stderr, "\nchild %d function %s\n",i,((chillAST_FunctionDecl *)children[i])->functionName); + } + //fprintf(stderr, "child %d IS from source file\n", i); + //if (children[i]->isMacroDefinition()) fprintf(fp, "\n"); fflush(fp); + children[i]->print( indent, fp ); + if (children[i]->isVarDecl()) fprintf(fp, ";\n"); fflush(fp); // top level vardecl\n"); + } + else { + //fprintf(stderr, "child %d is not from source file\n", i); + // this should all go away + +#ifdef NOPE + if (children[i]->filename // not null and not empty string + //&& 0 != strlen(children[i]->filename) + ) { // should not be necessary + //fprintf(fp, "// need an include for %s\n", children[i]->filename); + bool rddid = false; + sofar = includedfiles.size(); + + for (int j=0; j<sofar; j++) { + //fprintf(stderr, "comparing %s and %s\n", includedfiles[j], children[i]->filename ); + if (!strcmp( includedfiles[j], children[i]->filename) ) { // this file has already been included + rddid = true; + //fprintf(stderr, "already did that one\n"); + } + } + + if (false == rddid) { // we need to include it now + fprintf(fp, "#include \"%s\"\n", children[i]->filename); + includedfiles.push_back(strdup( children[i]->filename )); + } + //else { + // fprintf(fp, "already did\n"); + //} + } +#endif // NOPE + + + } + } + + fflush(fp); + + //fprintf(fp, "\n\n// functions??\n"); + //for (int i=0; i<functions.size(); i++) { + // fprintf(fp, "\n\n"); functions[i]->print(0,fp); fflush(fp); + //} +}; + + + + +void chillAST_SourceFile::printToFile( char *filename ) { + char fn[1024]; + + if (NULL == filename) { // build up a filename using original name and frontend if known + if (FileToWrite) { + strcpy( fn, FileToWrite ); + } + else { + // input name with name of frontend compiler prepended + if (frontend) sprintf(fn, "%s_%s\0", frontend, SourceFileName); + else sprintf(fn, "UNKNOWNFRONTEND_%s\0", SourceFileName); // should never happen + } + } + else strcpy( fn, filename ); + + FILE *fp = fopen(fn, "w"); + if (!fp) { + fprintf(stderr, "can't open file '%s' for writing\n", fn); + exit(-1); + } + + //fprintf(fp, "\n\n"); + //dump(0, fp); + fprintf(fp, "\n\n"); + print(0, fp); + +} + + + +void chillAST_SourceFile::dump( int indent, FILE *fp ) { + fflush(fp); + fprintf(fp, "\n//CHILL AST originally from file '%s'\n", SourceFileName); + int numchildren = children.size(); + for (int i=0; i<numchildren; i++) { + children[i]->dump( indent, fp ); + } + fflush(fp); +}; + + + +chillAST_MacroDefinition * chillAST_SourceFile::findMacro( const char *name ) { + //fprintf(stderr, "chillAST_SourceFile::findMacro( %s )\n", name ); + + int numMacros = macrodefinitions.size(); + for (int i=0; i<numMacros; i++) { + if (!strcmp( macrodefinitions[i]->macroName, name )) return macrodefinitions[i]; + } + return NULL; // not found +} + + +chillAST_FunctionDecl * chillAST_SourceFile::findFunction( const char *name ) { + //fprintf(stderr, "chillAST_SourceFile::findMacro( %s )\n", name ); + + int numFuncs = functions.size(); + for (int i=0; i<numFuncs; i++) { + if ( !strcmp( functions[i]->functionName, name )) return functions[i]; + } + return NULL; +} + + +chillAST_node *chillAST_SourceFile::findCall( const char *name ) { + chillAST_MacroDefinition *macro = findMacro( name ); + if (macro) return (chillAST_node *)macro; + chillAST_FunctionDecl *func =findFunction( name ); + return func; +} + + +chillAST_VarDecl * chillAST_SourceFile::findVariableNamed( const char *name ) { + fprintf(stderr, "SOURCEFILE SPECIAL %s findVariableNamed( %s )\n", getTypeString(), name ); + if (hasSymbolTable()) { // look in my symbol table if I have one + fprintf(stderr, "%s has a symbol table\n", getTypeString()); + chillAST_VarDecl *vd = symbolTableFindVariableNamed( getSymbolTable(), name); + if (vd) { + fprintf(stderr, "found it\n"); + return vd; // found locally + } + fprintf(stderr, "%s has a symbol table but couldn't find %s\n", getTypeString(), name ); + } + + fprintf(stderr, "looking for %s in SourceFile global_symbol_table\n", name); + chillAST_VarDecl *vd = symbolTableFindVariableNamed( global_symbol_table, name ); + if (vd) { + fprintf(stderr, "found it\n"); + return vd; // found locally + } + + if (!parent) { + fprintf(stderr, "%s has no parent\n", getTypeString()); + return NULL; // no more recursion available + } + // recurse upwards + //fprintf(stderr, "recursing from %s up to parent %p\n", getTypeString(), parent); + fprintf(stderr, "recursing from %s up to parent\n", getTypeString()); + return parent->findVariableNamed( name ); +} + + + +chillAST_TypedefDecl::chillAST_TypedefDecl() { + underlyingtype = newtype = arraypart = NULL; + asttype = CHILLAST_NODETYPE_TYPEDEFDECL; + parent = NULL; + metacomment = NULL; + isStruct = isUnion = false; + structname = NULL; + rd = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_TypedefDecl::chillAST_TypedefDecl(char *t, char *nt, chillAST_node *par) { + //fprintf(stderr, "chillAST_TypedefDecl::chillAST_TypedefDecl( underlying type %s, newtype %s )\n", t, nt); + underlyingtype = strdup(t); + newtype = strdup(nt); + arraypart = NULL; + asttype = CHILLAST_NODETYPE_TYPEDEFDECL; + parent = NULL; + metacomment = NULL; + isStruct = isUnion = false; + structname = NULL; + rd = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_TypedefDecl::chillAST_TypedefDecl(char *t, char *a, char *p, chillAST_node *par) { + underlyingtype = strdup(t); + //fprintf(stderr, "chillAST_TypedefDecl::chillAST_TypedefDecl( underlying type %s )\n", underlyingtype); + newtype = strdup(a); // the new named type ?? + + arraypart = strdup(p); // array (p)art? + // splitarraypart(); // TODO + + asttype = CHILLAST_NODETYPE_TYPEDEFDECL; + parent = par; + metacomment = NULL; + isStruct = isUnion = false; + structname = NULL; + rd = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + + + +void chillAST_TypedefDecl::print( int indent, FILE *fp ) { + //fprintf(fp, "typedefdecl->print()\n"); + + printPreprocBEFORE(indent, fp); + + if (isStruct) { + fprintf(fp, "\n/* A typedef STRUCT */\n"); chillindent(indent, fp); + } + + chillindent(indent, fp); + fprintf(fp, "typedef "); fflush(fp); + + if (rd) { + rd->print(indent, fp); // needs to not print the ending semicolon ?? + } + + else if (isStruct) { + fprintf(stderr, "/* no rd */\n"); + + //fprintf(fp, "struct %s\n", structname); + chillindent(indent, fp); + fprintf(fp, "{\n"); + for (int i=0; i<subparts.size(); i++) { + //fprintf(fp, "a %s\n", subparts[i]->getTypeString()); + subparts[i]->print(indent+1, fp); + fprintf(fp, ";\n"); + } + fprintf(fp, "};\n"); + } + else { + fprintf(fp, "/* NOT A STRUCT */ typedef %s %s%s;\n", underlyingtype, newtype, arraypart ); + dump(); printf("\n\n"); fflush(stdout); + } + + // then the newname + fprintf(fp, "%s;\n", newtype); + fflush(fp); + printPreprocAFTER(indent, fp); + + return; +} + + +chillAST_VarDecl *chillAST_TypedefDecl::findSubpart( const char *name ) { + //fprintf(stderr, "chillAST_TypedefDecl::findSubpart( %s )\n", name); + //fprintf(stderr, "typedef %s %s\n", structname, newtype); + + if (rd) { // we have a record decl look there + chillAST_VarDecl *sub = rd->findSubpart( name ); + //fprintf(stderr, "rd found subpart %p\n", sub); + return sub; + } + + // can this ever happen now ??? + int nsub = subparts.size(); + //fprintf(stderr, "%d subparts\n", nsub); + for (int i=0; i<nsub; i++) { + if ( !strcmp( name, subparts[i]->varname )) return subparts[i]; + } + //fprintf(stderr, "subpart not found\n"); + + + return NULL; +} + + +chillAST_RecordDecl * chillAST_TypedefDecl::getStructDef() { + if (rd) return rd; + return NULL; +} + + + +chillAST_RecordDecl::chillAST_RecordDecl() { + asttype = CHILLAST_NODETYPE_RECORDDECL; + name = strdup("unknown"); // ?? + originalname = NULL; // ?? + isStruct = isUnion = false; + parent = NULL; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_RecordDecl::chillAST_RecordDecl( const char *nam, chillAST_node *p ) { + //fprintf(stderr, "chillAST_RecordDecl::chillAST_RecordDecl()\n"); + asttype = CHILLAST_NODETYPE_RECORDDECL; + parent = p; + if (nam) name = strdup(nam); + else name = strdup("unknown"); // ?? + originalname = NULL; // ?? // make them do it manually? + isStruct = isUnion = false; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_RecordDecl::chillAST_RecordDecl( const char *nam, const char *orig, chillAST_node *p ) { + fprintf(stderr, "chillAST_RecordDecl::chillAST_RecordDecl( %s, ( AKA %s ) )\n", nam, orig); + asttype = CHILLAST_NODETYPE_RECORDDECL; + parent = p; + if (p) p->addChild( this ); + + if (nam) name = strdup(nam); + else name = strdup("unknown"); // ?? + + originalname = NULL; + if (orig) originalname = strdup(orig); + + isStruct = isUnion = false; + isFromSourceFile = true; // default + filename = NULL; +} + + + +chillAST_VarDecl * chillAST_RecordDecl::findSubpart( const char *nam ){ + //fprintf(stderr, "chillAST_RecordDecl::findSubpart( %s )\n", nam); + int nsub = subparts.size(); + //fprintf(stderr, "%d subparts\n", nsub); + for (int i=0; i<nsub; i++) { + //fprintf(stderr, "comparing to '%s' to '%s'\n", nam, subparts[i]->varname); + if ( !strcmp( nam, subparts[i]->varname )) return subparts[i]; + } + fprintf(stderr, "chillAST_RecordDecl::findSubpart() couldn't find member NAMED %s in ", nam); print(); printf("\n\n"); fflush(stdout); + + return NULL; +} + + +chillAST_VarDecl * chillAST_RecordDecl::findSubpartByType( const char *typ ){ + //fprintf(stderr, "chillAST_RecordDecl::findSubpart( %s )\n", nam); + int nsub = subparts.size(); + //fprintf(stderr, "%d subparts\n", nsub); + for (int i=0; i<nsub; i++) { + //fprintf(stderr, "comparing '%s' to '%s'\n", typ, subparts[i]->vartype); + if ( !strcmp( typ, subparts[i]->vartype )) return subparts[i]; + } + //fprintf(stderr, "chillAST_RecordDecl::findSubpart() couldn't find member of TYPE %s in ", typ); print(); printf("\n\n"); fflush(stdout); + + return NULL; +} + + +void chillAST_RecordDecl::print( int indent, FILE *fp ) { + //fprintf(fp, "chillAST_RecordDecl::print()\n"); + if (isUnnamed) return; + + printPreprocBEFORE(indent, fp); + + chillindent(indent, fp); + if (isStruct) { + //fprintf(fp, "\n/* A Record Decl STRUCT */\n"); chillindent(indent, fp); + fprintf(fp, "struct "); + if ( strncmp( "unnamed", name, 7) ) fprintf(fp, "%s\n", name); + + chillindent(indent, fp); + fprintf(fp, "{\n"); + for (int i=0; i<subparts.size(); i++) { + //fprintf(fp, "a %s\n", subparts[i]->getTypeString()); + subparts[i]->print(indent+1, fp); + fprintf(fp, ";\n"); + } + fprintf(fp, "} "); + fprintf(fp, "\n"); // TODO need semicolon when defining struct. can't have it when part of a typedef. One of the following lines is correct in each case. + //fprintf(fp, ";\n"); + } + else { + fprintf(fp, "/* UNKNOWN RECORDDECL print() */ "); + exit(-1); + } + printPreprocAFTER(indent, fp); + fflush(fp); +} + + +chillAST_SymbolTable * chillAST_RecordDecl::addVariableToSymbolTable( chillAST_VarDecl *vd ){ + // for now, just bail. or do we want the struct to have an actual symbol table? + //fprintf(stderr, "chillAST_RecordDecl::addVariableToSymbolTable() ignoring struct member %s vardecl\n", vd->varname); + return NULL; // damn, I hope nothing uses this! +} + +void chillAST_RecordDecl::printStructure( int indent, FILE *fp ) { + //fprintf(stderr, "chillAST_RecordDecl::printStructure()\n"); + chillindent(indent, fp); + if (isStruct) { + fprintf(fp, "struct { ", name); + for (int i=0; i<subparts.size(); i++) { + subparts[i]->print( 0, fp); // ?? TODO indent level + fprintf(fp, "; "); + } + fprintf(fp, "} "); + } + else { + fprintf(fp, "/* UNKNOWN RECORDDECL printStructure() */ "); + exit(-1); + } + fflush(fp); +} + + + +void chillAST_RecordDecl::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + +} + + +chillAST_FunctionDecl::chillAST_FunctionDecl() { + functionName = strdup("YouScrewedUp"); + asttype = CHILLAST_NODETYPE_FUNCTIONDECL; + forwarddecl = externfunc = builtin = false; + uniquePtr = (void *) NULL; + this->setFunctionCPU(); + parent = NULL; + metacomment = NULL; + //symbol_table = NULL; // eventually, pointing to body's symbol table + typedef_table = NULL; + body = new chillAST_CompoundStmt(); + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_FunctionDecl::chillAST_FunctionDecl(const char *rt, const char *fname, chillAST_node *par) { + returnType = strdup(rt); + functionName = strdup(fname); + this->setFunctionCPU(); + //fprintf(stderr, "functionName %s\n", functionName); + forwarddecl = externfunc = builtin = false; + + asttype = CHILLAST_NODETYPE_FUNCTIONDECL; + parent = par; + metacomment = NULL; + if (par) par->getSourceFile()->addFunc( this ); + // symbol_table = NULL; //use body's instead + typedef_table = NULL; + body = new chillAST_CompoundStmt(); + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_FunctionDecl::chillAST_FunctionDecl(const char *rt, const char *fname, chillAST_node *par, void *unique) { + fprintf(stderr, "chillAST_FunctionDecl::chillAST_FunctionDecl with unique %p\n", unique); + returnType = strdup(rt); + functionName = strdup(fname); + this->setFunctionCPU(); + //fprintf(stderr, "functionName %s\n", functionName); + forwarddecl = externfunc = builtin = false; + + body = new chillAST_CompoundStmt(); + asttype = CHILLAST_NODETYPE_FUNCTIONDECL; + uniquePtr = unique; // a quick way to check equivalence. DO NOT ACCESS THROUGH THIS + parent = par; + metacomment = NULL; + if (par) par->getSourceFile()->addFunc( this ); + //symbol_table = NULL; // use body's + typedef_table = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + +void chillAST_FunctionDecl::addParameter( chillAST_VarDecl *p) { + fprintf(stderr, "%s chillAST_FunctionDecl::addParameter( 0x%x param %s) total of %d parameters\n", functionName, p, p->varname, 1+parameters.size()); + + if (symbolTableHasVariableNamed( ¶meters, p->varname)) { // NOT recursive. just in FunctionDecl + fprintf(stderr, "chillAST_FunctionDecl::addParameter( %s ), parameter already exists?\n", p->varname); + // exit(-1); // ?? + return; // error? + } + + parameters.push_back(p); + //addSymbolToTable( parameters, p ); + fprintf(stderr, "setting %s isAParameter\n", p->varname); + p->isAParameter = true; + + p->setParent( this ); // ?? unclear TODO + //p->dump(); printf("\naddparameter done\n\n"); fflush(stdout); +} + + + +void chillAST_FunctionDecl::addDecl( chillAST_VarDecl *vd) { // to symbol table ONLY + fprintf(stderr, "chillAST_FunctionDecl::addDecl( %s )\n", vd->varname); + if (!body) { + //fprintf(stderr, "had no body\n"); + body = new chillAST_CompoundStmt(); + + //body->symbol_table = symbol_table; // probably wrong if this ever does something + } + + //fprintf(stderr, "before body->addvar(), func symbol table had %d entries\n", symbol_table->size()); + //fprintf(stderr, "before body->addvar(), body symbol table was %p\n", body->symbol_table); + //fprintf(stderr, "before body->addvar(), body symbol table had %d entries\n", body->symbol_table->size()); + //adds to body symbol table, and makes sure function has a copy. probably dumb + body->symbol_table = body->addVariableToSymbolTable( vd ); + //fprintf(stderr, "after body->addvar(), func symbol table had %d entries\n", symbol_table->size()); +} + +chillAST_VarDecl *chillAST_FunctionDecl::hasParameterNamed( const char *name ) { + int numparams = parameters.size(); + for (int i=0; i<numparams; i++) { + if (!strcmp(name, parameters[i]->varname)) return parameters[i]; // need to check type? + } + return NULL; +} + + +// similar to symbolTableHasVariableNamed() but returns the variable definition +chillAST_VarDecl *chillAST_FunctionDecl::funcHasVariableNamed( const char *name ) { // NOT recursive + //fprintf(stderr, "chillAST_FunctionDecl::funcHasVariableNamed( %s )\n", name ); + + // first check the parameters + int numparams = parameters.size(); + for (int i=0; i<numparams; i++) { + chillAST_VarDecl *vd = parameters[i]; + if (!strcmp(name, vd->varname)) { + //fprintf(stderr, "yep, it's parameter %d\n", i); + return vd; // need to check type? + } + } + //fprintf(stderr, "no parameter named %s\n", name); + + chillAST_SymbolTable *st = getSymbolTable(); + if (!st) { + fprintf(stderr,"and no symbol_table, so no variable named %s\n", name); + return NULL; // no symbol table so no variable by that name + } + + + int numvars = st->size(); + //fprintf(stderr, "checking against %d variables\n", numvars); + for (int i=0; i<numvars; i++) { + chillAST_VarDecl *vd = (*st)[i]; + //fprintf(stderr, "comparing '%s' to '%s'\n", name, vd->varname); + if (!strcmp(name, vd->varname)) { + //fprintf(stderr, "yep, it's variable %d\n", i); + fprintf(stderr, "%s was already defined in the function body\n", vd->varname); + return vd; // need to check type? + } + } + fprintf(stderr, "not a parameter or variable named %s\n", name); + return NULL; +} + + + + +void chillAST_FunctionDecl::setBody( chillAST_node * bod ) { + //fprintf(stderr, "%s chillAST_FunctionDecl::setBody( 0x%x ) total of %d children\n", functionName, bod, 1+children.size()); + if (bod->isCompoundStmt()) body = (chillAST_CompoundStmt *)bod; + else { + body = new chillAST_CompoundStmt(); + body->addChild( bod ); + } + //symbol_table = body->getSymbolTable(); + //addChild(bod); + bod->setParent( this ); // well, ... +} + + +void chillAST_FunctionDecl::insertChild(int i, chillAST_node* node) { + fprintf(stderr, "chillAST_FunctionDecl::insertChild() "); node->print(0,stderr); fprintf(stderr, "\n\n"); + body->insertChild( i, node ); + + if (node->isVarDecl()) { + chillAST_VarDecl *vd = ((chillAST_VarDecl *) node); + fprintf(stderr, "functiondecl %s inserting a VarDecl named %s\n", functionName, vd->varname); + chillAST_SymbolTable *st = getSymbolTable(); + if (!st) { + fprintf(stderr, "symbol table is NULL!\n"); + } + else { + fprintf(stderr, "%d entries in the symbol table\n", st->size()); + printSymbolTable( getSymbolTable() ); + } + fprintf(stderr, "\n\n"); + } +} + +void chillAST_FunctionDecl::addChild(chillAST_node* node) { + fprintf(stderr, "chillAST_FunctionDecl::addChild( ) "); node->print(0,stderr); fprintf(stderr, "\n\n"); + if (node->isVarDecl()) { + chillAST_VarDecl *vd = ((chillAST_VarDecl *) node); + fprintf(stderr, "functiondecl %s adding a VarDecl named %s\n", functionName, vd->varname); + } + + body->addChild( node ); + node->parent = this; // this, or body?? +} + + +void chillAST_FunctionDecl::printParameterTypes( FILE *fp ) { // also prints names + //fprintf(stderr, "\n\n%s chillAST_FunctionDecl::printParameterTypes()\n", functionName); + fprintf(fp, "( "); + int numparameters = parameters.size(); + for (int i=0; i<numparameters; i++) { + if (i!=0) fprintf(fp, ", "); + chillAST_VarDecl *p = parameters[i]; + p->print(0, fp); // note: no indent, as this is in the function parens + } + fprintf(fp, " )"); // end of input parameters + +} + + + + +void chillAST_FunctionDecl::print( int indent, FILE *fp ) { + //fprintf(fp, "\n// functiondecl %p \n", this); + //chillindent(indent, fp); + //fprintf(fp, "//(functiondecl) %d parameters\n", numparameters); + + printPreprocBEFORE(indent, fp); + + fprintf(fp, "\n"); + chillindent(indent, fp); + + if (externfunc) fprintf(fp, "extern "); + + if (function_type == CHILL_FUNCTION_GPU) fprintf(fp, "__global__ "); + fprintf(fp, "%s %s", returnType, functionName ); + printParameterTypes(fp); + + + + // non-parameter variables (now must have explicit vardecl in the body) + //int numvars = symbol_table.size(); + //for (int i=0; i<numvars; i++) { + // symbol_table[i]->print(1,fp); + // fprintf(fp, ";\n"); + //} + + // now the body + if (!(externfunc || forwarddecl)) { + if (body) { + fprintf(fp, "\n{\n"); + //chillindent(indent+1, fp); fprintf(fp, "//body\n"); fflush(fp); + body->print( indent+1, fp); + fprintf(fp, "\n"); + //chillindent(indent+1, fp); fprintf(fp, "//END body\n"); fflush(fp); + + // tidy up + chillindent(indent, fp); + fprintf(fp, "}\n"); + } // if body + else { + fprintf(fp, "{}\n"); // should never happen, but not external and no body + } + } + else { // extern func or forward decl. just end forward declaration + fprintf(fp, "; // fwd decl\n"); + } + + printPreprocAFTER(indent, fp); + + fflush(fp); +} + + + +void chillAST_FunctionDecl::dump( int indent, FILE *fp ) { + fprintf(fp, "\n"); + fprintf(fp, "// isFromSourceFile "); + if (filename) fprintf(fp, "%s ", filename); + if (isFromSourceFile) fprintf(fp, "true\n"); + else fprintf(fp, "false\n"); + chillindent(indent, fp); + fprintf(fp, "(FunctionDecl %s %s(", returnType, functionName ); + + int numparameters = parameters.size(); + for (int i=0; i<numparameters; i++) { + if (i!=0) fprintf(fp, ", "); + chillAST_VarDecl *p = parameters[i]; + //fprintf(stderr, "param type %s vartype %s\n", p->getTypeString(), p->vartype); + p->print(0, fp); // note: no indent, as this is in the function parens, ALSO print, not dump + } + fprintf(fp, ")\n"); // end of input parameters + + // now the body - + if (body) body->dump( indent+1 , fp); + + // tidy up + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +} + + + + + + +void chillAST_FunctionDecl::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_FunctionDecl::gatherVarDecls()\n"); + //if (0 < children.size()) fprintf(stderr, "functiondecl has %d children\n", children.size()); + //fprintf(stderr, "functiondecl has %d parameters\n", numParameters()); + for (int i=0; i<numParameters(); i++) parameters[i]->gatherVarDecls( decls ); + //fprintf(stderr, "after parms, %d decls\n", decls.size()); + for (int i=0; i<children.size(); i++) children[i]->gatherVarDecls( decls ); + //fprintf(stderr, "after children, %d decls\n", decls.size()); + body->gatherVarDecls( decls ); // todo, figure out if functiondecl has actual children + //fprintf(stderr, "after body, %d decls\n", decls.size()); + //for (int d=0; d<decls.size(); d++) { + // decls[d]->print(0,stderr); fprintf(stderr, "\n"); + //} +} + + +void chillAST_FunctionDecl::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + //if (0 < children.size()) fprintf(stderr, "functiondecl has %d children\n", children.size()); + + for (int i=0; i<numParameters(); i++) parameters[i]->gatherScalarVarDecls( decls ); + for (int i=0; i<children.size(); i++) children[i]->gatherScalarVarDecls( decls ); + body->gatherScalarVarDecls( decls ); // todo, figure out if functiondecl has actual children +} + + +void chillAST_FunctionDecl::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + //if (0 < children.size()) fprintf(stderr, "functiondecl has %d children\n", children.size()); + + for (int i=0; i<numParameters(); i++) parameters[i]->gatherArrayVarDecls( decls ); + for (int i=0; i<children.size(); i++) children[i]->gatherArrayVarDecls( decls ); + body->gatherArrayVarDecls( decls ); // todo, figure out if functiondecl has actual children +} + + +chillAST_VarDecl *chillAST_FunctionDecl::findArrayDecl( const char *name ) { + //fprintf(stderr, "chillAST_FunctionDecl::findArrayDecl( %s )\n", name ); + chillAST_VarDecl *p = hasParameterNamed( name ); + //if (p) fprintf(stderr, "function %s has parameter named %s\n", functionName, name ); + if (p && p->isArray()) return p; + + chillAST_VarDecl *v = funcHasVariableNamed ( name ); + //if (v) fprintf(stderr, "function %s has symbol table variable named %s\n", functionName, name ); + if (v && v->isArray()) return v; + + // declared variables that may not be in symbol table but probably should be + vector<chillAST_VarDecl*> decls ; + gatherArrayVarDecls( decls ); + for (int i=0; i<decls.size(); i++) { + chillAST_VarDecl *vd = decls[i]; + if (0 == strcmp(vd->varname, name ) && vd->isArray()) return vd; + } + + //fprintf(stderr, "can't find array named %s in function %s \n", name, functionName); + return NULL; +} + + +void chillAST_FunctionDecl::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + for (int i=0; i<children.size(); i++) children[i]->gatherVarUsage( decls ); + body->gatherVarUsage( decls ); // todo, figure out if functiondecl has actual children +} + + +void chillAST_FunctionDecl::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + for (int i=0; i<children.size(); i++) children[i]->gatherDeclRefExprs( refs ); + body->gatherDeclRefExprs( refs ); // todo, figure out if functiondecl has actual children +} + + + +void chillAST_FunctionDecl::cleanUpVarDecls() { + //fprintf(stderr, "\ncleanUpVarDecls() for function %s\n", functionName); + vector<chillAST_VarDecl*> used; + vector<chillAST_VarDecl*> defined; + vector<chillAST_VarDecl*> deletethese; + + gatherVarUsage( used ); + gatherVarDecls( defined ); + + //fprintf(stderr, "\nvars used: \n"); + //for ( int i=0; i< used.size(); i++) { + //used[i]->print(0, stderr); fprintf(stderr, "\n"); + //} + //fprintf(stderr, "\n"); + //fprintf(stderr, "\nvars defined: \n"); + //for ( int i=0; i< defined.size(); i++) { + // defined[i]->print(0, stderr); fprintf(stderr, "\n"); + //} + //fprintf(stderr, "\n"); + + for ( int j=0; j < defined.size(); j++) { + //fprintf(stderr, "j %d defined %s\n", j, defined[j]->varname); + bool definedandused = false; + for ( int i=0; i < used.size(); i++) { + if (used[i] == defined[j]) { + //fprintf(stderr, "i %d used %s\n", i, used[i]->varname); + //fprintf(stderr, "\n"); + definedandused = true; + break; + } + } + + if (!definedandused) { + if ( defined[j]->isParmVarDecl() ) { + //fprintf(stderr, "we'd remove %s except that it's a parameter. Maybe someday\n", defined[j]->varname); + } + else { + //fprintf(stderr, "we can probably remove the definition of %s\n", defined[j]->varname); + deletethese.push_back( defined[j] ); + } + } + } + + + //fprintf(stderr, "deleting %d vardecls\n", deletethese.size()); + for (int i=0; i<deletethese.size(); i++) { + //fprintf(stderr, "deleting varDecl %s\n", deletethese[i]->varname); + chillAST_node *par = deletethese[i]->parent; + par->removeChild( par->findChild( deletethese[i] )); + } + + + //fprintf(stderr, "\n\nnow check for vars used but not defined\n"); + // now check for vars used but not defined? + for ( int j=0; j < used.size(); j++) { + //fprintf(stderr, "%s is used\n", used[j]->varname); + bool definedandused = false; + for ( int i=0; i < defined.size(); i++) { + if (used[j] == defined[i]) { + //fprintf(stderr, "%s is defined\n", defined[i]->varname); + definedandused = true; + break; + } + } + if (!definedandused) { + //fprintf(stderr, "%s is used but not defined?\n", used[j]->varname); + // add it to the beginning of the function + insertChild(0, used[j]); + } + } + +} + +//void chillAST_FunctionDecl::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl ) { +// for (int i=0; i<children.size(); i++) children[i]->replaceVarDecls( olddecl, newdecl ); +//} + + +bool chillAST_FunctionDecl::findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync ) { + if (body) body->findLoopIndexesToReplace( symtab, false ); + return false; +} + + + + chillAST_node *chillAST_FunctionDecl::constantFold() { + //fprintf(stderr, "chillAST_FunctionDecl::constantFold()\n"); + // parameters can't have constants? + int numparameters = parameters.size(); + for (int i=0; i<numparameters; i++) { + parameters[i]->constantFold(); + } + if (body) body = (chillAST_CompoundStmt *)body->constantFold(); + return this; + } + + +chillAST_MacroDefinition::chillAST_MacroDefinition() { + macroName = strdup("UNDEFINEDMACRO"); + rhsString = NULL; + asttype = CHILLAST_NODETYPE_MACRODEFINITION; + parent = NULL; + metacomment = NULL; + symbol_table = NULL; + //rhsideString = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_MacroDefinition::chillAST_MacroDefinition(const char *mname, chillAST_node *par) { + macroName = strdup(mname); + rhsString = NULL; + asttype = CHILLAST_NODETYPE_MACRODEFINITION; + parent = par; + metacomment = NULL; + symbol_table = NULL; + //rhsideString = NULL; + + if (par) par->getSourceFile()->addMacro( this ); + + //fprintf(stderr, "chillAST_MacroDefinition::chillAST_MacroDefinition( %s, ", mname); + //if (par) fprintf(stderr, " parent NOT NULL);\n"); + //else fprintf(stderr, " parent NULL);\n"); + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_MacroDefinition::chillAST_MacroDefinition(const char *mname, const char *rhs, chillAST_node *par) { + macroName = strdup(mname); + rhsString = strdup(rhs); + asttype = CHILLAST_NODETYPE_MACRODEFINITION; + parent = par; + metacomment = NULL; + symbol_table = NULL; + + if (par) par->getSourceFile()->addMacro( this ); + + //fprintf(stderr, "chillAST_MacroDefinition::chillAST_MacroDefinition( %s, ", mname); + //if (par) fprintf(stderr, " parent NOT NULL);\n"); + //else fprintf(stderr, " parent NULL);\n"); + isFromSourceFile = true; // default + filename = NULL; +}; + + +chillAST_node* chillAST_MacroDefinition::clone() { + + // TODO ?? cloning a macro makes no sense + return this; +#ifdef CONFUSED + + //fprintf(stderr, "chillAST_MacroDefinition::clone() for %s\n", macroName); + chillAST_MacroDefinition *clo = new chillAST_MacroDefinition( macroName, parent); + for (int i=0; i<parameters.size(); i++) clo->addParameter( parameters[i] ); + clo->setBody( body->clone() ); + return clo; +#endif + +} + + +void chillAST_MacroDefinition::setBody( chillAST_node * bod ) { + fprintf(stderr, "%s chillAST_MacroDefinition::setBody( 0x%x )\n", macroName, bod); + body = bod; + fprintf(stderr, "body is:\n"); body->print(0,stderr); fprintf(stderr, "\n\n"); + rhsString = body->stringRep(); + bod->setParent( this ); // well, ... +} + + +void chillAST_MacroDefinition::addParameter( chillAST_VarDecl *p) { + //fprintf(stderr, "%s chillAST_MacroDefinition::addParameter( 0x%x ) total of %d children\n", functionName, p, 1+children.size()); + parameters.push_back(p); + fprintf(stderr, "macro setting %s isAParameter\n", p->varname); + p->isAParameter = true; + p->setParent( this ); + + addVariableToSymbolTable( p ); +} + + +chillAST_VarDecl *chillAST_MacroDefinition::hasParameterNamed( const char *name ) { + int numparams = parameters.size(); + for (int i=0; i<numparams; i++) { + if (!strcmp(name, parameters[i]->varname)) return parameters[i]; // need to check type? + } + return NULL; +} + + +void chillAST_MacroDefinition::insertChild(int i, chillAST_node* node) { + body->insertChild( i, node ); +} + +void chillAST_MacroDefinition::addChild(chillAST_node* node) { + body->addChild( node ); + node->parent = this; // this, or body?? +} + + +void chillAST_MacroDefinition::dump( int indent, FILE *fp ) { + fprintf(fp, "\n"); + chillindent(indent, fp); + fprintf(fp, "(MacroDefinition %s(", macroName); + for (int i=0; i<numParameters(); i++) { + fprintf(fp, "\n"); + chillindent(indent+1, fp); + fprintf(fp, "(%s)", parameters[i]->varname); + } + fprintf(fp, ")\n"); + body->dump( indent+1, fp); + if (rhsString) fprintf(fp, " (aka %s)"); + fprintf(fp, "\n"); + fflush(fp); +} + + +void chillAST_MacroDefinition::print( int indent, FILE *fp ) { // UHOH TODO + //fprintf(fp, "\n"); // ignore indentation + //fprintf(stderr, "macro has %d parameters\n", numParameters()); + + printPreprocBEFORE(indent, fp); + + fprintf(fp, "#define %s", macroName); + if (0 != numParameters()) { + fprintf(fp, "("); + for (int i=0; i<numParameters(); i++) { + if (i) fprintf(fp, ","); + fprintf(fp, "%s", parameters[i]->varname); + } + fprintf(fp, ") "); + } + + if (body) body->print(0, fp); // TODO should force newlines out of multiline macros + fprintf(fp, "\n"); +} + + + + +chillAST_ForStmt::chillAST_ForStmt() { + init = cond = incr = NULL; + body = new chillAST_CompoundStmt(); + + asttype = CHILLAST_NODETYPE_LOOP; // breaking with tradition, this was CHILL_AST_FORSTMT + conditionoperator = IR_COND_UNKNOWN; + parent = NULL; + metacomment = NULL; + symbol_table = NULL; + isFromSourceFile = true; // default + filename = NULL; +} + + +chillAST_ForStmt::chillAST_ForStmt( chillAST_node *ini, chillAST_node *con, chillAST_node *inc, chillAST_node *bod, chillAST_node *par) { + parent = par; + metacomment = NULL; + init = ini; + cond = con; + incr = inc; + body = bod; + init->setParent( this ); + cond->setParent( this ); + incr->setParent( this ); + + //fprintf(stderr, "chillAST_ForStmt::chillAST_ForStmt() bod %p\n", bod); + + if (body) body->setParent( this ); // not sure this should be legal + + asttype = CHILLAST_NODETYPE_LOOP; // breaking with tradition, this was CHILL_AST_FORSTMT + + if (!cond->isBinaryOperator()) { + fprintf(stderr, "ForStmt conditional is of type %s. Expecting a BinaryOperator\n", cond->getTypeString()); + exit(-1); + } + chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)cond; + char *condstring = bo->op; + if (!strcmp(condstring, "<")) conditionoperator = IR_COND_LT; + else if (!strcmp(condstring, "<=")) conditionoperator = IR_COND_LE; + else if (!strcmp(condstring, ">")) conditionoperator = IR_COND_GT; + else if (!strcmp(condstring, ">=")) conditionoperator = IR_COND_GE; + else { + fprintf(stderr, "ForStmt, illegal/unhandled end condition \"%s\"\n", condstring); + fprintf(stderr, "currently can only handle <, >, <=, >=\n"); + exit(1); + } + isFromSourceFile = true; // default + filename = NULL; +} + + +bool chillAST_ForStmt::lowerBound( int &l ) { // l is an output (passed as reference) + + // above, cond must be a binaryoperator ... ??? + if (conditionoperator == IR_COND_LT || + conditionoperator == IR_COND_LE ) { + + // lower bound is rhs of init + if (!init->isBinaryOperator()) { + fprintf(stderr, "chillAST_ForStmt::lowerBound() init is not a chillAST_BinaryOperator\n"); + exit(-1); + } + + chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)init; + if (!init->isAssignmentOp()) { + fprintf(stderr, "chillAST_ForStmt::lowerBound() init is not an assignment chillAST_BinaryOperator\n"); + exit(-1); + } + + //fprintf(stderr, "rhs "); bo->rhs->print(0,stderr); fprintf(stderr, " "); + l = bo->rhs->evalAsInt(); // float could be legal I suppose + //fprintf(stderr, " %d\n", l); + return true; + } + else if (conditionoperator == IR_COND_GT || + conditionoperator == IR_COND_GE ) { // decrementing + // lower bound is rhs of cond (not init) + chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)cond; + l = bo->rhs->evalAsInt(); // float could be legal I suppose + return true; + } + + // some case we don't handle ?? + fprintf(stderr, "chillAST_ForStmt::lowerBound() can't find lower bound of "); + print(0,stderr); + fprintf(stderr, "\n\n"); + return false; // or exit ??? +} + + +bool chillAST_ForStmt::upperBound( int &u ) { // u is an output (passed as reference) + + // above, cond must be a binaryoperator ... ??? + if (conditionoperator == IR_COND_GT || + conditionoperator == IR_COND_GE ) { // decrementing + + // upper bound is rhs of init + if (!init->isBinaryOperator()) { + fprintf(stderr, "chillAST_ForStmt::upperBound() init is not a chillAST_BinaryOperator\n"); + exit(-1); + } + + chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)init; + if (!init->isAssignmentOp()) { + fprintf(stderr, "chillAST_ForStmt::upperBound() init is not an assignment chillAST_BinaryOperator\n"); + exit(-1); + } + + u = bo->rhs->evalAsInt(); // float could be legal I suppose + return true; + } + else if (conditionoperator == IR_COND_LT || + conditionoperator == IR_COND_LE ) { + //fprintf(stderr, "upper bound is rhs of cond "); + // upper bound is rhs of cond (not init) + chillAST_BinaryOperator *bo = (chillAST_BinaryOperator *)cond; + //bo->rhs->print(0,stderr); + u = bo->rhs->evalAsInt(); // float could be legal I suppose + + if (conditionoperator == IR_COND_LT) u -= 1; + + //fprintf(stderr, " %d\n", u); + return true; + } + + // some case we don't handle ?? + fprintf(stderr, "chillAST_ForStmt::upperBound() can't find upper bound of "); + print(0,stderr); + fprintf(stderr, "\n\n"); + return false; // or exit ??? +} + + + + +void chillAST_ForStmt::printControl( int in, FILE *fp ) { + chillindent(in, fp); + fprintf(fp, "for ("); + init->print(0, fp); + fprintf(fp, "; "); + cond->print(0, fp); + fprintf(fp, "; "); + incr->print(0, fp); + fprintf(fp, ")"); + fflush(fp); +} + + +void chillAST_ForStmt::print( int indent, FILE *fp ) { + printPreprocBEFORE(indent, fp); + //fprintf(fp, "chillAST_ForStmt::print()\n"); + if (metacomment) { + chillindent(indent, fp); + //for(int i=0; i<indent; i++) fprintf(fp, ".."); + fprintf(fp, "// %s\n", metacomment); + } + + printControl(indent, fp); // does not do a newline or bracket + fprintf(fp, " {\n"); + + + // I have no idea what made me do this next bit. + // A forstmt with compounds inside compounds ??? + // this should probably all go away + + chillAST_node *b = body; + //fprintf(fp, "b children %d\n", b->getNumChildren()); + //fprintf(fp, "body child 0 of type %s\n", b->children[0]->getTypeString()); + //fprintf(stderr, "forstmt body type %s\n", Chill_AST_Node_Names[b->asttype] ); + // deal with a tree of compound statements, in an ugly way. leave the ugliness + while (1 == b->getNumChildren() && b->children[0]->isCompoundStmt()) { + b = b->children[0]; + } + + + // this was to sometimes not enclose in a bracket. stupid. always enclose in a bracket. + //if (1 == b->getNumChildren() && b->children[0]->isForStmt()) fprintf(fp, ") {\n" ); + //else if (1 == b->getNumChildren() ) fprintf(fp, ") { ?? \n" ); // to allow for() for( ) to not have open bracket? + //else { + //fprintf(fp, ")\n"); + //chillindent(in, fp); + //fprintf(fp, "{\n" ); + + //fprintf(fp, ")"); + //} + + b->print(indent+1, fp ); + + // I think this can't happen any more. body is always a compound statement + if (b->asttype == CHILLAST_NODETYPE_BINARYOPERATOR) { // a single assignment statement + fprintf(fp, ";\n"); + } + + // always print brackets + + //if ((1 == b->getNumChildren() && b->children[0]->isForStmt()) || + // (1 != b->getNumChildren() )) { + chillindent(indent, fp); + fprintf(fp, "}\n" ); + //} + + printPreprocAFTER(indent, fp); + fflush(fp); // +} + +void chillAST_ForStmt::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(ForStmt \n"); + + init->dump(indent+1, fp); + cond->dump(indent+1, fp); + incr->dump(indent+1, fp); + body->dump(indent+1, fp); + + chillindent(indent, fp); + fprintf(fp, ")\n"); +} + +chillAST_node *chillAST_ForStmt::constantFold() { + init = init->constantFold(); + cond = cond->constantFold(); + incr = incr->constantFold(); + body = body->constantFold(); + return this; + } + + + chillAST_node *chillAST_ForStmt::clone() { + chillAST_ForStmt *fs = new chillAST_ForStmt( init->clone(), cond->clone(), incr->clone(), body->clone(), parent); + fs->isFromSourceFile = isFromSourceFile; + if (filename) fs->filename = strdup(filename); + return fs; + } + +void chillAST_ForStmt::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_ForStmt::gatherVarDecls()\n"); + //fprintf(stderr, "chillAST_ForStmt::gatherVarDecls() before %d\n", decls.size()); + // TODO clear a loop_var_decls variable and then walk it ? + init->gatherVarDecls( decls ); + cond->gatherVarDecls( decls ); + incr->gatherVarDecls( decls ); + body->gatherVarDecls( decls ); + //fprintf(stderr, "after %d\n", decls.size()); +} + +void chillAST_ForStmt::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_ForStmt::gatherScalarVarDecls() before %d\n", decls.size()); + init->gatherScalarVarDecls( decls ); + cond->gatherScalarVarDecls( decls ); + incr->gatherScalarVarDecls( decls ); + body->gatherScalarVarDecls( decls ); +} + +void chillAST_ForStmt::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_ForStmt::gatherArrayVarDecls() before %d\n", decls.size()); + init->gatherArrayVarDecls( decls ); + cond->gatherArrayVarDecls( decls ); + incr->gatherArrayVarDecls( decls ); + body->gatherArrayVarDecls( decls ); +} + +void chillAST_ForStmt::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ) { + init->gatherArrayRefs( refs, 0 ); // 0 ?? + cond->gatherArrayRefs( refs, 0 ); // 0 ?? + incr->gatherArrayRefs( refs, 0 ); // 0 ?? + body->gatherArrayRefs( refs, 0 ); // 0 ?? +} + +void chillAST_ForStmt::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + init->gatherScalarRefs( refs, 0 ); // 0 ?? + cond->gatherScalarRefs( refs, 0 ); // 0 ?? + incr->gatherScalarRefs( refs, 0 ); // 0 ?? + body->gatherScalarRefs( refs, 0 ); // 0 ?? +} + +void chillAST_ForStmt::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + init->gatherDeclRefExprs( refs ); + cond->gatherDeclRefExprs( refs ); + incr->gatherDeclRefExprs( refs ); + body->gatherDeclRefExprs( refs ); +} + + + +void chillAST_ForStmt::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + init->gatherVarUsage( decls ); + cond->gatherVarUsage( decls ); + incr->gatherVarUsage( decls ); + body->gatherVarUsage( decls ); +} + +void chillAST_ForStmt::gatherStatements(std::vector<chillAST_node*> &statements ){ + + // for completeness, should do all 4. Maybe someday + //init->gatherStatements( statements ); + //cond->gatherStatements( statements ); + //incr->gatherStatements( statements ); + body->gatherStatements( statements ); +} + + + +void chillAST_ForStmt::addSyncs() { + //fprintf(stderr, "\nchillAST_ForStmt::addSyncs() "); + //fprintf(stderr, "for ("); + //init->print(0, stderr); + //fprintf(stderr, "; "); + //cond->print(0, stderr); + //fprintf(stderr, "; "); + //incr->print(0, stderr); + //fprintf(stderr, ")\n"); + + if (!parent) { + fprintf(stderr, "uhoh, chillAST_ForStmt::addSyncs() ForStmt has no parent!\n"); + fprintf(stderr, "for ("); + init->print(0, stderr); + fprintf(stderr, "; "); + cond->print(0, stderr); + fprintf(stderr, "; "); + incr->print(0, stderr); + fprintf(stderr, ")\n"); + + return; // exit? + } + + if (parent->isCompoundStmt()) { + //fprintf(stderr, "ForStmt parent is CompoundStmt 0x%x\n", parent); + vector<chillAST_node*> chillin = parent->getChildren(); + int numc = chillin.size(); + //fprintf(stderr, "ForStmt parent is CompoundStmt 0x%x with %d children\n", parent, numc); + for (int i=0; i<numc; i++) { + if (this == parent->getChild(i)) { + //fprintf(stderr, "forstmt 0x%x is child %d of %d\n", this, i, numc); + chillAST_CudaSyncthreads *ST = new chillAST_CudaSyncthreads(); + parent->insertChild(i+1, ST); // corrupts something ... + //fprintf(stderr, "Create a call to __syncthreads() 2\n"); + //parent->addChild(ST); // wrong, but safer still kills + } + } + + chillin = parent->getChildren(); + int nowc = chillin.size(); + //fprintf(stderr, "old, new number of children = %d %d\n", numc, nowc); + + } + else { + fprintf(stderr, "chillAST_ForStmt::addSyncs() unhandled parent type %s\n", parent->getTypeString()); + exit(-1); + } + + //fprintf(stderr, "leaving addSyncs()\n"); +} + + + + +void chillAST_ForStmt::removeSyncComment() { + //fprintf(stderr, "chillAST_ForStmt::removeSyncComment()\n"); + if (metacomment && strstr(metacomment, "~cuda~") && strstr(metacomment, "preferredIdx: ")) { + char *ptr = strlen( "preferredIdx: " ) + strstr(metacomment, "preferredIdx: "); + *ptr = '\0'; + } +} + + +bool chillAST_ForStmt::findLoopIndexesToReplace(chillAST_SymbolTable *symtab, bool forcesync ) { + fprintf(stderr, "\nchillAST_ForStmt::findLoopIndexesToReplace( force = %d )\n", forcesync); + //if (metacomment) fprintf(stderr, "metacomment '%s'\n", metacomment); + + bool force = forcesync; + bool didasync = false; + if (forcesync) { + //fprintf(stderr, "calling addSyncs() because PREVIOUS ForStmt in a block had preferredIdx\n"); + addSyncs(); + didasync = true; + } + + //fprintf(stderr, "chillAST_ForStmt::findLoopIndexesToReplace()\n"); + if (metacomment && strstr(metacomment, "~cuda~") && strstr(metacomment, "preferredIdx: ")) { + //fprintf(stderr, "metacomment '%s'\n", metacomment); + + char *copy = strdup(metacomment); + char *ptr = strstr(copy, "preferredIdx: "); + char *vname = ptr + strlen( "preferredIdx: " ); + char *space = strstr(vname, " "); // TODO index() + if (space) { + //fprintf(stderr, "vname = '%s'\n", vname); + force = true; + } + + if ((!didasync) && force ) { + //fprintf(stderr, "calling addSyncs() because ForStmt metacomment had preferredIdx '%s'\n", vname); + addSyncs(); + removeSyncComment(); + didasync = true; + } + + if (space) *space = '\0'; // if this is multiple words, grab the first one + //fprintf(stderr, "vname = '%s'\n", vname); + + //fprintf(stderr, "\nfor ("); + //init->print(0, stderr); + //fprintf(stderr, "; "); + //cond->print(0, stderr); + //fprintf(stderr, "; "); + //incr->print(0, stderr); + //fprintf(stderr, ") %s\n", metacomment ); + //fprintf(stderr, "prefer '%s'\n", vname ); + + vector<chillAST_VarDecl*> decls; + init->gatherVarLHSUsage( decls ); + //cond->gatherVarUsage( decls ); + //incr->gatherVarUsage( decls ); + //fprintf(stderr, "forstmt has %d vardecls in init, cond, inc\n", decls.size()); + + if ( 1 != decls.size()) { + fprintf(stderr, "uhoh, preferred index in for statement, but multiple variables used\n"); + print(0,stderr); + fprintf(stderr, "\nvariables are:\n"); + for (int i=0; i<decls.size(); i++) { + decls[i]->print(0,stderr); fprintf(stderr, "\n"); + } + exit(0); + } + chillAST_VarDecl* olddecl = decls[0]; + + // RIGHT NOW, change all the references that this loop wants swapped out + // find vardecl for named preferred index. it has to already exist + fprintf(stderr, "RIGHT NOW, change all the references that this loop wants swapped out \n"); + + chillAST_VarDecl *newguy = findVariableNamed( vname ); // recursive + if (!newguy) { + fprintf(stderr, "there was no variable named %s anywhere I could find\n", vname); + } + + // wrong - this only looks at variables defined in the forstmt, not + // in parents of the forstmt + //int numsym = symtab->size(); + //fprintf(stderr, "%d symbols\n", numsym); + //for (int i=0; i<numsym; i++) { + // fprintf(stderr, "sym %d is '%s'\n", i, (*symtab)[i]->varname); + // if (!strcmp(vname, (*symtab)[i]->varname)) { + // newguy = (*symtab)[i]; + // } + //} + if (!newguy) { + fprintf(stderr, "chillAST_ForStmt::findLoopIndexesToReplace() there is no defined variable %s\n", vname); + + // make one ?? seems like this should never happen + newguy = new chillAST_VarDecl( olddecl->vartype, vname, ""/*?*/, NULL ); + // insert actual declaration in code location? how? + + // find parent of the ForStmt? + // find parent^n of the ForStmt that is not a Forstmt? + // find parent^n of the Forstmt that is a FunctionDecl? + chillAST_node *contain = findContainingNonLoop(); + if (contain == NULL) { + fprintf(stderr, "nothing but loops all the way up?\n"); + exit(0); + } + fprintf(stderr, "containing non-loop is a %s\n", contain->getTypeString()); + + contain->print(0,stderr); + contain->insertChild( 0, newguy ); // ugly order TODO + contain->addVariableToSymbolTable( newguy ); // adds to first enclosing symbolTable + + if (! symbolTableHasVariableNamed( contain->getSymbolTable(), vname )) { + fprintf(stderr, "container doesn't have a var names %s afterwards???\n", vname); + exit(-1); + } + } + + + // swap out old for new in init, cond, incr, body + if (newguy) { + fprintf(stderr, "\nwill replace %s with %s in init, cond, incr\n", olddecl->varname, newguy->varname); + fprintf(stderr, "was: for ("); + init->print(0, stderr); + fprintf(stderr, "; "); + cond->print(0, stderr); + fprintf(stderr, "; "); + incr->print(0, stderr); + fprintf(stderr, ")\n"); + + + init->replaceVarDecls( olddecl, newguy ); + cond->replaceVarDecls( olddecl, newguy ); + incr->replaceVarDecls( olddecl, newguy ); + + fprintf(stderr, " is: for ("); + init->print(0, stderr); + fprintf(stderr, "; "); + cond->print(0, stderr); + fprintf(stderr, "; "); + incr->print(0, stderr); + fprintf(stderr, ")\n\n"); + + fprintf(stderr,"recursing to ForStmt body of type %s\n", body->getTypeString()); + body->replaceVarDecls( olddecl, newguy ); + + fprintf(stderr, "\nafter recursing to body, this loop is (there should be no %s)\n", olddecl->varname); + print(0, stderr); fprintf(stderr, "\n"); + + } + + //if (!space) // there was only one preferred + //fprintf(stderr, "removing metacomment\n"); + metacomment = NULL; // memleak + + } + + // check for more loops. We may have already swapped variables out in body (right above here) + body->findLoopIndexesToReplace( symtab, false ) ; + + return force; +} + +void chillAST_ForStmt::replaceChild( chillAST_node *old, chillAST_node *newchild ){ + //fprintf(stderr, "chillAST_ForStmt::replaceChild() REALLY CALLING BODY->ReplaceCHILD\n"); + body->replaceChild( old, newchild ); +} + + + +void chillAST_ForStmt::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + // logic problem if my loop var is olddecl! + + //fprintf(stderr, "chillAST_ForStmt::replaceVarDecls( old %s, new %s )\n", olddecl->varname, newdecl->varname); + + // this is called for inner loops! + init->replaceVarDecls( olddecl, newdecl ); + cond->replaceVarDecls( olddecl, newdecl ); + incr->replaceVarDecls( olddecl, newdecl ); + body->replaceVarDecls( olddecl, newdecl ); +} + + +void chillAST_ForStmt::gatherLoopIndeces( std::vector<chillAST_VarDecl*> &indeces ) { + //fprintf(stderr, "chillAST_ForStmt::gatherLoopIndeces()\nloop is:\n"); print(0,stderr); + + vector<chillAST_VarDecl*> decls; + init->gatherVarLHSUsage( decls ); + cond->gatherVarLHSUsage( decls ); + incr->gatherVarLHSUsage( decls ); + // note: NOT GOING INTO BODY OF THE LOOP + + int numdecls = decls.size(); + //fprintf(stderr, "gatherLoopIndeces(), %d lhs vardecls for this ForStmt\n", numdecls); + + for (int i=0; i<decls.size(); i++) { + //fprintf(stderr, "%s %p\n", decls[i]->varname, decls[i] ); + indeces.push_back( decls[i] ); + } + + // Don't forget to keep heading upwards! + if (parent) { + //fprintf(stderr, "loop %p has parent of type %s\n", this, parent->getTypeString()); + parent->gatherLoopIndeces( indeces ); + } + //else fprintf(stderr, "this loop has no parent???\n"); + +} + + +void chillAST_ForStmt::gatherLoopVars( std::vector<std::string> &loopvars ) { + //fprintf(stderr, "gathering loop vars for loop for ("); + //init->print(0, stderr); + //fprintf(stderr, "; "); + //cond->print(0, stderr); + //fprintf(stderr, "; "); + //incr->print(0, stderr); + //fprintf(stderr, ")\n" ); + + //init->dump(0, stderr); + + + vector<chillAST_VarDecl*> decls; + init->gatherVarLHSUsage( decls ); + cond->gatherVarLHSUsage( decls ); + incr->gatherVarLHSUsage( decls ); + // note: NOT GOING INTO BODY OF THE LOOP + + for (int i=0; i<decls.size(); i++) loopvars.push_back( strdup( decls[i]->varname )); + +} + + +void chillAST_ForStmt::loseLoopWithLoopVar( char *var ) { + + //fprintf(stderr, "\nchillAST_ForStmt::loseLoopWithLoopVar( %s )\n", var ); + + // now recurse (could do first, I suppose) + // if you DON'T do this first, you may have already replaced yourself with this loop body + // the body will no longer have this forstmt as parent, it will have the forstmt's parent as its parent + //fprintf(stderr, "forstmt 0x%x, recursing loseLoop to body 0x%x of type %s with parent 0x%x of type %s\n", this, body, body->getTypeString(), body->parent, body->parent->getTypeString()); + body->loseLoopWithLoopVar( var ) ; + + + + + // if *I* am a loop to be replaced, tell my parent to replace me with my loop body + + std::vector<std::string> loopvars; + gatherLoopVars( loopvars ); + + if (loopvars.size() != 1) { + fprintf(stderr, "uhoh, loop has more than a single loop var and trying to loseLoopWithLoopVar()\n"); + print(0,stderr); + fprintf(stderr, "\nvariables are:\n"); + for (int i=0; i<loopvars.size(); i++) { + fprintf(stderr, "%s\n", loopvars[i].c_str()); + } + + exit(-1); + } + + //fprintf(stderr, "my loop var %s, looking for %s\n", loopvars[0].c_str(), var ); + if (!strcmp(var, loopvars[0].c_str())) { + //fprintf(stderr, "OK, trying to lose myself! for ("); + //init->print(0, stderr); + //fprintf(stderr, "; "); + //cond->print(0, stderr); + //fprintf(stderr, "; "); + //incr->print(0, stderr); + //fprintf(stderr, ")\n" ); + + if (!parent) { + fprintf(stderr, "chillAST_ForStmt::loseLoopWithLoopVar() I have no parent!\n"); + exit(-1); + } + + vector<chillAST_VarDecl*> decls; + init->gatherVarLHSUsage( decls ); // this can fail if init is outside the loop + cond->gatherVarLHSUsage( decls ); + incr->gatherVarLHSUsage( decls ); + if (decls.size() > 1) { + fprintf(stderr, "chill_ast.cc multiple loop variables confuses me\n"); + exit(-1); + } + chillAST_node *newstmt = body; + + // ACTUALLY, if I am being replaced, and my loop conditional is a min (Ternary), then wrap my loop body in an if statement + if (cond->isBinaryOperator()) { // what else could it be? + chillAST_BinaryOperator *BO = (chillAST_BinaryOperator *) cond; + if (BO->rhs->isTernaryOperator()) { + + chillAST_TernaryOperator *TO = (chillAST_TernaryOperator *)BO->rhs; + chillAST_BinaryOperator *C = (chillAST_BinaryOperator *)TO->condition; + + //fprintf(stderr, "loop condition RHS is ternary\nCondition RHS"); + C->print(); printf("\n"); fflush(stdout); + chillAST_node *l = C->lhs; + if (l->isParenExpr()) l = ((chillAST_ParenExpr *)l)->subexpr; + chillAST_node *r = C->rhs; + if (r->isParenExpr()) r = ((chillAST_ParenExpr *)r)->subexpr; + + //fprintf(stderr, "lhs is %s rhs is %s\n", l->getTypeString(), r->getTypeString()); + + chillAST_node *ifcondrhs = NULL; + if (!(l->isConstant())) ifcondrhs = l; + else if (!(r->isConstant())) ifcondrhs = r; + else { + // should never happen. 2 constants. infinite loop + fprintf(stderr, "chill_ast.cc INIFNITE LOOP?\n"); + this->print(0,stderr); fprintf(stderr, "\n\n"); + exit(-1); + } + + // wrap the loop body in an if + chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr( decls[0] ); + chillAST_BinaryOperator *ifcond = new chillAST_BinaryOperator( DRE, "<=", ifcondrhs ); + chillAST_IfStmt *ifstmt = new chillAST_IfStmt( ifcond, body, NULL, NULL ); + + newstmt = ifstmt; + } + } + + //fprintf(stderr, "forstmt 0x%x has parent 0x%x of type %s\n", this, parent, parent->getTypeString()); + //fprintf(stderr, "forstmt will be replaced by\n"); + //newstmt->print(0,stderr); fprintf(stderr, "\n\n"); + + parent->replaceChild( this, newstmt ); + } + + +} + + + + + +chillAST_BinaryOperator::chillAST_BinaryOperator() { + //fprintf(stderr, "chillAST_BinaryOperator::chillAST_BinaryOperator() %p no parent\n", this); + fprintf(stderr, "chillAST_BinaryOperator::chillAST_BinaryOperator() no parent\n"); + lhs = rhs = NULL; + op = NULL; + asttype = CHILLAST_NODETYPE_BINARYOPERATOR; + isFromSourceFile = true; // default + filename = NULL; +} + + +chillAST_BinaryOperator::chillAST_BinaryOperator(chillAST_node *l, const char *oper, chillAST_node *r, chillAST_node *par) { + //fprintf(stderr, "chillAST_BinaryOperator::chillAST_BinaryOperator( l %p %s r %p, parent %p) this %p\n", l, oper, r, par, this); + fprintf(stderr, "chillAST_BinaryOperator::chillAST_BinaryOperator( l %s r )\n", oper); + + //if (l && r ) { + // fprintf(stderr, "("); l->print(0,stderr); fprintf(stderr, ") %s (", oper); r->print(0,stderr); fprintf(stderr, ")\n\n"); + //} + + lhs = l; + rhs = r; + parent = par; + + if (lhs) lhs->setParent( this ); + if (rhs) rhs->setParent( this ); // may only have part of the lhs and rhs when binop is created + op = strdup(oper); + asttype = CHILLAST_NODETYPE_BINARYOPERATOR; + + // if this writes to lhs and lhs type has an 'imwrittento' concept, set that up + if (isAssignmentOp()) { + if (lhs && lhs->isArraySubscriptExpr()) { + ((chillAST_ArraySubscriptExpr*)lhs)->imwrittento = true; + //fprintf(stderr, "chillAST_BinaryOperator, op '=', lhs is an array reference LVALUE\n"); + } + } + if (isAugmentedAssignmentOp()) { // += etc + //fprintf(stderr, "isAugmentedAssignmentOp() "); print(); fflush(stdout); + if (lhs && lhs->isArraySubscriptExpr()) { + //fprintf(stderr, "lhs is also read from "); lhs->print(); fflush(stdout); + ((chillAST_ArraySubscriptExpr*)lhs)->imreadfrom = true; // note will ALSO have imwrittento true + } + } + + isFromSourceFile = true; // default + filename = NULL; +} + + +int chillAST_BinaryOperator::evalAsInt() { + // very limited. allow +-*/ and integer literals ... + if (isAssignmentOp()) return rhs->evalAsInt(); // ?? ignores/loses lhs info + + if (!strcmp("+", op)) { + //fprintf(stderr, "chillAST_BinaryOperator::evalAsInt() %d + %d\n", lhs->evalAsInt(), rhs->evalAsInt()); + return lhs->evalAsInt() + rhs->evalAsInt(); + } + if (!strcmp("-", op)) return lhs->evalAsInt() - rhs->evalAsInt(); + if (!strcmp("*", op)) return lhs->evalAsInt() * rhs->evalAsInt(); + if (!strcmp("/", op)) return lhs->evalAsInt() / rhs->evalAsInt(); + + fprintf(stderr, "chillAST_BinaryOperator::evalAsInt() unhandled op '%s'\n", op); + segfault(); +} + +chillAST_IntegerLiteral *chillAST_BinaryOperator::evalAsIntegerLiteral() { + return new chillAST_IntegerLiteral( evalAsInt() ); // ?? +} + +void chillAST_BinaryOperator::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(BinaryOperator '%s'\n", op); + + if (lhs) lhs->dump(indent+1, fp); // lhs could be null + else { chillindent(indent+1, fp); fprintf(fp, "(NULL)\n"); } + fflush(fp); + + if (rhs) rhs->dump(indent+1, fp); // rhs could be null + else { chillindent(indent+1, fp); fprintf(fp, "(NULL)\n"); } + fflush(fp); + + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +} + +void chillAST_BinaryOperator::print( int indent, FILE *fp ) { // TODO this needparens logic is wrong + printPreprocBEFORE(indent, fp); + + chillindent( indent, fp ); + bool needparens = false; + if (lhs) { + if (lhs->isImplicitCastExpr()) { + // fprintf(stderr, "\nlhs 0x%x isImplicitCastExpr()\n", lhs); + // fprintf(stderr, "lhs subexpr 0x%x\n", ((chillAST_ImplicitCastExpr*)lhs)->subexpr); + // fprintf(stderr, "lhs subexpr type %s\n", ((chillAST_ImplicitCastExpr*)lhs)->subexpr->getTypeString()); + // + if (((chillAST_ImplicitCastExpr*)lhs)->subexpr->isNotLeaf()) needparens = true; + } + else if (lhs->isNotLeaf()) { + if (isMinusOp() && lhs->isPlusOp()) needparens = false; + else if (isPlusMinusOp() && lhs->isMultDivOp()) needparens = false; + else needparens = true; + } + } + + //fprintf(stderr, "\n\nbinop "); + //lhs->printonly(0,stderr); + //fprintf(stderr," %s ",op); + //rhs->printonly(0,stderr); + //fprintf(stderr,"\n"); + //fprintf(stderr, "op is %s lhs %s rhs %s\n", op, lhs->getTypeString(), rhs->getTypeString()); + //fprintf(stderr, "lhs "); lhs->printonly(0, stderr); fprintf(stderr, " "); + //fprintf(stderr, "lhs needparens = %d\n", needparens); + + + if (needparens) fprintf(fp, "("); + if (lhs) lhs->print( 0, fp ); + else fprintf(fp, "(NULL)"); + if (needparens) fprintf(fp, ")"); + + fprintf( fp, " %s ", op); + + needparens = false; + //fprintf(stderr, "binop rhs is of type %s\n", rhs->getTypeString()); + if (rhs) { + if (rhs->isImplicitCastExpr()) { + if (((chillAST_ImplicitCastExpr*)rhs)->subexpr->isNotLeaf()) needparens = true; + } + //else if (rhs->isNotLeaf()) needparens = true; // too many parens. test too simple + else if (rhs->isNotLeaf()) { + // really need the precedence ordering, and check relative of op and rhs op + if (isMinusOp() ) needparens = true; // safer. perhaps complicated thing on rhs of a minus + else if (isPlusMinusOp() && rhs->isMultDivOp()) needparens = false; + else needparens = true; + } + } + //fprintf(stderr, "rhs "); rhs->printonly(0, stderr); fprintf(stderr, " "); + //fprintf(stderr, "rhs needparens = %d\n\n", needparens); + //if (!needparens) fprintf(stderr, "rhs isNotLeaf() = %d\n", rhs->isNotLeaf()); + + if (needparens) fprintf(fp, "("); + if (rhs) rhs->print( 0, fp ); + else fprintf(fp, "(NULL)"); + if (needparens) fprintf(fp, ")"); + fflush(fp); + printPreprocAFTER(indent, fp); + +} + + +char *chillAST_BinaryOperator::stringRep(int indent ) { + std::string s = string( lhs->stringRep() ) + " " + op + " " + string(lhs->stringRep() ); + return strdup( s.c_str() ); +} + + + +void chillAST_BinaryOperator::printonly( int indent, FILE *fp ) { + + lhs->printonly( indent, fp ); + fprintf( fp, " %s ", op); + rhs->printonly( 0, fp ); + fflush(fp); + + + +} + + +class chillAST_node* chillAST_BinaryOperator::constantFold() { + //fprintf(stderr, "\nchillAST_BinaryOperator::constantFold() "); + //print(0,stderr); fprintf(stderr, "\n"); + + lhs = lhs->constantFold(); + rhs = rhs->constantFold(); + + chillAST_node *returnval = this; + + if (lhs->isConstant() && rhs->isConstant() ) { + //fprintf(stderr, "binop folding constants\n"); print(0,stderr); fprintf(stderr, "\n"); + + if (streq(op, "+") || streq(op, "-") || streq(op, "*")) { + if (lhs->isIntegerLiteral() && rhs->isIntegerLiteral()) { + chillAST_IntegerLiteral *l = (chillAST_IntegerLiteral *)lhs; + chillAST_IntegerLiteral *r = (chillAST_IntegerLiteral *)rhs; + chillAST_IntegerLiteral *I; + + if (streq(op, "+")) I = new chillAST_IntegerLiteral(l->value+r->value, parent); + if (streq(op, "-")) I = new chillAST_IntegerLiteral(l->value-r->value, parent); + if (streq(op, "*")) I = new chillAST_IntegerLiteral(l->value*r->value, parent); + + returnval = I; + //fprintf(stderr, "%d %s %d becomes %d\n", l->value,op, r->value, I->value); + } + else { // at least one is a float + + // usually don't want to do this for floats or doubles + // could probably check for special cases like 0.0/30.0 or X/X or X/1.0 +#ifdef FOLDFLOATS + float lval, rval; + if (lhs->isIntegerLiteral()) { + lval = (float) ((chillAST_IntegerLiteral *)lhs)->value; + } + else { + lval = ((chillAST_FloatingLiteral *)lhs)->value; + } + + if (rhs->isIntegerLiteral()) { + rval = (float) ((chillAST_IntegerLiteral *)rhs)->value; + } + else { + rval = ((chillAST_FloatingLiteral *)rhs)->value; + } + + chillAST_FloatingLiteral *F; + if (streq(op, "+")) F = new chillAST_FloatingLiteral(lval + rval, parent); + if (streq(op, "-")) F = new chillAST_FloatingLiteral(lval - rval, parent); + if (streq(op, "*")) F = new chillAST_FloatingLiteral(lval * rval, parent); + + returnval = F; +#endif + + } + } + //else fprintf(stderr, "can't fold op '%s' yet\n", op); + } + + //fprintf(stderr, "returning "); returnval->print(0,stderr); fprintf(stderr, "\n"); + return returnval; +} + + +class chillAST_node* chillAST_BinaryOperator::clone() { + //fprintf(stderr, "chillAST_BinaryOperator::clone() "); print(); printf("\n"); fflush(stdout); + + chillAST_node* l = lhs->clone(); + chillAST_node* r = rhs->clone(); + chillAST_BinaryOperator *bo = new chillAST_BinaryOperator( l, op, r, parent ); + l->setParent( bo ); + r->setParent( bo ); + bo->isFromSourceFile = isFromSourceFile; + if (filename) bo->filename = strdup(filename); + return bo; +} + +void chillAST_BinaryOperator::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool w ) { + //fprintf(stderr, "chillAST_BinaryOperator::gatherArrayRefs()\n"); + //print(); fflush(stdout); fprintf(stderr, "\n"); + //if (isAugmentedAssignmentOp()) { + // fprintf(stderr, "%s is augmented assignment\n", op); + //} + + //if (isAssignmentOp()) { + // fprintf(stderr, "%s is assignment\n", op); + //} + + //if (isAugmentedAssignmentOp()) { // lhs is ALSO on the RHS, NOT as a write + // if (lhs->isArraySubscriptExpr()) { // probably some case where this fails + // ((chillAST_ArraySubscriptExpr *) lhs)->imreadfrom = true; + // //lhs->&gatherArrayRefs( refs, 0 ); + // } + //} + + //fprintf(stderr, "in chillAST_BinaryOperator::gatherArrayRefs(), %d &arrayrefs before\n", refs.size()); + lhs->gatherArrayRefs( refs, isAssignmentOp() ); + //fprintf(stderr, "in chillAST_BinaryOperator::gatherArrayRefs(), %d &arrayrefs after lhs\n", refs.size()); + rhs->gatherArrayRefs( refs, 0 ); + //fprintf(stderr, "in chillAST_BinaryOperator::gatherArrayRefs(), %d &refs\n", refs.size()); + + //for (int i=0; i<refs.size(); i++) { + // fprintf(stderr, "%s\n", (*refs)[i]->basedecl->varname); + //} + +} + +void chillAST_BinaryOperator::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + lhs->gatherScalarRefs( refs, isAssignmentOp() ); + rhs->gatherScalarRefs( refs, 0 ); +} + + +void chillAST_BinaryOperator::replaceChild( chillAST_node *old, chillAST_node *newchild ) { + //fprintf(stderr, "\nbinop::replaceChild( old 0x%x, new ) lhs 0x%x rhd 0x%x\n", old, lhs, rhs); + + // will pointers match?? + if (lhs == old) setLHS( newchild ); + else if (rhs == old) setRHS( newchild ); + + // silently ignore? + //else { + // fprintf(stderr, "\nERROR chillAST_BinaryOperator::replaceChild( old 0x%x, new ) lhs 0x%x rhd 0x%x\n", old, lhs, rhs); + // fprintf(stderr, "old is not a child of this BinaryOperator\n"); + // print(); + // dump(); + // exit(-1); + //} +} + + + +void chillAST_BinaryOperator::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_BinaryOperator::gatherVarDecls()\n"); + + //fprintf(stderr, "chillAST_BinaryOperator::gatherVarDecls() before %d\n", decls.size()); + //print(0,stderr); fprintf(stderr, "\n"); + //fprintf(stderr, "lhs is %s\n", lhs->getTypeString()); + if (lhs) lhs->gatherVarDecls( decls ); // 'if' to deal with partially formed + if (rhs) rhs->gatherVarDecls( decls ); + //fprintf(stderr, "after %d\n", decls.size()); +} + + +void chillAST_BinaryOperator::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_BinaryOperator::gatherScalarVarDecls() before %d\n", decls.size()); + //fprintf(stderr, "lhs is %s\n", lhs->getTypeString()); + lhs->gatherScalarVarDecls( decls ); + rhs->gatherScalarVarDecls( decls ); + //fprintf(stderr, "after %d\n", decls.size()); +} + + +void chillAST_BinaryOperator::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_BinaryOperator::gatherArrayVarDecls() before %d\n", decls.size()); + //fprintf(stderr, "lhs is %s\n", lhs->getTypeString()); + lhs->gatherArrayVarDecls( decls ); + rhs->gatherArrayVarDecls( decls ); + //fprintf(stderr, "after %d\n", decls.size()); +} + + + +void chillAST_BinaryOperator::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + lhs->gatherDeclRefExprs( refs ); + rhs->gatherDeclRefExprs( refs ); +} + + +void chillAST_BinaryOperator::gatherStatements(std::vector<chillAST_node*> &statements ){ + + // what's legit? + if (isAssignmentOp()) { + statements.push_back( this ); + } + +} + + + + +void chillAST_BinaryOperator::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + lhs->gatherVarUsage( decls ); + rhs->gatherVarUsage( decls ); +} + +void chillAST_BinaryOperator::gatherVarLHSUsage( vector<chillAST_VarDecl*> &decls ) { + lhs->gatherVarUsage( decls ); +} + + void chillAST_BinaryOperator::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { + //if (!strcmp(op, "<=")) { + // fprintf(stderr, "chillAST_BinaryOperator::replaceVarDecls( old %s, new %s)\n", olddecl->varname, newdecl->varname ); + // print(); printf("\n"); fflush(stdout); + // fprintf(stderr, "binaryoperator, lhs is of type %s\n", lhs->getTypeString()); + // fprintf(stderr, "binaryoperator, rhs is of type %s\n", rhs->getTypeString()); + //} + lhs->replaceVarDecls( olddecl, newdecl ); + rhs->replaceVarDecls( olddecl, newdecl ); + //if (!strcmp(op, "<=")) { + // print(); printf("\n\n"); fflush(stdout); + //} + } + + +bool chillAST_BinaryOperator::isSameAs( chillAST_node *other ){ + if (!other->isBinaryOperator()) return false; + chillAST_BinaryOperator *o = (chillAST_BinaryOperator *)other; + if (strcmp(op, o->op)) return false; // different operators + return lhs->isSameAs( o->lhs ) && rhs->isSameAs( o->rhs ); // recurse +} + + + + +chillAST_TernaryOperator::chillAST_TernaryOperator() { + op = strdup("?"); // the only one so far + condition = lhs = rhs = NULL; + asttype = CHILLAST_NODETYPE_TERNARYOPERATOR; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_TernaryOperator::chillAST_TernaryOperator(const char *oper, chillAST_node *c, chillAST_node *l, chillAST_node *r, chillAST_node *par) { + + op = strdup(oper); + condition = c; condition->setParent( this ); + lhs = l; lhs->setParent( this ); + rhs = r; rhs->setParent( this ); + asttype = CHILLAST_NODETYPE_TERNARYOPERATOR; + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_TernaryOperator::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(TernaryOperator '%s'\n", op); + condition->dump(indent+1, fp); + lhs->dump(indent+1, fp); + rhs->dump(indent+1, fp); + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +} + +void chillAST_TernaryOperator::print( int indent, FILE *fp ) { + printPreprocBEFORE(indent, fp); + chillindent(indent, fp); + fprintf(fp, "("); + condition->print(0,fp); + fprintf(fp, "%s", op); + lhs->print(0,fp); + fprintf(fp, ":"); + rhs->print(0,fp); + fprintf(fp, ")"); + fflush(fp); +} + +void chillAST_TernaryOperator::replaceChild( chillAST_node *old, chillAST_node *newchild ) { + //fprintf(stderr, "\nbinop::replaceChild( old 0x%x, new ) lhs 0x%x rhd 0x%x\n", old, lhs, rhs); + + // will pointers match?? + if (lhs == old) setLHS( newchild ); + else if (rhs == old) setRHS( newchild ); + else if (condition == old) setCond( newchild ); + + // silently ignore? + //else { + //} +} + + +void chillAST_TernaryOperator::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + condition->gatherVarDecls( decls ); + lhs->gatherVarDecls( decls ); + rhs->gatherVarDecls( decls ); +} + +void chillAST_TernaryOperator::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + condition->gatherScalarVarDecls( decls ); + lhs->gatherScalarVarDecls( decls ); + rhs->gatherScalarVarDecls( decls ); +} + + +void chillAST_TernaryOperator::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + condition->gatherArrayVarDecls( decls ); + lhs->gatherArrayVarDecls( decls ); + rhs->gatherArrayVarDecls( decls ); +} + + + +void chillAST_TernaryOperator::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + condition->gatherDeclRefExprs( refs ); + lhs->gatherDeclRefExprs( refs ); + rhs->gatherDeclRefExprs( refs ); +} + + + +void chillAST_TernaryOperator::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + condition->gatherVarUsage( decls ); + lhs->gatherVarUsage( decls ); + rhs->gatherVarUsage( decls ); +} + +void chillAST_TernaryOperator::gatherVarLHSUsage( vector<chillAST_VarDecl*> &decls ) { + // this makes no sense for ternary ?? +} + +void chillAST_TernaryOperator::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { + condition->replaceVarDecls( olddecl, newdecl ); + lhs->replaceVarDecls( olddecl, newdecl ); + rhs->replaceVarDecls( olddecl, newdecl ); +} + +void chillAST_TernaryOperator::printonly( int indent, FILE *fp ) { + fprintf(fp, "("); + condition->printonly(0,fp); + fprintf(fp, "%s", op); + lhs->printonly(0,fp); + fprintf(fp, ":"); + rhs->printonly(0,fp); + fprintf(fp, ")"); + fflush(fp); +} + + +class chillAST_node* chillAST_TernaryOperator::constantFold() { + condition = condition->constantFold(); + lhs = lhs->constantFold(); + rhs = rhs->constantFold(); + + chillAST_node *returnval = this; + + if (condition->isConstant()) { + //fprintf(stderr, "ternop folding constants\n"); + //print(0,stderr); + //fprintf(stderr, "\n"); + + // assume op is "?" + // TODO + /* + + if (streq(op, "+") || streq(op, "-") || streq(op, "*")) { + if (lhs->isIntegerLiteral() && rhs->isIntegerLiteral()) { + chillAST_IntegerLiteral *l = (chillAST_IntegerLiteral *)lhs; + chillAST_IntegerLiteral *r = (chillAST_IntegerLiteral *)rhs; + chillAST_IntegerLiteral *I; + + if (streq(op, "+")) I = new chillAST_IntegerLiteral(l->value+r->value, parent); + if (streq(op, "-")) I = new chillAST_IntegerLiteral(l->value-r->value, parent); + if (streq(op, "*")) I = new chillAST_IntegerLiteral(l->value*r->value, parent); + + returnval = I; + //fprintf(stderr, "%d %s %d becomes %d\n", l->value,op, r->value, I->value); + } + else { // at least one is a float + float lval, rval; + if (lhs->isIntegerLiteral()) { + lval = (float) ((chillAST_IntegerLiteral *)lhs)->value; + } + else { + lval = ((chillAST_FloatingLiteral *)lhs)->value; + } + if (rhs->isIntegerLiteral()) { + rval = (float) ((chillAST_IntegerLiteral *)rhs)->value; + } + else { + rval = ((chillAST_FloatingLiteral *)rhs)->value; + } + + chillAST_FloatingLiteral *F; + if (streq(op, "+")) F = new chillAST_FloatingLiteral(lval + rval, parent); + if (streq(op, "-")) F = new chillAST_FloatingLiteral(lval - rval, parent); + if (streq(op, "*")) F = new chillAST_FloatingLiteral(lval * rval, parent); + + returnval = F; + } + } + else fprintf(stderr, "can't fold op '%s' yet\n", op); + */ + } + + return returnval; +} + +class chillAST_node* chillAST_TernaryOperator::clone() { + chillAST_node* c = condition->clone(); + chillAST_node* l = lhs->clone(); + chillAST_node* r = rhs->clone(); + chillAST_TernaryOperator *to = new chillAST_TernaryOperator( op, l, r, parent ); + c->setParent( to ); + l->setParent( to ); + r->setParent( to ); + to->isFromSourceFile = isFromSourceFile; + filename = NULL; + return to; +} + +void chillAST_TernaryOperator::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool w ) { + condition->gatherArrayRefs( refs, isAssignmentOp() ); + lhs->gatherArrayRefs( refs, isAssignmentOp() ); + rhs->gatherArrayRefs( refs, 0 ); +} + +void chillAST_TernaryOperator::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + condition->gatherScalarRefs( refs, isAssignmentOp() ); + lhs->gatherScalarRefs( refs, isAssignmentOp() ); + rhs->gatherScalarRefs( refs, 0 ); +} + + + + + + + +chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() { + //fprintf(stderr, "\n%p chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 0\n", this); + asttype = CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR; + base = index = NULL; + basedecl = NULL; //fprintf(stderr, "setting basedecl NULL for ASE %p\n", this); + imwrittento = false; // ?? + imreadfrom = false; // ?? + parent = NULL; + metacomment = NULL; + //fprintf(stderr, "chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() NEED TO FAKE A LOCATION\n"); + isFromSourceFile = true; // default + filename = NULL; + //fprintf(stderr, "\nASE %p is empty\n", this); +} + + + +chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr( chillAST_node *bas, chillAST_node *indx, chillAST_node *par, void *unique ) { + + //fprintf(stderr, "\nchillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 1\n"); + //fprintf(stderr, "ASE index %p ", indx); indx->print(0,stderr); fprintf(stderr, "\n"); + asttype = CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR; + bas->setParent( this ); + if (bas->isImplicitCastExpr()) base = ((chillAST_ImplicitCastExpr*)bas)->subexpr; // probably wrong + else base = bas; + if (indx->isImplicitCastExpr()) index = ((chillAST_ImplicitCastExpr*)indx)->subexpr; // probably wrong + else index = indx; + + base->setParent( this ); + index->setParent( this ); + + imwrittento = false; // ?? + imreadfrom = false; // ?? + uniquePtr = (void *) unique; + //fprintf(stderr,"chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() original = 0x%x\n", uniquePtr); + //fprintf(stderr, "chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 1 calling multibase()\n"); + basedecl = multibase();//fprintf(stderr, "%p ASE 1 basedecl = %p\n",this,basedecl); + //basedecl->print(); printf("\n"); + //basedecl->dump(); printf("\n"); fflush(stdout); + //fprintf(stderr, "basedecl varname %s\n", basedecl->varname); + isFromSourceFile = true; // default + filename = NULL; + + //fprintf(stderr, "\nASE %p parent %p ", this, parent); print(0,stderr); fprintf(stderr, "\n\n"); +} + + + +chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr( chillAST_node *bas, chillAST_node *indx, bool writtento, chillAST_node *par, void *unique ) { + //fprintf(stderr, "\nchillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 2 parent %p\n", par ); + //fprintf(stderr, "ASE %p index %p ", this, indx); indx->print(0,stderr); fprintf(stderr, "\n"); + + asttype = CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR; + bas->setParent( this ); + if (bas->isImplicitCastExpr()) base = ((chillAST_ImplicitCastExpr*)bas)->subexpr; // probably wrong + else base = bas; + + if (indx->isImplicitCastExpr()) index = ((chillAST_ImplicitCastExpr*)indx)->subexpr; // probably wrong + else index = indx; + + //fprintf(stderr, "setting parent of base %p to %p\n", base, this); + //fprintf(stderr, "setting parent of index %p to %p\n", index, this); + base->setParent( this ); + index->setParent( this ); + + imwrittento = writtento; // ?? + //fprintf(stderr, "ASE %p imwrittento %d\n", this, imwrittento); + imreadfrom = false; // ?? + + uniquePtr = (void *) unique; + //fprintf(stderr,"chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() original = 0x%x\n", uniquePtr); + + basedecl = multibase(); + + //fprintf(stderr, "%p ASE 2 basedecl = %p\n", this, basedecl); + //printf("basedecl is "); fflush(stdout); basedecl->print(); printf("\n"); fflush(stdout); + //basedecl->dump(); printf("\n"); fflush(stdout); + //fprintf(stderr, "basedecl varname %s\n", basedecl->varname); + isFromSourceFile = true; // default + filename = NULL; + + //fprintf(stderr, "chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 2 DONE\n"); + //print(0,stderr); fprintf(stderr, "\n\n"); + //fprintf(stderr, "\nASE %p parent %p ", this, parent); print(0,stderr); fprintf(stderr, "\n\n"); + } + + + +chillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr( chillAST_VarDecl *v, std::vector<chillAST_node *> indeces, chillAST_node *par) { + //fprintf(stderr, "\nchillAST_ArraySubscriptExpr::chillAST_ArraySubscriptExpr() 4\n"); + //fprintf(stderr,"chillAST_ArraySubscriptExpr( chillAST_VarDecl *v, std::vector<int> indeces)\n"); + asttype = CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR; + parent = par; + //if (parent == NULL) { + // fprintf(stderr, "dammit. ASE %p has no parent\n", this); + //} + + + int numindeces = indeces.size(); + for (int i=0; i<numindeces; i++) { + fprintf(stderr, "ASE index %d ", i); indeces[i]->print(0,stderr); fprintf(stderr, "\n"); + // printf("["); + // indeces[i]->print(); + // printf("]"); + } + //fflush(stdout); + //fprintf(stderr, "\n"); + + chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr( v->vartype, v->varname, v, NULL); + basedecl = v; // ?? + //fprintf(stderr, "%p ASE 3 basedecl = %p ", this, basedecl); + //fprintf(stderr, "of type %s\n", basedecl->getTypeString()); + //basedecl->print(); printf("\n"); + //basedecl->dump(); printf("\n"); fflush(stdout); + //fprintf(stderr, "basedecl varname %s\n", basedecl->varname); + + chillAST_ArraySubscriptExpr *rent = this; // parent for subnodes + + // these are on the top level ASE that we're creating here + base = (chillAST_node *) DRE; + index = indeces[ numindeces-1]; + + base->setParent( this ); + index->setParent(this); + + for (int i=numindeces-2; i>=0; i--) { + + chillAST_ArraySubscriptExpr *ASE = new chillAST_ArraySubscriptExpr( DRE, indeces[i], rent, 0); + rent->base = ASE; // + rent = ASE; + } + + imwrittento = false; + imreadfrom = false; + //fprintf(stderr, "ASE is "); print(); printf("\n\n"); fflush(stdout); + isFromSourceFile = true; // default + filename = NULL; + + //fprintf(stderr, "\nASE %p parent %p ", this, parent); print(0,stderr); fprintf(stderr, "\n\n"); +} + + + +chillAST_node *chillAST_node::getEnclosingStatement( int level ) { // TODO do for subclasses? + + //fprintf(stderr, "chillAST_node::getEnclosingStatement( level %d ) node type %s\n", level, getTypeString()); + //print(); printf("\n"); fflush(stdout); + + // so far, user will ONLY call this directly on an array subscript expression + if (isArraySubscriptExpr()) return parent->getEnclosingStatement( level+1); + + if (level != 0) { + if (isBinaryOperator() || + isUnaryOperator() || + isTernaryOperator() || + isReturnStmt() || + isCallExpr() + ) return this; + + + // things that are not endpoints. recurse through parent + if (isMemberExpr()) return parent->getEnclosingStatement( level+1 ); + if (isImplicitCastExpr()) return parent->getEnclosingStatement( level+1 ); + if (isSizeof()) return parent->getEnclosingStatement( level+1 ); + if (isCStyleCastExpr()) return parent->getEnclosingStatement( level+1 ); + return NULL; + } + + fprintf(stderr, "getEnclosingStatement() level %d type %s, returning NULL\n", level, getTypeString()); + segfault(); + + return NULL; +} + + + +void chillAST_ArraySubscriptExpr::gatherIndeces(std::vector<chillAST_node*>&ind) { + if (base->isArraySubscriptExpr()) ((chillAST_ArraySubscriptExpr *)base)->gatherIndeces( ind ); + ind.push_back( index ); +} + + + +void chillAST_ArraySubscriptExpr::dump( int indent, FILE *fp ) { +// fprintf(stderr, "\n%p chillAST_ArraySubscriptExpr::dump() basedecl %p\n", basedecl); + + char *local; + if (basedecl && basedecl->vartype) { + local = strdup( basedecl->vartype ); + } + else { + fprintf(stderr, "%p chillAST_ArraySubscriptExpr::dump(), no basedecl ???\n",this); + local = strdup(""); + //fprintf(stderr, "base is "); base->dump(); printf("\n"); base->print(); printf("\n"); fflush(stdout); + //print(); printf("\n"); fflush(stdout); + } + + + char *space = rindex(local, ' '); // can't use index because it's a class member! + if (space) *space = '\0'; // turn "float *" into "float" + + chillindent(indent, fp); + //fprintf(fp, "(ArraySubscriptExpr '%s' ", local); + if (basedecl) { + //fprintf(stderr, " chillAST_ArraySubscriptExpr::dump() basedecl is of type %s\n", basedecl->getTypeString()); + fprintf(fp, "(ArraySubscriptExpr (%s) '%s' ", basedecl->varname, local); + } + else fprintf(stderr, " chillAST_ArraySubscriptExpr::dump() has no basedecl\n"); + free(local); + + if (imwrittento) { + if (imreadfrom) fprintf(fp, "lvalue AND rvalue\n"); + else fprintf(fp, "lvalue\n"); + } + else fprintf(fp, "rvalue\n"); + base->dump( indent+1, fp ); + index->dump(indent+1, fp); + + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +} + + + +void chillAST_ArraySubscriptExpr::print( int indent, FILE *fp ) { + base->print( indent, fp ); + fprintf(fp, "["); + index->print(0, fp); + fprintf(fp, "]"); + fflush(fp); +} + +char *chillAST_ArraySubscriptExpr::stringRep(int indent ) { + fprintf(stderr, "chillAST_ArraySubscriptExpr::stringRep\n"); + + char *blurb; + char *b = base->stringRep(0); + char *i = index->stringRep(0); + // combine. shoudl be using strings. much cleaner TODO + std::string s = string(b) + "[" + string(i) + "]"; + fprintf(stderr, "ASE stringrep %s\n", s.c_str()); + return strdup( s.c_str()); + + +} + + +void chillAST_ArraySubscriptExpr::printonly( int indent, FILE *fp ) { + base->printonly( indent, fp ); + fprintf(fp, "["); + index->printonly(0, fp); + fprintf(fp, "]"); + fflush(fp); +} + + +void chillAST_ArraySubscriptExpr::print( int indent, FILE *fp ) const { + base->print( indent, fp ); + fprintf(fp, "["); + index->print(0, fp); + fprintf(fp, "]"); + fflush(fp); +}; + + +chillAST_VarDecl *chillAST_ArraySubscriptExpr::multibase() { + // return the VARDECL of the thing the subscript is an index into + //this should probably be a chillAST_node function instead of having all these ifs + //print(); printf("\n"); fflush(stdout); + //base->print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "chillAST_ArraySubscriptExpr::multibase() base of type %s\n", base->getTypeString()); + + return base->multibase(); + + // this will be used to SET basedecl + //basedecl = NULL; // do this so we don't confuse ourselves looking at uninitialized basedecl + + chillAST_node *b = base; + //fprintf(stderr, "base is of type %s\n", b->getTypeString()); + + if (!b) return NULL; // just in case ?? + + if (base->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) { // bad coding + b = ((chillAST_ImplicitCastExpr*)b)->subexpr; + } + + if (b->asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR) { // multidimensional array! + // recurse + return ((chillAST_ArraySubscriptExpr *)b)->multibase(); + } + + if (b->asttype == CHILLAST_NODETYPE_DECLREFEXPR) return(((chillAST_DeclRefExpr*)b)->getVarDecl()); + + + if (b->isBinaryOperator()) { + // presumably a dot or pointer ref that resolves to an array + chillAST_BinaryOperator *BO = (chillAST_BinaryOperator *) b; + if ( strcmp(BO->op, ".") ) { + fprintf(stderr, "chillAST_ArraySubscriptExpr::multibase(), UNHANDLED case:\n"); + fprintf(stderr, "base is binary operator, of type %s\n", BO->op); + exit(-1); + } + + chillAST_node *l = BO->lhs; + chillAST_node *r = BO->rhs; + printf("L %s\nR %s\n", l->getTypeString(), r->getTypeString()); + exit(-1); + + return NULL; // TODO do checks? + } + + if (b->isMemberExpr()) { + //c.i[c.count] we want i member of inspector + + chillAST_MemberExpr *ME = (chillAST_MemberExpr *) b; + //fprintf(stderr, "multibase() Member Expression "); ME->print(); printf("\n"); fflush(stdout); + + chillAST_node *n = ME->base; // WRONG want the MEMBER + //fprintf(stderr, "chillAST_ArraySubscriptExpr::multibase() Member Expression base of type %s\n", n->getTypeString()); + //fprintf(stderr, "base is "); ME->base->dump(); + + // NEED to be able to get lowest level recorddecl or typedef from this base + + fprintf(stderr, "chillast.cc, L2315, bailing??\n"); + exit(0); + + if (!n->isDeclRefExpr()) { + fprintf(stderr, "MemberExpr member is not chillAST_DeclRefExpr\n"); + exit(-1); + } + chillAST_DeclRefExpr *DRE = (chillAST_DeclRefExpr *)n; + n = DRE->decl; + //fprintf(stderr, "DRE decl is of type %s\n", n->getTypeString()); + assert( n->isVarDecl() ); + chillAST_VarDecl *vd = (chillAST_VarDecl *) n; + vd->print(); printf("\n"); fflush(stdout); + + chillAST_TypedefDecl *tdd = vd->typedefinition; + chillAST_RecordDecl *rd = vd->vardef; + //fprintf(stderr, "tdd %p rd %p\n", tdd, rd); + + print(); printf("\n"); + dump(); printf("\n"); fflush(stdout); + + assert( tdd != NULL || rd != NULL ); + + chillAST_VarDecl *sub; + if (tdd) sub = tdd->findSubpart( ME->member ); + if (rd) sub = rd->findSubpart( ME->member ); + + //fprintf(stderr, "subpart is "); sub->print(); printf("\n"); fflush(stdout); + + return sub; // what if the sub is an array ?? TODO + } + + + fprintf(stderr, "chillAST_ArraySubscriptExpr::multibase(), UNHANDLED case %s\n", + b->getTypeString()); + print(); printf("\n"); fflush(stdout); + fprintf(stderr, "base is: "); b->print(); printf("\n"); fflush(stdout); + segfault(); +} + + +chillAST_node *chillAST_ArraySubscriptExpr::getIndex(int dim) { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::getIndex( %d )\n", dim); + + chillAST_node *b = base; + + int depth = 0; + std::vector<chillAST_node*> ind; + chillAST_node *curindex = index; + for (;;) { + if (b->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) b = ((chillAST_ImplicitCastExpr*)b)->subexpr; + else if (b->asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR) { + //fprintf(stderr, "base "); b->print(); fprintf(stderr, "\n"); + //fprintf(stderr, "index "); curindex->print(); fprintf(stderr, "\n"); + ind.push_back(curindex); + curindex = ((chillAST_ArraySubscriptExpr*)b)->index; + b = ((chillAST_ArraySubscriptExpr*)b)->base; + depth++; + } + else { + //fprintf(stderr, "base "); b->print(); fprintf(stderr, "\n"); + //fprintf(stderr, "index "); curindex->print(); fprintf(stderr, "\n"); + //fprintf(stderr, "stopping at base type %s\n", b->getTypeString()); + ind.push_back(curindex); + break; + } + } + //fprintf(stderr, "depth %d\n", depth ); + //for (int i=0; i<ind.size(); i++) { ind[i]->print(); fprintf(stderr, "\n"); } + + return ind[ depth - dim ]; + /* + if (dim == 0) return index; // single dimension + fprintf(stderr, "DIM NOT 0\n"); + // multidimension + chillAST_node *b = base; + if (base->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) { // bad coding + b = ((chillAST_ImplicitCastExpr*)b)->subexpr; + } + if (b->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) { // bad coding + b = ((chillAST_ImplicitCastExpr*)b)->subexpr; + } + + b->print(); printf("\n"); fflush(stdout); + if (b->asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR) { + return ((chillAST_ArraySubscriptExpr *)b)->getIndex(dim-1); + } + + fprintf(stderr, "chillAST_ArraySubscriptExpr::getIndex() failed\n"); + */ + exit(-1); +} + + + + +class chillAST_node* chillAST_ArraySubscriptExpr::constantFold() { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::constantFold()\n"); + base = base->constantFold(); + index = index->constantFold(); + return this; +} + +class chillAST_node* chillAST_ArraySubscriptExpr::clone() { + //fprintf(stderr,"chillAST_ArraySubscriptExpr::clone() old imwrittento %d\n", imwrittento); + //fprintf(stderr, "cloning ASE %p ", this); print(0,stderr); printf(" with parent %p\n", parent); fflush(stdout); + //fprintf(stderr, "base %p base->parent %p index %p index->parent %p\n", base, base->parent, index, index->parent); + + //fprintf(stderr, "old base "); base->print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "old base "); base->dump(); printf("\n"); fflush(stdout); + if (base->isDeclRefExpr()) { + chillAST_VarDecl *vd = (chillAST_VarDecl *)(((chillAST_DeclRefExpr *)base)->decl); + //fprintf(stderr, "old decl "); vd->print(); printf("\n");fflush(stdout); + //fprintf(stderr, "old decl "); vd->dump(); printf("\n");fflush(stdout); + } + chillAST_node *b = base->clone(); + //fprintf(stderr, "new base "); b->print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "new base "); b->dump(); printf("\n"); fflush(stdout); + + chillAST_node *i = index->clone(); + //fprintf(stderr, "new index "); i->print(); printf("\n"); fflush(stdout); + + + //if (!index->parent) { + // fprintf(stderr, "ASE %p SOURCE OF CLONE INDEX %p of type %s HAS NO PARENT\n", this, index, index->getTypeString()); + // fprintf(stderr, "ASE SOURCE IS "); print(0,stderr); fprintf(stderr, "\n\n"); + //} + //fprintf(stderr, "cloning AST %p, after cloning base and index, creating a new ASE\n", this); + chillAST_ArraySubscriptExpr *ASE = new chillAST_ArraySubscriptExpr( b, i, imwrittento, parent, uniquePtr /* ?? */ ); + //fprintf(stderr, "cloned AST will be %p with parent %p and base %p index %p\n", ASE, parent, b, i); + + ASE->imreadfrom = false; // don't know this yet + //ASE->imreadfrom = imreadfrom; // ?? + //if (ASE->imreadfrom) { + // fprintf(stderr, "in chillAST_ArraySubscriptExpr::clone(), imreadfrom is being set. \n"); + // ASE->print(); fflush(stdout); fprintf(stderr, "\n"); + //} + + //fprintf(stderr, "cloned result "); ASE->print(); printf("\n\n\n"); fflush(stdout); + //fprintf(stderr, "ASE clone() this 0x%x clone 0x%x\n", this, ASE); + ASE->isFromSourceFile = isFromSourceFile; + if (filename) ASE->filename = strdup(filename); + return ASE; +} + +void chillAST_ArraySubscriptExpr::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ) { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::gatherArrayRefs setting imwrittento %d for ", writtento); +//fprintf(stderr, "%s ", base->getTypeString()); +//base->print(); printf("\n"); fflush(stdout); + + //fprintf(stderr, "found an array subscript. &refs 0x%x ", refs); + if (!imwrittento) imwrittento = writtento; // may be both written and not for += + fflush(stdout); + + //fprintf(stderr, "recursing on index "); index->print(0,stderr); fprintf(stderr, "\n"); + index->gatherArrayRefs( refs, 0 ); // recurse first + //fprintf(stderr, "adding this "); print(0,stderr); fprintf(stderr, "\n"); + //fprintf(stderr, "refs[%d] = 0x%x = ", refs.size(), this); print(); fflush(stdout); + refs.push_back( this ); + + //fprintf(stderr, " size now %d\n", refs.size()); + +} + +void chillAST_ArraySubscriptExpr::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + index->gatherScalarRefs( refs, 0 ); +} + +void chillAST_ArraySubscriptExpr::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::gatherVarDecls()\n"); + + base->gatherVarDecls( decls ); + index->gatherVarDecls( decls ); +} + + +void chillAST_ArraySubscriptExpr::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::gatherScalarVarDecls()\n"); + //fprintf(stderr, "base %s index %s\n", base->getTypeString(), index->getTypeString()); + base->gatherScalarVarDecls( decls ); + index->gatherScalarVarDecls( decls ); +} + + +void chillAST_ArraySubscriptExpr::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::gatherArrayVarDecls()\n"); + //fprintf(stderr, "base %s index %s\n", base->getTypeString(), index->getTypeString()); + base->gatherArrayVarDecls( decls ); + index->gatherArrayVarDecls( decls ); +} + + +void chillAST_ArraySubscriptExpr::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + base->gatherDeclRefExprs( refs ); + index->gatherDeclRefExprs( refs ); +} + + +void chillAST_ArraySubscriptExpr::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + base->gatherVarUsage( decls ); + index->gatherVarUsage( decls ); +} + + +void chillAST_ArraySubscriptExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + base->replaceVarDecls( olddecl, newdecl ); + index->replaceVarDecls( olddecl, newdecl ); +} + + +void chillAST_ArraySubscriptExpr::replaceChild( chillAST_node *old, chillAST_node *newchild ) { + //fprintf(stderr,"chillAST_ArraySubscriptExpr::replaceChild()\n"); + + // arraysubscriptexpression doesn t really have children (should it?) + // try index ??? + if (old == index) { + //fprintf(stderr, "old is index\n"); + index = newchild; + index->parent = this; + return; + } + + // try base ??? unclear if this makes sense TODO + if (old == base) { + //fprintf(stderr, "old is base\n"); + base = newchild; + base->parent = this; + return; + } + + fprintf(stderr, "chillAST_ArraySubscriptExpr::replaceChild() old is not base or index\n"); + print(0,stderr); fprintf(stderr, "\nchild: "); + if (!old) fprintf(stderr, "oldchild NULL!\n"); + old->print(0,stderr); fprintf(stderr, "\nnew: "); + newchild->print(0,stderr); fprintf(stderr, "\n"); + segfault(); // make easier for gdb +}; + + +bool chillAST_ArraySubscriptExpr::operator!=( const chillAST_ArraySubscriptExpr &other) { + bool opposite = *this == other; + return !opposite; +} + + + +bool chillAST_ArraySubscriptExpr::operator==( const chillAST_ArraySubscriptExpr &other) { + //fprintf(stderr, "chillAST_ArraySubscriptExpr::operator==\n"); + //fprintf(stderr, "this->basedecl 0x%x other.basedecl 0x%x\n", this->basedecl, other.basedecl); + //this->basedecl->print(); printf("\n\n"); + //other.basedecl->print(); printf("\n"); fflush(stdout); + + //this->print(); printf(" 0x%x == 0x%x ",this->uniquePtr, other.uniquePtr ); other.print(); printf(" ?? "); fflush(stdout); + //if ( this->uniquePtr == other.uniquePtr) fprintf(stderr, "t\n"); + //else fprintf(stderr, "f\n"); + return this->uniquePtr == other.uniquePtr; +} + + + + + +chillAST_MemberExpr::chillAST_MemberExpr() { + asttype = CHILLAST_NODETYPE_MEMBEREXPR; + base = NULL; + member = NULL; + parent = NULL; + metacomment = NULL; + exptype = CHILL_MEMBER_EXP_DOT; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_MemberExpr::chillAST_MemberExpr( chillAST_node *bas, const char *mem, chillAST_node *p, void *unique, CHILL_MEMBER_EXP_TYPE t ) { + asttype = CHILLAST_NODETYPE_MEMBEREXPR; + base = bas; + if (base) base->setParent( this ); + if (mem) member = strdup( mem ); + parent = p; + metacomment = NULL; + uniquePtr = unique; + exptype = t; + isFromSourceFile = true; // default + filename = NULL; + + return; // ignore tests below ?? TODO ?? + + + // base needs to RESOLVE to a decl ref expr but may not BE one + // A.b . c lhs is a binop or memberexpr + + if (bas->isBinaryOperator()) { + //fprintf(stderr, "checking binop to see if it resolved to a declrefexpr\n"); + // cheat for now or just remove the check below + return; + } + + if (! ( bas->isDeclRefExpr() || bas->isArraySubscriptExpr() )) { + fprintf(stderr, "chillAST_MemberExpr::chillAST_MemberExpr(), base is of type %s\n", bas->getTypeString()); + fprintf(stderr, "chillAST_MemberExpr::chillAST_MemberExpr(), base is not DeclRefExpr\n"); + + base->print(); printf(".%s\n", mem); fflush(stdout); + segfault(); + } +} + + +void chillAST_MemberExpr::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(MemberExpr \n"); + + base->dump( indent+1, fp ); + chillindent(indent+1, fp); + if (exptype == CHILL_MEMBER_EXP_ARROW) fprintf(fp, "->"); + else fprintf(fp, "."); + + fprintf(fp, "%s\n", member); + + chillindent(indent, fp); + fprintf(fp, ")\n"); +} + + +void chillAST_MemberExpr::print( int indent, FILE *fp ) { + if (base) base->print( indent, fp ); + else { + chillindent( indent, fp ); + fprintf(fp, "(NULL)"); + } + if (exptype == CHILL_MEMBER_EXP_ARROW) fprintf(fp, "->"); + else fprintf(fp, "."); + if (member) fprintf(fp, "%s", member); + else fprintf(fp, "(NULL)"); + fflush(fp); +} + + +void chillAST_MemberExpr::printonly( int indent, FILE *fp ) { + base->print( indent, fp ); + if (exptype == CHILL_MEMBER_EXP_ARROW) fprintf(fp, "->"); + else fprintf(fp, "."); + fprintf(fp, "%s", member); + fflush(fp); +} + +char *chillAST_MemberExpr::stringRep( int indent ) { // char pointer to what we'd print + fprintf(stderr, "*chillAST_MemberExpr::stringRep()\n"); + if (base->isDeclRefExpr()) { // + chillAST_VarDecl *vd = (chillAST_VarDecl *) ((chillAST_DeclRefExpr *)base)->decl; + char *leak = (char *)malloc(128); + if (exptype == CHILL_MEMBER_EXP_ARROW) sprintf(leak, "%s->%s", vd->varname, member); + else sprintf(leak, "%s.%s", vd->varname, member); + printstring = leak; + return leak; + } + + + // else + // TODO + return strdup("chillAST_MemberExpr::getStringRep()hadanerror"); +} + + +class chillAST_node* chillAST_MemberExpr::constantFold() { + base = base->constantFold(); + //member = member->constantFold(); + return this; +} + +class chillAST_node* chillAST_MemberExpr::clone() { + chillAST_node *b = base->clone(); + char *m = strdup( member ); // ?? + chillAST_MemberExpr *ME = new chillAST_MemberExpr( b, m, parent, uniquePtr /* ?? */ ); + ME->isFromSourceFile = isFromSourceFile; + if (filename) ME->filename = strdup(filename); + return ME; +} + +void chillAST_MemberExpr::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ) { + fprintf(stderr, "chillAST_MemberExpr::gatherArrayRefs() "); print(0,stderr); fprintf(stderr, "\n"); + fprintf(stderr, "base of of type %s\n", base->getTypeString()); + base->gatherArrayRefs( refs, writtento ); // + +} + +void chillAST_MemberExpr::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + base->gatherScalarRefs( refs, writtento ); +} + +void chillAST_MemberExpr::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + base->gatherVarDecls( decls ); +} + +void chillAST_MemberExpr::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + base->gatherScalarVarDecls( decls ); +} + + +void chillAST_MemberExpr::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + base->gatherArrayVarDecls( decls ); +} + + +void chillAST_MemberExpr::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + base->gatherDeclRefExprs( refs ); +} + + +void chillAST_MemberExpr::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + base->gatherVarUsage( decls ); +} + + +void chillAST_MemberExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + base->replaceVarDecls( olddecl, newdecl ); +} + +bool chillAST_MemberExpr::operator!=( const chillAST_MemberExpr &other) { + bool opposite = *this == other; + return !opposite; +} + +bool chillAST_MemberExpr::operator==( const chillAST_MemberExpr &other) { + return this->uniquePtr == other.uniquePtr; +} + + +void chillAST_MemberExpr::replaceChild( chillAST_node *old, chillAST_node *newchild ) { + //printf("\nMemberExpr::replaceChild( )\n"); + //printf("old: "); + //old->print(); + //printf("\nnew: "); + //newchild->print(); + //printf("\n"); fflush(stdout); + + // will pointers match?? + if (base == old) { + //fprintf(stderr, "old matches base of MemberExpr\n"); + base = newchild; + } + else { + base->replaceChild( old, newchild ); + } +} + +chillAST_node *chillAST_MemberExpr::multibase2() { /*fprintf(stderr, "ME MB2\n" );*/ return (chillAST_node *)this; } + +chillAST_VarDecl* chillAST_MemberExpr::getUnderlyingVarDecl() { + fprintf(stderr, "chillAST_MemberExpr:getUnderlyingVarDecl()\n"); + print(); printf("\n"); fflush(stdout); + exit(-1); + // find the member with the correct name + +} + + + + +chillAST_VarDecl *chillAST_MemberExpr::multibase() { + //c.i[c.count] we want i member of c + //fprintf(stderr, "ME MB\n" ); + + //fprintf(stderr, "chillAST_MemberExpr::multibase()\n"); + //print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "MemberExpr base is type %s, member %s\n", base->getTypeString(), member); + + //chillAST_VarDecl *vd = base->getUnderlyingVarDecl(); // this is the only thing that ever calls this ??? + chillAST_VarDecl *vd = base->multibase(); // ?? + + + //fprintf(stderr, "vd "); vd->print(); printf("\n"); fflush(stdout); + + chillAST_RecordDecl *rd = vd->getStructDef(); + if (!rd) { + fprintf(stderr, "chillAST_MemberExpr::multibase() vardecl is not a struct??\n"); + fprintf(stderr, "vd "); vd->print(); printf("\n"); fflush(stdout); + fprintf(stderr, "vd "); vd->dump(); printf("\n"); fflush(stdout); + exit(-1); + } + + // OK, we have the recorddecl that defines the structure + // now find the member with the correct name + chillAST_VarDecl *sub = rd->findSubpart( member ); + //fprintf(stderr, "sub %s:\n", member); + if (!sub) { + fprintf(stderr, "can't find member %s in \n", member); + rd->print(); + } + //sub->print(); printf("\n"); fflush(stdout); + //sub->dump() ; printf("\n"); fflush(stdout); + + return sub; + //find vardecl of member in def of base + + +} + + + + +chillAST_DeclRefExpr::chillAST_DeclRefExpr() { + asttype = CHILLAST_NODETYPE_DECLREFEXPR; + declarationType = strdup("UNKNOWN"); + declarationName = strdup("NONE"); + decl = NULL; + parent = NULL; + metacomment = NULL; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_DeclRefExpr::chillAST_DeclRefExpr( const char *varname, chillAST_node *par ) { + asttype = CHILLAST_NODETYPE_DECLREFEXPR; + declarationType = strdup("UNKNOWN"); + declarationName = strdup(varname); + decl = NULL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_DeclRefExpr::chillAST_DeclRefExpr( const char *vartype, const char *varname, chillAST_node *par) { + //fprintf(stderr, "DRE::DRE 0x%x %s %s\n", this, vartype, varname ); + asttype = CHILLAST_NODETYPE_DECLREFEXPR; + declarationType = strdup(vartype); + declarationName = strdup(varname); + decl = NULL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_DeclRefExpr::chillAST_DeclRefExpr( const char *vartype, const char *varname, chillAST_node *d, chillAST_node *par ) { + //fprintf(stderr, "DRE::DRE2 0x%x %s %s 0x%x\n", this, vartype, varname, d ); + asttype = CHILLAST_NODETYPE_DECLREFEXPR; + declarationType = strdup(vartype); + declarationName = strdup(varname); + decl = d; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_DeclRefExpr::chillAST_DeclRefExpr( chillAST_VarDecl *vd, chillAST_node *par ){ // variable def + //fprintf(stderr, "DRE::DRE3 (VD) 0x%x %s %s 0x%x\n", this, vd->vartype, vd->varname, vd ); + + asttype = CHILLAST_NODETYPE_DECLREFEXPR; + declarationType = strdup(vd->vartype); + declarationName = strdup(vd->varname); + decl = vd; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + + +chillAST_DeclRefExpr::chillAST_DeclRefExpr( chillAST_FunctionDecl *fd, chillAST_node *par ){ // function def + asttype = CHILLAST_NODETYPE_DECLREFEXPR; + declarationType = strdup(fd->returnType); + declarationName = strdup(fd->functionName); + decl = fd; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + + + +chillAST_DeclRefExpr *buildDeclRefExpr( chillAST_VarDecl *vd) { + chillAST_DeclRefExpr *dre = new chillAST_DeclRefExpr( vd, NULL ); + +} + +void chillAST_DeclRefExpr::print( int indent, FILE *fp) { + chillindent(indent, fp); + //fprintf(fp, "%s %s", declarationType, declarationName); // this is printing float *A + fprintf(fp, "%s", declarationName); // this is printing A + fflush(fp); +} + + +char *chillAST_DeclRefExpr::stringRep( int indent ) { + return strdup( declarationName ); +} + + +void chillAST_DeclRefExpr::dump( int indent, FILE *fp) { + chillindent(indent, fp); + fprintf(fp, "(DeclRefExpr '%s' ", declarationType); + chillAST_VarDecl *vd = getVarDecl(); + if (vd) { + if (vd->isAParameter) fprintf(fp, "ParmVar "); + else fprintf(fp, "Var "); + } + fprintf(fp, "'%s' ", declarationName); // variable or function name + + if (chillAST_FunctionDecl *fd = getFunctionDecl()) { + // print parameter types for functions + fd->printParameterTypes( fp ); + } + + fprintf(fp, ")\n"); + fflush(fp); +} + +class chillAST_node* chillAST_DeclRefExpr::constantFold() { // can never do anything? + return this; +} + +class chillAST_node* chillAST_DeclRefExpr::clone() { + //fprintf(stderr, "chillAST_DeclRefExpr::clone()\n"); + chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr( declarationType, declarationName, decl, parent ); + DRE->isFromSourceFile = isFromSourceFile; + if (filename) DRE->filename = strdup(filename); + return DRE; +} + + +void chillAST_DeclRefExpr::gatherVarDeclsMore( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_DeclRefExpr::gatherVarDeclsMore()\n"); + decl->gatherVarDeclsMore( decls ); +} + + +void chillAST_DeclRefExpr::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_DeclRefExpr::gatherScalarVarDecls()\n"); + decl->gatherScalarVarDecls(decls); + //fprintf(stderr, "now %d scalar vardecls\n", decls.size()); +} + + +void chillAST_DeclRefExpr::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_DeclRefExpr::gatherArrayVarDecls()\n"); + decl->gatherArrayVarDecls(decls); + //fprintf(stderr, "now %d Array vardecls\n", decls.size()); +} + + +void chillAST_DeclRefExpr::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + refs.push_back(this); +} + +void chillAST_DeclRefExpr::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + refs.push_back(this); +} + +void chillAST_DeclRefExpr::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_DeclRefExpr::gatherVarUsage()\n"); + for (int i=0; i<decls.size(); i++) { + if (decls[i] == decl) { + //fprintf(stderr, "decl was already there\n"); + return; + } + if (streq(declarationName, decls[i]->varname)) { + if (streq(declarationType, decls[i]->vartype)) { + //fprintf(stderr, "decl was already there\n"); + return; + } + } + } + chillAST_VarDecl *vd = getVarDecl(); // null for functiondecl + if (vd) decls.push_back( vd ); + +} + + + + +void chillAST_DeclRefExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + //fprintf(stderr, "chillAST_DeclRefExpr::replaceVarDecls()\n"); + if (decl == olddecl) { + //fprintf(stderr, "replacing old %s with %s\n", olddecl->varname, newdecl->varname); + //fprintf(stderr, "DRE was "); print(); + decl = newdecl; + declarationType = strdup(newdecl->vartype); + declarationName = strdup(newdecl->varname); + //fprintf(stderr, "\nDRE is "); print(); fprintf(stderr, "\n\n"); + } + else { + if (!strcmp(olddecl->varname, declarationName)) { + //fprintf(stderr, "uhoh, chillAST_DeclRefExpr::replaceVarDecls()\n"); + decl = newdecl; + declarationType = strdup(newdecl->vartype); + declarationName = strdup(newdecl->varname); + } + } +} + +chillAST_VarDecl *chillAST_ImplicitCastExpr::multibase() { + return subexpr->multibase(); +} + + +chillAST_VarDecl *chillAST_DeclRefExpr::multibase() { + // presumably, this is being called because this DRE is the base of an ArraySubscriptExpr + return getVarDecl(); +} + + + + + + + + + +void chillAST_VarDecl::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_VarDecl::gatherVarDecls()\n"); + for (int i=0; i<decls.size(); i++) { + if (decls[i] == this) { + //fprintf(stderr, "decl was already there\n"); + return; + } + if (streq(decls[i]->varname, varname)) { + if (streq(decls[i]->vartype, vartype)) { + //fprintf(stderr, "VarDecl (direct) decl was already there\n"); + return; + } + } + } + decls.push_back( this ); +} + + +void chillAST_VarDecl::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_VarDecl::gatherScalarVarDecls(), %s numdimensions %d\n", varname, numdimensions); + + if (numdimensions != 0) return; // not a scalar + + for (int i=0; i<decls.size(); i++) { + if (decls[i] == this) { + //fprintf(stderr, "decl was already there\n"); + return; + } + + if (streq(decls[i]->varname, varname)) { // wrong. scoping. TODO + if (streq(decls[i]->vartype, vartype)) { + //fprintf(stderr, "VarDecl (direct) decl was already there\n"); + return; + } + } + } + //fprintf(stderr, "adding vardecl for %s to decls\n", varname); + decls.push_back( this ); +} + + +void chillAST_VarDecl::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_VarDecl::gatherScalarVarDecls(), %s numdimensions %d\n", varname, numdimensions); + + if (numdimensions == 0) return; // not an array + + for (int i=0; i<decls.size(); i++) { + if (decls[i] == this) { + //fprintf(stderr, "decl was already there\n"); + return; + } + + if (streq(decls[i]->varname, varname)) { // wrong. scoping. TODO + if (streq(decls[i]->vartype, vartype)) { + //fprintf(stderr, "VarDecl (direct) decl was already there\n"); + return; + } + } + } + //fprintf(stderr, "adding vardecl for %s to decls\n", varname); + decls.push_back( this ); +} + + + +chillAST_node *chillAST_VarDecl::constantFold() { return this; } + +chillAST_node* chillAST_VarDecl::clone() { + fprintf(stderr, "\nchillAST_VarDecl::clone() cloning vardecl for %s\n", varname); + if (isAParameter) fprintf(stderr, "old vardecl IS a parameter\n"); + //else fprintf(stderr, "old vardecl IS NOT a parameter\n"); + + chillAST_VarDecl *vd = new chillAST_VarDecl( vartype, strdup(varname), arraypart, NULL); // NULL so we don't add the variable AGAIN to the (presumably) function + + vd->typedefinition = typedefinition; + vd->vardef = vardef; // perhaps should not do this TODO + //vd->isStruct = (vardef != NULL); // ?? + + vd->underlyingtype = strdup(underlyingtype); + + vd->arraysizes = NULL; + vd->knownArraySizes = knownArraySizes; + vd->numdimensions = numdimensions; + vd->arraypointerpart = NULL; + + if (arraypart != NULL && NULL!=arraysizes) { // !strcmp(arraypart, "")) { + //fprintf(stderr, "in chillAST_VarDecl::clone(), cloning the array info\n"); + //fprintf(stderr, "numdimensions %d arraysizes 0x%x\n", numdimensions, arraysizes) ; + vd->numdimensions = numdimensions; + + if (arraysizes) { + vd->arraysizes = (int *)malloc( sizeof(int *) * numdimensions ); + for (int i=0; i< numdimensions; i++) { + //fprintf(stderr, "i %d\n", i); + vd->arraysizes[i] = arraysizes[i]; + } + } + } + + if ( arraypointerpart ) { + //fprintf(stderr, "copying arraypointerpart\n"); + vd->arraypointerpart = strdup( arraypointerpart); + } + + vd->isStruct = this->isStruct; + //vd->insideAStruct = this->insideAStruct; + + //if (vd->isStruct) fprintf(stderr, "vardecl::clone() %s is a struct\n", varname); + //else fprintf(stderr, "vardecl::clone() %s is NOT a struct\n", varname); + + + vd->knownArraySizes = this->knownArraySizes; + vd->isFromSourceFile = isFromSourceFile; + if (filename) vd->filename = strdup(filename); + return vd; +} + + +void chillAST_VarDecl::splitarraypart() { + fprintf(stderr, "chillAST_VarDecl::splitarraypart() "); + //fprintf(stderr, "%p ", arraypart); + if (arraypart) fprintf(stderr, "%s", arraypart); + fprintf(stderr, "\n"); + + // split arraypart into (leading??) asterisks and known sizes [1][2][3] + if (!arraypart || // NULL + (arraypart && (*arraypart == '\0'))) { // or empty string + + // parts are both empty string + if (arraypointerpart) free(arraypointerpart); + arraypointerpart = strdup(""); + if (arraysetpart) free(arraysetpart); + arraysetpart = strdup(""); + return; + } + + // arraypart exists and is not empty + int asteriskcount = 0; + int fixedcount = 0; + for ( int i=0; i<strlen(arraypart); i++) { + if (arraypart[i] == '*') { + if (fixedcount) { + fprintf(stderr, "illegal vardecl arraypart: '%s'\n", arraypart); + segfault(); + exit(-1); + } + asteriskcount++; + } + else { // remainder is fixed? + fixedcount++; + // check for brackets and digits only? TODO + } + } + arraypointerpart = (char *) calloc( asteriskcount+1, sizeof(char)); + arraysetpart = (char *) calloc( fixedcount+1, sizeof(char)); + char *ptr = arraypart; + for ( int i=0; i<asteriskcount; i++) arraypointerpart[i] = *ptr++; + for ( int i=0; i<fixedcount; i++) arraysetpart[i] = *ptr++; + + //fprintf(stderr, "%s = %s + %s\n", arraypart, arraypointerpart, arraysetpart); +} + + + + + + +chillAST_IntegerLiteral::chillAST_IntegerLiteral(int val, chillAST_node *par){ + value = val; + asttype = CHILLAST_NODETYPE_INTEGERLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_IntegerLiteral::print( int indent, FILE *fp) { + chillindent(indent, fp); + fprintf(fp, "%d", value); + fflush(fp); +} + +void chillAST_IntegerLiteral::dump( int indent, FILE *fp) { + chillindent(indent, fp); + fprintf(fp, "(IntegerLiteral 'int' %d)\n", value); + fflush(fp); +} + + + +class chillAST_node* chillAST_IntegerLiteral::constantFold() { return this; } // can never do anything + + +class chillAST_node* chillAST_IntegerLiteral::clone() { + + chillAST_IntegerLiteral *IL = new chillAST_IntegerLiteral( value, parent ); + IL->isFromSourceFile = isFromSourceFile; + if (filename) IL->filename = strdup(filename); + return IL; + +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(float val, chillAST_node *par){ + value = val; + precision = 1; + float0double1 = 0; // which is live! + allthedigits = NULL; + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(double val, chillAST_node *par){ + doublevalue = val; + precision = 2; + float0double1 = 1; // which is live! + allthedigits = NULL; + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(float val, int precis, chillAST_node *par){ + value = val; + precision = 1; + float0double1 = 0; // which is live! + precision = precis; // + allthedigits = NULL; + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(double val, int precis, chillAST_node *par){ + doublevalue = val; + float0double1 = 1; // which is live! + precision = precis; // + allthedigits = NULL; + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(float val, const char *printthis, chillAST_node *par){ + value = val; + float0double1 = 0; // which is live! + precision = 1; + allthedigits = NULL; + if (printthis) allthedigits = strdup( printthis ); + //fprintf(stderr, "\nfloatingliteral allthedigits = '%s'\n", allthedigits); + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_FloatingLiteral::chillAST_FloatingLiteral(float val, int precis, const char *printthis, chillAST_node *par){ + value = val; + float0double1 = 0; // which is live! + precision = precis; // but value is a float?? TODO + allthedigits = NULL; + if (printthis) { + //fprintf(stderr, "\nchillAST_FloatingLiteral constructor, printthis "); + //fprintf(stderr, "%p\n", printthis); + allthedigits = strdup( printthis ); + } + //fprintf(stderr, "\nfloatingliteral allthedigits = '%s'\n", allthedigits); + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + + +chillAST_FloatingLiteral::chillAST_FloatingLiteral( chillAST_FloatingLiteral *old ) { + //fprintf(stderr, "chillAST_FloatingLiteral::chillAST_FloatingLiteral( old ) allthedigits %p\n", old->allthedigits); + + asttype = CHILLAST_NODETYPE_FLOATINGLITERAL; + value = old->value; + doublevalue = old->doublevalue; + float0double1 = old->float0double1; + allthedigits = NULL; + if (old->allthedigits) allthedigits = strdup(old->allthedigits); + precision = old->precision; + isFromSourceFile = true; // default + filename = NULL; +} + + + +void chillAST_FloatingLiteral::print( int indent, FILE *fp) { + chillindent(indent, fp); + //fprintf(fp, "%f", value); + // attempt to be more like rose output + char output[1024]; // warning, hardcoded + + if (allthedigits != NULL) { + strcpy(output, allthedigits ); // if they have specified 100 digits of pi, give 'em 100 digits + //fprintf(stderr, "floatingliteral allthedigits = '%s'\n", allthedigits); + } + else { + if (float0double1 == 0) sprintf(output, "%f", value); + else sprintf(output, "%f", doublevalue); + + // next part to avoid printing 123.4560000000000000000000000000 + char *dot = index(output, '.'); + if (dot) { + char *end = output + strlen(output); + char *onechar; + char *lastnonzero = dot; + for (onechar = output; onechar < end; onechar ++) { + if (*onechar != '0') lastnonzero = onechar; + } + + if (lastnonzero == dot) + lastnonzero[2] = '\0'; // may be after end of string, but that should be OK + else lastnonzero[1] = '\0'; // may be after end of string, but that should be OK + } + } + if (precision == 1) { + int len = strlen(output); + output[len] = 'f'; // explicit single precision + output[len+1] = '\0'; + } + + fprintf(fp, "%s", output); + fflush(fp); +} + +void chillAST_FloatingLiteral::dump( int indent, FILE *fp) { + chillindent(indent, fp); + // 2x2 cases ??? + if (precision == 1) + fprintf(fp, "(FloatingLiteral 'float' "); + else fprintf(fp, "(FloatingLiteral 'double' "); + + if (float0double1 == 0) fprintf(fp, "%f)\n", value); // %f gives enough digits + else fprintf(fp, "%f)\n", doublevalue); // %f gives enough digits + fflush(fp); +} + + +chillAST_node* chillAST_FloatingLiteral::constantFold() { return this; }; // NOOP + +chillAST_node* chillAST_FloatingLiteral::clone() { + //fprintf(stderr, "chillAST_FloatingLiteral::clone() "); + //fprintf(stderr, "allthedigits %p \n", allthedigits); + chillAST_FloatingLiteral *newone = new chillAST_FloatingLiteral( this ); + + newone->isFromSourceFile = isFromSourceFile; + if (filename) newone->filename = strdup(filename); + //print(); printf(" "); newone->print(); printf("\n"); fflush(stdout); + return newone; +} + +bool chillAST_FloatingLiteral::isSameAs( chillAST_node *other ){ + if (!other->isFloatingLiteral()) return false; + chillAST_FloatingLiteral *o = (chillAST_FloatingLiteral *)other; + // should we care about single vs double precision? + if (float0double1 != o->float0double1) return false; + if (float0double1 == 0) { + return value == o->value; // WARNING, comparing floats with == + } + return doublevalue == o->doublevalue; // WARNING, comparing doubless with == +} + + + + + +chillAST_UnaryOperator::chillAST_UnaryOperator( const char *oper, bool pre, chillAST_node *sub, chillAST_node *par ) { + op = strdup(oper); + prefix = pre; + subexpr = sub; + subexpr->setParent( this ); + asttype = CHILLAST_NODETYPE_UNARYOPERATOR; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_UnaryOperator::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool w ) { + subexpr->gatherArrayRefs( refs, isAssignmentOp()); // +} + + + +void chillAST_UnaryOperator::print( int indent, FILE *fp) { + bool needparens = false; + if (subexpr->isNotLeaf()) needparens = true; // may get more complicated + + chillindent( indent, fp); // will this ever be invoked? + if (prefix) fprintf(fp, "%s", op); + if (needparens) fprintf(fp, "("); + subexpr->print( 0, fp ); + if (needparens) fprintf(fp, ")"); + if (!prefix) fprintf(fp, "%s", op); + fflush(fp); +} + + +void chillAST_UnaryOperator::dump( int indent, FILE *fp) { + chillindent( indent, fp); + fprintf(fp, "(UnaryOperator "); + if (prefix) fprintf(fp, "prefix "); + else fprintf(fp, "postfix "); + fprintf(fp, "%s\n", op); + subexpr->dump(indent+1, fp); + + chillindent( indent, fp); + fprintf(fp, ")\n"); +} + + +void chillAST_UnaryOperator::gatherVarLHSUsage( vector<chillAST_VarDecl*> &decls ) { + if ((!strcmp("++", op)) || (!strcmp("--", op))) { + subexpr->gatherVarUsage( decls ); // do all unary modify the subexpr? (no, - ) + } +} + + + +chillAST_node* chillAST_UnaryOperator::constantFold() { + //fprintf(stderr, "chillAST_UnaryOperator::constantFold() "); + //print(); fprintf(stderr, "\n"); + + subexpr = subexpr->constantFold(); + chillAST_node *returnval = this; + if (subexpr->isConstant()) { + //fprintf(stderr, "unary op folding constants\n"); + //print(0,stderr); fprintf(stderr, "\n"); + + if (streq(op, "-")) { + if (subexpr->isIntegerLiteral()) { + int intval = ((chillAST_IntegerLiteral*)subexpr)->value; + chillAST_IntegerLiteral *I = new chillAST_IntegerLiteral( -intval, parent); + returnval = I; + //fprintf(stderr, "integer -%d becomes %d\n", intval, I->value); + } + else { + chillAST_FloatingLiteral *FL = (chillAST_FloatingLiteral*)subexpr; + chillAST_FloatingLiteral *F = new chillAST_FloatingLiteral( FL ); // clone + F->parent = FL->parent; + + F->value = -F->value; + F->doublevalue = -F->doublevalue; + + F->print(); fprintf(stderr, "\n"); + + returnval = F; + } + } + else fprintf(stderr, "can't fold op '%s' yet\n", op); + } + return returnval; +} + + +class chillAST_node* chillAST_UnaryOperator::clone() { + chillAST_UnaryOperator *UO = new chillAST_UnaryOperator( op, prefix, subexpr->clone(), parent ); + UO->isFromSourceFile = isFromSourceFile; + if (filename) UO->filename = strdup(filename); + return UO; +} + + +void chillAST_UnaryOperator::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherVarDecls( decls ); +} + + +void chillAST_UnaryOperator::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherScalarVarDecls( decls ); +} + + +void chillAST_UnaryOperator::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherArrayVarDecls( decls ); +} + + +void chillAST_UnaryOperator::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + subexpr->gatherDeclRefExprs( refs ); +} + + +void chillAST_UnaryOperator::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherVarUsage( decls ); +} + + void chillAST_UnaryOperator::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { + subexpr->replaceVarDecls( olddecl, newdecl ); + } + + +int chillAST_UnaryOperator::evalAsInt() { + if (!strcmp("+", op)) return subexpr->evalAsInt(); + if (!strcmp("-", op)) return -subexpr->evalAsInt(); + if (!strcmp("++", op)) return 1 + subexpr->evalAsInt(); + if (!strcmp("--", op)) return subexpr->evalAsInt() - 1; + + fprintf(stderr, "chillAST_UnaryOperator::evalAsInt() unhandled op '%s'\n", op); + segfault(); + +} + +bool chillAST_UnaryOperator::isSameAs( chillAST_node *other ){ + if (!other->isUnaryOperator()) return false; + chillAST_UnaryOperator *o = (chillAST_UnaryOperator *)other; + if (strcmp(op, o->op)) return false; // different operators + return subexpr->isSameAs( o->subexpr ); // recurse +} + + +chillAST_ImplicitCastExpr::chillAST_ImplicitCastExpr( chillAST_node *sub, chillAST_node *par ) { + subexpr = sub; + subexpr->setParent( this ); + asttype = CHILLAST_NODETYPE_IMPLICITCASTEXPR; + parent = par; + //fprintf(stderr, "ImplicitCastExpr 0x%x has subexpr 0x%x", this, subexpr); + //fprintf(stderr, " of type %s\n", subexpr->getTypeString()); + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_ImplicitCastExpr::print( int indent, FILE *fp) { + // No need to print anything, simply forward to the sub expression. + subexpr->print( indent, fp ); + fflush(fp); +}; + +void chillAST_ImplicitCastExpr::printonly( int indent, FILE *fp) { + // No need to print anything, simply forward to the sub expression. + subexpr->printonly( indent, fp ); + fflush(fp); +}; + +void chillAST_ImplicitCastExpr::replaceChild( chillAST_node *old, chillAST_node *newchild ){ + if (subexpr == old) { // should be the case for this to get called + subexpr = newchild; + subexpr->setParent( this ); + //old->parent = NULL; + return; + } + + fprintf(stderr, "chillAST_ImplicitCastExpr::replaceChild() called with bad 'old'\n"); + exit(-1); // ?? +} + +class chillAST_node* chillAST_ImplicitCastExpr::constantFold() { + chillAST_node *child = subexpr->constantFold(); + child->setParent( parent ) ; // remove myself !! probably a bad idea. TODO + return child; +} + + +class chillAST_node* chillAST_ImplicitCastExpr::clone() { + chillAST_ImplicitCastExpr *ICE = new chillAST_ImplicitCastExpr( subexpr->clone(), parent); + ICE->isFromSourceFile = isFromSourceFile; + if (filename) ICE->filename = strdup(filename); + return ICE; +} + + +void chillAST_ImplicitCastExpr::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool w ) { + subexpr->gatherArrayRefs( refs, w ); +} + +void chillAST_ImplicitCastExpr::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + subexpr->gatherScalarRefs( refs, writtento ); +} + +void chillAST_ImplicitCastExpr::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherVarDecls( decls ); +} + + +void chillAST_ImplicitCastExpr::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherScalarVarDecls( decls ); +} + + +void chillAST_ImplicitCastExpr::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherArrayVarDecls( decls ); +} + + +void chillAST_ImplicitCastExpr::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + subexpr->gatherDeclRefExprs( refs ); +} + + +void chillAST_ImplicitCastExpr::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherVarUsage( decls ); +} + + + +chillAST_CStyleCastExpr::chillAST_CStyleCastExpr( const char *to, chillAST_node *sub, chillAST_node *par ) { + + //fprintf(stderr, "chillAST_CStyleCastExpr::chillAST_CStyleCastExpr( %s, ...)\n", to); + towhat = strdup(to); + subexpr = sub; + if (subexpr) subexpr->setParent( this ); + asttype = CHILLAST_NODETYPE_CSTYLECASTEXPR; + parent = par; + //fprintf(stderr, "chillAST_CStyleCastExpr (%s) sub 0x%x\n", towhat, sub ); + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_CStyleCastExpr::replaceChild( chillAST_node *old, chillAST_node *newchild ){ + if (subexpr == old) { // should be the case for this to get called + subexpr = newchild; + subexpr->setParent( this ); + //old->parent = NULL; + return; + } + + fprintf(stderr, "chillAST_CStyleCastExpr::replaceChild() called with bad 'old'\n"); + exit(-1); // ?? +} + + void chillAST_CStyleCastExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { + subexpr->replaceVarDecls( olddecl, newdecl); + } + +void chillAST_CStyleCastExpr::print( int indent, FILE *fp) { + //fprintf(stderr, "CStyleCastExpr::print()\n"); + chillindent(indent, fp); + + // special cases? should probably walk the AST and change the literal itself + if ( !strcmp("float", towhat) && subexpr->isIntegerLiteral()) { // (float) 3 => 3.0f + subexpr->print( 0, fp ); fprintf(fp, ".0f"); + } + else if ( !strcmp("double", towhat) && subexpr->isIntegerLiteral()) { // (double) 3 => 3.0 + subexpr->print( 0, fp ); fprintf(fp, ".0"); + } + else if ( !strcmp("float", towhat) && subexpr->isFloatingLiteral()) { // (float) 3.0 => 3.0f + subexpr->print( 0, fp ); fprintf(fp, "f"); + } + else { // general case + fprintf(fp, "((%s) ", towhat); + //fprintf(fp, "\ntowhat '%s'\n", towhat ); + + if (subexpr->isVarDecl()) fprintf(fp, "%s", ((chillAST_VarDecl *)subexpr)->varname); + else subexpr->print( indent, fp ); + //fprintf(fp, "subexpr '%s' ", subexpr->getTypeString()); + fprintf(fp, ")"); + } + fflush(fp); +}; + + +void chillAST_CStyleCastExpr::dump( int indent, FILE *fp) { + chillindent(indent, fp); + fprintf(fp, "(CStyleCastExpr (%s) \n", towhat); + subexpr->dump( indent+1, fp ); + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +} + +class chillAST_node* chillAST_CStyleCastExpr::constantFold() { + subexpr = subexpr->constantFold(); + return this; +} + + +class chillAST_node* chillAST_CStyleCastExpr::clone() { + chillAST_CStyleCastExpr *CSCE = new chillAST_CStyleCastExpr( towhat, subexpr->clone(), parent ); + CSCE->isFromSourceFile = isFromSourceFile; + if (filename) CSCE->filename = strdup(filename); + return CSCE; +} + +void chillAST_CStyleCastExpr::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool w ) { + subexpr->gatherArrayRefs( refs, w ); +} + +void chillAST_CStyleCastExpr::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + subexpr->gatherScalarRefs( refs, writtento ); +} + + +void chillAST_CStyleCastExpr::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherVarDecls( decls ); +} + + +void chillAST_CStyleCastExpr::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherScalarVarDecls( decls ); +} + + +void chillAST_CStyleCastExpr::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherArrayVarDecls( decls ); +} + + +void chillAST_CStyleCastExpr::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + subexpr->gatherDeclRefExprs( refs ); +} + + +void chillAST_CStyleCastExpr::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherVarUsage( decls ); +} + + + + +chillAST_CStyleAddressOf::chillAST_CStyleAddressOf( chillAST_node *sub, chillAST_node *par ) { + subexpr = sub; + subexpr->setParent( this ); + asttype = CHILLAST_NODETYPE_CSTYLEADDRESSOF; + parent = par; + //fprintf(stderr, "chillAST_CStyleCastExpr (%s) sub 0x%x\n", towhat, sub ); + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_CStyleAddressOf::print( int indent, FILE *fp) { + //fprintf(stderr, "CStyleAddressOf::print()\n"); + chillindent(indent, fp); + fprintf(fp, "(&"); + subexpr->print( 0, fp ); + fprintf(fp, ")"); + fflush(fp); +}; + +void chillAST_CStyleAddressOf::dump( int indent, FILE *fp) { + chillindent(indent, fp); + fprintf(fp, "(CStyleAddressOf \n"); + subexpr->print( indent+1, fp ); + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +} + +class chillAST_node* chillAST_CStyleAddressOf::constantFold() { + subexpr = subexpr->constantFold(); + return this; +} + +class chillAST_node* chillAST_CStyleAddressOf::clone() { + chillAST_CStyleAddressOf *CSAO = new chillAST_CStyleAddressOf( subexpr->clone(), parent ); + CSAO->isFromSourceFile = isFromSourceFile; + if (filename) CSAO->filename = strdup(filename); + return CSAO; +} + +void chillAST_CStyleAddressOf::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool w ) { + subexpr->gatherArrayRefs( refs, w ); +} + +void chillAST_CStyleAddressOf::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + subexpr->gatherScalarRefs( refs, writtento ); +} + +void chillAST_CStyleAddressOf::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherVarDecls( decls ); +} + +void chillAST_CStyleAddressOf::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherScalarVarDecls( decls ); +} + + +void chillAST_CStyleAddressOf::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherArrayVarDecls( decls ); +} + + +void chillAST_CStyleAddressOf::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + subexpr->gatherDeclRefExprs( refs ); +} + + +void chillAST_CStyleAddressOf::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherVarUsage( decls ); +} + + + + +chillAST_Malloc::chillAST_Malloc(chillAST_node *size, chillAST_node *p) { + thing = NULL; + sizeexpr = size; // probably a multiply like sizeof(int) * 1024 + asttype = CHILLAST_NODETYPE_MALLOC; + parent = p; + isFromSourceFile = true; // default + filename = NULL; +}; + +chillAST_Malloc::chillAST_Malloc(char *thething, chillAST_node *numthings, chillAST_node *p) { + thing = strdup(thething); // "int" or "float" or "struct widget" + sizeexpr = numthings; + asttype = CHILLAST_NODETYPE_MALLOC; + parent = p; + isFromSourceFile = true; // default + filename = NULL; +}; + +chillAST_node* chillAST_Malloc::constantFold() { + sizeexpr->constantFold(); +} + +chillAST_node* chillAST_Malloc::clone() { + chillAST_Malloc *M = new chillAST_Malloc( thing, sizeexpr, parent); // the general version + M->isFromSourceFile = isFromSourceFile; + if (filename) M->filename = strdup(filename); + return M; +}; + +void chillAST_Malloc::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ) { + sizeexpr->gatherArrayRefs( refs, writtento ); +}; + + +void chillAST_Malloc::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + sizeexpr->gatherScalarRefs( refs, writtento ); +}; + +void chillAST_Malloc::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + sizeexpr->gatherVarDecls(decls); +}; + +void chillAST_Malloc::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ){ + sizeexpr->gatherScalarVarDecls(decls); +}; + +void chillAST_Malloc::gatherArrayVarDecls ( vector<chillAST_VarDecl*> &decls ) { + sizeexpr->gatherArrayVarDecls(decls); +}; + +void chillAST_Malloc::gatherVarUsage( vector<chillAST_VarDecl*> &decls ){ + sizeexpr->gatherVarUsage(decls); +}; + + + +void chillAST_Malloc::print( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "malloc("); + + if (thing) { + fprintf(fp, " sizeof(%s) * ", thing ); + } + sizeexpr->print(0,fp); + fprintf(fp, ")"); + fflush(fp); +}; + + +void chillAST_Malloc::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(Malloc \n"); + sizeexpr->dump( indent+1, fp ); + chillindent(indent, fp); + fprintf(fp, ")\n"); + fflush(fp); +}; + + + +chillAST_CudaMalloc::chillAST_CudaMalloc(chillAST_node *devmemptr, chillAST_node *size, chillAST_node *p) { + devPtr = devmemptr; + sizeinbytes = size; // probably a multiply like sizeof(int) * 1024 + asttype = CHILLAST_NODETYPE_CUDAMALLOC; + parent = p; + isFromSourceFile = true; // default + filename = NULL; +}; + +void chillAST_CudaMalloc::print( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "cudaMalloc("); + devPtr->print( 0, fp ); + fprintf(fp, ","); + sizeinbytes->print( 0, fp ); + fprintf(fp, ")"); + fflush(fp); +}; + +void chillAST_CudaMalloc::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(CudaMalloc \n"); + devPtr->dump( indent+1, fp ); + fprintf(fp, "\n"); + sizeinbytes->dump( indent+1, fp ); + fprintf(fp, ")\n"); + fflush(fp); +}; + +class chillAST_node* chillAST_CudaMalloc::constantFold() { + devPtr = devPtr->constantFold(); + return this; +} + +class chillAST_node* chillAST_CudaMalloc::clone() { + chillAST_CudaMalloc *CM = new chillAST_CudaMalloc( devPtr->clone(), sizeinbytes->clone(), parent ); + CM->isFromSourceFile = isFromSourceFile; + if (filename) CM->filename = strdup(filename); + return CM; +} + +void chillAST_CudaMalloc::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool w ) { + devPtr->gatherArrayRefs( refs, false ); + sizeinbytes->gatherArrayRefs( refs, false ); +} + +void chillAST_CudaMalloc::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + devPtr->gatherScalarRefs( refs, false ); + sizeinbytes->gatherScalarRefs( refs, false ); +} + +void chillAST_CudaMalloc::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + devPtr->gatherVarDecls( decls ); + sizeinbytes->gatherVarDecls( decls ); +} + + +void chillAST_CudaMalloc::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + devPtr->gatherScalarVarDecls( decls ); + sizeinbytes->gatherScalarVarDecls( decls ); +} + + + +void chillAST_CudaMalloc::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + devPtr->gatherArrayVarDecls( decls ); + sizeinbytes->gatherArrayVarDecls( decls ); +} + + + +void chillAST_CudaMalloc::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + devPtr->gatherVarUsage( decls ); + sizeinbytes->gatherVarUsage( decls ); +} + + + +chillAST_CudaFree::chillAST_CudaFree(chillAST_VarDecl *var, chillAST_node *p) { + variable = var; + parent = p; + asttype = CHILLAST_NODETYPE_CUDAFREE; + isFromSourceFile = true; // default + filename = NULL; +}; + +void chillAST_CudaFree::print( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "cudaFree(%s)", variable->varname); + fflush(fp); +}; + +void chillAST_CudaFree::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(CudaFree %s )\n", variable->varname); + fflush(fp); +}; + +class chillAST_node* chillAST_CudaFree::constantFold() { + return this; +} + +class chillAST_node* chillAST_CudaFree::clone() { + chillAST_CudaFree *CF = new chillAST_CudaFree( variable, parent ); + CF->isFromSourceFile = isFromSourceFile; + if (filename) CF->filename = strdup(filename); + return CF; +} + +void chillAST_CudaFree::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool w ) {} +void chillAST_CudaFree::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) {} + +void chillAST_CudaFree::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + variable->gatherVarDecls( decls ); +} + + +void chillAST_CudaFree::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + variable->gatherScalarVarDecls( decls ); +} + + +void chillAST_CudaFree::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + variable->gatherArrayVarDecls( decls ); +} + + + +void chillAST_CudaFree::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + variable->gatherVarUsage( decls ); +} + + + + + + + + + +chillAST_CudaMemcpy::chillAST_CudaMemcpy(chillAST_VarDecl *d, chillAST_VarDecl *s, chillAST_node *siz, char *kind, chillAST_node *par) { + dest = d; + src = s; + //fprintf(stderr, "chillAST_CudaMemcpy::chillAST_CudaMemcpy( dest %s, src %s, ...)\n", d->varname, s->varname ); + size = siz; + cudaMemcpyKind = kind; + asttype = CHILLAST_NODETYPE_CUDAMEMCPY; + isFromSourceFile = true; // default + filename = NULL; + parent = par; +}; + +void chillAST_CudaMemcpy::print( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "cudaMemcpy(%s,%s,", dest->varname, src->varname); + //dest->print( 0, fp ); + //fprintf(fp, ","); + // src->print( 0, fp ); just want the src NAME, not name and array info + //fprintf(fp, ","); + size->print( 0, fp ); + fprintf(fp, ",%s)", cudaMemcpyKind); + fflush(fp); +}; + +void chillAST_CudaMemcpy::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(CudaMemcpy \n"); + dest->dump( indent+1, fp ); + src->dump( indent+1, fp ); + size->dump( indent+1, fp ); + chillindent(indent+1, fp); + fprintf(fp, ",%s\n", cudaMemcpyKind); + fflush(fp); +}; + +class chillAST_node* chillAST_CudaMemcpy::constantFold() { + dest = (chillAST_VarDecl *)dest->constantFold(); + src = (chillAST_VarDecl *)src->constantFold(); + size = size->constantFold(); + return this; +} + +class chillAST_node* chillAST_CudaMemcpy::clone() { + chillAST_CudaMemcpy *CMCPY = new chillAST_CudaMemcpy((chillAST_VarDecl *)(dest->clone()),(chillAST_VarDecl *)(src->clone()), size->clone(), strdup(cudaMemcpyKind), parent ); + CMCPY->isFromSourceFile = isFromSourceFile; + if (filename) CMCPY->filename = strdup(filename); + return CMCPY; +} + +void chillAST_CudaMemcpy::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool w ) { + dest->gatherArrayRefs( refs, false ); + src ->gatherArrayRefs( refs, false ); + size->gatherArrayRefs( refs, false ); +} + +void chillAST_CudaMemcpy::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + dest->gatherScalarRefs( refs, false ); + src ->gatherScalarRefs( refs, false ); + size->gatherScalarRefs( refs, false ); +} + +void chillAST_CudaMemcpy::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + dest->gatherVarDecls( decls ); + src ->gatherVarDecls( decls ); + size->gatherVarDecls( decls ); +} + + +void chillAST_CudaMemcpy::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + dest->gatherScalarVarDecls( decls ); + src ->gatherScalarVarDecls( decls ); + size->gatherScalarVarDecls( decls ); +} + + +void chillAST_CudaMemcpy::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + dest->gatherArrayVarDecls( decls ); + src ->gatherArrayVarDecls( decls ); + size->gatherArrayVarDecls( decls ); +} + + +void chillAST_CudaMemcpy::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + dest->gatherVarUsage( decls ); + src ->gatherVarUsage( decls ); + size->gatherVarUsage( decls ); +} + + + +chillAST_CudaSyncthreads::chillAST_CudaSyncthreads( chillAST_node *par) { + asttype = CHILLAST_NODETYPE_CUDASYNCTHREADS; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + + void chillAST_CudaSyncthreads::print( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "__syncthreads()"); + fflush(fp); + } + + void chillAST_CudaSyncthreads::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(syncthreads)\n"); + fflush(fp); + } + + + + + + + + + + +chillAST_ReturnStmt::chillAST_ReturnStmt( chillAST_node *retval, chillAST_node *par ) { + asttype = CHILLAST_NODETYPE_RETURNSTMT; + returnvalue = retval; + if (returnvalue) returnvalue->setParent( this ); + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + + +void chillAST_ReturnStmt::print( int indent, FILE *fp) { + printPreprocBEFORE(indent, fp); + chillindent(indent, fp); + if (returnvalue != NULL) { + fprintf(fp, "return("); + returnvalue->print( 0, fp ); + fprintf(fp, ")" ); // parent will add ";\n" ?? + } + else { + fprintf(fp, "return"); + } + fflush(fp); +} + + +void chillAST_ReturnStmt::dump( int indent, FILE *fp) { + chillindent(indent, fp); + fprintf(fp, "(ReturnStmt"); + if (returnvalue) { + fprintf(fp, "\n"); + returnvalue->dump(indent+1,fp); + chillindent(indent, fp); + } + fprintf(fp, ")\n"); +} + + +class chillAST_node* chillAST_ReturnStmt::constantFold() { + if (returnvalue) returnvalue = returnvalue->constantFold(); + return this; +} + + + +class chillAST_node* chillAST_ReturnStmt::clone() { + chillAST_node *val = NULL; + if ( returnvalue ) val = returnvalue->clone(); + chillAST_ReturnStmt *RS = new chillAST_ReturnStmt( val, parent ); + RS->isFromSourceFile = isFromSourceFile; + if (filename) RS->filename = strdup(filename); + return RS; +} + + +void chillAST_ReturnStmt::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + if (returnvalue) returnvalue->gatherVarDecls( decls ); +} + + +void chillAST_ReturnStmt::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + if (returnvalue) returnvalue->gatherScalarVarDecls( decls ); +} + + +void chillAST_ReturnStmt::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + if (returnvalue) returnvalue->gatherArrayVarDecls( decls ); +} + + + +void chillAST_ReturnStmt::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + if (returnvalue) returnvalue->gatherDeclRefExprs( refs ); +} + + + +void chillAST_ReturnStmt::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + if (returnvalue) returnvalue->gatherVarUsage( decls ); +} + + + + +chillAST_CallExpr::chillAST_CallExpr(chillAST_node *c, chillAST_node *par) { //, int numofargs, chillAST_node **theargs ) { + + //fprintf(stderr, "chillAST_CallExpr::chillAST_CallExpr callee type %s\n", c->getTypeString()); + asttype = CHILLAST_NODETYPE_CALLEXPR; + callee = c; + //callee->setParent( this ); // ?? + numargs = 0; + parent = par; + grid = block = NULL; + isFromSourceFile = true; // default + filename = NULL; +} + + +void chillAST_CallExpr::addArg( chillAST_node *a ) { + args.push_back( a ); + a->setParent( this ); + numargs += 1; +} + + +void chillAST_CallExpr::print( int indent, FILE *fp) { + printPreprocBEFORE(indent, fp); + chillindent(indent, fp); + chillAST_FunctionDecl *FD = NULL; + chillAST_MacroDefinition *MD = NULL; + + if (callee->isDeclRefExpr()) { + chillAST_DeclRefExpr *DRE = (chillAST_DeclRefExpr *) callee; + //fprintf(stderr, "DRE decl is 0x%x\n", DRE->decl); + if (!DRE->decl) { + // a macro? + fprintf(fp, "%s ", DRE->declarationName); + return; // ?? + } + + //fprintf(stderr, "DRE decl of type %s\n", DRE->decl->getTypeString()); + if ( (DRE->decl)->isFunctionDecl()) FD = (chillAST_FunctionDecl *)DRE->decl; + else { + fprintf(stderr, "chillAST_CallExpr::print() DRE decl of type %s\n", DRE->decl->getTypeString()); + exit(-1); + } + } + else if (callee->isFunctionDecl()) FD = (chillAST_FunctionDecl *) callee; + else if (callee->isMacroDefinition()) { + MD = (chillAST_MacroDefinition *) callee; + fprintf(fp, "%s(", MD->macroName); + } + else { + fprintf(stderr, "\nchillAST_CallExpr::print() callee of unhandled type %s\n", callee->getTypeString()); + callee->dump(); + exit(-1); + } + + if (FD) { + fprintf(fp, "%s", FD->functionName ); fflush(fp); + if (grid && block) { + fprintf(fp, "<<<%s,%s>>>(", grid->varname, block->varname); // a + } + else fprintf(fp, "("); + } + + + //callee->print( indent, fp); + for (int i=0; i<args.size(); i++) { + if (i!=0) fprintf(fp, ", "); + args[i]->print(0, fp); + } + fprintf(fp, ")"); //a + fflush(fp); +} + +void chillAST_CallExpr::dump( int indent, FILE *fp) { + chillindent(indent, fp); + fprintf(fp, "(CallExpr "); + //fprintf(stderr, "callee type %s\n", callee->getTypeString()); + chillAST_FunctionDecl *fd = NULL; + if (callee->isDeclRefExpr()) { // always? + chillAST_DeclRefExpr *dre = (chillAST_DeclRefExpr *)callee; + fd = dre->getFunctionDecl(); // if NULL, we've got a Vardecl instead + if (fd) { + //fd->print(); + fprintf(fp, "%s\n", fd->returnType); + } + + callee->dump(indent+1, fp); + if (fd) { + int numparams = fd->parameters.size(); + for (int i=0; i<numparams; i++) fd->parameters[i]->dump(indent+1, fp); + } + } + chillindent(indent, fp); + fprintf(fp, ")\n"); +} + +void chillAST_CallExpr::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ) { + for (int i=0; i<args.size(); i++) { + args[i]->gatherArrayRefs( refs, writtento ); + } +} +void chillAST_CallExpr::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + for (int i=0; i<args.size(); i++) { + args[i]->gatherScalarRefs( refs, writtento ); + } +} + + +void chillAST_CallExpr::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + for (int i=0; i<args.size(); i++) { + args[i]->gatherVarDecls( decls ); + } +} + + +void chillAST_CallExpr::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + for (int i=0; i<args.size(); i++) { + args[i]->gatherScalarVarDecls( decls ); + } +} + + +void chillAST_CallExpr::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + for (int i=0; i<args.size(); i++) { + args[i]->gatherArrayVarDecls( decls ); + } +} + + +void chillAST_CallExpr::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + for (int i=0; i<args.size(); i++) { + args[i]->gatherDeclRefExprs( refs ); + } +} + +void chillAST_CallExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + for (int i=0; i<args.size(); i++) args[i]->replaceVarDecls( olddecl, newdecl ); +} + +void chillAST_CallExpr::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + for (int i=0; i<args.size(); i++) { + args[i]->gatherVarUsage( decls ); + } +} + + +chillAST_node* chillAST_CallExpr::constantFold() { + numargs = args.size(); // wrong place for this + for (int i=0; i<numargs; i++) { + args[i] = args[i]->constantFold(); + } + return this; +} + +chillAST_node* chillAST_CallExpr::clone() { + //fprintf(stderr, "chillAST_CallExpr::clone()\n"); + //print(0, stderr); fprintf(stderr, "\n"); + + chillAST_CallExpr *CE = new chillAST_CallExpr( callee->clone(), NULL ); + for (int i=0; i<args.size(); i++) CE->addArg( args[i]->clone() ); + CE->isFromSourceFile = isFromSourceFile; + if (filename) CE->filename = strdup(filename); + return CE; +} + + + + +chillAST_VarDecl::chillAST_VarDecl() { + //fprintf(stderr, "0chillAST_VarDecl::chillAST_VarDecl() %p\n", this); + fprintf(stderr, "0chillAST_VarDecl::chillAST_VarDecl()\n"); + vartype = underlyingtype = varname = arraypart = arraypointerpart = arraysetpart = NULL; + typedefinition = NULL; + + //fprintf(stderr, "setting underlying type NULL\n" ); + init = NULL; + numdimensions=0; arraysizes = NULL; + asttype = CHILLAST_NODETYPE_VARDECL; // + parent = NULL; + metacomment = NULL; + + vardef = NULL; + isStruct = false; + + //insideAStruct = false; + isAParameter = false; + byreference = false; + isABuiltin = false; + isRestrict = isDevice = isShared = false; // fprintf(stderr, "RDS = false\n"); + knownArraySizes = false; + isFromSourceFile = true; // default + filename = NULL; +}; + + + +chillAST_VarDecl::chillAST_VarDecl( const char *t, const char *n, const char *a, chillAST_node *par) { + //fprintf(stderr, "1chillAST_VarDecl::chillAST_VarDecl( type %s, name %s, arraypart %s, parent %p) %p\n", t, n, a, par, this); + fprintf(stderr, "1chillAST_VarDecl::chillAST_VarDecl( type %s, name %s, arraypart %s)\n", t, n, a); + vartype = strdup(t); + typedefinition = NULL; + + underlyingtype = parseUnderlyingType( vartype ); + //fprintf(stderr, "setting underlying type %s from %s\n", underlyingtype, vartype ); + varname = strdup(n); + arraypointerpart = arraysetpart = NULL; + if (a) arraypart = strdup(a); + else arraypart = strdup(""); + splitarraypart(); + + init = NULL; + numdimensions=0; arraysizes = NULL; + uniquePtr = NULL; + asttype = CHILLAST_NODETYPE_VARDECL; + parent = par; + + + + knownArraySizes = false; + //fprintf(stderr, "arraypart len %d\n", strlen(a)); + for (int i=0; i<strlen(a); i++) { + if (a[i] == '[') { numdimensions++; knownArraySizes = true; } + if (!knownArraySizes && a[i] == '*') numdimensions++; + } + + vardef = NULL; + isStruct = false; + + //insideAStruct = false; + isAParameter = false; + byreference = false; + isABuiltin = false; + isRestrict = isDevice = isShared = false; // fprintf(stderr, "RDS = false\n"); + + if (parent) { + //fprintf(stderr, "chillAST_VarDecl::chillAST_VarDecl( %s ), adding to symbol table???\n", varname); + parent->addVariableToSymbolTable( this ); // should percolate up until something has a symbol table + + } + isFromSourceFile = true; // default + filename = NULL; +}; + + + +chillAST_VarDecl::chillAST_VarDecl( chillAST_RecordDecl *astruct, const char *nam, const char *array, chillAST_node *par) { + // define a variable whose type is a struct! + + fprintf(stderr, "3chillAST_VarDecl::chillAST_VarDecl( %s %p struct ", nam, this ); + const char *type = astruct->getName(); + fprintf (stderr, "%s, name %s, arraypart %s parent ) %p\n", type, nam, array, this); // , par); + + vartype = strdup(type); + + // these always go together ?? + vardef = astruct;// pointer to the thing that says what is inside the struct + isStruct = true; // ?? wrong if it's a union ?? TODO + + //insideAStruct = false; + //fprintf(stderr, "setting vardef of %s to %p\n", nam, vardef); + + underlyingtype = parseUnderlyingType( vartype ); + //fprintf(stderr, "setting underlying type %s from %s\n", underlyingtype, vartype ); + varname = strdup(nam); + arraypart = strdup(array); + arraypointerpart = arraysetpart = NULL; + splitarraypart(); + + init = NULL; + numdimensions=0; arraysizes = NULL; + uniquePtr = NULL; + asttype = CHILLAST_NODETYPE_VARDECL; + parent = par; + + knownArraySizes = false; + //fprintf(stderr, "arraypart len %d\n", strlen(a)); + for (int i=0; i<strlen(array); i++) { + if (array[i] == '[') { numdimensions++; knownArraySizes = true; } + if (!knownArraySizes && array[i] == '*') numdimensions++; + } + + isAParameter = false; + fprintf(stderr, "%s is NOT a parameter\n", nam); + byreference = false; + isABuiltin = false; + isRestrict = isDevice = isShared = false; // fprintf(stderr, "RDS = false\n"); + typedefinition = NULL; + + //fprintf(stderr, "chillAST_VarDecl::chillAST_VarDecl( chillAST_RecordDecl *astruct, ...) MIGHT add struct to some symbol table\n"); + //if (parent) fprintf(stderr, "yep, adding it\n"); + + if (parent) parent->addVariableToSymbolTable( this ); // should percolate up until something has a symbol table + + isFromSourceFile = true; // default + filename = NULL; + +}; + + + + + +chillAST_VarDecl::chillAST_VarDecl( chillAST_TypedefDecl *tdd, const char *n, const char *a, chillAST_node *par) { + fprintf(stderr, "4chillAST_VarDecl::chillAST_VarDecl( %s typedef ", n); + const char *type = tdd->getStructName(); + //fprintf (stderr, "%s, name %s, arraypart %s parent ) %p\n", type, n, a,this); // , par); + typedefinition = tdd; + vartype = strdup(type); + underlyingtype = parseUnderlyingType( vartype ); + //fprintf(stderr, "setting underlying type %s from %s\n", underlyingtype, vartype ); + varname = strdup(n); + arraypart = strdup(a); + arraypointerpart = arraysetpart = NULL; + splitarraypart(); + + init = NULL; + numdimensions=0; arraysizes = NULL; + uniquePtr = NULL; + asttype = CHILLAST_NODETYPE_VARDECL; + parent = par; + + knownArraySizes = false; + //fprintf(stderr, "arraypart len %d\n", strlen(a)); + for (int i=0; i<strlen(a); i++) { + if (a[i] == '[') { numdimensions++; knownArraySizes = true; } + if (!knownArraySizes && a[i] == '*') numdimensions++; + } + + isStruct = tdd->isAStruct(); + + //insideAStruct = false; + + vardef = NULL; + + + isAParameter = false; + byreference = false; + isABuiltin = false; + isRestrict = isDevice = isShared = false; // //fprintf(stderr, "RDS = false\n"); + if (parent) parent->addVariableToSymbolTable( this ); // should percolate up until something has a symbol table + isFromSourceFile = true; // default + filename = NULL; +}; + + + + + +chillAST_VarDecl::chillAST_VarDecl( const char *t, const char *n, const char *a, void *ptr, chillAST_node *par) { + fprintf(stderr, "2chillAST_VarDecl::chillAST_VarDecl( type %s, name %s, arraypart '%s' ) %p\n", t, n, a, this); + //fprintf(stderr, "2chillAST_VarDecl::chillAST_VarDecl( type %s, name %s, arraypart %s, ptr 0x%x, parent 0x%x )\n", t, n, a, ptr, par); + + + vartype = strdup(t); + typedefinition = NULL; + underlyingtype = parseUnderlyingType( vartype ); + //fprintf(stderr, "setting underlying type %s from %s\n", underlyingtype, vartype ); + varname = strdup(n); + + vardef = NULL; // not a struct + isStruct = false; + isAParameter = false; + + if (a) arraypart = strdup(a); + else arraypart = strdup(""); // should catch this earlier + arraypointerpart = arraysetpart = NULL; + splitarraypart(); + + init = NULL; + numdimensions=0; arraysizes = NULL; + uniquePtr = ptr; + asttype = CHILLAST_NODETYPE_VARDECL; + parent = par; + knownArraySizes = false; + + if (par) par->addChild(this); // ?? + + //fprintf(stderr, "name arraypart len %d\n", strlen(a)); + //fprintf(stderr, "arraypart '%s'\n", arraypart); + for (int i=0; i<strlen(a); i++) { + if (a[i] == '[') { numdimensions++; knownArraySizes = true; } + if (!knownArraySizes && a[i] == '*') numdimensions++; // fails for a[4000 * 4] + } + //if (0 == strlen(a) && numdimensions == 0) { + // for (int i=0; i<strlen(t); i++) { // handle float * x + // if (t[i] == '[') numdimensions++; + // if (t[i] == '*') numdimensions++; + // } + //} + //fprintf(stderr, "2name %s numdimensions %d\n", n, numdimensions); + + + + + // this is from ir_clang.cc ConvertVarDecl(), that got executed AFTER the vardecl was constructed. dumb + int numdim = 0; + //knownArraySizes = true; + //if (index(vartype, '*')) knownArraySizes = false; // float *a; for example + //if (index(arraypart, '*')) knownArraySizes = false; + + // note: vartype here, arraypart in next code.. is that right? + if (index(vartype, '*')) { + for (int i = 0; i<strlen(vartype); i++) if (vartype[i] == '*') numdim++; + //fprintf(stderr, "numd %d\n", numd); + numdimensions = numdim; + } + + if (index(arraypart, '[')) { // JUST [12][34][56] no asterisks + char *dupe = strdup(arraypart); + + int len = strlen(arraypart); + for (int i=0; i<len; i++) if (dupe[i] == '[') numdim++; + + //fprintf(stderr, "numdim %d\n", numdim); + + numdimensions = numdim; + int *as = (int *)malloc(sizeof(int *) * numdim ); + if (!as) { + fprintf(stderr, "can't malloc array sizes in ConvertVarDecl()\n"); + exit(-1); + } + arraysizes = as; // 'as' changed later! + + + char *ptr = dupe; + //fprintf(stderr, "dupe '%s'\n", ptr); + while (ptr = index(ptr, '[')) { // this fails for float a[4000*4] + ptr++; + char *leak = strdup(ptr); + char *close = index(leak, ']'); + if (close) *close = '\0'; + + int l = strlen(leak); + bool justdigits = true; + bool justmath = true; + for (int i=0; i<l; i++) { + char c = leak[i]; + if (!isdigit(c)) justdigits = false; + if (!( isdigit(c) || + isblank(c) || + ((c == '+') || (c == '*') || (c == '*') || (c == '*')) || // math + ((c == '(') || (c == ')'))) + ) { + //fprintf(stderr, " not justmath because '%c'\n", c); + justmath = false; + } + + } + + //fprintf(stderr, "tmp '%s'\n", leak); + if (justdigits) { + int dim; + sscanf(ptr, "%d", &dim); + //fprintf(stderr, "dim %d\n", dim); + *as++ = dim; + } + else { + if (justmath) fprintf(stderr, "JUST MATH\n"); + fprintf(stderr, "need to evaluate %s, faking with hardcoded 16000\n", leak); + *as++ = 16000; // temp TODO DFL + } + free (leak); + + ptr = index(ptr, ']'); + //fprintf(stderr, "bottom of loop, ptr = '%s'\n", ptr); + } + free(dupe); + //for (int i=0; i<numdim; i++) { + // fprintf(stderr, "dimension %d = %d\n", i, arraysizes[i]); + //} + + //fprintf(stderr, "need to handle [] array to determine num dimensions\n"); + //exit(-1); + } + + + //insideAStruct = false; + byreference = false; + isABuiltin = false; + isRestrict = isDevice = isShared = false; // fprintf(stderr, "RDS = false\n"); + + //print(); printf("\n"); fflush(stdout); + + // currently this is bad, because a struct does not have a symbol table, so the + // members of a struct are passed up to the func or sourcefile. + if (parent) parent->addVariableToSymbolTable( this ); // should percolate up until something has a symbol table + + + isFromSourceFile = true; // default + filename = NULL; + + fprintf(stderr, "2chillAST_VarDecl::chillAST_VarDecl LEAVING\n"); + //parent->print(); fprintf(stderr, "\n\n"); + + +}; + + +void chillAST_VarDecl::print( int indent, FILE *fp ) { + //fprintf(fp, "chillAST_VarDecl::print()\n"); + + printPreprocBEFORE(indent, fp); + + //fprintf(fp, "VarDecl vartype '%s' varname %s ", vartype, varname); + //if (isAStruct()) fprintf(fp, "isAStruct()\n"); + //else fprintf(fp, "NOT A Struct\n"); + + // fprintf(fp, "\n"); fflush(fp); dump(0,fp); fflush(fp); // debug + + chillindent(indent, fp); + //fprintf(fp, "vardecl->print vartype '%s'\n", vartype); + if (isDevice) fprintf(fp, "__device__ "); + if (isShared) fprintf(fp, "__shared__ "); + + //if (isAStruct()) fprintf(fp, "/* isAStruct() */ "); + //else fprintf(fp, "/* NOT A Struct() */ "); + //if (vardef) fprintf(fp, "/* vardef */ "); + //else fprintf(fp, "/* NOT vardef */ "); + + + //fprintf(stderr, "chillAST_VarDecl::print() %s\n", varname ); + //if (isParmVarDecl()) fprintf(stderr, "%s is a parameter\n", varname); + //if (isAStruct()) fprintf(stderr, "%s is a struct\n", varname); + //else fprintf(stderr, "%s is NOT a struct\n", varname); + //if (!parent) fprintf(stderr, "VARDECL HAS NO PARENT\n"); + //else fprintf(stderr, "parent of %s is type %s\n", varname, parent->getTypeString()); + + // this logic is probably wrong (what about pointer to struct? ) + + //fprintf(stderr, "checking for unnamed only used here\n"); + + if ((!isAParameter) && isAStruct() && vardef) { // an unnamed struct used only here ?? + + //fprintf(fp, "i%s sAStruct() && vardef ?? vardecl of type UNNAMED ONLY USED HERE \n", varname ); + // print the internals of the struct and then the name + vardef->printStructure( 0, fp ); + fprintf(fp, "%s", varname ); + + return; + } + + //fprintf(fp, "ugly logic\n"); + // ugly logic TODO + + if (typedefinition && typedefinition->isAStruct()) fprintf(fp, "struct "); + + if (isAParameter) { + //fprintf(fp, "%s isaparameter\n", varname); + //if (isAStruct()) fprintf(fp, "struct "); + //fprintf(fp, "(param) nd %d", numdimensions ); + //dump(); + if (numdimensions > 0) { + if (knownArraySizes) { // just [12][34][56] + fprintf(fp, "%s ", vartype); + if (byreference) fprintf(fp, "&"); + fprintf(fp, "%s", varname); + for (int n=0; n< (numdimensions); n++) fprintf(fp, "[%d]", arraysizes[n]); + } + else { // some unknown array part float *a; or float **a; or float (*)a[1234] + + //fprintf(fp, "\nsome unknown\n"); + //fprintf(fp, "arraypointerpart '%s'\n", arraypointerpart); + //fprintf(fp, "arraysetpart '%s'\n", arraysetpart); + + if (numdimensions == 1) { + //fprintf(fp, "\nnd1, vartype %s\n", vartype); + + // TODO this if means I have probably made a mistake somewhere + if (!index(vartype, '*')) fprintf(fp, "%s *%s", vartype, varname ); // float *x + else fprintf(fp, "%s%s", vartype, varname); // float *a; + + + } + else { // more than one dimension + + if ( !strcmp("", arraysetpart) ) { // no known dimensions float ***a; + fprintf(fp, "%s %s%s", vartype, arraypointerpart, varname); + } + else if ( !strcmp("", arraypointerpart)) { // ALL known float a[2][7]; + fprintf(fp, "%s %s", vartype, varname); + for (int n=0; n< numdimensions; n++) fprintf(fp, "[%d]", arraysizes[n]); + } + else { // float (*)a[1234] + // this seems really wrong + // float (*)a[1234] + fprintf(fp, "%s (", vartype); + for (int n=0; n< (numdimensions-1); n++) fprintf(fp, "*"); + fprintf(fp, "%s)", varname); + fprintf(fp, "[%d]", arraysizes[numdimensions-1]); + } + + } + } + } // if numdimensions > 0 + else { // parameter float x + fprintf(fp, "%s ", vartype); + if (byreference) fprintf(fp, "&"); + fprintf(fp, "%s", varname); + } + } // end parameter + + else { // NOT A PARAMETER + //fprintf(fp, "NOT A PARAM ... vartype '%s'\n", vartype); + //if (isArray()) fprintf(stderr, "an array, numdimensions %d\n", numdimensions); + //fprintf(stderr, "arraysizes %p\n", arraysizes); + + + + //if (isArray() && arraysizes == NULL) { + // // we just know the number of dimensions but no sizes + // // int ***something + // fprintf(fp, "%s ", vartype); // "int " + // for (int i=0; i<numdimensions; i++) fprintf(fp, "*"); // *** + // fprintf(fp, "%s", varname); // variable name + // } + // else + + fprintf(fp, "%s %s", vartype, arraypointerpart); + if (isRestrict) fprintf(fp, " __restrict__ "); // wrong place + fprintf(fp, "%s%s", varname, arraysetpart ); + if (init) { + fprintf(fp, " = "); fflush(fp); + init->print(0, fp); + } + } + fflush(fp); + //fprintf(stderr, "numdimensions %d arraysizes address 0x%x\n", numdimensions, arraysizes); + //if (!isAParameter) fprintf(fp, ";\n", vartype, varname, arraypart ); +}; + + + + +void chillAST_VarDecl::printName( int in, FILE *fp ) { + chillindent(in, fp); + fprintf(fp, "%s", varname); +}; + + + + +void chillAST_VarDecl::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(VarDecl \"'%s' '%s' '%s'\" n_dim %d ) ", vartype, varname, arraypart, numdimensions); + + //fprintf(fp, "vardef %p\n", vardef); + //if (vardef) fprintf(fp, "(typedef or struct!)\n"); + //fprintf(fp, "typedefinition %p\n", typedefinition); + //if (isStruct) fprintf(fp, "isStruct\n"); + + //if (isAParameter) fprintf(fp, "PARAMETER\n"); + //else fprintf(fp, "NOT PARAMETER\n"); + fflush(fp); + + //segfault(); // see what called this +}; + + +chillAST_RecordDecl * chillAST_VarDecl::getStructDef() { + if (vardef) return vardef; + if (typedefinition) return typedefinition->getStructDef(); + return NULL; +} + + + + + +chillAST_CompoundStmt::chillAST_CompoundStmt() { + //fprintf(stderr, "chillAST_CompoundStmt::chillAST_CompoundStmt() %p\n", this); + asttype = CHILLAST_NODETYPE_COMPOUNDSTMT; + parent = NULL; + symbol_table = new chillAST_SymbolTable; + typedef_table = NULL; + isFromSourceFile = true; // default + filename = NULL; +}; + + +void chillAST_CompoundStmt::print( int indent, FILE *fp ) { + printPreprocBEFORE(indent, fp); + int numchildren = children.size(); + //fprintf(stderr, "NUMCHILDREN %d\n", numchildren); sleep(1); + for (int i=0; i<numchildren; i++) { + children[i]->print(indent, fp); + if (children[i]->asttype != CHILLAST_NODETYPE_FORSTMT + && children[i]->asttype != CHILLAST_NODETYPE_IFSTMT + && children[i]->asttype != CHILLAST_NODETYPE_COMPOUNDSTMT + //&& children[i]->asttype != CHILLAST_NODETYPE_VARDECL // vardecl does its own ";\n" + ) + { + fprintf(fp, ";\n"); // probably wrong + } + } + fflush(fp); +} + +void chillAST_CompoundStmt::replaceChild( chillAST_node *old, chillAST_node *newchild ){ + //fprintf(stderr, "chillAST_CompoundStmt::replaceChild( old %s, new %s)\n", old->getTypeString(), newchild->getTypeString() ); + vector<chillAST_node*> dupe = children; + int numdupe = dupe.size(); + int any = 0; + + for (int i=0; i<numdupe; i++) { + + //fprintf(stderr, "\ni %d\n",i); + //for (int j=0; j<numdupe; j++) { + // fprintf(stderr, "this 0x%x children[%d/%d] = 0x%x type %s\n", this, j, children.size(), children[j], children[j]->getTypeString()); + //} + + + if (dupe[i] == old) { + //fprintf(stderr, "replacing child %d of %d\n", i, numdupe); + //fprintf(stderr, "was \n"); print(); + children[i] = newchild; + newchild->setParent( this ); + //fprintf(stderr, "is \n"); print(); fprintf(stderr, "\n\n"); + // old->parent = NULL; + any = 1; + } + } + + if (!any) { + fprintf(stderr, "chillAST_CompoundStmt::replaceChild(), could not find old\n"); + exit(-1); + } +} + + +void chillAST_CompoundStmt::loseLoopWithLoopVar( char *var ) { + //fprintf(stderr, "chillAST_CompoundStmt::loseLoopWithLoopVar( %s )\n", var); + + //fprintf(stderr, "CompoundStmt 0x%x has parent 0x%x ", this, this->parent); + //fprintf(stderr, "%s\n", parent->getTypeString()); + + + //fprintf(stderr, "CompoundStmt node has %d children\n", children.size()); + //fprintf(stderr, "before doing a damned thing, \n"); + //print(); + //dump(); fflush(stdout); + //fprintf(stderr, "\n\n"); + +#ifdef DAMNED + for (int j=0; j<children.size(); j++) { + fprintf(stderr, "j %d/%d ", j, children.size()); + fprintf(stderr, "subnode %d 0x%x ", j, children[j] ); + fprintf(stderr, "asttype %d ", children[j]->asttype); + fprintf(stderr, "%s ", children[j]->getTypeString()); + if (children[j]->isForStmt()) { + chillAST_ForStmt *FS = ((chillAST_ForStmt *) children[j]); + fprintf(stderr, "for ("); + FS->init->print(0, stderr); + fprintf(stderr, "; "); + FS->cond->print(0, stderr); + fprintf(stderr, "; "); + FS->incr->print(0, stderr); + fprintf(stderr, ") with %d statements in body 0x%x\n", FS->body->getNumChildren(), FS->body ); + } + else fprintf(stderr, "\n"); + } +#endif + + + vector<chillAST_node*> dupe = children; // simple enough? + for (int i=0; i<dupe.size(); i++) { + //for (int j=0; j<dupe.size(); j++) { + // fprintf(stderr, "j %d/%d\n", j, dupe.size()); + // fprintf(stderr, "subnode %d %s ", j, children[j]->getTypeString()); + // if (children[j]->isForStmt()) { + // chillAST_ForStmt *FS = ((chillAST_ForStmt *) children[j]); + // fprintf(stderr, "for ("); + // FS->init->print(0, stderr); + // fprintf(stderr, "; "); + // FS->cond->print(0, stderr); + // fprintf(stderr, "; "); + // FS->incr->print(0, stderr); + // fprintf(stderr, ") with %d statements in body 0x%x\n", FS->body->getNumChildren(), FS->body ); + //} + //else fprintf(stderr, "\n"); + //} + + //fprintf(stderr, "CompoundStmt 0x%x recursing to child %d/%d\n", this, i, dupe.size()); + dupe[i]->loseLoopWithLoopVar( var ); + } + //fprintf(stderr, "CompoundStmt node 0x%x done recursing\n", this ); +} + + + +void chillAST_CompoundStmt::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(CompoundStmt \n" ); + int numchildren = children.size(); + + //for (int i=0; i<numchildren; i++) { + // fprintf(fp, "%d %s 0x%x\n", i, children[i]->getTypeString(), children[i]); + //} + //fprintf(fp, "\n"); + + for (int i=0; i<numchildren; i++) { + children[i]->dump(indent+1, fp); + fprintf(fp, "\n"); // ??? + fflush(fp); + } + chillindent(indent, fp); + fprintf(fp, ")\n"); +}; + + + +chillAST_node* chillAST_CompoundStmt::constantFold(){ + //fprintf(stderr, "chillAST_CompoundStmt::constantFold()\n"); + for (int i=0; i<children.size(); i++) children[i] = children[i]->constantFold(); + return this; +} + + +chillAST_node* chillAST_CompoundStmt::clone(){ + chillAST_CompoundStmt *cs = new chillAST_CompoundStmt(); + for (int i=0; i<children.size(); i++) cs->addChild( children[i]->clone() ); + cs->setParent( parent ); + cs->isFromSourceFile = isFromSourceFile; + if (filename) cs->filename = strdup(filename); + return cs; +} + + +void chillAST_CompoundStmt::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + //fprintf(stderr, "chillAST_CompoundStmt::gatherVarDecls()\n"); + for (int i=0; i<children.size(); i++) children[i]->gatherVarDecls( decls ); +} + + +void chillAST_CompoundStmt::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + for (int i=0; i<children.size(); i++) children[i]->gatherScalarVarDecls( decls ); +} + + +void chillAST_CompoundStmt::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + for (int i=0; i<children.size(); i++) children[i]->gatherArrayVarDecls( decls ); +} + + +void chillAST_CompoundStmt::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + for (int i=0; i<children.size(); i++) children[i]->gatherDeclRefExprs( refs ); +} + + +void chillAST_CompoundStmt::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + for (int i=0; i<children.size(); i++) children[i]->gatherVarUsage( decls ); +} + + +void chillAST_CompoundStmt::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ) { + for (int i=0; i<children.size(); i++) children[i]->gatherArrayRefs( refs, 0); +} + +void chillAST_CompoundStmt::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + for (int i=0; i<children.size(); i++) children[i]->gatherScalarRefs( refs, 0); +} + +void chillAST_CompoundStmt::gatherStatements(std::vector<chillAST_node*> &statements ){ + for (int i=0; i<children.size(); i++) children[i]->gatherStatements( statements ); +} + + + +void chillAST_CompoundStmt::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + for (int i=0; i<children.size(); i++) children[i]->replaceVarDecls( olddecl, newdecl ); +} + + +bool chillAST_CompoundStmt::findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync ) { + + // see how many elements we currently have + int sofar = children.size(); + + // make big enough to add a sync after each statement. wasteful. TODO + // this prevents inserts happening at the forstmt::addSync() from causing a + // reallocation, which screwsup the loop below here + children.reserve( 2 * sofar ); + //fprintf(stderr, "sofar %d reserved %d\n", sofar, 2*sofar); + + bool force = false; + for (int i=0; i<children.size(); i++) { // children.size() to see it gain each time + if (children.size() > sofar ) { + //fprintf(stderr, "HEY! CompoundStmt::findLoopIndexesToReplace() noticed that children increased from %d to %d\n", sofar, children.size()); + sofar = children.size(); + } + + //fprintf(stderr, "compound child %d of type %s force %d\n", i, children[i]->getTypeString(), force ); + bool thisforces = children[i]->findLoopIndexesToReplace( symtab, force ); + force = force || thisforces; // once set, always + } + + return false; + +/* + vector<chillAST_node*> childrencopy; + for (int i=0; i<children.size(); i++) childrencopy.push_back( children[i] ); + bool force = false; + + char *origtypes[64]; + int origsize = children.size(); + for (int i=0; i<children.size(); i++) { + fprintf(stderr, "ORIGINAL compound child %d of type %s\n", i, children[i]->getTypeString() ); + origtypes[i] = strdup( children[i]->getTypeString() ); + fprintf(stderr, "ORIGINAL compound child %d of type %s\n", i, children[i]->getTypeString() ); + } + + for (int i=0; i<childrencopy.size(); i++) { + fprintf(stderr, "compound child %d of type %s force %d\n", i, childrencopy[i]->getTypeString(), force ); + force = force || childrencopy[i]->findLoopIndexesToReplace( symtab, force ); // once set, always + } + + fprintf(stderr, "\n"); + for (int i=0; i<origsize; i++) { + fprintf(stderr, "BEFORE compound child %d/%d of type %s\n", i, origsize, origtypes[i]); + } + for (int i=0; i<children.size(); i++) { + fprintf(stderr, "AFTER compound child %d/%d of type %s\n", i, children.size(), children[i]->getTypeString() ); + } + + return false; +*/ +} + + + + + +chillAST_ParenExpr::chillAST_ParenExpr( chillAST_node *sub, chillAST_node *par ){ + subexpr = sub; + subexpr->setParent( this ); + asttype = CHILLAST_NODETYPE_PARENEXPR; + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_ParenExpr::print( int indent, FILE *fp ) { + //fprintf(stderr, "chillAST_ParenExpr::print()\n"); + chillindent(indent, fp); // hard to believe this will ever do anything + fprintf(fp, "(" ); + subexpr->print( 0, fp ); + fprintf(fp, ")" ); + fflush(fp); +} + +void chillAST_ParenExpr::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(ParenExpr \n"); + subexpr->dump( indent+1, fp ); + chillindent(indent, fp); + fprintf(fp, ")\n"); +} + + +void chillAST_ParenExpr::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ) { + subexpr->gatherArrayRefs( refs, writtento ); +} + +void chillAST_ParenExpr::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + subexpr->gatherScalarRefs( refs, writtento ); +} + + + +chillAST_node* chillAST_ParenExpr::constantFold() { + subexpr = subexpr->constantFold(); + return this; +} + + +chillAST_node* chillAST_ParenExpr::clone() { + chillAST_ParenExpr *PE = new chillAST_ParenExpr( subexpr->clone(), NULL ); + PE->isFromSourceFile = isFromSourceFile; + if (filename) PE->filename = strdup(filename); + return PE; +} + +void chillAST_ParenExpr::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherVarDecls( decls ); +} + + +void chillAST_ParenExpr::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherScalarVarDecls( decls ); +} + + +void chillAST_ParenExpr::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherArrayVarDecls( decls ); +} + + +void chillAST_ParenExpr::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + subexpr->gatherDeclRefExprs( refs ); +} + +void chillAST_ParenExpr::replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){ + subexpr->replaceVarDecls( olddecl, newdecl ); +} + +void chillAST_ParenExpr::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + subexpr->gatherVarUsage( decls ); +} + + + +chillAST_Sizeof::chillAST_Sizeof( char *athing, chillAST_node *par ){ + thing = strdup( athing ); // memory leak + parent = par; + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_Sizeof::print( int indent, FILE *fp ) { + //fprintf(stderr, "chillAST_Sizeof::print()\n"); + chillindent(indent, fp); // hard to believe this will ever do anything + fprintf(fp, "sizeof(" ); + fprintf(fp, "%s)", thing ); + fflush(fp); +} + + +void chillAST_Sizeof::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(Sizeof %s )\n", thing); +} + +void chillAST_Sizeof::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ) {} +void chillAST_Sizeof::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) {} + +chillAST_node* chillAST_Sizeof::constantFold() { + return this; +} + +chillAST_node* chillAST_Sizeof::clone() { + chillAST_Sizeof *SO = new chillAST_Sizeof( thing, NULL ); + SO->isFromSourceFile = isFromSourceFile; + if (filename) SO->filename = strdup(filename); + return SO; +} + +void chillAST_Sizeof::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { // TODO +} + + +void chillAST_Sizeof::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { // TODO +} + + +void chillAST_Sizeof::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { // TODO +} + + +void chillAST_Sizeof::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + // TODO +} + + +void chillAST_Sizeof::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { +} + + +void insertNewDeclAtLocationOfOldIfNeeded( chillAST_VarDecl *newdecl, chillAST_VarDecl *olddecl) { + //fprintf(stderr, "insertNewDeclAtLocationOfOldIfNeeded( new 0x%x old 0x%x\n", newdecl, olddecl ); + + if (newdecl == NULL || olddecl == NULL) { + fprintf(stderr, "chill_ast.cc insertNewDeclAtLocationOfOldIfNeeded() NULL decl\n"); + exit(-1); + } + + if (newdecl == olddecl) return; + + newdecl->vartype = strdup(olddecl->vartype); + + chillAST_node *newparent = newdecl->parent; + chillAST_node *oldparent = olddecl->parent; + //fprintf(stderr, "newparent 0x%x oldparent 0x%x\n", newparent, oldparent ); + if (newparent == oldparent) return; + + if (newparent != NULL) + //fprintf(stderr, "chill_ast.cc insertNewDeclAtLocationOfOldIfNeeded() new decl already has parent?? probably wrong\n"); + newdecl->parent = oldparent; // will be true soon + + // find actual location of old decl and insert new one there + //fprintf(stderr, "oldparent is of type %s\n", oldparent->getTypeString()); // better be compoundstmt ?? + vector<chillAST_node*> children = oldparent->getChildren(); + + int numchildren = children.size(); + //fprintf(stderr, "oldparent has %d children\n", numchildren); + + if (numchildren == 0) { + fprintf(stderr, "chill_ast.cc insertNewDeclAtLocationOfOldIfNeeded() impossible number of oldparent children (%d)\n", numchildren); + exit(-1); + } + + bool newalreadythere = false; + int index = -1; + //fprintf(stderr, "olddecl is 0x%x\n", olddecl); + //fprintf(stderr, "I know of %d variables\n", numchildren); + for (int i=0; i<numchildren; i++) { + chillAST_node *child = oldparent->getChild(i); + //fprintf(stderr, "child %d @ 0x%x is of type %s\n", i, child, child->getTypeString()); + if (children[i] == olddecl) { + index = i; + //fprintf(stderr, "found old decl at index %d\n", index); + } + if (children[i] == newdecl) { + newalreadythere = true; + //fprintf(stderr, "new already there @ index %d\n", i); + } + } + if (index == -1) { + fprintf(stderr, "chill_ast.cc insertNewDeclAtLocationOfOldIfNeeded() can't find old decl for %s\n", olddecl->varname); + exit(-1); + } + + if (!newalreadythere) oldparent->insertChild( index, newdecl ); + +} + + +void gatherVarDecls( vector<chillAST_node*> &code, vector<chillAST_VarDecl*> &decls) { + //fprintf(stderr, "gatherVarDecls()\n"); + + int numcode = code.size(); + //fprintf(stderr, "%d top level statements\n", numcode); + for (int i=0; i<numcode; i++) { + chillAST_node *statement = code[i]; + statement->gatherVarDecls( decls ); + } + +} + + +void gatherVarUsage( vector<chillAST_node*> &code, vector<chillAST_VarDecl*> &decls) { + //fprintf(stderr, "gatherVarUsage()\n"); + + int numcode = code.size(); + //fprintf(stderr, "%d top level statements\n", numcode); + for (int i=0; i<numcode; i++) { + chillAST_node *statement = code[i]; + statement->gatherVarUsage( decls ); + } + +} + + + + +chillAST_IfStmt::chillAST_IfStmt() { + cond = thenpart = elsepart = NULL; + asttype = CHILLAST_NODETYPE_IFSTMT; + isFromSourceFile = true; // default + filename = NULL; +} + +chillAST_IfStmt::chillAST_IfStmt(chillAST_node *c, chillAST_node *t, chillAST_node *e, chillAST_node *p){ + cond = c; + if (cond) cond->setParent( this ); + thenpart = t; + if (thenpart) thenpart->setParent( this ); + elsepart = e; + if (elsepart) elsepart->setParent( this ); + parent = p; + asttype = CHILLAST_NODETYPE_IFSTMT; + isFromSourceFile = true; // default + filename = NULL; +} + +void chillAST_IfStmt::gatherVarDecls( vector<chillAST_VarDecl*> &decls ) { + if (cond) cond->gatherVarDecls( decls ); + if (thenpart) thenpart->gatherVarDecls( decls ); + if (elsepart) elsepart->gatherVarDecls( decls ); +} + + +void chillAST_IfStmt::gatherScalarVarDecls( vector<chillAST_VarDecl*> &decls ) { + if (cond) cond->gatherScalarVarDecls( decls ); + if (thenpart) thenpart->gatherScalarVarDecls( decls ); + if (elsepart) elsepart->gatherScalarVarDecls( decls ); +} + + +void chillAST_IfStmt::gatherArrayVarDecls( vector<chillAST_VarDecl*> &decls ) { + if (cond) cond->gatherArrayVarDecls( decls ); + if (thenpart) thenpart->gatherArrayVarDecls( decls ); + if (elsepart) elsepart->gatherArrayVarDecls( decls ); +} + + +void chillAST_IfStmt::gatherDeclRefExprs( vector<chillAST_DeclRefExpr *>&refs ) { + if (cond) cond->gatherDeclRefExprs( refs ); + if (thenpart) thenpart->gatherDeclRefExprs( refs ); + if (elsepart) elsepart->gatherDeclRefExprs( refs ); +} + + +void chillAST_IfStmt::gatherVarUsage( vector<chillAST_VarDecl*> &decls ) { + if (cond) cond->gatherVarUsage( decls ); + if (thenpart) thenpart->gatherVarUsage( decls ); + if (elsepart) elsepart->gatherVarUsage( decls ); +} + + +void chillAST_IfStmt::gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ) { + cond->gatherArrayRefs( refs, 0 ); // 0 ?? + thenpart->gatherArrayRefs( refs, 0 ); // 0 ?? + if (elsepart) elsepart->gatherArrayRefs( refs, 0 ); // 0 ?? +} + +void chillAST_IfStmt::gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + cond->gatherScalarRefs( refs, 0 ); // 0 ?? + thenpart->gatherScalarRefs( refs, 0 ); // 0 ?? + if (elsepart) elsepart->gatherScalarRefs( refs, 0 ); // 0 ?? +} + + +chillAST_node *chillAST_IfStmt::constantFold() { + if (cond) cond = cond->constantFold(); + if (thenpart) thenpart = thenpart->constantFold(); + if (elsepart) elsepart = elsepart->constantFold(); + return this; +} + +void chillAST_IfStmt::gatherStatements(std::vector<chillAST_node*> &statements ){ + + //print(); printf("\n"); fflush(stdout); + thenpart->gatherStatements( statements ); + //fprintf(stderr, "ifstmt, after then, %d statements\n", statements.size()); + if (elsepart){ + //fprintf(stderr, "there is an elsepart of type %s\n", elsepart->getTypeString()); + elsepart->gatherStatements( statements ); + } + //fprintf(stderr, "ifstmt, after else, %d statements\n", statements.size()); +} + + + +chillAST_node *chillAST_IfStmt::clone() { + chillAST_node *c, *t, *e; + c = t = e = NULL; + if (cond) c = cond->clone(); // has to be one, right? + if (thenpart) t = thenpart->clone(); + if (elsepart) e = elsepart->clone(); + + chillAST_IfStmt *IS = new chillAST_IfStmt( c, t, e, parent); + IS->isFromSourceFile = isFromSourceFile; + if (filename) IS->filename = strdup(filename); + return IS; +} + + + +void chillAST_IfStmt::dump( int indent, FILE *fp ) { + chillindent(indent, fp); + fprintf(fp, "(if "); + fprintf(fp, "\n"); + + cond->dump(indent+1, fp); + fprintf(fp, "\n"); + + thenpart->dump(indent+1, fp); + fprintf(fp, "\n"); + + if (elsepart) { + elsepart->dump(indent+1, fp); + fprintf(fp, "\n"); + } + chillindent(indent, fp); + fprintf(fp, ")\n"); +} + + + +void chillAST_IfStmt::print(int indent, FILE *fp ) { + printPreprocBEFORE(indent, fp); + chillindent(indent, fp); + fprintf(fp, "if ("); + if (cond) cond->print(0, fp); + else fprintf(fp, "(NULL cond)"); + + bool needbracket = true; + if (thenpart) { + if (thenpart->isBinaryOperator()) needbracket = false; + if (thenpart->isCompoundStmt()) { // almost always true + chillAST_CompoundStmt *CS = (chillAST_CompoundStmt*) thenpart; + if (CS->children.size() == 1 && CS->children[0]->isBinaryOperator()) needbracket = false; + } + + if(needbracket) fprintf(fp, ") {\n"); + else fprintf(fp, ")\n"); + + thenpart->print(indent+1, fp); // end of line + + if(needbracket) { + //fprintf(fp, "\n"); + chillindent(indent, fp); + fprintf(fp, "}\n"); + } + } + else fprintf(fp, "(NULL thenpart)"); + + + needbracket = true; + if (elsepart) { + if (elsepart->isBinaryOperator()) needbracket = false; + if (elsepart->isCompoundStmt()) { // almost always true + chillAST_CompoundStmt *CS = (chillAST_CompoundStmt*) elsepart; + + if (CS->children.size() == 1 && CS->children[0]->isBinaryOperator()) needbracket = false; + + } + + fprintf(fp, "\n"); + chillindent(indent, fp); + + if (needbracket) fprintf(fp, "else {\n"); + else fprintf(fp, "else\n"); + + elsepart->print(indent+1, fp); + + if(needbracket) { + fprintf(fp, "\n"); + chillindent(indent, fp); + fprintf(fp, "}\n"); + } + } + //else fprintf(fp, "else { /* NOTHING */ }"); +} + + + +bool chillAST_IfStmt::findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync ) { + thenpart->findLoopIndexesToReplace( symtab ); + elsepart->findLoopIndexesToReplace( symtab ); + return false; // ?? +} + + + +chillAST_node *lessthanmacro( chillAST_node *left, chillAST_node *right) { + + chillAST_ParenExpr *lp1 = new chillAST_ParenExpr( left ); + chillAST_ParenExpr *rp1 = new chillAST_ParenExpr( right ); + chillAST_BinaryOperator *cond = new chillAST_BinaryOperator( lp1, "<", rp1 ); + + chillAST_ParenExpr *lp2 = new chillAST_ParenExpr( left ); + chillAST_ParenExpr *rp2 = new chillAST_ParenExpr( right ); + + chillAST_TernaryOperator *t = new chillAST_TernaryOperator("?", cond, lp2, rp2); + + return t; +} + + + + +// look for function declaration with a given name, in the tree with root "node" +void findFunctionDeclRecursive( chillAST_node *node, const char *procname, vector<chillAST_FunctionDecl*>& funcs ) +{ + //fprintf(stderr, "findmanually() CHILL AST node of type %s\n", node->getTypeString()); + + if (node->isFunctionDecl()) { + char *name = ((chillAST_FunctionDecl *) node)->functionName; // compare name with desired name + //fprintf(stderr, "node name 0x%x ", name); + //fprintf(stderr, "%s procname ", name); + //fprintf(stderr, "0x%x ", procname); + //fprintf(stderr, "%s\n", procname); + if (!strcmp( name, procname)) { + //fprintf(stderr, "found procedure %s\n", procname ); + funcs.push_back( (chillAST_FunctionDecl*) node ); // this is it + // quit recursing. probably not correct in some horrible case + return; + } + //else fprintf(stderr, "this is not the function we're looking for\n"); + } + + + // this is where the children can be used effectively. + // we don't really care what kind of node we're at. We just check the node itself + // and then its children is needed. + + int numc = node->children.size(); + fprintf(stderr, "(top)node has %d children\n", numc); + + for (int i=0; i<numc; i++) { + if (node->isSourceFile()) { + fprintf(stderr, "node of type %s is recursing to child %d of type %s\n", node->getTypeString(), i, node->children[i]->getTypeString()); + if (node->children[i]->isFunctionDecl()) { + chillAST_FunctionDecl *fd = (chillAST_FunctionDecl*) node->children[i]; + fprintf(stderr, "child %d is functiondecl %s\n", i, fd->functionName); + } + } + findFunctionDeclRecursive( node->children[i], procname, funcs ); + + } + return; +} + + +chillAST_FunctionDecl *findFunctionDecl( chillAST_node *node, const char *procname) +{ + vector<chillAST_FunctionDecl*> functions; + findFunctionDeclRecursive( node, procname, functions ); + + if ( functions.size() == 0 ) { + fprintf(stderr, "could not find function named '%s'\n", procname); + exit(-1); + } + + if ( functions.size() > 1 ) { + fprintf(stderr, "oddly, found %d functions named '%s'\n", functions.size(), procname); + fprintf(stderr, "I am unsure what to do\n"); + + for (int f = 0; f < functions.size(); f++) { + fprintf(stderr, "function %d %p %s\n", f, functions[f], functions[f]->functionName); + } + exit(-1); + } + + //fprintf(stderr, "found the procedure named %s\n", procname); + return functions[0]; +} + + +chillAST_SymbolTable *addSymbolToTable( chillAST_SymbolTable *st, chillAST_VarDecl *vd ) // definition +{ + chillAST_SymbolTable *s = st; + if (!s) s = new chillAST_SymbolTable; + + int tablesize = s->size(); + + for (int i=0; i<tablesize; i++) { + if ((*s)[i] == vd) { + //fprintf(stderr, "the exact same symbol, not just the same name, was already there\n"); + return s; // already there + } + } + + for (int i=0; i<tablesize; i++) { + //fprintf(stderr, "name %s vs name %s\n", (*s)[i]->varname, vd->varname); + if (!strcmp( (*s)[i]->varname, vd->varname)) { + //fprintf(stderr, "symbol with the same name was already there\n"); + return s; // already there + } + } + + //fprintf(stderr, "adding %s %s to a symbol table that didn't already have it\n", vd->vartype, vd->varname); + + //printf("before:\n"); + //printSymbolTable( s ); fflush(stdout); + + s->push_back(vd); // add it + + //printf("after:\n"); + //printSymbolTable( s ); fflush(stdout); + return s; +} + + +chillAST_TypedefTable *addTypedefToTable( chillAST_TypedefTable *tdt, chillAST_TypedefDecl *td ) +{ + + chillAST_TypedefTable *t = tdt; + if (!t) t = new chillAST_TypedefTable; + + int tablesize = t->size(); + + for (int i=0; i<tablesize; i++) { + if ((*t)[i] == td) return t; // already there + } + t->push_back(td); // add it + return t; +} + + +chillAST_NoOp::chillAST_NoOp( chillAST_node *p ) { + parent = p; + isFromSourceFile = true; // default + filename = NULL; +}; // so we have SOMETHING for NoOp in the cc file ??? + + +chillAST_Preprocessing::chillAST_Preprocessing() { + position = CHILL_PREPROCESSING_POSITIONUNKNOWN; + pptype = CHILL_PREPROCESSING_TYPEUNKNOWN; + blurb = strdup(""); // never use null. ignore the leak ?? +} + + + chillAST_Preprocessing::chillAST_Preprocessing(CHILL_PREPROCESSING_POSITION pos, + CHILL_PREPROCESSING_TYPE t, + char *text ) + { + position = pos; + pptype = t; + blurb = strdup( text ); + } + +void chillAST_Preprocessing::print( int indent, FILE *fp ) { // probably very wrong + if (position == CHILL_PREPROCESSING_LINEAFTER ) { + fprintf(fp, "\n"); + chillindent(indent, fp); + } + if (position == CHILL_PREPROCESSING_LINEBEFORE) { // ??? + //fprintf(fp, "\n"); + chillindent(indent, fp); + } + + fprintf(fp, "%s", blurb); + + if (position == CHILL_PREPROCESSING_TOTHERIGHT) { + fprintf(fp, "\n"); + } + + + if (position == CHILL_PREPROCESSING_LINEBEFORE) { + //fprintf(fp, "\n"); // comment seems to have \n at the end already + //chillindent(indent, fp); + } + + + //if (pptype != CHILL_PREPROCESSING_IMMEDIATELYBEFORE && pptype != CHILL_PREPROCESSING_UNKNOWN) fprint(fp, "\n"); + + } diff --git a/src/chillmodule.cc b/src/chillmodule.cc index b347570..291cb51 100644 --- a/src/chillmodule.cc +++ b/src/chillmodule.cc @@ -10,7 +10,6 @@ #include <omega.h> #include "loop.hh" #include "ir_code.hh" -#include "ir_rose.hh" #include "chillmodule.hh" @@ -81,11 +80,6 @@ static void init_loop(int loop_num_start, int loop_num_end) { } else { if (ir_code == NULL) { - if (procedure_name.empty()) - procedure_name = "main"; - - ir_code = new IR_roseCode(source_filename.c_str(), procedure_name.c_str()); - IR_Block *block = ir_code->GetCode(); ir_controls = ir_code->FindOneLevelControlStructure(block); for (int i = 0; i < ir_controls.size(); i++) { @@ -37,15 +37,22 @@ std::ostream& operator<<(std::ostream &os, const DependenceVector &d) { switch (d.type) { case DEP_W2R: - os << "true"; + os << "flow"; + // Check for reduction implemetation correctness if (d.is_reduction) os << "_reduction"; break; case DEP_R2W: os << "anti"; + // TODO: Remove Check for reduction implemetation correctness + if (d.is_reduction) + os << "_reduction"; break; case DEP_W2W: os << "output"; + // TODO: Remove Check for reduction implemetation correctness + if (d.is_reduction) + os << "_reduction"; break; case DEP_R2R: os << "input"; @@ -94,6 +101,13 @@ std::ostream& operator<<(std::ostream &os, const DependenceVector &d) { return os; } +// DependenceVector::DependenceVector(int size): +// lbounds(std::vector<coef_t>(size, 0)), +// ubounds(std::vector<coef_t>(size, 0)) { +// src = NULL; +// dst = NULL; +// } + DependenceVector::DependenceVector(const DependenceVector &that) { if (that.sym != NULL) this->sym = that.sym->clone(); @@ -105,6 +119,7 @@ DependenceVector::DependenceVector(const DependenceVector &that) { quasi = that.quasi; is_scalar_dependence = that.is_scalar_dependence; is_reduction = that.is_reduction; + is_reduction_cand = that.is_reduction_cand; // Manu } DependenceVector &DependenceVector::operator=(const DependenceVector &that) { @@ -120,6 +135,7 @@ DependenceVector &DependenceVector::operator=(const DependenceVector &that) { quasi = that.quasi; is_scalar_dependence = that.is_scalar_dependence; is_reduction = that.is_reduction; + is_reduction_cand = that.is_reduction_cand; } return *this; } @@ -128,12 +144,18 @@ DependenceType DependenceVector::getType() const { } bool DependenceVector::is_data_dependence() const { - return (type == DEP_W2R || type == DEP_R2W || type == DEP_W2W - || type == DEP_R2R); + if (type == DEP_W2R || type == DEP_R2W || type == DEP_W2W + || type == DEP_R2R) + return true; + else + return false; } bool DependenceVector::is_control_dependence() const { - return type == DEP_CONTROL; + if (type == DEP_CONTROL) + return true; + else + return false; } bool DependenceVector::has_negative_been_carried_at(int dim) const { @@ -147,7 +169,10 @@ bool DependenceVector::has_negative_been_carried_at(int dim) const { if (lbounds[i] > 0 || ubounds[i] < 0) return false; - return lbounds[dim] < 0; + if (lbounds[dim] < 0) + return true; + else + return false; } @@ -162,7 +187,10 @@ bool DependenceVector::has_been_carried_at(int dim) const { if (lbounds[i] > 0 || ubounds[i] < 0) return false; - return (lbounds[dim] != 0) || (ubounds[dim] !=0); + if ((lbounds[dim] != 0) || (ubounds[dim] !=0)) + return true; + + return false; } bool DependenceVector::has_been_carried_before(int dim) const { @@ -243,14 +271,22 @@ bool DependenceVector::hasPositive(int dim) const { if (dim >= lbounds.size()) throw std::invalid_argument("invalid dependence dimension"); - return lbounds[dim] > 0; + if (lbounds[dim] > 0) + //av: changed from ubounds to lbounds may have side effects + return true; + else + return false; } bool DependenceVector::hasNegative(int dim) const { if (dim >= lbounds.size()) throw std::invalid_argument("invalid dependence dimension"); - return ubounds[dim] < 0; + if (ubounds[dim] < 0) + //av: changed from lbounds to ubounds may have side effects + return true; + else + return false; } bool DependenceVector::isCarried(int dim, omega::coef_t distance) const { @@ -269,13 +305,18 @@ bool DependenceVector::isCarried(int dim, omega::coef_t distance) const { if (dim >= lbounds.size()) return true; - return lbounds[dim] >= -distance && ubounds[dim] <= distance; + if (lbounds[dim] > distance) + return false; + else if (ubounds[dim] < -distance) + return false; + + return true; } bool DependenceVector::canPermute(const std::vector<int> &pi) const { if (pi.size() != lbounds.size()) throw std::invalid_argument( - "permute dimensionality do not match dependence space"); + "permute dimensionality do not match dependence space"); for (int i = 0; i < pi.size(); i++) { if (lbounds[pi[i]] > 0) @@ -316,10 +357,10 @@ std::vector<DependenceVector> DependenceVector::normalize() const { } std::vector<DependenceVector> DependenceVector::permute( - const std::vector<int> &pi) const { + const std::vector<int> &pi) const { if (pi.size() != lbounds.size()) throw std::invalid_argument( - "permute dimensionality do not match dependence space"); + "permute dimensionality do not match dependence space"); const int n = lbounds.size(); @@ -370,6 +411,60 @@ DependenceVector DependenceVector::reverse() const { return dv; } +// std::vector<DependenceVector> DependenceVector::matrix(const std::vector<std::vector<int> > &M) const { +// if (M.size() != lbounds.size()) +// throw std::invalid_argument("(non)unimodular transformation dimensionality does not match dependence space"); + +// const int n = lbounds.size(); +// DependenceVector dv; +// if (sym != NULL) +// dv.sym = sym->clone(); +// else +// dv.sym = NULL; +// dv.type = type; + +// for (int i = 0; i < n; i++) { +// assert(M[i].size() == n+1 || M[i].size() == n); + +// omega::coef_t lb, ub; +// if (M[i].size() == n+1) +// lb = ub = M[i][n]; +// else +// lb = ub = 0; + +// for (int j = 0; j < n; j++) { +// int c = M[i][j]; +// if (c == 0) +// continue; + +// if (c > 0) { +// if (lbounds[j] == -posInfinity) +// lb = -posInfinity; +// else if (lb != -posInfinity) +// lb += c * lbounds[j]; +// if (ubounds[j] == posInfinity) +// ub = posInfinity; +// else if (ub != posInfinity) +// ub += c * ubounds[j]; +// } +// else { +// if (ubounds[j] == posInfinity) +// lb = -posInfinity; +// else if (lb != -posInfinity) +// lb += c * ubounds[j]; +// if (lbounds[j] == -posInfinity) +// ub = posInfinity; +// else if (ub != posInfinity) +// ub += c * lbounds[j]; +// } +// } +// dv.lbounds.push_back(lb); +// dv.ubounds.push_back(ub); +// } +// dv.is_reduction = is_reduction; + +// return dv.normalize(); +// } //----------------------------------------------------------------------------- // Class: DependenceGraph @@ -411,6 +506,20 @@ DependenceGraph DependenceGraph::permute(const std::vector<int> &pi, return g; } +// DependenceGraph DependenceGraph::matrix(const std::vector<std::vector<int> > &M) const { +// DependenceGraph g; + +// for (int i = 0; i < vertex.size(); i++) +// g.insert(vertex[i].first); + +// for (int i = 0; i < vertex.size(); i++) +// for (EdgeList::const_iterator j = vertex[i].second.begin(); j != vertex[i].second.end(); j++) +// for (int k = 0; k < j->second.size(); k++) +// g.connect(i, j->first, j->second[k].matrix(M)); + +// return g; +// } + DependenceGraph DependenceGraph::subspace(int dim) const { DependenceGraph g; diff --git a/src/ir_clang.cc b/src/ir_clang.cc new file mode 100755 index 0000000..ba11ac5 --- /dev/null +++ b/src/ir_clang.cc @@ -0,0 +1,3239 @@ + + +/***************************************************************************** + Copyright (C) 2009-2010 University of Utah + All Rights Reserved. + +Purpose: +CHiLL's CLANG interface. +convert from CLANG AST to chill AST + +Notes: +Array supports mixed pointer and array type in a single declaration. + +History: +12/10/2010 LLVM/CLANG Interface created by Saurav Muralidharan. + *****************************************************************************/ + +#include <typeinfo> +#include <sstream> +#include "ir_clang.hh" +#include "loop.hh" +#include "chill_error.hh" + +#define DUMPFUNC(x, y) std::cerr << "In function " << x << "\n"; y->dump(); + +#include "clang/Frontend/FrontendActions.h" +#include <clang/CodeGen/CodeGenAction.h> +#include <clang/Frontend/CompilerInstance.h> +#include <clang/Frontend/CompilerInvocation.h> +#include <clang/Basic/DiagnosticOptions.h> +#include <clang/Frontend/TextDiagnosticPrinter.h> +#include <clang/AST/ASTContext.h> +#include <clang/AST/RecordLayout.h> +#include <clang/AST/Decl.h> +#include <clang/Parse/ParseAST.h> +#include <clang/Basic/TargetInfo.h> + +#include <llvm/ADT/IntrusiveRefCntPtr.h> +#include <llvm/Support/Host.h> + +#include "code_gen/CG_chillRepr.h" +#include "code_gen/CG_chillBuilder.h" +#include <vector> + +#include "chill_ast.hh" + +// TODO move to ir_clang.hh +// fwd declarations +chillAST_node * ConvertVarDecl( clang::VarDecl *D, chillAST_node * ); +chillAST_node * ConvertTypeDefDecl( clang::TypedefDecl *TDD, chillAST_node * ); +chillAST_node * ConvertRecordDecl( clang::RecordDecl *D, chillAST_node * ); +chillAST_node * ConvertDeclStmt( clang::DeclStmt *clangDS, chillAST_node * ); +chillAST_node * ConvertCompoundStmt( clang::CompoundStmt *clangCS, chillAST_node * ); +chillAST_node * ConvertFunctionDecl( clang::FunctionDecl *D , chillAST_node *); +chillAST_node * ConvertForStmt( clang::ForStmt *clangFS, chillAST_node * ); +chillAST_node * ConvertUnaryOperator( clang::UnaryOperator * clangU, chillAST_node *O ); +chillAST_node * ConvertBinaryOperator( clang::BinaryOperator * clangBO, chillAST_node *B ); +chillAST_node * ConvertArraySubscriptExpr( clang::ArraySubscriptExpr *clangASE, chillAST_node * ); +chillAST_node * ConvertDeclRefExpr( clang::DeclRefExpr * clangDRE, chillAST_node * ); +chillAST_node * ConvertIntegerLiteral( clang::IntegerLiteral *clangIL, chillAST_node * ); +chillAST_node * ConvertFloatingLiteral( clang::FloatingLiteral *clangFL, chillAST_node * ); +chillAST_node * ConvertImplicitCastExpr( clang::ImplicitCastExpr *clangICE, chillAST_node * ); +chillAST_node * ConvertCStyleCastExpr( clang::CStyleCastExpr *clangICE, chillAST_node * ); +chillAST_node * ConvertReturnStmt( clang::ReturnStmt *clangRS, chillAST_node * ); +chillAST_node * ConvertCallExpr( clang::CallExpr *clangCE , chillAST_node *); +chillAST_node * ConvertIfStmt( clang::IfStmt *clangIS , chillAST_node *); +chillAST_node * ConvertMemberExpr( clang::MemberExpr *clangME , chillAST_node *); + + +chillAST_node * ConvertTranslationUnit( clang::TranslationUnitDecl *TUD, char *filename ); +chillAST_node * ConvertGenericClangAST( clang::Stmt *s, chillAST_node * ); + + +std::vector<chillAST_VarDecl *> VariableDeclarations; +std::vector<chillAST_FunctionDecl *> FunctionDeclarations; + +using namespace clang; +using namespace clang::driver; +using namespace omega; +using namespace std; + + +static string binops[] = { + " ", " ", // BO_PtrMemD, BO_PtrMemI, // [C++ 5.5] Pointer-to-member operators. + "*", "/", "%", // BO_Mul, BO_Div, BO_Rem, // [C99 6.5.5] Multiplicative operators. + "+", "-", // BO_Add, BO_Sub, // [C99 6.5.6] Additive operators. + "<<", ">>", // BO_Shl, BO_Shr, // [C99 6.5.7] Bitwise shift operators. + "<", ">", "<=", ">=", // BO_LT, BO_GT, BO_LE, BO_GE, // [C99 6.5.8] Relational operators. + "==", "!=", // BO_EQ, BO_NE, // [C99 6.5.9] Equality operators. + "&", // BO_And, // [C99 6.5.10] Bitwise AND operator. + "??", // BO_Xor, // [C99 6.5.11] Bitwise XOR operator. + "|", // BO_Or, // [C99 6.5.12] Bitwise OR operator. + "&&", // BO_LAnd, // [C99 6.5.13] Logical AND operator. + "||", // BO_LOr, // [C99 6.5.14] Logical OR operator. + "=", "*=", // BO_Assign, BO_MulAssign, // [C99 6.5.16] Assignment operators. + "/=", "%=", // BO_DivAssign, BO_RemAssign, + "+=", "-=", // BO_AddAssign, BO_SubAssign, + "???", "???", // BO_ShlAssign, BO_ShrAssign, + "&&=", "???", // BO_AndAssign, BO_XorAssign, + "||=", // BO_OrAssign, + ","}; // BO_Comma // [C99 6.5.17] Comma operator. + + +static string unops[] = { + "++", "--", // [C99 6.5.2.4] Postfix increment and decrement + "++", "--", // [C99 6.5.3.1] Prefix increment and decrement + "@", "*", // [C99 6.5.3.2] Address and indirection + "+", "-", // [C99 6.5.3.3] Unary arithmetic + "~", "!", // [C99 6.5.3.3] Unary arithmetic + "__real", "__imag", // "__real expr"/"__imag expr" Extension. + "__extension" // __extension__ marker. +}; + +// forward defs +SourceManager * globalSRCMAN; // ugly. shame. + +char *splitTypeInfo( char *underlyingtype ); +void printsourceline( const char *filename, int line ); +void printlines( SourceLocation &S, SourceLocation &E, SourceManager *SRCMAN ); + +void PrintBinaryOperator( Stmt *s, SourceManager *SRCMAN, int level ); +void PrintDeclStmt( Stmt *s, SourceManager *SRCMAN, int level ); +void PrintALoop( Stmt *L, SourceManager *SRCMAN, int level ); +void PrintAUnaryOperator( Stmt *s, SourceManager *SRCMAN, int level ); +void PrintAnIfStmt( Stmt *s, SourceManager *SRCMAN, int level ); +void PrintCompoundStmt( Stmt *s, SourceManager *SRCMAN, int level ); +void PrintDeclRefExpr( Stmt *s, SourceManager *SRCMAN, int level ); +void PrintImplicitCastExpr( Stmt *s, SourceManager *SRCMAN, int level ); +void PrintReturnStmt( Stmt *s, SourceManager *SRCMAN, int level ); +void PrintStmt( Stmt *s, SourceManager *SRCMAN, int level ); + +void PrintAnIntegerLiteral( Stmt *I ); +void PrintAFloatingLiteral( Stmt *s ); + +void PrintFunctionDecl( FunctionDecl *D, SourceManager *SRCMAN, int level ); +void PrintTypeDefDecl( TypedefDecl *D, SourceManager *SRCMAN, int level ); +void PrintVarDecl( VarDecl *D, SourceManager *SRCMAN, int level ); + + + + + +void printlines( SourceLocation &S, SourceLocation &E, SourceManager *SRCMAN ) { + unsigned int startlineno = SRCMAN->getPresumedLineNumber( S ); + unsigned int endlineno = SRCMAN->getPresumedLineNumber( E ); + const char *filename = SRCMAN->getBufferName( S ); + fprintf(stderr, "\n"); + for (int l=startlineno; l<= endlineno; l++) printsourceline( filename, l); +} + + +void Indent( int level ) { + for (int i=0; i<level; i++) fprintf(stderr, " "); +} + + +// really slow and bad. but I'm debugging +void printsourceline( const char *filename, int line ) +{ + FILE *fp = fopen (filename, "r"); + + // Now read lines up to and including the line we want. + char buf[10240]; + int l = 0; + while (l < line) { + if (fgets (buf, sizeof(buf), fp)) + ++l; + else + break; + } + fclose(fp); + + fprintf(stderr, "* %s", buf); +} + + + +void PrintBinaryOperator( Stmt *s, SourceManager *SRCMAN, int level ) { // SOMETIMES SHOULD HAVE ; + return + //rintf(stderr, "\nBinaryOperator(%d) ", level); + BinaryOperator *b = cast<BinaryOperator>(s); + + BinaryOperator::Opcode op = b->getOpcode(); + Expr *lhs = b->getLHS(); + Expr *rhs = b->getRHS(); + + //fprintf(stderr, "binaryoperator lhs has type %s\n", lhs->getStmtClassName()); + //fprintf(stderr, "binaryoperator rhs has type %s\n\n", rhs->getStmtClassName()); + + PrintStmt( lhs, SRCMAN, level+1 ); + fprintf(stderr, " %s ", binops[op].c_str()); + PrintStmt( rhs, SRCMAN, level+1); + if (level == 1) fprintf(stderr, ";\n"); +} + + + +void PrintDeclStmt( Stmt *s, SourceManager *SRCMAN, int level ) { + fprintf(stderr, "\nDeclaration Statement(%d)", level); + DeclStmt *D = cast<DeclStmt>(s); + + //QualType QT = D->getType(); + //string TypeStr = QT.getAsString(); + //fprintf(stderr, "type %s\n", TypeStr,c_str()); + + //SourceLocation S = D->getStartLoc(); + //SourceLocation E = D->getEndLoc(); + //printlines(S, E, SRCMAN); + + if (D->isSingleDecl()) { + fprintf(stderr, "this is a single definition\n"); + Decl *d = D->getSingleDecl(); + } + else { + fprintf(stderr, "this is NOT a single definition\n"); + DeclGroupRef dg = D->getDeclGroup(); + } + + for (DeclStmt::decl_iterator DI = D->decl_begin(), DE = D->decl_end(); DI != DE; ++DI) { + //fprintf(stderr, "a def\n"); + Decl *d = *DI; + //fprintf(stderr, "\nstatement of type %s\n", d->getStmtClassName()); + //std::cout << (void *) d << "?"; + if (ValueDecl *VD = dyn_cast<ValueDecl>(d)) { + if (VarDecl *V = dyn_cast<VarDecl>(VD)) { + if (V->getStorageClass() != SC_None) { + fprintf(stderr, "%s ", VarDecl::getStorageClassSpecifierString(V->getStorageClass())); + } + // else fprintf(stderr, "no storage class? "); + + QualType T = V->getType(); + string TypeStr = T.getAsString(); + std::string Name = VD->getNameAsString(); + //VD->getType().getAsStringInternal(Name, + // PrintingPolicy(VD->getASTContext().getLangOpts())); + fprintf(stderr,"%s %s ", TypeStr.c_str(), Name.c_str()); + // If this is a vardecl with an initializer, emit it. + if (Expr *E = V->getInit()) { + fprintf(stderr, " = "); + + Stmt *s = dyn_cast<Stmt>(E); + PrintStmt(s, SRCMAN, level+1); + //fprintf(stderr, ";\n"); + + } + + } + + } + if (level <= 1) fprintf(stderr, ";\n"); // TODO wrong + + } // for each actual declaration +} + + + + + + +void PrintAFloatingLiteral( Stmt *s ) { + FloatingLiteral *F = dyn_cast<FloatingLiteral>(s); + fprintf(stderr, "%f", F->getValueAsApproximateDouble()); // TODO approximate? +} + + + + +void PrintALoop( Stmt *L, SourceManager *SRCMAN, int level ) { + //fprintf(stderr, "\nA LOOP L=0x%x SRCMAN 0x%x", L, &SRCMAN); + ForStmt *ForStatement = cast<ForStmt>(L); + + SourceLocation srcloc = ForStatement->getForLoc(); + unsigned int lineno = SRCMAN->getPresumedLineNumber( srcloc ); + const char *filename = SRCMAN->getBufferName( srcloc ); + //fprintf(stderr, " in file %s at line %d ", filename, lineno); + //printsourceline( filename, lineno); + + Stmt *init = ForStatement->getInit(); + Expr *cond = ForStatement->getCond(); + Expr *incr = ForStatement->getInc(); + Stmt *body = ForStatement->getBody(); + + fprintf(stderr, "for ("); + PrintStmt(init, SRCMAN, 0); + fprintf(stderr, "; "); + PrintStmt(cond, SRCMAN, 0); + fprintf(stderr, "; "); + PrintStmt(incr, SRCMAN, 0); + fprintf(stderr, " )\n"); + Indent(level); + fprintf(stderr, "{\n"); + PrintStmt(body, SRCMAN, level+1); + fprintf(stderr, "}\n\n"); + +} + + +void PrintAUnaryOperator( Stmt *s, SourceManager *SRCMAN, int level ) { + //fprintf(stderr, "UnaryOperator "); + UnaryOperator *u = cast<UnaryOperator>(s); + + const char *op = unops[u->getOpcode()].c_str(); + + if (u->isPrefix()) { + fprintf(stderr, "%s", op ); + } + + PrintStmt( u->getSubExpr(), SRCMAN, level+1 ); + + if (u->isPostfix()) { + fprintf(stderr, "%s", op ); + } +} + + + +void PrintAnIfStmt( Stmt *s, SourceManager *SRCMAN, int level ) { + //fprintf(stderr, "an IF statement\n"); + // SourceLocation S = s->getLocStart(); + // SourceLocation E = s->getLocEnd(); + // printlines( S, E, SRCMAN); + + IfStmt *IfStatement = cast<IfStmt>(s); + + Stmt *Cond = IfStatement->getCond(); + Stmt *Then = IfStatement->getThen(); + Stmt *Else = IfStatement->getElse(); + + fprintf(stderr, "if ("); + PrintStmt(Cond, SRCMAN, level+1); + fprintf(stderr, ") {\n"); + PrintStmt(Then, SRCMAN, level+1); + fprintf(stderr, "\n}\nelse\n{\n"); + PrintStmt(Else, SRCMAN, level+1); + fprintf(stderr, "\n}\n\n"); +} + + + +void PrintAnIntegerLiteral( Stmt *s ) { + IntegerLiteral *I = dyn_cast<IntegerLiteral>(s); + bool isSigned = I->getType()->isSignedIntegerType(); + fprintf(stderr, "%s", I->getValue().toString(10, isSigned).c_str()); +} + + + +void PrintArraySubscriptExpr( Stmt *s, SourceManager *SRCMAN, int level ) { + ArraySubscriptExpr *ASE = dyn_cast<ArraySubscriptExpr>(s); + + Expr *Base = ASE->getBase(); + Expr *Index = ASE->getIdx(); + + PrintStmt(Base, SRCMAN, level+1); + fprintf(stderr, "["); + PrintStmt(Index, SRCMAN, level+1); + fprintf(stderr, "]"); +} + + +void PrintCompoundStmt( Stmt *s, SourceManager *SRCMAN, int level ) { + //fprintf(stderr, "\nCompoundStmt(%d)", level); + CompoundStmt *cs = dyn_cast<CompoundStmt>(s); + int numchildren=cs->size(); + //fprintf(stderr, "CompoundStmt has %d children\n", numchildren); + + +#ifdef DEBUGGING +BUH + for (Stmt::child_range I = cs->children(); I; ++I) { + const char *classname = I->getStmtClassName(); + if (!strcmp(classname, "BinaryOperator")) { + BinaryOperator *b = cast<BinaryOperator>(*I); + BinaryOperator::Opcode op = b->getOpcode(); + if (op == BO_Assign) { + fprintf(stderr, "compound statement has child of type ASSIGNMENT STATEMENT "); + SourceLocation S = I->getLocStart(); + SourceLocation E = I->getLocEnd(); + unsigned int startlineno = SRCMAN->getPresumedLineNumber( S ); + unsigned int endlineno = SRCMAN->getPresumedLineNumber( E ); + fprintf(stderr, "(%d-%d)\n", startlineno, endlineno ); + } + else + fprintf(stderr, "compound statement has child of type %s\n", I->getStmtClassName()); + } + else + fprintf(stderr, "compound statement has child of type %s\n", I->getStmtClassName()); + } +#endif // debugging + + + + for (auto I = cs->child_begin(); I!=cs->child_end(); ++I) { + Stmt *child = *I; + PrintStmt( child, SRCMAN, level ); // NOTE not level + 1 + + fprintf(stderr, "\n"); // ***\n\n"); + } + +} + + + + +void PrintDeclRefExpr( Stmt *s, SourceManager *SRCMAN, int level ) { + DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(s); + + //if (NestedNameSpecifier *Qualifier = DRE->getQualifier()) + // Qualifier->print( raw_ostream nonstandard of course ); + DeclarationNameInfo DNI = DRE->getNameInfo(); + DeclarationName DN = DNI.getName(); + fprintf(stderr, "%s", DN.getAsString().c_str()); + +} + + + +void PrintFunctionDecl( FunctionDecl *D, SourceManager *SRCMAN, int level ) { + //rintf(stderr, "\nFunctionDecl(%d) %s\n", level, D->getNameInfo().getAsString().c_str()); + // Type name as string + QualType QT = D->getReturnType(); + string TypeStr = QT.getAsString(); + + // Function name + DeclarationName DeclName = D->getNameInfo().getName(); + string FuncName = DeclName.getAsString(); + //fprintf(stderr, "function %s has type %s ", FuncName.c_str(), TypeStr.c_str()); + + + fprintf(stderr, "\n%s %s(",TypeStr.c_str(), FuncName.c_str()); + + int numparams = D->getNumParams(); + //fprintf(stderr, "and %d parameters\n", numparams); + for (int i=0; i<numparams; i++) { + if (i) fprintf(stderr, ", "); + ParmVarDecl *clangVardecl = D->getParamDecl(i); + + // from DeclPrinter::VisitVarDecl(VarDecl *D) + StorageClass SCAsWritten = clangVardecl->getStorageClass(); + if (SCAsWritten != SC_None) { + fprintf(stderr, "%s ", VarDecl::getStorageClassSpecifierString(SCAsWritten)); + } + //else fprintf(stderr, "(no storage class?) "); + + QualType T = clangVardecl->getType(); + if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(clangVardecl)) + T = Parm->getOriginalType(); + + string Name = clangVardecl->getName(); + char *td = strdup(T.getAsString().c_str()); + fprintf(stderr, "td = '%s'\n", td); + char *arraypart = splitTypeInfo(td); + fprintf(stderr, "%s %s%s ", td, Name.c_str(), arraypart); + + } + + fprintf(stderr, ")\n{\n"); // beginning of function body + + Stmt *body = D->getBody(); + PrintStmt( body, SRCMAN, level+1); + fprintf(stderr, "}\n\n"); // end of function body +} + + +void PrintImplicitCastExpr( Stmt *s, SourceManager *SRCMAN, int level ) { + ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(s); + PrintStmt( ICE->getSubExpr(), SRCMAN, level+1); +} + + + +void PrintReturnStmt( Stmt *s, SourceManager *SRCMAN, int level ) { + ReturnStmt *r = dyn_cast<ReturnStmt>(s); + + fprintf(stderr, "return"); + if (r->getRetValue()) { + fprintf(stderr, " "); + PrintStmt( r->getRetValue(), SRCMAN, level+1); + } + fprintf(stderr, ";\n"); +} + + +void PrintStmt( Stmt *s, SourceManager *SRCMAN, int level ) { + //fprintf(stderr, "\nprint statement 0x%x of type %s\n", s, s->getStmtClassName()); + + + //fprintf(stderr, "*"); + //SourceLocation srcloc = s->getStartLoc(); + //unsigned int lineno = SRCMAN->getPresumedLineNumber( srcloc ); + //const char *filename = SRCMAN->getBufferName( srcloc ); + + //StmtClass getStmtClass() + if (isa<DeclStmt>(s)) { PrintDeclStmt(s, SRCMAN, level); + } else if (isa<FloatingLiteral>(s)) { PrintAFloatingLiteral(s ); + } else if (isa<IntegerLiteral>(s)) { PrintAnIntegerLiteral(s ); + } else if (isa<UnaryOperator>(s)) { PrintAUnaryOperator(s, SRCMAN, level); + } else if (isa<BinaryOperator>(s)) { PrintBinaryOperator(s, SRCMAN, level); + } else if (isa<ForStmt>(s)) { PrintALoop(s, SRCMAN, level); + } else if (isa<IfStmt>(s)) { PrintAnIfStmt(s, SRCMAN, level); + } else if (isa<CompoundStmt>(s)) { PrintCompoundStmt(s, SRCMAN, level); + } else if (isa<ImplicitCastExpr>(s)) { PrintImplicitCastExpr(s, SRCMAN, level); + } else if (isa<DeclRefExpr>(s)) { PrintDeclRefExpr(s, SRCMAN, level); + } else if (isa<ArraySubscriptExpr>(s)) {PrintArraySubscriptExpr(s, SRCMAN, level); + } else if (isa<ReturnStmt>(s)) { PrintReturnStmt(s, SRCMAN, level); + } else { + fprintf(stderr, "\nPrintStmt() UNHANDLED statement of type %s\n", s->getStmtClassName()); + exit(-1); + } + //int numchildren=0; + //for (Stmt::child_range I = s->children(); I; ++I, numchildren++) ; + //if (numchildren) fprintf(stderr, "has %d children\n", numchildren); + //if (numchildren) { + // for (Stmt::child_range I = s->children(); I; ++I + //} +} + + +void PrintTranslationUnit( TranslationUnitDecl *TUD, ASTContext &CTX ) { + // TUD derived from Decl and DeclContext + static DeclContext *DC = TUD->castToDeclContext( TUD ); + //SourceManager SM = CTX.getSourceManager(); + + for (DeclContext::decl_iterator DI = DC->decls_begin(), DE = DC->decls_end(); DI != DE; ++DI) { + Decl *D = *DI; + + if (isa<FunctionDecl>(D)) { //fprintf(stderr, "FunctionDecl\n"); + PrintFunctionDecl( dyn_cast<FunctionDecl>(D), &CTX.getSourceManager(), 0); + } + else if (isa<VarDecl>(D)) { //fprintf(stderr, "VarDecl\n"); + PrintVarDecl( dyn_cast<VarDecl>(D), &CTX.getSourceManager(), 0 ); + } + else if (isa<TypedefDecl>(D)) { //fprintf(stderr, "TypedefDecl\n"); + PrintTypeDefDecl( dyn_cast<TypedefDecl>(D), &CTX.getSourceManager(), 0 ); + } + else if (isa<TypeAliasDecl>(D)) { fprintf(stderr, "TypeAliasDecl\n"); + } + else { + fprintf(stderr, "\na declaration of type %s (%d) which I have no idea how to handle\n", D->getDeclKindName(), D->getKind()); + exit(-1); + } + + //else if (isa<TypedefNameDecl>(D)) { fprintf(stderr, "TypedefNameDecl\n");} + } +} + + +void PrintTypeDefDecl( TypedefDecl *D, SourceManager *SRCMAN, int level ) { + + /* internal typedefs do not have a source file and this will die! + SourceLocation S = D->getLocStart(); // NOT getStartLoc(), that's class DeclStmt + SourceLocation E = D->getLocEnd(); + unsigned int startlineno = SRCMAN->getPresumedLineNumber( S ); + unsigned int endlineno = SRCMAN->getPresumedLineNumber( E ); + const char *filename = SRCMAN-> etBufferName( S ); + fprintf(stderr, " in file %s at lines %d-%d", filename, startlineno, endlineno); + for (int l=startlineno; l<= endlineno; l++) printsourceline( filename, l); + */ + + // arrays suck + char *td = strdup( D->getUnderlyingType().getAsString().c_str()); + //fprintf(stderr, "td = '%s'\n", td); + char *arraypart = splitTypeInfo(td); + fprintf(stderr, "typedef %s %s%s;\n", td, D->getName().str().c_str(), arraypart); + + free(td); + free(arraypart); +} + + + +void PrintVarDecl( VarDecl *D, SourceManager *SRCMAN, int level ) { + // arrays suck + char *td = strdup( D->getType().getAsString().c_str()); // leak + //fprintf(stderr, "td = '%s'\n", td); + char *arraypart = splitTypeInfo(td); + fprintf(stderr, "%s %s%s", td, D->getName().str().c_str(), arraypart); + + Expr *Init = D->getInit(); + if (Init) { + //fprintf(stderr," = (TODO)"); + PrintStmt( Init, SRCMAN, level+1); + } + fprintf(stderr, ";\n"); + + free(td); + free(arraypart); +} //PrintVarDecl + + + + + + + + +chillAST_node * ConvertVarDecl( VarDecl *D, chillAST_node *p ) { + //fprintf(stderr, "\nConvertVarDecl()\n"); + //fprintf(stderr, "Decl has type %s\n", D->getDeclKindName()); + //PrintVarDecl( D, globalSRCMAN, 0 ); + + bool isParm = false; + + QualType T0 = D->getType(); + QualType T = T0; + if (ParmVarDecl *Parm = dyn_cast<ParmVarDecl>(D)) { // My GOD clang stinks + T = Parm->getOriginalType(); + isParm = true; + } + + // arrays suck + char *vartype = strdup( T.getAsString().c_str()); + //fprintf(stderr, "vartype = '%s' T0 '%s\n", vartype, T0.getAsString().c_str() ); + char *arraypart = splitTypeInfo(vartype); + //fprintf(stderr, "arraypart = '%s'\n", arraypart); + + + char *varname = strdup(D->getName().str().c_str()); + //fprintf(stderr, "VarDecl (clang 0x%x) for %s %s%s\n", D, vartype, varname, arraypart); + + chillAST_VarDecl * chillVD = new chillAST_VarDecl( vartype, varname, arraypart, (void *)D, p /* , initializer */ ); + + chillVD->isAParameter = isParm; + //fprintf(stderr, "\nthis is the vardecl\n"); + //chillVD->print(); printf("\n\n"); fflush(stdout); + + //clang::QualType qtyp = D->getType(); + //clang::Expr *e = D->getInit(); + //fprintf(stderr, "e 0x%x\n", e); + + //if (qtyp->isPointerType()) { + // fprintf(stderr, "pointer type\n"); + // clang::QualType ptyp = qtyp->getPointeeType(); + // fprintf(stderr, "%s\n", ptyp.getAsString().c_str()); + //} + + //if (qtyp->isArrayType()) fprintf(stderr, "Array type\n"); + //if (qtyp->isConstantArrayType()) fprintf(stderr, "constant array type\n"); + + //const clang::Type *typ = qtyp.getTypePtr(); + //clang::Expr *e = ((clang::VariableArrayType *)typ)->getSizeExpr(); + //e->dump(); + + + int numdim = 0; + chillVD-> knownArraySizes = true; + if (index(vartype, '*')) chillVD->knownArraySizes = false; // float *a; for example + if (index(arraypart, '*')) chillVD->knownArraySizes = false; + + // note: vartype here, arraypart in next code.. is that right? + if (index(vartype, '*')) { + for (int i = 0; i<strlen(vartype); i++) if (vartype[i] == '*') numdim++; + //fprintf(stderr, "numd %d\n", numd); + chillVD->numdimensions = numdim; + } + + if (index(arraypart, '[')) { // JUST [12][34][56] no asterisks + char *dupe = strdup(arraypart); + + int len = strlen(arraypart); + for (int i=0; i<len; i++) if (dupe[i] == '[') numdim++; + + //fprintf(stderr, "numdim %d\n", numdim); + + chillVD->numdimensions = numdim; + int *as = (int *)malloc(sizeof(int *) * numdim ); + if (!as) { + fprintf(stderr, "can't malloc array sizes in ConvertVarDecl()\n"); + exit(-1); + } + chillVD->arraysizes = as; // 'as' changed later! + + + char *ptr = dupe; + //fprintf(stderr, "dupe '%s'\n", ptr); + while (ptr = index(ptr, '[')) { + ptr++; + //fprintf(stderr, "tmp '%s'\n", ptr); + int dim; + sscanf(ptr, "%d", &dim); + //fprintf(stderr, "dim %d\n", dim); + *as++ = dim; + + ptr = index(ptr, ']'); + //fprintf(stderr, "bottom of loop, ptr = '%s'\n", ptr); + } + free(dupe); + //for (int i=0; i<numdim; i++) { + // fprintf(stderr, "dimension %d = %d\n", i, chillVD->arraysizes[i]); + //} + + //fprintf(stderr, "need to handle [] array to determine num dimensions\n"); + //exit(-1); + } + + Expr *Init = D->getInit(); + if (Init) { + fprintf(stderr," = VARDECL HAS INIT. (TODO) (RIGHT NOW)"); exit(-1); + } + //fprintf(stderr, ";\n"); + + + //fprintf(stderr, "calling chillVD->print()\n"); + //chillVD->print(); // debugging only + + free (vartype); + free (varname); + + // store this away for declrefexpr that references it! + VariableDeclarations.push_back(chillVD); + return chillVD; +} + + + +chillAST_node * ConvertRecordDecl( clang::RecordDecl *RD, chillAST_node *p ) { // for structs and unions + + //fprintf(stderr, "ConvertRecordDecl( )\n\nclang sees\n"); + //RD->dump(); + //fflush(stdout); + //fprintf(stderr, "\n"); + + //fprintf(stderr, "%s with name %s\n", ((clang::Decl *)RD)->getDeclKindName(), RD->getNameAsString().c_str()); + //const clang::ASTRecordLayout RL = RD->getASTContext().getASTRecordLayout( RD ); + //RD->getASTContext().DumpRecordLayout( RD , cout ); + + int count = 0; + for (clang::RecordDecl::field_iterator fi = RD->field_begin(); fi != RD->field_end(); fi++) count++; + //fprintf(stderr, "%d fields in this struct/union\n", count); + + char blurb[128]; + sprintf(blurb, "struct %s", RD->getNameAsString().c_str()); + fprintf(stderr, "blurb is '%s'\n", blurb); + + chillAST_TypedefDecl *astruct = new chillAST_TypedefDecl( blurb, "", p); + astruct->setStruct( true ); + astruct->setStructName( RD->getNameAsString().c_str() ); + + for (clang::RecordDecl::field_iterator fi = RD->field_begin(); fi != RD->field_end(); fi++) { + clang::FieldDecl *FD = (*fi); + FD->dump(); printf(";\n"); fflush(stdout); + string TypeStr = FD->getType().getAsString(); + + const char *typ = TypeStr.c_str(); + const char *name = FD->getNameAsString().c_str(); + fprintf(stderr, "(typ) %s (name) %s\n", typ, name); + + chillAST_VarDecl *VD = NULL; + // very clunky and incomplete + VD = new chillAST_VarDecl( typ, name, "", astruct ); // can't handle arrays yet + + astruct->subparts.push_back(VD); + } + + + fprintf(stderr, "I just defined a struct\n"); + astruct->print(0, stderr); + + return astruct; +} + + + + + + + +chillAST_node * ConvertTypeDefDecl( TypedefDecl *TDD, chillAST_node *p ) { + //fprintf(stderr, "ConvertTypedefDecl( ) \n"); + //fprintf(stderr, "TDD has type %s\n", TDD->getDeclKindName()); + //TDD->dump(); fprintf(stderr, "\n"); + + char *under = strdup( TDD->getUnderlyingType().getAsString().c_str()); + //fprintf(stderr, "under = '%s'\n", under); + char *arraypart = splitTypeInfo(under); + //fprintf(stderr, "typedef %s %s%s;\n", under, TDD->getName().str().c_str(), arraypart); + // fprintf(stderr, "len arraypart = %d\n", strlen(arraypart)); + char *alias = strdup(TDD->getName().str().c_str()); + + //fprintf(stderr, "underlying type %s arraypart '%s' name %s\n", under, arraypart, TDD->getName().str().c_str() ); + chillAST_TypedefDecl *CTDD = new chillAST_TypedefDecl( under, alias, arraypart, p ); + + free(under); + free(arraypart); + + return CTDD; +} + + + +chillAST_node * ConvertDeclStmt( DeclStmt *clangDS, chillAST_node *p ) { + //fprintf(stderr, "ConvertDeclStmt()\n"); + + chillAST_VarDecl *chillvardecl; // the thing we'll return if this is a single declaration + + bool multiples = !clangDS->isSingleDecl(); + if ( multiples) { + //fprintf(stderr, "ir_clang.cc multiple declarations in a single CLANG DeclStmt not really handled! (??)\n"); + // for now, try to make the multiple decls into a compoundstmt with them inside. + // if we don't get scoping problems, this might work + } + + DeclGroupRef dgr = clangDS->getDeclGroup(); + clang::DeclGroupRef::iterator DI = dgr.begin(); + clang::DeclGroupRef::iterator DE = dgr.end(); + + for ( ; DI != DE; ++DI) { + Decl *D = *DI; + const char *declty = D->getDeclKindName(); + //fprintf(stderr, "a decl of type %s\n", D->getDeclKindName()); + + if (!strcmp("Var", declty)) { + VarDecl *V = dyn_cast<VarDecl>(D); + // ValueDecl *VD = dyn_cast<ValueDecl>(D); // not needed? + std::string Name = V->getNameAsString(); + char *varname = strdup( Name.c_str()); + + //fprintf(stderr, "variable named %s\n", Name.c_str()); + QualType T = V->getType(); + string TypeStr = T.getAsString(); + char *vartype = strdup( TypeStr.c_str()); + + //fprintf(stderr, "%s %s\n", td, varname); + char *arraypart = splitTypeInfo( vartype ); + + chillvardecl = new chillAST_VarDecl(vartype, varname, arraypart, (void *)D, p ); + //fprintf(stderr, "DeclStmt (clang 0x%x) for %s %s%s\n", D, vartype, varname, arraypart); + + // store this away for declrefexpr that references it! + VariableDeclarations.push_back(chillvardecl); + + if (multiples) p->addChild( chillvardecl ); + + // TODO + if (V->hasInit()) { + fprintf(stderr, " ConvertDeclStmt() UNHANDLED initialization\n"); + exit(-1); + } + } + } // for each of possibly multiple decls + + if (multiples) return NULL; // multiple decls added themselves already + return chillvardecl; // OR a single decl +} + + + +chillAST_node * ConvertCompoundStmt( CompoundStmt *clangCS, chillAST_node *p ) { + //fprintf(stderr, "ConvertCompoundStmt( )\n"); + int numchildren= clangCS->size(); + //fprintf(stderr, "clang CompoundStmt has %d children\n", numchildren); + + // make an empty CHILL compound statement + chillAST_CompoundStmt *chillCS = new chillAST_CompoundStmt; + chillCS->setParent( p ); + + // for each clang child + for (auto I = clangCS->child_begin(); I!=clangCS->child_end(); ++I) { // ?? loop looks WRONG + // create the chill ast for each child + Stmt *child = *I; + chillAST_node *n = ConvertGenericClangAST( child, chillCS ); + // usually n will be a statement. We just add it as a child. + // SOME DeclStmts have multiple declarations. They will add themselves and return NULL + if (n) chillCS->addChild( n ); + } + + return chillCS; +} + + + + +chillAST_node * ConvertFunctionDecl( FunctionDecl *D, chillAST_node *p ) { + //fprintf(stderr, "\nConvertFunctionDecl( )\n"); + QualType QT = D->getReturnType(); + string ReturnTypeStr = QT.getAsString(); + + // Function name + DeclarationName DeclName = D->getNameInfo().getName(); + string FuncName = DeclName.getAsString(); + //fprintf(stderr, "function %s has type %s ", FuncName.c_str(), ReturnTypeStr.c_str()); + //fprintf(stderr, "\n%s %s()\n", ReturnTypeStr.c_str(), FuncName.c_str()); + + chillAST_FunctionDecl *chillFD = new chillAST_FunctionDecl( ReturnTypeStr.c_str(), FuncName.c_str(), p, D); + + + int numparams = D->getNumParams(); + + //fprintf(stderr, "\nand %d parameters\n", numparams); + for (int i=0; i<numparams; i++) { + if (i) fprintf(stderr, ", "); + VarDecl *clangvardecl = D->getParamDecl(i); // the ith parameter (CLANG) + ParmVarDecl *pvd = D->getParamDecl(i); + QualType T = pvd->getOriginalType(); + fprintf(stderr, "OTYPE %s\n", T.getAsString().c_str()); + + chillAST_VarDecl *chillPVD = (chillAST_VarDecl *)ConvertVarDecl( clangvardecl, chillFD ) ; + //chillPVD->print(); fflush(stdout); + + //chillPVD->isAParameter = 1; + VariableDeclarations.push_back(chillPVD); + + chillFD->addParameter(chillPVD); + fprintf(stderr, "chillAST ParmVarDecl for %s from chill location 0x%x\n",chillPVD->varname, clangvardecl); + } // for each parameter + + + + //fprintf(stderr, ")\n{\n"); // beginning of function body + //if (D->isExternC()) { chillFD->setExtern(); fprintf(stderr, "%s is extern\n", FuncName.c_str()); }; + if (D->getBuiltinID()) { chillFD->setExtern(); fprintf(stderr, "%s is builtin (extern)\n", FuncName.c_str()); }; + + Stmt *clangbody = D->getBody(); + if (clangbody) { // may just be fwd decl or external, without an actual body + //fprintf(stderr, "body of type %s\n", clangbody->getStmtClassName()); + //chillAST_node *CB = ConvertCompoundStmt( dyn_cast<CompoundStmt>(clangbody) ); // always a compound statement? + chillAST_node *CB = ConvertGenericClangAST( clangbody, chillFD ); + //fprintf(stderr, "FunctionDecl body = 0x%x of type %s\n", CB, CB->getTypeString()); + chillFD->setBody ( CB ); + } + + //fprintf(stderr, "adding function %s 0x%x to FunctionDeclarations\n", chillFD->functionName, chillFD); + FunctionDeclarations.push_back(chillFD); + return chillFD; +} + + +chillAST_node * ConvertForStmt( ForStmt *clangFS, chillAST_node *p ) { + + Stmt *init = clangFS->getInit(); + Expr *cond = clangFS->getCond(); + Expr *incr = clangFS->getInc(); + Stmt *body = clangFS->getBody(); + + chillAST_node *ini = ConvertGenericClangAST( init, NULL ); + chillAST_node *con = ConvertGenericClangAST( cond, NULL); + chillAST_node *inc = ConvertGenericClangAST( incr, NULL); + chillAST_node *bod = ConvertGenericClangAST( body, NULL); + if (bod->asttype != CHILLAST_NODETYPE_COMPOUNDSTMT) { + //fprintf(stderr, "ForStmt body of type %s\n", bod->getTypeString()); + // make single statement loop bodies loop like other loops + chillAST_CompoundStmt *cs = new chillAST_CompoundStmt( ); + cs->addChild( bod ); + bod = cs; + } + + + chillAST_ForStmt *chill_loop = new chillAST_ForStmt( ini, con, inc, bod, p ); + ini->setParent( chill_loop ); + con->setParent( chill_loop ); + inc->setParent( chill_loop ); + bod->setParent( chill_loop ); + + return chill_loop; +} + + +chillAST_node * ConvertIfStmt( IfStmt *clangIS, chillAST_node *p ) { + Expr *cond = clangIS->getCond(); + Stmt *thenpart = clangIS->getThen(); + Stmt *elsepart = clangIS->getElse(); + + chillAST_node *con = ConvertGenericClangAST( cond, NULL); + chillAST_node *thn = NULL; + if (thenpart) thn = ConvertGenericClangAST( thenpart, NULL); + chillAST_node *els = NULL; + if (elsepart) els = ConvertGenericClangAST( elsepart, NULL); + + chillAST_IfStmt *ifstmt = new chillAST_IfStmt( con, thn, els, NULL); + return ifstmt; +} + + + +chillAST_node * ConvertUnaryOperator( UnaryOperator * clangUO, chillAST_node *p ) { + const char *op = unops[clangUO->getOpcode()].c_str(); + bool pre = clangUO->isPrefix(); + chillAST_node *sub = ConvertGenericClangAST( clangUO->getSubExpr(), NULL ); + + chillAST_UnaryOperator *chillUO = new chillAST_UnaryOperator( op, pre, sub, p ); + sub->setParent( chillUO ); + return chillUO; +} + + +chillAST_node * ConvertBinaryOperator( BinaryOperator * clangBO, chillAST_node *p ) { + + // get the clang parts + Expr *lhs = clangBO->getLHS(); + Expr *rhs = clangBO->getRHS(); + BinaryOperator::Opcode op = clangBO->getOpcode(); // this is CLANG op, not CHILL op + + + // convert to chill equivalents + chillAST_node *l = ConvertGenericClangAST( lhs, NULL ); + const char *opstring = binops[op].c_str(); + chillAST_node *r = ConvertGenericClangAST( rhs, NULL ); + // TODO chill equivalent for numeric op. + + // build up the chill Binary Op AST node + chillAST_BinaryOperator * binop = new chillAST_BinaryOperator( l, opstring, r, p ); + l->setParent( binop ); + r->setParent( binop ); + + return binop; +} + + + + +chillAST_node * ConvertArraySubscriptExpr( ArraySubscriptExpr *clangASE, chillAST_node *p ) { + + Expr *clangbase = clangASE->getBase(); + Expr *clangindex = clangASE->getIdx(); + //fprintf(stderr, "clang base: "); clangbase->dump(); fprintf(stderr, "\n"); + + chillAST_node *bas = ConvertGenericClangAST( clangbase, NULL ); + chillAST_node *indx = ConvertGenericClangAST( clangindex, NULL ); + + chillAST_ArraySubscriptExpr * chillASE = new chillAST_ArraySubscriptExpr( bas, indx, p, clangASE); + bas->setParent( chillASE ); + indx->setParent( chillASE ); + return chillASE; +} + + + +chillAST_node * ConvertDeclRefExpr( DeclRefExpr * clangDRE, chillAST_node *p ) { + DeclarationNameInfo DNI = clangDRE->getNameInfo(); + + ValueDecl *vd = static_cast<ValueDecl *>(clangDRE->getDecl()); // ValueDecl ?? VarDecl ?? + + QualType QT = vd->getType(); + string TypeStr = QT.getAsString(); + //fprintf(stderr, "\n\n*** type %s ***\n\n", TypeStr.c_str()); + //fprintf(stderr, "kind %s\n", vd->getDeclKindName()); + + DeclarationName DN = DNI.getName(); + const char *varname = DN.getAsString().c_str() ; + chillAST_DeclRefExpr * chillDRE = new chillAST_DeclRefExpr(TypeStr.c_str(), varname, p ); + + //fprintf(stderr, "clang DeclRefExpr refers to declaration of %s @ 0x%x\n", varname, vd); + //fprintf(stderr, "clang DeclRefExpr refers to declaration of %s of kind %s\n", varname, vd->getDeclKindName()); + + // find the definition (we hope) + if ( (!strcmp("Var", vd->getDeclKindName())) || (!strcmp("ParmVar", vd->getDeclKindName()))) { + // it's a variable reference + int numvars = VariableDeclarations.size(); + chillAST_VarDecl *chillvd = NULL; + for (int i=0; i<numvars; i++) { + if (VariableDeclarations[i]->uniquePtr == vd) { + chillvd = VariableDeclarations[i]; + //fprintf(stderr, "found it at variabledeclaration %d of %d\n", i, numvars); + } + } + if (!chillvd) { + fprintf(stderr, "\nWARNING, ir_clang.cc clang DeclRefExpr %s refers to a declaration I can't find! at ox%x\n", varname, vd); + fprintf(stderr, "variables I know of are:\n"); + for (int i=0; i<numvars; i++) { + chillAST_VarDecl *adecl = VariableDeclarations[i]; + if (adecl->isParmVarDecl()) fprintf(stderr, "(parameter) "); + fprintf(stderr, "%s %s at location 0x%x\n", adecl->vartype, adecl->varname, adecl->uniquePtr); + } + fprintf(stderr, "\n"); + } + + if (chillvd == NULL) { fprintf(stderr, "chillDRE->decl = 0x%x\n", chillvd); exit(-1); } + + chillDRE->decl = (chillAST_node *)chillvd; // start of spaghetti pointers ... + } + else if (!strcmp("Function", vd->getDeclKindName())) { + //fprintf(stderr, "declrefexpr of type Function\n"); + int numfuncs = FunctionDeclarations.size(); + chillAST_FunctionDecl *chillfd = NULL; + for (int i=0; i<numfuncs; i++) { + if (FunctionDeclarations[i]->uniquePtr == vd) { + chillfd = FunctionDeclarations[i]; + //fprintf(stderr, "found it at functiondeclaration %d of %d\n", i, numfuncs); + } + } + if (chillfd == NULL) { fprintf(stderr, "chillDRE->decl = 0x%x\n", chillfd); exit(-1); } + + chillDRE->decl = (chillAST_node *)chillfd; // start of spaghetti pointers ... + + } + else { + fprintf(stderr, "clang DeclRefExpr refers to declaration of %s of kind %s\n", varname, vd->getDeclKindName()); + fprintf(stderr, "chillDRE->decl = UNDEFINED\n"); + exit(-1); + } + + //fprintf(stderr, "%s\n", DN.getAsString().c_str()); + return chillDRE; +} + + + +chillAST_node * ConvertIntegerLiteral( IntegerLiteral *clangIL, chillAST_node *p ) { + bool isSigned = clangIL->getType()->isSignedIntegerType(); + //int val = clangIL->getIntValue(); + const char *printable = clangIL->getValue().toString(10, isSigned).c_str(); + int val = atoi( printable ); + //fprintf(stderr, "int value %s (%d)\n", printable, val); + chillAST_IntegerLiteral *chillIL = new chillAST_IntegerLiteral( val, p ); + return chillIL; +} + + +chillAST_node * ConvertFloatingLiteral( FloatingLiteral *clangFL, chillAST_node *p ) { + //fprintf(stderr, "\nConvertFloatingLiteral()\n"); + float val = clangFL->getValueAsApproximateDouble(); // TODO approx is a bad idea! + string WHAT; + SmallString<16> Str; + clangFL->getValue().toString( Str ); + const char *printable = Str.c_str(); + //fprintf(stderr, "literal %s\n", printable); + + SourceLocation sloc = clangFL->getLocStart(); + SourceLocation eloc = clangFL->getLocEnd(); + + std::string start = sloc.printToString( *globalSRCMAN ); + std::string end = eloc.printToString( *globalSRCMAN ); + //fprintf(stderr, "literal try2 start %s end %s\n", start.c_str(), end.c_str()); + //printlines( sloc, eloc, globalSRCMAN ); + unsigned int startlineno = globalSRCMAN->getPresumedLineNumber( sloc ); + unsigned int endlineno = globalSRCMAN->getPresumedLineNumber( eloc ); ; + const char *filename = globalSRCMAN->getBufferName( sloc ); + + std::string fname = globalSRCMAN->getFilename( sloc ); + //fprintf(stderr, "fname %s\n", fname.c_str()); + + if (filename && strlen(filename) > 0) {} // fprintf(stderr, "literal file '%s'\n", filename); + else { + fprintf(stderr, "\nConvertFloatingLiteral() filename is NULL?\n"); + + //sloc = globalSRCMAN->getFileLoc( sloc ); // should get spelling loc? + sloc = globalSRCMAN->getSpellingLoc( sloc ); // should get spelling loc? + //eloc = globalSRCMAN->getFileLoc( eloc ); + + start = sloc.printToString( *globalSRCMAN ); + //end = eloc.printToString( *globalSRCMAN ); + //fprintf(stderr, "literal try3 start %s end %s\n", start.c_str(), end.c_str()); + + startlineno = globalSRCMAN->getPresumedLineNumber( sloc ); + //endlineno = globalSRCMAN->getPresumedLineNumber( eloc ); ; + //fprintf(stderr, "start, end line numbers %d %d\n", startlineno, endlineno); + + filename = globalSRCMAN->getBufferName( sloc ); + + //if (globalSRCMAN->isMacroBodyExpansion( sloc )) { + // fprintf(stderr, "IS MACRO\n"); + //} + } + + unsigned int offset = globalSRCMAN->getFileOffset( sloc ); + //fprintf(stderr, "literal file offset %d\n", offset); + + FILE *fp = fopen (filename, "r"); + fseek(fp, offset, SEEK_SET); // go to the part of the file where the float is defined + + char buf[10240]; + fgets (buf, sizeof(buf), fp); // read a line starting where the float starts + fclose(fp); + + // buf has the line we want grab the float constant out of it + //fprintf(stderr, "\nbuf '%s'\n", buf); + char *ptr = buf; + if (*ptr == '-') ptr++; // ignore possible minus sign + int len = strspn(ptr, ".-0123456789f"); + buf[len] = '\0'; + //fprintf(stderr, "'%s'\n", buf); + + chillAST_FloatingLiteral *chillFL = new chillAST_FloatingLiteral( val, buf, p ); + + //chillFL->print(); printf("\n"); fflush(stdout); + return chillFL; +} + + +chillAST_node * ConvertImplicitCastExpr( ImplicitCastExpr *clangICE, chillAST_node *p ) { + //fprintf(stderr, "ConvertImplicitCastExpr()\n"); + CastExpr *CE = dyn_cast<ImplicitCastExpr>(clangICE); + //fprintf(stderr, "implicit cast of type %s\n", CE->getCastKindName()); + chillAST_node * sub = ConvertGenericClangAST( clangICE->getSubExpr(), p ); + chillAST_ImplicitCastExpr *chillICE = new chillAST_ImplicitCastExpr( sub, p ); + + //sub->setParent( chillICE ); // these 2 lines work + //return chillICE; + + //sub->setParent(p); // ignore the ImplicitCastExpr !! TODO (probably a bad idea) + return sub; + +} + + + + +chillAST_node * ConvertCStyleCastExpr( CStyleCastExpr *clangCSCE, chillAST_node *p ) { + //fprintf(stderr, "ConvertCStyleCastExpr()\n"); + //fprintf(stderr, "C Style cast of kind "); + CastExpr *CE = dyn_cast<CastExpr>(clangCSCE); + //fprintf(stderr, "%s\n", CE->getCastKindName()); + + //clangCSCE->getTypeAsWritten().getAsString(Policy) + const char * towhat = strdup( clangCSCE->getTypeAsWritten().getAsString().c_str() ); + //fprintf(stderr, "before sub towhat (%s)\n", towhat); + + chillAST_node * sub = ConvertGenericClangAST( clangCSCE->getSubExprAsWritten(), NULL ); + //fprintf(stderr, "after sub towhat (%s)\n", towhat); + chillAST_CStyleCastExpr *chillCSCE = new chillAST_CStyleCastExpr( towhat, sub, p ); + //fprintf(stderr, "after CSCE towhat (%s)\n", towhat); + sub->setParent( chillCSCE ); + return chillCSCE; +} + + + + +chillAST_node * ConvertReturnStmt( ReturnStmt *clangRS, chillAST_node *p ) { + chillAST_node * retval = ConvertGenericClangAST( clangRS->getRetValue(), NULL ); // NULL is handled + //if (retval == NULL) fprintf(stderr, "return stmt returns nothing\n"); + + chillAST_ReturnStmt * chillRS = new chillAST_ReturnStmt( retval, p ); + if (retval) retval->setParent( chillRS ); + return chillRS; +} + + +chillAST_node * ConvertCallExpr( CallExpr *clangCE, chillAST_node *p ) { + //fprintf(stderr, "ConvertCallExpr()\n"); + + chillAST_node *callee = ConvertGenericClangAST( clangCE->getCallee(), NULL ); + //fprintf(stderr, "callee is of type %s\n", callee->getTypeString()); + + //chillAST_node *next = ((chillAST_ImplicitCastExpr *)callee)->subexpr; + //fprintf(stderr, "callee is of type %s\n", next->getTypeString()); + + chillAST_CallExpr *chillCE = new chillAST_CallExpr( callee, p ); + callee->setParent( chillCE ); + + int numargs = clangCE->getNumArgs(); + //fprintf(stderr, "CallExpr has %d args\n", numargs); + Expr **clangargs = clangCE->getArgs(); + for (int i=0; i<numargs; i++) { + chillCE->addArg( ConvertGenericClangAST( clangargs[i], chillCE ) ); + } + + return chillCE; +} + + +chillAST_node * ConvertParenExpr( ParenExpr *clangPE, chillAST_node *p ) { + chillAST_node *sub = ConvertGenericClangAST( clangPE->getSubExpr(), NULL); + chillAST_ParenExpr *chillPE = new chillAST_ParenExpr( sub, p); + sub->setParent( chillPE ); + + return chillPE; +} + + +chillAST_node * ConvertTranslationUnit( TranslationUnitDecl *TUD, char *filename ) { + //fprintf(stderr, "ConvertTranslationUnit( filename %s )\n\n", filename); + // TUD derived from Decl and DeclContext + static DeclContext *DC = TUD->castToDeclContext( TUD ); + + + // TODO this was to get the filename without having to pass it in + //ASTContext CTX = TUD->getASTContext (); + //SourceManager SM = CTX.getSourceManager(); + //SourceLocation srcloc = ForStatement->getForLoc(); + //unsigned int lineno = SRCMAN->getPresumedLineNumber( srcloc ); + //const char *filename = SRCMAN->getBufferName( srcloc ); + + + chillAST_SourceFile * topnode = new chillAST_SourceFile( filename ); + topnode->setFrontend("clang"); + topnode->chill_array_counter = 1; + topnode->chill_scalar_counter = 0; + + // now recursively build clang AST from the children of TUD + //for (DeclContext::decl_iterator DI = DC->decls_begin(), DE = DC->decls_end(); DI != DE; ++DI) + DeclContext::decl_iterator start = DC->decls_begin(); + DeclContext::decl_iterator end = DC->decls_end(); + for (DeclContext::decl_iterator DI=start; DI != end; ++DI) { + Decl *D = *DI; + + if (isa<FunctionDecl>(D)) { //fprintf(stderr, "\nTUD FunctionDecl\n"); + topnode->addChild( ConvertFunctionDecl( dyn_cast<FunctionDecl>(D), topnode )); + } + else if (isa<VarDecl>(D)) { //fprintf(stderr, "\nTUD VarDecl\n"); + topnode->addChild( ConvertVarDecl( dyn_cast<VarDecl>(D), topnode )); + //fflush(stdout); fprintf(stderr, "\nTUD VarDecl DONE\n"); + } + else if (isa<TypedefDecl>(D)) { //fprintf(stderr, "\nTUD TypedefDecl\n"); + topnode->addChild( ConvertTypeDefDecl( dyn_cast<TypedefDecl>(D), topnode )); + } + else if (isa<RecordDecl>(D)) { fprintf(stderr, "\nTUD RecordDecl\n"); + topnode->addChild( ConvertRecordDecl( dyn_cast<RecordDecl>(D), topnode )); + } + else if (isa<TypeAliasDecl>(D)) { fprintf(stderr, "TUD TypeAliasDecl TODO \n"); exit(-1); + } + else { + fprintf(stderr, "\nTUD a declaration of type %s (%d) which I can't handle\n", D->getDeclKindName(), D->getKind()); + exit(-1); + } + } + //fflush(stdout); fprintf(stderr, "leaving ConvertTranslationUnit()\n\n"); + + //fprintf(stderr, "in ConvertTranslationUnit(), dumping the file\n"); + //topnode->dump(); + return ( chillAST_node *) topnode; +} + + + + chillAST_node * ConvertGenericClangAST( Stmt *s, chillAST_node *p ) { + + if (s == NULL) return NULL; + //fprintf(stderr, "\nConvertGenericClangAST() Stmt of type %d (%s)\n", s->getStmtClass(),s->getStmtClassName()); + Decl *D = (Decl *) s; + //if (isa<Decl>(D)) fprintf(stderr, "Decl of kind %d (%s)\n", D->getKind(),D->getDeclKindName() ); + + + chillAST_node *ret = NULL; + + if (isa<CompoundStmt>(s)) {ret = ConvertCompoundStmt( dyn_cast<CompoundStmt>(s),p); + } else if (isa<DeclStmt>(s)) {ret = ConvertDeclStmt(dyn_cast<DeclStmt>(s),p); + } else if (isa<ForStmt>(s)) {ret = ConvertForStmt(dyn_cast<ForStmt>(s),p); + } else if (isa<BinaryOperator>(s)) {ret = ConvertBinaryOperator(dyn_cast<BinaryOperator>(s),p); + } else if (isa<ArraySubscriptExpr>(s)) {ret = ConvertArraySubscriptExpr(dyn_cast<ArraySubscriptExpr>(s),p); + } else if (isa<DeclRefExpr>(s)) {ret = ConvertDeclRefExpr(dyn_cast<DeclRefExpr>(s),p); + } else if (isa<FloatingLiteral>(s)) {ret = ConvertFloatingLiteral(dyn_cast<FloatingLiteral>(s),p); + } else if (isa<IntegerLiteral>(s)) {ret = ConvertIntegerLiteral(dyn_cast<IntegerLiteral>(s),p); + } else if (isa<UnaryOperator>(s)) {ret = ConvertUnaryOperator(dyn_cast<UnaryOperator>(s),p); + } else if (isa<ImplicitCastExpr>(s)) {ret = ConvertImplicitCastExpr(dyn_cast<ImplicitCastExpr>(s),p); + } else if (isa<CStyleCastExpr>(s)) {ret = ConvertCStyleCastExpr(dyn_cast<CStyleCastExpr>(s),p); + } else if (isa<ReturnStmt>(s)) {ret = ConvertReturnStmt(dyn_cast<ReturnStmt>(s),p); + } else if (isa<CallExpr>(s)) {ret = ConvertCallExpr(dyn_cast<CallExpr>(s),p); + } else if (isa<ParenExpr>(s)) {ret = ConvertParenExpr(dyn_cast<ParenExpr>(s),p); + } else if (isa<IfStmt>(s)) {ret = ConvertIfStmt(dyn_cast<IfStmt>(s),p); + } else if (isa<MemberExpr>(s)) {ret = ConvertMemberExpr(dyn_cast<MemberExpr>(s),p); + + + // these can only happen at the top level? + // } else if (isa<FunctionDecl>(D)) { ret = ConvertFunctionDecl( dyn_cast<FunctionDecl>(D)); + //} else if (isa<VarDecl>(D)) { ret = ConvertVarDecl( dyn_cast<VarDecl>(D) ); + //} else if (isa<TypedefDecl>(D)) { ret = ConvertTypeDefDecl( dyn_cast<TypedefDecl>(D)); + // else if (isa<TranslationUnitDecl>(s)) // need filename + + + + + // } else if (isa<>(s)) { Convert ( dyn_cast<>(s)); + + /* + */ + + } else { + // more work to do + fprintf(stderr, "ir_clang.cc ConvertGenericClangAST() UNHANDLED "); + //if (isa<Decl>(D)) fprintf(stderr, "Decl of kind %s\n", D->getDeclKindName() ); + if (isa<Stmt>(s))fprintf(stderr, "Stmt of type %s\n", s->getStmtClassName()); + exit(-1); + } + + return ret; + } + + + + + + + + + + +// ---------------------------------------------------------------------------- +// Class: IR_chillScalarSymbol +// ---------------------------------------------------------------------------- + +std::string IR_chillScalarSymbol::name() const { + //return vd_->getNameAsString(); CLANG + //fprintf(stderr, "IR_chillScalarSymbol::name() %s\n", chillvd->varname); + return std::string(chillvd->varname); // CHILL +} + + +// Return size in bytes +int IR_chillScalarSymbol::size() const { + //return (vd_->getASTContext().getTypeSize(vd_->getType())) / 8; // ?? + fprintf(stderr, "IR_chillScalarSymbol::size() probably WRONG\n"); + return (8); // bytes?? +} + + +bool IR_chillScalarSymbol::operator==(const IR_Symbol &that) const { + //fprintf(stderr, "IR_xxxxScalarSymbol::operator== probably WRONG\n"); + if (typeid(*this) != typeid(that)) + return false; + + const IR_chillScalarSymbol *l_that = static_cast<const IR_chillScalarSymbol *>(&that); + return this->chillvd == l_that->chillvd; +} + +IR_Symbol *IR_chillScalarSymbol::clone() const { + return new IR_chillScalarSymbol(ir_, chillvd ); // clone +} + +// ---------------------------------------------------------------------------- +// Class: IR_chillArraySymbol +// ---------------------------------------------------------------------------- + +std::string IR_chillArraySymbol::name() const { + return std::string( strdup( chillvd ->varname)); +} + + +int IR_chillArraySymbol::elem_size() const { + fprintf(stderr, "IR_chillArraySymbol::elem_size() TODO\n"); exit(-1); + return 8; // TODO + //const ArrayType *at = dyn_cast<ArrayType>(vd_->getType()); + //if(at) { + // return (vd_->getASTContext().getTypeSize(at->getElementType())) / 8; + //} else + // throw ir_error("Symbol is not an array!"); + //return 0; +} + + +int IR_chillArraySymbol::n_dim() const { + //fprintf(stderr, "IR_chillArraySymbol::n_dim()\n"); + //fprintf(stderr, "variable %s %s %s\n", chillvd->vartype, chillvd->varname, chillvd->arraypart); + //fprintf(stderr, "IR_chillArraySymbol::n_dim() %d\n", chillvd->numdimensions); + //fprintf(stderr, "IR_chillArraySymbol::n_dim() TODO \n"); exit(-1); + return chillvd->numdimensions; +} + + +// TODO +omega::CG_outputRepr *IR_chillArraySymbol::size(int dim) const { + fprintf(stderr, "IR_chillArraySymbol::n_size() TODO \n"); exit(-1); + return NULL; +} + + +bool IR_chillArraySymbol::operator!=(const IR_Symbol &that) const { + //fprintf(stderr, "IR_xxxxArraySymbol::operator!= NOT EQUAL\n"); + //chillAST_VarDecl *chillvd; + return chillvd != ((IR_chillArraySymbol*)&that)->chillvd ; +} + +bool IR_chillArraySymbol::operator==(const IR_Symbol &that) const { + //fprintf(stderr, "IR_xxxxArraySymbol::operator== EQUAL\n"); + //chillAST_VarDecl *chillvd; + return chillvd == ((IR_chillArraySymbol*)&that)->chillvd ; + /* + if (typeid(*this) != typeid(that)) + return false; + + const IR_chillArraySymbol *l_that = static_cast<const IR_chillArraySymbol *>(&that); + return this->vd_ == l_that->vd_ && this->offset_ == l_that->offset_; + */ +} + + +IR_Symbol *IR_chillArraySymbol::clone() const { + return new IR_chillArraySymbol(ir_, chillvd, offset_); +} + +// ---------------------------------------------------------------------------- +// Class: IR_chillConstantRef +// ---------------------------------------------------------------------------- + +bool IR_chillConstantRef::operator==(const IR_Ref &that) const { + if (typeid(*this) != typeid(that)) + return false; + + const IR_chillConstantRef *l_that = static_cast<const IR_chillConstantRef *>(&that); + + if (this->type_ != l_that->type_) + return false; + + if (this->type_ == IR_CONSTANT_INT) + return this->i_ == l_that->i_; + else + return this->f_ == l_that->f_; +} + + +omega::CG_outputRepr *IR_chillConstantRef::convert() { + //assert(astContext_ != NULL); + if (type_ == IR_CONSTANT_INT) { + + fprintf(stderr, "IR_chillConstantRef::convert() unimplemented\n"); exit(-1); + + // TODO + /* + BuiltinType *bint = new BuiltinType(BuiltinType::Int); + IntegerLiteral *ilit = new (astContext_)IntegerLiteral(*astContext_, llvm::APInt(32, i_), bint->desugar(), SourceLocation()); + omega::CG_chillRepr *result = new omega::CG_chillRepr(ilit); + delete this; + return result; + */ + } + else + throw ir_error("constant type not supported"); +} + + +IR_Ref *IR_chillConstantRef::clone() const { + if (type_ == IR_CONSTANT_INT) + return new IR_chillConstantRef(ir_, i_); + else if (type_ == IR_CONSTANT_FLOAT) + return new IR_chillConstantRef(ir_, f_); + else + throw ir_error("constant type not supported"); +} + +// ---------------------------------------------------------------------------- +// Class: IR_chillScalarRef +// ---------------------------------------------------------------------------- + +bool IR_chillScalarRef::is_write() const { + return op_pos_ == OP_DEST; // 2 other alternatives: OP_UNKNOWN, OP_SRC +} + + +IR_ScalarSymbol *IR_chillScalarRef::symbol() const { + //VarDecl *vd = static_cast<VarDecl *>(vs_->getDecl()); + //fprintf(stderr, "ir_clang.cc IR_chillScalarRef::symbol()\n"); //exit(-1); + chillAST_VarDecl *vd = NULL; + if (chillvd) vd = chillvd; + return new IR_chillScalarSymbol(ir_, vd); // IR_chillScalarRef::symbol() +} + + +bool IR_chillScalarRef::operator==(const IR_Ref &that) const { + if (typeid(*this) != typeid(that)) + return false; + + const IR_chillScalarRef *l_that = static_cast<const IR_chillScalarRef *>(&that); + + return this->chillvd == l_that->chillvd; +} + + +omega::CG_outputRepr *IR_chillScalarRef::convert() { + //fprintf(stderr, "IR_chillScalarRef::convert() unimplemented\n"); exit(-1); + if (!dre) fprintf(stderr, "IR_chillScalarRef::convert() CLANG SCALAR REF has no dre\n"); + omega::CG_chillRepr *result = new omega::CG_chillRepr(dre); + delete this; + return result; +} + +IR_Ref * IR_chillScalarRef::clone() const { + if (dre) return new IR_chillScalarRef(ir_, dre); // use declrefexpr if it exists + return new IR_chillScalarRef(ir_, chillvd); // uses vardecl +} + + +// ---------------------------------------------------------------------------- +// Class: IR_chillArrayRef +// ---------------------------------------------------------------------------- + +bool IR_chillArrayRef::is_write() const { + + return (iswrite); // TODO +} + + +// TODO +omega::CG_outputRepr *IR_chillArrayRef::index(int dim) const { + fprintf(stderr, "IR_xxxxArrayRef::index( %d ) \n", dim); + //chillASE->print(); printf("\n"); fflush(stdout); + //chillASE->getIndex(dim)->print(); printf("\n"); fflush(stdout); + return new omega::CG_chillRepr( chillASE->getIndex(dim) ); +} + + +IR_ArraySymbol *IR_chillArrayRef::symbol() const { + //fprintf(stderr, "IR_chillArrayRef::symbol()\n"); + //chillASE->print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "base: "); chillASE->base->print(); printf("\n"); fflush(stdout); + + + chillAST_node *mb = chillASE->multibase(); + chillAST_VarDecl *vd = (chillAST_VarDecl*)mb; + //fprintf(stderr, "symbol: '%s'\n", vd->varname); + + //fprintf(stderr, "IR_chillArrayRef symbol: '%s%s'\n", vd->varname, vd->arraypart); + //fprintf(stderr, "numdimensions %d\n", vd->numdimensions); + IR_ArraySymbol *AS = new IR_chillArraySymbol(ir_, vd); + //fprintf(stderr, "ir_clang.cc returning IR_chillArraySymbol 0x%x\n", AS); + return AS; +/* + chillAST_node *b = chillASE->base; + fprintf(stderr, "base of type %s\n", b->getTypeString()); + //b->print(); printf("\n"); fflush(stdout); + if (b->asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR) { + b = ((chillAST_ImplicitCastExpr*)b)->subexpr; + fprintf(stderr, "base of type %s\n", b->getTypeString()); + } + + if (b->asttype == CHILLAST_NODETYPE_DECLREFEXPR) { + if (NULL == ((chillAST_DeclRefExpr*)b)->decl) { + fprintf(stderr, "IR_chillArrayRef::symbol() var decl = 0x%x\n", ((chillAST_DeclRefExpr*)b)->decl); + exit(-1); + } + return new IR_chillArraySymbol(ir_, ((chillAST_DeclRefExpr*)b)->decl); // -> decl? + } + if (b->asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR) { // multidimensional array + return ( + } + fprintf(stderr, "IR_chillArrayRef::symbol() can't handle\n"); + fprintf(stderr, "base of type %s\n", b->getTypeString()); + exit(-1); + return NULL; +*/ +} + + +bool IR_chillArrayRef::operator!=(const IR_Ref &that) const { + //fprintf(stderr, "IR_xxxxArrayRef::operator!=\n"); + bool op = (*this) == that; // opposite + return !op; +} + +void IR_chillArrayRef::Dump() const { + //fprintf(stderr, "IR_chillArrayRef::Dump() this 0x%x chillASE 0x%x\n", this, chillASE); + chillASE->print(); printf("\n");fflush(stdout); +} + + +bool IR_chillArrayRef::operator==(const IR_Ref &that) const { + //fprintf(stderr, "IR_xxxxArrayRef::operator==\n"); + //printf("I am\n"); chillASE->print(); printf("\n"); + const IR_chillArrayRef *l_that = static_cast<const IR_chillArrayRef *>(&that); + const chillAST_ArraySubscriptExpr* thatASE = l_that->chillASE; + //printf("other is:\n"); thatASE->print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "addresses are 0x%x 0x%x\n", chillASE, thatASE ); + return (*chillASE) == (*thatASE); + /* + + if (typeid(*this) != typeid(that)) + return false; + + const IR_chillArrayRef *l_that = static_cast<const IR_chillArrayRef *>(&that); + + return this->as_ == l_that->as_; + */ +} + + +omega::CG_outputRepr *IR_chillArrayRef::convert() { + //fprintf(stderr, "IR_chillArrayRef::convert()\n"); + CG_chillRepr *result = new CG_chillRepr( chillASE->clone() ); +// omega::CG_chillRepr *temp = new omega::CG_chillRepr(static_cast<Expr*>(this->as_)); +// omega::CG_outputRepr *result = temp->clone(); + delete this; + return result; +} + + +IR_Ref *IR_chillArrayRef::clone() const { + return new IR_chillArrayRef(ir_, chillASE, iswrite); +} + + +// ---------------------------------------------------------------------------- +// Class: IR_chillLoop +// ---------------------------------------------------------------------------- +IR_chillLoop::IR_chillLoop(const IR_Code *ir, clang::ForStmt *tf) { fprintf(stderr, "IR_chillLoop::IR_chillLoop() you lose\n"); exit(-1); }; + +IR_chillLoop::IR_chillLoop(const IR_Code *ir, chillAST_ForStmt *achillforstmt) { + fprintf(stderr, "IR_xxxxLoop::IR_xxxxLoop()\n"); + fprintf(stderr, "loop is:\n"); + achillforstmt->print(); + + ir_ = ir; + chillforstmt = achillforstmt; + + chillAST_BinaryOperator *init = (chillAST_BinaryOperator *)chillforstmt->getInit(); + chillAST_BinaryOperator *cond = (chillAST_BinaryOperator *)chillforstmt->getCond(); + // check to be sure (assert) + if (!init->isAssignmentOp() || !cond->isComparisonOp() ) { + fprintf(stderr, "ir_clang.cc, malformed loop init or cond:\n"); + achillforstmt->print(); + exit(-1); + } + + chilllowerbound = init->getRHS(); + chillupperbound = cond->getRHS(); + conditionoperator = achillforstmt->conditionoperator; + + chillAST_node *inc = chillforstmt->getInc(); + // check the increment + //fprintf(stderr, "increment is of type %s\n", inc->getTypeString()); + //inc->print(); printf("\n"); fflush(stdout); + + if (inc->asttype == CHILLAST_NODETYPE_UNARYOPERATOR) { + if (!strcmp(((chillAST_UnaryOperator *) inc)->op, "++")) step_size_ = 1; + else step_size_ = -1; + } + else if (inc->asttype == CHILLAST_NODETYPE_BINARYOPERATOR) { + int beets = false; // slang + chillAST_BinaryOperator *bop = (chillAST_BinaryOperator *) inc; + if (bop->isAssignmentOp()) { // I=I+1 or similar + chillAST_node *rhs = bop->getRHS(); // (I+1) + // TODO looks like this will fail for I=1+I or I=J+1 etc. do more checking + + char *assop = bop->getOp(); + //fprintf(stderr, "'%s' is an assignment op\n", bop->getOp()); + if (streq(assop, "+=") || streq(assop, "-=")) { + chillAST_node *stride = rhs; + //fprintf(stderr, "stride is of type %s\n", stride->getTypeString()); + if (stride->isIntegerLiteral()) { + int val = ((chillAST_IntegerLiteral *)stride)->value; + if (streq( assop, "+=")) step_size_ = val; + else if (streq( assop, "-=")) step_size_ = -val; + else beets = true; + } + else beets = true; // += or -= but not constant stride + } + else if (rhs->isBinaryOperator()) { + chillAST_BinaryOperator *binoprhs = (chillAST_BinaryOperator *)rhs; + chillAST_node *intlit = binoprhs->getRHS(); + if (intlit->isIntegerLiteral()) { + int val = ((chillAST_IntegerLiteral *)intlit)->value; + if (!strcmp( binoprhs->getOp(), "+")) step_size_ = val; + else if (!strcmp( binoprhs->getOp(), "-")) step_size_ = -val; + else beets = true; + } + else beets = true; + } + else beets = true; + } + else beets = true; + + if (beets) { + fprintf(stderr, "malformed loop increment (or more likely unhandled case)\n"); + inc->print(); + exit(-1); + } + } // binary operator + else { + fprintf(stderr, "IR_chillLoop constructor, unhandled loop increment\n"); + inc->print(); + exit(-1); + } + //inc->print(0, stderr);fprintf(stderr, "\n"); + + chillAST_DeclRefExpr *dre = (chillAST_DeclRefExpr *)init->getLHS(); + if (!dre->isDeclRefExpr()) { + fprintf(stderr, "malformed loop init.\n"); + init->print(); + } + + chillindex = dre; // the loop index variable + + //fprintf(stderr, "\n\nindex is "); dre->print(0, stderr); fprintf(stderr, "\n"); + //fprintf(stderr, "init is "); + //chilllowerbound->print(0, stderr); fprintf(stderr, "\n"); + //fprintf(stderr, "condition is %s ", "<"); + //chillupperbound->print(0, stderr); fprintf(stderr, "\n"); + //fprintf(stderr, "step size is %d\n\n", step_size_) ; + + chillbody = achillforstmt->getBody(); + + fprintf(stderr, "IR_xxxxLoop::IR_xxxxLoop() DONE\n"); +} + + +omega::CG_outputRepr *IR_chillLoop::lower_bound() const { + fprintf(stderr, "IR_xxxxLoop::lower_bound()\n"); + return new omega::CG_chillRepr(chilllowerbound); +} + +omega::CG_outputRepr *IR_chillLoop::upper_bound() const { + fprintf(stderr, "IR_xxxxLoop::upper_bound()\n"); + return new omega::CG_chillRepr(chillupperbound); +} + +IR_Block *IR_chillLoop::body() const { + fprintf(stderr, "IR_xxxxLoop::body()\n"); + //assert(isa<CompoundStmt>(tf_->getBody())); + //fprintf(stderr, "returning a clangBLOCK corresponding to the body of the loop\n"); + //fprintf(stderr, "body type %s\n", chillbody->getTypeString()); + return new IR_chillBlock(ir_, chillbody ) ; // static_cast<CompoundStmt *>(tf_->getBody())); +} + +IR_Control *IR_chillLoop::clone() const { + fprintf(stderr, "IR_xxxxLoop::clone()\n"); + //chillforstmt->print(); fflush(stdout); + return new IR_chillLoop(ir_, chillforstmt); +} + +IR_CONDITION_TYPE IR_chillLoop::stop_cond() const { + chillAST_BinaryOperator *loopcondition = (chillAST_BinaryOperator*) chillupperbound; + fprintf(stderr, "IR_xxxxLoop::stop_cond()\n"); + return conditionoperator; +} + +IR_Block *IR_chillLoop::convert() { // convert the loop to a block + fprintf(stderr, "IR_xxxxLoop::convert() maybe \n"); + return new IR_chillBlock( ir_, chillbody ); // ?? + return NULL; +} + +void IR_chillLoop::dump() const { + fprintf(stderr, "TODO: IR_chillLoop::dump()\n"); exit(-1); +} + + +// ---------------------------------------------------------------------------- +// Class: IR_chillBlock +// ---------------------------------------------------------------------------- +omega::CG_outputRepr *IR_chillBlock::original() const { + fprintf(stderr, "IR_xxxxBlock::original() TODO \n"); + exit(-1); + return NULL; +} + + + +omega::CG_outputRepr *IR_chillBlock::extract() const { + fflush(stdout); + fprintf(stderr, "IR_xxxxBlock::extract()\n"); + //omega::CG_chillRepr *tnl = new omega::CG_chillRepr(getStmtList()); + + // if the block refers to a compound statement, return the next level + // of statements ; otherwise just return a repr of the statements + + chillAST_node *code = chillAST; + //if (chillAST != NULL) fprintf(stderr, "block has chillAST of type %s\n",code->getTypeString()); + //fprintf(stderr, "block has %d exploded statements\n", statements.size()); + + omega::CG_chillRepr *OR; + if (0 == statements.size()) { + OR = new omega::CG_chillRepr(code); // presumably a compound statement ?? + } + else { + fprintf(stderr, "adding a statement from IR_chillBlock::extract()\n"); + OR = new omega::CG_chillRepr(); // empty of statements + for (int i=0; i<statements.size(); i++) OR->addStatement( statements[i] ); + } + + fflush(stdout); + fprintf(stderr, "IR_xxxxBlock::extract() LEAVING\n"); + return OR; +} + +IR_Control *IR_chillBlock::clone() const { + fprintf(stderr, "IR_xxxxBlock::clone()\n"); + //fprintf(stderr, "IR_xxxxBlock::clone() %d statements\n", statements.size()); + return new IR_chillBlock( this ); // shallow copy ? +} + +void IR_chillBlock::dump() const { + fprintf(stderr, "IR_chillBlock::dump() TODO\n"); return; +} + +//StmtList +vector<chillAST_node*> IR_chillBlock::getStmtList() const { + fprintf(stderr, "IR_xxxxBlock::getStmtList()\n"); + return statements; // ?? +} + + +void IR_chillBlock::addStatement( chillAST_node* s ) { + statements.push_back( s ); +} + + + +void PrintTranslationUnit( TranslationUnitDecl *TUD) { // , ASTContext &CTX ) { + fprintf(stderr, "MY PrintTranslationUnit()\n"); + // TUD derived from Decl and DeclContext + static DeclContext *DC = TUD->castToDeclContext( TUD ); + //SourceManager SM = CTX.getSourceManager(); + + for (DeclContext::decl_iterator DI = DC->decls_begin(), DE = DC->decls_end(); DI != DE; ++DI) { + Decl *D = *DI; + fprintf(stderr, "D\n"); + if (isa<FunctionDecl>(D)) { fprintf(stderr, "FunctionDecl\n"); + //PrintFunctionDecl( dyn_cast<FunctionDecl>(D), CTX.getSourceManager(), 0); + } + else if (isa<VarDecl>(D)) { fprintf(stderr, "VarDecl\n"); + //PrintVarDecl( dyn_cast<VarDecl>(D), CTX.getSourceManager(), 0 ); + } + else if (isa<TypedefDecl>(D)) { fprintf(stderr, "TypedefDecl\n"); + //PrintTypeDefDecl( dyn_cast<TypedefDecl>(D), CTX.getSourceManager(), 0 ); + } + else if (isa<TypeAliasDecl>(D)) { fprintf(stderr, "TypeAliasDecl\n"); + } + else fprintf(stderr, "\na declaration of type %s (%d)\n", D->getDeclKindName(), D->getKind()); + //else if (isa<TypedefNameDecl>(D)) { fprintf(stderr, "TypedefNameDecl\n");} + } +} + +class NULLASTConsumer : public ASTConsumer +{ +}; + + + +void findmanually( chillAST_node *node, char *procname, std::vector<chillAST_node*>& procs ) { + //fprintf(stderr, "findmanually() CHILL AST node of type %s\n", node->getTypeString()); + + if (node->asttype == CHILLAST_NODETYPE_FUNCTIONDECL ) { + char *name = ((chillAST_FunctionDecl *) node)->functionName; + //fprintf(stderr, "node name 0x%x ", name); + //fprintf(stderr, "%s procname ", name); + //fprintf(stderr, "0x%x ", procname); + //fprintf(stderr, "%s\n", procname); + if (!strcmp( name, procname)) { + //fprintf(stderr, "found procedure %s\n", procname ); + procs.push_back( node ); + // quit recursing. probably not correct in some horrible case + return; + } + //else fprintf(stderr, "this is not the function we're looking for\n"); + } + + + // this is where the children can be used effectively. + // we don't really care what kind of node we're at. We just check the node itself + // and then its children is needed. + + int numc = node->children.size(); + //fprintf(stderr, "%d children\n", numc); + + for (int i=0; i<numc; i++) { + //fprintf(stderr, "node of type %s is recursing to child %d\n", node->getTypeString(), i); + findmanually( node->children[i], procname, procs ); + } + return; +} + +// ---------------------------------------------------------------------------- +// Class: IR_clangCode_Global_Init +// ---------------------------------------------------------------------------- + +IR_clangCode_Global_Init *IR_clangCode_Global_Init::pinstance = 0; + + +IR_clangCode_Global_Init *IR_clangCode_Global_Init::Instance(char **argv) { + fprintf(stderr, "in IR_clangCode_Global_Init::Instance(), "); + if (pinstance == 0) { + //fprintf(stderr, "\n\n*** making the one and only instance ***\n\n\n"); + // this is the only way to create an IR_clangCode_Global_Init + pinstance = new IR_clangCode_Global_Init; + pinstance->ClangCompiler = new aClangCompiler( argv[1] ); + + } + //fprintf(stderr, "leaving IR_clangCode_Global_Init::Instance()\n"); + return pinstance; +} + + +aClangCompiler::aClangCompiler( char *filename ) { + + //fprintf(stderr, "making a clang compiler for file %s\n", filename); + SourceFileName = strdup( filename ); + + // Arguments to pass to the clang frontend + std::vector<const char *> args; + args.push_back(strdup(filename)); + + // The compiler invocation needs a DiagnosticsEngine so it can report problems + //IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts = new DiagnosticOptions(); // temp + diagnosticOptions = new DiagnosticOptions(); // private member of aClangCompiler + + pTextDiagnosticPrinter = new clang::TextDiagnosticPrinter(llvm::errs(), diagnosticOptions); // private member of aClangCompiler + + //llvm::IntrusiveRefCntPtr<clang::DiagnosticIDs> DiagID(new clang::DiagnosticIDs()); + diagID = new clang::DiagnosticIDs(); // private member of IR_clangCode_Global_Init + + //clang::DiagnosticsEngine Diags(DiagID, &*DiagOpts, DiagClient); + diagnosticsEngine = new clang::DiagnosticsEngine(diagID, diagnosticOptions, pTextDiagnosticPrinter); + + // Create the compiler invocation + // This class is designed to represent an abstract "invocation" of the compiler, + // including data such as the include paths, the code generation options, + // the warning flags, and so on. + std::unique_ptr<clang::CompilerInvocation> CI(new clang::CompilerInvocation()); + //CI = new clang::CompilerInvocation; + clang::CompilerInvocation::CreateFromArgs(*CI, &args[0], &args[0] + args.size(), *diagnosticsEngine); + + + // Create the compiler instance + Clang = new clang::CompilerInstance(); // TODO should have a better name ClangCompilerInstance + + + // Get ready to report problems + Clang->createDiagnostics(nullptr, true); + //Clang.createDiagnostics(0, 0); + + +//#ifdef KIDDINGME + //fprintf(stderr, "target\n"); + // Initialize target info with the default triple for our platform. + //TargetOptions TO; + //TO.Triple = llvm::sys::getDefaultTargetTriple(); + //TargetInfo *TI = TargetInfo::CreateTargetInfo( Clang->getDiagnostics(), TO); + + // the above causes core dumps, because clang is stupid and frees the target multiple times, corrupting memory + const std::shared_ptr<clang::TargetOptions> to = std::make_shared<clang::TargetOptions>(); + targetOptions->Triple = llvm::sys::getDefaultTargetTriple(); + + TargetInfo *pti = TargetInfo::CreateTargetInfo(Clang->getDiagnostics(),to); + + Clang->setTarget(pti); + +//#endif + + + // ?? + //fprintf(stderr, "filemgr\n"); + Clang->createFileManager(); + FileManager &FileMgr = Clang->getFileManager(); + fileManager = &FileMgr; + + //fprintf(stderr, "sourcemgr\n"); + Clang->createSourceManager(FileMgr); + SourceManager &SourceMgr = Clang->getSourceManager(); + sourceManager = &SourceMgr; // ?? aclangcompiler copy + globalSRCMAN = &SourceMgr; // TODO global bad + + Clang->setInvocation(CI.get()); // Replace the current invocation + + + + //fprintf(stderr, "PP\n"); + Clang->createPreprocessor(TU_Complete); + + + + //clang::Preprocessor Pre = Clang->getPreprocessor(); + //preprocessor = &Pre; + + //fprintf(stderr, "CONTEXT\n"); + Clang->createASTContext(); // needs preprocessor + astContext_ = &Clang->getASTContext(); + + + //fprintf(stderr, "filein\n"); + const FileEntry *FileIn = FileMgr.getFile(filename); // needs preprocessor + SourceMgr.setMainFileID(SourceMgr.createFileID(FileIn,clang::SourceLocation(),clang::SrcMgr::C_User)); + //DiagnosticConsumer DiagConsumer = Clang->getDiagnosticClient(); + Clang->getDiagnosticClient().BeginSourceFile( Clang->getLangOpts(), &Clang->getPreprocessor()); + + + NULLASTConsumer TheConsumer; // must pass a consumer in to ParseAST(). This one does nothing + + //fprintf(stderr, "ready? Parse.\n"); + fprintf(stderr, "actually parsing file %s using clang\n", filename); + + ParseAST( Clang->getPreprocessor(), &TheConsumer, Clang->getASTContext()); + + // Translation Unit is contents of a file + TranslationUnitDecl* TUD = astContext_->getTranslationUnitDecl(); + // TUD->dump(); // print it out + + // create another AST, very similar to the clang AST but not written by idiots + fprintf(stderr, "converting entire clang AST into chill AST (ir_clang.cc)\n"); + chillAST_node * wholefile = ConvertTranslationUnit( TUD, filename); + + fflush(stdout); + //fprintf(stderr, "printing whole file\n"); + //fprintf(stdout, "\n\n" ); fflush(stdout); + //wholefile->print(); + //wholefile->dump(); + //fflush(stdout); + + entire_file_AST = (chillAST_SourceFile *)wholefile; + + + astContext_ = &Clang->getASTContext(); + + //#define DOUBLE +#ifdef DOUBLE + fprintf(stderr, "DOUBLE\n"); + + fprintf(stderr, "\n\nCLANG dump of the file I parsed:\n"); + llvm::OwningPtr<clang::FrontendAction> Act2(new clang::ASTDumpAction()); + // here it actually does the FrontEndAction ?? + if (!Clang->ExecuteAction(*Act2)) { // ast dump using builtin function + exit(3); + } +#endif + fflush(stdout); fflush(stderr); + fflush(stdout); fflush(stderr); + fflush(stdout); fflush(stderr); + fflush(stdout); fflush(stderr); + + + + + + + + + +#ifdef DONTDOTHIS + + // calling this Action seems to overwrite the astcontext and the AST. (!) + // don't ever do this, or you lose contact with the original AST (?) + + // Create an action and make the compiler instance carry it out + //llvm::OwningPtr<clang::CodeGenAction> Act(new clang::EmitLLVMOnlyAction()); + llvm::OwningPtr<clang::FrontendAction> Act(new clang::ASTDumpAction()); + + fprintf(stderr, "\n\ndump of the file I parsed:\n"); + // here it actually does the FrontEndAction ?? + if (!Clang->ExecuteAction(*Act)) { // ast dump using builtin function + exit(3); + } + fflush(stdout); +#endif + + + //fprintf(stderr, "leaving aClangCompiler::aClangCompiler( filename )\n"); +} + + + + +chillAST_FunctionDecl* aClangCompiler::findprocedurebyname( char *procname ) { + + //fprintf(stderr, "searching through files in the clang AST\n\n"); + //fprintf(stderr, "astContext_ 0x%x\n", astContext_); + + std::vector<chillAST_node*> procs; + findmanually( entire_file_AST, procname, procs ); + + //fprintf(stderr, "procs has %d members\n", procs.size()); + + if ( procs.size() == 0 ) { + fprintf(stderr, "could not find function named '%s' in AST from file %s\n", procname, SourceFileName); + exit(-1); + } + + if ( procs.size() > 1 ) { + fprintf(stderr, "oddly, found %d functions named '%s' in AST from file %s\n", procs.size(), procname, SourceFileName); + fprintf(stderr, "I am unsure what to do\n"); + exit(-1); + } + + fprintf(stderr, "found the procedure named %s\n", procname); + return (chillAST_FunctionDecl *)procs[0]; + +} + + + +#ifdef NOPE +IR_clangCode_Global_Init::IR_clangCode_Global_Init(char *filename , clang::FileSystemOptions fso ) : + fileManager(fso) // , headerSearch( headerSearchOptions, fileManager, diagengine, languageOptions, pTargetInfo ) +{ + /* CLANG Initialization */ + diagnosticsEngine = new clang::DiagnosticsEngine( const IntrusiveRefCntPtr<DiagnosticIDs> &Diags, + diagnosticOptionsnsa utah + ) ; // DiagnosticConsumer *client = 0, bool ShouldOwnClient = true) + pTextDiagnosticPrinter = new clang::TextDiagnosticPrinter(llvm::outs(), diagnosticOptions); + diagnostic = new clang::Diagnostic(pTextDiagnosticPrinter); + sourceManager = new clang::SourceManager(*diagnostic); + + // FIXME + + // <Warning!!> -- Platform Specific Code lives here + // This depends on A) that you're running linux and + // B) that you have the same GCC LIBs installed that + // I do. + // Search through Clang itself for something like this, + // go on, you won't find it. The reason why is Clang + // has its own versions of std* which are installed under + // /usr/local/lib/clang/<version>/include/ + // See somewhere around Driver.cpp:77 to see Clang adding + // its version of the headers to its include path. + /*headerSearchOptions.AddPath("/usr/include/linux", clang::frontend::Angled, false, false, false); + headerSearchOptions.AddPath("/usr/include/c++/4.3/tr1", clang::frontend::Angled, false, false, false); + headerSearchOptions.AddPath("/usr/include/c++/4.3", clang::frontend::Angled, false, false, false);*/ + // </Warning!!> -- End of Platform Specific Code + + targetOptions.Triple = llvm::sys::getHostTriple(); + pTargetInfo = clang::TargetInfo::CreateTargetInfo(*diagnostic, targetOptions); + clang::ApplyHeaderSearchOptions( headerSearch, headerSearchOptions, languageOptions, pTargetInfo->getTriple()); + preprocessor = new clang::Preprocessor(*diagnostic, languageOptions, *pTargetInfo, *sourceManager, headerSearch); + clang::InitializePreprocessor(*preprocessor, preprocessorOptions, headerSearchOptions, frontendOptions); + const clang::FileEntry *pFile = fileManager.getFile(filename); + sourceManager->createMainFileID(pFile); + //preprocessor.EnterMainSourceFile(); + + clang::TargetInfo &targetInfo = *pTargetInfo; + + idTable = new clang::IdentifierTable(languageOptions); + + builtinContext = new clang::Builtin::Context(targetInfo); + astContext_ = new clang::ASTContext(languageOptions, *sourceManager, targetInfo, *idTable, selTable, *builtinContext, 0); + astConsumer_ = new Chill_ASTConsumer(); + clang::Sema sema(*preprocessor, *astContext_, *astConsumer_); + sema.Initialize(); + clang::ParseAST(*preprocessor, astConsumer_, *astContext_); +} +#endif + + +IR_clangCode_Global_Init::~IR_clangCode_Global_Init() +{ + /* + delete pTextDiagnosticPrinter; + delete diagnostic; + delete sourceManager; + delete preprocessor; + delete idTable; + delete builtinContext; + delete astContext_; + delete astConsumer_; + */ +} + + + +// ---------------------------------------------------------------------------- +// Class: IR_clangCode +// ---------------------------------------------------------------------------- + +IR_clangCode::IR_clangCode(const char *fname, char *proc_name): IR_Code() { + fprintf(stderr, "\nIR_xxxxCode::IR_xxxxCode()\n\n"); + //fprintf(stderr, "IR_clangCode::IR_clangCode( filename %s, procedure %s )\n", filename, proc_name); + + filename = strdup(fname); // filename is internal to IR_clangCode + procedurename = strdup(proc_name); + + int argc = 2; + char *argv[2]; + argv[0] = "chill"; + argv[1] = strdup(filename); + + // use clang to parse the input file ? (or is that already done?) + //fprintf(stderr, "IR_clangCode::IR_clangCode(), parsing input file %s\n", argv[1]); + + // this causes opening and parsing of the file. + // this is the only call to Instance that has an argument list or file name + IR_clangCode_Global_Init *pInstance = IR_clangCode_Global_Init::Instance(argv); + + if(pInstance) { + + aClangCompiler *Clang = pInstance->ClangCompiler; + //fprintf(stderr, "Clang is 0x%x\n", Clang); + + //fprintf(stderr, "want to get pointer to clang ast for procedure %s\n", proc_name); + pInstance->setCurrentFunction( NULL ); // we have no function AST yet + + entire_file_AST = Clang->entire_file_AST; // ugly that same name, different classes + chillAST_FunctionDecl *localFD = Clang->findprocedurebyname( proc_name ); // stored locally + //fprintf(stderr, "back from findprocedurebyname( %s )\n", proc_name ); + //localFD->print(); + + pInstance->setCurrentFunction( localFD ); + + chillAST_node *b = localFD->getBody(); // we do this just because it will get done next + fprintf(stderr, "in IR_xxxxCode::IR_xxxxCode(), new CG_xxxxBuilder\n"); + + fprintf(stderr, "ir_clang.cc calling new CG_chillBuilder() umwut?\n"); + ocg_ = new omega::CG_chillBuilder(); // ocg == omega code gen + chillfunc = localFD; + + } + + fprintf(stderr, "IR_xxxxCode::IR_xxxxCode() returning after reading source file and finding function\n\n"); + + //chillfunc->dump( 0, stderr); + +} + + +IR_clangCode::~IR_clangCode() { + //func_->print(llvm::outs(), 4); // printing as part of the destructor !! + fprintf(stderr, "IR_xxxxCode::~IR_xxxxCode()\noutput happening as part of the destructor !!\n"); + //chillfunc->dump(); + //chillfunc->print(); + + //fprintf(stderr, "Constant Folding before\n"); + //chillfunc->print(); + chillfunc->constantFold(); + //fprintf(stderr, "\nConstant Folding after\n"); + //chillfunc->print(); + + chillfunc->cleanUpVarDecls(); + + //chillfunc->dump(); + + // TODO should output the entire file, not just the function we're working on + chillAST_SourceFile *src = chillfunc->getSourceFile(); + //chillAST_node *p = chillfunc->parent; // should be translationDeclUnit + if (src) { + //src->print(); // tmp + if (src->isSourceFile()) src->printToFile( ); + } +} + + + + + +//TODO +IR_ScalarSymbol *IR_clangCode::CreateScalarSymbol(const IR_Symbol *sym, int i) { + //fprintf(stderr, "IR_clangCode::CreateScalarSymbol()\n"); + if (typeid(*sym) == typeid( IR_chillScalarSymbol ) ) { // should be the case ??? + fprintf(stderr, "IR_xxxxCode::CreateScalarSymbol() from a scalar symbol\n"); + //fprintf(stderr, "(typeid(*sym) == typeid( IR_chillScalarSymbol )\n"); + const IR_chillScalarSymbol *CSS = (IR_chillScalarSymbol*) sym; + chillAST_VarDecl *vd = CSS->chillvd; + + // do we have to check to see if it's already there? + VariableDeclarations.push_back(vd); + chillAST_node *bod = chillfunc->getBody(); // always a compoundStmt ?? + bod->insertChild(0, vd); + fprintf(stderr, "returning ... really\n"); + return new IR_chillScalarSymbol( this, CSS->chillvd); // CSS->clone(); + } + + // ?? + if (typeid(*sym) == typeid( IR_chillArraySymbol ) ) { + fprintf(stderr, "IR_xxxxCode::CreateScalarSymbol() from an array symbol?\n"); + const IR_chillArraySymbol *CAS = (IR_chillArraySymbol*) sym; + //fprintf(stderr, "CAS 0x%x chillvd = 0x%x\n", CAS, CAS->chillvd); + //fprintf(stderr, "\nthis is the SYMBOL?: \n"); + //CAS->print(); + //CAS->dump(); + + chillAST_VarDecl *vd = CAS->chillvd; + //fprintf(stderr, "\nthis is the var decl?: "); + //vd->print(); printf("\n"); + //vd->dump(); printf("\n\n"); + fflush(stdout); + + // figure out the base type (probably float) of the array + char *basetype = vd->underlyingtype; + fprintf(stderr, "scalar will be of type SgType%s\n", basetype); + + char tmpname[128]; + sprintf(tmpname, "newVariable%i\0", vd->chill_scalar_counter++); + chillAST_VarDecl * scalarvd = new chillAST_VarDecl( basetype, tmpname, "", NULL); // TODO parent + scalarvd->print(); printf("\n"); fflush(stdout); + + fprintf(stderr, "VarDecl has parent that is a NULL\n"); + + return (IR_ScalarSymbol *) (new IR_chillScalarSymbol( this, scalarvd)); // CSS->clone(); + } + + fprintf(stderr, "IR_clangCode::CreateScalarSymbol(), passed a sym that is not a clang scalar symbol OR an array symbol???\n"); + int *n = NULL; + n[0] = 1; + exit(-1); + return NULL; +} + + +IR_ArraySymbol *IR_clangCode::CreateArraySymbol(const IR_Symbol *sym, std::vector<omega::CG_outputRepr *> &size, int i) { + fprintf(stderr, "IR_xxxxCode::CreateArraySymbol()\n"); + + // build a new array name + char namestring[128]; + + sprintf(namestring, "_P%d\0", entire_file_AST->chill_array_counter++); + fprintf(stderr, "creating Array %s\n", namestring); + + char arraypart[100]; + char *s = &arraypart[0]; + + for (int i=0; i<size.size(); i++) { + omega::CG_outputRepr *OR = size[i]; + CG_chillRepr * CR = (CG_chillRepr * ) OR; + //fprintf(stderr, "%d chillnodes\n", CR->chillnodes.size()); + + // this SHOULD be 1 chillnode of type IntegerLiteral (per dimension) + int numnodes = CR->chillnodes.size(); + if (1 != numnodes) { + fprintf(stderr, + "IR_clangCode::CreateArraySymbol() array dimension %d has %d chillnodes\n", + i, numnodes ); + exit(-1); + } + + chillAST_node *nodezero = CR->chillnodes[0]; + if (!nodezero->isIntegerLiteral()) { + fprintf(stderr, "IR_clangCode::CreateArraySymbol() array dimension %d not an IntegerLiteral\n", i); + exit(-1); + } + + chillAST_IntegerLiteral *IL = (chillAST_IntegerLiteral *)nodezero; + int val = IL->value; + sprintf(s, "[%d]\0", val); + s = &arraypart[ strlen(arraypart) ]; + } + //fprintf(stderr, "arraypart '%s'\n", arraypart); + + chillAST_VarDecl *vd = new chillAST_VarDecl( "float", namestring, arraypart, NULL); // todo type from sym + + // put decl in some symbol table + VariableDeclarations.push_back(vd); + // insert decl in the IR_code body + chillAST_node *bod = chillfunc->getBody(); // always a compoundStmt ?? + bod->insertChild(0, vd); + + return new IR_chillArraySymbol( this, vd); +} + +// TODO +std::vector<IR_ScalarRef *> IR_clangCode::FindScalarRef(const omega::CG_outputRepr *repr) const { + std::vector<IR_ScalarRef *> scalars; + fprintf(stderr, "IR_clangCode::FindScalarRef() DIE\n"); exit(-1); + return scalars; +} + + + +IR_ScalarRef *IR_clangCode::CreateScalarRef(const IR_ScalarSymbol *sym) { + //fprintf(stderr, "\n***** ir_clang.cc IR_clangCode::CreateScalarRef( sym %s )\n", sym->name().c_str()); + //DeclRefExpr *de = new (vd->getASTContext())DeclRefExpr(static_cast<ValueDecl*>(vd), vd->getType(), SourceLocation()); + //fprintf(stderr, "sym 0x%x\n", sym); + + IR_chillScalarRef *sr = new IR_chillScalarRef(this, buildDeclRefExpr(((IR_chillScalarSymbol*)sym)->chillvd)); // uses VarDecl to mak a declrefexpr + //fprintf(stderr, "returning ScalarRef with dre 0x%x\n", sr->dre); + return sr; + //return (IR_ScalarRef *)NULL; +} + + + +IR_ArrayRef *IR_clangCode::CreateArrayRef(const IR_ArraySymbol *sym, std::vector<omega::CG_outputRepr *> &index) { + fprintf(stderr, "IR_clangCode::CreateArrayRef() ir_clang.cc\n"); + fprintf(stderr, "sym->n_dim() %d index.size() %d\n", sym->n_dim(), index.size()); + + int t; + if(sym->n_dim() != index.size()) { + throw std::invalid_argument("incorrect array symbol dimensionality dim != size ir_clang.cc L2359"); + } + + const IR_chillArraySymbol *c_sym = static_cast<const IR_chillArraySymbol *>(sym); + chillAST_VarDecl *vd = c_sym->chillvd; + std::vector<chillAST_node *> inds; + + //fprintf(stderr, "%d array indeces\n", sym->n_dim()); + for (int i=0; i< index.size(); i++) { + CG_chillRepr *CR = (CG_chillRepr *)index[i]; + + int numnodes = CR->chillnodes.size(); + if (1 != numnodes) { + fprintf(stderr, + "IR_clangCode::CreateArrayRef() array dimension %d has %d chillnodes\n", + i, numnodes ); + exit(-1); + } + + inds.push_back( CR->chillnodes[0] ); + + /* + chillAST_node *nodezero = CR->chillnodes[0]; + if (!nodezero->isIntegerLiteral()) { + fprintf(stderr,"IR_clangCode::CreateArrayRef() array dimension %d not an IntegerLiteral\n",i); + fprintf(stderr, "it is a %s\n", nodezero->getTypeString()); + nodezero->print(); printf("\n"); fflush(stdout); + exit(-1); + } + + chillAST_IntegerLiteral *IL = (chillAST_IntegerLiteral *)nodezero; + int val = IL->value; + inds.push_back( val ); + */ + } + + // now we've got the vardecl AND the indeces to make a chillAST that represents the array reference + // TODO Passing NULL for chillAST node? + chillAST_ArraySubscriptExpr *ASE = new chillAST_ArraySubscriptExpr( vd, inds, NULL); + + auto ref = new IR_chillArrayRef( this, ASE, 0 ); + + return ref; +} + +// find all array references ANYWHERE in this block of code ?? +std::vector<IR_ArrayRef *> IR_clangCode::FindArrayRef(const omega::CG_outputRepr *repr) const { + //fprintf(stderr, "FindArrayRef()\n"); + std::vector<IR_ArrayRef *> arrays; + const omega::CG_chillRepr *crepr = static_cast<const omega::CG_chillRepr *>(repr); + std::vector<chillAST_node*> chillstmts = crepr->getChillCode(); + + //fprintf(stderr, "there are %d chill statements in this repr\n", chillstmts.size()); + + std::vector<chillAST_ArraySubscriptExpr*> refs; + for (int i=0; i<chillstmts.size(); i++) { + //fprintf(stderr, "\nchillstatement %d = ", i); chillstmts[i]->print(0, stderr); fprintf(stderr, "\n"); + chillstmts[i]->gatherArrayRefs( refs, false ); + } + //fprintf(stderr, "%d total refs\n", refs.size()); + for (int i=0; i<refs.size(); i++) { + if (refs[i]->imreadfrom) { + //fprintf(stderr, "ref[%d] going to be put in TWICE, as both read and write\n", i); + arrays.push_back( new IR_chillArrayRef( this, refs[i], 0 ) ); // UGLY TODO dual usage of a ref in "+=" + } + arrays.push_back( new IR_chillArrayRef( this, refs[i], refs[i]->imwrittento ) ); // this is wrong + // we need to know whether this reference will be written, etc. + } + + /* + if(chillstmts.size() > 1) { + for(int i=0; i<tnl->size(); ++i) { + omega::CG_chillRepr *r = new omega::CG_chillRepr((*tnl)[i]); + std::vector<IR_ArrayRef *> a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + } + } else if(chillstmts.size() == 1) { + Stmt *s = (*tnl)[0]; + + if(CompoundStmt *cs = dyn_cast<CompoundStmt>(s)) { + for(CompoundStmt::body_iterator bi = cs->body_begin(); bi != cs->body_end(); ++bi) { + omega::CG_chillRepr *r = new omega::CG_chillRepr(*bi); + std::vector<IR_ArrayRef *> a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + } + } else if(ForStmt *fs = dyn_cast<ForStmt>(s)) { + omega::CG_chillRepr *r = new omega::CG_chillRepr(fs->getBody()); + std::vector<IR_ArrayRef *> a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + } else if(IfStmt *ifs = dyn_cast<IfStmt>(s)) { + omega::CG_chillRepr *r = new omega::CG_chillRepr(ifs->getCond()); + std::vector<IR_ArrayRef *> a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + r = new omega::CG_chillRepr(ifs->getThen()); + a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + if(Stmt *s_else = ifs->getElse()) { + r = new omega::CG_chillRepr(s_else); + a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + } + } else if(Expr *e = dyn_cast<Expr>(s)) { + omega::CG_chillRepr *r = new omega::CG_chillRepr(static_cast<Expr*>(s)); + std::vector<IR_ArrayRef *> a = FindArrayRef(r); + delete r; + std::copy(a.begin(), a.end(), back_inserter(arrays)); + } else throw ir_error("control structure not supported"); + } + */ +/* + else { // We have an expression + Expr *op = static_cast<const omega::CG_chillRepr *>(repr)->GetExpression(); + if(0) { // TODO: Handle pointer reference exp. here + } else if(BinaryOperator *bop = dyn_cast<BinaryOperator>(op)) { + omega::CG_chillRepr *r1 = new omega::CG_chillRepr(bop->getLHS()); + std::vector<IR_ArrayRef *> a1 = FindArrayRef(r1); + delete r1; + std::copy(a1.begin(), a1.end(), back_inserter(arrays)); + omega::CG_chillRepr *r2 = new omega::CG_chillRepr(bop->getRHS()); + std::vector<IR_ArrayRef *> a2 = FindArrayRef(r2); + delete r2; + std::copy(a2.begin(), a2.end(), back_inserter(arrays)); + } else if(UnaryOperator *uop = dyn_cast<UnaryOperator>(op)) { + omega::CG_chillRepr *r1 = new omega::CG_chillRepr(uop->getSubExpr()); + std::vector<IR_ArrayRef *> a1 = FindArrayRef(r1); + delete r1; + std::copy(a1.begin(), a1.end(), back_inserter(arrays)); + } //else throw ir_error("Invalid expr. type passed to FindArrayRef"); + } + */ + return arrays; +} + + +std::vector<IR_Control *> IR_clangCode::FindOneLevelControlStructure(const IR_Block *block) const { + fprintf(stderr, "IR_xxxxCode::FindOneLevelControlStructure()\n"); + const IR_chillBlock *CB = (const IR_chillBlock *) block; + //fprintf(stderr, "block 0x%x\n", block); + + std::vector<IR_Control *> controls; + + chillAST_node *blockast = CB->chillAST; + //fprintf(stderr, "blockast 0x%x\n", blockast); + if (blockast == NULL) { + int numstmts = CB->statements.size(); + fprintf(stderr, "%d statements\n", numstmts); + + if (numstmts == 0) return controls; + + else if (numstmts == 1) blockast = CB->statements[0]; // a single statement + + else { + fprintf(stderr, "IR_xxxBlock is dumb, with multiple ways to hold statements\n"); + exit(-1); // TODO FIX + } + } + + //fprintf(stderr, "block's AST is of type %s\n", blockast->getTypeString()); + //blockast->print(); printf("\n\n"); fflush(stdout); + + + //vector<chillAST_node *> funcchildren = chillfunc->getChildren(); + //fprintf(stderr, "%d children of clangcode\n", funcchildren.size()); // includes parameters + + // build up a vector of "controls". + // a run of straight-line code (statements that can't cause branching) will be + // bundled up into an IR_Block + // ifs and loops will get their own entry + + std::vector<chillAST_node *> children; + + + if (blockast->asttype == CHILLAST_NODETYPE_FORSTMT) { fflush(stdout); + fprintf(stderr, "found a top level For statement (Loop)\n"); + fprintf(stderr, "For Stmt (loop) is:\n"); + blockast->print(); + fprintf(stderr, "pushing the loop at TOP\n"); + + controls.push_back( new IR_chillLoop( this, (chillAST_ForStmt *)blockast)); + } + //else if (blockast->asttype == CHILLAST_NODETYPE_IFSTMT) { + // controls.push_back( new IR_clangIf( this, (chillAST_IfStmt *)blockast)); + //} + else if (blockast->asttype == CHILLAST_NODETYPE_COMPOUNDSTMT || + blockast->asttype == CHILLAST_NODETYPE_FUNCTIONDECL) { + + if (blockast->asttype == CHILLAST_NODETYPE_FUNCTIONDECL) { + //fprintf(stderr, "ir_clanc.cc blockast->asttype == CHILLAST_NODETYPE_FUNCTIONDECL\n"); + + chillAST_FunctionDecl *FD = (chillAST_FunctionDecl *)blockast; + chillAST_node *bod = FD->getBody(); + //fprintf(stderr, "bod 0x%x\n", bod); + + children = bod->getChildren(); + + //fprintf(stderr, "FunctionDecl body is of type %s\n", bod->getTypeString()); + //fprintf(stderr, "found a top level FunctionDecl (Basic Block)\n"); + //fprintf(stderr, "basic block has %d statements\n", children.size() ); + //fprintf(stderr, "basic block is:\n"); + //bod->print(); + } + else /* CompoundStmt */ { + //fprintf(stderr, "found a top level Basic Block\n"); + children = blockast->getChildren(); + } + + int numchildren = children.size(); + //fprintf(stderr, "basic block has %d statements\n", numchildren); + //fprintf(stderr, "basic block is:\n"); + //fprintf(stderr, "{\n"); + //blockast->print(); + //fprintf(stderr, "}\n"); + + int ns; + IR_chillBlock *basicblock = new IR_chillBlock(this); // no statements + for (int i=0; i<numchildren; i++) { + //fprintf(stderr, "child %d is of type %s\n", i, children[i]->getTypeString()); + CHILL_ASTNODE_TYPE typ = children[i]->asttype; + if (typ == CHILLAST_NODETYPE_LOOP) { + if (numchildren == 1) { + fprintf(stderr, "found a For statement (Loop)\n"); + } + else { + fprintf(stderr, "found a For statement (Loop) at %d within a Basic Block\n", i); + } + //children[i]->print(); printf("\n"); fflush(stdout); + + ns = basicblock->numstatements(); + if (ns) { + fprintf(stderr, "pushing a run of statements %d to %d as a block\n", i-ns, i-1); + controls.push_back( basicblock ); + basicblock = new IR_chillBlock(this); // start a new one + } + + //fprintf(stderr, "pushing the loop at %d\n", i); + controls.push_back( new IR_chillLoop(this, (chillAST_ForStmt *)children[i] )); + + } + //else if (typ == CHILLAST_NODETYPE_IFSTMT ) // TODO + else { // straight line code + //fprintf(stderr, "straight line code\n"); + basicblock->addStatement( children[i] ); + //fprintf(stderr, "child %d = \n", i); children[i]->print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "child %d is part of a basic block\n", i); + } + } // for each child + ns = basicblock->numstatements(); + //fprintf(stderr, "ns %d\n", ns); + if (ns != 0 ) { + if (ns != numchildren) { + //fprintf(stderr, "end of body ends the run of %d statements in the Basic Block\n", ns); + controls.push_back( basicblock ); + } + else { + //fprintf(stderr, "NOT sending straightline run of statements, because it would be the entire block. There are no control statements in the block\n"); + } + } + //else fprintf(stderr, "NOT sending the last run of %d statements\n", ns); + + } + else { + fprintf(stderr, "IR_clangCode::FindOneLevelControlStructure(), block is a %s???\n", blockast->getTypeString()); + exit(-1); + } + + fprintf(stderr, "returning vector of %d controls\n", controls.size() ); + return controls; +} + + +IR_Block *IR_clangCode::MergeNeighboringControlStructures(const std::vector<IR_Control *> &controls) const { + fprintf(stderr, "IR_xxxxCode::MergeNeighboringControlStructures %d controls\n", controls.size()); + + if (controls.size() == 0) + return NULL; + + IR_chillBlock *CBlock = new IR_chillBlock(controls[0]->ir_); // the thing we're building + + std::vector<chillAST_node*> statements; + chillAST_node *parent = NULL; + for (int i = 0; i < controls.size(); i++) { + switch (controls[i]->type()) { + case IR_CONTROL_LOOP: { + fprintf(stderr, "control %d is IR_CONTROL_LOOP\n", i); + chillAST_ForStmt *loop = static_cast<IR_chillLoop *>(controls[i])->chillforstmt; + if (parent == NULL) { + parent = loop->parent; + } else { + if (parent != loop->parent) { + throw ir_error("controls to merge not at the same level"); + } + } + CBlock->addStatement( loop ); + break; + } + case IR_CONTROL_BLOCK: { + fprintf(stderr, "control %d is IR_CONTROL_BLOCK\n", i); + IR_chillBlock *CB = static_cast<IR_chillBlock*>(controls[i]); + std::vector<chillAST_node*> blockstmts = CB->statements; + if (statements.size() != 0) { + for (int j=0; j< blockstmts.size(); j++) { + if (parent == NULL) { + parent = blockstmts[j]->parent; + } + else { + if (parent != blockstmts[j]->parent) { + throw ir_error("ir_clang.cc IR_clangCode::MergeNeighboringControlStructures controls to merge not at the same level"); + } + } + CBlock->addStatement( blockstmts[j] ); + } + } + else { + if (CB->chillAST) CBlock->addStatement(CBlock->chillAST); // if this is a block, add theblock's statements? + else { // should never happen + fprintf(stderr, "WARNING: ir_clang.cc IR_clangCode::MergeNeighboringControlStructures"); + fprintf(stderr, " empty IR_CONTROL_BLOCK \n"); + } + } + break; + } + default: + throw ir_error("unrecognized control to merge"); + } + } // for each control + + return CBlock; +} + + +IR_Block *IR_clangCode::GetCode() const { // return IR_Block corresponding to current function? + //fprintf(stderr, "IR_clangCode::GetCode()\n"); + //Stmt *s = func_->getBody(); // clang statement, and clang getBody + //fprintf(stderr, "chillfunc 0x%x\n", chillfunc); + + //chillAST_node *bod = chillfunc->getBody(); // chillAST + //fprintf(stderr, "printing the function getBody()\n"); + //fprintf(stderr, "sourceManager 0x%x\n", sourceManager); + //bod->print(); + + return new IR_chillBlock(this, chillfunc ) ; +} + + +void IR_clangCode::ReplaceCode(IR_Control *old, omega::CG_outputRepr *repr) { + fflush(stdout); + fprintf(stderr, "IR_xxxxCode::ReplaceCode( old, *repr)\n"); + + CG_chillRepr *chillrepr = (CG_chillRepr *) repr; + std::vector<chillAST_node*> newcode = chillrepr->getChillCode(); + int numnew = newcode.size(); + + //fprintf(stderr, "new code (%d) is\n", numnew); + //for (int i=0; i<numnew; i++) { + // newcode[i]->print(0, stderr); + // fprintf(stderr, "\n"); + //} + + struct IR_chillLoop* cloop; + + std::vector<chillAST_VarDecl*> olddecls; + chillfunc->gatherVarDecls( olddecls ); + //fprintf(stderr, "\n%d old decls they are:\n", olddecls.size()); + //for (int i=0; i<olddecls.size(); i++) { + // fprintf(stderr, "olddecl[%d] ox%x ",i, olddecls[i]); + // olddecls[i]->print(); printf("\n"); fflush(stdout); + //} + + + //fprintf(stderr, "num new stmts %d\n", numnew); + //fprintf(stderr, "new code we're look for decls in:\n"); + std::vector<chillAST_VarDecl*> decls; + for (int i=0; i<numnew; i++) { + //newcode[i]->print(0,stderr); + //fprintf(stderr, "\n"); + newcode[i]->gatherVarUsage( decls ); + } + + //fprintf(stderr, "\n%d new vars used they are:\n", decls.size()); + //for (int i=0; i<decls.size(); i++) { + // fprintf(stderr, "decl[%d] ox%x ",i, decls[i]); + // decls[i]->print(); printf("\n"); fflush(stdout); + //} + + + for (int i=0; i<decls.size(); i++) { + //fprintf(stderr, "\nchecking "); decls[i]->print(); printf("\n"); fflush(stdout); + int inthere = 0; + for (int j=0; j<VariableDeclarations.size(); j++) { + if (VariableDeclarations[j] == decls[i]) { + //fprintf(stderr, "it's in the Variable Declarations()\n"); + } + } + for (int j=0; j<olddecls.size(); j++) { + if (decls[i] == olddecls[j]) { + //fprintf(stderr, "it's in the olddecls (exactly)\n"); + inthere = 1; + } + if (streq(decls[i]->varname, olddecls[j]->varname)) { + if (streq(decls[i]->arraypart, olddecls[j]->arraypart)) { + //fprintf(stderr, "it's in the olddecls (INEXACTLY)\n"); + inthere = 1; + } + } + } + if (!inthere) { + //fprintf(stderr, "inserting decl[%d] for ",i); decls[i]->print(); printf("\n");fflush(stdout); + chillfunc->getBody()->insertChild(0, decls[i]); + olddecls.push_back( decls[i] ); + } + } + + chillAST_node *par; + switch (old->type()) { + case IR_CONTROL_LOOP: + { + //fprintf(stderr, "old is IR_CONTROL_LOOP\n"); + cloop = (struct IR_chillLoop* )old; + chillAST_ForStmt *forstmt = cloop->chillforstmt; + + fprintf(stderr, "old was\n"); + forstmt->print(); printf("\n"); fflush(stdout); + + //fprintf(stderr, "\nnew code is\n"); + //for (int i=0; i<numnew; i++) { newcode[i]->print(); printf("\n"); } + //fflush(stdout); + + + par = forstmt->parent; + if (!par) { + fprintf(stderr, "old parent was NULL\n"); + fprintf(stderr, "ir_clang.cc that will not work very well.\n"); + exit(-1); + } + + + + fprintf(stderr, "\nold parent was\n\n{\n"); + par->print(); printf("\n"); fflush(stdout); + fprintf(stderr, "\n}\n"); + + std::vector<chillAST_node*> oldparentcode = par->getChildren(); // probably only works for compoundstmts + //fprintf(stderr, "ir_clang.cc oldparentcode\n"); + + // find loop in the parent + int index = -1; + int numstatements = oldparentcode.size(); + for (int i=0; i<numstatements; i++) if (oldparentcode[i] == forstmt) { index = i; } + if (index == -1) { + fprintf(stderr, "ir_clang.cc can't find the loop in its parent\n"); + exit(-1); + } + //fprintf(stderr, "loop is index %d\n", index); + + // insert the new code + par->setChild(index, newcode[0]); // overwrite old stmt + //fprintf(stderr, "inserting %s 0x%x as index %d of 0x%x\n", newcode[0]->getTypeString(), newcode[0], index, par); + // do we need to update the IR_cloop? + cloop->chillforstmt = (chillAST_ForStmt*) newcode[0]; // ?? DFL + + + + //printf("inserting "); newcode[0]->print(); printf("\n"); + if (numnew > 1){ + //oldparentcode.insert( oldparentcode.begin()+index+1, numnew-1, NULL); // allocate in bulk + + // add the rest of the new statements + for (int i=1; i<numnew; i++) { + printf("inserting "); newcode[i]->print(); printf("\n"); + par->insertChild( index+i, newcode[i] ); // sets parent + } + } + + // TODO add in (insert) variable declarations that go with the new loops + + + fflush(stdout); + } + break; + case IR_CONTROL_BLOCK: + fprintf(stderr, "old is IR_CONTROL_BLOCK\n"); + fprintf(stderr, "IR_clangCode::ReplaceCode() stubbed out\n"); + exit(-1); + //tf_old = static_cast<IR_chillBlock *>(old)->getStmtList()[0]; + break; + default: + throw ir_error("control structure to be replaced not supported"); + break; + } + + fflush(stdout); + //fprintf(stderr, "\nafter inserting %d statements into the Clang IR,", numnew); + fprintf(stderr, "\nnew parent2 is\n\n{\n"); + std::vector<chillAST_node*> newparentcode = par->getChildren(); + for (int i=0; i<newparentcode.size(); i++) { + fflush(stdout); + //fprintf(stderr, "%d ", i); + newparentcode[i]->print(); printf(";\n"); fflush(stdout); + } + + + + fprintf(stderr, "}\n"); + +} + + + + +void IR_clangCode::ReplaceExpression(IR_Ref *old, omega::CG_outputRepr *repr) { + fprintf(stderr, "IR_xxxxCode::ReplaceExpression()\n"); + + if (typeid(*old) == typeid(IR_chillArrayRef)) { + //fprintf(stderr, "expressions is IR_chillArrayRef\n"); + IR_chillArrayRef *CAR = (IR_chillArrayRef *)old; + chillAST_ArraySubscriptExpr* CASE = CAR->chillASE; + printf("\nreplacing old "); CASE->print(); printf("\n"); fflush(stdout); + + omega::CG_chillRepr *crepr = (omega::CG_chillRepr *)repr; + if (crepr->chillnodes.size() != 1) { + fprintf(stderr, "IR_clangCode::ReplaceExpression(), replacing with %d chillnodes???\n"); + //exit(-1); + } + + chillAST_node *newthing = crepr->chillnodes[0]; + fprintf(stderr, "with new "); newthing->print(); printf("\n\n"); fflush(stdout); + + if (!CASE->parent) { + fprintf(stderr, "IR_clangCode::ReplaceExpression() old has no parent ??\n"); + exit(-1); + } + + fprintf(stderr, "OLD parent = "); // of type %s\n", CASE->parent->getTypeString()); + if (CASE->parent->isImplicitCastExpr()) CASE->parent->parent->print(); + else CASE->parent->print(); + printf("\n"); fflush(stdout); + + //CASE->parent->print(); printf("\n"); fflush(stdout); + //CASE->parent->parent->print(); printf("\n"); fflush(stdout); + //CASE->parent->parent->print(); printf("\n"); fflush(stdout); + //CASE->parent->parent->parent->print(); printf("\n"); fflush(stdout); + + CASE->parent->replaceChild( CASE, newthing ); + + fprintf(stderr, "after replace parent is "); // of type %s\n", CASE->parent->getTypeString()); + if (CASE->parent->isImplicitCastExpr()) CASE->parent->parent->print(); + else CASE->parent->print(); + printf("\n\n"); fflush(stdout); + + + + //CASE->parent->print(); printf("\n"); fflush(stdout); + //CASE->parent->parent->print(); printf("\n"); fflush(stdout); + //CASE->parent->parent->print(); printf("\n"); fflush(stdout); + //CASE->parent->parent->parent->print(); printf("\n"); fflush(stdout); + + + } + else if (typeid(*old) == typeid(IR_chillScalarRef)) { + fprintf(stderr, "IR_clangCode::ReplaceExpression() IR_chillScalarRef unhandled\n"); + } + else { + fprintf(stderr, "UNKNOWN KIND OF REF\n"); exit(-1); + } + + delete old; +} + + +// TODO +IR_CONDITION_TYPE IR_clangCode::QueryBooleanExpOperation(const omega::CG_outputRepr *repr) const { + return IR_COND_UNKNOWN; +} + + + +IR_OPERATION_TYPE IR_clangCode::QueryExpOperation(const omega::CG_outputRepr *repr) const { + //fprintf(stderr, "IR_clangCode::QueryExpOperation()\n"); + + CG_chillRepr *crepr = (CG_chillRepr *) repr; + chillAST_node *node = crepr->chillnodes[0]; + //fprintf(stderr, "chillAST node type %s\n", node->getTypeString()); + + // really need to be more rigorous than this hack // TODO + if (node->isImplicitCastExpr()) node = ((chillAST_ImplicitCastExpr*)node)->subexpr; + if (node->isCStyleCastExpr()) node = ((chillAST_CStyleCastExpr*) node)->subexpr; + if (node->isParenExpr()) node = ((chillAST_ParenExpr*) node)->subexpr; + + if (node->isIntegerLiteral() || node->isFloatingLiteral()) return IR_OP_CONSTANT; + else if (node->isBinaryOperator() || node->isUnaryOperator()) { + char *opstring; + if (node->isBinaryOperator()) + opstring= ((chillAST_BinaryOperator*)node)->op; // TODO enum + else + opstring= ((chillAST_UnaryOperator*)node)->op; // TODO enum + + if (!strcmp(opstring, "+")) return IR_OP_PLUS; + if (!strcmp(opstring, "-")) return IR_OP_MINUS; + if (!strcmp(opstring, "*")) return IR_OP_MULTIPLY; + if (!strcmp(opstring, "/")) return IR_OP_DIVIDE; + if (!strcmp(opstring, "=")) return IR_OP_ASSIGNMENT; + + fprintf(stderr, "ir_clang.cc IR_clangCode::QueryExpOperation() UNHANDLED Binary(or Unary)Operator op type (%s)\n", opstring); + exit(-1); + } + else if (node->isDeclRefExpr() ) return IR_OP_VARIABLE; // ?? + //else if (node->is ) return something; + else { + fprintf(stderr, "IR_clangCode::QueryExpOperation() UNHANDLED NODE TYPE %s\n", node->getTypeString()); + exit(-1); + } + + /* CLANG + Expr *e = static_cast<const omega::CG_chillRepr *>(repr)->GetExpression(); + if(isa<IntegerLiteral>(e) || isa<FloatingLiteral>(e)) return IR_OP_CONSTANT; + else if(isa<DeclRefExpr>(e)) return IR_OP_VARIABLE; + else if(BinaryOperator *bop = dyn_cast<BinaryOperator>(e)) { + switch(bop->getOpcode()) { + case BO_Assign: return IR_OP_ASSIGNMENT; + case BO_Add: return IR_OP_PLUS; + case BO_Sub: return IR_OP_MINUS; + case BO_Mul: return IR_OP_MULTIPLY; + case BO_Div: return IR_OP_DIVIDE; + default: return IR_OP_UNKNOWN; + } + } else if(UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) { + switch(uop->getOpcode()) { + case UO_Minus: return IR_OP_NEGATIVE; + case UO_Plus: return IR_OP_POSITIVE; + default: return IR_OP_UNKNOWN; + } + } else if(ConditionalOperator *cop = dyn_cast<ConditionalOperator>(e)) { + BinaryOperator *bop; + if(bop = dyn_cast<BinaryOperator>(cop->getCond())) { + if(bop->getOpcode() == BO_GT) return IR_OP_MAX; + else if(bop->getOpcode() == BO_LT) return IR_OP_MIN; + } else return IR_OP_UNKNOWN; + + } + + else if(e == NULL) return IR_OP_NULL; + else return IR_OP_UNKNOWN; + } + END CLANG */ +} + + +std::vector<omega::CG_outputRepr *> IR_clangCode::QueryExpOperand(const omega::CG_outputRepr *repr) const { + //fprintf(stderr, "IR_clangCode::QueryExpOperand()\n"); + std::vector<omega::CG_outputRepr *> v; + + CG_chillRepr *crepr = (CG_chillRepr *) repr; + //Expr *e = static_cast<const omega::CG_chillRepr *>(repr)->GetExpression(); wrong.. CLANG + chillAST_node *e = crepr->chillnodes[0]; // ?? + //e->print(); printf("\n"); fflush(stdout); + + // really need to be more rigorous than this hack // TODO + if (e->isImplicitCastExpr()) e = ((chillAST_ImplicitCastExpr*)e)->subexpr; + if (e->isCStyleCastExpr()) e = ((chillAST_CStyleCastExpr*) e)->subexpr; + if (e->isParenExpr()) e = ((chillAST_ParenExpr*) e)->subexpr; + + + //if(isa<IntegerLiteral>(e) || isa<FloatingLiteral>(e) || isa<DeclRefExpr>(e)) { + if (e->isIntegerLiteral() || e->isFloatingLiteral() || e->isDeclRefExpr() ) { + //fprintf(stderr, "it's a constant\n"); + omega::CG_chillRepr *repr = new omega::CG_chillRepr(e); + v.push_back(repr); + //} else if(BinaryOperator *bop = dyn_cast<BinaryOperator>(e)) { + } else if (e->isBinaryOperator()) { + //fprintf(stderr, "ir_clang.cc BOP TODO\n"); exit(-1); // + chillAST_BinaryOperator *bop = (chillAST_BinaryOperator*)e; + char *op = bop->op; // TODO enum for operator types + if (streq(op, "=")) { + v.push_back(new omega::CG_chillRepr( bop->rhs )); // for assign, return RHS + } + else if (streq(op, "+") || streq(op, "-") || streq(op, "*") || streq(op, "/") ) { + v.push_back(new omega::CG_chillRepr( bop->lhs )); // for +*-/ return both lhs and rhs + v.push_back(new omega::CG_chillRepr( bop->rhs )); + } + else { + fprintf(stderr, "ir_clang.cc IR_clangCode::QueryExpOperand() Binary Operator UNHANDLED op (%s)\n", op); + exit(-1); + } + } // BinaryOperator + else if (e->isUnaryOperator()) { + omega::CG_chillRepr *repr; + chillAST_UnaryOperator *uop = (chillAST_UnaryOperator*)e; + char *op = uop->op; // TODO enum + if (streq(op, "+") || streq(op, "-")) { + v.push_back( new omega::CG_chillRepr( uop->subexpr )); + } + else { + fprintf(stderr, "ir_clang.cc IR_clangCode::QueryExpOperand() Unary Operator UNHANDLED op (%s)\n", op); + exit(-1); + } + } // unaryoperator + else { + fprintf(stderr, "ir_clang.cc IR_clangCode::QueryExpOperand() UNHANDLED node type %s\n", e->getTypeString()); + exit(-1); + } + + + /* + Expr *op1, *op2; + switch(bop->getOpcode()) { + case BO_Assign: + op2 = bop->getRHS(); + repr = new omega::CG_chillRepr(op2); + v.push_back(repr); + break; + case BO_Add: + case BO_Sub: + case BO_Mul: + case BO_Div: + op1 = bop->getLHS(); + repr = new omega::CG_chillRepr(op1); + v.push_back(repr); + op2 = bop->getRHS(); + repr = new omega::CG_chillRepr(op2); + v.push_back(repr); + break; + default: + throw ir_error("operation not supported"); + } + */ + //} else if(UnaryOperator *uop = dyn_cast<UnaryOperator>(e)) { + //} else if(e->isUnaryOperator()) { + /* + omega::CG_chillRepr *repr; + + switch(uop->getOpcode()) { + case UO_Minus: + case UO_Plus: + op1 = uop->getSubExpr(); + repr = new omega::CG_chillRepr(op1); + v.push_back(repr); + break; + default: + throw ir_error("operation not supported"); + } + */ + //} else if(ConditionalOperator *cop = dyn_cast<ConditionalOperator>(e)) { + //omega::CG_chillRepr *repr; + + // TODO: Handle conditional operator here + //} else throw ir_error("operand type UNsupported"); + + return v; +} + +IR_Ref *IR_clangCode::Repr2Ref(const omega::CG_outputRepr *repr) const { + CG_chillRepr *crepr = (CG_chillRepr *) repr; + chillAST_node *node = crepr->chillnodes[0]; + + //Expr *e = static_cast<const omega::CG_chillRep *>(repr)->GetExpression(); + + if(node->isIntegerLiteral()) { + // FIXME: Not sure if it'll work in all cases (long?) + int val = ((chillAST_IntegerLiteral*)node)->value; + return new IR_chillConstantRef(this, static_cast<omega::coef_t>(val) ); + } else if(node->isFloatingLiteral()) { + float val = ((chillAST_FloatingLiteral*)node)->value; + return new IR_chillConstantRef(this, val ); + } else if(node->isDeclRefExpr()) { + //fprintf(stderr, "ir_clang.cc IR_clangCode::Repr2Ref() declrefexpr TODO\n"); exit(-1); + return new IR_chillScalarRef(this, (chillAST_DeclRefExpr*)node); // uses DRE + } else { + fprintf(stderr, "ir_clang.cc IR_clangCode::Repr2Ref() UNHANDLED node type %s\n", node->getTypeString()); + exit(-1); + //assert(0); + } +} + +chillAST_node * ConvertMemberExpr( clang::MemberExpr *clangME , chillAST_node *) { + fprintf(stderr, "ConvertMemberExpr()\n"); + + clang::Expr *E = clangME->getBase(); + E->dump(); + + chillAST_node *base = ConvertGenericClangAST( clangME->getBase(), NULL ); + + DeclarationNameInfo memnameinfo = clangME->getMemberNameInfo(); + DeclarationName DN = memnameinfo.getName(); + const char *member = DN.getAsString().c_str(); + //fprintf(stderr, "%s\n", DN.getAsString().c_str()); + + chillAST_MemberExpr *ME = new chillAST_MemberExpr( base, member, NULL, clangME ); + + fprintf(stderr, "this is the Member Expresion\n"); + ME->print(); + fprintf(stderr, "\n"); + + return ME; + +} diff --git a/src/ir_rose.cc b/src/ir_rose.cc deleted file mode 100644 index f4039ab..0000000 --- a/src/ir_rose.cc +++ /dev/null @@ -1,1699 +0,0 @@ -/***************************************************************************** - Copyright (C) 2009-2010 University of Utah - All Rights Reserved. - - Purpose: - CHiLL's rose interface. - - Notes: - Array supports mixed pointer and array type in a single declaration. - - History: - 02/23/2009 Created by Chun Chen. -*****************************************************************************/ -#include <string> -#include "ir_rose.hh" -#include "ir_rose_utils.hh" -#include "code_gen/rose_attributes.h" -#include "code_gen/CG_roseRepr.h" -#include "code_gen/CG_roseBuilder.h" - -using namespace SageBuilder; -using namespace SageInterface; -using namespace omega; -// ---------------------------------------------------------------------------- -// Class: IR_roseScalarSymbol -// ---------------------------------------------------------------------------- - -std::string IR_roseScalarSymbol::name() const { - return vs_->get_name().getString(); -} - -int IR_roseScalarSymbol::size() const { - return (vs_->get_type()->memoryUsage()) / (vs_->get_type()->numberOfNodes()); -} - -bool IR_roseScalarSymbol::operator==(const IR_Symbol &that) const { - if (typeid(*this) != typeid(that)) - return false; - - const IR_roseScalarSymbol *l_that = - static_cast<const IR_roseScalarSymbol *>(&that); - return this->vs_ == l_that->vs_; -} - -IR_Symbol *IR_roseScalarSymbol::clone() const { - return NULL; -} - -// ---------------------------------------------------------------------------- -// Class: IR_roseArraySymbol -// ---------------------------------------------------------------------------- - -std::string IR_roseArraySymbol::name() const { - return (vs_->get_declaration()->get_name().getString()); -} - -int IR_roseArraySymbol::elem_size() const { - - SgType *tn = vs_->get_type(); - SgType* arrType; - - int elemsize; - - if (arrType = isSgArrayType(tn)) { - while (isSgArrayType(arrType)) { - arrType = arrType->findBaseType(); - } - } else if (arrType = isSgPointerType(tn)) { - while (isSgPointerType(arrType)) { - arrType = arrType->findBaseType(); - } - } - - elemsize = (int) arrType->memoryUsage() / arrType->numberOfNodes(); - return elemsize; -} - -int IR_roseArraySymbol::n_dim() const { - int dim = 0; - SgType* arrType = isSgArrayType(vs_->get_type()); - SgType* ptrType = isSgPointerType(vs_->get_type()); - if (arrType != NULL) { - while (isSgArrayType(arrType)) { - arrType = isSgArrayType(arrType)->get_base_type(); - dim++; - } - } else if (ptrType != NULL) { - while (isSgPointerType(ptrType)) { - ptrType = isSgPointerType(ptrType)->get_base_type(); - dim++; - } - } - - // Manu:: fortran support - if (static_cast<const IR_roseCode *>(ir_)->is_fortran_) { - - if (arrType != NULL) { - dim = 0; - SgExprListExp * dimList = isSgArrayType(vs_->get_type())->get_dim_info(); - SgExpressionPtrList::iterator it = dimList->get_expressions().begin(); - for(;it != dimList->get_expressions().end(); it++) { - dim++; - } - } else if (ptrType != NULL) { - ; // not sure if this case will happen - } - } - - return dim; -} - -omega::CG_outputRepr *IR_roseArraySymbol::size(int dim) const { - - SgArrayType* arrType = isSgArrayType(vs_->get_type()); - int count = 0; - SgExpression* expr; - SgType* pntrType = isSgPointerType(vs_->get_type()); - - if (arrType != NULL) { - SgExprListExp* dimList = arrType->get_dim_info(); - if (!static_cast<const IR_roseCode *>(ir_)->is_fortran_) { - SgExpressionPtrList::iterator it = - dimList->get_expressions().begin(); - - while ((it != dimList->get_expressions().end()) && (count < dim)) { - it++; - count++; - } - - expr = *it; - } else { - SgExpressionPtrList::reverse_iterator i = - dimList->get_expressions().rbegin(); - for (; (i != dimList->get_expressions().rend()) && (count < dim); - i++) { - - count++; - } - - expr = *i; - } - } else if (pntrType != NULL) { - - while (count < dim) { - pntrType = (isSgPointerType(pntrType))->get_base_type(); - count++; - } - if (isSgPointerType(pntrType)) - expr = new SgExpression; - } - - if (!expr) - throw ir_error("Index variable is NULL!!"); - - // Manu :: debug - std::cout << "---------- size :: " << isSgNode(expr)->unparseToString().c_str() << "\n"; - - return new omega::CG_roseRepr(expr); - -} - -IR_ARRAY_LAYOUT_TYPE IR_roseArraySymbol::layout_type() const { - if (static_cast<const IR_roseCode *>(ir_)->is_fortran_) - return IR_ARRAY_LAYOUT_COLUMN_MAJOR; - else - return IR_ARRAY_LAYOUT_ROW_MAJOR; - -} - -bool IR_roseArraySymbol::operator==(const IR_Symbol &that) const { - - if (typeid(*this) != typeid(that)) - return false; - - const IR_roseArraySymbol *l_that = - static_cast<const IR_roseArraySymbol *>(&that); - return this->vs_ == l_that->vs_; - -} - -IR_Symbol *IR_roseArraySymbol::clone() const { - return new IR_roseArraySymbol(ir_, vs_); -} - -// ---------------------------------------------------------------------------- -// Class: IR_roseConstantRef -// ---------------------------------------------------------------------------- - -bool IR_roseConstantRef::operator==(const IR_Ref &that) const { - - if (typeid(*this) != typeid(that)) - return false; - - const IR_roseConstantRef *l_that = - static_cast<const IR_roseConstantRef *>(&that); - - if (this->type_ != l_that->type_) - return false; - - if (this->type_ == IR_CONSTANT_INT) - return this->i_ == l_that->i_; - else - return this->f_ == l_that->f_; - -} - -omega::CG_outputRepr *IR_roseConstantRef::convert() { - if (type_ == IR_CONSTANT_INT) { - omega::CG_roseRepr *result = new omega::CG_roseRepr( - isSgExpression(buildIntVal(static_cast<int>(i_)))); - delete this; - return result; - } else - throw ir_error("constant type not supported"); - -} - -IR_Ref *IR_roseConstantRef::clone() const { - if (type_ == IR_CONSTANT_INT) - return new IR_roseConstantRef(ir_, i_); - else if (type_ == IR_CONSTANT_FLOAT) - return new IR_roseConstantRef(ir_, f_); - else - throw ir_error("constant type not supported"); - -} - -// ---------------------------------------------------------------------------- -// Class: IR_roseScalarRef -// ---------------------------------------------------------------------------- - -bool IR_roseScalarRef::is_write() const { - if (is_write_ == 1) - return true; - - return false; -} - -IR_ScalarSymbol *IR_roseScalarRef::symbol() const { - return new IR_roseScalarSymbol(ir_, vs_->get_symbol()); -} - -bool IR_roseScalarRef::operator==(const IR_Ref &that) const { - if (typeid(*this) != typeid(that)) - return false; - - const IR_roseScalarRef *l_that = - static_cast<const IR_roseScalarRef *>(&that); - - if (this->ins_pos_ == NULL) - return this->vs_ == l_that->vs_; - else - return this->ins_pos_ == l_that->ins_pos_ - && this->op_pos_ == l_that->op_pos_; -} - -omega::CG_outputRepr *IR_roseScalarRef::convert() { - omega::CG_roseRepr *result = new omega::CG_roseRepr(isSgExpression(vs_)); - delete this; - return result; - -} - -IR_Ref * IR_roseScalarRef::clone() const { - return new IR_roseScalarRef(ir_, vs_, this->is_write_); -} - -// ---------------------------------------------------------------------------- -// Class: IR_roseArrayRef -// ---------------------------------------------------------------------------- - -bool IR_roseArrayRef::is_write() const { - SgAssignOp* assignment; - - if (is_write_ == 1 || is_write_ == 0) - return is_write_; - if (assignment = isSgAssignOp(ia_->get_parent())) { - if (assignment->get_lhs_operand() == ia_) - return true; - } else if (SgExprStatement* expr_stmt = isSgExprStatement( - ia_->get_parent())) { - SgExpression* exp = expr_stmt->get_expression(); - - if (exp) { - if (assignment = isSgAssignOp(exp)) { - if (assignment->get_lhs_operand() == ia_) - return true; - - } - } - - } - return false; -} - -omega::CG_outputRepr *IR_roseArrayRef::index(int dim) const { - - SgExpression *current = isSgExpression(ia_); - SgExpression* expr; - int count = 0; - - while (isSgPntrArrRefExp(current)) { - current = isSgPntrArrRefExp(current)->get_lhs_operand(); - count++; - } - - current = ia_; - - while (count > dim) { - expr = isSgPntrArrRefExp(current)->get_rhs_operand(); - current = isSgPntrArrRefExp(current)->get_lhs_operand(); - count--; - } - - // Manu:: fortran support - if (static_cast<const IR_roseCode *>(ir_)->is_fortran_) { - expr = isSgPntrArrRefExp(ia_)->get_rhs_operand(); - count = 0; - if (isSgExprListExp(expr)) { - SgExpressionPtrList::iterator indexList = isSgExprListExp(expr)->get_expressions().begin(); - while (count < dim) { - indexList++; - count++; - } - expr = isSgExpression(*indexList); - } - } - - if (!expr) - throw ir_error("Index variable is NULL!!"); - - - omega::CG_roseRepr* ind = new omega::CG_roseRepr(expr); - - return ind->clone(); - -} - -IR_ArraySymbol *IR_roseArrayRef::symbol() const { - - SgExpression *current = isSgExpression(ia_); - - SgVarRefExp* base; - SgVariableSymbol *arrSymbol; - while (isSgPntrArrRefExp(current) || isSgUnaryOp(current)) { - if (isSgPntrArrRefExp(current)) - current = isSgPntrArrRefExp(current)->get_lhs_operand(); - else if (isSgUnaryOp(current)) - /* To handle support for addressof operator and pointer dereference - * both of which are unary ops - */ - current = isSgUnaryOp(current)->get_operand(); - } - if (base = isSgVarRefExp(current)) { - arrSymbol = (SgVariableSymbol*) (base->get_symbol()); - std::string x = arrSymbol->get_name().getString(); - } else - throw ir_error("Array Symbol is not a variable?!"); - - return new IR_roseArraySymbol(ir_, arrSymbol); - -} - -bool IR_roseArrayRef::operator==(const IR_Ref &that) const { - if (typeid(*this) != typeid(that)) - return false; - - const IR_roseArrayRef *l_that = static_cast<const IR_roseArrayRef *>(&that); - - return this->ia_ == l_that->ia_; -} - -omega::CG_outputRepr *IR_roseArrayRef::convert() { - omega::CG_roseRepr *temp = new omega::CG_roseRepr( - isSgExpression(this->ia_)); - omega::CG_outputRepr *result = temp->clone(); -// delete this; // Commented by Manu - return result; -} - -IR_Ref *IR_roseArrayRef::clone() const { - return new IR_roseArrayRef(ir_, ia_, is_write_); -} - -// ---------------------------------------------------------------------------- -// Class: IR_roseLoop -// ---------------------------------------------------------------------------- - -IR_ScalarSymbol *IR_roseLoop::index() const { - SgForStatement *tf = isSgForStatement(tf_); - SgFortranDo *tfortran = isSgFortranDo(tf_); - SgVariableSymbol* vs = NULL; - if (tf) { - SgForInitStatement* list = tf->get_for_init_stmt(); - SgStatementPtrList& initStatements = list->get_init_stmt(); - SgStatementPtrList::const_iterator j = initStatements.begin(); - - if (SgExprStatement *expr = isSgExprStatement(*j)) - if (SgAssignOp* op = isSgAssignOp(expr->get_expression())) - if (SgVarRefExp* var_ref = isSgVarRefExp(op->get_lhs_operand())) - vs = var_ref->get_symbol(); - } else if (tfortran) { - SgExpression* init = tfortran->get_initialization(); - - if (SgAssignOp* op = isSgAssignOp(init)) - if (SgVarRefExp* var_ref = isSgVarRefExp(op->get_lhs_operand())) - vs = var_ref->get_symbol(); - - } - - if (vs == NULL) - throw ir_error("Index variable is NULL!!"); - - return new IR_roseScalarSymbol(ir_, vs); -} - -omega::CG_outputRepr *IR_roseLoop::lower_bound() const { - SgForStatement *tf = isSgForStatement(tf_); - SgFortranDo *tfortran = isSgFortranDo(tf_); - - SgExpression* lowerBound = NULL; - - if (tf) { - SgForInitStatement* list = tf->get_for_init_stmt(); - SgStatementPtrList& initStatements = list->get_init_stmt(); - SgStatementPtrList::const_iterator j = initStatements.begin(); - - if (SgExprStatement *expr = isSgExprStatement(*j)) - if (SgAssignOp* op = isSgAssignOp(expr->get_expression())) { - lowerBound = op->get_rhs_operand(); - //Rose sometimes introduces an unnecessary cast which is a unary op - if (isSgUnaryOp(lowerBound)) - lowerBound = isSgUnaryOp(lowerBound)->get_operand(); - - } - } else if (tfortran) { - SgExpression* init = tfortran->get_initialization(); - - if (SgAssignOp* op = isSgAssignOp(init)) - lowerBound = op->get_rhs_operand(); - } - - if (lowerBound == NULL) - throw ir_error("Lower Bound is NULL!!"); - - return new omega::CG_roseRepr(lowerBound); -} - -omega::CG_outputRepr *IR_roseLoop::upper_bound() const { - SgForStatement *tf = isSgForStatement(tf_); - SgFortranDo *tfortran = isSgFortranDo(tf_); - SgExpression* upperBound = NULL; - if (tf) { - SgBinaryOp* test_expr = isSgBinaryOp(tf->get_test_expr()); - if (test_expr == NULL) - throw ir_error("Test Expression is NULL!!"); - - upperBound = test_expr->get_rhs_operand(); - //Rose sometimes introduces an unnecessary cast which is a unary op - if (isSgUnaryOp(upperBound)) - upperBound = isSgUnaryOp(upperBound)->get_operand(); - if (upperBound == NULL) - throw ir_error("Upper Bound is NULL!!"); - } else if (tfortran) { - - upperBound = tfortran->get_bound(); - - } - - return new omega::CG_roseRepr(upperBound); - -} - -IR_CONDITION_TYPE IR_roseLoop::stop_cond() const { - SgForStatement *tf = isSgForStatement(tf_); - SgFortranDo *tfortran = isSgFortranDo(tf_); - - if (tf) { - SgExpression* stopCond = NULL; - SgExpression* test_expr = tf->get_test_expr(); - - if (isSgLessThanOp(test_expr)) - return IR_COND_LT; - else if (isSgLessOrEqualOp(test_expr)) - return IR_COND_LE; - else if (isSgGreaterThanOp(test_expr)) - return IR_COND_GT; - else if (isSgGreaterOrEqualOp(test_expr)) - return IR_COND_GE; - - else - throw ir_error("loop stop condition unsupported"); - } else if (tfortran) { - SgExpression* increment = tfortran->get_increment(); - if (!isSgNullExpression(increment)) { - if (isSgMinusOp(increment) - && !isSgBinaryOp(isSgMinusOp(increment)->get_operand())) - return IR_COND_GE; - else - return IR_COND_LE; - } else { - return IR_COND_LE; // Manu:: if increment is not present, assume it to be 1. Just a workaround, not sure if it will be correct for all cases. - SgExpression* lowerBound = NULL; - SgExpression* upperBound = NULL; - SgExpression* init = tfortran->get_initialization(); - SgIntVal* ub; - SgIntVal* lb; - if (SgAssignOp* op = isSgAssignOp(init)) - lowerBound = op->get_rhs_operand(); - - upperBound = tfortran->get_bound(); - - if ((upperBound != NULL) && (lowerBound != NULL)) { - - if ((ub = isSgIntVal(isSgValueExp(upperBound))) && (lb = - isSgIntVal(isSgValueExp(lowerBound)))) { - if (ub->get_value() > lb->get_value()) - return IR_COND_LE; - else - return IR_COND_GE; - } else - throw ir_error("loop stop condition unsupported"); - - } else - throw ir_error("malformed fortran loop bounds!!"); - - } - } - -} - -IR_Block *IR_roseLoop::body() const { - SgForStatement *tf = isSgForStatement(tf_); - SgFortranDo *tfortran = isSgFortranDo(tf_); - SgNode* loop_body = NULL; - SgStatement* body_statements = NULL; - - if (tf) { - body_statements = tf->get_loop_body(); - } else if (tfortran) { - body_statements = isSgStatement(tfortran->get_body()); - - } - - loop_body = isSgNode(body_statements); - - SgStatementPtrList list; - if (isSgBasicBlock(loop_body)) { - list = isSgBasicBlock(loop_body)->get_statements(); - - if (list.size() == 1) - loop_body = isSgNode(*(list.begin())); - } - - if (loop_body == NULL) - throw ir_error("for loop body is NULL!!"); - - return new IR_roseBlock(ir_, loop_body); -} - -int IR_roseLoop::step_size() const { - - SgForStatement *tf = isSgForStatement(tf_); - SgFortranDo *tfortran = isSgFortranDo(tf_); - - if (tf) { - SgExpression *increment = tf->get_increment(); - - if (isSgPlusPlusOp(increment)) - return 1; - if (isSgMinusMinusOp(increment)) - return -1; - else if (SgAssignOp* assignment = isSgAssignOp(increment)) { - SgBinaryOp* stepsize = isSgBinaryOp(assignment->get_lhs_operand()); - if (stepsize == NULL) - throw ir_error("Step size expression is NULL!!"); - SgIntVal* step = isSgIntVal(stepsize->get_lhs_operand()); - return step->get_value(); - } else if (SgBinaryOp* inc = isSgPlusAssignOp(increment)) { - SgIntVal* step = isSgIntVal(inc->get_rhs_operand()); - return (step->get_value()); - } else if (SgBinaryOp * inc = isSgMinusAssignOp(increment)) { - SgIntVal* step = isSgIntVal(inc->get_rhs_operand()); - return -(step->get_value()); - } else if (SgBinaryOp * inc = isSgCompoundAssignOp(increment)) { - SgIntVal* step = isSgIntVal(inc->get_rhs_operand()); - return (step->get_value()); - } - - } else if (tfortran) { - - SgExpression* increment = tfortran->get_increment(); - - if (!isSgNullExpression(increment)) { - if (isSgMinusOp(increment)) { - if (SgValueExp *inc = isSgValueExp( - isSgMinusOp(increment)->get_operand())) - if (isSgIntVal(inc)) - return -(isSgIntVal(inc)->get_value()); - } else { - if (SgValueExp* inc = isSgValueExp(increment)) - if (isSgIntVal(inc)) - return isSgIntVal(inc)->get_value(); - } - } else { - return 1; // Manu:: if increment is not present, assume it to be 1. Just a workaround, not sure if it will be correct for all cases. - SgExpression* lowerBound = NULL; - SgExpression* upperBound = NULL; - SgExpression* init = tfortran->get_initialization(); - SgIntVal* ub; - SgIntVal* lb; - if (SgAssignOp* op = isSgAssignOp(init)) - lowerBound = op->get_rhs_operand(); - - upperBound = tfortran->get_bound(); - - if ((upperBound != NULL) && (lowerBound != NULL)) { - - if ((ub = isSgIntVal(isSgValueExp(upperBound))) && (lb = - isSgIntVal(isSgValueExp(lowerBound)))) { - if (ub->get_value() > lb->get_value()) - return 1; - else - return -1; - } else - throw ir_error("loop stop condition unsupported"); - - } else - throw ir_error("loop stop condition unsupported"); - - } - - } - -} - -IR_Block *IR_roseLoop::convert() { - const IR_Code *ir = ir_; - SgNode *tnl = isSgNode(tf_); - delete this; - return new IR_roseBlock(ir, tnl); -} - -IR_Control *IR_roseLoop::clone() const { - - return new IR_roseLoop(ir_, tf_); - -} - -// ---------------------------------------------------------------------------- -// Class: IR_roseBlock -// ---------------------------------------------------------------------------- - -omega::CG_outputRepr *IR_roseBlock::original() const { - - omega::CG_outputRepr * tnl; - - if (isSgBasicBlock(tnl_)) { - - SgStatementPtrList *bb = new SgStatementPtrList(); - SgStatementPtrList::iterator it; - for (it = (isSgBasicBlock(tnl_)->get_statements()).begin(); - it != (isSgBasicBlock(tnl_)->get_statements()).end() - && (*it != start_); it++) - ; - - if (it != (isSgBasicBlock(tnl_)->get_statements()).end()) { - for (; it != (isSgBasicBlock(tnl_)->get_statements()).end(); it++) { - bb->push_back(*it); - if ((*it) == end_) - break; - } - } - tnl = new omega::CG_roseRepr(bb); - - } else { - - tnl = new omega::CG_roseRepr(tnl_); - - } - - return tnl; - -} -omega::CG_outputRepr *IR_roseBlock::extract() const { - - std::string x = tnl_->unparseToString(); - - omega::CG_roseRepr * tnl; - - omega::CG_outputRepr* block; - - if (isSgBasicBlock(tnl_)) { - - SgStatementPtrList *bb = new SgStatementPtrList(); - SgStatementPtrList::iterator it; - for (it = (isSgBasicBlock(tnl_)->get_statements()).begin(); - it != (isSgBasicBlock(tnl_)->get_statements()).end() - && (*it != start_); it++) - ; - - if (it != (isSgBasicBlock(tnl_)->get_statements()).end()) { - for (; it != (isSgBasicBlock(tnl_)->get_statements()).end(); it++) { - bb->push_back(*it); - if ((*it) == end_) - break; - } - } - tnl = new omega::CG_roseRepr(bb); - block = tnl->clone(); - - } else { - tnl = new omega::CG_roseRepr(tnl_); - - block = tnl->clone(); - } - - delete tnl; - return block; -} - -IR_Control *IR_roseBlock::clone() const { - return new IR_roseBlock(ir_, tnl_, start_, end_); - -} -// ---------------------------------------------------------------------------- -// Class: IR_roseIf -// ---------------------------------------------------------------------------- -omega::CG_outputRepr *IR_roseIf::condition() const { - SgNode *tnl = isSgNode(isSgIfStmt(ti_)->get_conditional()); - SgExpression* exp = NULL; - if (SgExprStatement* stmt = isSgExprStatement(tnl)) - exp = stmt->get_expression(); - if (exp == NULL) - return new omega::CG_roseRepr(tnl); - else - return new omega::CG_roseRepr(exp); -} - -IR_Block *IR_roseIf::then_body() const { - SgNode *tnl = isSgNode(isSgIfStmt(ti_)->get_true_body()); - - if (tnl == NULL) - return NULL; - - return new IR_roseBlock(ir_, tnl); -} - -IR_Block *IR_roseIf::else_body() const { - SgNode *tnl = isSgNode(isSgIfStmt(ti_)->get_false_body()); - - if (tnl == NULL) - return NULL; - - return new IR_roseBlock(ir_, tnl); -} - -IR_Block *IR_roseIf::convert() { - const IR_Code *ir = ir_; - delete this; - return new IR_roseBlock(ir, ti_); -} - -IR_Control *IR_roseIf::clone() const { - return new IR_roseIf(ir_, ti_); -} - -// -----------------------------------------------------------y----------------- -// Class: IR_roseCode_Global_Init -// ---------------------------------------------------------------------------- - -IR_roseCode_Global_Init *IR_roseCode_Global_Init::pinstance = 0; - -IR_roseCode_Global_Init * IR_roseCode_Global_Init::Instance(char** argv) { - if (pinstance == 0) { - pinstance = new IR_roseCode_Global_Init; - pinstance->project = frontend(2, argv); - - } - return pinstance; -} - -// ---------------------------------------------------------------------------- -// Class: IR_roseCode -// ---------------------------------------------------------------------------- - -IR_roseCode::IR_roseCode(const char *filename, const char* proc_name) : - IR_Code() { - - SgProject* project; - - char* argv[2]; - int counter = 0; - argv[0] = (char*) malloc(5 * sizeof(char)); - argv[1] = (char*) malloc((strlen(filename) + 1) * sizeof(char)); - strcpy(argv[0], "rose"); - strcpy(argv[1], filename); - - project = (IR_roseCode_Global_Init::Instance(argv))->project; - firstScope = getFirstGlobalScope(project); - SgFilePtrList& file_list = project->get_fileList(); - - for (SgFilePtrList::iterator it = file_list.begin(); it != file_list.end(); - it++) { - file = isSgSourceFile(*it); - if (file->get_outputLanguage() == SgFile::e_Fortran_output_language) - is_fortran_ = true; - else - is_fortran_ = false; - - root = file->get_globalScope(); - - if (!is_fortran_) { // Manu:: this macro should not be created if the input code is in fortran - buildCpreprocessorDefineDeclaration(root, - "#define __rose_lt(x,y) ((x)<(y)?(x):(y))", - PreprocessingInfo::before); - buildCpreprocessorDefineDeclaration(root, - "#define __rose_gt(x,y) ((x)>(y)?(x):(y))", - PreprocessingInfo::before); - } - - symtab_ = isSgScopeStatement(root)->get_symbol_table(); - SgDeclarationStatementPtrList& declList = root->get_declarations(); - - p = declList.begin(); - - while (p != declList.end()) { - func = isSgFunctionDeclaration(*p); - if (func) { - if (!strcmp((func->get_name().getString()).c_str(), proc_name)) - break; - - } - p++; - counter++; - } - if (p != declList.end()) - break; - - } - - symtab2_ = func->get_definition()->get_symbol_table(); - symtab3_ = func->get_definition()->get_body()->get_symbol_table(); - // Manu:: added is_fortran_ parameter - // TODO Substitute it with a better builder - ocg_ = new omega::CG_roseBuilder(is_fortran_, root, firstScope, - func->get_definition()->get_symbol_table(), - func->get_definition()->get_body()->get_symbol_table(), - isSgNode(func->get_definition()->get_body())); - - i_ = 0; /*i_ handling may need revision */ - - free(argv[1]); - free(argv[0]); - -} - -IR_roseCode::~IR_roseCode() { -} - -void IR_roseCode::finalizeRose() { - SgProject* project = (IR_roseCode_Global_Init::Instance(NULL))->project; - project->unparse(); -} - -IR_ScalarSymbol *IR_roseCode::CreateScalarSymbol(const IR_Symbol *sym, int) { - char str1[14]; - if (typeid(*sym) == typeid(IR_roseScalarSymbol)) { - SgType *tn = - static_cast<const IR_roseScalarSymbol *>(sym)->vs_->get_type(); - sprintf(str1, "newVariable%i", i_); - SgVariableDeclaration* defn = buildVariableDeclaration(str1, tn); - i_++; - - SgInitializedNamePtrList& variables = defn->get_variables(); - SgInitializedNamePtrList::const_iterator i = variables.begin(); - SgInitializedName* initializedName = *i; - SgVariableSymbol* vs = new SgVariableSymbol(initializedName); - - prependStatement(defn, - isSgScopeStatement(func->get_definition()->get_body())); - vs->set_parent(symtab_); - symtab_->insert(str1, vs); - - if (vs == NULL) - throw ir_error("in CreateScalarSymbol: vs is NULL!!"); - - return new IR_roseScalarSymbol(this, vs); - } else if (typeid(*sym) == typeid(IR_roseArraySymbol)) { - SgType *tn1 = - static_cast<const IR_roseArraySymbol *>(sym)->vs_->get_type(); - while (isSgArrayType(tn1) || isSgPointerType(tn1)) { - if (isSgArrayType(tn1)) - tn1 = isSgArrayType(tn1)->get_base_type(); - else if (isSgPointerType(tn1)) - tn1 = isSgPointerType(tn1)->get_base_type(); - else - throw ir_error( - "in CreateScalarSymbol: symbol not an array nor a pointer!"); - } - - sprintf(str1, "newVariable%i", i_); - i_++; - - SgVariableDeclaration* defn1 = buildVariableDeclaration(str1, tn1); - SgInitializedNamePtrList& variables1 = defn1->get_variables(); - - SgInitializedNamePtrList::const_iterator i1 = variables1.begin(); - SgInitializedName* initializedName1 = *i1; - - SgVariableSymbol *vs1 = new SgVariableSymbol(initializedName1); - prependStatement(defn1, - isSgScopeStatement(func->get_definition()->get_body())); - - vs1->set_parent(symtab_); - symtab_->insert(str1, vs1); - - if (vs1 == NULL) - throw ir_error("in CreateScalarSymbol: vs1 is NULL!!"); - - return new IR_roseScalarSymbol(this, vs1); - } else - throw std::bad_typeid(); - -} - -IR_ArraySymbol *IR_roseCode::CreateArraySymbol(const IR_Symbol *sym, - std::vector<omega::CG_outputRepr *> &size, int) { - SgType *tn; - char str1[14]; - - if (typeid(*sym) == typeid(IR_roseScalarSymbol)) { - tn = static_cast<const IR_roseScalarSymbol *>(sym)->vs_->get_type(); - } else if (typeid(*sym) == typeid(IR_roseArraySymbol)) { - tn = static_cast<const IR_roseArraySymbol *>(sym)->vs_->get_type(); - while (isSgArrayType(tn) || isSgPointerType(tn)) { - if (isSgArrayType(tn)) - tn = isSgArrayType(tn)->get_base_type(); - else if (isSgPointerType(tn)) - tn = isSgPointerType(tn)->get_base_type(); - else - throw ir_error( - "in CreateScalarSymbol: symbol not an array nor a pointer!"); - } - } else - throw std::bad_typeid(); - - - // Manu:: Fortran support - std::vector<SgExpression *>exprs; - SgExprListExp *exprLstExp; - SgExpression* sizeExpression = new SgNullExpression(); - SgArrayType* arrayType = new SgArrayType(tn,sizeExpression); - sizeExpression->set_parent(arrayType); - - if (!is_fortran_) { - for (int i = size.size() - 1; i >= 0; i--) { - tn = buildArrayType(tn,static_cast<omega::CG_roseRepr *>(size[i])->GetExpression()); - } - } else { // Manu:: required for fortran support - for (int i = size.size() - 1; i >= 0; i--) { - exprs.push_back(static_cast<omega::CG_roseRepr *>(size[i])->GetExpression()); - } - } - - if (is_fortran_) { - exprLstExp = buildExprListExp(exprs); - arrayType->set_dim_info(exprLstExp); - exprLstExp->set_parent(arrayType); - arrayType->set_rank(exprLstExp->get_expressions().size()); - } - - static int rose_array_counter = 1; - SgVariableDeclaration* defn2; - std::string s; - if (!is_fortran_) { - s = std::string("_P") + omega::to_string(rose_array_counter++); - defn2 = buildVariableDeclaration(const_cast<char *>(s.c_str()), tn); - } else {// Manu:: fortran support - s = std::string("f_P") + omega::to_string(rose_array_counter++); - defn2 = buildVariableDeclaration(const_cast<char *>(s.c_str()), arrayType); - } - - - SgInitializedNamePtrList& variables2 = defn2->get_variables(); - - SgInitializedNamePtrList::const_iterator i2 = variables2.begin(); - SgInitializedName* initializedName2 = *i2; - SgVariableSymbol *vs = new SgVariableSymbol(initializedName2); - - prependStatement(defn2, - isSgScopeStatement(func->get_definition()->get_body())); - - vs->set_parent(symtab_); - symtab_->insert(SgName(s.c_str()), vs); - - return new IR_roseArraySymbol(this, vs); -} - -IR_ScalarRef *IR_roseCode::CreateScalarRef(const IR_ScalarSymbol *sym) { - return new IR_roseScalarRef(this, - buildVarRefExp(static_cast<const IR_roseScalarSymbol *>(sym)->vs_)); - -} - -IR_ArrayRef *IR_roseCode::CreateArrayRef(const IR_ArraySymbol *sym, - std::vector<omega::CG_outputRepr *> &index) { - - int t; - - if (sym->n_dim() != index.size()) - throw std::invalid_argument("incorrect array symbol dimensionality"); - - const IR_roseArraySymbol *l_sym = - static_cast<const IR_roseArraySymbol *>(sym); - - SgVariableSymbol *vs = l_sym->vs_; - SgExpression* ia1 = buildVarRefExp(vs); - - - - if (is_fortran_) { // Manu:: fortran support - std::vector<SgExpression *>exprs; - for (int i = 0 ; i < index.size(); i++) { - exprs.push_back(static_cast<omega::CG_roseRepr *>(index[i])->GetExpression()); - } - SgExprListExp *exprLstExp; - exprLstExp = buildExprListExp(exprs); - ia1 = buildPntrArrRefExp(ia1,exprLstExp); - } else { - for (int i = 0; i < index.size(); i++) { - - ia1 = buildPntrArrRefExp(ia1, - static_cast<omega::CG_roseRepr *>(index[i])->GetExpression()); - - } - } - - SgPntrArrRefExp *ia = isSgPntrArrRefExp(ia1); - - return new IR_roseArrayRef(this, ia, -1); - -} - -std::vector<IR_ScalarRef *> IR_roseCode::FindScalarRef( - const omega::CG_outputRepr *repr) const { - std::vector<IR_ScalarRef *> scalars; - SgNode *tnl = static_cast<const omega::CG_roseRepr *>(repr)->GetCode(); - SgStatementPtrList *list = - static_cast<const omega::CG_roseRepr *>(repr)->GetList(); - SgStatement* stmt; - SgExpression * exp; - - if (list != NULL) { - for (SgStatementPtrList::iterator it = (*list).begin(); - it != (*list).end(); it++) { - omega::CG_roseRepr *r = new omega::CG_roseRepr(isSgNode(*it)); - std::vector<IR_ScalarRef *> a = FindScalarRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(scalars)); - } - } - - else if (tnl != NULL) { - if (stmt = isSgStatement(tnl)) { - if (isSgBasicBlock(stmt)) { - SgStatementPtrList& stmts = - isSgBasicBlock(stmt)->get_statements(); - for (int i = 0; i < stmts.size(); i++) { - omega::CG_roseRepr *r = new omega::CG_roseRepr( - isSgNode(stmts[i])); - std::vector<IR_ScalarRef *> a = FindScalarRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(scalars)); - } - - } else if (isSgForStatement(stmt)) { - - SgForStatement *tnf = isSgForStatement(stmt); - omega::CG_roseRepr *r = new omega::CG_roseRepr( - isSgStatement(tnf->get_loop_body())); - std::vector<IR_ScalarRef *> a = FindScalarRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(scalars)); - } else if (isSgFortranDo(stmt)) { - SgFortranDo *tfortran = isSgFortranDo(stmt); - omega::CG_roseRepr *r = new omega::CG_roseRepr( - isSgStatement(tfortran->get_body())); - std::vector<IR_ScalarRef *> a = FindScalarRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(scalars)); - } else if (isSgIfStmt(stmt)) { - SgIfStmt* tni = isSgIfStmt(stmt); - omega::CG_roseRepr *r = new omega::CG_roseRepr( - isSgNode(tni->get_conditional())); - std::vector<IR_ScalarRef *> a = FindScalarRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(scalars)); - r = new omega::CG_roseRepr(isSgNode(tni->get_true_body())); - a = FindScalarRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(scalars)); - r = new omega::CG_roseRepr(isSgNode(tni->get_false_body())); - a = FindScalarRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(scalars)); - } else if (isSgExprStatement(stmt)) { - omega::CG_roseRepr *r = new omega::CG_roseRepr( - isSgExpression( - isSgExprStatement(stmt)->get_expression())); - std::vector<IR_ScalarRef *> a = FindScalarRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(scalars)); - - } - } - } else { - SgExpression* op = - static_cast<const omega::CG_roseRepr *>(repr)->GetExpression(); - if (isSgVarRefExp(op) - && (!isSgArrayType(isSgVarRefExp(op)->get_type()))) { - if (SgBinaryOp* op_ = isSgBinaryOp( - isSgVarRefExp(op)->get_parent())) { - if (SgCompoundAssignOp *op__ = isSgCompoundAssignOp(op_)) { - if (isSgCompoundAssignOp(op_)->get_lhs_operand() - == isSgVarRefExp(op)) { - scalars.push_back( - new IR_roseScalarRef(this, isSgVarRefExp(op), - 1)); - scalars.push_back( - new IR_roseScalarRef(this, isSgVarRefExp(op), - 0)); - } - } - } else if (SgAssignOp* assmt = isSgAssignOp( - isSgVarRefExp(op)->get_parent())) { - - if (assmt->get_lhs_operand() == isSgVarRefExp(op)) - scalars.push_back( - new IR_roseScalarRef(this, isSgVarRefExp(op), 1)); - } else if (SgAssignOp * assmt = isSgAssignOp( - isSgVarRefExp(op)->get_parent())) { - - if (assmt->get_rhs_operand() == isSgVarRefExp(op)) - scalars.push_back( - new IR_roseScalarRef(this, isSgVarRefExp(op), 0)); - } else - scalars.push_back( - new IR_roseScalarRef(this, isSgVarRefExp(op), 0)); - } else if (isSgAssignOp(op)) { - omega::CG_roseRepr *r1 = new omega::CG_roseRepr( - isSgAssignOp(op)->get_lhs_operand()); - std::vector<IR_ScalarRef *> a1 = FindScalarRef(r1); - delete r1; - std::copy(a1.begin(), a1.end(), back_inserter(scalars)); - omega::CG_roseRepr *r2 = new omega::CG_roseRepr( - isSgAssignOp(op)->get_rhs_operand()); - std::vector<IR_ScalarRef *> a2 = FindScalarRef(r2); - delete r2; - std::copy(a2.begin(), a2.end(), back_inserter(scalars)); - - } else if (isSgBinaryOp(op)) { - omega::CG_roseRepr *r1 = new omega::CG_roseRepr( - isSgBinaryOp(op)->get_lhs_operand()); - std::vector<IR_ScalarRef *> a1 = FindScalarRef(r1); - delete r1; - std::copy(a1.begin(), a1.end(), back_inserter(scalars)); - omega::CG_roseRepr *r2 = new omega::CG_roseRepr( - isSgBinaryOp(op)->get_rhs_operand()); - std::vector<IR_ScalarRef *> a2 = FindScalarRef(r2); - delete r2; - std::copy(a2.begin(), a2.end(), back_inserter(scalars)); - } else if (isSgUnaryOp(op)) { - omega::CG_roseRepr *r1 = new omega::CG_roseRepr( - isSgUnaryOp(op)->get_operand()); - std::vector<IR_ScalarRef *> a1 = FindScalarRef(r1); - delete r1; - std::copy(a1.begin(), a1.end(), back_inserter(scalars)); - } - - } - return scalars; - -} - -std::vector<IR_ArrayRef *> IR_roseCode::FindArrayRef( - const omega::CG_outputRepr *repr) const { - std::vector<IR_ArrayRef *> arrays; - SgNode *tnl = static_cast<const omega::CG_roseRepr *>(repr)->GetCode(); - SgStatementPtrList* list = - static_cast<const omega::CG_roseRepr *>(repr)->GetList(); - SgStatement* stmt; - SgExpression * exp; - - if (list != NULL) { - for (SgStatementPtrList::iterator it = (*list).begin(); - it != (*list).end(); it++) { - omega::CG_roseRepr *r = new omega::CG_roseRepr(isSgNode(*it)); - std::vector<IR_ArrayRef *> a = FindArrayRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(arrays)); - } - } else if (tnl != NULL) { - if (stmt = isSgStatement(tnl)) { - if (isSgBasicBlock(stmt)) { - SgStatementPtrList& stmts = - isSgBasicBlock(stmt)->get_statements(); - for (int i = 0; i < stmts.size(); i++) { - omega::CG_roseRepr *r = new omega::CG_roseRepr( - isSgNode(stmts[i])); - std::vector<IR_ArrayRef *> a = FindArrayRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(arrays)); - } - - } else if (isSgForStatement(stmt)) { - - SgForStatement *tnf = isSgForStatement(stmt); - omega::CG_roseRepr *r = new omega::CG_roseRepr( - isSgStatement(tnf->get_loop_body())); - std::vector<IR_ArrayRef *> a = FindArrayRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(arrays)); - } else if (isSgFortranDo(stmt)) { - SgFortranDo *tfortran = isSgFortranDo(stmt); - omega::CG_roseRepr *r = new omega::CG_roseRepr( - isSgStatement(tfortran->get_body())); - std::vector<IR_ArrayRef *> a = FindArrayRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(arrays)); - } else if (isSgIfStmt(stmt)) { - SgIfStmt* tni = isSgIfStmt(stmt); - omega::CG_roseRepr *r = new omega::CG_roseRepr( - isSgNode(tni->get_conditional())); - std::vector<IR_ArrayRef *> a = FindArrayRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(arrays)); - r = new omega::CG_roseRepr(isSgNode(tni->get_true_body())); - a = FindArrayRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(arrays)); - r = new omega::CG_roseRepr(isSgNode(tni->get_false_body())); - a = FindArrayRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(arrays)); - } else if (isSgExprStatement(stmt)) { - omega::CG_roseRepr *r = new omega::CG_roseRepr( - isSgExpression( - isSgExprStatement(stmt)->get_expression())); - std::vector<IR_ArrayRef *> a = FindArrayRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(arrays)); - - } - } - } else { - SgExpression* op = - static_cast<const omega::CG_roseRepr *>(repr)->GetExpression(); - if (isSgPntrArrRefExp(op)) { - - SgVarRefExp* base; - SgExpression* op2; - if (isSgCompoundAssignOp(isSgPntrArrRefExp(op)->get_parent())) { - IR_roseArrayRef *ref1 = new IR_roseArrayRef(this, - isSgPntrArrRefExp(op), 0); - arrays.push_back(ref1); - IR_roseArrayRef *ref2 = new IR_roseArrayRef(this, - isSgPntrArrRefExp(op), 1); - arrays.push_back(ref2); - } else { - IR_roseArrayRef *ref3 = new IR_roseArrayRef(this, - isSgPntrArrRefExp(op), -1); - arrays.push_back(ref3); - - while (isSgPntrArrRefExp(op)) { - op2 = isSgPntrArrRefExp(op)->get_rhs_operand(); - op = isSgPntrArrRefExp(op)->get_lhs_operand(); - omega::CG_roseRepr *r = new omega::CG_roseRepr(op2); - std::vector<IR_ArrayRef *> a = FindArrayRef(r); - delete r; - std::copy(a.begin(), a.end(), back_inserter(arrays)); - - } - } - } else if (isSgAssignOp(op)) { - omega::CG_roseRepr *r1 = new omega::CG_roseRepr( - isSgAssignOp(op)->get_lhs_operand()); - std::vector<IR_ArrayRef *> a1 = FindArrayRef(r1); - delete r1; - std::copy(a1.begin(), a1.end(), back_inserter(arrays)); - omega::CG_roseRepr *r2 = new omega::CG_roseRepr( - isSgAssignOp(op)->get_rhs_operand()); - std::vector<IR_ArrayRef *> a2 = FindArrayRef(r2); - delete r2; - std::copy(a2.begin(), a2.end(), back_inserter(arrays)); - - } else if (isSgBinaryOp(op)) { - omega::CG_roseRepr *r1 = new omega::CG_roseRepr( - isSgBinaryOp(op)->get_lhs_operand()); - std::vector<IR_ArrayRef *> a1 = FindArrayRef(r1); - delete r1; - std::copy(a1.begin(), a1.end(), back_inserter(arrays)); - omega::CG_roseRepr *r2 = new omega::CG_roseRepr( - isSgBinaryOp(op)->get_rhs_operand()); - std::vector<IR_ArrayRef *> a2 = FindArrayRef(r2); - delete r2; - std::copy(a2.begin(), a2.end(), back_inserter(arrays)); - } else if (isSgUnaryOp(op)) { - omega::CG_roseRepr *r1 = new omega::CG_roseRepr( - isSgUnaryOp(op)->get_operand()); - std::vector<IR_ArrayRef *> a1 = FindArrayRef(r1); - delete r1; - std::copy(a1.begin(), a1.end(), back_inserter(arrays)); - } - - } - return arrays; -} - -std::vector<IR_Control *> IR_roseCode::FindOneLevelControlStructure( - const IR_Block *block) const { - - std::vector<IR_Control *> controls; - int i; - int j; - int begin; - int end; - SgNode* tnl_ = - ((static_cast<IR_roseBlock *>(const_cast<IR_Block *>(block)))->tnl_); - - if (isSgForStatement(tnl_)) - controls.push_back(new IR_roseLoop(this, tnl_)); - else if (isSgFortranDo(tnl_)) - controls.push_back(new IR_roseLoop(this, tnl_)); - else if (isSgIfStmt(tnl_)) - controls.push_back(new IR_roseIf(this, tnl_)); - - else if (isSgBasicBlock(tnl_)) { - - SgStatementPtrList& stmts = isSgBasicBlock(tnl_)->get_statements(); - - for (i = 0; i < stmts.size(); i++) { - if (isSgNode(stmts[i]) - == ((static_cast<IR_roseBlock *>(const_cast<IR_Block *>(block)))->start_)) - begin = i; - if (isSgNode(stmts[i]) - == ((static_cast<IR_roseBlock *>(const_cast<IR_Block *>(block)))->end_)) - end = i; - } - - SgNode* start = NULL; - SgNode* prev = NULL; - for (i = begin; i <= end; i++) { - if (isSgForStatement(stmts[i]) || isSgFortranDo(stmts[i])) { - if (start != NULL) { - controls.push_back( - new IR_roseBlock(this, - (static_cast<IR_roseBlock *>(const_cast<IR_Block *>(block)))->tnl_, - start, prev)); - start = NULL; - } - controls.push_back(new IR_roseLoop(this, isSgNode(stmts[i]))); - } else if (isSgIfStmt(stmts[i])) { - if (start != NULL) { - controls.push_back( - new IR_roseBlock(this, - (static_cast<IR_roseBlock *>(const_cast<IR_Block *>(block)))->tnl_, - start, prev)); - start = NULL; - } - controls.push_back(new IR_roseIf(this, isSgNode(stmts[i]))); - - } else if (start == NULL) - start = isSgNode(stmts[i]); - - prev = isSgNode(stmts[i]); - } - - if ((start != NULL) && (start != isSgNode(stmts[begin]))) - controls.push_back( - new IR_roseBlock(this, - (static_cast<IR_roseBlock *>(const_cast<IR_Block *>(block)))->tnl_, - start, prev)); - } - - return controls; - -} - -IR_Block *IR_roseCode::MergeNeighboringControlStructures( - const std::vector<IR_Control *> &controls) const { - if (controls.size() == 0) - return NULL; - - SgNode *tnl = NULL; - SgNode *start, *end; - for (int i = 0; i < controls.size(); i++) { - switch (controls[i]->type()) { - case IR_CONTROL_LOOP: { - SgNode *tf = static_cast<IR_roseLoop *>(controls[i])->tf_; - if (tnl == NULL) { - tnl = tf->get_parent(); - start = end = tf; - } else { - if (tnl != tf->get_parent()) - throw ir_error("controls to merge not at the same level"); - end = tf; - } - break; - } - case IR_CONTROL_BLOCK: { - if (tnl == NULL) { - tnl = static_cast<IR_roseBlock *>(controls[0])->tnl_; - start = static_cast<IR_roseBlock *>(controls[0])->start_; - end = static_cast<IR_roseBlock *>(controls[0])->end_; - } else { - if (tnl != static_cast<IR_roseBlock *>(controls[0])->tnl_) - throw ir_error("controls to merge not at the same level"); - end = static_cast<IR_roseBlock *>(controls[0])->end_; - } - break; - } - default: - throw ir_error("unrecognized control to merge"); - } - } - - return new IR_roseBlock(controls[0]->ir_, tnl, start, end); -} - -IR_Block *IR_roseCode::GetCode() const { - SgFunctionDefinition* def = NULL; - SgBasicBlock* block = NULL; - if (func != 0) { - if (def = func->get_definition()) { - if (block = def->get_body()) - return new IR_roseBlock(this, - func->get_definition()->get_body()); - } - } - - return NULL; - -} - -void IR_roseCode::ReplaceCode(IR_Control *old, omega::CG_outputRepr *repr) { - SgStatementPtrList *tnl = - static_cast<omega::CG_roseRepr *>(repr)->GetList(); - SgNode* node_ = static_cast<omega::CG_roseRepr *>(repr)->GetCode(); - SgNode * tf_old; - - /* May need future revision if tnl has more than one statement */ - - switch (old->type()) { - - case IR_CONTROL_LOOP: - tf_old = static_cast<IR_roseLoop *>(old)->tf_; - break; - case IR_CONTROL_BLOCK: - tf_old = static_cast<IR_roseBlock *>(old)->start_; - break; - - default: - throw ir_error("control structure to be replaced not supported"); - break; - } - - std::string y = tf_old->unparseToString(); - SgStatement *s = isSgStatement(tf_old); - if (s != 0) { - SgStatement *p = isSgStatement(tf_old->get_parent()); - - if (p != 0) { - SgStatement* temp = s; - if (tnl != NULL) { - SgStatementPtrList::iterator it = (*tnl).begin(); - p->insert_statement(temp, *it, true); - temp = *it; - p->remove_statement(s); - it++; - for (; it != (*tnl).end(); it++) { - p->insert_statement(temp, *it, false); - temp = *it; - } - } else if (node_ != NULL) { - if (!isSgStatement(node_)) - throw ir_error("Replacing Code not a statement!"); - else { - SgStatement* replace_ = isSgStatement(node_); - p->insert_statement(s, replace_, true); - p->remove_statement(s); - - } - } else { - throw ir_error("Replacing Code not a statement!"); - } - } else - throw ir_error("Replacing Code not a statement!"); - } else - throw ir_error("Replacing Code not a statement!"); - - delete old; - delete repr; -} - -void IR_roseCode::ReplaceExpression(IR_Ref *old, omega::CG_outputRepr *repr) { - - SgExpression* op = static_cast<omega::CG_roseRepr *>(repr)->GetExpression(); - - if (typeid(*old) == typeid(IR_roseArrayRef)) { - SgPntrArrRefExp* ia_orig = static_cast<IR_roseArrayRef *>(old)->ia_; - SgExpression* parent = isSgExpression(isSgNode(ia_orig)->get_parent()); - std::string x = isSgNode(op)->unparseToString(); - std::string y = isSgNode(ia_orig)->unparseToString(); - if (parent != NULL) { - std::string z = isSgNode(parent)->unparseToString(); - parent->replace_expression(ia_orig, op); - isSgNode(op)->set_parent(isSgNode(parent)); - } else { - SgStatement* parent_stmt = isSgStatement( - isSgNode(ia_orig)->get_parent()); - if (parent_stmt != NULL) - parent_stmt->replace_expression(ia_orig, op); - else - throw ir_error( - "ReplaceExpression: parent neither expression nor statement"); - } - } else - throw ir_error("replacing a scalar variable not implemented"); - - delete old; -} - -IR_OPERATION_TYPE IR_roseCode::QueryExpOperation( - const omega::CG_outputRepr *repr) const { - SgExpression* op = - static_cast<const omega::CG_roseRepr *>(repr)->GetExpression(); - - if (isSgValueExp(op)) - return IR_OP_CONSTANT; - else if (isSgVarRefExp(op) || isSgPntrArrRefExp(op)) - return IR_OP_VARIABLE; - else if (isSgAssignOp(op) || isSgCompoundAssignOp(op)) - return IR_OP_ASSIGNMENT; - else if (isSgAddOp(op)) - return IR_OP_PLUS; - else if (isSgSubtractOp(op)) - return IR_OP_MINUS; - else if (isSgMultiplyOp(op)) - return IR_OP_MULTIPLY; - else if (isSgDivideOp(op)) - return IR_OP_DIVIDE; - else if (isSgMinusOp(op)) - return IR_OP_NEGATIVE; - else if (isSgConditionalExp(op)) { - SgExpression* cond = isSgConditionalExp(op)->get_conditional_exp(); - if (isSgGreaterThanOp(cond)) - return IR_OP_MAX; - else if (isSgLessThanOp(cond)) - return IR_OP_MIN; - } else if (isSgUnaryAddOp(op)) - return IR_OP_POSITIVE; - else if (isSgNullExpression(op)) - return IR_OP_NULL; - else - return IR_OP_UNKNOWN; -} - -IR_CONDITION_TYPE IR_roseCode::QueryBooleanExpOperation( - const omega::CG_outputRepr *repr) const { - SgExpression* op2 = - static_cast<const omega::CG_roseRepr *>(repr)->GetExpression(); - SgNode* op; - - if (op2 == NULL) { - op = static_cast<const omega::CG_roseRepr *>(repr)->GetCode(); - - if (op != NULL) { - if (isSgExprStatement(op)) - op2 = isSgExprStatement(op)->get_expression(); - else - return IR_COND_UNKNOWN; - } else - return IR_COND_UNKNOWN; - } - - if (isSgEqualityOp(op2)) - return IR_COND_EQ; - else if (isSgNotEqualOp(op2)) - return IR_COND_NE; - else if (isSgLessThanOp(op2)) - return IR_COND_LT; - else if (isSgLessOrEqualOp(op2)) - return IR_COND_LE; - else if (isSgGreaterThanOp(op2)) - return IR_COND_GT; - else if (isSgGreaterOrEqualOp(op2)) - return IR_COND_GE; - - return IR_COND_UNKNOWN; - -} - -std::vector<omega::CG_outputRepr *> IR_roseCode::QueryExpOperand( - const omega::CG_outputRepr *repr) const { - std::vector<omega::CG_outputRepr *> v; - SgExpression* op1; - SgExpression* op2; - SgExpression* op = - static_cast<const omega::CG_roseRepr *>(repr)->GetExpression(); - omega::CG_roseRepr *repr1; - - if (isSgValueExp(op) || isSgVarRefExp(op)) { - omega::CG_roseRepr *repr = new omega::CG_roseRepr(op); - v.push_back(repr); - } else if (isSgAssignOp(op)) { - op1 = isSgAssignOp(op)->get_rhs_operand(); - repr1 = new omega::CG_roseRepr(op1); - v.push_back(repr1); - /*may be a problem as assignOp is a binaryop destop might be needed */ - } else if (isSgMinusOp(op)) { - op1 = isSgMinusOp(op)->get_operand(); - repr1 = new omega::CG_roseRepr(op1); - v.push_back(repr1); - } else if (isSgUnaryAddOp(op)) { - op1 = isSgUnaryAddOp(op)->get_operand(); - repr1 = new omega::CG_roseRepr(op1); - v.push_back(repr1); - } else if ((isSgAddOp(op) || isSgSubtractOp(op)) - || (isSgMultiplyOp(op) || isSgDivideOp(op))) { - op1 = isSgBinaryOp(op)->get_lhs_operand(); - repr1 = new omega::CG_roseRepr(op1); - v.push_back(repr1); - - op2 = isSgBinaryOp(op)->get_rhs_operand(); - repr1 = new omega::CG_roseRepr(op2); - v.push_back(repr1); - } else if (isSgConditionalExp(op)) { - SgExpression* cond = isSgConditionalExp(op)->get_conditional_exp(); - op1 = isSgBinaryOp(cond)->get_lhs_operand(); - repr1 = new omega::CG_roseRepr(op1); - v.push_back(repr1); - - op2 = isSgBinaryOp(cond)->get_rhs_operand(); - repr1 = new omega::CG_roseRepr(op2); - v.push_back(repr1); - } else if (isSgCompoundAssignOp(op)) { - SgExpression* cond = isSgCompoundAssignOp(op); - op1 = isSgBinaryOp(cond)->get_lhs_operand(); - repr1 = new omega::CG_roseRepr(op1); - v.push_back(repr1); - - op2 = isSgBinaryOp(cond)->get_rhs_operand(); - repr1 = new omega::CG_roseRepr(op2); - v.push_back(repr1); - - } else if (isSgBinaryOp(op)) { - - op1 = isSgBinaryOp(op)->get_lhs_operand(); - repr1 = new omega::CG_roseRepr(op1); - v.push_back(repr1); - - op2 = isSgBinaryOp(op)->get_rhs_operand(); - repr1 = new omega::CG_roseRepr(op2); - v.push_back(repr1); - } - - else - throw ir_error("operation not supported"); - - return v; -} - -IR_Ref *IR_roseCode::Repr2Ref(const omega::CG_outputRepr *repr) const { - SgExpression* op = - static_cast<const omega::CG_roseRepr *>(repr)->GetExpression(); - - if (SgValueExp* im = isSgValueExp(op)) { - if (isSgIntVal(im)) - return new IR_roseConstantRef(this, - static_cast<omega::coef_t>(isSgIntVal(im)->get_value())); - else if (isSgUnsignedIntVal(im)) - return new IR_roseConstantRef(this, - static_cast<omega::coef_t>(isSgUnsignedIntVal(im)->get_value())); - else if (isSgLongIntVal(im)) - return new IR_roseConstantRef(this, - static_cast<omega::coef_t>(isSgLongIntVal(im)->get_value())); - else if (isSgFloatVal(im)) - return new IR_roseConstantRef(this, isSgFloatVal(im)->get_value()); - else - assert(0); - - } else if (isSgVarRefExp(op)) - return new IR_roseScalarRef(this, isSgVarRefExp(op)); - else - assert(0); - -} - diff --git a/src/ir_rose_utils.cc b/src/ir_rose_utils.cc deleted file mode 100644 index 1329031..0000000 --- a/src/ir_rose_utils.cc +++ /dev/null @@ -1,62 +0,0 @@ -/***************************************************************************** - Copyright (C) 2008 University of Southern California - Copyright (C) 2009 University of Utah - All Rights Reserved. - - Purpose: - ROSE interface utilities. - - Notes: - - Update history: - 01/2006 created by Chun Chen -*****************************************************************************/ - -#include "ir_rose_utils.hh" - - - -std::vector<SgForStatement *> find_loops(SgNode *tnl) { - std::vector<SgForStatement *> result; - - SgStatementPtrList& blockStatements = isSgBasicBlock(tnl)->get_statements(); - for(SgStatementPtrList::const_iterator j = blockStatements.begin(); j != blockStatements.end(); j++) - if(isSgForStatement(*j)) - result.push_back(isSgForStatement(*j)); - - return result; -} - -std::vector<SgForStatement *> find_deepest_loops(SgStatementPtrList& tnl) { - - std::vector<SgForStatement *> loops; - - for(SgStatementPtrList::const_iterator j = tnl.begin(); j != tnl.end(); j++) - { - std::vector<SgForStatement *> t = find_deepest_loops(isSgNode(*j)); - if (t.size() > loops.size()) - loops = t; - } - - return loops; -} - -std::vector<SgForStatement *> find_deepest_loops(SgNode *tn) { - if (isSgForStatement(tn)) { - std::vector<SgForStatement *> loops; - - SgForStatement *tnf = static_cast<SgForStatement*>(tn); - loops.insert(loops.end(), tnf); - std::vector<SgForStatement*> t = find_deepest_loops(isSgNode(tnf->get_loop_body())); - std::copy(t.begin(), t.end(), std::back_inserter(loops)); - - return loops; - } - else if (isSgBasicBlock(tn)) { - SgBasicBlock *tnb = static_cast<SgBasicBlock*>(tn); - return find_deepest_loops(tnb->get_statements()); - } - else - return std::vector<SgForStatement *>(); -} - diff --git a/src/irtools.cc b/src/irtools.cc index e7e5029..16c4f7c 100644 --- a/src/irtools.cc +++ b/src/irtools.cc @@ -19,61 +19,80 @@ using namespace omega; -std::vector<ir_tree_node *> build_ir_tree(IR_Control *control, ir_tree_node *parent) { +// Build Chill IR tree from the source code (from the front end compiler's AST). +// Block type node can only be a leaf, i.e., there are no further structures +// inside a block allowed. +std::vector<ir_tree_node *> build_ir_tree(IR_Control *control, + ir_tree_node *parent) { std::vector<ir_tree_node *> result; + fprintf(stderr, "irtools.cc, build_ir_tree( control, parent) building a CHILL IR tree \n"); + switch (control->type()) { case IR_CONTROL_BLOCK: { - std::vector<IR_Control *> controls = control->ir_->FindOneLevelControlStructure(static_cast<IR_Block *>(control)); + fprintf(stderr, "irtools.cc L31 case IR_CONTROL_BLOCK\n"); + IR_Block *IRCB = static_cast<IR_Block *>(control); + std::vector<IR_Control *> controls = control->ir_->FindOneLevelControlStructure(IRCB); + + fprintf(stderr, "irtools.cc BACK FROM FindOneLevelControlStructure() %d controls\n", controls.size()); + if (controls.size() == 0) { + fprintf(stderr, "controls.size() == 0\n"); + ir_tree_node *node = new ir_tree_node; - node->content = control; - node->parent = parent; + node->content = control; + node->parent = parent; node->payload = -1; result.push_back(node); } else { + fprintf(stderr, "controls.size() == %d (NONZERO)\n", controls.size()); delete control; + for (int i = 0; i < controls.size(); i++) switch (controls[i]->type()) { case IR_CONTROL_BLOCK: { + fprintf(stderr, "controls[%d] is IR_CONTROL_BLOCK\n", i); std::vector<ir_tree_node *> t = build_ir_tree(controls[i], parent); result.insert(result.end(), t.begin(), t.end()); break; } case IR_CONTROL_LOOP: { + fprintf(stderr, "controls[%d] is IR_CONTROL_LOOP\n", i); ir_tree_node *node = new ir_tree_node; node->content = controls[i]; node->parent = parent; - node->children = build_ir_tree(static_cast<IR_Loop *>(controls[i])->body(), node); + node->children = build_ir_tree(static_cast<IR_Loop *>(controls[i])->body(), node); // recurse node->payload = -1; result.push_back(node); break; } case IR_CONTROL_IF: { + fprintf(stderr, "controls[%d] is IR_CONTROL_IF\n", i); static int unique_if_identifier = 0; - IR_Block *block = static_cast<IR_If *>(controls[i])->then_body(); + IR_If* theif = static_cast<IR_If *>(controls[i]); + IR_Block *block = theif->then_body(); if (block != NULL) { ir_tree_node *node = new ir_tree_node; node->content = controls[i]; node->parent = parent; - node->children = build_ir_tree(block, node); + node->children = build_ir_tree(block, node); // recurse node->payload = unique_if_identifier+1; result.push_back(node); } - block = static_cast<IR_If *>(controls[i])->else_body(); - if ( block != NULL) { + block = theif->else_body(); + if (block != NULL) { + fprintf(stderr, "IF_CONTROL has an else\n"); ir_tree_node *node = new ir_tree_node; node->content = controls[i]->clone(); node->parent = parent; - node->children = build_ir_tree(block, node); + node->children = build_ir_tree(block, node); // recurse node->payload = unique_if_identifier; result.push_back(node); } - unique_if_identifier += 2; break; } @@ -89,42 +108,58 @@ std::vector<ir_tree_node *> build_ir_tree(IR_Control *control, ir_tree_node *par break; } case IR_CONTROL_LOOP: { + fprintf(stderr, "case IR_CONTROL_LOOP\n"); ir_tree_node *node = new ir_tree_node; node->content = control; - node->parent = parent; - node->children = build_ir_tree(static_cast<const IR_Loop *>(control)->body(), node); + node->parent = parent; + fprintf(stderr, "recursing. build_ir_tree() of CONTROL_LOOP creating children L122\n"); + node->children = build_ir_tree( + static_cast<const IR_Loop *>(control)->body(), node); node->payload = -1; result.push_back(node); + fprintf(stderr, "recursing. build_ir_tree() of CONTROL_LOOP creating children DONE\n"); break; } default: ir_tree_node *node = new ir_tree_node; node->content = control; - node->parent = parent; + node->parent = parent; node->payload = -1; result.push_back(node); break; } + fprintf(stderr, "build_ir_tree() vector result has %ld parts\n", result.size()); return result; } + +// Extract statements from IR tree. Statements returned are ordered in +// lexical order in the source code. std::vector<ir_tree_node *> extract_ir_stmts(const std::vector<ir_tree_node *> &ir_tree) { + + fprintf(stderr, "extract_ir_stmts() ir_tree.size() %d\n", ir_tree.size()); std::vector<ir_tree_node *> result; for (int i = 0; i < ir_tree.size(); i++) switch (ir_tree[i]->content->type()) { + case IR_CONTROL_BLOCK: + fprintf(stderr, "IR_CONTROL_BLOCK\n"); result.push_back(ir_tree[i]); break; + case IR_CONTROL_LOOP: { + fprintf(stderr, "IR_CONTROL_LOOP( recursing )\n"); // clear loop payload from previous unsuccessful initialization process ir_tree[i]->payload = -1; std::vector<ir_tree_node *> t = extract_ir_stmts(ir_tree[i]->children); + result.insert(result.end(), t.begin(), t.end()); break; } case IR_CONTROL_IF: { + fprintf(stderr, "IR_CONTROL_IF( recursing )\n"); std::vector<ir_tree_node *> t = extract_ir_stmts(ir_tree[i]->children); result.insert(result.end(), t.begin(), t.end()); break; @@ -136,6 +171,20 @@ std::vector<ir_tree_node *> extract_ir_stmts(const std::vector<ir_tree_node *> & return result; } +std::string chill_ir_control_type_string( IR_CONTROL_TYPE type ) { + switch(type) { + case IR_CONTROL_BLOCK: return std::string( "IR_CONTROL_BLOCK"); + case IR_CONTROL_LOOP: return std::string( "IR_CONTROL_LOOP" ); + case IR_CONTROL_IF: return std::string( "IR_CONTROL_IF" ); + case IR_CONTROL_WHILE: return std::string( "IR_CONTROL_WHLIE"); break; + default: return std::string( "UNKNOWN_IR_NODE_TYPE" ); + } +} + +std::string chill_ir_node_type_string( ir_tree_node *node ) { + return chill_ir_control_type_string( node->content->type() ); +} + bool is_dependence_valid(ir_tree_node *src_node, ir_tree_node *dst_node, const DependenceVector &dv, bool before) { @@ -179,46 +228,240 @@ bool is_dependence_valid(ir_tree_node *src_node, ir_tree_node *dst_node, } -std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > test_data_dependences( - IR_Code *ir, const CG_outputRepr *repr1, const Relation &IS1, - const CG_outputRepr *repr2, const Relation &IS2, - std::vector<Free_Var_Decl*> &freevar, std::vector<std::string> index, - int i, int j) { + +//Anand: Adding function to collect the loop inductive and possibly if conditions +//enclosing a statement + +std::vector<omega::CG_outputRepr *> collect_loop_inductive_and_conditionals( + ir_tree_node * stmt_node) { + + std::vector<omega::CG_outputRepr *> to_return; + ir_tree_node *itn = stmt_node; + + while (itn->parent != NULL) { + itn = itn->parent; + + switch (itn->content->type()) { + case IR_CONTROL_LOOP: { + IR_Loop *lp = static_cast<IR_Loop *>(itn->content); + to_return.push_back(lp->lower_bound()); + to_return.push_back(lp->upper_bound()); + + break; + } + case IR_CONTROL_IF: { + CG_outputRepr *cond = + static_cast<IR_If *>(itn->content)->condition(); + + to_return.push_back(cond); + break; + } + default: + throw std::invalid_argument("invalid ir tree"); + } + } + return to_return; +} + + +// Test data dependences between two statements. The first statement +// in parameter must be lexically before the second statement in +// parameter. Returned dependences are all lexicographically +// positive. The first vector in returned pair is dependences from the +// first statement to the second statement and the second vector in +// returned pair is in reverse order. +std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > +test_data_dependences(IR_Code *ir, + const CG_outputRepr *repr1, + const Relation &IS1, + const CG_outputRepr *repr2, + const Relation &IS2, + std::vector<Free_Var_Decl*> &freevar, + std::vector<std::string> index, + int nestLeveli, + int nestLevelj, + std::map<std::string, std::vector<omega::CG_outputRepr * > > &uninterpreted_symbols, + std::map<std::string, std::vector<omega::CG_outputRepr * > > &uninterpreted_symbols_stringrepr) { + + fprintf(stderr, "\nirtools.cc test_data_dependences() %d freevars\n", freevar.size()); + fprintf(stderr, "\nrepr1 %p ", repr1); repr1->dump(); fflush(stdout); + fprintf(stderr, "\nrepr2 %p ", repr2); repr2->dump(); fflush(stdout); + + for (int i=0; i<index.size(); i++) fprintf(stderr, "index %d %s\n", i, index[i].c_str()); + Relation *helper = new Relation(IS1); fprintf(stderr, "IS1 "); helper->print(); fflush(stdout); + helper = new Relation(IS2); fprintf(stderr, "IS2 "); helper->print(); fflush(stdout); + + + //for (int i=0; i<freevar.size(); i++) { + // std::string shit = (const std::string)(freevar[i]->base_name()); + + // fprintf(stderr, "freevar %d %s\n", i, shit.c_str()); + //} + std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > result; if (repr1 == repr2) { + fprintf(stderr, "repr1 == repr2\nrepr1->dump()\n"); + repr1->dump(); + fflush(stdout); + std::vector<IR_ArrayRef *> access = ir->FindArrayRef(repr1); + fprintf(stderr, "access of size %d\n", access.size()); + for (int i = 0; i < access.size(); i++) { + IR_ArrayRef *a = access[i]; + + if (a->is_write()) { + fprintf(stderr, "WRITE array access %d = %s\n", i, a->name().c_str()); + } + else { + fprintf(stderr, " array access %d = %s\n", i, a->name().c_str()); + } + } + fprintf(stderr, "that was the list\n\n"); + + // Manu:: variables/structures added to identify dependence vectors related to reduction operation + tempResultMap trMap; + tempResultMap::iterator ittrMap; + int ref2Stmt[access.size()]; // mapping of reference to statement + std::set<int> nrStmts; // stores statements that can't be reduced + std::set<int> tnrStmts; + int stmtId = 1; + int tempStmtId = 1; + std::map<int,std::set<int> > rMap; // This maps statement number to a set of dependences + std::map<int, std::set<int> >::iterator itMap; + for (int i = 0; i < access.size(); i++) { + ref2Stmt[i] = -1; + } + + // Manu -- changes for identifying possible reduction operation + // The below loop nest is used to classify array references into different statements + fprintf(stderr, "\nbefore mapRefstoStatements()\n"); + mapRefstoStatements(ir,access,ref2Stmt,rMap,tnrStmts,nrStmts); + fprintf(stderr, "after mapRefstoStatements()\n\n"); + + //------------------------------------------------------------- + omega::coef_t lbound[3], ubound[3]; // for each kind of dependence. We can potentially have reduction only if all + // lbounds match and all ubounds match. At present, we only check the last loop level. + lbound[0] = lbound[1] = lbound[2] = LLONG_MAX; + ubound[0] = ubound[1] = ubound[2] = LLONG_MIN; + //------------------------------------------------------------- for (int i = 0; i < access.size(); i++) { + fprintf(stderr, "i %d\n", i); IR_ArrayRef *a = access[i]; IR_ArraySymbol *sym_a = a->symbol(); + fprintf(stderr, "sym_a = %s\n", a->name().c_str()); for (int j = i; j < access.size(); j++) { + fprintf(stderr, "irtools.cc j %d\n", j); IR_ArrayRef *b = access[j]; IR_ArraySymbol *sym_b = b->symbol(); + fprintf(stderr, "sym_b = %s\n", b->name().c_str()); + + fprintf(stderr, "irtools.cc ij %d %d\n", i, j); + if (*sym_a == *sym_b) fprintf(stderr, "*sym_a == *sym_b\n"); + else fprintf(stderr, "*sym_a NOT == *sym_b\n"); + + if ( a->is_write()) fprintf(stderr, "%d a->is_write()\n", i); + else fprintf(stderr, "%d a->is_NOT_write()\n", i); + if ( b->is_write()) fprintf(stderr, "%d b->is_write()\n", j); + else fprintf(stderr, "%d b->is_NOT_write()\n", j); + if (*sym_a == *sym_b && (a->is_write() || b->is_write())) { - Relation r = arrays2relation(ir, freevar, a, IS1, b, IS2); + fprintf(stderr, "\nirtools.cc ij %d %d SYMBOL A == SYMBOL B and one is a write\n", i, j); + Relation r = arrays2relation(ir, freevar, a, IS1, b, IS2,uninterpreted_symbols,uninterpreted_symbols_stringrepr); + helper = new Relation(r); fprintf(stderr, "r "); helper->print(); fflush(stdout); + + + fprintf(stderr, "1\n"); std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > dv = relation2dependences(a, b, r); - result.first.insert(result.first.end(), dv.first.begin(), + fprintf(stderr, "\nirtools.cc ij %d %d dv.first %d dv.second %d\n", i, j, dv.first.size(), dv.second.size()); + fprintf(stderr, "2"); + result.first.insert(result.first.end(), dv.first.begin(), dv.first.end()); + fprintf(stderr, "3"); result.second.insert(result.second.end(), dv.second.begin(), dv.second.end()); + fprintf(stderr, "4"); + + // Manu:: check if the array references belong to the same statement + // If yes, set the flag in the dependence vector + //---------------------------------------------- + if(DEP_DEBUG){ + std::cout << "Size of the dependence vector '" << a->name().c_str() << "' -- " << dv.first.size() << "\n"; + std::cout << "------------ Printing dependence vector START ---------------\n"; + + for (std::vector<DependenceVector>::iterator itd = dv.first.begin(); itd != dv.first.end(); itd++){ + if (itd->type == DEP_R2W) + std::cout<<"WAR\n"; + else if (itd->type == DEP_W2R) + std::cout<<"RAW\n"; + else if (itd->type == DEP_W2W) + std::cout<<"WAW\n"; + + std::vector<omega::coef_t>::iterator itu = itd->ubounds.begin(); + for (std::vector<omega::coef_t>::iterator itl = itd->lbounds.begin(); itl != itd->lbounds.end(); itl++){ + std::cout << "(" << *itl << ", " << *itu << ")\n"; + itu++; + } + } + std::cout << "--------\n"; + for (std::vector<DependenceVector>::iterator itd = dv.second.begin(); itd != dv.second.end(); itd++){ + if (itd->type == DEP_R2W) + std::cout<<"WAR\n"; + else if (itd->type == DEP_W2R) + std::cout<<"RAW\n"; + else if (itd->type == DEP_W2W) + std::cout<<"WAW\n"; + + std::vector<omega::coef_t>::iterator itu = itd->ubounds.begin(); + for (std::vector<omega::coef_t>::iterator itl = itd->lbounds.begin(); itl != itd->lbounds.end(); itl++){ + std::cout << "(" << *itl << ", " << *itu << ")\n"; + itu++; + } + } + std::cout << "------------ Printing dependence vector END---------------\n"; + } + checkReductionDependence(i,j,nestLeveli,lbound,ubound,ref2Stmt,rMap,dv,trMap,nrStmts); + //---------------------------------------------- + +// // Manu:: original code without the condition + if (((rMap.find(ref2Stmt[i])->second).size() != 3) || (lbound[0] != lbound[1]) || (lbound[1] != lbound[2]) || + (lbound[0] != lbound[2]) || (ubound[0] != ubound[1]) || (ubound[1] != ubound[2]) || (ubound[0] != ubound[2])) { // Manu:: original code without the condition + result.first.insert(result.first.end(), + dv.first.begin(), dv.first.end()); + result.second.insert(result.second.end(), + dv.second.begin(), dv.second.end()); + } + + } delete sym_b; } delete sym_a; - + } + + // Manu + for (ittrMap = trMap.begin(); ittrMap != trMap.end(); ittrMap++) { + DVPair tdv = ittrMap->second; + result.first.insert(result.first.end(), tdv.first.begin(), + tdv.first.end()); + result.second.insert(result.second.end(), tdv.second.begin(), + tdv.second.end()); } for (int i = 0; i < access.size(); i++) delete access[i]; } else { + fprintf(stderr, "\nrepr1 != repr2\n"); + std::vector<IR_ArrayRef *> access1 = ir->FindArrayRef(repr1); std::vector<IR_ArrayRef *> access2 = ir->FindArrayRef(repr2); for (int i = 0; i < access1.size(); i++) { + fprintf(stderr, "i %d\n", i); IR_ArrayRef *a = access1[i]; IR_ArraySymbol *sym_a = a->symbol(); @@ -226,7 +469,7 @@ std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > test_da IR_ArrayRef *b = access2[j]; IR_ArraySymbol *sym_b = b->symbol(); if (*sym_a == *sym_b && (a->is_write() || b->is_write())) { - Relation r = arrays2relation(ir, freevar, a, IS1, b, IS2); + Relation r = arrays2relation(ir, freevar, a, IS1, b, IS2, uninterpreted_symbols,uninterpreted_symbols_stringrepr); std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > dv = relation2dependences(a, b, r); @@ -246,6 +489,242 @@ std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > test_da for (int i = 0; i < access2.size(); i++) delete access2[i]; } + /*std::pair<std::vector<DependenceVector>, + std::vector<DependenceVector> > dv = + ir->FindScalarDeps(repr1, repr2, index, i, j); + + + result.first.insert(result.first.end(), dv.first.begin(), + dv.first.end()); + result.second.insert(result.second.end(), dv.second.begin(), + dv.second.end());*/ + /*result.first.insert(result.first.end(), dv.first.begin(), + dv.first.end()); + result.second.insert(result.second.end(), dv.second.begin(), + dv.second.end()); + */ + + fprintf(stderr, "LEAVING test_data_dependences() first size %d second size %d\n\n", result.first.size(), result.second.size()); return result; } + +//Manu:: This function tests if two references are from the same statement +//CG_outputRepr * from_same_statement(IR_Code *ir, IR_ArrayRef *a, IR_ArrayRef *b) { +bool from_same_statement(IR_Code *ir, IR_ArrayRef *a, IR_ArrayRef *b) { + return ir->FromSameStmt(a,b); +} + +// Manu +int stmtType(IR_Code *ir, const CG_outputRepr *repr) { + fprintf(stderr, "stmtType() DIE \n"); + exit(-1); + return (ir->getStmtType(repr)); /// AIEEE returns a meaningless number encoding rose internals. +} + +// Manu:: set the reduction operation +IR_OPERATION_TYPE getReductionOperator(IR_Code *ir, const CG_outputRepr *repr) { + return (ir->getReductionOp(repr)); +} + +// Manu:: map references to its corresponding statements +void mapRefstoStatements(IR_Code *ir, std::vector<IR_ArrayRef *> access, int ref2Stmt[], std::map<int,std::set<int> >& rMap, std::set<int>& tnrStmts, std::set<int>& nrStmts) { + + int stmtId = 1; + for (int i = 0; i < access.size(); i++) { + IR_ArrayRef *a = access[i]; + IR_ArraySymbol *sym_a = a->symbol(); + for (int j = i; j < access.size(); j++) { + IR_ArrayRef *b = access[j]; + IR_ArraySymbol *sym_b = b->symbol(); + bool inSameStmt; + if (from_same_statement(ir,access[i],access[j])) { + inSameStmt = true; +// std::cout << "Manu:: inSameStmt " << a->name().c_str() << ", " << b->name().c_str() << "\n"; + } else { + inSameStmt = false; +// std::cout << "Manu:: NOT inSameStmt " << a->name().c_str() << ", " << b->name().c_str() << "\n"; + } + if (inSameStmt) { + if (ref2Stmt[i] == -1) + ref2Stmt[i] = stmtId++; + ref2Stmt[j] = ref2Stmt[i]; + rMap.insert(std::pair<int,std::set<int> >(ref2Stmt[i],std::set<int>())); + } else { + if (ref2Stmt[i] == -1) + ref2Stmt[i] = stmtId++; + if (ref2Stmt[j] == -1) + ref2Stmt[j] = stmtId++; + if (*sym_a == *sym_b && (a->is_write() || b->is_write())) { + tnrStmts.insert(i); + tnrStmts.insert(j); + } + } + + } + } + std::set<int>::iterator itS; + for (itS = tnrStmts.begin(); itS != tnrStmts.end(); itS++) { + nrStmts.insert(ref2Stmt[*itS]); + } + +} + +// Manu:: This function tests reduction dependence and updates corresponding data structures +void checkReductionDependence(int i, int j, int nestLeveli, omega::coef_t lbound[], omega::coef_t ubound[], int ref2Stmt[], std::map<int,std::set<int> >& rMap, DVPair& dv, tempResultMap& trMap, std::set<int> nrStmts ) { + + std::map<int, std::set<int> >::iterator itMap; + tempResultMap::iterator ittrMap; + bool raw,war,waw, flg; + raw = war = waw = flg = false; + if ((ref2Stmt[i] == ref2Stmt[j]) && (nrStmts.find(ref2Stmt[i])== nrStmts.end())) { + for (int k = 0; k < dv.first.size(); k++) { + if ((dv.first[k].lbounds[nestLeveli-1] == 0) && (dv.first[k].ubounds[nestLeveli-1] == 0)) + continue; + itMap = rMap.find(ref2Stmt[i]); + if (dv.first[k].type == DEP_R2W) { + war = true; + std::set<int> s = itMap->second; + s.insert(1); // war == 1 + rMap.erase(itMap); + rMap.insert(std::pair<int,std::set<int> >(ref2Stmt[i],s)); + if (lbound[0] > dv.first[k].lbounds[nestLeveli-1]) + lbound[0] = dv.first[k].lbounds[nestLeveli-1]; + if(ubound[0] < dv.first[k].ubounds[nestLeveli-1]) + ubound[0] = dv.first[k].ubounds[nestLeveli-1]; + } else if (dv.first[k].type == DEP_W2R) { + // for (int k1 = 0; k1 < dv.first[k].lbounds.size(); k1++) { + // omega::coef_t lbound = dv.first[k].lbounds[k1]; + omega::coef_t lbound1 = dv.first[k].lbounds[nestLeveli-1]; + if (lbound1 > 0) { + flg = true; + // break; + } + // } + raw = true; + if (raw) { + std::set<int> s = itMap->second; + s.insert(2); // raw == 2 + rMap.erase(itMap); + rMap.insert(std::pair<int,std::set<int> >(ref2Stmt[i],s)); + if (lbound[1] > dv.first[k].lbounds[nestLeveli-1]) + lbound[1] = dv.first[k].lbounds[nestLeveli-1]; + if(ubound[1] < dv.first[k].ubounds[nestLeveli-1]) + ubound[1] = dv.first[k].ubounds[nestLeveli-1]; + } + } else if (dv.first[k].type == DEP_W2W) { + waw = true; + std::set<int> s = itMap->second; + s.insert(3); // waw == 3 + rMap.erase(itMap); + rMap.insert(std::pair<int,std::set<int> >(ref2Stmt[i],s)); + if (lbound[2] > dv.first[k].lbounds[nestLeveli-1]) + lbound[2] = dv.first[k].lbounds[nestLeveli-1]; + if(ubound[2] < dv.first[k].ubounds[nestLeveli-1]) + ubound[2] = dv.first[k].ubounds[nestLeveli-1]; + } +// std::cout<< "Manu:: Flags:: " << "raw " << raw << ", war " << war << ", waw " << waw << "\n"; + } + flg = false; + for (int k = 0; k < dv.second.size(); k++) { + if ((dv.second[k].lbounds[nestLeveli-1] == 0) && (dv.second[k].ubounds[nestLeveli-1] == 0)) + continue; + itMap = rMap.find(ref2Stmt[i]); + if (dv.second[k].type == DEP_R2W) { + war = true; + std::set<int> s = itMap->second; + s.insert(1); // war == 1 + rMap.erase(itMap); + rMap.insert(std::pair<int,std::set<int> >(ref2Stmt[i],s)); + if (lbound[0] > dv.second[k].lbounds[nestLeveli-1]) + lbound[0] = dv.second[k].lbounds[nestLeveli-1]; + if (ubound[0] < dv.second[k].ubounds[nestLeveli-1]) + ubound[0] = dv.second[k].ubounds[nestLeveli-1]; + + } else if (dv.second[k].type == DEP_W2R) { + // for (int k1 = 0; k1 < dv.second[k].lbounds.size(); k1++) { + //omega::coef_t lbound = dv.second[k].lbounds[k1]; + omega::coef_t lbound1 = dv.second[k].lbounds[nestLeveli-1]; + if (lbound1 > 0) { + flg = true; + // break; + } + // } + raw = true; + if (raw) { + std::set<int> s = itMap->second; + s.insert(2); // raw == 2 + rMap.erase(itMap); + rMap.insert(std::pair<int,std::set<int> >(ref2Stmt[i],s)); + if (lbound[1] > dv.second[k].lbounds[nestLeveli-1]) + lbound[1] = dv.second[k].lbounds[nestLeveli-1]; + if (ubound[1] < dv.second[k].ubounds[nestLeveli-1]) + ubound[1] = dv.second[k].ubounds[nestLeveli-1]; + + } + + } else if (dv.second[k].type == DEP_W2W) { + waw = true; + std::set<int> s = itMap->second; + s.insert(3); // waw == 3 + rMap.erase(itMap); + rMap.insert(std::pair<int,std::set<int> >(ref2Stmt[i],s)); + if (lbound[2] > dv.second[k].lbounds[nestLeveli-1]) + lbound[2] = dv.second[k].lbounds[nestLeveli-1]; + if (ubound[2] < dv.second[k].ubounds[nestLeveli-1]) + ubound[2] = dv.second[k].ubounds[nestLeveli-1]; + + } +// std::cout<< "Manu:: Flags:: " << "raw " << raw << ", war " << war << ", waw " << waw << "\n"; + } + +// if ((rMap.find(ref2Stmt[i])->second).size() == 3) { + if(DEP_DEBUG){ + std::cout << "lbounds: " << lbound[0] << ", " << lbound[1] << ", " <<lbound[2] << "\n"; + std::cout << "ubounds: " << ubound[0] << ", " << ubound[1] << ", " <<ubound[2] << "\n"; + } + if (((rMap.find(ref2Stmt[i])->second).size() == 3) && (lbound[0] == lbound[1]) && (lbound[1] == lbound[2]) + && (ubound[0] == ubound[1]) && (ubound[1] == ubound[2])) { +// std::cout << "Manu:: All dependences present 1 \n"; + for (int k = 0; k < dv.second.size(); k++) + dv.second[k].is_reduction_cand = true; + for (int k = 0; k < dv.first.size(); k++) + dv.first[k].is_reduction_cand = true; + trMap.insert(std::pair<int,DVPair>(ref2Stmt[i],DVPair(dv.first,dv.second))); + } + } else { + // tempArrayRefId[i] = tempArrayRefId[j] = 0; + for (int k = 0; k < dv.second.size(); k++) + dv.second[k].is_reduction_cand = false; + for (int k = 0; k < dv.first.size(); k++) + dv.first[k].is_reduction_cand = false; +// reductionCand = false; + ittrMap = trMap.find(ref2Stmt[i]); + if (ittrMap != trMap.end()) { + DVPair tdv = ittrMap->second; + for (int k = 0; k < (tdv.first).size(); k++) + tdv.first[k].is_reduction_cand = false; + for (int k = 0; k < (tdv.second).size(); k++) + tdv.second[k].is_reduction_cand = false; + trMap.erase(ittrMap); + trMap.insert(std::pair<int,DVPair>(ref2Stmt[i],DVPair(tdv.first,tdv.second))); + } + } + +} + + + +void print_control( IR_Control *con ) { + IR_CONTROL_TYPE type = con->type(); + fprintf(stderr, "this is IR_Control of type %s\n", chill_ir_control_type_string( type ).c_str()); + + switch (type) { + case IR_CONTROL_BLOCK: + case IR_CONTROL_LOOP: + case IR_CONTROL_IF: + case IR_CONTROL_WHILE: + default: return; + } + +} diff --git a/src/loop.cc b/src/loop.cc index 19378a4..5f863f2 100644 --- a/src/loop.cc +++ b/src/loop.cc @@ -26,6 +26,8 @@ #include <math.h> #include <code_gen/codegen.h> #include <code_gen/CG_utils.h> +#include <code_gen/CG_stringRepr.h> +#include <code_gen/CG_chillRepr.h> // Mark. Bad idea. TODO #include <iostream> #include <algorithm> #include <map> @@ -35,11 +37,258 @@ #include "chill_error.hh" #include <string.h> #include <list> + +// TODO +#define _DEBUG_ true + + + using namespace omega; const std::string Loop::tmp_loop_var_name_prefix = std::string("chill_t"); // Manu:: In fortran, first character of a variable name must be a letter, so this change const std::string Loop::overflow_var_name_prefix = std::string("over"); +void echocontroltype( const IR_Control *control ) { + switch(control->type()) { + case IR_CONTROL_BLOCK: { + fprintf(stderr, "IR_CONTROL_BLOCK\n"); + break; + } + case IR_CONTROL_LOOP: { + fprintf(stderr, "IR_CONTROL_LOOP\n"); + break; + } + case IR_CONTROL_IF: { + fprintf(stderr, "IR_CONTROL_IF\n"); + break; + } + default: + fprintf(stderr, "just a bunch of statements?\n"); + + } // switch +} + +omega::Relation Loop::getNewIS(int stmt_num) const { + + omega::Relation result; + + if (stmt[stmt_num].xform.is_null()) { + omega::Relation known = omega::Extend_Set(omega::copy(this->known), + stmt[stmt_num].IS.n_set() - this->known.n_set()); + result = omega::Intersection(omega::copy(stmt[stmt_num].IS), known); + } else { + omega::Relation known = omega::Extend_Set(omega::copy(this->known), + stmt[stmt_num].xform.n_out() - this->known.n_set()); + result = omega::Intersection( + omega::Range( + omega::Restrict_Domain( + omega::copy(stmt[stmt_num].xform), + omega::copy(stmt[stmt_num].IS))), known); + } + + result.simplify(2, 4); + + return result; +} + + + +void Loop::reduce(int stmt_num, + std::vector<int> &level, + int param, + std::string func_name, + std::vector<int> &seq_levels, + std::vector<int> cudaized_levels, + int bound_level) { + + // illegal instruction?? fprintf(stderr, " Loop::reduce( stmt %d, param %d, func_name (encrypted)...)\n", stmt, param); // , func_name.c_str()); + + //std::cout << "Reducing stmt# " << stmt_num << " at level " << level << "\n"; + //ir->printStmt(stmt[stmt_num].code); + + if (stmt[stmt_num].reduction != 1) { + std::cout << "loop.cc Cannot reduce this statement\n"; + return; + } + fprintf(stderr, "loop.cc CAN reduce this statment?\n"); + + /*for (int i = 0; i < level.size(); i++) + if (stmt[stmt_num].loop_level[level[i] - 1].segreducible != true) { + std::cout << "Cannot reduce this statement\n"; + return; + } + for (int i = 0; i < seq_levels.size(); i++) + if (stmt[stmt_num].loop_level[seq_levels[i] - 1].segreducible != true) { + std::cout << "Cannot reduce this statement\n"; + return; + } + */ + // std::pair<int, std::string> to_insert(level, func_name); + // reduced_statements.insert(std::pair<int, std::pair<int, std::string> >(stmt_num, to_insert )); + // invalidate saved codegen computation + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + fprintf(stderr, "set last_compute_cg_ = NULL;\n"); + + omega::CG_outputBuilder *ocg = ir->builder(); + + omega::CG_outputRepr *funCallRepr; + std::vector<omega::CG_outputRepr *> arg_repr_list; + apply_xform(stmt_num); + std::vector<IR_ArrayRef *> access = ir->FindArrayRef(stmt[stmt_num].code); + std::set<std::string> names; + for (int i = 0; i < access.size(); i++) { + std::vector<IR_ArrayRef *> access2; + for (int j = 0; j < access[i]->n_dim(); j++) { + std::vector<IR_ArrayRef *> access3 = ir->FindArrayRef( + access[i]->index(j)); + access2.insert(access2.end(), access3.begin(), access3.end()); + } + if (access2.size() == 0) { + if (names.find(access[i]->name()) == names.end()) { + arg_repr_list.push_back( + ocg->CreateAddressOf(access[i]->convert())); + names.insert(access[i]->name()); + if (access[i]->is_write()) + reduced_write_refs.insert(access[i]->name()); + } + } else { + if (names.find(access[i]->name()) == names.end()) { + arg_repr_list.push_back(ocg->CreateAddressOf(ocg->CreateArrayRefExpression(ocg->CreateIdent(access[i]->name()), + ocg->CreateInt(0)))); + names.insert(access[i]->name()); + if (access[i]->is_write()) + reduced_write_refs.insert(access[i]->name()); + } + } + } + + for (int i = 0; i < seq_levels.size(); i++) + arg_repr_list.push_back( + ocg->CreateIdent( + stmt[stmt_num].IS.set_var(seq_levels[i])->name())); + + if (bound_level != -1) { + + omega::Relation new_IS = copy(stmt[stmt_num].IS); + new_IS.copy_names(stmt[stmt_num].IS); + new_IS.setup_names(); + new_IS.simplify(); + int dim = bound_level; + //omega::Relation r = getNewIS(stmt_num); + for (int j = dim + 1; j <= new_IS.n_set(); j++) + new_IS = omega::Project(new_IS, new_IS.set_var(j)); + + new_IS.simplify(2, 4); + + omega::Relation bound_ = get_loop_bound(copy(new_IS), dim - 1); + omega::Variable_ID v = bound_.set_var(dim); + std::vector<omega::CG_outputRepr *> ubList; + for (omega::GEQ_Iterator e( + const_cast<omega::Relation &>(bound_).single_conjunct()->GEQs()); + e; e++) { + if ((*e).get_coef(v) < 0) { + // && (*e).is_const_except_for_global(v)) + omega::CG_outputRepr *UPPERBOUND = + omega::output_upper_bound_repr(ir->builder(), *e, v, + bound_, + std::vector< + std::pair<omega::CG_outputRepr *, int> >( + bound_.n_set(), + std::make_pair( + static_cast<omega::CG_outputRepr *>(NULL), + 0)), uninterpreted_symbols[stmt_num]); + if (UPPERBOUND != NULL) + ubList.push_back(UPPERBOUND); + + } + + } + + omega::CG_outputRepr * ubRepr; + if (ubList.size() > 1) { + + ubRepr = ir->builder()->CreateInvoke("min", ubList); + arg_repr_list.push_back(ubRepr); + } else if (ubList.size() == 1) + arg_repr_list.push_back(ubList[0]); + } + + funCallRepr = ocg->CreateInvoke(func_name, arg_repr_list); + stmt[stmt_num].code = funCallRepr; + for (int i = 0; i < level.size(); i++) { + //stmt[*i].code = outputStatement(ocg, stmt[*i].code, 0, mapping, known, std::vector<CG_outputRepr *>(mapping.n_out(), NULL)); + std::vector<std::string> loop_vars; + loop_vars.push_back(stmt[stmt_num].IS.set_var(level[i])->name()); + + std::vector<omega::CG_outputRepr *> subs; + subs.push_back(ocg->CreateInt(0)); + + stmt[stmt_num].code = ocg->CreateSubstitutedStmt(0, stmt[stmt_num].code, + loop_vars, subs); + + } + + omega::Relation new_IS = copy(stmt[stmt_num].IS); + new_IS.copy_names(stmt[stmt_num].IS); + new_IS.setup_names(); + new_IS.simplify(); + int old_size = new_IS.n_set(); + + omega::Relation R = omega::copy(stmt[stmt_num].IS); + R.copy_names(stmt[stmt_num].IS); + R.setup_names(); + + for (int i = level.size() - 1; i >= 0; i--) { + int j; + + for (j = 0; j < cudaized_levels.size(); j++) { + if (cudaized_levels[j] == level[i]) + break; + + } + + if (j == cudaized_levels.size()) { + R = omega::Project(R, level[i], omega::Input_Var); + R.simplify(); + + } + // + + } + + omega::F_And *f_Root = R.and_with_and(); + for (int i = level.size() - 1; i >= 0; i--) { + int j; + + for (j = 0; j < cudaized_levels.size(); j++) { + if (cudaized_levels[j] == level[i]) + break; + + } + + if (j == cudaized_levels.size()) { + + omega::EQ_Handle h = f_Root->add_EQ(); + + h.update_coef(R.set_var(level[i]), 1); + h.update_const(-1); + } + // + + } + + R.simplify(); + stmt[stmt_num].IS = R; +} + + + + + + //----------------------------------------------------------------------------- // Class Loop //----------------------------------------------------------------------------- @@ -53,11 +302,24 @@ bool Loop::isInitialized() const { bool Loop::init_loop(std::vector<ir_tree_node *> &ir_tree, std::vector<ir_tree_node *> &ir_stmt) { + + fprintf(stderr, "\n Loop::init_loop()\n"); + + fprintf(stderr, "extract_ir_stmts()\n"); + fprintf(stderr, "ir_tree has %d statements\n", ir_tree.size()); ir_stmt = extract_ir_stmts(ir_tree); + + fprintf(stderr,"nesting level stmt size = %d\n", (int)ir_stmt.size()); stmt_nesting_level_.resize(ir_stmt.size()); + std::vector<int> stmt_nesting_level(ir_stmt.size()); + + fprintf(stderr, "%d statements?\n", (int)ir_stmt.size()); + + // find out how deeply nested each statement is. (how can these be different?) for (int i = 0; i < ir_stmt.size(); i++) { + fprintf(stderr, "i %d\n", i); ir_stmt[i]->payload = i; int t = 0; ir_tree_node *itn = ir_stmt[i]; @@ -68,145 +330,240 @@ bool Loop::init_loop(std::vector<ir_tree_node *> &ir_tree, } stmt_nesting_level_[i] = t; stmt_nesting_level[i] = t; + fprintf(stderr, "stmt_nesting_level[%d] = %d\n", i, t); } - + + if (actual_code.size() == 0) + actual_code = std::vector<CG_outputRepr*>(ir_stmt.size()); + stmt = std::vector<Statement>(ir_stmt.size()); + fprintf(stderr, "in init_loop, made %d stmts\n", (int)ir_stmt.size()); + + uninterpreted_symbols = std::vector<std::map<std::string, std::vector<omega::CG_outputRepr * > > >(ir_stmt.size()); + uninterpreted_symbols_stringrepr = std::vector<std::map<std::string, std::vector<omega::CG_outputRepr * > > >(ir_stmt.size()); + int n_dim = -1; int max_loc; //std::vector<std::string> index; for (int i = 0; i < ir_stmt.size(); i++) { int max_nesting_level = -1; int loc; - for (int j = 0; j < ir_stmt.size(); j++) + + // find the max nesting level and remember the statement that was at that level + for (int j = 0; j < ir_stmt.size(); j++) { if (stmt_nesting_level[j] > max_nesting_level) { max_nesting_level = stmt_nesting_level[j]; loc = j; } - + } + + fprintf(stderr, "max nesting level %d at location %d\n", max_nesting_level, loc); + // most deeply nested statement acting as a reference point if (n_dim == -1) { + fprintf(stderr, "loop.cc L356 n_dim now max_nesting_level %d\n", max_nesting_level); n_dim = max_nesting_level; max_loc = loc; - + index = std::vector<std::string>(n_dim); - + ir_tree_node *itn = ir_stmt[loc]; + fprintf(stderr, "itn = stmt[%d]\n", loc); int cur_dim = n_dim - 1; while (itn->parent != NULL) { + fprintf(stderr, "parent\n"); + itn = itn->parent; if (itn->content->type() == IR_CONTROL_LOOP) { - index[cur_dim] = - static_cast<IR_Loop *>(itn->content)->index()->name(); + fprintf(stderr, "IR_CONTROL_LOOP cur_dim %d\n", cur_dim); + IR_Loop *IRL = static_cast<IR_Loop *>(itn->content); + index[cur_dim] = IRL->index()->name(); + fprintf(stderr, "index[%d] = '%s'\n", cur_dim, index[cur_dim].c_str()); itn->payload = cur_dim--; } } } - + + fprintf(stderr, "align loops by names,\n"); // align loops by names, temporary solution - ir_tree_node *itn = ir_stmt[loc]; + ir_tree_node *itn = ir_stmt[loc]; // defined outside loops?? int depth = stmt_nesting_level_[loc] - 1; + for (int t = depth; t >= 0; t--) { int y = t; - ir_tree_node *itn = ir_stmt[loc]; - + itn = ir_stmt[loc]; + while ((itn->parent != NULL) && (y >= 0)) { itn = itn->parent; if (itn->content->type() == IR_CONTROL_LOOP) y--; } - + if (itn->content->type() == IR_CONTROL_LOOP && itn->payload == -1) { CG_outputBuilder *ocg = ir->builder(); - + itn->payload = depth - t; - + CG_outputRepr *code = static_cast<IR_Block *>(ir_stmt[loc]->content)->extract(); - + std::vector<CG_outputRepr *> index_expr; std::vector<std::string> old_index; CG_outputRepr *repl = ocg->CreateIdent(index[itn->payload]); index_expr.push_back(repl); old_index.push_back( - static_cast<IR_Loop *>(itn->content)->index()->name()); + static_cast<IR_Loop *>(itn->content)->index()->name()); code = ocg->CreateSubstitutedStmt(0, code, old_index, index_expr); - + replace.insert(std::pair<int, CG_outputRepr*>(loc, code)); + //stmt[loc].code = code; + } } - + + fprintf(stderr, "\nset relation variable names ****\n"); // set relation variable names + + // this finds the loop variables for loops enclosing this statement and puts + // them in an Omega Relation (just their names, which could fail) + + fprintf(stderr, "Relation r(%d)\n", n_dim); Relation r(n_dim); F_And *f_root = r.add_and(); itn = ir_stmt[loc]; int temp_depth = depth; while (itn->parent != NULL) { - + itn = itn->parent; if (itn->content->type() == IR_CONTROL_LOOP) { + fprintf(stderr, "it's a loop. temp_depth %d\n", temp_depth); + fprintf(stderr, "r.name_set_var( %d, %s )\n", itn->payload + 1, index[temp_depth].c_str()); r.name_set_var(itn->payload + 1, index[temp_depth]); - + temp_depth--; } + //static_cast<IR_Loop *>(itn->content)->index()->name()); } - + fprintf(stderr, "Relation r "); r.print(); fflush(stdout); + //fprintf(stderr, "f_root "); f_root->print(stderr); fprintf(stderr, "\n"); + + /*while (itn->parent != NULL) { + itn = itn->parent; + if (itn->content->type() == IR_CONTROL_LOOP) + r.name_set_var(itn->payload+1, static_cast<IR_Loop *>(itn->content)->index()->name()); + }*/ + + + + + fprintf(stderr, "extract information from loop/if structures\n"); // extract information from loop/if structures std::vector<bool> processed(n_dim, false); std::vector<std::string> vars_to_be_reversed; + + std::vector<std::string> insp_lb; + std::vector<std::string> insp_ub; + itn = ir_stmt[loc]; - while (itn->parent != NULL) { + while (itn->parent != NULL) { // keep heading upward itn = itn->parent; - + switch (itn->content->type()) { case IR_CONTROL_LOOP: { + fprintf(stderr, "loop.cc l 462 IR_CONTROL_LOOP\n"); IR_Loop *lp = static_cast<IR_Loop *>(itn->content); Variable_ID v = r.set_var(itn->payload + 1); int c; - + try { c = lp->step_size(); + //fprintf(stderr, "step size %d\n", c); if (c > 0) { CG_outputRepr *lb = lp->lower_bound(); + fprintf(stderr, "loop.cc, got the lower bound. it is:\n"); + lb->dump(); printf("\n"); fflush(stdout); + exp2formula(ir, r, f_root, freevar, lb, v, 's', - IR_COND_GE, true); + IR_COND_GE, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + CG_outputRepr *ub = lp->upper_bound(); + //fprintf(stderr, "loop.cc, got the upper bound. it is:\n"); + //ub->dump(); printf("\n"); fflush(stdout); + + + IR_CONDITION_TYPE cond = lp->stop_cond(); if (cond == IR_COND_LT || cond == IR_COND_LE) exp2formula(ir, r, f_root, freevar, ub, v, 's', - cond, true); + cond, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); else throw ir_error("loop condition not supported"); - + + + if ((ir->QueryExpOperation(lp->lower_bound()) + == IR_OP_ARRAY_VARIABLE) + && (ir->QueryExpOperation(lp->lower_bound()) + == ir->QueryExpOperation( + lp->upper_bound()))) { + + fprintf(stderr, "loop.cc lower and upper are both IR_OP_ARRAY_VARIABLE?\n"); + + std::vector<CG_outputRepr *> v = + ir->QueryExpOperand(lp->lower_bound()); + IR_ArrayRef *ref = + static_cast<IR_ArrayRef *>(ir->Repr2Ref( + v[0])); + std::string s0 = ref->name(); + std::vector<CG_outputRepr *> v2 = + ir->QueryExpOperand(lp->upper_bound()); + IR_ArrayRef *ref2 = + static_cast<IR_ArrayRef *>(ir->Repr2Ref( + v2[0])); + std::string s1 = ref2->name(); + + if (s0 == s1) { + insp_lb.push_back(s0); + insp_ub.push_back(s1); + + } + + } + + } else if (c < 0) { CG_outputBuilder *ocg = ir->builder(); CG_outputRepr *lb = lp->lower_bound(); lb = ocg->CreateMinus(NULL, lb); exp2formula(ir, r, f_root, freevar, lb, v, 's', - IR_COND_GE, true); + IR_COND_GE, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); CG_outputRepr *ub = lp->upper_bound(); ub = ocg->CreateMinus(NULL, ub); IR_CONDITION_TYPE cond = lp->stop_cond(); if (cond == IR_COND_GE) exp2formula(ir, r, f_root, freevar, ub, v, 's', - IR_COND_LE, true); + IR_COND_LE, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); else if (cond == IR_COND_GT) exp2formula(ir, r, f_root, freevar, ub, v, 's', - IR_COND_LT, true); + IR_COND_LT, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); else throw ir_error("loop condition not supported"); - + vars_to_be_reversed.push_back(lp->index()->name()); } else throw ir_error("loop step size zero"); } catch (const ir_error &e) { + actual_code[loc] = + static_cast<IR_Block *>(ir_stmt[loc]->content)->extract(); for (int i = 0; i < itn->children.size(); i++) delete itn->children[i]; itn->children = std::vector<ir_tree_node *>(); itn->content = itn->content->convert(); return false; } - + + // check for loop increment or decrement that is not 1 + //fprintf(stderr, "abs(c)\n"); if (abs(c) != 1) { F_Exists *f_exists = f_root->add_exists(); Variable_ID e = f_exists->declare(); @@ -219,22 +576,28 @@ bool Loop::init_loop(std::vector<ir_tree_node *> &ir_tree, h.update_coef(v, -1); CG_outputRepr *lb = lp->lower_bound(); exp2formula(ir, r, f_and, freevar, lb, e, 's', IR_COND_EQ, - true); + true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); } - + processed[itn->payload] = true; break; } + + case IR_CONTROL_IF: { + fprintf(stderr, "IR_CONTROL_IF\n"); + IR_If *theif = static_cast<IR_If *>(itn->content); + CG_outputRepr *cond = static_cast<IR_If *>(itn->content)->condition(); + try { if (itn->payload % 2 == 1) - exp2constraint(ir, r, f_root, freevar, cond, true); + exp2constraint(ir, r, f_root, freevar, cond, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); else { F_Not *f_not = f_root->add_not(); F_And *f_and = f_not->add_and(); - exp2constraint(ir, r, f_and, freevar, cond, true); + exp2constraint(ir, r, f_and, freevar, cond, true,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); } } catch (const ir_error &e) { std::vector<ir_tree_node *> *t; @@ -258,10 +621,11 @@ bool Loop::init_loop(std::vector<ir_tree_node *> &ir_tree, } return false; } - + break; } default: + //fprintf(stderr, "default?\n"); for (int i = 0; i < itn->children.size(); i++) delete itn->children[i]; itn->children = std::vector<ir_tree_node *>(); @@ -269,7 +633,9 @@ bool Loop::init_loop(std::vector<ir_tree_node *> &ir_tree, return false; } } - + + + //fprintf(stderr, "add information for missing loops n_dim(%d)\n", n_dim); // add information for missing loops for (int j = 0; j < n_dim; j++) if (!processed[j]) { @@ -280,32 +646,138 @@ bool Loop::init_loop(std::vector<ir_tree_node *> &ir_tree, && itn->payload == j) break; } - + Variable_ID v = r.set_var(j + 1); if (loc < max_loc) { - + CG_outputBuilder *ocg = ir->builder(); - + CG_outputRepr *lb = static_cast<IR_Loop *>(itn->content)->lower_bound(); - + exp2formula(ir, r, f_root, freevar, lb, v, 's', IR_COND_EQ, - false); - + false,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + + /* if (ir->QueryExpOperation( + static_cast<IR_Loop *>(itn->content)->lower_bound()) + == IR_OP_VARIABLE) { + IR_ScalarRef *ref = + static_cast<IR_ScalarRef *>(ir->Repr2Ref( + static_cast<IR_Loop *>(itn->content)->lower_bound())); + std::string name_ = ref->name(); + + for (int i = 0; i < index.size(); i++) + if (index[i] == name_) { + exp2formula(ir, r, f_root, freevar, lb, v, 's', + IR_COND_GE, false); + + CG_outputRepr *ub = + static_cast<IR_Loop *>(itn->content)->upper_bound(); + IR_CONDITION_TYPE cond = + static_cast<IR_Loop *>(itn->content)->stop_cond(); + if (cond == IR_COND_LT || cond == IR_COND_LE) + exp2formula(ir, r, f_root, freevar, ub, v, + 's', cond, false); + + + + } + + } + */ + } else { // loc > max_loc - + CG_outputBuilder *ocg = ir->builder(); CG_outputRepr *ub = static_cast<IR_Loop *>(itn->content)->upper_bound(); - + exp2formula(ir, r, f_root, freevar, ub, v, 's', IR_COND_EQ, - false); + false,uninterpreted_symbols[i],uninterpreted_symbols_stringrepr[i]); + /*if (ir->QueryExpOperation( + static_cast<IR_Loop *>(itn->content)->upper_bound()) + == IR_OP_VARIABLE) { + IR_ScalarRef *ref = + static_cast<IR_ScalarRef *>(ir->Repr2Ref( + static_cast<IR_Loop *>(itn->content)->upper_bound())); + std::string name_ = ref->name(); + + for (int i = 0; i < index.size(); i++) + if (index[i] == name_) { + + CG_outputRepr *lb = + static_cast<IR_Loop *>(itn->content)->lower_bound(); + + exp2formula(ir, r, f_root, freevar, lb, v, 's', + IR_COND_GE, false); + + CG_outputRepr *ub = + static_cast<IR_Loop *>(itn->content)->upper_bound(); + IR_CONDITION_TYPE cond = + static_cast<IR_Loop *>(itn->content)->stop_cond(); + if (cond == IR_COND_LT || cond == IR_COND_LE) + exp2formula(ir, r, f_root, freevar, ub, v, + 's', cond, false); + + + } + } + */ } } - + r.setup_names(); r.simplify(); - + + // THIS IS MISSING IN PROTONU's + for (int j = 0; j < insp_lb.size(); j++) { + + std::string lb = insp_lb[j] + "_"; + std::string ub = lb + "_"; + + Global_Var_ID u, l; + bool found_ub = false; + bool found_lb = false; + for (DNF_Iterator di(copy(r).query_DNF()); di; di++) + for (Constraint_Iterator ci = (*di)->constraints(); ci; ci++) + + for (Constr_Vars_Iter cvi(*ci); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + if (v->kind() == Global_Var) + if (v->get_global_var()->arity() > 0) { + + std::string name = + v->get_global_var()->base_name(); + if (name == lb) { + l = v->get_global_var(); + found_lb = true; + } else if (name == ub) { + u = v->get_global_var(); + found_ub = true; + } + } + + } + + if (found_lb && found_ub) { + Relation known_(copy(r).n_set()); + known_.copy_names(copy(r)); + known_.setup_names(); + Variable_ID index_lb = known_.get_local(l, Input_Tuple); + Variable_ID index_ub = known_.get_local(u, Input_Tuple); + F_And *fr = known_.add_and(); + GEQ_Handle g = fr->add_GEQ(); + g.update_coef(index_ub, 1); + g.update_coef(index_lb, -1); + g.update_const(-1); + addKnown(known_); + + } + + } + + + fprintf(stderr, "loop.cc L441 insert the statement\n"); // insert the statement CG_outputBuilder *ocg = ir->builder(); std::vector<CG_outputRepr *> reverse_expr; @@ -314,51 +786,96 @@ bool Loop::init_loop(std::vector<ir_tree_node *> &ir_tree, repl = ocg->CreateMinus(NULL, repl); reverse_expr.push_back(repl); } + fprintf(stderr, "loop.cc before extract\n"); CG_outputRepr *code = static_cast<IR_Block *>(ir_stmt[loc]->content)->extract(); + fprintf(stderr, "code = ocg->CreateSubstitutedStmt(...)\n"); + ((CG_chillRepr *)code)->Dump(); fflush(stdout); + code = ocg->CreateSubstitutedStmt(0, code, vars_to_be_reversed, reverse_expr); + fprintf(stderr, "stmt\n"); + ((CG_chillRepr *)code)->Dump(); fflush(stdout); + stmt[loc].code = code; stmt[loc].IS = r; + + //Anand: Add Information on uninterpreted function constraints to + //Known relation + + fprintf(stderr, "loop.cc stmt[%d].loop_level has size n_dim %d\n", loc, n_dim); + stmt[loc].loop_level = std::vector<LoopLevel>(n_dim); stmt[loc].ir_stmt_node = ir_stmt[loc]; - for (int i = 0; i < n_dim; i++) { - stmt[loc].loop_level[i].type = LoopLevelOriginal; - stmt[loc].loop_level[i].payload = i; - stmt[loc].loop_level[i].parallel_level = 0; + stmt[loc].has_inspector = false; + fprintf(stderr, "for int i < n_dim(%d)\n", n_dim); + for (int ii = 0; ii < n_dim; ii++) { + stmt[loc].loop_level[ii].type = LoopLevelOriginal; + stmt[loc].loop_level[ii].payload = ii; + stmt[loc].loop_level[ii].parallel_level = 0; } - + fprintf(stderr, "whew\n"); + stmt_nesting_level[loc] = -1; } + dump(); + fprintf(stderr, " loop.cc Loop::init_loop() END\n\n"); return true; } -Loop::Loop(const IR_Control *control) { + +Loop::Loop(const IR_Control *control) { + + fprintf(stderr, "\nLoop::Loop(const IR_Control *control)\n"); + fprintf(stderr, "control type is %d ", control->type()); + echocontroltype(control); + last_compute_cgr_ = NULL; last_compute_cg_ = NULL; + fprintf(stderr, "2set last_compute_cg_ = NULL; \n"); - ir = const_cast<IR_Code *>(control->ir_); + ir = const_cast<IR_Code *>(control->ir_); // point to the CHILL IR that this loop came from + if (ir == 0) { + fprintf(stderr, "ir gotten from control = 0x%x\n", (long)ir); + fprintf(stderr, "loop.cc GONNA DIE SOON *******************************\n\n"); + } + init_code = NULL; cleanup_code = NULL; tmp_loop_var_name_counter = 1; overflow_var_name_counter = 1; known = Relation::True(0); - + + fprintf(stderr, "in Loop::Loop, calling build_ir_tree()\n"); + fprintf(stderr, "\nloop.cc, Loop::Loop() about to clone control\n"); ir_tree = build_ir_tree(control->clone(), NULL); + //fprintf(stderr,"in Loop::Loop. ir_tree has %ld parts\n", ir_tree.size()); + + // std::vector<ir_tree_node *> ir_stmt; + //fprintf(stderr, "loop.cc after build_ir_tree() %ld statements\n", stmt.size()); + + int count = 0; + //fprintf(stderr, "before init_loops, %d freevar\n", freevar.size()); + //fprintf(stderr, "count %d\n", count++); + //fprintf(stderr, "loop.cc before init_loop, %ld statements\n", stmt.size()); while (!init_loop(ir_tree, ir_stmt)) { + //fprintf(stderr, "count %d\n", count++); } - + fprintf(stderr, "after init_loop, %d freevar\n", (int)freevar.size()); + + + fprintf(stderr, "loop.cc after init_loop, %d statements\n", (int)stmt.size()); for (int i = 0; i < stmt.size(); i++) { std::map<int, CG_outputRepr*>::iterator it = replace.find(i); - + if (it != replace.end()) stmt[i].code = it->second; else stmt[i].code = stmt[i].code; } - + if (stmt.size() != 0) dep = DependenceGraph(stmt[0].IS.n_set()); else @@ -366,82 +883,194 @@ Loop::Loop(const IR_Control *control) { // init the dependence graph for (int i = 0; i < stmt.size(); i++) dep.insert(); - - for (int i = 0; i < stmt.size(); i++) + + fprintf(stderr, "this really REALLY needs some comments\n"); + // this really REALLY needs some comments + for (int i = 0; i < stmt.size(); i++) { + fprintf(stderr, "i %d\n", i); + stmt[i].reduction = 0; // Manu -- initialization for (int j = i; j < stmt.size(); j++) { + fprintf(stderr, "j %d\n", j); std::pair<std::vector<DependenceVector>, - std::vector<DependenceVector> > dv = test_data_dependences( - ir, stmt[i].code, stmt[i].IS, stmt[j].code, stmt[j].IS, - freevar, index, stmt_nesting_level_[i], - stmt_nesting_level_[j]); - + std::vector<DependenceVector> > dv = test_data_dependences( + ir, + stmt[i].code, + stmt[i].IS, + stmt[j].code, + stmt[j].IS, + freevar, + index, + stmt_nesting_level_[i], + stmt_nesting_level_[j], + uninterpreted_symbols[ i ], + uninterpreted_symbols_stringrepr[ i ]); + + fprintf(stderr, "dv.first.size() %d\n", (int)dv.first.size()); for (int k = 0; k < dv.first.size(); k++) { + fprintf(stderr, "k1 %d\n", k); if (is_dependence_valid(ir_stmt[i], ir_stmt[j], dv.first[k], true)) dep.connect(i, j, dv.first[k]); else { dep.connect(j, i, dv.first[k].reverse()); } - + } - for (int k = 0; k < dv.second.size(); k++) + + for (int k = 0; k < dv.second.size(); k++) { + fprintf(stderr, "k2 %d\n", k); if (is_dependence_valid(ir_stmt[j], ir_stmt[i], dv.second[k], false)) dep.connect(j, i, dv.second[k]); else { dep.connect(i, j, dv.second[k].reverse()); } + } } - - + } + + fprintf(stderr, "\n\n*** LOTS OF REDUCTIONS ***\n\n"); + + // TODO: Reduction check + // Manu:: Initial implementation / algorithm + std::set<int> reducCand = std::set<int>(); + std::vector<int> canReduce = std::vector<int>(); + fprintf(stderr, "\ni range %d\n", stmt.size()); + for (int i = 0; i < stmt.size(); i++) { + fprintf(stderr, "i %d\n", i); + if (!dep.hasEdge(i, i)) { + continue; + } + fprintf(stderr, "dep.hasEdge(%d, %d)\n", i, i); + + // for each statement check if it has all the three dependences (RAW, WAR, WAW) + // If there is such a statement, it is a reduction candidate. Mark all reduction candidates. + std::vector<DependenceVector> tdv = dep.getEdge(i, i); + fprintf(stderr, "tdv size %d\n", tdv.size()); + for (int j = 0; j < tdv.size(); j++) { + fprintf(stderr, "ij %d %d\n", i, j); + if (tdv[j].is_reduction_cand) { + fprintf(stderr, "reducCand.insert( %d )\n", i); + reducCand.insert(i); + } + } + } + + fprintf(stderr, "loop.cc reducCand.size() %d\n", reducCand.size()); + bool reduc; + std::set<int>::iterator it; + int counter = 0; + for (it = reducCand.begin(); it != reducCand.end(); it++) { + fprintf(stderr, "counter %d\n", counter); + reduc = true; + for (int j = 0; j < stmt.size(); j++) { + fprintf(stderr, "j %d\n", j); + if ((*it != j) + && (stmt_nesting_level_[*it] < stmt_nesting_level_[j])) { + if (dep.hasEdge(*it, j) || dep.hasEdge(j, *it)) { + fprintf(stderr, "counter %d j %d reduc = false\n", counter, j); + reduc = false; + break; + } + } + counter += 1; + } + + if (reduc) { + fprintf(stderr, "canReduce.push_back()\n"); + canReduce.push_back(*it); + stmt[*it].reduction = 2; // First, assume that reduction is possible with some processing + } + } + + + // If reduction is possible without processing, update the value of the reduction variable to 1 + fprintf(stderr, "loop.cc canReduce.size() %d\n", canReduce.size()); + for (int i = 0; i < canReduce.size(); i++) { + // Here, assuming that stmtType returns 1 when there is a single statement within stmt[i] + if (stmtType(ir, stmt[canReduce[i]].code) == 1) { + stmt[canReduce[i]].reduction = 1; + IR_OPERATION_TYPE opType; + opType = getReductionOperator(ir, stmt[canReduce[i]].code); + stmt[canReduce[i]].reductionOp = opType; + } + } + + // printing out stuff for debugging + + if (DEP_DEBUG) { + std::cout << "STATEMENTS THAT CAN BE REDUCED: \n"; + for (int i = 0; i < canReduce.size(); i++) { + std::cout << "------- " << canReduce[i] << " ------- " + << stmt[canReduce[i]].reduction << "\n"; + ir->printStmt(stmt[canReduce[i]].code); // Manu + if (stmt[canReduce[i]].reductionOp == IR_OP_PLUS) + std::cout << "Reduction type:: + \n"; + else if (stmt[canReduce[i]].reductionOp == IR_OP_MINUS) + std::cout << "Reduction type:: - \n"; + else if (stmt[canReduce[i]].reductionOp == IR_OP_MULTIPLY) + std::cout << "Reduction type:: * \n"; + else if (stmt[canReduce[i]].reductionOp == IR_OP_DIVIDE) + std::cout << "Reduction type:: / \n"; + else + std::cout << "Unknown reduction type\n"; + } + } + // cleanup the IR tree + + fprintf(stderr, "init dumb transformation relations\n"); // init dumb transformation relations e.g. [i, j] -> [ 0, i, 0, j, 0] for (int i = 0; i < stmt.size(); i++) { int n = stmt[i].IS.n_set(); stmt[i].xform = Relation(n, 2 * n + 1); F_And *f_root = stmt[i].xform.add_and(); - + for (int j = 1; j <= n; j++) { EQ_Handle h = f_root->add_EQ(); h.update_coef(stmt[i].xform.output_var(2 * j), 1); h.update_coef(stmt[i].xform.input_var(j), -1); } - + for (int j = 1; j <= 2 * n + 1; j += 2) { EQ_Handle h = f_root->add_EQ(); h.update_coef(stmt[i].xform.output_var(j), 1); } stmt[i].xform.simplify(); } - + //fprintf(stderr, "done with dumb\n"); + if (stmt.size() != 0) num_dep_dim = stmt[0].IS.n_set(); else num_dep_dim = 0; -// Debug output -// for (int i = 0; i < stmt.size(); i++) { -// std::cout << i << ": "; -// stmt[i].xform.print(); -// stmt[i].IS.print(); -// std::cout << std::endl; -// -// } + // debug + /*for (int i = 0; i < stmt.size(); i++) { + std::cout << i << ": "; + //stmt[i].xform.print(); + stmt[i].IS.print(); + std::cout << std::endl; + + }*/ + //end debug + fprintf(stderr, " at bottom of Loop::Loop, printCode\n"); + printCode(); // this dies TODO figure out why } Loop::~Loop() { - + delete last_compute_cgr_; delete last_compute_cg_; - + for (int i = 0; i < stmt.size(); i++) if (stmt[i].code != NULL) { stmt[i].code->clear(); delete stmt[i].code; } - + for (int i = 0; i < ir_tree.size(); i++) delete ir_tree[i]; - + if (init_code != NULL) { init_code->clear(); delete init_code; @@ -452,13 +1081,16 @@ Loop::~Loop() { } } + + + int Loop::get_dep_dim_of(int stmt_num, int level) const { if (stmt_num < 0 || stmt_num >= stmt.size()) throw std::invalid_argument("invaid statement " + to_string(stmt_num)); - + if (level < 1 || level > stmt[stmt_num].loop_level.size()) return -1; - + int trip_count = 0; while (true) { switch (stmt[stmt_num].loop_level[level - 1].type) { @@ -469,36 +1101,35 @@ int Loop::get_dep_dim_of(int stmt_num, int level) const { if (level < 1) return -1; if (level > stmt[stmt_num].loop_level.size()) - throw loop_error( - "incorrect loop level information for statement " - + to_string(stmt_num)); + throw loop_error("incorrect loop level information for statement " + + to_string(stmt_num)); break; default: throw loop_error( - "unknown loop level information for statement " - + to_string(stmt_num)); + "unknown loop level information for statement " + + to_string(stmt_num)); } trip_count++; if (trip_count >= stmt[stmt_num].loop_level.size()) throw loop_error( - "incorrect loop level information for statement " - + to_string(stmt_num)); + "incorrect loop level information for statement " + + to_string(stmt_num)); } } int Loop::get_last_dep_dim_before(int stmt_num, int level) const { if (stmt_num < 0 || stmt_num >= stmt.size()) throw std::invalid_argument("invaid statement " + to_string(stmt_num)); - + if (level < 1) return -1; if (level > stmt[stmt_num].loop_level.size()) level = stmt[stmt_num].loop_level.size() + 1; - + for (int i = level - 1; i >= 1; i--) if (stmt[stmt_num].loop_level[i - 1].type == LoopLevelOriginal) return stmt[stmt_num].loop_level[i - 1].payload; - + return -1; } @@ -530,53 +1161,96 @@ void Loop::print_internal_loop_structure() const { } } +void Loop::debugRelations() const { + const int m = stmt.size(); + { + std::vector<Relation> IS(m); + std::vector<Relation> xforms(m); + + for (int i = 0; i < m; i++) { + IS[i] = stmt[i].IS; + xforms[i] = stmt[i].xform; // const stucks + } + + printf("\nxforms:\n"); + for (int i = 0; i < m; i++) { xforms[i].print(); printf("\n"); } + printf("\nIS:\n"); + for (int i = 0; i < m; i++) { IS[i].print(); printf("\n"); } + fflush(stdout); + } +} + + CG_outputRepr *Loop::getCode(int effort) const { + fprintf(stderr,"\nloop.cc Loop::getCode( effort %d )\n", effort ); + const int m = stmt.size(); if (m == 0) return NULL; const int n = stmt[0].xform.n_out(); - + if (last_compute_cg_ == NULL) { + fprintf(stderr, "Loop::getCode() last_compute_cg_ == NULL\n"); + std::vector<Relation> IS(m); std::vector<Relation> xforms(m); for (int i = 0; i < m; i++) { IS[i] = stmt[i].IS; xforms[i] = stmt[i].xform; } + + debugRelations(); + + Relation known = Extend_Set(copy(this->known), n - this->known.n_set()); - + printf("\nknown:\n"); known.print(); printf("\n\n"); fflush(stdout); + last_compute_cg_ = new CodeGen(xforms, IS, known); delete last_compute_cgr_; last_compute_cgr_ = NULL; } + else { + fprintf(stderr, "Loop::getCode() last_compute_cg_ NOT NULL\n"); + } + if (last_compute_cgr_ == NULL || last_compute_effort_ != effort) { delete last_compute_cgr_; last_compute_cgr_ = last_compute_cg_->buildAST(effort); last_compute_effort_ = effort; } - + std::vector<CG_outputRepr *> stmts(m); + fprintf(stderr, "%d stmts\n", m); for (int i = 0; i < m; i++) stmts[i] = stmt[i].code; CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *repr = last_compute_cgr_->printRepr(ocg, stmts); + fprintf(stderr, "calling last_compute_cgr_->printRepr()\n"); + CG_outputRepr *repr = last_compute_cgr_->printRepr(ocg, stmts, + uninterpreted_symbols); + if (init_code != NULL) repr = ocg->StmtListAppend(init_code->clone(), repr); if (cleanup_code != NULL) repr = ocg->StmtListAppend(repr, cleanup_code->clone()); - + + fprintf(stderr,"\nloop.cc Loop::getCode( effort %d ) DONE\n", effort ); return repr; } + + + void Loop::printCode(int effort) const { + fprintf(stderr,"\nloop.cc Loop::printCode( effort %d )\n", effort ); const int m = stmt.size(); if (m == 0) return; const int n = stmt[0].xform.n_out(); - + if (last_compute_cg_ == NULL) { + fprintf(stderr, "Loop::printCode(), last_compute_cg_ == NULL\n"); std::vector<Relation> IS(m); std::vector<Relation> xforms(m); for (int i = 0; i < m; i++) { @@ -584,19 +1258,22 @@ void Loop::printCode(int effort) const { xforms[i] = stmt[i].xform; } Relation known = Extend_Set(copy(this->known), n - this->known.n_set()); - + last_compute_cg_ = new CodeGen(xforms, IS, known); delete last_compute_cgr_; last_compute_cgr_ = NULL; } - + else fprintf(stderr, "Loop::printCode(), last_compute_cg_ NOT NULL\n"); + if (last_compute_cgr_ == NULL || last_compute_effort_ != effort) { delete last_compute_cgr_; last_compute_cgr_ = last_compute_cg_->buildAST(effort); last_compute_effort_ = effort; } - - std::string repr = last_compute_cgr_->printString(); + + std::string repr = last_compute_cgr_->printString( + uninterpreted_symbols_stringrepr); + fprintf(stderr, "leaving Loop::printCode()\n"); std::cout << repr << std::endl; } @@ -620,66 +1297,59 @@ void Loop::printDependenceGraph() const { } } -Relation Loop::getNewIS(int stmt_num) const { - Relation result; - - if (stmt[stmt_num].xform.is_null()) { - Relation known = Extend_Set(copy(this->known), - stmt[stmt_num].IS.n_set() - this->known.n_set()); - result = Intersection(copy(stmt[stmt_num].IS), known); - } else { - Relation known = Extend_Set(copy(this->known), - stmt[stmt_num].xform.n_out() - this->known.n_set()); - result = Intersection( - Range( - Restrict_Domain(copy(stmt[stmt_num].xform), - copy(stmt[stmt_num].IS))), known); - } - - result.simplify(2, 4); - - return result; -} - std::vector<Relation> Loop::getNewIS() const { const int m = stmt.size(); - + std::vector<Relation> new_IS(m); for (int i = 0; i < m; i++) new_IS[i] = getNewIS(i); - + return new_IS; } +// pragmas are tied to loops only ??? void Loop::pragma(int stmt_num, int level, const std::string &pragmaText) { - // check sanity of parameters - if(stmt_num < 0) - throw std::invalid_argument("invalid statement " + to_string(stmt_num)); - - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *code = stmt[stmt_num].code; - ocg->CreatePragmaAttribute(code, level, pragmaText); + // check sanity of parameters + if(stmt_num < 0) + throw std::invalid_argument("invalid statement " + to_string(stmt_num)); + + CG_outputBuilder *ocg = ir->builder(); + CG_outputRepr *code = stmt[stmt_num].code; + ocg->CreatePragmaAttribute(code, level, pragmaText); } -void Loop::prefetch(int stmt_num, int level, const std::string &arrName, int hint) { - // check sanity of parameters - if(stmt_num < 0) - throw std::invalid_argument("invalid statement " + to_string(stmt_num)); - CG_outputBuilder *ocg = ir->builder(); - CG_outputRepr *code = stmt[stmt_num].code; - ocg->CreatePrefetchAttribute(code, level, arrName, hint); +/* + void Loop::prefetch(int stmt_num, int level, const std::string &arrName, const std::string &indexName, int offset, int hint) { + // check sanity of parameters + if(stmt_num < 0) + throw std::invalid_argument("invalid statement " + to_string(stmt_num)); + + CG_outputBuilder *ocg = ir->builder(); + CG_outputRepr *code = stmt[stmt_num].code; + ocg->CreatePrefetchAttribute(code, level, arrName, indexName, int offset, hint); + } +*/ + +void Loop::prefetch(int stmt_num, int level, const std::string &arrName, int hint) { + // check sanity of parameters + if(stmt_num < 0) + throw std::invalid_argument("invalid statement " + to_string(stmt_num)); + + CG_outputBuilder *ocg = ir->builder(); + CG_outputRepr *code = stmt[stmt_num].code; + ocg->CreatePrefetchAttribute(code, level, arrName, hint); } std::vector<int> Loop::getLexicalOrder(int stmt_num) const { assert(stmt_num < stmt.size()); - + const int n = stmt[stmt_num].xform.n_out(); std::vector<int> lex(n, 0); - + for (int i = 0; i < n; i += 2) lex[i] = get_const(stmt[stmt_num].xform, i, Output_Var); - + return lex; } @@ -688,13 +1358,13 @@ std::vector<int> Loop::getLexicalOrder(int stmt_num) const { std::set<int> Loop::getSubLoopNest(int stmt_num, int level) const { assert(stmt_num >= 0 && stmt_num < stmt.size()); assert(level > 0 && level <= stmt[stmt_num].loop_level.size()); - + std::set<int> working; for (int i = 0; i < stmt.size(); i++) if (const_cast<Loop *>(this)->stmt[i].IS.is_upper_bound_satisfiable() && stmt[i].loop_level.size() >= level) working.insert(i); - + for (int i = 1; i <= level; i++) { int a = getLexicalOrder(stmt_num, i); for (std::set<int>::iterator j = working.begin(); j != working.end();) { @@ -705,14 +1375,14 @@ std::set<int> Loop::getSubLoopNest(int stmt_num, int level) const { ++j; } } - + return working; } int Loop::getLexicalOrder(int stmt_num, int level) const { assert(stmt_num >= 0 && stmt_num < stmt.size()); assert(level > 0 && level <= stmt[stmt_num].loop_level.size()+1); - + Relation &r = const_cast<Loop *>(this)->stmt[stmt_num].xform; for (EQ_Iterator e(r.single_conjunct()->EQs()); e; e++) if (abs((*e).get_coef(r.output_var(2 * level - 1))) == 1) { @@ -727,15 +1397,15 @@ int Loop::getLexicalOrder(int stmt_num, int level) const { return (*e).get_coef(r.output_var(2 * level - 1)) > 0 ? -t : t; } } - + throw loop_error( - "can't find lexical order for statement " + to_string(stmt_num) - + "'s loop level " + to_string(level)); + "can't find lexical order for statement " + to_string(stmt_num) + + "'s loop level " + to_string(level)); } std::set<int> Loop::getStatements(const std::vector<int> &lex, int dim) const { const int m = stmt.size(); - + std::set<int> same_loops; for (int i = 0; i < m; i++) { if (dim < 0) @@ -749,32 +1419,32 @@ std::set<int> Loop::getStatements(const std::vector<int> &lex, int dim) const { if (j > dim) same_loops.insert(i); } - + } - + return same_loops; } void Loop::shiftLexicalOrder(const std::vector<int> &lex, int dim, int amount) { const int m = stmt.size(); - + if (amount == 0) return; - + for (int i = 0; i < m; i++) { std::vector<int> lex2 = getLexicalOrder(i); - + bool need_shift = true; - + for (int j = 0; j < dim; j++) if (lex2[j] != lex[j]) { need_shift = false; break; } - + if (!need_shift) continue; - + if (amount > 0) { if (lex2[dim] < lex[dim]) continue; @@ -782,14 +1452,14 @@ void Loop::shiftLexicalOrder(const std::vector<int> &lex, int dim, int amount) { if (lex2[dim] > lex[dim]) continue; } - + assign_const(stmt[i].xform, dim, lex2[dim] + amount); } } std::vector<std::set<int> > Loop::sort_by_same_loops(std::set<int> active, int level) { - + std::set<int> not_nested_at_this_level; std::map<ir_tree_node*, std::set<int> > sorted_by_loop; std::map<int, std::set<int> > sorted_by_lex_order; @@ -797,73 +1467,79 @@ std::vector<std::set<int> > Loop::sort_by_same_loops(std::set<int> active, bool lex_order_already_set = false; for (std::set<int>::iterator it = active.begin(); it != active.end(); it++) { - + if (stmt[*it].ir_stmt_node == NULL) lex_order_already_set = true; } - + if (lex_order_already_set) { - + for (std::set<int>::iterator it = active.begin(); it != active.end(); it++) { std::map<int, std::set<int> >::iterator it2 = sorted_by_lex_order.find( - get_const(stmt[*it].xform, 2 * (level - 1), - Output_Var)); - + get_const(stmt[*it].xform, 2 * (level - 1), + Output_Var)); + if (it2 != sorted_by_lex_order.end()) it2->second.insert(*it); else { - + std::set<int> to_insert; - + to_insert.insert(*it); - + sorted_by_lex_order.insert( - std::pair<int, std::set<int> >( - get_const(stmt[*it].xform, 2 * (level - 1), - Output_Var), to_insert)); - + std::pair<int, std::set<int> >( + get_const(stmt[*it].xform, 2 * (level - 1), + Output_Var), to_insert)); + } - + } - + for (std::map<int, std::set<int> >::iterator it2 = sorted_by_lex_order.begin(); it2 != sorted_by_lex_order.end(); it2++) to_return.push_back(it2->second); - + } else { - + for (std::set<int>::iterator it = active.begin(); it != active.end(); it++) { - + ir_tree_node* itn = stmt[*it].ir_stmt_node; itn = itn->parent; - while ((itn != NULL) && (itn->payload != level - 1)) + //while (itn->content->type() != IR_CONTROL_LOOP && itn != NULL) + // itn = itn->parent; + + while ((itn != NULL) && (itn->payload != level - 1)) { itn = itn->parent; - + while (itn != NULL && itn->content->type() != IR_CONTROL_LOOP ) + itn = itn->parent; + } + if (itn == NULL) not_nested_at_this_level.insert(*it); else { std::map<ir_tree_node*, std::set<int> >::iterator it2 = sorted_by_loop.find(itn); - + if (it2 != sorted_by_loop.end()) it2->second.insert(*it); else { std::set<int> to_insert; - + to_insert.insert(*it); - + sorted_by_loop.insert( - std::pair<ir_tree_node*, std::set<int> >(itn, - to_insert)); - + std::pair<ir_tree_node*, std::set<int> >(itn, + to_insert)); + } - + } - + } if (not_nested_at_this_level.size() > 0) { for (std::set<int>::iterator it = not_nested_at_this_level.begin(); @@ -871,7 +1547,7 @@ std::vector<std::set<int> > Loop::sort_by_same_loops(std::set<int> active, std::set<int> temp; temp.insert(*it); to_return.push_back(temp); - + } } for (std::map<ir_tree_node*, std::set<int> >::iterator it2 = @@ -881,37 +1557,46 @@ std::vector<std::set<int> > Loop::sort_by_same_loops(std::set<int> active, return to_return; } -void update_successors(int n, int node_num[], int cant_fuse_with[], - Graph<std::set<int>, bool> &g, std::list<int> &work_list) { - +void update_successors(int n, + int node_num[], + int cant_fuse_with[], + Graph<std::set<int>, bool> &g, + std::list<int> &work_list, + std::list<bool> &type_list, + std::vector<bool> types) { + std::set<int> disconnect; for (Graph<std::set<int>, bool>::EdgeList::iterator i = g.vertex[n].second.begin(); i != g.vertex[n].second.end(); i++) { int m = i->first; - + if (node_num[m] != -1) throw loop_error("Graph input for fusion has cycles not a DAG!!"); - + std::vector<bool> check_ = g.getEdge(n, m); - + bool has_bad_edge_path = false; for (int i = 0; i < check_.size(); i++) if (!check_[i]) { has_bad_edge_path = true; break; } - if (has_bad_edge_path) - cant_fuse_with[m] = std::max(cant_fuse_with[m], node_num[n]); - else + if (!types[m]) { cant_fuse_with[m] = std::max(cant_fuse_with[m], cant_fuse_with[n]); + } else { + if (has_bad_edge_path) + cant_fuse_with[m] = std::max(cant_fuse_with[m], node_num[n]); + else + cant_fuse_with[m] = std::max(cant_fuse_with[m], cant_fuse_with[n]); + } disconnect.insert(m); } - - + + for (std::set<int>::iterator i = disconnect.begin(); i != disconnect.end(); i++) { g.disconnect(n, *i); - + bool no_incoming_edges = true; for (int j = 0; j < g.vertex.size(); j++) if (j != *i) @@ -919,23 +1604,44 @@ void update_successors(int n, int node_num[], int cant_fuse_with[], no_incoming_edges = false; break; } - - - if (no_incoming_edges) + + if (no_incoming_edges) { work_list.push_back(*i); + type_list.push_back(types[*i]); + } } +} + + +int Loop::getMinLexValue(std::set<int> stmts, int level) { + + int min; + + std::set<int>::iterator it = stmts.begin(); + min = getLexicalOrder(*it, level); + + for (; it != stmts.end(); it++) { + int curr = getLexicalOrder(*it, level); + if (curr < min) + min = curr; + } + + return min; } + + + Graph<std::set<int>, bool> Loop::construct_induced_graph_at_level( - std::vector<std::set<int> > s, DependenceGraph dep, int dep_dim) { + std::vector<std::set<int> > s, DependenceGraph dep, int dep_dim) { Graph<std::set<int>, bool> g; - + for (int i = 0; i < s.size(); i++) g.insert(s[i]); - + for (int i = 0; i < s.size(); i++) { - + for (int j = i + 1; j < s.size(); j++) { bool has_true_edge_i_to_j = false; bool has_true_edge_j_to_i = false; @@ -943,32 +1649,32 @@ Graph<std::set<int>, bool> Loop::construct_induced_graph_at_level( bool is_connected_j_to_i = false; for (std::set<int>::iterator ii = s[i].begin(); ii != s[i].end(); ii++) { - + for (std::set<int>::iterator jj = s[j].begin(); jj != s[j].end(); jj++) { - + std::vector<DependenceVector> dvs = dep.getEdge(*ii, *jj); for (int k = 0; k < dvs.size(); k++) if (dvs[k].is_control_dependence() || (dvs[k].is_data_dependence() && dvs[k].has_been_carried_at(dep_dim))) { - + if (dvs[k].is_data_dependence() && dvs[k].has_negative_been_carried_at( - dep_dim)) { + dep_dim)) { //g.connect(i, j, false); is_connected_i_to_j = true; break; } else { //g.connect(i, j, true); - + has_true_edge_i_to_j = true; //break } } - + //if (is_connected) - + // break; // if (has_true_edge_i_to_j && !is_connected_i_to_j) // g.connect(i, j, true); @@ -977,142 +1683,226 @@ Graph<std::set<int>, bool> Loop::construct_induced_graph_at_level( if (dvs[k].is_control_dependence() || (dvs[k].is_data_dependence() && dvs[k].has_been_carried_at(dep_dim))) { - + if (is_connected_i_to_j || has_true_edge_i_to_j) throw loop_error( - "Graph input for fusion has cycles not a DAG!!"); - + "Graph input for fusion has cycles not a DAG!!"); + if (dvs[k].is_data_dependence() && dvs[k].has_negative_been_carried_at( - dep_dim)) { + dep_dim)) { + //g.connect(i, j, false); is_connected_j_to_i = true; break; } else { + //g.connect(i, j, true); + has_true_edge_j_to_i = true; + //break; } } + + // if (is_connected) + //break; + // if (is_connected) + //break; } + + //if (is_connected) + // break; } - - + + if (is_connected_i_to_j) g.connect(i, j, false); else if (has_true_edge_i_to_j) g.connect(i, j, true); - + if (is_connected_j_to_i) g.connect(j, i, false); else if (has_true_edge_j_to_i) g.connect(j, i, true); - - + } } return g; } -std::vector<std::set<int> > Loop::typed_fusion(Graph<std::set<int>, bool> g) { - bool roots[g.vertex.size()]; +std::vector<std::set<int> > Loop::typed_fusion(Graph<std::set<int>, bool> g, + std::vector<bool> &types) { + + bool roots[g.vertex.size()]; + for (int i = 0; i < g.vertex.size(); i++) roots[i] = true; - + for (int i = 0; i < g.vertex.size(); i++) for (int j = i + 1; j < g.vertex.size(); j++) { - + if (g.hasEdge(i, j)) roots[j] = false; - + if (g.hasEdge(j, i)) roots[i] = false; - + } - + std::list<int> work_list; + std::list<bool> type_list; int cant_fuse_with[g.vertex.size()]; + int fused = 0; + int lastfused = 0; + int lastnum = 0; std::vector<std::set<int> > s; //Each Fused set's representative node - + int node_to_fused_nodes[g.vertex.size()]; int node_num[g.vertex.size()]; + int next[g.vertex.size()]; + for (int i = 0; i < g.vertex.size(); i++) { - if (roots[i] == true) + if (roots[i] == true) { work_list.push_back(i); + type_list.push_back(types[i]); + } cant_fuse_with[i] = 0; node_to_fused_nodes[i] = 0; node_num[i] = -1; + next[i] = 0; } + + // topological sort according to chun's permute algorithm + // std::vector<std::set<int> > s = g.topoSort(); std::vector<std::set<int> > s2 = g.topoSort(); if (work_list.empty() || (s2.size() != g.vertex.size())) { + std::cout << s2.size() << "\t" << g.vertex.size() << std::endl; throw loop_error("Input for fusion not a DAG!!"); + + } int fused_nodes_counter = 0; while (!work_list.empty()) { int n = work_list.front(); + bool type = type_list.front(); + //int n_ = g.vertex[n].first; work_list.pop_front(); + type_list.pop_front(); int node; - if (cant_fuse_with[n] == 0) + /*if (cant_fuse_with[n] == 0) node = 0; - else + else node = cant_fuse_with[n]; - - if ((fused_nodes_counter != 0) && (node != fused_nodes_counter)) { - int rep_node = node_to_fused_nodes[node]; - node_num[n] = node_num[rep_node]; - - try { - update_successors(n, node_num, cant_fuse_with, g, work_list); - } catch (const loop_error &e) { - - throw loop_error( - "statements cannot be fused together due to negative dependence"); - - + */ + int p; + if (type) { + //if ((fused_nodes_counter != 0) && (node != fused_nodes_counter)) { + if (cant_fuse_with[n] == 0) + p = fused; + else + p = next[cant_fuse_with[n]]; + + if (p != 0) { + int rep_node = node_to_fused_nodes[p]; + node_num[n] = node_num[rep_node]; + + try { + update_successors(n, node_num, cant_fuse_with, g, work_list, + type_list, types); + } catch (const loop_error &e) { + + throw loop_error( + "statements cannot be fused together due to negative dependence"); + + } + for (std::set<int>::iterator it = g.vertex[n].first.begin(); + it != g.vertex[n].first.end(); it++) + s[node_num[n] - 1].insert(*it); + } else { + //std::set<int> new_node; + //new_node.insert(n_); + s.push_back(g.vertex[n].first); + lastnum = lastnum + 1; + node_num[n] = lastnum; + node_to_fused_nodes[node_num[n]] = n; + + if (lastfused == 0) { + fused = lastnum; + lastfused = fused; + } else { + next[lastfused] = lastnum; + lastfused = lastnum; + + } + + try { + update_successors(n, node_num, cant_fuse_with, g, work_list, + type_list, types); + } catch (const loop_error &e) { + + throw loop_error( + "statements cannot be fused together due to negative dependence"); + + } + fused_nodes_counter++; } - for (std::set<int>::iterator it = g.vertex[n].first.begin(); - it != g.vertex[n].first.end(); it++) - s[node].insert(*it); + } else { s.push_back(g.vertex[n].first); - node_to_fused_nodes[node] = n; - node_num[n] = ++node; + lastnum = lastnum + 1; + node_num[n] = lastnum; + node_to_fused_nodes[node_num[n]] = n; + try { - update_successors(n, node_num, cant_fuse_with, g, work_list); + update_successors(n, node_num, cant_fuse_with, g, work_list, + type_list, types); } catch (const loop_error &e) { - + throw loop_error( - "statements cannot be fused together due to negative dependence"); - - + "statements cannot be fused together due to negative dependence"); + } - fused_nodes_counter++; + //fused_nodes_counter++; + } + } - + return s; } + + + void Loop::setLexicalOrder(int dim, const std::set<int> &active, int starting_order, std::vector<std::vector<std::string> > idxNames) { + fprintf(stderr, "Loop::setLexicalOrder() %d idxNames active size %d starting_order %d\n", idxNames.size(), active.size(), starting_order); if (active.size() == 0) return; + for (int i=0; i< idxNames.size(); i++) { + std::vector<std::string> what = idxNames[i]; + for (int j=0; j<what.size(); j++) { + fprintf(stderr, "%2d %2d %s\n", i,j, what[j].c_str()); + } + } + // check for sanity of parameters if (dim < 0 || dim % 2 != 0) throw std::invalid_argument( - "invalid constant loop level to set lexicographical order"); + "invalid constant loop level to set lexicographical order"); std::vector<int> lex; int ref_stmt_num; for (std::set<int>::iterator i = active.begin(); i != active.end(); i++) { if ((*i) < 0 || (*i) >= stmt.size()) throw std::invalid_argument( - "invalid statement number " + to_string(*i)); + "invalid statement number " + to_string(*i)); if (dim >= stmt[*i].xform.n_out()) throw std::invalid_argument( - "invalid constant loop level to set lexicographical order"); + "invalid constant loop level to set lexicographical order"); if (i == active.begin()) { lex = getLexicalOrder(*i); ref_stmt_num = *i; @@ -1121,11 +1911,11 @@ void Loop::setLexicalOrder(int dim, const std::set<int> &active, for (int j = 0; j < dim; j += 2) if (lex[j] != lex2[j]) throw std::invalid_argument( - "statements are not in the same sub loop nest"); + "statements are not in the same sub loop nest"); } } - - // sepearate statements by current loop level types + + // separate statements by current loop level types int level = (dim + 2) / 2; std::map<std::pair<LoopLevelType, int>, std::set<int> > active_by_level_type; std::set<int> active_by_no_level; @@ -1134,10 +1924,10 @@ void Loop::setLexicalOrder(int dim, const std::set<int> &active, active_by_no_level.insert(*i); else active_by_level_type[std::make_pair( - stmt[*i].loop_level[level - 1].type, - stmt[*i].loop_level[level - 1].payload)].insert(*i); + stmt[*i].loop_level[level - 1].type, + stmt[*i].loop_level[level - 1].payload)].insert(*i); } - + // further separate statements due to control dependences std::vector<std::set<int> > active_by_level_type_splitted; for (std::map<std::pair<LoopLevelType, int>, std::set<int> >::iterator i = @@ -1164,16 +1954,16 @@ void Loop::setLexicalOrder(int dim, const std::set<int> &active, } if (controlled.size() != 0 && not_controlled.size() != 0) { active_by_level_type_splitted.erase( - active_by_level_type_splitted.begin() + j); + active_by_level_type_splitted.begin() + j); active_by_level_type_splitted.push_back(controlled); active_by_level_type_splitted.push_back(not_controlled); } } - + // set lexical order separating loops with different loop types first if (active_by_level_type_splitted.size() + active_by_no_level.size() > 1) { int dep_dim = get_last_dep_dim_before(ref_stmt_num, level) + 1; - + Graph<std::set<int>, Empty> g; for (std::vector<std::set<int> >::iterator i = active_by_level_type_splitted.begin(); @@ -1198,7 +1988,7 @@ void Loop::setLexicalOrder(int dim, const std::set<int> &active, if (dvs[k].is_control_dependence() || (dvs[k].is_data_dependence() && !dvs[k].has_been_carried_before( - dep_dim))) { + dep_dim))) { g.connect(i, j); connected = true; break; @@ -1222,7 +2012,7 @@ void Loop::setLexicalOrder(int dim, const std::set<int> &active, if (dvs[k].is_control_dependence() || (dvs[k].is_data_dependence() && !dvs[k].has_been_carried_before( - dep_dim))) { + dep_dim))) { g.connect(j, i); connected = true; break; @@ -1234,13 +2024,13 @@ void Loop::setLexicalOrder(int dim, const std::set<int> &active, break; } } - + std::vector<std::set<int> > s = g.topoSort(); if (s.size() != g.vertex.size()) throw loop_error( - "cannot separate statements with different loop types at loop level " - + to_string(level)); - + "cannot separate statements with different loop types at loop level " + + to_string(level)); + // assign lexical order int order = starting_order; for (int i = 0; i < s.size(); i++) { @@ -1252,19 +2042,20 @@ void Loop::setLexicalOrder(int dim, const std::set<int> &active, for (int j = dim + 2; j < stmt[cur_stmt].xform.n_out(); j += 2) assign_const(stmt[cur_stmt].xform, j, 0); order++; - } else { + } else { // recurse ! + fprintf(stderr, "Loop:setLexicalOrder() recursing\n"); setLexicalOrder(dim, cur_scc, order, idxNames); order += sz; } } } - // set lexical order seperating single iteration statements and loops - else { + else { // set lexical order separating single iteration statements and loops + std::set<int> true_singles; std::set<int> nonsingles; std::map<coef_t, std::set<int> > fake_singles; std::set<int> fake_singles_; - + // sort out statements that do not require loops for (std::set<int>::iterator i = active.begin(); i != active.end(); i++) { @@ -1282,7 +2073,7 @@ void Loop::setLexicalOrder(int dim, const std::set<int> &active, fake_singles_.insert(*i); try { fake_singles[get_const(cur_IS, dim + 1, Set_Var)].insert( - *i); + *i); } catch (const std::exception &e) { fake_singles[posInfinity].insert(*i); } @@ -1290,58 +2081,199 @@ void Loop::setLexicalOrder(int dim, const std::set<int> &active, } else nonsingles.insert(*i); } - - + + // split nonsingles forcibly according to negative dependences present (loop unfusible) int dep_dim = get_dep_dim_of(ref_stmt_num, level); - + if (dim < stmt[ref_stmt_num].xform.n_out() - 1) { - + + bool dummy_level_found = false; + std::vector<std::set<int> > s; - + s = sort_by_same_loops(active, level); bool further_levels_exist = false; - + if (!idxNames.empty()) if (level <= idxNames[ref_stmt_num].size()) if (idxNames[ref_stmt_num][level - 1].length() == 0) { - // Dummy level found + // && s.size() == 1) { int order1 = 0; - + dummy_level_found = true; + for (int i = level; i < idxNames[ref_stmt_num].size(); i++) if (idxNames[ref_stmt_num][i].length() > 0) further_levels_exist = true; - + } - + + //if (!dummy_level_found) { + if (s.size() > 1) { - + + std::vector<bool> types; + for (int i = 0; i < s.size(); i++) + types.push_back(true); + Graph<std::set<int>, bool> g = construct_induced_graph_at_level( - s, dep, dep_dim); - s = typed_fusion(g); + s, dep, dep_dim); + s = typed_fusion(g, types); } - int order = 0; + int order = starting_order; for (int i = 0; i < s.size(); i++) { - + for (std::set<int>::iterator it = s[i].begin(); - it != s[i].end(); it++) + it != s[i].end(); it++) { assign_const(stmt[*it].xform, dim, order); - - if ((dim + 2) <= (stmt[ref_stmt_num].xform.n_out() - 1)) + stmt[*it].xform.simplify(); + } + + if ((dim + 2) <= (stmt[ref_stmt_num].xform.n_out() - 1)) { // recurse ! + fprintf(stderr, "Loop:setLexicalOrder() recursing\n"); setLexicalOrder(dim + 2, s[i], order, idxNames); - + } + order++; } + //} + /* else { + + int order1 = 0; + int order = 0; + for (std::set<int>::iterator i = active.begin(); + i != active.end(); i++) { + if (!further_levels_exist) + assign_const(stmt[*i].xform, dim, order1++); + else + assign_const(stmt[*i].xform, dim, order1); + + } + + if ((dim + 2) <= (stmt[ref_stmt_num].xform.n_out() - 1) && further_levels_exist) + setLexicalOrder(dim + 2, active, order, idxNames); + } + */ } else { int dummy_order = 0; for (std::set<int>::iterator i = active.begin(); i != active.end(); - i++) + i++) { assign_const(stmt[*i].xform, dim, dummy_order++); + stmt[*i].xform.simplify(); + } + } + /*for (int i = 0; i < g2.vertex.size(); i++) + for (int j = i+1; j < g2.vertex.size(); j++) { + std::vector<DependenceVector> dvs = dep.getEdge(g2.vertex[i].first, g2.vertex[j].first); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].is_control_dependence() || + (dvs[k].is_data_dependence() && dvs[k].has_negative_been_carried_at(dep_dim))) { + g2.connect(i, j); + break; + } + dvs = dep.getEdge(g2.vertex[j].first, g2.vertex[i].first); + for (int k = 0; k < dvs.size(); k++) + if (dvs[k].is_control_dependence() || + (dvs[k].is_data_dependence() && dvs[k].has_negative_been_carried_at(dep_dim))) { + g2.connect(j, i); + break; + } + } + + std::vector<std::set<int> > s2 = g2.packed_topoSort(); + + std::vector<std::set<int> > splitted_nonsingles; + for (int i = 0; i < s2.size(); i++) { + std::set<int> cur_scc; + for (std::set<int>::iterator j = s2[i].begin(); j != s2[i].end(); j++) + cur_scc.insert(g2.vertex[*j].first); + splitted_nonsingles.push_back(cur_scc); + } + */ + //convert to dependence graph for grouped statements + //dep_dim = get_last_dep_dim_before(ref_stmt_num, level) + 1; + /*int order = 0; + for (std::set<int>::iterator j = active.begin(); j != active.end(); + j++) { + std::set<int> continuous; + std::cout<< active.size()<<std::endl; + while (nonsingles.find(*j) != nonsingles.end() && j != active.end()) { + continuous.insert(*j); + j++; + } + + printf("continuous size is %d\n", continuous.size()); + + + + if (continuous.size() > 0) { + std::vector<std::set<int> > s = typed_fusion(continuous, dep, + dep_dim); + + for (int i = 0; i < s.size(); i++) { + for (std::set<int>::iterator l = s[i].begin(); + l != s[i].end(); l++) { + assign_const(stmt[*l].xform, dim + 2, order); + setLexicalOrder(dim + 2, s[i]); + } + order++; + } + } + + if (j != active.end()) { + assign_const(stmt[*j].xform, dim + 2, order); + + for (int k = dim + 4; k < stmt[*j].xform.n_out(); k += 2) + assign_const(stmt[*j].xform, k, 0); + order++; + } + + if( j == active.end()) + break; + } + */ + + + // assign lexical order + /*int order = starting_order; + for (int i = 0; i < s.size(); i++) { + // translate each SCC into original statements + std::set<int> cur_scc; + for (std::set<int>::iterator j = s[i].begin(); j != s[i].end(); j++) + copy(s[i].begin(), s[i].end(), + inserter(cur_scc, cur_scc.begin())); + + // now assign the constant + for (std::set<int>::iterator j = cur_scc.begin(); + j != cur_scc.end(); j++) + assign_const(stmt[*j].xform, dim, order); + + if (cur_scc.size() > 1) + setLexicalOrder(dim + 2, cur_scc); + else if (cur_scc.size() == 1) { + int cur_stmt = *(cur_scc.begin()); + for (int j = dim + 2; j < stmt[cur_stmt].xform.n_out(); j += 2) + assign_const(stmt[cur_stmt].xform, j, 0); + } + + if (cur_scc.size() > 0) + order++; + } + */ + } + + fprintf(stderr, "LEAVING Loop::setLexicalOrder() %d idxNames\n", idxNames.size()); + for (int i=0; i< idxNames.size(); i++) { + std::vector<std::string> what = idxNames[i]; + for (int j=0; j<what.size(); j++) { + fprintf(stderr, "%2d %2d %s\n", i,j, what[j].c_str()); } } } + + void Loop::apply_xform() { std::set<int> active; for (int i = 0; i < stmt.size(); i++) @@ -1350,56 +2282,206 @@ void Loop::apply_xform() { } void Loop::apply_xform(int stmt_num) { + fprintf(stderr, "apply_xform( %d )\n", stmt_num); std::set<int> active; active.insert(stmt_num); apply_xform(active); } void Loop::apply_xform(std::set<int> &active) { + fflush(stdout); + fprintf(stderr, "loop.cc apply_xform( set )\n"); + int max_n = 0; - - CG_outputBuilder *ocg = ir->builder(); + + omega::CG_outputBuilder *ocg = ir->builder(); for (std::set<int>::iterator i = active.begin(); i != active.end(); i++) { int n = stmt[*i].loop_level.size(); if (n > max_n) max_n = n; - + std::vector<int> lex = getLexicalOrder(*i); - - Relation mapping(2 * n + 1, n); - F_And *f_root = mapping.add_and(); + + omega::Relation mapping(2 * n + 1, n); + omega::F_And *f_root = mapping.add_and(); for (int j = 1; j <= n; j++) { - EQ_Handle h = f_root->add_EQ(); + omega::EQ_Handle h = f_root->add_EQ(); h.update_coef(mapping.output_var(j), 1); h.update_coef(mapping.input_var(2 * j), -1); } - mapping = Composition(mapping, stmt[*i].xform); + mapping = omega::Composition(mapping, stmt[*i].xform); mapping.simplify(); - + // match omega input/output variables to variable names in the code for (int j = 1; j <= stmt[*i].IS.n_set(); j++) mapping.name_input_var(j, stmt[*i].IS.set_var(j)->name()); for (int j = 1; j <= n; j++) mapping.name_output_var(j, tmp_loop_var_name_prefix - + to_string(tmp_loop_var_name_counter + j - 1)); + + omega::to_string( + tmp_loop_var_name_counter + j - 1)); mapping.setup_names(); - - Relation known = Extend_Set(copy(this->known), - mapping.n_out() - this->known.n_set()); + mapping.print(); // "{[I] -> [_t1] : I = _t1 } + fflush(stdout); + + omega::Relation known = Extend_Set(copy(this->known), + mapping.n_out() - this->known.n_set()); + //stmt[*i].code = outputStatement(ocg, stmt[*i].code, 0, mapping, known, std::vector<CG_outputRepr *>(mapping.n_out(), NULL)); + + omega::CG_outputBuilder *ocgr = ir->builder(); + + + //this is probably CG_chillBuilder; + + omega::CG_stringBuilder *ocgs = new omega::CG_stringBuilder; + if (uninterpreted_symbols[*i].size() == 0) { + + + std::set<std::string> globals; + + for (omega::DNF_Iterator di(stmt[*i].IS.query_DNF()); di; di++) { + + for (omega::Constraint_Iterator e(*di); e; e++) { + for (omega::Constr_Vars_Iter cvi(*e); cvi; cvi++) { + omega::Variable_ID v = cvi.curr_var(); + if (v->kind() == omega::Global_Var + && v->get_global_var()->arity() > 0 + && globals.find(v->name()) == globals.end()) { + omega::Global_Var_ID g = v->get_global_var(); + globals.insert(v->name()); + std::vector<omega::CG_outputRepr *> reprs; + std::vector<omega::CG_outputRepr *> reprs2; + + for (int l = 1; l <= g->arity(); l++) { + omega::CG_outputRepr *temp = ocgr->CreateIdent( + stmt[*i].IS.set_var(l)->name()); + omega::CG_outputRepr *temp2 = ocgs->CreateIdent( + stmt[*i].IS.set_var(l)->name()); + + reprs.push_back(temp); + reprs2.push_back(temp2); + } + uninterpreted_symbols[*i].insert( + std::pair<std::string, + std::vector<omega::CG_outputRepr *> >( + v->get_global_var()->base_name(), + reprs)); + uninterpreted_symbols_stringrepr[*i].insert( + std::pair<std::string, + std::vector<omega::CG_outputRepr *> >( + v->get_global_var()->base_name(), + reprs2)); + } + } + } + } + } + std::vector<std::string> loop_vars; - for (int j = 1; j <= stmt[*i].IS.n_set(); j++) + for (int j = 1; j <= stmt[*i].IS.n_set(); j++) { loop_vars.push_back(stmt[*i].IS.set_var(j)->name()); + } + for (int j = 0; j<loop_vars.size(); j++) { + fprintf(stderr, "loop vars %d %s\n", j, loop_vars[j].c_str()); + } std::vector<CG_outputRepr *> subs = output_substitutions(ocg, Inverse(copy(mapping)), - std::vector<std::pair<CG_outputRepr *, int> >(mapping.n_out(), - std::make_pair(static_cast<CG_outputRepr *>(NULL), 0))); + std::vector<std::pair<CG_outputRepr *, int> >( + mapping.n_out(), + std::make_pair( + static_cast<CG_outputRepr *>(NULL), 0)), + uninterpreted_symbols[*i]); + + std::vector<CG_outputRepr *> subs2; + for (int l = 0; l < subs.size(); l++) + subs2.push_back(subs[l]->clone()); + + fprintf(stderr, "%d uninterpreted symbols\n", (int)uninterpreted_symbols.size()); + for (int j = 0; j<loop_vars.size(); j++) { + fprintf(stderr, "loop vars %d %s\n", j, loop_vars[j].c_str()); + } + + + int count = 0; + for (std::map<std::string, std::vector<CG_outputRepr *> >::iterator it = + uninterpreted_symbols[*i].begin(); + it != uninterpreted_symbols[*i].end(); it++) { + fprintf(stderr, "\ncount %d\n", count); + + std::vector<CG_outputRepr *> reprs_ = it->second; + fprintf(stderr, "%d reprs_\n", (int)reprs_.size()); + + std::vector<CG_outputRepr *> reprs_2; + for (int k = 0; k < reprs_.size(); k++) { + fprintf(stderr, "k %d\n", k); + std::vector<CG_outputRepr *> subs; + for (int l = 0; l < subs2.size(); l++) { + fprintf(stderr, "l %d\n", l); + subs.push_back(subs2[l]->clone()); + } + + fprintf(stderr, "clone\n"); + CG_outputRepr *c = reprs_[k]->clone(); + c->dump(); fflush(stdout); + + fprintf(stderr, "createsub\n"); + CG_outputRepr *s = ocgr->CreateSubstitutedStmt(0, c, + loop_vars, subs, true); + + fprintf(stderr, "push back\n"); + reprs_2.push_back( s ); + + } + + it->second = reprs_2; + count++; + fprintf(stderr, "bottom\n"); + } + + std::vector<CG_outputRepr *> subs3 = output_substitutions( + ocgs, Inverse(copy(mapping)), + std::vector<std::pair<CG_outputRepr *, int> >( + mapping.n_out(), + std::make_pair( + static_cast<CG_outputRepr *>(NULL), 0)), + uninterpreted_symbols_stringrepr[*i]); + + for (std::map<std::string, std::vector<CG_outputRepr *> >::iterator it = + uninterpreted_symbols_stringrepr[*i].begin(); + it != uninterpreted_symbols_stringrepr[*i].end(); it++) { + + std::vector<CG_outputRepr *> reprs_ = it->second; + std::vector<CG_outputRepr *> reprs_2; + for (int k = 0; k < reprs_.size(); k++) { + std::vector<CG_outputRepr *> subs; + /* for (int l = 0; l < subs3.size(); l++) + subs.push_back(subs3[l]->clone()); + reprs_2.push_back( + ocgs->CreateSubstitutedStmt(0, reprs_[k]->clone(), + loop_vars, subs)); + */ + reprs_2.push_back(subs3[k]->clone()); + } + + it->second = reprs_2; + + } + + + fprintf(stderr, "loop.cc stmt[*i].code =\n"); + //stmt[*i].code->dump(); + //fprintf(stderr, "\n"); stmt[*i].code = ocg->CreateSubstitutedStmt(0, stmt[*i].code, loop_vars, subs); - stmt[*i].IS = Range(Restrict_Domain(mapping, stmt[*i].IS)); + //fprintf(stderr, "loop.cc substituted code =\n"); + //stmt[*i].code->dump(); + //fprintf(stderr, "\n"); + + stmt[*i].IS = omega::Range(Restrict_Domain(mapping, stmt[*i].IS)); stmt[*i].IS.simplify(); - + // replace original transformation relation with straight 1-1 mapping + //fprintf(stderr, "replace original transformation relation with straight 1-1 mapping\n"); mapping = Relation(n, 2 * n + 1); f_root = mapping.add_and(); for (int j = 1; j <= n; j++) { @@ -1413,29 +2495,46 @@ void Loop::apply_xform(std::set<int> &active) { h.update_const(-lex[j - 1]); } stmt[*i].xform = mapping; + + //fprintf(stderr, "\ncode is: \n"); + //stmt[*i].code->dump(); + //fprintf(stderr, "\n\n"); + } - + tmp_loop_var_name_counter += max_n; + fflush(stdout); + fprintf(stderr, "loop.cc LEAVING apply_xform( set )\n\n"); + //for (std::set<int>::iterator i = active.begin(); i != active.end(); i++) { + // fprintf(stderr, "\nloop.cc stmt[i].code =\n"); + // stmt[*i].code->dump(); + // fprintf(stderr, "\n\n"); + //} + } -void Loop::addKnown(const Relation &cond) { + + +void Loop::addKnown(const Relation &cond) { + // invalidate saved codegen computation delete last_compute_cgr_; last_compute_cgr_ = NULL; delete last_compute_cg_; last_compute_cg_ = NULL; - + fprintf(stderr, "Loop::addKnown(), SETTING last_compute_cg_ = NULL\n"); + int n1 = this->known.n_set(); - + Relation r = copy(cond); int n2 = r.n_set(); - + if (n1 < n2) this->known = Extend_Set(this->known, n2 - n1); else if (n1 > n2) r = Extend_Set(r, n1 - n2); - + this->known = Intersection(this->known, r); } @@ -1443,11 +2542,11 @@ void Loop::removeDependence(int stmt_num_from, int stmt_num_to) { // check for sanity of parameters if (stmt_num_from >= stmt.size()) throw std::invalid_argument( - "invalid statement number " + to_string(stmt_num_from)); + "invalid statement number " + to_string(stmt_num_from)); if (stmt_num_to >= stmt.size()) throw std::invalid_argument( - "invalid statement number " + to_string(stmt_num_to)); - + "invalid statement number " + to_string(stmt_num_to)); + dep.disconnect(stmt_num_from, stmt_num_to); } @@ -1482,16 +2581,16 @@ void Loop::dump() const { bool Loop::nonsingular(const std::vector<std::vector<int> > &T) { if (stmt.size() == 0) return true; - + // check for sanity of parameters for (int i = 0; i < stmt.size(); i++) { if (stmt[i].loop_level.size() != num_dep_dim) throw std::invalid_argument( - "nonsingular loop transformations must be applied to original perfect loop nest"); + "nonsingular loop transformations must be applied to original perfect loop nest"); for (int j = 0; j < stmt[i].loop_level.size(); j++) if (stmt[i].loop_level[j].type != LoopLevelOriginal) throw std::invalid_argument( - "nonsingular loop transformations must be applied to original perfect loop nest"); + "nonsingular loop transformations must be applied to original perfect loop nest"); } if (T.size() != num_dep_dim) throw std::invalid_argument("invalid transformation matrix"); @@ -1503,6 +2602,8 @@ bool Loop::nonsingular(const std::vector<std::vector<int> > &T) { last_compute_cgr_ = NULL; delete last_compute_cg_; last_compute_cg_ = NULL; + fprintf(stderr, "Loop::nonsingular(), SETTING last_compute_cg_ = NULL\n"); + // build relation from matrix Relation mapping(2 * num_dep_dim + 1, 2 * num_dep_dim + 1); F_And *f_root = mapping.add_and(); @@ -1520,11 +2621,11 @@ bool Loop::nonsingular(const std::vector<std::vector<int> > &T) { h.update_coef(mapping.output_var(i), -1); h.update_coef(mapping.input_var(i), 1); } - + // update transformation relations for (int i = 0; i < stmt.size(); i++) stmt[i].xform = Composition(copy(mapping), stmt[i].xform); - + // update dependence graph for (int i = 0; i < dep.vertex.size(); i++) for (DependenceGraph::EdgeList::iterator j = @@ -1539,7 +2640,7 @@ bool Loop::nonsingular(const std::vector<std::vector<int> > &T) { case DEP_W2W: case DEP_R2R: { std::vector<coef_t> lbounds(num_dep_dim), ubounds( - num_dep_dim); + num_dep_dim); for (int p = 0; p < num_dep_dim; p++) { coef_t lb = 0; coef_t ub = 0; @@ -1579,7 +2680,7 @@ bool Loop::nonsingular(const std::vector<std::vector<int> > &T) { } dv.lbounds = lbounds; dv.ubounds = ubounds; - + break; } default: @@ -1588,13 +2689,13 @@ bool Loop::nonsingular(const std::vector<std::vector<int> > &T) { } j->second = dvs; } - + // set constant loop values std::set<int> active; for (int i = 0; i < stmt.size(); i++) active.insert(i); setLexicalOrder(0, active); - + return true; } @@ -1612,7 +2713,7 @@ bool Loop::is_dependence_valid_based_on_lex_order(int i, int j, last_dim = last_dim / 2; if (last_dim == 0) return true; - + for (int i = 0; i < last_dim; i++) { if (dv.lbounds[i] > 0) return true; @@ -1622,8 +2723,1713 @@ bool Loop::is_dependence_valid_based_on_lex_order(int i, int j, } if (before) return true; - + return false; + +} + +// Manu:: reduction operation + +void Loop::scalar_expand(int stmt_num, const std::vector<int> &levels, + std::string arrName, int memory_type, int padding_alignment, + int assign_then_accumulate, int padding_stride) { + + //std::cout << "In scalar_expand function: " << stmt_num << ", " << arrName << "\n"; + //std::cout.flush(); + + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; i<stmt.size(); i++) { + // fprintf(stderr, "%2d ", i); + // ((CG_chillRepr *)stmt[i].code)->Dump(); + //} + //fprintf(stderr, "\n"); + + // check for sanity of parameters + bool found_non_constant_size_dimension = false; + + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument( + "invalid statement number " + to_string(stmt_num)); + //Anand: adding check for privatized levels + //if (arrName != "RHS") + // throw std::invalid_argument( + // "invalid 3rd argument: only 'RHS' supported " + arrName); + for (int i = 0; i < levels.size(); i++) { + if (levels[i] <= 0 || levels[i] > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument( + "1invalid loop level " + to_string(levels[i])); + + if (i > 0) { + if (levels[i] < levels[i - 1]) + throw std::invalid_argument( + "loop levels must be in ascending order"); + } + } + //end --adding check for privatized levels + + delete last_compute_cgr_; + last_compute_cgr_ = NULL; + delete last_compute_cg_; + last_compute_cg_ = NULL; + fprintf(stderr, "Loop::scalar_expand(), SETTING last_compute_cg_ = NULL\n"); + + fprintf(stderr, "\nloop.cc finding array accesses in stmt %d of the code\n",stmt_num ); + std::vector<IR_ArrayRef *> access = ir->FindArrayRef(stmt[stmt_num].code); + fprintf(stderr, "loop.cc L2726 %d access\n", access.size()); + + IR_ArraySymbol *sym = NULL; + fprintf(stderr, "arrName %s\n", arrName.c_str()); + if (arrName == "RHS") { + fprintf(stderr, "sym RHS\n"); + sym = access[0]->symbol(); + } + else { + fprintf(stderr, "looking for array %s in access\n", arrName.c_str()); + for (int k = 0; k < access.size(); k++) { // BUH + + //fprintf(stderr, "access[%d] = %s ", k, access[k]->getTypeString()); access[k]->print(0,stderr); fprintf(stderr, "\n"); + + std::string name = access[k]->symbol()->name(); + //fprintf(stderr, "comparing %s to %s\n", name.c_str(), arrName.c_str()); + + if (access[k]->symbol()->name() == arrName) { + fprintf(stderr, "found it sym access[ k=%d ]\n", k); + sym = access[k]->symbol(); + } + } + } + if (!sym) fprintf(stderr, "DIDN'T FIND IT\n"); + fprintf(stderr, "sym %p\n", sym); + + // collect array references by name + std::vector<int> lex = getLexicalOrder(stmt_num); + int dim = 2 * levels[levels.size() - 1] - 1; + std::set<int> same_loop = getStatements(lex, dim - 1); + + //Anand: shifting this down + // assign_const(stmt[newStmt_num].xform, 2*level+1, 1); + + // std::cout << " before temp array name \n "; + // create a temporary variable + IR_Symbol *tmp_sym; + + // get the loop upperbound, that would be the size of the temp array. + omega::coef_t lb[levels.size()], ub[levels.size()], size[levels.size()]; + + //Anand Adding apply xform so that tiled loop bounds are reflected + fprintf(stderr, "Adding apply xform so that tiled loop bounds are reflected\n"); + apply_xform(same_loop); + fprintf(stderr, "loop.cc, back from apply_xform()\n"); + + //Anand commenting out the folowing 4 lines + /* copy(stmt[stmt_num].IS).query_variable_bounds( + copy(stmt[stmt_num].IS).set_var(level), lb, ub); + std::cout << "Upper Bound = " << ub << "\n"; + std::cout << "lower Bound = " << lb << "\n"; + */ + // testing testing -- Manu //////////////////////////////////////////////// + /* + // int n_dim = sym->n_dim(); + // std::cout << "------- n_dim ----------- " << n_dim << "\n"; + std::pair<EQ_Handle, Variable_ID> result = find_simplest_stride(stmt[stmt_num].IS, stmt[stmt_num].IS.set_var(level)); + omega::coef_t index_stride; + if (result.second != NULL) { + index_stride = abs(result.first.get_coef(result.second))/gcd(abs(result.first.get_coef(result.second)), abs(result.first.get_coef(stmt[stmt_num].IS.set_var(level)))); + std::cout << "simplest_stride :: " << index_stride << ", " << result.first.get_coef(result.second) << ", " << result.first.get_coef(stmt[stmt_num].IS.set_var(level))<< "\n"; + } + Relation bound; + // bound = get_loop_bound(stmt[stmt_num].IS, level); + bound = SimpleHull(stmt[stmt_num].IS,true, true); + bound.print(); + + bound = copy(stmt[stmt_num].IS); + for (int i = 1; i < level; i++) { + bound = Project(bound, i, Set_Var); + std::cout << "-------------------------------\n"; + bound.print(); + } + + bound.simplify(); + bound.print(); + // bound = get_loop_bound(bound, level); + + copy(bound).query_variable_bounds(copy(bound).set_var(level), lb, ub); + std::cout << "Upper Bound = " << ub << "\n"; + std::cout << "lower Bound = " << lb << "\n"; + + result = find_simplest_stride(bound, bound.set_var(level)); + if (result.second != NULL) + index_stride = abs(result.first.get_coef(result.second))/gcd(abs(result.first.get_coef(result.second)), abs(result.first.get_coef(bound.set_var(level)))); + else + index_stride = 1; + std::cout << "simplest_stride 11:: " << index_stride << "\n"; + */ + //////////////////////////////////////////////////////////////////////////////// + ///////////////////////////// copied datacopy code here ///////////////////////////////////////////// + + //std::cout << "In scalar_expand function 2: " << stmt_num << ", " << arrName << "\n"; + //std::cout.flush(); + + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; i<stmt.size(); i++) { + // fprintf(stderr, "%2d ", i); + // ((CG_chillRepr *)stmt[i].code)->Dump(); + //} + //fprintf(stderr, "\n"); + + + + int n_dim = levels.size(); + Relation copy_is = copy(stmt[stmt_num].IS); + // extract temporary array information + CG_outputBuilder *ocg1 = ir->builder(); + std::vector<CG_outputRepr *> index_lb(n_dim); // initialized to NULL + std::vector<coef_t> index_stride(n_dim); + std::vector<bool> is_index_eq(n_dim, false); + std::vector<std::pair<int, CG_outputRepr *> > index_sz(0); + Relation reduced_copy_is = copy(copy_is); + std::vector<CG_outputRepr *> size_repr; + std::vector<int> size_int; + Relation xform = copy(stmt[stmt_num].xform); + for (int i = 0; i < n_dim; i++) { + + dim = 2 * levels[i] - 1; + //Anand: Commenting out the lines below: not required + // if (i != 0) + // reduced_copy_is = Project(reduced_copy_is, level - 1 + i, Set_Var); + Relation bound = get_loop_bound(copy(reduced_copy_is), levels[i] - 1); + + // extract stride + std::pair<EQ_Handle, Variable_ID> result = find_simplest_stride(bound, + bound.set_var(levels[i])); + if (result.second != NULL) + index_stride[i] = abs(result.first.get_coef(result.second)) + / gcd(abs(result.first.get_coef(result.second)), + abs( + result.first.get_coef( + bound.set_var(levels[i])))); + else + index_stride[i] = 1; + // std::cout << "simplest_stride 11:: " << index_stride[i] << "\n"; + + // check if this array index requires loop + Conjunct *c = bound.query_DNF()->single_conjunct(); + for (EQ_Iterator ei(c->EQs()); ei; ei++) { + if ((*ei).has_wildcards()) + continue; + + int coef = (*ei).get_coef(bound.set_var(levels[i])); + if (coef != 0) { + int sign = 1; + if (coef < 0) { + coef = -coef; + sign = -1; + } + + CG_outputRepr *op = NULL; + for (Constr_Vars_Iter ci(*ei); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + if ((*ci).var != bound.set_var(levels[i])) + if ((*ci).coef * sign == 1) + op = ocg1->CreateMinus(op, + ocg1->CreateIdent((*ci).var->name())); + else if ((*ci).coef * sign == -1) + op = ocg1->CreatePlus(op, + ocg1->CreateIdent((*ci).var->name())); + else if ((*ci).coef * sign > 1) { + op = ocg1->CreateMinus(op, + ocg1->CreateTimes( + ocg1->CreateInt( + abs((*ci).coef)), + ocg1->CreateIdent( + (*ci).var->name()))); + } + else + // (*ci).coef*sign < -1 + op = ocg1->CreatePlus(op, + ocg1->CreateTimes( + ocg1->CreateInt( + abs((*ci).coef)), + ocg1->CreateIdent( + (*ci).var->name()))); + break; + } + case Global_Var: { + Global_Var_ID g = (*ci).var->get_global_var(); + if ((*ci).coef * sign == 1) + op = ocg1->CreateMinus(op, + ocg1->CreateIdent(g->base_name())); + else if ((*ci).coef * sign == -1) + op = ocg1->CreatePlus(op, + ocg1->CreateIdent(g->base_name())); + else if ((*ci).coef * sign > 1) + op = ocg1->CreateMinus(op, + ocg1->CreateTimes( + ocg1->CreateInt(abs((*ci).coef)), + ocg1->CreateIdent(g->base_name()))); + else + // (*ci).coef*sign < -1 + op = ocg1->CreatePlus(op, + ocg1->CreateTimes( + ocg1->CreateInt(abs((*ci).coef)), + ocg1->CreateIdent(g->base_name()))); + break; + } + default: + throw loop_error("unsupported array index expression"); + } + } + if ((*ei).get_const() != 0) + op = ocg1->CreatePlus(op, + ocg1->CreateInt(-sign * ((*ei).get_const()))); + if (coef != 1) + op = ocg1->CreateIntegerFloor(op, ocg1->CreateInt(coef)); + + index_lb[i] = op; + is_index_eq[i] = true; + break; + } + } + if (is_index_eq[i]) + continue; + + // separate lower and upper bounds + std::vector<GEQ_Handle> lb_list, ub_list; + std::set<Variable_ID> excluded_floor_vars; + excluded_floor_vars.insert(bound.set_var(levels[i])); + for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { + int coef = (*gi).get_coef(bound.set_var(levels[i])); + if (coef != 0 && (*gi).has_wildcards()) { + bool clean_bound = true; + GEQ_Handle h; + for (Constr_Vars_Iter cvi(*gi, true); gi; gi++) + if (!find_floor_definition(bound, (*cvi).var, + excluded_floor_vars).first) { + clean_bound = false; + break; + } + else + h= find_floor_definition(bound, (*cvi).var, + excluded_floor_vars).second; + + if (!clean_bound) + continue; + else{ + if (coef > 0) + lb_list.push_back(h); + else if (coef < 0) + ub_list.push_back(h); + continue; + } + + } + + if (coef > 0) + lb_list.push_back(*gi); + else if (coef < 0) + ub_list.push_back(*gi); + } + if (lb_list.size() == 0 || ub_list.size() == 0) + throw loop_error("failed to calcuate array footprint size"); + + // build lower bound representation + std::vector<CG_outputRepr *> lb_repr_list; + /* for (int j = 0; j < lb_list.size(); j++){ + if(this->known.n_set() == 0) + lb_repr_list.push_back(output_lower_bound_repr(ocg1, lb_list[j], bound.set_var(level-1+i+1), result.first, result.second, bound, Relation::True(bound.n_set()), std::vector<std::pair<CG_outputRepr *, int> >(bound.n_set(), std::make_pair(static_cast<CG_outputRepr *>(NULL), 0)))); + else + lb_repr_list.push_back(output_lower_bound_repr(ocg1, lb_list[j], bound.set_var(level-1+i+1), result.first, result.second, bound, this->known, std::vector<std::pair<CG_outputRepr *, int> >(bound.n_set(), std::make_pair(static_cast<CG_outputRepr *>(NULL), 0)))); + + } + */ + if (lb_repr_list.size() > 1) + index_lb[i] = ocg1->CreateInvoke("max", lb_repr_list); + else if (lb_repr_list.size() == 1) + index_lb[i] = lb_repr_list[0]; + + // build temporary array size representation + { + Relation cal(copy_is.n_set(), 1); + F_And *f_root = cal.add_and(); + for (int j = 0; j < ub_list.size(); j++) + for (int k = 0; k < lb_list.size(); k++) { + GEQ_Handle h = f_root->add_GEQ(); + + for (Constr_Vars_Iter ci(ub_list[j]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + int pos = (*ci).var->get_position(); + h.update_coef(cal.input_var(pos), (*ci).coef); + break; + } + case Global_Var: { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = cal.get_local(g); + else + v = cal.get_local(g, (*ci).var->function_of()); + h.update_coef(v, (*ci).coef); + break; + } + default: + throw loop_error( + "cannot calculate temporay array size statically"); + } + } + h.update_const(ub_list[j].get_const()); + + for (Constr_Vars_Iter ci(lb_list[k]); ci; ci++) { + switch ((*ci).var->kind()) { + case Input_Var: { + int pos = (*ci).var->get_position(); + h.update_coef(cal.input_var(pos), (*ci).coef); + break; + } + case Global_Var: { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = cal.get_local(g); + else + v = cal.get_local(g, (*ci).var->function_of()); + h.update_coef(v, (*ci).coef); + break; + } + default: + throw loop_error( + "cannot calculate temporay array size statically"); + } + } + h.update_const(lb_list[k].get_const()); + + h.update_const(1); + h.update_coef(cal.output_var(1), -1); + } + + cal = Restrict_Domain(cal, copy(copy_is)); + for (int j = 1; j <= cal.n_inp(); j++) { + cal = Project(cal, j, Input_Var); + } + cal.simplify(); + + // pad temporary array size + // TODO: for variable array size, create padding formula + //int padding_stride = 0; + Conjunct *c = cal.query_DNF()->single_conjunct(); + bool is_index_bound_const = false; + if (padding_stride != 0 && i == n_dim - 1) { + //size = (size + index_stride[i] - 1) / index_stride[i]; + size_repr.push_back(ocg1->CreateInt(padding_stride)); + } else { + for (GEQ_Iterator gi(c->GEQs()); gi && !is_index_bound_const; + gi++) + if ((*gi).is_const(cal.output_var(1))) { + coef_t size = (*gi).get_const() + / (-(*gi).get_coef(cal.output_var(1))); + + if (padding_alignment > 1 && i == n_dim - 1) { // align to boundary for data packing + int residue = size % padding_alignment; + if (residue) + size = size + padding_alignment - residue; + } + + index_sz.push_back( + std::make_pair(i, ocg1->CreateInt(size))); + is_index_bound_const = true; + size_int.push_back(size); + size_repr.push_back(ocg1->CreateInt(size)); + + // std::cout << "============================== size :: " + // << size << "\n"; + + } + + if (!is_index_bound_const) { + + found_non_constant_size_dimension = true; + Conjunct *c = bound.query_DNF()->single_conjunct(); + for (GEQ_Iterator gi(c->GEQs()); + gi && !is_index_bound_const; gi++) { + int coef = (*gi).get_coef(bound.set_var(levels[i])); + if (coef < 0) { + + size_repr.push_back( + ocg1->CreatePlus( + output_upper_bound_repr(ocg1, *gi, + bound.set_var(levels[i]), + bound, + std::vector< + std::pair< + CG_outputRepr *, + int> >( + bound.n_set(), + std::make_pair( + static_cast<CG_outputRepr *>(NULL), + 0)), + uninterpreted_symbols[stmt_num]), + ocg1->CreateInt(1))); + + /*CG_outputRepr *op = NULL; + for (Constr_Vars_Iter ci(*gi); ci; ci++) { + if ((*ci).var != cal.output_var(1)) { + switch ((*ci).var->kind()) { + case Global_Var: { + Global_Var_ID g = + (*ci).var->get_global_var(); + if ((*ci).coef == 1) + op = ocg1->CreatePlus(op, + ocg1->CreateIdent( + g->base_name())); + else if ((*ci).coef == -1) + op = ocg1->CreateMinus(op, + ocg1->CreateIdent( + g->base_name())); + else if ((*ci).coef > 1) + op = + ocg1->CreatePlus(op, + ocg1->CreateTimes( + ocg1->CreateInt( + (*ci).coef), + ocg1->CreateIdent( + g->base_name()))); + else + // (*ci).coef < -1 + op = + ocg1->CreateMinus(op, + ocg1->CreateTimes( + ocg1->CreateInt( + -(*ci).coef), + ocg1->CreateIdent( + g->base_name()))); + break; + } + default: + throw loop_error( + "failed to generate array index bound code"); + } + } + } + int c = (*gi).get_const(); + if (c > 0) + op = ocg1->CreatePlus(op, ocg1->CreateInt(c)); + else if (c < 0) + op = ocg1->CreateMinus(op, ocg1->CreateInt(-c)); + */ + /* if (padding_stride != 0) { + if (i == fastest_changing_dimension) { + coef_t g = gcd(index_stride[i], static_cast<coef_t>(padding_stride)); + coef_t t1 = index_stride[i] / g; + if (t1 != 1) + op = ocg->CreateIntegerFloor(ocg->CreatePlus(op, ocg->CreateInt(t1-1)), ocg->CreateInt(t1)); + coef_t t2 = padding_stride / g; + if (t2 != 1) + op = ocg->CreateTimes(op, ocg->CreateInt(t2)); + } + else if (index_stride[i] != 1) { + op = ocg->CreateIntegerFloor(ocg->CreatePlus(op, ocg->CreateInt(index_stride[i]-1)), ocg->CreateInt(index_stride[i])); + } + } + */ + //index_sz.push_back(std::make_pair(i, op)); + //break; + } + } + } + } + } + //size[i] = ub[i]; + + } + ///////////////////////////////////////////////////////////////////////////////////////////////////// + // + + //Anand: Creating IS of new statement + + //for(int l = dim; l < stmt[stmt_num].xform.n_out(); l+=2) + //std::cout << "In scalar_expand function 3: " << stmt_num << ", " << arrName << "\n"; + //std::cout.flush(); + + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; i<stmt.size(); i++) { + // fprintf(stderr, "%2d ", i); + // ((CG_chillRepr *)stmt[i].code)->Dump(); + //} + //fprintf(stderr, "\n"); + + + shiftLexicalOrder(lex, dim + 1, 1); + Statement s = stmt[stmt_num]; + s.ir_stmt_node = NULL; + int newStmt_num = stmt.size(); + + fprintf(stderr, "loop.cc L3249 adding stmt %d\n", stmt.size()); + stmt.push_back(s); + + fprintf(stderr, "uninterpreted_symbols.push_back() newStmt_num %d\n", newStmt_num); + uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); + stmt[newStmt_num].code = stmt[stmt_num].code->clone(); + stmt[newStmt_num].IS = copy(stmt[stmt_num].IS); + stmt[newStmt_num].xform = xform; + stmt[newStmt_num].reduction = stmt[stmt_num].reduction; + stmt[newStmt_num].reductionOp = stmt[stmt_num].reductionOp; + + + //fprintf(stderr, "\nafter clone, %d statements\n", stmt.size()); + //for (int i=0; i<stmt.size(); i++) { + // fprintf(stderr, "%2d ", i); + // ((CG_chillRepr *)stmt[i].code)->Dump(); + //} + //fprintf(stderr, "\n"); + + + + //assign_const(stmt[newStmt_num].xform, stmt[stmt_num].xform.n_out(), 1);//Anand: change from 2*level + 1 to stmt[stmt_num].xform.size() + //Anand-End creating IS of new statement + + CG_outputRepr * tmpArrSz; + CG_outputBuilder *ocg = ir->builder(); + + //for(int k =0; k < levels.size(); k++ ) + // size_repr.push_back(ocg->CreateInt(size[k]));//Anand: copying apply_xform functionality to prevent IS modification + //due to side effects with uninterpreted function symbols and failures in omega + + //int n = stmt[stmt_num].loop_level.size(); + + /*Relation mapping(2 * n + 1, n); + F_And *f_root = mapping.add_and(); + for (int j = 1; j <= n; j++) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(j), 1); + h.update_coef(mapping.input_var(2 * j), -1); + } + mapping = Composition(mapping, copy(stmt[stmt_num].xform)); + mapping.simplify(); + + // match omega input/output variables to variable names in the code + for (int j = 1; j <= stmt[stmt_num].IS.n_set(); j++) + mapping.name_input_var(j, stmt[stmt_num].IS.set_var(j)->name()); + for (int j = 1; j <= n; j++) + mapping.name_output_var(j, + tmp_loop_var_name_prefix + + to_string(tmp_loop_var_name_counter + j - 1)); + mapping.setup_names(); + + Relation size_ = omega::Range(Restrict_Domain(mapping, copy(stmt[stmt_num].IS))); + size_.simplify(); + */ + + //Anand -commenting out tmp sym creation as symbol may have more than one dimension + //tmp_sym = ir->CreateArraySymbol(tmpArrSz, sym); + std::vector<CG_outputRepr *> lhs_index; + CG_outputRepr *arr_ref_repr; + arr_ref_repr = ocg->CreateIdent( + stmt[stmt_num].IS.set_var(levels[levels.size() - 1])->name()); + + CG_outputRepr *total_size = size_repr[0]; + fprintf(stderr, "total_size = "); total_size->dump(); fflush(stdout); + + for (int i = 1; i < size_repr.size(); i++) { + fprintf(stderr, "total_size now "); total_size->dump(); fflush(stdout); fprintf(stderr, " times something\n\n"); + + total_size = ocg->CreateTimes(total_size->clone(), + size_repr[i]->clone()); + + } + + // COMMENT NEEDED + //fprintf(stderr, "\nloop.cc COMMENT NEEDED\n"); + for (int k = levels.size() - 2; k >= 0; k--) { + CG_outputRepr *temp_repr =ocg->CreateIdent(stmt[stmt_num].IS.set_var(levels[k])->name()); + for (int l = k + 1; l < levels.size(); l++) { + //fprintf(stderr, "\nloop.cc CREATETIMES\n"); + temp_repr = ocg->CreateTimes(temp_repr->clone(), + size_repr[l]->clone()); + } + + //fprintf(stderr, "\nloop.cc CREATEPLUS\n"); + arr_ref_repr = ocg->CreatePlus(arr_ref_repr->clone(), + temp_repr->clone()); + } + + + //fprintf(stderr, "loop.cc, about to die\n"); + std::vector<CG_outputRepr *> to_push; + to_push.push_back(total_size); + + if (!found_non_constant_size_dimension) { + fprintf(stderr, "constant size dimension\n"); + tmp_sym = ir->CreateArraySymbol(sym, to_push, memory_type); + } + else { + fprintf(stderr, "NON constant size dimension?\n"); + //tmp_sym = ir->CreatePointerSymbol(sym, to_push); + tmp_sym = ir->CreatePointerSymbol(sym, to_push); + + static_cast<IR_PointerSymbol *>(tmp_sym)->set_size(0, total_size); // ?? + ptr_variables.push_back(static_cast<IR_PointerSymbol *>(tmp_sym)); + fprintf(stderr, "ptr_variables now has %d entries\n", ptr_variables.size()); + } + + // add tmp_sym to Loop symtables ?? + + + // std::cout << " temp array name == " << tmp_sym->name().c_str() << "\n"; + + // get loop index variable at the given "level" + // Relation R = omega::Range(Restrict_Domain(copy(stmt[stmt_num].xform), copy(stmt[stmt_num].IS))); + // stmt[stmt_num].IS.print(); + //stmt[stmt_num].IS. + // std::cout << stmt[stmt_num].IS.n_set() << std::endl; + // std::string v = stmt[stmt_num].IS.set_var(level)->name(); + // std::cout << "loop index variable is '" << v.c_str() << "'\n"; + + // create a reference for the temporary array + fprintf(stderr, "create a reference for the temporary array\n"); + //std::cout << "In scalar_expand function 4: " << stmt_num << ", " << arrName << "\n"; + //std::cout.flush(); + + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; i<stmt.size(); i++) { + // fprintf(stderr, "%2d ", i); + // ((CG_chillRepr *)stmt[i].code)->Dump(); + //} + //fprintf(stderr, "\n"); + + + + std::vector<CG_outputRepr *> to_push2; + to_push2.push_back(arr_ref_repr); // can have only one entry + + //lhs_index[0] = ocg->CreateIdent(v); + + + IR_ArrayRef *tmp_array_ref; + IR_PointerArrayRef * tmp_ptr_array_ref; // was IR_PointerArrayref + + if (!found_non_constant_size_dimension) { + fprintf(stderr, "constant size\n"); + + tmp_array_ref = ir->CreateArrayRef( + static_cast<IR_ArraySymbol *>(tmp_sym), to_push2); + } + else { + fprintf(stderr, "NON constant size\n"); + tmp_ptr_array_ref = ir->CreatePointerArrayRef( + static_cast<IR_PointerSymbol *>(tmp_sym), to_push2); + // TODO static_cast<IR_PointerSymbol *>(tmp_sym), to_push2); + } + fflush(stdout); + + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; i<stmt.size(); i++) { + // fprintf(stderr, "%2d ", i); + // ((CG_chillRepr *)stmt[i].code)->Dump(); + //} + //fprintf(stderr, "\n"); + + + //std::string stemp; + //stemp = tmp_array_ref->name(); + //std::cout << "Created array reference --> " << stemp.c_str() << "\n"; + + // get the RHS expression + fprintf(stderr, "get the RHS expression arrName %s\n", arrName.c_str()); + + CG_outputRepr *rhs; + if (arrName == "RHS") { + rhs = ir->GetRHSExpression(stmt[stmt_num].code); + + std::vector<IR_ArrayRef *> symbols = ir->FindArrayRef(rhs); + } + std::set<std::string> sym_names; + + //for (int i = 0; i < symbols.size(); i++) + // sym_names.insert(symbols[i]->symbol()->name()); + + fflush(stdout); + + //fprintf(stderr, "\nbefore if (arrName == RHS)\n%d statements\n", stmt.size()); // problem is after here + //for (int i=0; i<stmt.size(); i++) { + // fprintf(stderr, "%2d ", i); + // ((CG_chillRepr *)stmt[i].code)->Dump(); + //} + //fprintf(stderr, "\n"); + + if (arrName == "RHS") { + + std::vector<IR_ArrayRef *> symbols = ir->FindArrayRef(rhs); + + for (int i = 0; i < symbols.size(); i++) + sym_names.insert(symbols[i]->symbol()->name()); + } + else { + + fprintf(stderr, "finding array refs in stmt_num %d\n", stmt_num); + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; i<stmt.size(); i++) { + // fprintf(stderr, "%2d ", i); + // ((CG_chillRepr *)stmt[i].code)->Dump(); + //} + //fprintf(stderr, "\n"); + + std::vector<IR_ArrayRef *> refs = ir->FindArrayRef(stmt[stmt_num].code); + fprintf(stderr, "\n%d refs\n", refs.size()); + + + bool found = false; + + for (int j = 0; j < refs.size(); j++) { + CG_outputRepr* to_replace; + + fprintf(stderr, "j %d build new assignment statement with temporary array\n",j); + // build new assignment statement with temporary array + if (!found_non_constant_size_dimension) { + to_replace = tmp_array_ref->convert(); + } else { + to_replace = tmp_ptr_array_ref->convert(); + } + //fprintf(stderr, "to_replace %p\n", to_replace); + //CG_chillRepr *CR = (CG_chillRepr *) to_replace; + //CR->Dump(); + + if (refs[j]->name() == arrName) { + fflush(stdout); + fprintf(stderr, "loop.cc L353\n"); // problem is after here + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; i<stmt.size(); i++) { + // fprintf(stderr, "%2d ", i); + // ((CG_chillRepr *)stmt[i].code)->Dump(); + //} + //fprintf(stderr, "\n"); + + + sym_names.insert(refs[j]->symbol()->name()); + + if (!found) { + if (!found_non_constant_size_dimension) { + fprintf(stderr, "constant size2\n"); + omega::CG_outputRepr * t = tmp_array_ref->convert(); + omega::CG_outputRepr * r = refs[j]->convert()->clone(); + //CR = (CG_chillRepr *) t; + //CR->Dump(); + //CR = (CG_chillRepr *) r; + //CR->Dump(); + + //fprintf(stderr, "lhs t %p lhs r %p\n", t, r); + stmt[newStmt_num].code = + ir->builder()->CreateAssignment(0, + t, // tmp_array_ref->convert(), + r); // refs[j]->convert()->clone() + } + else { + fprintf(stderr, "NON constant size2\n"); + omega::CG_outputRepr * t = tmp_ptr_array_ref->convert(); // this fails + omega::CG_outputRepr * r = refs[j]->convert()->clone(); + + //omega::CG_chillRepr *CR = (omega::CG_chillRepr *) t; + //CR->Dump(); + //CR = (omega::CG_chillRepr *) r; + //CR->Dump(); + + //fprintf(stderr, "lhs t %p lhs r %p\n", t, r); + stmt[newStmt_num].code = + ir->builder()->CreateAssignment(0, + t, // tmp_ptr_array_ref->convert(), + r ); // refs[j]->convert()->clone()); + } + found = true; + + } + + // refs[j] has no parent? + fprintf(stderr, "replacing refs[%d]\n", j ); + ir->ReplaceExpression(refs[j], to_replace); + } + + } + + } + //ToDo need to update the dependence graph + //Anand adding dependence graph update + fprintf(stderr, "adding dependence graph update\n"); // problem is before here + //fprintf(stderr, "\n%d statements\n", stmt.size()); + //for (int i=0; i<stmt.size(); i++) { + // fprintf(stderr, "%2d ", i); + // ((CG_chillRepr *)stmt[i].code)->Dump(); + //} + //fprintf(stderr, "\n"); + + dep.insert(); + + //Anand:Copying Dependence checks from datacopy code, might need to be a separate function/module + // in the future + + /*for (int i = 0; i < newStmt_num; i++) { + std::vector<std::vector<DependenceVector> > D; + + for (DependenceGraph::EdgeList::iterator j = + dep.vertex[i].second.begin(); j != dep.vertex[i].second.end(); + ) { + if (same_loop.find(i) != same_loop.end() + && same_loop.find(j->first) == same_loop.end()) { + std::vector<DependenceVector> dvs1, dvs2; + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.sym != NULL + && sym_names.find(dv.sym->name()) != sym_names.end() + && (dv.type == DEP_R2R || dv.type == DEP_R2W)) + dvs1.push_back(dv); + else + dvs2.push_back(dv); + } + j->second = dvs2; + if (dvs1.size() > 0) + dep.connect(newStmt_num, j->first, dvs1); + } else if (same_loop.find(i) == same_loop.end() + && same_loop.find(j->first) != same_loop.end()) { + std::vector<DependenceVector> dvs1, dvs2; + for (int k = 0; k < j->second.size(); k++) { + DependenceVector dv = j->second[k]; + if (dv.sym != NULL + && sym_names.find(dv.sym->name()) != sym_names.end() + && (dv.type == DEP_R2R || dv.type == DEP_W2R)) + dvs1.push_back(dv); + else + dvs2.push_back(dv); + } + j->second = dvs2; + if (dvs1.size() > 0) + D.push_back(dvs1); + } + + if (j->second.size() == 0) + dep.vertex[i].second.erase(j++); + else + j++; + } + + for (int j = 0; j < D.size(); j++) + dep.connect(i, newStmt_num, D[j]); + } + */ + //Anand--end dependence check + if (arrName == "RHS") { + + // build new assignment statement with temporary array + if (!found_non_constant_size_dimension) { + if (assign_then_accumulate) { + stmt[newStmt_num].code = ir->builder()->CreateAssignment(0, + tmp_array_ref->convert(), rhs); + fprintf(stderr, "ir->ReplaceRHSExpression( stmt_ num %d )\n", stmt_num); + ir->ReplaceRHSExpression(stmt[stmt_num].code, tmp_array_ref); + } else { + CG_outputRepr *temp = tmp_array_ref->convert()->clone(); + if (ir->QueryExpOperation(stmt[stmt_num].code) + != IR_OP_PLUS_ASSIGNMENT) + throw ir_error( + "Statement is not a += accumulation statement"); + + fprintf(stderr, "replacing in a +=\n"); + stmt[newStmt_num].code = ir->builder()->CreatePlusAssignment(0, + temp->clone(), rhs); + + CG_outputRepr * lhs = ir->GetLHSExpression(stmt[stmt_num].code); + + CG_outputRepr *assignment = ir->builder()->CreateAssignment(0, + lhs, temp->clone()); + Statement init_ = stmt[newStmt_num]; // copy ?? + init_.ir_stmt_node = NULL; + + init_.code = stmt[newStmt_num].code->clone(); + init_.IS = copy(stmt[newStmt_num].IS); + init_.xform = copy(stmt[newStmt_num].xform); + init_.has_inspector = false; // ?? + + Relation mapping(init_.IS.n_set(), init_.IS.n_set()); + + F_And *f_root = mapping.add_and(); + + for (int i = 1; i <= mapping.n_inp(); i++) { + EQ_Handle h = f_root->add_EQ(); + //if (i < levels[0]) { + if (i <= levels[levels.size() - 1]) { + h.update_coef(mapping.input_var(i), 1); + h.update_coef(mapping.output_var(i), -1); + } else { + h.update_const(-1); + h.update_coef(mapping.output_var(i), 1); + } + + /*else { + int j; + for (j = 0; j < levels.size(); j++) + if (i == levels[j]) + break; + + if (j == levels.size()) { + + h.update_coef(mapping.output_var(i), 1); + h.update_const(-1); + + } else { + + + h.update_coef(mapping.input_var(i), 1); + h.update_coef(mapping.output_var(i), -1); + + + } + */ + //} + } + + mapping.simplify(); + // match omega input/output variables to variable names in the code + for (int j = 1; j <= init_.IS.n_set(); j++) + mapping.name_output_var(j, init_.IS.set_var(j)->name()); + for (int j = 1; j <= init_.IS.n_set(); j++) + mapping.name_input_var(j, init_.IS.set_var(j)->name()); + + mapping.setup_names(); + + init_.IS = omega::Range( + omega::Restrict_Domain(mapping, init_.IS)); + std::vector<int> lex = getLexicalOrder(newStmt_num); + int dim = 2 * levels[0] - 1; + //init_.IS.print(); + // init_.xform.print(); + //stmt[newStmt_num].xform.print(); + // shiftLexicalOrder(lex, dim + 1, 1); + shiftLexicalOrder(lex, dim + 1, 1); + init_.reduction = stmt[newStmt_num].reduction; + init_.reductionOp = stmt[newStmt_num].reductionOp; + + init_.code = ir->builder()->CreateAssignment(0, temp->clone(), + ir->builder()->CreateInt(0)); + + fprintf(stderr, "loop.cc L3693 adding stmt %d\n", stmt.size()); + stmt.push_back(init_); + + uninterpreted_symbols.push_back(uninterpreted_symbols[newStmt_num]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[newStmt_num]); + stmt[stmt_num].code = assignment; + } + } else { + if (assign_then_accumulate) { + stmt[newStmt_num].code = ir->builder()->CreateAssignment(0, + tmp_ptr_array_ref->convert(), rhs); + ir->ReplaceRHSExpression(stmt[stmt_num].code, + tmp_ptr_array_ref); + } else { + CG_outputRepr *temp = tmp_ptr_array_ref->convert()->clone(); + if (ir->QueryExpOperation(stmt[stmt_num].code) + != IR_OP_PLUS_ASSIGNMENT) + throw ir_error( + "Statement is not a += accumulation statement"); + stmt[newStmt_num].code = ir->builder()->CreatePlusAssignment(0, + temp->clone(), rhs); + + CG_outputRepr * lhs = ir->GetLHSExpression(stmt[stmt_num].code); + + CG_outputRepr *assignment = ir->builder()->CreateAssignment(0, + lhs, temp->clone()); + + stmt[stmt_num].code = assignment; + } + // call function to replace rhs with temporary array + } + } + + //std::cout << "End of scalar_expand function!! \n"; + + // if(arrName == "RHS"){ + DependenceVector dv; + std::vector<DependenceVector> E; + dv.lbounds = std::vector<omega::coef_t>(4); + dv.ubounds = std::vector<omega::coef_t>(4); + dv.type = DEP_W2R; + + for (int k = 0; k < 4; k++) { + dv.lbounds[k] = 0; + dv.ubounds[k] = 0; + + } + + //std::vector<IR_ArrayRef*> array_refs = ir->FindArrayRef(stmt[newStmt_num].code); + dv.sym = tmp_sym->clone(); + + E.push_back(dv); + + dep.connect(newStmt_num, stmt_num, E); + // } + +} + + + +std::pair<Relation, Relation> createCSRstyleISandXFORM(CG_outputBuilder *ocg, + std::vector<Relation> &outer_loop_bounds, std::string index_name, + std::map<int, Relation> &zero_loop_bounds, + std::map<std::string, std::vector<omega::CG_outputRepr *> > &uninterpreted_symbols, + std::map<std::string, std::vector<omega::CG_outputRepr *> > &uninterpreted_symbols_string, + Loop *this_loop) { + + Relation IS(outer_loop_bounds.size() + 1 + zero_loop_bounds.size()); + Relation XFORM(outer_loop_bounds.size() + 1 + zero_loop_bounds.size(), + 2 * (outer_loop_bounds.size() + 1 + zero_loop_bounds.size()) + 1); + + F_And * f_r_ = IS.add_and(); + F_And * f_root = XFORM.add_and(); + + if (outer_loop_bounds.size() > 0) { + for (int it = 0; it < IS.n_set(); it++) { + IS.name_set_var(it + 1, + const_cast<Relation &>(outer_loop_bounds[0]).set_var(it + 1)->name()); + XFORM.name_input_var(it + 1, + const_cast<Relation &>(outer_loop_bounds[0]).set_var(it + 1)->name()); + + } + } else if (zero_loop_bounds.size() > 0) { + for (int it = 0; it < IS.n_set(); it++) { + IS.name_set_var(it + 1, + const_cast<Relation &>(zero_loop_bounds.begin()->second).set_var( + it + 1)->name()); + XFORM.name_input_var(it + 1, + const_cast<Relation &>(zero_loop_bounds.begin()->second).set_var( + it + 1)->name()); + + } + + } + + for (int i = 0; i < outer_loop_bounds.size(); i++) + IS = replace_set_var_as_another_set_var(IS, outer_loop_bounds[i], i + 1, + i + 1); + + int count = 1; + for (std::map<int, Relation>::iterator i = zero_loop_bounds.begin(); + i != zero_loop_bounds.end(); i++, count++) + IS = replace_set_var_as_another_set_var(IS, i->second, + outer_loop_bounds.size() + 1 + count, i->first); + + if (outer_loop_bounds.size() > 0) { + Free_Var_Decl *lb = new Free_Var_Decl(index_name + "_", 1); // index_ + Variable_ID csr_lb = IS.get_local(lb, Input_Tuple); + + Free_Var_Decl *ub = new Free_Var_Decl(index_name + "__", 1); // index__ + Variable_ID csr_ub = IS.get_local(ub, Input_Tuple); + + //lower bound + + F_And * f_r = IS.and_with_and(); + GEQ_Handle lower_bound = f_r->add_GEQ(); + lower_bound.update_coef(csr_lb, -1); + lower_bound.update_coef(IS.set_var(outer_loop_bounds.size() + 1), 1); + + //upper bound + + GEQ_Handle upper_bound = f_r->add_GEQ(); + upper_bound.update_coef(csr_ub, 1); + upper_bound.update_coef(IS.set_var(outer_loop_bounds.size() + 1), -1); + upper_bound.update_const(-1); + + omega::CG_stringBuilder *ocgs = new CG_stringBuilder; + + std::vector<omega::CG_outputRepr *> reprs; + std::vector<omega::CG_outputRepr *> reprs2; + + std::vector<omega::CG_outputRepr *> reprs3; + std::vector<omega::CG_outputRepr *> reprs4; + + reprs.push_back( + ocg->CreateIdent(IS.set_var(outer_loop_bounds.size())->name())); + reprs2.push_back( + ocgs->CreateIdent( + IS.set_var(outer_loop_bounds.size())->name())); + uninterpreted_symbols.insert( + std::pair<std::string, std::vector<CG_outputRepr *> >( + index_name + "_", reprs)); + uninterpreted_symbols_string.insert( + std::pair<std::string, std::vector<CG_outputRepr *> >( + index_name + "_", reprs2)); + + std::string arg = "(" + IS.set_var(outer_loop_bounds.size())->name() + + ")"; + std::vector< std::string > argvec; + argvec.push_back( arg ); + + CG_outputRepr *repr = ocg->CreateArrayRefExpression(index_name, + ocg->CreateIdent(IS.set_var(outer_loop_bounds.size())->name())); + + //fprintf(stderr, "( VECTOR _)\n"); + //fprintf(stderr, "loop.cc calling CreateDefineMacro( %s, argvec, repr)\n", (index_name + "_").c_str()); + this_loop->ir->CreateDefineMacro(index_name + "_", argvec, repr); + + Relation known_(copy(IS).n_set()); + known_.copy_names(copy(IS)); + known_.setup_names(); + Variable_ID index_lb = known_.get_local(lb, Input_Tuple); + Variable_ID index_ub = known_.get_local(ub, Input_Tuple); + F_And *fr = known_.add_and(); + GEQ_Handle g = fr->add_GEQ(); + g.update_coef(index_ub, 1); + g.update_coef(index_lb, -1); + g.update_const(-1); + this_loop->addKnown(known_); + + reprs3.push_back( + + ocg->CreateIdent(IS.set_var(outer_loop_bounds.size())->name())); + reprs4.push_back( + + ocgs->CreateIdent(IS.set_var(outer_loop_bounds.size())->name())); + + CG_outputRepr *repr2 = ocg->CreateArrayRefExpression(index_name, + ocg->CreatePlus( + ocg->CreateIdent( + IS.set_var(outer_loop_bounds.size())->name()), + ocg->CreateInt(1))); + + //fprintf(stderr, "( VECTOR __)\n"); + //fprintf(stderr, "loop.cc calling CreateDefineMacro( %s, argvec, repr)\n", (index_name + "__").c_str()); + + this_loop->ir->CreateDefineMacro(index_name + "__", argvec, repr2); + + uninterpreted_symbols.insert( + std::pair<std::string, std::vector<CG_outputRepr *> >( + index_name + "__", reprs3)); + uninterpreted_symbols_string.insert( + std::pair<std::string, std::vector<CG_outputRepr *> >( + index_name + "__", reprs4)); + } else { + Free_Var_Decl *ub = new Free_Var_Decl(index_name); + Variable_ID csr_ub = IS.get_local(ub); + F_And * f_r = IS.and_with_and(); + GEQ_Handle upper_bound = f_r->add_GEQ(); + upper_bound.update_coef(csr_ub, 1); + upper_bound.update_coef(IS.set_var(outer_loop_bounds.size() + 1), -1); + upper_bound.update_const(-1); + + GEQ_Handle lower_bound = f_r->add_GEQ(); + lower_bound.update_coef(IS.set_var(outer_loop_bounds.size() + 1), 1); + + } + + for (int j = 1; j <= XFORM.n_inp(); j++) { + omega::EQ_Handle h = f_root->add_EQ(); + h.update_coef(XFORM.output_var(2 * j), 1); + h.update_coef(XFORM.input_var(j), -1); + } + + for (int j = 1; j <= XFORM.n_out(); j += 2) { + omega::EQ_Handle h = f_root->add_EQ(); + h.update_coef(XFORM.output_var(j), 1); + } + + if (_DEBUG_) { + IS.print(); + XFORM.print(); + + } + + return std::pair<Relation, Relation>(IS, XFORM); + } +std::pair<Relation, Relation> construct_reduced_IS_And_XFORM(IR_Code *ir, + const Relation &is, const Relation &xform, const std::vector<int> loops, + std::vector<int> &lex_order, Relation &known, + std::map<std::string, std::vector<CG_outputRepr *> > &uninterpreted_symbols) { + + Relation IS(loops.size()); + Relation XFORM(loops.size(), 2 * loops.size() + 1); + int count_ = 1; + std::map<int, int> pos_mapping; + + int n = is.n_set(); + Relation is_and_known = Intersection(copy(is), + Extend_Set(copy(known), n - known.n_set())); + + for (int it = 0; it < loops.size(); it++, count_++) { + IS.name_set_var(count_, + const_cast<Relation &>(is).set_var(loops[it])->name()); + XFORM.name_input_var(count_, + const_cast<Relation &>(xform).input_var(loops[it])->name()); + XFORM.name_output_var(2 * count_, + const_cast<Relation &>(xform).output_var((loops[it]) * 2)->name()); + XFORM.name_output_var(2 * count_ - 1, + const_cast<Relation &>(xform).output_var((loops[it]) * 2 - 1)->name()); + pos_mapping.insert(std::pair<int, int>(count_, loops[it])); + } + + XFORM.name_output_var(2 * loops.size() + 1, + const_cast<Relation &>(xform).output_var(is.n_set() * 2 + 1)->name()); + + F_And * f_r = IS.add_and(); + for (std::map<int, int>::iterator it = pos_mapping.begin(); + it != pos_mapping.end(); it++) + IS = replace_set_var_as_another_set_var(IS, is_and_known, it->first, + it->second); + /* + for (std::map<std::string, std::vector<CG_outputRepr *> >::iterator it2 = + uninterpreted_symbols.begin(); + it2 != uninterpreted_symbols.end(); it2++) { + std::vector<CG_outputRepr *> reprs_ = it2->second; + //std::vector<CG_outputRepr *> reprs_2; + + for (int k = 0; k < reprs_.size(); k++) { + std::vector<IR_ScalarRef *> refs = ir->FindScalarRef(reprs_[k]); + bool exception_found = false; + for (int m = 0; m < refs.size(); m++){ + + if (refs[m]->name() + == const_cast<Relation &>(is).set_var(it->second)->name()) + try { + ir->ReplaceExpression(refs[m], + ir->builder()->CreateIdent( + IS.set_var(it->first)->name())); + } catch (ir_error &e) { + + reprs_[k] = ir->builder()->CreateIdent( + IS.set_var(it->first)->name()); + exception_found = true; + } + if(exception_found) + break; + } + + } + it2->second = reprs_; + } + + } + */ + if (_DEBUG_) { + std::cout << "relation debug" << std::endl; + IS.print(); + } + + F_And *f_root = XFORM.add_and(); + + count_ = 1; + + for (int j = 1; j <= loops.size(); j++) { + omega::EQ_Handle h = f_root->add_EQ(); + h.update_coef(XFORM.output_var(2 * j), 1); + h.update_coef(XFORM.input_var(j), -1); + } + for (int j = 0; j < loops.size(); j++, count_++) { + omega::EQ_Handle h = f_root->add_EQ(); + h.update_coef(XFORM.output_var(count_ * 2 - 1), 1); + h.update_const(-lex_order[count_ * 2 - 2]); + } + + omega::EQ_Handle h = f_root->add_EQ(); + h.update_coef(XFORM.output_var((loops.size()) * 2 + 1), 1); + h.update_const(-lex_order[xform.n_out() - 1]); + + if (_DEBUG_) { + std::cout << "relation debug" << std::endl; + IS.print(); + XFORM.print(); + } + + return std::pair<Relation, Relation>(IS, XFORM); + +} + +std::set<std::string> inspect_repr_for_scalars(IR_Code *ir, + CG_outputRepr * repr, std::set<std::string> ignore) { + + std::vector<IR_ScalarRef *> refs = ir->FindScalarRef(repr); + std::set<std::string> loop_vars; + + for (int i = 0; i < refs.size(); i++) + if (ignore.find(refs[i]->name()) == ignore.end()) + loop_vars.insert(refs[i]->name()); + + return loop_vars; + +} + +std::set<std::string> inspect_loop_bounds(IR_Code *ir, const Relation &R, + int pos, + std::map<std::string, std::vector<omega::CG_outputRepr *> > &uninterpreted_symbols) { + + if (!R.is_set()) + throw loop_error("Input R has to be a set not a relation!"); + + std::set<std::string> vars; + + std::vector<CG_outputRepr *> refs; + Variable_ID v = const_cast<Relation &>(R).set_var(pos); + for (DNF_Iterator di(const_cast<Relation &>(R).query_DNF()); di; di++) { + for (GEQ_Iterator gi = (*di)->GEQs(); gi; gi++) { + if ((*gi).get_coef(v) != 0 && (*gi).is_const_except_for_global(v)) { + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + + case Global_Var: { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() > 0) { + + std::string s = g->base_name(); + std::copy( + uninterpreted_symbols.find(s)->second.begin(), + uninterpreted_symbols.find(s)->second.end(), + back_inserter(refs)); + + } + + break; + } + default: + break; + } + } + + } + } + } + + for (int i = 0; i < refs.size(); i++) { + std::vector<IR_ScalarRef *> refs_ = ir->FindScalarRef(refs[i]); + + for (int j = 0; j < refs_.size(); j++) + vars.insert(refs_[j]->name()); + + } + return vars; +} + +CG_outputRepr * create_counting_loop_body(IR_Code *ir, const Relation &R, + int pos, CG_outputRepr * count, + std::map<std::string, std::vector<omega::CG_outputRepr *> > &uninterpreted_symbols) { + + if (!R.is_set()) + throw loop_error("Input R has to be a set not a relation!"); + + CG_outputRepr *ub, *lb; + ub = NULL; + lb = NULL; + std::vector<CG_outputRepr *> refs; + Variable_ID v = const_cast<Relation &>(R).set_var(pos); + for (DNF_Iterator di(const_cast<Relation &>(R).query_DNF()); di; di++) { + for (GEQ_Iterator gi = (*di)->GEQs(); gi; gi++) { + if ((*gi).get_coef(v) != 0 && (*gi).is_const_except_for_global(v)) { + bool same_ge_1 = false; + bool same_ge_2 = false; + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + + case Global_Var: { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() > 0) { + + std::string s = g->base_name(); + + if ((*gi).get_coef(v) > 0) { + if (ub != NULL) + throw ir_error( + "bound expression too complex!"); + + ub = ir->builder()->CreateInvoke(s, + uninterpreted_symbols.find(s)->second); + //ub = ir->builder()->CreateMinus(ub->clone(), ir->builder()->CreateInt(-(*gi).get_const())); + same_ge_1 = true; + + } else { + if (lb != NULL) + throw ir_error( + "bound expression too complex!"); + lb = ir->builder()->CreateInvoke(s, + uninterpreted_symbols.find(s)->second); + same_ge_2 = true; + + } + } + + break; + } + default: + break; + } + } + + if (same_ge_1 && same_ge_2) + lb = ir->builder()->CreatePlus(lb->clone(), + ir->builder()->CreateInt(-(*gi).get_const())); + else if (same_ge_1) + ub = ir->builder()->CreatePlus(ub->clone(), + ir->builder()->CreateInt(-(*gi).get_const())); + else if (same_ge_2) + lb = ir->builder()->CreatePlus(lb->clone(), + ir->builder()->CreateInt(-(*gi).get_const())); + } + } + + } + + return ir->builder()->CreatePlusAssignment(0, count, + ir->builder()->CreatePlus( + ir->builder()->CreateMinus(ub->clone(), lb->clone()), + ir->builder()->CreateInt(1))); +} + + + +std::map<std::string, std::vector<std::string> > recurse_on_exp_for_arrays( + IR_Code * ir, CG_outputRepr * exp) { + + std::map<std::string, std::vector<std::string> > arr_index_to_ref; + switch (ir->QueryExpOperation(exp)) { + + case IR_OP_ARRAY_VARIABLE: { + IR_ArrayRef *ref = dynamic_cast<IR_ArrayRef *>(ir->Repr2Ref(exp)); + IR_PointerArrayRef *ref_ = + dynamic_cast<IR_PointerArrayRef *>(ir->Repr2Ref(exp)); + if (ref == NULL && ref_ == NULL) + throw loop_error("Array symbol unidentifiable!"); + + if (ref != NULL) { + std::vector<std::string> s0; + + for (int i = 0; i < ref->n_dim(); i++) { + CG_outputRepr * index = ref->index(i); + std::map<std::string, std::vector<std::string> > a0 = + recurse_on_exp_for_arrays(ir, index); + std::vector<std::string> s; + for (std::map<std::string, std::vector<std::string> >::iterator j = + a0.begin(); j != a0.end(); j++) { + if (j->second.size() != 1 && (j->second)[0] != "") + throw loop_error( + "indirect array references not allowed in guard!"); + s.push_back(j->first); + } + std::copy(s.begin(), s.end(), back_inserter(s0)); + } + arr_index_to_ref.insert( + std::pair<std::string, std::vector<std::string> >( + ref->name(), s0)); + } else { + std::vector<std::string> s0; + for (int i = 0; i < ref_->n_dim(); i++) { + CG_outputRepr * index = ref_->index(i); + std::map<std::string, std::vector<std::string> > a0 = + recurse_on_exp_for_arrays(ir, index); + std::vector<std::string> s; + for (std::map<std::string, std::vector<std::string> >::iterator j = + a0.begin(); j != a0.end(); j++) { + if (j->second.size() != 1 && (j->second)[0] != "") + throw loop_error( + "indirect array references not allowed in guard!"); + s.push_back(j->first); + } + std::copy(s.begin(), s.end(), back_inserter(s0)); + } + arr_index_to_ref.insert( + std::pair<std::string, std::vector<std::string> >( + ref_->name(), s0)); + } + break; + } + case IR_OP_PLUS: + case IR_OP_MINUS: + case IR_OP_MULTIPLY: + case IR_OP_DIVIDE: { + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(exp); + std::map<std::string, std::vector<std::string> > a0 = + recurse_on_exp_for_arrays(ir, v[0]); + std::map<std::string, std::vector<std::string> > a1 = + recurse_on_exp_for_arrays(ir, v[1]); + arr_index_to_ref.insert(a0.begin(), a0.end()); + arr_index_to_ref.insert(a1.begin(), a1.end()); + break; + + } + case IR_OP_POSITIVE: + case IR_OP_NEGATIVE: { + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(exp); + std::map<std::string, std::vector<std::string> > a0 = + recurse_on_exp_for_arrays(ir, v[0]); + + arr_index_to_ref.insert(a0.begin(), a0.end()); + break; + + } + case IR_OP_VARIABLE: { + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(exp); + IR_ScalarRef *ref = static_cast<IR_ScalarRef *>(ir->Repr2Ref(v[0])); + + std::string s = ref->name(); + std::vector<std::string> to_insert; + to_insert.push_back(""); + arr_index_to_ref.insert( + std::pair<std::string, std::vector<std::string> >(s, + to_insert)); + break; + } + case IR_OP_CONSTANT: + break; + + default: { + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(exp); + + for (int i = 0; i < v.size(); i++) { + std::map<std::string, std::vector<std::string> > a0 = + recurse_on_exp_for_arrays(ir, v[i]); + + arr_index_to_ref.insert(a0.begin(), a0.end()); + } + + break; + } + } + return arr_index_to_ref; +} + + + +std::vector<CG_outputRepr *> find_guards(IR_Code *ir, IR_Control *code) { + fprintf(stderr, "find_guards()\n"); + std::vector<CG_outputRepr *> guards; + switch (code->type()) { + case IR_CONTROL_IF: { + fprintf(stderr, "find_guards() it's an if\n"); + CG_outputRepr *cond = dynamic_cast<IR_If*>(code)->condition(); + + std::vector<CG_outputRepr *> then_body; + std::vector<CG_outputRepr *> else_body; + IR_Block *ORTB = dynamic_cast<IR_If*>(code)->then_body(); + if (ORTB != NULL) { + fprintf(stderr, "recursing on then\n"); + then_body = find_guards(ir, ORTB); + //dynamic_cast<IR_If*>(code)->then_body()); + } + if (dynamic_cast<IR_If*>(code)->else_body() != NULL) { + fprintf(stderr, "recursing on then\n"); + else_body = find_guards(ir, + dynamic_cast<IR_If*>(code)->else_body()); + } + + guards.push_back(cond); + if (then_body.size() > 0) + std::copy(then_body.begin(), then_body.end(), + back_inserter(guards)); + if (else_body.size() > 0) + std::copy(else_body.begin(), else_body.end(), + back_inserter(guards)); + break; + } + case IR_CONTROL_BLOCK: { + fprintf(stderr, "find_guards() it's a control block\n"); + IR_Block* IRCB = dynamic_cast<IR_Block*>(code); + fprintf(stderr, "find_guards() calling ir->FindOneLevelControlStructure(IRCB);\n"); + std::vector<IR_Control *> stmts = ir->FindOneLevelControlStructure(IRCB); + + for (int i = 0; i < stmts.size(); i++) { + std::vector<CG_outputRepr *> stmt_repr = find_guards(ir, stmts[i]); + std::copy(stmt_repr.begin(), stmt_repr.end(), + back_inserter(guards)); + } + break; + } + case IR_CONTROL_LOOP: { + fprintf(stderr, "find_guards() it's a control loop\n"); + std::vector<CG_outputRepr *> body = find_guards(ir, + dynamic_cast<IR_Loop*>(code)->body()); + if (body.size() > 0) + std::copy(body.begin(), body.end(), back_inserter(guards)); + break; + } // loop + } // switch + return guards; +} + +bool sort_helper(std::pair<std::string, std::vector<std::string> > i, + std::pair<std::string, std::vector<std::string> > j) { + int c1 = 0; + int c2 = 0; + for (int k = 0; k < i.second.size(); k++) + if (i.second[k] != "") + c1++; + + for (int k = 0; k < j.second.size(); k++) + if (j.second[k] != "") + c2++; + return (c1 < c2); + +} + +bool sort_helper_2(std::pair<int, int> i, std::pair<int, int> j) { + + return (i.second < j.second); + +} + +std::vector<std::string> construct_iteration_order( + std::map<std::string, std::vector<std::string> > & input) { + std::vector<std::string> arrays; + std::vector<std::string> scalars; + std::vector<std::pair<std::string, std::vector<std::string> > > input_aid; + + for (std::map<std::string, std::vector<std::string> >::iterator j = + input.begin(); j != input.end(); j++) + input_aid.push_back( + std::pair<std::string, std::vector<std::string> >(j->first, + j->second)); + + std::sort(input_aid.begin(), input_aid.end(), sort_helper); + + for (int j = 0; j < input_aid[input_aid.size() - 1].second.size(); j++) + if (input_aid[input_aid.size() - 1].second[j] != "") { + arrays.push_back(input_aid[input_aid.size() - 1].second[j]); + + } + + if (arrays.size() > 0) { + for (int i = input_aid.size() - 2; i >= 0; i--) { + + int max_count = 0; + for (int j = 0; j < input_aid[i].second.size(); j++) + if (input_aid[i].second[j] != "") { + max_count++; + } + if (max_count > 0) { + for (int j = 0; j < max_count; j++) { + std::string s = input_aid[i].second[j]; + bool found = false; + for (int k = 0; k < max_count; k++) + if (s == arrays[k]) + found = true; + if (!found) + throw loop_error("guard condition not solvable"); + } + } else { + bool found = false; + for (int k = 0; k < arrays.size(); k++) + if (arrays[k] == input_aid[i].first) + found = true; + if (!found) + arrays.push_back(input_aid[i].first); + } + } + } else { + + for (int i = input_aid.size() - 1; i >= 0; i--) { + arrays.push_back(input_aid[i].first); + } + } + return arrays; +} + + + diff --git a/src/loop_basic.cc b/src/loop_basic.cc index cf72c97..a058598 100644 --- a/src/loop_basic.cc +++ b/src/loop_basic.cc @@ -11,6 +11,8 @@ #include "omegatools.hh" #include <string.h> +#include <code_gen/CG_utils.h> + using namespace omega; void Loop::permute(const std::vector<int> &pi) { @@ -26,6 +28,7 @@ void Loop::original() { for (int i = 0; i < stmt.size(); i++) active.insert(i); setLexicalOrder(0, active); + //apply_xform(); } void Loop::permute(int stmt_num, int level, const std::vector<int> &pi) { // check for sanity of parameters @@ -35,7 +38,7 @@ void Loop::permute(int stmt_num, int level, const std::vector<int> &pi) { "invalid statement number " + to_string(stmt_num)); std::set<int> active; if (level < 0 || level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument("invalid loop level " + to_string(level)); + throw std::invalid_argument("3invalid loop level " + to_string(level)); else if (level == 0) { for (int i = 0; i < stmt.size(); i++) active.insert(i); @@ -436,8 +439,7 @@ void Loop::permute(const std::set<int> &active, const std::vector<int> &pi) { break; case LoopLevelTile: { new_loop_level[j - 1].type = LoopLevelTile; - int ref_level = stmt[*i].loop_level[reverse_pi[j - level] - - 1].payload; + int ref_level = stmt[*i].loop_level[reverse_pi[j - level]-1].payload; if (ref_level >= level && ref_level < level + pi.size()) new_loop_level[j - 1].payload = reverse_pi[ref_level - level]; @@ -485,12 +487,18 @@ void Loop::permute(const std::set<int> &active, const std::vector<int> &pi) { setLexicalOrder(2 * level - 2, active); } + +void Loop::set_array_size(std::string name, int size ){ + array_dims.insert(std::pair<std::string, int >(name, size)); +} + + std::set<int> Loop::split(int stmt_num, int level, const Relation &cond) { // check for sanity of parameters if (stmt_num < 0 || stmt_num >= stmt.size()) throw std::invalid_argument("invalid statement " + to_string(stmt_num)); if (level <= 0 || level > stmt[stmt_num].loop_level.size()) - throw std::invalid_argument("invalid loop level " + to_string(level)); + throw std::invalid_argument("4invalid loop level " + to_string(level)); std::set<int> result; int dim = 2 * level - 1; @@ -784,8 +792,17 @@ std::set<int> Loop::split(int stmt_num, int level, const Relation &cond) { stmt[*i].IS = part1; - if (Intersection(copy(part2), - Extend_Set(copy(this->known), n - this->known.n_set())).is_upper_bound_satisfiable()) { + int n1 = part2.n_set(); + int m = this->known.n_set(); + Relation test; + if(m > n1) + test = Intersection(copy(this->known), + Extend_Set(copy(part2), m - part2.n_set())); + else + test = Intersection(copy(part2), + Extend_Set(copy(this->known), n1 - this->known.n_set())); + + if (test.is_upper_bound_satisfiable()) { Statement new_stmt; new_stmt.code = stmt[*i].code->clone(); new_stmt.IS = part2; @@ -793,14 +810,23 @@ std::set<int> Loop::split(int stmt_num, int level, const Relation &cond) { new_stmt.ir_stmt_node = NULL; new_stmt.loop_level = stmt[*i].loop_level; + new_stmt.has_inspector = stmt[*i].has_inspector; + new_stmt.reduction = stmt[*i].reduction; + new_stmt.reductionOp = stmt[*i].reductionOp; + stmt_nesting_level_.push_back(stmt_nesting_level_[*i]); - + + if (place_after) assign_const(new_stmt.xform, dim - 1, cur_lex + 1); else assign_const(new_stmt.xform, dim - 1, cur_lex - 1); + fprintf(stderr, "loop_basic.cc L828 adding stmt %d\n", stmt.size()); stmt.push_back(new_stmt); + + uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); dep.insert(); what_stmt_num[*i] = stmt.size() - 1; if (*i == stmt_num) @@ -898,7 +924,7 @@ void Loop::skew(const std::set<int> &stmt_nums, int level, "invalid statement number " + to_string(*i)); if (level < 1 || level > stmt[*i].loop_level.size()) throw std::invalid_argument( - "invalid loop level " + to_string(level)); + "5invalid loop level " + to_string(level)); for (int j = stmt[*i].loop_level.size(); j < skew_amount.size(); j++) if (skew_amount[j] != 0) throw std::invalid_argument("invalid skewing formula"); @@ -952,76 +978,56 @@ void Loop::skew(const std::set<int> &stmt_nums, int level, int cur_dep_dim = get_dep_dim_of(*i, kk + 1); if (skew_amount[kk] > 0) { if (lb != -posInfinity - && stmt[*i].loop_level[kk].type - == LoopLevelOriginal - && dv.lbounds[cur_dep_dim] - != -posInfinity) - lb += skew_amount[kk] - * dv.lbounds[cur_dep_dim]; + && stmt[*i].loop_level[kk].type == LoopLevelOriginal + && dv.lbounds[cur_dep_dim] != -posInfinity) + lb += skew_amount[kk] * dv.lbounds[cur_dep_dim]; else { if (cur_dep_dim != -1 - && !(dv.lbounds[cur_dep_dim] - == 0 - && dv.ubounds[cur_dep_dim] - == 0)) + && !(dv.lbounds[cur_dep_dim] == 0 + && dv.ubounds[cur_dep_dim]== 0)) lb = -posInfinity; } if (ub != posInfinity - && stmt[*i].loop_level[kk].type - == LoopLevelOriginal - && dv.ubounds[cur_dep_dim] - != posInfinity) - ub += skew_amount[kk] - * dv.ubounds[cur_dep_dim]; + && stmt[*i].loop_level[kk].type == LoopLevelOriginal + && dv.ubounds[cur_dep_dim] != posInfinity) + ub += skew_amount[kk] * dv.ubounds[cur_dep_dim]; else { if (cur_dep_dim != -1 - && !(dv.lbounds[cur_dep_dim] - == 0 - && dv.ubounds[cur_dep_dim] - == 0)) + && !(dv.lbounds[cur_dep_dim] == 0 + && dv.ubounds[cur_dep_dim] == 0)) ub = posInfinity; } } else if (skew_amount[kk] < 0) { if (lb != -posInfinity - && stmt[*i].loop_level[kk].type - == LoopLevelOriginal - && dv.ubounds[cur_dep_dim] - != posInfinity) - lb += skew_amount[kk] - * dv.ubounds[cur_dep_dim]; + && stmt[*i].loop_level[kk].type == LoopLevelOriginal + && dv.ubounds[cur_dep_dim] != posInfinity) + lb += skew_amount[kk] * dv.ubounds[cur_dep_dim]; else { if (cur_dep_dim != -1 - && !(dv.lbounds[cur_dep_dim] - == 0 - && dv.ubounds[cur_dep_dim] - == 0)) + && !(dv.lbounds[cur_dep_dim] == 0 + && dv.ubounds[cur_dep_dim] == 0)) lb = -posInfinity; } if (ub != posInfinity - && stmt[*i].loop_level[kk].type - == LoopLevelOriginal - && dv.lbounds[cur_dep_dim] - != -posInfinity) - ub += skew_amount[kk] - * dv.lbounds[cur_dep_dim]; + && stmt[*i].loop_level[kk].type == LoopLevelOriginal + && dv.lbounds[cur_dep_dim] != -posInfinity) + ub += skew_amount[kk] * dv.lbounds[cur_dep_dim]; else { if (cur_dep_dim != -1 - && !(dv.lbounds[cur_dep_dim] - == 0 - && dv.ubounds[cur_dep_dim] - == 0)) + && !(dv.lbounds[cur_dep_dim] == 0 + && dv.ubounds[cur_dep_dim] == 0)) ub = posInfinity; } } } dv.lbounds[dep_dim] = lb; dv.ubounds[dep_dim] = ub; - if ((dv.isCarried(dep_dim) - && dv.hasPositive(dep_dim)) && dv.quasi) + if ((dv.isCarried(dep_dim) && dv.hasPositive(dep_dim)) + && dv.quasi) dv.quasi = false; - if ((dv.isCarried(dep_dim) - && dv.hasNegative(dep_dim)) && !dv.quasi) + if ((dv.isCarried(dep_dim) && dv.hasNegative(dep_dim)) + && !dv.quasi) throw loop_error( "loop error: Skewing is illegal, dependence violation!"); dv.lbounds[dep_dim] = lb; @@ -1085,7 +1091,7 @@ void Loop::shift(const std::set<int> &stmt_nums, int level, int shift_amount) { "invalid statement number " + to_string(*i)); if (level < 1 || level > stmt[*i].loop_level.size()) throw std::invalid_argument( - "invalid loop level " + to_string(level)); + "6invalid loop level " + to_string(level)); } // do nothing @@ -1185,16 +1191,25 @@ void Loop::fuse(const std::set<int> &stmt_nums, int level) { // check for sanity of parameters std::vector<int> ref_lex; int ref_stmt_num; + apply_xform(); for (std::set<int>::const_iterator i = stmt_nums.begin(); i != stmt_nums.end(); i++) { - if (*i < 0 || *i >= stmt.size()) + if (*i < 0 || *i >= stmt.size()) { + fprintf(stderr, "statement number %d should be in [0, %d)\n", *i, stmt.size()); throw std::invalid_argument( - "invalid statement number " + to_string(*i)); + "FUSE invalid statement number " + to_string(*i)); + } if (level <= 0 - || (level > (stmt[*i].xform.n_out() - 1) / 2 - || level > stmt[*i].loop_level.size())) + // || (level > (stmt[*i].xform.n_out() - 1) / 2 + // || level > stmt[*i].loop_level.size()) + ) { + fprintf(stderr, "FUSE level %d ", level); + fprintf(stderr, "must be greater than zero and \n"); + fprintf(stderr, "must NOT be greater than (%d - 1)/2 == %d and\n", stmt[*i].xform.n_out(), (stmt[*i].xform.n_out() - 1) / 2); + fprintf(stderr, "must NOT be greater than %d\n", stmt[*i].loop_level.size()); throw std::invalid_argument( - "invalid loop level " + to_string(level)); + "FUSE invalid loop level " + to_string(level)); + } if (ref_lex.size() == 0) { ref_lex = getLexicalOrder(*i); ref_stmt_num = *i; @@ -1258,14 +1273,66 @@ void Loop::fuse(const std::set<int> &stmt_nums, int level) { std::vector<std::set<int> > s = sort_by_same_loops(same_loop, level); - std::set<int> s1; - std::set<int> s2; - std::set<int> s4; - std::vector<std::set<int> > s3; + std::vector<bool> s2; + + for (int i = 0; i < s.size(); i++) { + s2.push_back(false); + } + for (std::set<int>::iterator kk = stmt_nums.begin(); kk != stmt_nums.end(); kk++) for (int i = 0; i < s.size(); i++) if (s[i].find(*kk) != s[i].end()) { + + s2[i] = true; + } + + try { + + //Dependence Check for Ordering Constraint + //Graph<std::set<int>, bool> dummy = construct_induced_graph_at_level(s5, + // dep, dep_dim); + + Graph<std::set<int>, bool> g = construct_induced_graph_at_level(s, dep, + dep_dim); + std::cout << g; + s = typed_fusion(g, s2); + } catch (const loop_error &e) { + + throw loop_error( + "statements cannot be fused together due to negative dependence"); + + } + + int order = 0; + for (int i = 0; i < s.size(); i++) { + for (std::set<int>::iterator it = s[i].begin(); it != s[i].end(); it++) { + assign_const(stmt[*it].xform, 2 * level - 2, order); + } + order++; + } + + + //plan for selective typed fusion + + /* + 1. sort the lex values of the statements + 2. construct induced graph on sorted statements + 3. pick a node from the graph, check if it is before/after from the candidate set for fusion + equal-> set the max fused node of this node to be the start/target node for fusion + before -> augment and continue + + 4. once target node identified and is on work queue update successors and other nodes to start node + 5. augment and continue + 6. if all candidate nodes dont end up in start node throw error + 7. Get nodes and update lexical values + + */ + + /* for (std::set<int>::iterator kk = stmt_nums.begin(); kk != stmt_nums.end(); + kk++) + for (int i = 0; i < s.size(); i++) + if (s[i].find(*kk) != s[i].end()) { s1.insert(s[i].begin(), s[i].end()); s2.insert(i); } @@ -1282,10 +1349,12 @@ void Loop::fuse(const std::set<int> &stmt_nums, int level) { s5.push_back(s4); //Dependence Check for Ordering Constraint - + //Graph<std::set<int>, bool> dummy = construct_induced_graph_at_level(s5, + // dep, dep_dim); + Graph<std::set<int>, bool> g = construct_induced_graph_at_level(s3, dep, dep_dim); - + std::cout<< g; s = typed_fusion(g); } catch (const loop_error &e) { @@ -1346,7 +1415,7 @@ void Loop::fuse(const std::set<int> &stmt_nums, int level) { } else throw loop_error("Typed Fusion Error"); - + */ } @@ -1354,7 +1423,9 @@ void Loop::fuse(const std::set<int> &stmt_nums, int level) { void Loop::distribute(const std::set<int> &stmt_nums, int level) { if (stmt_nums.size() == 0 || stmt_nums.size() == 1) return; - + fprintf(stderr, "Loop::distribute()\n"); + + // invalidate saved codegen computation delete last_compute_cgr_; last_compute_cgr_ = NULL; @@ -1369,11 +1440,12 @@ void Loop::distribute(const std::set<int> &stmt_nums, int level) { if (*i < 0 || *i >= stmt.size()) throw std::invalid_argument( "invalid statement number " + to_string(*i)); + if (level < 1 || (level > (stmt[*i].xform.n_out() - 1) / 2 || level > stmt[*i].loop_level.size())) throw std::invalid_argument( - "invalid loop level " + to_string(level)); + "8invalid loop level " + to_string(level)); if (ref_lex.size() == 0) { ref_lex = getLexicalOrder(*i); ref_stmt_num = *i; @@ -1386,6 +1458,7 @@ void Loop::distribute(const std::set<int> &stmt_nums, int level) { + to_string(level) + " subloop"); } } + // find SCC in the to-be-distributed loop int dep_dim = get_dep_dim_of(ref_stmt_num, level); std::set<int> same_loop = getStatements(ref_lex, dim - 1); @@ -1491,6 +1564,276 @@ void Loop::distribute(const std::set<int> &stmt_nums, int level) { order++; } // no need to update dependence graph + return; } + + + +std::vector<IR_ArrayRef *> FindOuterArrayRefs(IR_Code *ir, + std::vector<IR_ArrayRef *> &arr_refs) { + std::vector<IR_ArrayRef *> to_return; + for (int i = 0; i < arr_refs.size(); i++) + if (!ir->parent_is_array(arr_refs[i])) { + int j; + for (j = 0; j < to_return.size(); j++) + if (*to_return[j] == *arr_refs[i]) + break; + if (j == to_return.size()) + to_return.push_back(arr_refs[i]); + } + return to_return; +} + + + + + +std::vector<std::vector<std::string> > constructInspectorVariables(IR_Code *ir, + std::set<IR_ArrayRef *> &arr, std::vector<std::string> &index) { + + fprintf(stderr, "constructInspectorVariables()\n"); + + std::vector<std::vector<std::string> > to_return; + + for (std::set<IR_ArrayRef *>::iterator i = arr.begin(); i != arr.end(); + i++) { + + std::vector<std::string> per_index; + + CG_outputRepr *subscript = (*i)->index(0); + + if ((*i)->n_dim() > 1) + throw ir_error( + "multi-dimensional array support non-existent for flattening currently"); + + while (ir->QueryExpOperation(subscript) == IR_OP_ARRAY_VARIABLE) { + + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(subscript); + + IR_ArrayRef *ref = static_cast<IR_ArrayRef *>(ir->Repr2Ref(v[0])); + //per_index.push_back(ref->name()); + + subscript = ref->index(0); + + } + + if (ir->QueryExpOperation(subscript) == IR_OP_VARIABLE) { + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(subscript); + IR_ScalarRef *ref = static_cast<IR_ScalarRef *>(ir->Repr2Ref(v[0])); + per_index.push_back(ref->name()); + int j; + for (j = 0; j < index.size(); j++) + if (index[j] == ref->name()) + break; + + if (j == index.size()) + throw ir_error("Non index variable in array expression"); + + int k; + for (k = 0; k < to_return.size(); k++) + if (to_return[k][0] == ref->name()) + break; + if (k == to_return.size()) { + to_return.push_back(per_index); + fprintf(stderr, "adding index %s\n", ref->name().c_str()); + } + + } + + } + + return to_return; + +} + +/*std::vector<CG_outputRepr *> constructInspectorData(IR_Code *ir, std::vector<std::vector<std::string> > &indices){ + + std::vector<CG_outputRepr *> to_return; + + for(int i =0; i < indices.size(); i++) + ir->CreateVariableDeclaration(indices[i][0]); + return to_return; + } + + + CG_outputRepr* constructInspectorFunction(IR_Code* ir, std::vector<std::vector<std::string> > &indices){ + + CG_outputRepr *to_return; + + + + return to_return; + } + +*/ + +CG_outputRepr * checkAndGenerateIndirectMappings(CG_outputBuilder * ocg, + std::vector<std::vector<std::string> > &indices, + CG_outputRepr * instance, CG_outputRepr * class_def, + CG_outputRepr * count_var) { + + CG_outputRepr *to_return = NULL; + + for (int i = 0; i < indices.size(); i++) + if (indices[i].size() > 1) { + std::string index = indices[i][indices[i].size() - 1]; + CG_outputRepr *rep = ocg->CreateArrayRefExpression( + ocg->CreateDotExpression(instance, + ocg->lookup_member_data(class_def, index, instance)), + count_var); + for (int j = indices[i].size() - 2; j >= 0; j--) + rep = ocg->CreateArrayRefExpression(indices[i][j], rep); + + CG_outputRepr *lhs = ocg->CreateArrayRefExpression( + ocg->CreateDotExpression(instance, + ocg->lookup_member_data(class_def, indices[i][0], instance)), + count_var); + + to_return = ocg->StmtListAppend(to_return, + ocg->CreateAssignment(0, lhs, rep)); + + } + + return to_return; + +} + +CG_outputRepr *generatePointerAssignments(CG_outputBuilder *ocg, + std::string prefix_name, + std::vector<std::vector<std::string> > &indices, + CG_outputRepr *instance, + CG_outputRepr *class_def) { + + fprintf(stderr, "generatePointerAssignments()\n"); + CG_outputRepr *list = NULL; + + fprintf(stderr, "prefix '%s', %d indices\n", prefix_name.c_str(), indices.size()); + for (int i = 0; i < indices.size(); i++) { + + std::string s = prefix_name + "_" + indices[i][0]; + + fprintf(stderr, "s %s\n", s.c_str()); + + // create a variable definition for a pointer to int with this name + // that seems to be the only actual result of this routine ... + //chillAST_VarDecl *vd = new chillAST_VarDecl( "int", prefix_name.c_str(), "*", NULL); + //vd->print(); printf("\n"); fflush(stdout); + //vd->dump(); printf("\n"); fflush(stdout); + + CG_outputRepr *ptr_exp = ocg->CreatePointer(s); // but dropped on the floor. unused + //fprintf(stderr, "ptr_exp created\n"); + + //CG_outputRepr *rhs = ocg->CreateDotExpression(instance, + // ocg->lookup_member_data(class_def, indices[i][0], instance)); + + //CG_outputRepr *ptr_assignment = ocg->CreateAssignment(0, ptr_exp, rhs); + + //list = ocg->StmtListAppend(list, ptr_assignment); + + } + + fprintf(stderr, "generatePointerAssignments() DONE\n\n"); + return list; +} + +void Loop::normalize(int stmt_num, int loop_level) { + + if (stmt_num < 0 || stmt_num >= stmt.size()) + throw std::invalid_argument( + + "invalid statement number " + to_string(stmt_num)); + + if (loop_level <= 0) + throw std::invalid_argument( + "12invalid loop level " + to_string(loop_level)); + if (loop_level > stmt[stmt_num].loop_level.size()) + throw std::invalid_argument( + "there is no loop level " + to_string(loop_level) + + " for statement " + to_string(stmt_num)); + + apply_xform(stmt_num); + + Relation r = copy(stmt[stmt_num].IS); + + Relation bound = get_loop_bound(r, loop_level, this->known); + if (!bound.has_single_conjunct() || !bound.is_satisfiable() + || bound.is_tautology()) + throw loop_error("unable to extract loop bound for normalize"); + + // extract the loop stride + coef_t stride; + std::pair<EQ_Handle, Variable_ID> result = find_simplest_stride(bound, + bound.set_var(loop_level)); + if (result.second == NULL) + stride = 1; + else + stride = abs(result.first.get_coef(result.second)) + / gcd(abs(result.first.get_coef(result.second)), + abs(result.first.get_coef(bound.set_var(loop_level)))); + + if (stride != 1) + throw loop_error( + "normalize currently only handles unit stride, non unit stride present in loop bounds"); + + GEQ_Handle lb; + + Conjunct *c = bound.query_DNF()->single_conjunct(); + for (GEQ_Iterator gi(c->GEQs()); gi; gi++) { + int coef = (*gi).get_coef(bound.set_var(loop_level)); + if (coef > 0) + lb = *gi; + } + + //Loop bound already zero + //Nothing to do. + if (lb.is_const(bound.set_var(loop_level)) && lb.get_const() == 0) + return; + + if (lb.is_const_except_for_global(bound.set_var(loop_level))) { + + int n = stmt[stmt_num].xform.n_out(); + + Relation r(n, n); + F_And *f_root = r.add_and(); + for (int j = 1; j <= n; j++) + if (j != 2 * loop_level) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(r.input_var(j), 1); + h.update_coef(r.output_var(j), -1); + } + + stmt[stmt_num].xform = Composition(r, stmt[stmt_num].xform); + stmt[stmt_num].xform.simplify(); + + for (Constr_Vars_Iter ci(lb); ci; ci++) { + if ((*ci).var->kind() == Global_Var) { + Global_Var_ID g = (*ci).var->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = stmt[stmt_num].xform.get_local(g); + else + v = stmt[stmt_num].xform.get_local(g, + (*ci).var->function_of()); + + F_And *f_super_root = stmt[stmt_num].xform.and_with_and(); + F_Exists *f_exists = f_super_root->add_exists(); + F_And *f_root = f_exists->add_and(); + + EQ_Handle h = f_root->add_EQ(); + h.update_coef(stmt[stmt_num].xform.output_var(2 * loop_level), + 1); + h.update_coef(stmt[stmt_num].xform.input_var(loop_level), -1); + h.update_coef(v, 1); + + stmt[stmt_num].xform.simplify(); + } + + } + + } else + throw loop_error("loop bounds too complex for normalize!"); + +} + diff --git a/src/loop_datacopy.cc b/src/loop_datacopy.cc index 1ccd444..12d74fd 100644 --- a/src/loop_datacopy.cc +++ b/src/loop_datacopy.cc @@ -21,8 +21,15 @@ using namespace omega; +// +// data copy function by referring arrays by numbers. +// e.g. A[i] = A[i-1] + B[i] +// parameter array_ref_num=[0,2] means to copy data touched by A[i-1] and A[i] +// bool Loop::datacopy(const std::vector<std::pair<int, std::vector<int> > > &array_ref_nums, int level, bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type) { + //fprintf(stderr, "Loop::datacopy()\n"); + // check for sanity of parameters std::set<int> same_loop; for (int i = 0; i < array_ref_nums.size(); i++) { @@ -67,11 +74,22 @@ bool Loop::datacopy(const std::vector<std::pair<int, std::vector<int> > > &array throw std::invalid_argument("found no array references to copy"); // do the copy - return datacopy_privatized(selected_refs, level, std::vector<int>(), allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); + bool whatever = datacopy_privatized(selected_refs, level, std::vector<int>(), allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); + return whatever; } +// +// data copy function by referring arrays by name. +// e.g. A[i] = A[i-1] + B[i] +// parameter array_name=A means to copy data touched by A[i-1] and A[i] +// bool Loop::datacopy(int stmt_num, int level, const std::string &array_name, bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type) { + + fflush(stdout); + //fprintf(stderr, "Loop::datacopy2()\n"); + //fprintf(stderr, "array name %s stmt num %d\n", array_name.c_str(), stmt_num); + // check for sanity of parameters if (stmt_num < 0 || stmt_num >= stmt.size()) throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); @@ -95,16 +113,38 @@ bool Loop::datacopy(int stmt_num, int level, const std::string &array_name, if (t.size() != 0) selected_refs.push_back(std::make_pair(*i, t)); } + + //fprintf(stderr, "selected refs:\n"); + //for (int i=0; i<selected_refs.size(); i++) { + // //fprintf(stderr, "%d 0x%x ", selected_refs[i].first, selected_refs[i].second[0]); + // selected_refs[i].second[0]->Dump(); printf("\n"); fflush(stdout); + //} + if (selected_refs.size() == 0) throw std::invalid_argument("found no array references with name " + to_string(array_name) + " to copy"); + IR_ArrayRef *AR = selected_refs[0].second[0]; + //IR_roseArrayRef *RAR = (IR_roseArrayRef *)AR; + //fprintf(stderr, "before datacopy_privatized, "); + //AR->Dump(); + // do the copy - return datacopy_privatized(selected_refs, level, std::vector<int>(), allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); + //fprintf(stderr, "\nLoop::datacopy2 calling privatized\n"); + + bool whatever = datacopy_privatized(selected_refs, level, std::vector<int>(), allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); + + //AR = selected_refs[0].second[0]; + //fprintf(stderr, "after datacopy_privatized, "); + //AR->Dump(); + + return whatever; } bool Loop::datacopy_privatized(int stmt_num, int level, const std::string &array_name, const std::vector<int> &privatized_levels, bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type) { + //fprintf(stderr, "Loop::datacopy_privatized()\n"); + // check for sanity of parameters if (stmt_num < 0 || stmt_num >= stmt.size()) throw std::invalid_argument("invalid statement number " + to_string(stmt_num)); @@ -131,11 +171,14 @@ bool Loop::datacopy_privatized(int stmt_num, int level, const std::string &array throw std::invalid_argument("found no array references with name " + to_string(array_name) + " to copy"); // do the copy - return datacopy_privatized(selected_refs, level, privatized_levels, allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); + bool whatever = datacopy_privatized(selected_refs, level, privatized_levels, allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); + return whatever; } bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<int> > > &array_ref_nums, int level, const std::vector<int> &privatized_levels, bool allow_extra_read, int fastest_changing_dimension, int padding_stride, int padding_alignment, int memory_type) { + //fprintf(stderr, "Loop::datacopy_privatized2()\n"); + // check for sanity of parameters std::set<int> same_loop; for (int i = 0; i < array_ref_nums.size(); i++) { @@ -180,13 +223,28 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<int> throw std::invalid_argument("found no array references to copy"); // do the copy - return datacopy_privatized(selected_refs, level, privatized_levels, allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); + bool whatever = datacopy_privatized(selected_refs, level, privatized_levels, allow_extra_read, fastest_changing_dimension, padding_stride, padding_alignment, memory_type); + return whatever; } -bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_ArrayRef *> > > &stmt_refs, int level, + +// +// Implement low level datacopy function with lots of options. +// + +bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_ArrayRef *> > > &stmt_refs, + int level, const std::vector<int> &privatized_levels, - bool allow_extra_read, int fastest_changing_dimension, - int padding_stride, int padding_alignment, int memory_type) { + bool allow_extra_read, + int fastest_changing_dimension, + int padding_stride, + int padding_alignment, + int memory_type) { + + //fprintf(stderr, "\nLoop::datacopy_privatized3() *****\n"); + //fprintf(stderr, "privatized_levels.size() %d\n", privatized_levels.size()); + //fprintf(stderr, "level %d\n", level); + if (stmt_refs.size() == 0) return true; @@ -233,6 +291,12 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A } } } + + //fprintf(stderr, "sym %p\n", sym); + if (!sym) { + fprintf(stderr, "sym NULL, gonna die\n"); int *i=0; int j=i[0]; + } + if (!(fastest_changing_dimension >= -1 && fastest_changing_dimension < sym->n_dim())) throw std::invalid_argument("invalid fastest changing dimension for the array to be copied"); if (padding_stride < 0) @@ -255,6 +319,7 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A default: throw loop_error("unsupported array layout"); } + // OK, parameter sanity checked // invalidate saved codegen computation @@ -264,20 +329,58 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A last_compute_cg_ = NULL; // build iteration spaces for all reads and for all writes separately + //fprintf(stderr, "dp3: before apply_xform() ARRAY REFS\n"); + //for (int i = 0; i < stmt_refs.size(); i++) { + // for (int j = 0; j < stmt_refs[i].second.size(); j++) { + // IR_ArrayRef *AR = stmt_refs[i].second[j]; + // fprintf(stderr, "array ref ij %d %d ", i, j); AR->Dump(); fprintf(stderr, "\n"); + // } + //} + //for (int i=0; i<stmt.size(); i++) { + // fprintf(stderr, "stmt %d = ", i); + // stmt[i].code->dump(); + // fprintf(stderr, "\n"); + //} + apply_xform(active); + //fprintf(stderr, "dp3: back from apply_xform() ARRAY REFS\n"); + + //for (int i = 0; i < stmt_refs.size(); i++) { + // for (int j = 0; j < stmt_refs[i].second.size(); j++) { + // IR_ArrayRef *AR = stmt_refs[i].second[j]; + // fprintf(stderr, "array ref ij %d %d ", i, j); + // AR->Dump(); + // fprintf(stderr, "\n"); + // } + //} + + //for (int i=0; i<stmt.size(); i++) { + // fprintf(stderr, "stmt %d = ", i); + // stmt[i].code->dump(); + // fprintf(stderr, "\n"); + //} + bool has_write_refs = false; bool has_read_refs = false; Relation wo_copy_is = Relation::False(level-1+privatized_levels.size()+n_dim); Relation ro_copy_is = Relation::False(level-1+privatized_levels.size()+n_dim); + //fprintf(stderr, "\n\ni range: 0-%d\n", -1 + stmt_refs.size()); + int stmt_num = stmt_refs[0].first; for (int i = 0; i < stmt_refs.size(); i++) { int stmt_num = stmt_refs[i].first; + //fprintf(stderr, "j range: 0-%d\n", -1 + stmt_refs[i].second.size()); + for (int j = 0; j < stmt_refs[i].second.size(); j++) { + //fprintf(stderr, "ij %d %d\n", i, j); + Relation mapping(stmt[stmt_num].IS.n_set(), level-1+privatized_levels.size()+n_dim); for (int k = 1; k <= mapping.n_inp(); k++) mapping.name_input_var(k, stmt[stmt_num].IS.set_var(k)->name()); mapping.setup_names(); + mapping.print(); fflush(stdout); // "{[I] -> [_t1] : I = _t1 } + F_And *f_root = mapping.add_and(); for (int k = 1; k <= level-1; k++) { EQ_Handle h = f_root->add_EQ(); @@ -290,12 +393,28 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A h.update_coef(mapping.output_var(level+k), -1); } for (int k = 0; k < n_dim; k++) { + IR_ArrayRef *AR = stmt_refs[i].second[j]; + //fprintf(stderr, "array ref "); + AR->Dump(); + CG_outputRepr *repr = stmt_refs[i].second[j]->index(k); - exp2formula(ir, mapping, f_root, freevar, repr, mapping.output_var(level-1+privatized_levels.size()+k+1), 'w', IR_COND_EQ, false); + //fprintf(stderr, "k %d j %d repr ", k, j); repr->dump(); fflush(stdout); + + exp2formula(ir, + mapping, + f_root, + freevar, + repr, + mapping.output_var(level-1+privatized_levels.size()+k+1), + 'w', + IR_COND_EQ, + false, + uninterpreted_symbols[stmt_num], + uninterpreted_symbols_stringrepr[stmt_num]); repr->clear(); delete repr; } - Relation r = Range(Restrict_Domain(mapping, Intersection(copy(stmt[stmt_num].IS), Extend_Set(copy(this->known), stmt[stmt_num].IS.n_set() - this->known.n_set())))); + Relation r = omega::Range(Restrict_Domain(mapping, Intersection(copy(stmt[stmt_num].IS), Extend_Set(copy(this->known), stmt[stmt_num].IS.n_set() - this->known.n_set())))); if (stmt_refs[i].second[j]->is_write()) { has_write_refs = true; wo_copy_is = Union(wo_copy_is, r); @@ -312,6 +431,7 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A } } + //fprintf(stderr, "dp3: simplify\n"); // simplify read and write footprint iteration space { if (allow_extra_read) @@ -356,6 +476,7 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A ro_copy_is.setup_names(); } + //fprintf(stderr, "\ndp3: build merged\n"); // build merged footprint iteration space for calculating temporary array size Relation copy_is = SimpleHull(Union(copy(ro_copy_is), copy(wo_copy_is)), true, true); @@ -368,37 +489,48 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A Relation reduced_copy_is = copy(copy_is); for (int i = 0; i < n_dim; i++) { + //fprintf(stderr, "i %d/%d\n", i, n_dim); if (i != 0) reduced_copy_is = Project(reduced_copy_is, level-1+privatized_levels.size()+i, Set_Var); Relation bound = get_loop_bound(reduced_copy_is, level-1+privatized_levels.size()+i); + //fprintf(stderr, "dp3: extract stride\n"); // extract stride std::pair<EQ_Handle, Variable_ID> result = find_simplest_stride(bound, bound.set_var(level-1+privatized_levels.size()+i+1)); if (result.second != NULL) index_stride[i] = abs(result.first.get_coef(result.second))/gcd(abs(result.first.get_coef(result.second)), abs(result.first.get_coef(bound.set_var(level-1+privatized_levels.size()+i+1)))); else index_stride[i] = 1; + //fprintf(stderr, "dp3: index_stride[%d] = %d\n", i, index_stride[i]); - // check if this arary index requires loop + // check if this array index requires loop Conjunct *c = bound.query_DNF()->single_conjunct(); for (EQ_Iterator ei(c->EQs()); ei; ei++) { + //fprintf(stderr, "dp3: for\n"); if ((*ei).has_wildcards()) continue; + //fprintf(stderr, "dp3: no wildcards\n"); int coef = (*ei).get_coef(bound.set_var(level-1+privatized_levels.size()+i+1)); if (coef != 0) { + //fprintf(stderr, "coef != 0\n"); int sign = 1; if (coef < 0) { + //fprintf(stderr, "coef < 0\n"); coef = -coef; sign = -1; } CG_outputRepr *op = NULL; for (Constr_Vars_Iter ci(*ei); ci; ci++) { + //fprintf(stderr, "dp3: ci\n"); switch ((*ci).var->kind()) { case Input_Var: { - if ((*ci).var != bound.set_var(level-1+privatized_levels.size()+i+1)) + //fprintf(stderr, "dp3: Input_Var\n"); + if ((*ci).var != bound.set_var(level-1+privatized_levels.size()+i+1)) { + //fprintf(stderr, "dp3: IF sign %d\n",(*ci).coef*sign); + if ((*ci).coef*sign == 1) op = ocg->CreateMinus(op, ocg->CreateIdent((*ci).var->name())); else if ((*ci).coef*sign == -1) @@ -407,10 +539,12 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A op = ocg->CreateMinus(op, ocg->CreateTimes(ocg->CreateInt(abs((*ci).coef)), ocg->CreateIdent((*ci).var->name()))); else // (*ci).coef*sign < -1 op = ocg->CreatePlus(op, ocg->CreateTimes(ocg->CreateInt(abs((*ci).coef)), ocg->CreateIdent((*ci).var->name()))); + } break; } case Global_Var: { + //fprintf(stderr, "dp3: Global_Var\n"); Global_Var_ID g = (*ci).var->get_global_var(); if ((*ci).coef*sign == 1) op = ocg->CreateMinus(op, ocg->CreateIdent(g->base_name())); @@ -439,7 +573,8 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A if (is_index_eq[i]) continue; - // seperate lower and upper bounds + //fprintf(stderr, "dp3: separate lower and upper bounds\n"); + // separate lower and upper bounds std::vector<GEQ_Handle> lb_list, ub_list; std::set<Variable_ID> excluded_floor_vars; excluded_floor_vars.insert(bound.set_var(level-1+privatized_levels.size()+i+1)); @@ -465,19 +600,41 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A if (lb_list.size() == 0 || ub_list.size() == 0) throw loop_error("failed to calcuate array footprint size"); + //fprintf(stderr, "dp3: build lower bound representation\n"); // build lower bound representation std::vector<CG_outputRepr *> lb_repr_list; for (int j = 0; j < lb_list.size(); j++){ - if(this->known.n_set() == 0) - lb_repr_list.push_back(output_lower_bound_repr(ocg, lb_list[j], bound.set_var(level-1+privatized_levels.size()+i+1), result.first, result.second, bound, Relation::True(bound.n_set()), std::vector<std::pair<CG_outputRepr *, int> >(bound.n_set(), std::make_pair(static_cast<CG_outputRepr *>(NULL), 0)))); - else - lb_repr_list.push_back(output_lower_bound_repr(ocg, lb_list[j], bound.set_var(level-1+privatized_levels.size()+i+1), result.first, result.second, bound, this->known, std::vector<std::pair<CG_outputRepr *, int> >(bound.n_set(), std::make_pair(static_cast<CG_outputRepr *>(NULL), 0)))); + if(this->known.n_set() == 0) { + lb_repr_list.push_back(output_lower_bound_repr(ocg, + lb_list[j], + bound.set_var(level-1+privatized_levels.size()+i+1), + result.first, + result.second, + bound, + Relation::True(bound.n_set()), + std::vector<std::pair<CG_outputRepr *, int> >(bound.n_set(), std::make_pair(static_cast<CG_outputRepr *>(NULL), 0)), + uninterpreted_symbols[stmt_num])); + } + else { + lb_repr_list.push_back(output_lower_bound_repr(ocg, + lb_list[j], + bound.set_var(level-1+privatized_levels.size()+i+1), + result.first, + result.second, + bound, + this->known, + std::vector<std::pair<CG_outputRepr *, int> >(bound.n_set(), std::make_pair(static_cast<CG_outputRepr *>(NULL), 0)), + uninterpreted_symbols[stmt_num])); + } } - if (lb_repr_list.size() > 1) + if (lb_repr_list.size() > 1) { + //fprintf(stderr, "loop_datacopy.cc dp3 createInvoke( max )\n"); index_lb[i] = ocg->CreateInvoke("max", lb_repr_list); + } else if (lb_repr_list.size() == 1) index_lb[i] = lb_repr_list[0]; + //fprintf(stderr, "dp3: build temporary array size representation\n"); // build temporary array size representation { Relation cal(copy_is.n_set(), 1); @@ -545,6 +702,7 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A cal = Project(cal, j, Input_Var); cal.simplify(); + //fprintf(stderr, "dp3: pad temporary array size\n"); // pad temporary array size // TODO: for variable array size, create padding formula Conjunct *c = cal.query_DNF()->single_conjunct(); @@ -626,8 +784,9 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A } } + //fprintf(stderr, "dp3: change the temporary array index order\n"); // change the temporary array index order - for (int i = 0; i < index_sz.size(); i++) + for (int i = 0; i < index_sz.size(); i++) { if (index_sz[i].first == fastest_changing_dimension) switch (sym->layout_type()) { case IR_ARRAY_LAYOUT_ROW_MAJOR: @@ -639,36 +798,53 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A default: throw loop_error("unsupported array layout"); } - + } + + //fprintf(stderr, "dp3: declare temporary array or scalar\n"); // declare temporary array or scalar IR_Symbol *tmp_sym; if (index_sz.size() == 0) { + //fprintf(stderr, "tmp_sym is a scalar\n"); tmp_sym = ir->CreateScalarSymbol(sym, memory_type); } else { + //fprintf(stderr, "tmp_sym is an array\n"); std::vector<CG_outputRepr *> tmp_array_size(index_sz.size()); - for (int i = 0; i < index_sz.size(); i++) + for (int i = 0; i < index_sz.size(); i++) { tmp_array_size[i] = index_sz[i].second->clone(); + index_sz[i].second->dump(); // THIS PRINTF + } tmp_sym = ir->CreateArraySymbol(sym, tmp_array_size, memory_type); } + //fprintf(stderr, "dp3: create temporary array read initialization code\n"); // create temporary array read initialization code CG_outputRepr *copy_code_read; - if (has_read_refs) + if (has_read_refs) { + //fprintf(stderr, "has read refs\n"); if (index_sz.size() == 0) { - IR_ScalarRef *tmp_scalar_ref = ir->CreateScalarRef(static_cast<IR_ScalarSymbol *>(tmp_sym)); + //fprintf(stderr, "if\n"); + //fprintf(stderr, "tmp sym %s\n", tmp_sym->name().c_str()); + IR_ScalarRef *tmp_scalar_ref = ir->CreateScalarRef(static_cast<IR_ScalarSymbol *>(tmp_sym)); // create ref from symbol + // tmp_scalar_ref is incomplete + std::vector<CG_outputRepr *> rhs_index(n_dim); - for (int i = 0; i < index_lb.size(); i++) + for (int i = 0; i < index_lb.size(); i++) { + //fprintf(stderr, "i %d\n", i); if (is_index_eq[i]) rhs_index[i] = index_lb[i]->clone(); else rhs_index[i] = ir->builder()->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+i+1)->name()); + } IR_ArrayRef *copied_array_ref = ir->CreateArrayRef(sym, rhs_index); + // IR_ScalarRef tmp_scalar_ref has no actual reference yet. It only has the variable definition. copy_code_read = ir->builder()->CreateAssignment(0, tmp_scalar_ref->convert(), copied_array_ref->convert()); + //fprintf(stderr, "if ends\n"); } else { + //fprintf(stderr, "else\n"); std::vector<CG_outputRepr *> lhs_index(index_sz.size()); for (int i = 0; i < index_sz.size(); i++) { int cur_index_num = index_sz[i].first; @@ -693,7 +869,9 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A lhs_index[i] = cur_index_repr; } + //fprintf(stderr, "dp3: making tmp_array_ref\n"); IR_ArrayRef *tmp_array_ref = ir->CreateArrayRef(static_cast<IR_ArraySymbol *>(tmp_sym), lhs_index); + //fprintf(stderr, "dp3: DONE making tmp_array_ref\n"); std::vector<CG_outputRepr *> rhs_index(n_dim); for (int i = 0; i < index_lb.size(); i++) @@ -703,13 +881,22 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A rhs_index[i] = ir->builder()->CreateIdent(copy_is.set_var(level-1+privatized_levels.size()+i+1)->name()); IR_ArrayRef *copied_array_ref = ir->CreateArrayRef(sym, rhs_index); - copy_code_read = ir->builder()->CreateAssignment(0, tmp_array_ref->convert(), copied_array_ref->convert()); + //fprintf(stderr, "dp3: loop_datacopy.cc copy_code_read = CreateAssignment\n"); + //copy_code_read = ir->builder()->CreateAssignment(0, tmp_array_ref->convert(), copied_array_ref->convert()); + CG_outputRepr *lhs = tmp_array_ref->convert(); + CG_outputRepr *rhs = copied_array_ref->convert(); + copy_code_read = ir->builder()->CreateAssignment(0, lhs, rhs); //tmp_array_ref->convert(), copied_array_ref->convert()); + //fprintf(stderr, "dp3: loop_datacopy.cc copy_code_read = CreateAssignment DONE\n\n"); } + } // has read refs + //fprintf(stderr, "dp3: create temporary array write back code\n"); // create temporary array write back code CG_outputRepr *copy_code_write; - if (has_write_refs) + if (has_write_refs) { + //fprintf(stderr, "has_write_refs\n"); if (index_sz.size() == 0) { + //fprintf(stderr, "index_sz.size() == 0\n"); IR_ScalarRef *tmp_scalar_ref = ir->CreateScalarRef(static_cast<IR_ScalarSymbol *>(tmp_sym)); std::vector<CG_outputRepr *> rhs_index(n_dim); @@ -723,6 +910,8 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A copy_code_write = ir->builder()->CreateAssignment(0, copied_array_ref->convert(), tmp_scalar_ref->convert()); } else { + //fprintf(stderr, "index_sz.size() NOT = 0\n"); + std::vector<CG_outputRepr *> lhs_index(n_dim); for (int i = 0; i < index_lb.size(); i++) if (is_index_eq[i]) @@ -758,9 +947,11 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A copy_code_write = ir->builder()->CreateAssignment(0, copied_array_ref->convert(), tmp_array_ref->convert()); } + } // has write refs // now we can remove those loops for array indexes that are // dependent on others + //fprintf(stderr, "dp3: now we can remove those loops\n"); if (!(index_sz.size() == n_dim && (sym->layout_type() == IR_ARRAY_LAYOUT_ROW_MAJOR || n_dim <= 1))) { Relation mapping(level-1+privatized_levels.size()+n_dim, level-1+privatized_levels.size()+index_sz.size()); F_And *f_root = mapping.add_and(); @@ -793,8 +984,8 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A cur_index++; } - wo_copy_is = Range(Restrict_Domain(copy(mapping), wo_copy_is)); - ro_copy_is = Range(Restrict_Domain(copy(mapping), ro_copy_is)); + wo_copy_is = omega::Range(Restrict_Domain(copy(mapping), wo_copy_is)); + ro_copy_is = omega::Range(Restrict_Domain(copy(mapping), ro_copy_is)); for (int i = 1; i <= level-1+privatized_levels.size(); i++) { wo_copy_is.name_set_var(i, copy_is.set_var(i)->name()); ro_copy_is.name_set_var(i, copy_is.set_var(i)->name()); @@ -808,6 +999,8 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A } // insert read copy statement + //fprintf(stderr, "dp3: insert read copy statement\n"); + int old_num_stmt = stmt.size(); int ro_copy_stmt_num = -1; if (has_read_refs) { @@ -834,8 +1027,10 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A copy_stmt_read.IS = ro_copy_is; copy_stmt_read.xform = copy_xform; copy_stmt_read.code = copy_code_read; + //fprintf(stderr, "dp3: copy_stmt_read.code = \n"); copy_stmt_read.loop_level = std::vector<LoopLevel>(ro_copy_is.n_set()); copy_stmt_read.ir_stmt_node = NULL; + copy_stmt_read.has_inspector = false; for (int i = 0; i < level-1; i++) { copy_stmt_read.loop_level[i].type = stmt[*(active.begin())].loop_level[i].type; if (stmt[*(active.begin())].loop_level[i].type == LoopLevelTile && @@ -859,12 +1054,12 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A copy_stmt_read.loop_level[level-1+i].parallel_level = stmt[*(active.begin())].loop_level[privatized_levels[i]].parallel_level; } int left_num_dim = num_dep_dim - (get_last_dep_dim_before(*(active.begin()), level) + 1); - for (int i = 0; i < min(left_num_dim, static_cast<int>(index_sz.size())); i++) { + for (int i = 0; i < std::min(left_num_dim, static_cast<int>(index_sz.size())); i++) { copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].type = LoopLevelOriginal; copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].payload = num_dep_dim-left_num_dim+i; copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].parallel_level = 0; } - for (int i = min(left_num_dim, static_cast<int>(index_sz.size())); i < index_sz.size(); i++) { + for (int i = std::min(left_num_dim, static_cast<int>(index_sz.size())); i < index_sz.size(); i++) { copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].type = LoopLevelUnknown; copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].payload = -1; copy_stmt_read.loop_level[level-1+privatized_levels.size()+i].parallel_level = 0; @@ -872,11 +1067,17 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A shiftLexicalOrder(lex, dim-1, 1); + + fprintf(stderr, "loop_datacopy.cc L1071 adding stmt %d\n", stmt.size()); stmt.push_back(copy_stmt_read); + + uninterpreted_symbols.push_back(uninterpreted_symbols[*(active.begin())]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[*(active.begin())]); ro_copy_stmt_num = stmt.size() - 1; dep.insert(); } + //fprintf(stderr, "dp3: insert write copy statement\n"); // insert write copy statement int wo_copy_stmt_num = -1; if (has_write_refs) { @@ -905,6 +1106,7 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A copy_stmt_write.code = copy_code_write; copy_stmt_write.loop_level = std::vector<LoopLevel>(wo_copy_is.n_set()); copy_stmt_write.ir_stmt_node = NULL; + copy_stmt_write.has_inspector = false; for (int i = 0; i < level-1; i++) { copy_stmt_write.loop_level[i].type = stmt[*(active.begin())].loop_level[i].type; @@ -929,28 +1131,35 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A copy_stmt_write.loop_level[level-1+i].parallel_level = stmt[*(active.begin())].loop_level[privatized_levels[i]].parallel_level; } int left_num_dim = num_dep_dim - (get_last_dep_dim_before(*(active.begin()), level) + 1); - for (int i = 0; i < min(left_num_dim, static_cast<int>(index_sz.size())); i++) { + for (int i = 0; i < std::min(left_num_dim, static_cast<int>(index_sz.size())); i++) { copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].type = LoopLevelOriginal; copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].payload = num_dep_dim-left_num_dim+i; copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].parallel_level = 0; } - for (int i = min(left_num_dim, static_cast<int>(index_sz.size())); i < index_sz.size(); i++) { + for (int i = std::min(left_num_dim, static_cast<int>(index_sz.size())); i < index_sz.size(); i++) { copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].type = LoopLevelUnknown; copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].payload = -1; copy_stmt_write.loop_level[level-1+privatized_levels.size()+i].parallel_level = 0; } lex[dim-1]++; shiftLexicalOrder(lex, dim-1, -2); + + fprintf(stderr, "loop_datacopy.cc L1147 adding stmt %d\n", stmt.size()); stmt.push_back(copy_stmt_write); + + uninterpreted_symbols.push_back(uninterpreted_symbols[*(active.begin())]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[*(active.begin())]); wo_copy_stmt_num = stmt.size() - 1; dep.insert(); } + //fprintf(stderr, "replace original array accesses with temporary array accesses\n"); // replace original array accesses with temporary array accesses for (int i =0; i < stmt_refs.size(); i++) for (int j = 0; j < stmt_refs[i].second.size(); j++) { if (index_sz.size() == 0) { IR_ScalarRef *tmp_scalar_ref = ir->CreateScalarRef(static_cast<IR_ScalarSymbol *>(tmp_sym)); + //fprintf(stderr, "dp3: loop_datacopy.cc calling ReplaceExpression i%d j%d\n", i, j); ir->ReplaceExpression(stmt_refs[i].second[j], tmp_scalar_ref->convert()); } else { @@ -980,11 +1189,14 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A } IR_ArrayRef *tmp_array_ref = ir->CreateArrayRef(static_cast<IR_ArraySymbol *>(tmp_sym), index_repr); + //fprintf(stderr, "loop_datacopy.cc ir->ReplaceExpression( ... )\n"); ir->ReplaceExpression(stmt_refs[i].second[j], tmp_array_ref->convert()); } } // update dependence graph + //fprintf(stderr, "update dependence graph\n"); + int dep_dim = get_last_dep_dim_before(*(active.begin()), level) + 1; if (ro_copy_stmt_num != -1) { for (int i = 0; i < old_num_stmt; i++) { @@ -1029,6 +1241,8 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A } // insert dependences from copy statement loop to copied statements + //fprintf(stderr, "insert dependences from copy statement loop to copied statements\n"); + DependenceVector dv; dv.type = DEP_W2R; dv.sym = tmp_sym->clone(); @@ -1085,6 +1299,8 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A } // insert dependences from copied statements to write statements + //fprintf(stderr, "dp3: insert dependences from copied statements to write statements\n"); + DependenceVector dv; dv.type = DEP_W2R; dv.sym = tmp_sym->clone(); @@ -1133,6 +1349,7 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A } } + //fprintf(stderr, "Loop::datacopy_privatized3() cleanup\n"); // cleanup delete sym; delete tmp_sym; @@ -1147,3 +1364,6 @@ bool Loop::datacopy_privatized(const std::vector<std::pair<int, std::vector<IR_A return true; } + + + diff --git a/src/loop_unroll.cc b/src/loop_unroll.cc index 911d900..86ffd84 100644 --- a/src/loop_unroll.cc +++ b/src/loop_unroll.cc @@ -20,6 +20,7 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, std::vector<std::vector<std::string> > idxNames, int cleanup_split_level) { // check for sanity of parameters + // check for sanity of parameters if (unroll_amount < 0) throw std::invalid_argument( "invalid unroll amount " + to_string(unroll_amount)); @@ -70,6 +71,16 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, } dim2 = stmt[*i].loop_level[dim2].payload; + /*if (dv.isCarried(dim2) + && (dv.hasNegative(dim2) && !dv.quasi)) + throw loop_error( + "loop error: Unrolling is illegal, dependence violation!"); + + if (dv.isCarried(dim2) + && (dv.hasPositive(dim2) && dv.quasi)) + throw loop_error( + "loop error: Unrolling is illegal, dependence violation!"); + */ bool safe = false; if (dv.isCarried(dim2) && dv.hasPositive(dim2)) { @@ -78,11 +89,20 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, "loop error: a quasi dependence with a positive carried distance"); if (!dv.quasi) { if (dv.lbounds[dim2] != posInfinity) { + //if (dv.lbounds[dim2] != negInfinity) if (dv.lbounds[dim2] > unroll_amount) safe = true; } else safe = true; - } + }/* else { + if (dv.ubounds[dim2] != negInfinity) { + if (dv.ubounds[dim2] != posInfinity) + if ((-(dv.ubounds[dim2])) > unroll_amount) + safe = true; + } else + safe = true; + }*/ + if (!safe) { for (int l = level + 1; l <= (n - 1) / 2; l++) { int dim3 = l - 1; @@ -131,7 +151,7 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, h.update_coef(mapping.output_var(j), -1); } hull = Intersection(hull, - Range(Restrict_Domain(mapping, copy(stmt[*i].IS)))); + omega::Range(Restrict_Domain(mapping, copy(stmt[*i].IS)))); hull.simplify(2, 4); } @@ -288,7 +308,8 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, overflow_table[i][j][NULL] = int_mod_hat( overflow_table[i][j][NULL], unroll_amount); - // Since we don't have MODULO instruction in SUIF yet (only MOD), make all coef positive in the final formula + // Since we don't have MODULO instruction in SUIF yet (only MOD), + // make all coef positive in the final formula for (std::map<Variable_ID, int>::iterator k = overflow_table[i][j].begin(); k != overflow_table[i][j].end(); k++) @@ -437,14 +458,16 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, std::vector<CG_outputRepr *> lb_repr_list, ub_repr_list; for (int i = 0; i < lb_list.size(); i++) { lb_repr_list.push_back( - output_lower_bound_repr(ocg, lb_list[i], + output_lower_bound_repr(ocg, + lb_list[i], bound.set_var(dim + 1), result.first, result.second, bound, Relation::True(bound.n_set()), std::vector<std::pair<CG_outputRepr *, int> >( bound.n_set(), std::make_pair( static_cast<CG_outputRepr *>(NULL), - 0)))); + 0)), + uninterpreted_symbols[stmt_num])); GEQ_Handle h = cond_lower.and_with_GEQ(lb_list[i]); } for (int i = 0; i < ub_list.size(); i++) { @@ -455,21 +478,28 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, bound.n_set(), std::make_pair( static_cast<CG_outputRepr *>(NULL), - 0)))); + 0)), + uninterpreted_symbols[stmt_num])); GEQ_Handle h = cond_upper.and_with_GEQ(ub_list[i]); h.update_coef(cond_upper.get_local(over_free_var), -stride); } - CG_outputRepr *lbRepr, *ubRepr; - if (lb_repr_list.size() > 1) + CG_outputRepr *lbRepr, *ubRepr; + if (lb_repr_list.size() > 1) { + //fprintf(stderr, "loop_unroll.cc createInvoke( max )\n"); lbRepr = ocg->CreateInvoke("max", lb_repr_list); - else if (lb_repr_list.size() == 1) + } + else if (lb_repr_list.size() == 1) { lbRepr = lb_repr_list[0]; + } - if (ub_repr_list.size() > 1) + if (ub_repr_list.size() > 1) { + //fprintf(stderr, "loop_unroll.cc createInvoke( min )\n"); ubRepr = ocg->CreateInvoke("min", ub_repr_list); - else if (ub_repr_list.size() == 1) + } + else if (ub_repr_list.size() == 1) { ubRepr = ub_repr_list[0]; + } // create overflow assignment CG_outputRepr *rhs = ocg->CreatePlus(ocg->CreateMinus(ubRepr, lbRepr), @@ -503,7 +533,7 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, h.update_coef(mapping.output_var(i), 1); h.update_coef(mapping.input_var(i), -1); } - Relation overflow_IS = Range(Restrict_Domain(mapping, copy(hull))); + Relation overflow_IS = omega::Range(Restrict_Domain(mapping, copy(hull))); for (int i = 1; i < cleanup_split_level; i++) overflow_IS.name_set_var(i, hull.set_var(i)->name()); overflow_IS.setup_names(); @@ -548,7 +578,11 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, stmt[stmt_num].loop_level[i].parallel_level; } + fprintf(stderr, "loop_unroll.cc L581 adding stmt %d\n", stmt.size()); stmt.push_back(overflow_stmt); + + uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); dep.insert(); overflow_stmt_num = stmt.size() - 1; overflow[overflow_stmt_num] = over_var_list; @@ -567,8 +601,7 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, dv.type = DEP_W2W; { IR_ScalarSymbol *overflow_sym = NULL; - std::vector<IR_ScalarRef *> scalars = ir->FindScalarRef( - overflow_code); + std::vector<IR_ScalarRef *> scalars = ir->FindScalarRef(overflow_code); for (int i = scalars.size() - 1; i >= 0; i--) if (scalars[i]->is_write()) { overflow_sym = scalars[i]->symbol(); @@ -703,7 +736,12 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, new_stmt.loop_level = stmt[*i].loop_level; new_stmt.ir_stmt_node = NULL; + + fprintf(stderr, "loop_unroll.cc L740 adding stmt %d\n", stmt.size()); stmt.push_back(new_stmt); + + uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); dep.insert(); what_stmt_num[*i].push_back(stmt.size() - 1); } @@ -990,33 +1028,70 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, Statement new_stmt; new_stmt.code = NULL; - for (int j = 1; j < unroll_amount; j++) + for (int j = 1; j < unroll_amount; j++) { for (int i = 0; i < stmt_order.size(); i++) { std::vector<std::string> loop_vars; std::vector<CG_outputRepr *> subs; + + //fprintf(stderr, "loop_unroll.cc, will replace '%s with '%s+%d' ??\n", + // stmt[stmt_order[i].second].IS.set_var(level)->name().c_str(), + // stmt[stmt_order[i].second].IS.set_var(level)->name().c_str(), j * stride); + loop_vars.push_back( stmt[stmt_order[i].second].IS.set_var(level)->name()); subs.push_back( - ocg->CreatePlus( - ocg->CreateIdent( - stmt[stmt_order[i].second].IS.set_var( - level)->name()), - ocg->CreateInt(j * stride))); + ocg->CreatePlus(ocg->CreateIdent(stmt[stmt_order[i].second].IS.set_var(level)->name()), + ocg->CreateInt(j * stride))); // BUG HERE + //fprintf(stderr, "loop_unroll.cc subs now has %d parts\n", subs.size()); + //for (int k=0; k< subs.size(); k++) //fprintf(stderr, "subs[%d] = 0x%x\n", k, subs[k]); + + //fprintf(stderr, "ij %d %d ", i, j); + //fprintf(stderr, "old src was =\n"); + //stmt[stmt_order[i].second].code->dump(); fflush(stdout); //fprintf(stderr, "\n"); + + + CG_outputRepr *code = ocg->CreateSubstitutedStmt(0, - stmt[stmt_order[i].second].code->clone(), loop_vars, + stmt[stmt_order[i].second].code->clone(), + loop_vars, subs); + + //fprintf(stderr, "old src is =\n"); + //stmt[stmt_order[i].second].code->dump(); fflush(stdout); //fprintf(stderr, "\n"); + + //fprintf(stderr, "substituted copy is =\n"); + //code->dump(); //fprintf(stderr, "\n\n"); + + new_stmt.code = ocg->StmtListAppend(new_stmt.code, code); + //fprintf(stderr, "appended code =\n"); + //new_stmt.code->dump(); + } + } + + + //fprintf(stderr, "new_stmt.IS = \n"); new_stmt.IS = copy(stmt[stmt_num].IS); new_stmt.xform = copy(stmt[stmt_num].xform); assign_const(new_stmt.xform, 2 * max_level, stmt_order[stmt_order.size() - 1].first + 1); new_stmt.loop_level = stmt[stmt_num].loop_level; new_stmt.ir_stmt_node = NULL; + + new_stmt.has_inspector = false; // ?? or from copied stmt? + if (stmt[stmt_num].has_inspector) fprintf(stderr, "OLD STMT HAS INSPECTOR\n"); + else fprintf(stderr, "OLD STMT DOES NOT HAVE INSPECTOR\n"); + + fprintf(stderr, "loop_unroll.cc L1083 adding stmt %d\n", stmt.size()); stmt.push_back(new_stmt); + + uninterpreted_symbols.push_back(uninterpreted_symbols[stmt_num]); + uninterpreted_symbols_stringrepr.push_back(uninterpreted_symbols_stringrepr[stmt_num]); dep.insert(); + //fprintf(stderr, "update dependence graph\n"); // update dependence graph if (stmt[stmt_num].loop_level[level - 1].type == LoopLevelOriginal) { int dep_dim = stmt[stmt_num].loop_level[level - 1].payload; @@ -1140,6 +1215,7 @@ std::set<int> Loop::unroll(int stmt_num, int level, int unroll_amount, } } + //fprintf(stderr, " loop_unroll.cc returning new_stmts\n"); return new_stmts; } diff --git a/src/omegatools.cc b/src/omegatools.cc index 3aac404..0322182 100644 --- a/src/omegatools.cc +++ b/src/omegatools.cc @@ -14,10 +14,15 @@ *****************************************************************************/ #include <code_gen/codegen.h> + #include "omegatools.hh" #include "ir_code.hh" #include "chill_error.hh" +#include "chill_ast.hh" +#include "code_gen/CG_chillRepr.h" +#include <code_gen/CG_utils.h> + using namespace omega; namespace { @@ -41,471 +46,855 @@ std::string tmp_e() { return std::string("e")+to_string(counter++); } -void exp2formula(IR_Code *ir, Relation &r, F_And *f_root, std::vector<Free_Var_Decl*> &freevars, - CG_outputRepr *repr, Variable_ID lhs, char side, IR_CONDITION_TYPE rel, bool destroy) { + + +//----------------------------------------------------------------------------- +// Convert expression tree to omega relation. "destroy" means shallow +// deallocation of "repr", not freeing the actual code inside. +// ----------------------------------------------------------------------------- +void exp2formula(IR_Code *ir, + Relation &r, + F_And *f_root, + std::vector<Free_Var_Decl*> &freevars, + CG_outputRepr *repr, + Variable_ID lhs, + char side, + IR_CONDITION_TYPE rel, + bool destroy, + std::map<std::string, std::vector<omega::CG_outputRepr *> > &uninterpreted_symbols, + std::map<std::string, std::vector<omega::CG_outputRepr *> > &uninterpreted_symbols_stringrepr + ) { - switch (ir->QueryExpOperation(repr)) { - case IR_OP_CONSTANT: - { - std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); - IR_ConstantRef *ref = static_cast<IR_ConstantRef *>(ir->Repr2Ref(v[0])); - if (!ref->is_integer()) - throw ir_exp_error("non-integer constant coefficient"); + fprintf(stderr, "\n*** exp2formula()\n"); + //repr->dump(); /* printf("\n"); */fflush(stdout); + fprintf(stderr, "repr "); r.print(); printf("\n"); fflush(stdout); + + + IR_OPERATION_TYPE optype = ir->QueryExpOperation(repr); + + switch (optype) { - coef_t c = ref->integer(); - if (rel == IR_COND_GE || rel == IR_COND_GT) { - GEQ_Handle h = f_root->add_GEQ(); - h.update_coef(lhs, 1); - if (rel == IR_COND_GE) + + + + case IR_OP_CONSTANT: + { + fprintf(stderr, "IR_OP_CONSTANT\n"); + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + IR_ConstantRef *ref = static_cast<IR_ConstantRef *>(ir->Repr2Ref(v[0])); + if (!ref->is_integer()) + throw ir_exp_error("non-integer constant coefficient"); + + coef_t c = ref->integer(); + if (rel == IR_COND_GE || rel == IR_COND_GT) { + GEQ_Handle h = f_root->add_GEQ(); + h.update_coef(lhs, 1); + if (rel == IR_COND_GE) + h.update_const(-c); + else + h.update_const(-c-1); + } + else if (rel == IR_COND_LE || rel == IR_COND_LT) { + GEQ_Handle h = f_root->add_GEQ(); + h.update_coef(lhs, -1); + if (rel == IR_COND_LE) + h.update_const(c); + else + h.update_const(c-1); + } + else if (rel == IR_COND_EQ) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(lhs, 1); h.update_const(-c); + } else - h.update_const(-c-1); - } - else if (rel == IR_COND_LE || rel == IR_COND_LT) { - GEQ_Handle h = f_root->add_GEQ(); - h.update_coef(lhs, -1); - if (rel == IR_COND_LE) - h.update_const(c); - else - h.update_const(c-1); - } - else if (rel == IR_COND_EQ) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(lhs, 1); - h.update_const(-c); + throw std::invalid_argument("unsupported condition type"); + + delete v[0]; + delete ref; + if (destroy) + delete repr; + + break; } - else - throw std::invalid_argument("unsupported condition type"); - delete v[0]; - delete ref; - if (destroy) - delete repr; - break; - } case IR_OP_VARIABLE: - { - std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); - IR_ScalarRef *ref = static_cast<IR_ScalarRef *>(ir->Repr2Ref(v[0])); - - std::string s = ref->name(); - Variable_ID e = find_index(r, s, side); - - if (e == NULL) { // must be free variable - Free_Var_Decl *t = NULL; - for (unsigned i = 0; i < freevars.size(); i++) { - std::string ss = freevars[i]->base_name(); - if (s == ss) { - t = freevars[i]; - break; + { + fprintf(stderr, "IR_OP_VARIABLE\n"); + //fprintf(stderr, "repr "); repr->dump(); fflush(stdout); + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + //fprintf(stderr, "v "); v[0]->dump(); fflush(stdout); + IR_ScalarRef *ref = static_cast<IR_ScalarRef *>(ir->Repr2Ref(v[0])); + + //fprintf(stderr, "omegatools.cc calling ref->name()\n"); + std::string s = ref->name(); + Variable_ID e = find_index(r, s, side); + //fprintf(stderr, "s %s\n", s.c_str()); + + + if (e == NULL) { // must be free variable + Free_Var_Decl *t = NULL; + for (unsigned i = 0; i < freevars.size(); i++) { + std::string ss = freevars[i]->base_name(); + if (s == ss) { + t = freevars[i]; + break; + } + } + + if (t == NULL) { + t = new Free_Var_Decl(s); + freevars.insert(freevars.end(), t); } + + e = r.get_local(t); } - if (t == NULL) { - t = new Free_Var_Decl(s); - freevars.insert(freevars.end(), t); + if (rel == IR_COND_GE || rel == IR_COND_GT) { + GEQ_Handle h = f_root->add_GEQ(); + h.update_coef(lhs, 1); + h.update_coef(e, -1); + if (rel == IR_COND_GT) + h.update_const(-1); + } + else if (rel == IR_COND_LE || rel == IR_COND_LT) { + GEQ_Handle h = f_root->add_GEQ(); + h.update_coef(lhs, -1); + h.update_coef(e, 1); + if (rel == IR_COND_LT) + h.update_const(-1); } + else if (rel == IR_COND_EQ) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(lhs, 1); + h.update_coef(e, -1); + } + else + throw std::invalid_argument("unsupported condition type"); - e = r.get_local(t); - } - - if (rel == IR_COND_GE || rel == IR_COND_GT) { - GEQ_Handle h = f_root->add_GEQ(); - h.update_coef(lhs, 1); - h.update_coef(e, -1); - if (rel == IR_COND_GT) - h.update_const(-1); - } - else if (rel == IR_COND_LE || rel == IR_COND_LT) { - GEQ_Handle h = f_root->add_GEQ(); - h.update_coef(lhs, -1); - h.update_coef(e, 1); - if (rel == IR_COND_LT) - h.update_const(-1); + // delete v[0]; + delete ref; + if (destroy) + delete repr; + break; } - else if (rel == IR_COND_EQ) { - EQ_Handle h = f_root->add_EQ(); - h.update_coef(lhs, 1); - h.update_coef(e, -1); + + case IR_OP_ASSIGNMENT: + { + fprintf(stderr, "IR_OP_ASSIGNMENT\n"); + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + exp2formula(ir, r, f_root, freevars, v[0], lhs, side, rel, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + if (destroy) + delete repr; + break; } - else - throw std::invalid_argument("unsupported condition type"); - // delete v[0]; - delete ref; - if (destroy) - delete repr; - break; - } - case IR_OP_ASSIGNMENT: - { - std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); - exp2formula(ir, r, f_root, freevars, v[0], lhs, side, rel, true); - if (destroy) - delete repr; - break; - } case IR_OP_PLUS: - { - F_Exists *f_exists = f_root->add_exists(); - Variable_ID e1 = f_exists->declare(tmp_e()); - Variable_ID e2 = f_exists->declare(tmp_e()); - F_And *f_and = f_exists->add_and(); - - if (rel == IR_COND_GE || rel == IR_COND_GT) { - GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, 1); - h.update_coef(e1, -1); - h.update_coef(e2, -1); - if (rel == IR_COND_GT) - h.update_const(-1); - } - else if (rel == IR_COND_LE || rel == IR_COND_LT) { - GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, -1); - h.update_coef(e1, 1); - h.update_coef(e2, 1); - if (rel == IR_COND_LT) - h.update_const(-1); - } - else if (rel == IR_COND_EQ) { - EQ_Handle h = f_and->add_EQ(); - h.update_coef(lhs, 1); - h.update_coef(e1, -1); - h.update_coef(e2, -1); + { + fprintf(stderr, "IR_OP_PLUS\n"); + F_Exists *f_exists = f_root->add_exists(); + Variable_ID e1 = f_exists->declare(tmp_e()); + Variable_ID e2 = f_exists->declare(tmp_e()); + F_And *f_and = f_exists->add_and(); + + if (rel == IR_COND_GE || rel == IR_COND_GT) { + GEQ_Handle h = f_and->add_GEQ(); + h.update_coef(lhs, 1); + h.update_coef(e1, -1); + h.update_coef(e2, -1); + if (rel == IR_COND_GT) + h.update_const(-1); + } + else if (rel == IR_COND_LE || rel == IR_COND_LT) { + GEQ_Handle h = f_and->add_GEQ(); + h.update_coef(lhs, -1); + h.update_coef(e1, 1); + h.update_coef(e2, 1); + if (rel == IR_COND_LT) + h.update_const(-1); + } + else if (rel == IR_COND_EQ) { + EQ_Handle h = f_and->add_EQ(); + h.update_coef(lhs, 1); + h.update_coef(e1, -1); + h.update_coef(e2, -1); + } + else + throw std::invalid_argument("unsupported condition type"); + + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + exp2formula(ir, r, f_and, freevars, v[0], e1, side, IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + exp2formula(ir, r, f_and, freevars, v[1], e2, side, IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + if (destroy) + delete repr; + break; } - else - throw std::invalid_argument("unsupported condition type"); - - std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); - exp2formula(ir, r, f_and, freevars, v[0], e1, side, IR_COND_EQ, true); - exp2formula(ir, r, f_and, freevars, v[1], e2, side, IR_COND_EQ, true); - if (destroy) - delete repr; - break; - } case IR_OP_MINUS: - { - F_Exists *f_exists = f_root->add_exists(); - Variable_ID e1 = f_exists->declare(tmp_e()); - Variable_ID e2 = f_exists->declare(tmp_e()); - F_And *f_and = f_exists->add_and(); - - if (rel == IR_COND_GE || rel == IR_COND_GT) { - GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, 1); - h.update_coef(e1, -1); - h.update_coef(e2, 1); - if (rel == IR_COND_GT) - h.update_const(-1); - } - else if (rel == IR_COND_LE || rel == IR_COND_LT) { - GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, -1); - h.update_coef(e1, 1); - h.update_coef(e2, -1); - if (rel == IR_COND_LT) - h.update_const(-1); - } - else if (rel == IR_COND_EQ) { - EQ_Handle h = f_and->add_EQ(); - h.update_coef(lhs, 1); - h.update_coef(e1, -1); - h.update_coef(e2, 1); + { + fprintf(stderr, "IR_OP_MINUS\n"); + F_Exists *f_exists = f_root->add_exists(); + Variable_ID e1 = f_exists->declare(tmp_e()); + Variable_ID e2 = f_exists->declare(tmp_e()); + F_And *f_and = f_exists->add_and(); + + if (rel == IR_COND_GE || rel == IR_COND_GT) { + GEQ_Handle h = f_and->add_GEQ(); + h.update_coef(lhs, 1); + h.update_coef(e1, -1); + h.update_coef(e2, 1); + if (rel == IR_COND_GT) + h.update_const(-1); + } + else if (rel == IR_COND_LE || rel == IR_COND_LT) { + GEQ_Handle h = f_and->add_GEQ(); + h.update_coef(lhs, -1); + h.update_coef(e1, 1); + h.update_coef(e2, -1); + if (rel == IR_COND_LT) + h.update_const(-1); + } + else if (rel == IR_COND_EQ) { + EQ_Handle h = f_and->add_EQ(); + h.update_coef(lhs, 1); + h.update_coef(e1, -1); + h.update_coef(e2, 1); + } + else + throw std::invalid_argument("unsupported condition type"); + + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + fprintf(stderr, "IR_OP_MINUS v has %d parts\n", (int)v.size()); + fprintf(stderr, "IR_OP_MINUS recursing 1\n"); + exp2formula(ir, r, f_and, freevars, v[0], e1, side, IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + + if (v.size() > 1) { + fprintf(stderr, "IR_OP_MINUS recursing 2\n"); // dies here because it's unary minus? + exp2formula(ir, r, f_and, freevars, v[1], e2, side, IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + } + + + if (destroy) + delete repr; + break; } - else - throw std::invalid_argument("unsupported condition type"); - - std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); - exp2formula(ir, r, f_and, freevars, v[0], e1, side, IR_COND_EQ, true); - exp2formula(ir, r, f_and, freevars, v[1], e2, side, IR_COND_EQ, true); - if (destroy) - delete repr; - break; - } + + case IR_OP_MULTIPLY: - { - std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); - - coef_t coef; - CG_outputRepr *term; - if (ir->QueryExpOperation(v[0]) == IR_OP_CONSTANT) { - IR_ConstantRef *ref = static_cast<IR_ConstantRef *>(ir->Repr2Ref(v[0])); - coef = ref->integer(); - delete v[0]; - delete ref; - term = v[1]; + { + fprintf(stderr, "IR_OP_MULTIPLY\n"); + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + + coef_t coef; + CG_outputRepr *term; + if (ir->QueryExpOperation(v[0]) == IR_OP_CONSTANT) { + IR_ConstantRef *ref = static_cast<IR_ConstantRef *>(ir->Repr2Ref(v[0])); + coef = ref->integer(); + delete v[0]; + delete ref; + term = v[1]; + } + else if (ir->QueryExpOperation(v[1]) == IR_OP_CONSTANT) { + IR_ConstantRef *ref = static_cast<IR_ConstantRef *>(ir->Repr2Ref(v[1])); + coef = ref->integer(); + delete v[1]; + delete ref; + term = v[0]; + } + else + throw ir_exp_error("not presburger expression"); + + F_Exists *f_exists = f_root->add_exists(); + Variable_ID e = f_exists->declare(tmp_e()); + F_And *f_and = f_exists->add_and(); + + if (rel == IR_COND_GE || rel == IR_COND_GT) { + GEQ_Handle h = f_and->add_GEQ(); + h.update_coef(lhs, 1); + h.update_coef(e, -coef); + if (rel == IR_COND_GT) + h.update_const(-1); + } + else if (rel == IR_COND_LE || rel == IR_COND_LT) { + GEQ_Handle h = f_and->add_GEQ(); + h.update_coef(lhs, -1); + h.update_coef(e, coef); + if (rel == IR_COND_LT) + h.update_const(-1); + } + else if (rel == IR_COND_EQ) { + EQ_Handle h = f_and->add_EQ(); + h.update_coef(lhs, 1); + h.update_coef(e, -coef); + } + else + throw std::invalid_argument("unsupported condition type"); + + exp2formula(ir, r, f_and, freevars, term, e, side, IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + if (destroy) + delete repr; + break; } - else if (ir->QueryExpOperation(v[1]) == IR_OP_CONSTANT) { + + case IR_OP_DIVIDE: + { + fprintf(stderr, "IR_OP_DIVIDE\n"); + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + + assert(ir->QueryExpOperation(v[1]) == IR_OP_CONSTANT); IR_ConstantRef *ref = static_cast<IR_ConstantRef *>(ir->Repr2Ref(v[1])); - coef = ref->integer(); + coef_t coef = ref->integer(); delete v[1]; delete ref; - term = v[0]; - } - else - throw ir_exp_error("not presburger expression"); - - F_Exists *f_exists = f_root->add_exists(); - Variable_ID e = f_exists->declare(tmp_e()); - F_And *f_and = f_exists->add_and(); - - if (rel == IR_COND_GE || rel == IR_COND_GT) { - GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, 1); - h.update_coef(e, -coef); - if (rel == IR_COND_GT) - h.update_const(-1); - } - else if (rel == IR_COND_LE || rel == IR_COND_LT) { - GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, -1); - h.update_coef(e, coef); - if (rel == IR_COND_LT) - h.update_const(-1); - } - else if (rel == IR_COND_EQ) { - EQ_Handle h = f_and->add_EQ(); - h.update_coef(lhs, 1); - h.update_coef(e, -coef); - } - else - throw std::invalid_argument("unsupported condition type"); - - exp2formula(ir, r, f_and, freevars, term, e, side, IR_COND_EQ, true); - if (destroy) - delete repr; - break; - } - case IR_OP_DIVIDE: - { - std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); - - assert(ir->QueryExpOperation(v[1]) == IR_OP_CONSTANT); - IR_ConstantRef *ref = static_cast<IR_ConstantRef *>(ir->Repr2Ref(v[1])); - coef_t coef = ref->integer(); - delete v[1]; - delete ref; - - F_Exists *f_exists = f_root->add_exists(); - Variable_ID e = f_exists->declare(tmp_e()); - F_And *f_and = f_exists->add_and(); - - if (rel == IR_COND_GE || rel == IR_COND_GT) { - GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, coef); - h.update_coef(e, -1); - if (rel == IR_COND_GT) - h.update_const(-1); - } - else if (rel == IR_COND_LE || rel == IR_COND_LT) { - GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, -coef); - h.update_coef(e, 1); - if (rel == IR_COND_LT) - h.update_const(-1); - } - else if (rel == IR_COND_EQ) { - EQ_Handle h = f_and->add_EQ(); - h.update_coef(lhs, coef); - h.update_coef(e, -1); - } - else - throw std::invalid_argument("unsupported condition type"); - - exp2formula(ir, r, f_and, freevars, v[0], e, side, IR_COND_EQ, true); - if (destroy) - delete repr; - break; - } - case IR_OP_POSITIVE: - { - std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); - - exp2formula(ir, r, f_root, freevars, v[0], lhs, side, rel, true); - if (destroy) - delete repr; - break; - } - case IR_OP_NEGATIVE: - { - std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); - - F_Exists *f_exists = f_root->add_exists(); - Variable_ID e = f_exists->declare(tmp_e()); - F_And *f_and = f_exists->add_and(); - - if (rel == IR_COND_GE || rel == IR_COND_GT) { - GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, 1); - h.update_coef(e, 1); - if (rel == IR_COND_GT) - h.update_const(-1); - } - else if (rel == IR_COND_LE || rel == IR_COND_LT) { - GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, -1); - h.update_coef(e, -1); - if (rel == IR_COND_LT) - h.update_const(-1); - } - else if (rel == IR_COND_EQ) { - EQ_Handle h = f_and->add_EQ(); - h.update_coef(lhs, 1); - h.update_coef(e, 1); - } - else - throw std::invalid_argument("unsupported condition type"); - - exp2formula(ir, r, f_and, freevars, v[0], e, side, IR_COND_EQ, true); - if (destroy) - delete repr; - break; - } - case IR_OP_MIN: - { - std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); - - F_Exists *f_exists = f_root->add_exists(); - - if (rel == IR_COND_GE || rel == IR_COND_GT) { - F_Or *f_or = f_exists->add_and()->add_or(); - for (int i = 0; i < v.size(); i++) { - Variable_ID e = f_exists->declare(tmp_e()); - F_And *f_and = f_or->add_and(); + + F_Exists *f_exists = f_root->add_exists(); + Variable_ID e = f_exists->declare(tmp_e()); + F_And *f_and = f_exists->add_and(); + + if (rel == IR_COND_GE || rel == IR_COND_GT) { GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, 1); + h.update_coef(lhs, coef); h.update_coef(e, -1); if (rel == IR_COND_GT) h.update_const(-1); - - exp2formula(ir, r, f_and, freevars, v[i], e, side, IR_COND_EQ, true); } - } - else if (rel == IR_COND_LE || rel == IR_COND_LT) { - F_And *f_and = f_exists->add_and(); - for (int i = 0; i < v.size(); i++) { - Variable_ID e = f_exists->declare(tmp_e()); + else if (rel == IR_COND_LE || rel == IR_COND_LT) { GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, -1); + h.update_coef(lhs, -coef); h.update_coef(e, 1); if (rel == IR_COND_LT) h.update_const(-1); - - exp2formula(ir, r, f_and, freevars, v[i], e, side, IR_COND_EQ, true); } + else if (rel == IR_COND_EQ) { + EQ_Handle h = f_and->add_EQ(); + h.update_coef(lhs, coef); + h.update_coef(e, -1); + } + else + throw std::invalid_argument("unsupported condition type"); + + exp2formula(ir, r, f_and, freevars, v[0], e, side, IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + if (destroy) + delete repr; + break; } - else if (rel == IR_COND_EQ) { - F_Or *f_or = f_exists->add_and()->add_or(); - for (int i = 0; i < v.size(); i++) { - Variable_ID e = f_exists->declare(tmp_e()); - F_And *f_and = f_or->add_and(); + + case IR_OP_MOD: + { + fprintf(stderr, "IR_OP_MOD\n"); + /* the left hand of a mod can be a var but the right must be a const */ + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + + assert(ir->QueryExpOperation(v[1]) == IR_OP_CONSTANT); + IR_ConstantRef *ref = static_cast<IR_ConstantRef *>(ir->Repr2Ref(v[1])); + coef_t coef = ref->integer(); + delete v[1]; + delete ref; + + F_Exists *f_exists = f_root->add_exists(); + Variable_ID e = f_exists->declare(tmp_e()); + Variable_ID b = f_exists->declare(tmp_e()); + F_And *f_and = f_exists->add_and(); + + + if (rel == IR_COND_EQ) + { + EQ_Handle h = f_and->add_EQ(); + h.update_coef(lhs, 1); + h.update_coef(b, coef); + h.update_coef(e, -1); + } + + else if (rel == IR_COND_GE || rel == IR_COND_GT) { + //i = CONST alpha + beta && beta >= const ( handled higher up ) && beta < CONST + EQ_Handle h = f_and->add_EQ(); + h.update_coef(lhs, 1); + h.update_coef(b, coef); + h.update_coef(e, -1); + GEQ_Handle k = f_and->add_GEQ(); + k.update_coef(lhs, -1 ); + k.update_const(coef-1); + + } + + else if (rel == IR_COND_LE || rel == IR_COND_LT) { + //i = CONST alpha + beta && beta <= const ( handled higher up ) && beta >= 0 EQ_Handle h = f_and->add_EQ(); h.update_coef(lhs, 1); + h.update_coef(b, coef); h.update_coef(e, -1); - exp2formula(ir, r, f_and, freevars, v[i], e, side, IR_COND_EQ, false); + GEQ_Handle k = f_and->add_GEQ(); + k.update_coef(lhs, 1 ); - for (int j = 0; j < v.size(); j++) - if (j != i) { - Variable_ID e2 = f_exists->declare(tmp_e()); - GEQ_Handle h2 = f_and->add_GEQ(); - h2.update_coef(e, -1); - h2.update_coef(e2, 1); - - exp2formula(ir, r, f_and, freevars, v[j], e2, side, IR_COND_EQ, false); - } } - for (int i = 0; i < v.size(); i++) - delete v[i]; + exp2formula(ir, r, f_and, freevars, v[0], e, side, IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + if (destroy) + delete repr; + + break; } - else - throw std::invalid_argument("unsupported condition type"); - if (destroy) - delete repr; - } - case IR_OP_MAX: - { - std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); - F_Exists *f_exists = f_root->add_exists(); + case IR_OP_POSITIVE: + { + fprintf(stderr, "IR_OP_POSITIVE\n"); + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + + exp2formula(ir, r, f_root, freevars, v[0], lhs, side, rel, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + + if (destroy) + delete repr; + break; + } + - if (rel == IR_COND_LE || rel == IR_COND_LT) { - F_Or *f_or = f_exists->add_and()->add_or(); - for (int i = 0; i < v.size(); i++) { - Variable_ID e = f_exists->declare(tmp_e()); - F_And *f_and = f_or->add_and(); + case IR_OP_NEGATIVE: + { + fprintf(stderr, "IR_OP_NEGATIVE\n"); + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + + F_Exists *f_exists = f_root->add_exists(); + Variable_ID e = f_exists->declare(tmp_e()); + F_And *f_and = f_exists->add_and(); + + if (rel == IR_COND_GE || rel == IR_COND_GT) { GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, -1); + h.update_coef(lhs, 1); h.update_coef(e, 1); - if (rel == IR_COND_LT) + if (rel == IR_COND_GT) h.update_const(-1); - - exp2formula(ir, r, f_and, freevars, v[i], e, side, IR_COND_EQ, true); } - } - else if (rel == IR_COND_GE || rel == IR_COND_GT) { - F_And *f_and = f_exists->add_and(); - for (int i = 0; i < v.size(); i++) { - Variable_ID e = f_exists->declare(tmp_e()); + else if (rel == IR_COND_LE || rel == IR_COND_LT) { GEQ_Handle h = f_and->add_GEQ(); - h.update_coef(lhs, 1); + h.update_coef(lhs, -1); h.update_coef(e, -1); - if (rel == IR_COND_GT) + if (rel == IR_COND_LT) h.update_const(-1); - - exp2formula(ir, r, f_and, freevars, v[i], e, side, IR_COND_EQ, true); } - } - else if (rel == IR_COND_EQ) { - F_Or *f_or = f_exists->add_and()->add_or(); - for (int i = 0; i < v.size(); i++) { - Variable_ID e = f_exists->declare(tmp_e()); - F_And *f_and = f_or->add_and(); - + else if (rel == IR_COND_EQ) { EQ_Handle h = f_and->add_EQ(); h.update_coef(lhs, 1); - h.update_coef(e, -1); + h.update_coef(e, 1); + } + else + throw std::invalid_argument("unsupported condition type"); + + exp2formula(ir, r, f_and, freevars, v[0], e, side, IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + if (destroy) + delete repr; + break; + } + + + case IR_OP_MIN: + { + fprintf(stderr, "IR_OP_MIN\n"); + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + + F_Exists *f_exists = f_root->add_exists(); + + if (rel == IR_COND_GE || rel == IR_COND_GT) { + F_Or *f_or = f_exists->add_and()->add_or(); + for (int i = 0; i < v.size(); i++) { + Variable_ID e = f_exists->declare(tmp_e()); + F_And *f_and = f_or->add_and(); + GEQ_Handle h = f_and->add_GEQ(); + h.update_coef(lhs, 1); + h.update_coef(e, -1); + if (rel == IR_COND_GT) + h.update_const(-1); + + exp2formula(ir, r, f_and, freevars, v[i], e, side, IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + } + } + else if (rel == IR_COND_LE || rel == IR_COND_LT) { + F_And *f_and = f_exists->add_and(); + for (int i = 0; i < v.size(); i++) { + Variable_ID e = f_exists->declare(tmp_e()); + GEQ_Handle h = f_and->add_GEQ(); + h.update_coef(lhs, -1); + h.update_coef(e, 1); + if (rel == IR_COND_LT) + h.update_const(-1); + + exp2formula(ir, r, f_and, freevars, v[i], e, side, IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + } + } + else if (rel == IR_COND_EQ) { + F_Or *f_or = f_exists->add_and()->add_or(); + for (int i = 0; i < v.size(); i++) { + Variable_ID e = f_exists->declare(tmp_e()); + F_And *f_and = f_or->add_and(); + + EQ_Handle h = f_and->add_EQ(); + h.update_coef(lhs, 1); + h.update_coef(e, -1); + + exp2formula(ir, r, f_and, freevars, v[i], e, side, IR_COND_EQ, false, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + + for (int j = 0; j < v.size(); j++) + if (j != i) { + Variable_ID e2 = f_exists->declare(tmp_e()); + GEQ_Handle h2 = f_and->add_GEQ(); + h2.update_coef(e, -1); + h2.update_coef(e2, 1); + + exp2formula(ir, r, f_and, freevars, v[j], e2, side, + IR_COND_EQ, false, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + } + } - exp2formula(ir, r, f_and, freevars, v[i], e, side, IR_COND_EQ, false); + for (int i = 0; i < v.size(); i++) + delete v[i]; + } + else + throw std::invalid_argument("unsupported condition type"); + + if (destroy) + delete repr; + break; + } + + case IR_OP_MAX: + { + fprintf(stderr, "IR_OP_MAX\n"); + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + + F_Exists *f_exists = f_root->add_exists(); + + if (rel == IR_COND_LE || rel == IR_COND_LT) { + F_Or *f_or = f_exists->add_and()->add_or(); + for (int i = 0; i < v.size(); i++) { + Variable_ID e = f_exists->declare(tmp_e()); + F_And *f_and = f_or->add_and(); + GEQ_Handle h = f_and->add_GEQ(); + h.update_coef(lhs, -1); + h.update_coef(e, 1); + if (rel == IR_COND_LT) + h.update_const(-1); + + exp2formula(ir, r, f_and, freevars, v[i], e, side, IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + } + } + else if (rel == IR_COND_GE || rel == IR_COND_GT) { + F_And *f_and = f_exists->add_and(); + for (int i = 0; i < v.size(); i++) { + Variable_ID e = f_exists->declare(tmp_e()); + GEQ_Handle h = f_and->add_GEQ(); + h.update_coef(lhs, 1); + h.update_coef(e, -1); + if (rel == IR_COND_GT) + h.update_const(-1); + + exp2formula(ir, r, f_and, freevars, v[i], e, side, IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + + } + } + else if (rel == IR_COND_EQ) { + F_Or *f_or = f_exists->add_and()->add_or(); + for (int i = 0; i < v.size(); i++) { + Variable_ID e = f_exists->declare(tmp_e()); + F_And *f_and = f_or->add_and(); + + EQ_Handle h = f_and->add_EQ(); + h.update_coef(lhs, 1); + h.update_coef(e, -1); + + exp2formula(ir, r, f_and, freevars, v[i], e, side, IR_COND_EQ, false, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + + for (int j = 0; j < v.size(); j++) + if (j != i) { + Variable_ID e2 = f_exists->declare(tmp_e()); + GEQ_Handle h2 = f_and->add_GEQ(); + h2.update_coef(e, 1); + h2.update_coef(e2, -1); + + exp2formula(ir, r, f_and, freevars, v[j], e2, side, IR_COND_EQ, false, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + } + } - for (int j = 0; j < v.size(); j++) - if (j != i) { - Variable_ID e2 = f_exists->declare(tmp_e()); - GEQ_Handle h2 = f_and->add_GEQ(); - h2.update_coef(e, 1); - h2.update_coef(e2, -1); - - exp2formula(ir, r, f_and, freevars, v[j], e2, side, IR_COND_EQ, false); - } + for (int i = 0; i < v.size(); i++) + delete v[i]; } + else + throw std::invalid_argument("unsupported condition type"); - for (int i = 0; i < v.size(); i++) - delete v[i]; + if (destroy) + delete repr; + break; } - else - throw std::invalid_argument("unsupported condition type"); - if (destroy) - delete repr; + case IR_OP_ARRAY_VARIABLE: { // ***** + fprintf(stderr, "\nomegatools.cc IR_OP_ARRAY_VARIABLE ARRAY! \n"); + + // temp for printing + //CG_chillRepr *CR = (CG_chillRepr *)repr; + //fprintf(stderr, "repr "); CR->dump(); fflush(stdout); + + //fprintf(stderr, "repr "); repr->dump(); /* printf("\n"); */fflush(stdout); + + std::vector<CG_outputRepr *> v = ir->QueryExpOperand(repr); + IR_Ref *ref = static_cast<IR_ScalarRef *>(ir->Repr2Ref(v[0])); + + + CG_chillRepr *CR = (CG_chillRepr *)v[0]; // cheat for now. we should not know this is a chillRepr + //fprintf(stderr, "v "); CR->dump(); fflush(stdout); + //fprintf(stderr, "v "); v[0]->dump(); /* printf("\n"); */ fflush(stdout); + chillAST_node* node = CR->GetCode(); + + + //fprintf(stderr, "\n**** walking parents!\n"); + //std::vector<chillAST_VarDecl*> loopvars; + //node->gatherLoopIndeces( loopvars ); + //fprintf(stderr, "in omegatools, %d loop vars\n", (int)loopvars.size()); + + + std::string s = ref->name(); + //fprintf(stderr, "array variable s is %s\n", s.c_str()); + + int max_dim = 0; + bool need_new_fsymbol = false; + std::set<std::string> vars; + //fprintf(stderr, "ref->n_dim %d\n", ref->n_dim()); + for (int i = 0; i < ref->n_dim(); i++) { + //fprintf(stderr, "dimension %d\n", i); + Relation temp(r.n_inp()); + + // r is enclosing relation, we build another that will include this + r.setup_names(); + if (r.is_set()) + for (int j = 1; j <= r.n_set(); j++) { + temp.name_set_var(j, r.set_var(j)->name()); + } + else + for (int j = 1; j <= r.n_inp(); j++) { + temp.name_input_var(j, r.input_var(j)->name()); + } + + F_And *temp_root = temp.add_and(); + + CG_outputRepr* repr; + if(dynamic_cast<IR_PointerArrayRef *>(ref) != NULL) + repr = dynamic_cast<IR_PointerArrayRef *>(ref)->index(i); // i or i+1 + else if(dynamic_cast<IR_ArrayRef *>(ref) != NULL) + repr = dynamic_cast<IR_ArrayRef *>(ref)->index(i); + + std::vector<Free_Var_Decl*> freevars; + Free_Var_Decl *t = new Free_Var_Decl(s); + Variable_ID e = temp.get_local(t); + freevars.insert(freevars.end(), t); + + fprintf(stderr, "exp2formula recursing? \n"); + exp2formula(ir, temp, temp_root, freevars, repr, e, side, + IR_COND_EQ, false, uninterpreted_symbols, + uninterpreted_symbols_stringrepr); + fprintf(stderr, "BACK FROM exp2formula recursing? \n"); + + // temp is relation for the index of the array ?? + for (DNF_Iterator di(temp.query_DNF()); di; di++) { + for (EQ_Iterator ei = (*di)->EQs(); ei; ei++) { + + if ((*ei).get_const() != 0) + need_new_fsymbol = true; + for (Constr_Vars_Iter cvi(*ei); cvi; cvi++) + if ((*cvi).var->kind() == Input_Var) { + if ((*cvi).var->get_position() > max_dim) + max_dim = (*cvi).var->get_position(); + vars.insert( + r.input_var((*cvi).var->get_position())->name()); + + } + } + + } + + if (max_dim != ref->n_dim()) + need_new_fsymbol = true; + } + + //fprintf(stderr, "%d vars: ", (int)vars.size()); + //for (int i=0; i<vars.size(); i++) fprintf(stderr, "%s", vars[i].c_str()); + //for (std::set<std::string>::iterator it = vars.begin(); it != vars.end(); it++) { + // fprintf(stderr, "%s ", (*it).c_str()); + //} + //fprintf(stderr, "\n"); + + // r is enclosing relation, we build another that will include + Variable_ID e = find_index(r, s, side); // s is the array named "index" + + std::vector<chillAST_node*> internals = ((CG_chillRepr *)v[0])->getChillCode(); + int numnodes = internals.size(); // always 1? + std::vector<chillAST_DeclRefExpr *>dres; + std::vector<chillAST_VarDecl*> decls; + std::vector<chillAST_VarDecl*> sdecls; + for (int i=0; i<numnodes; i++) { + internals[i]->gatherScalarVarDecls(sdecls); // vardecls for scalars + } + + //fprintf(stderr, "%d scalar var decls()\n", sdecls.size()); + //for (int i=0; i<sdecls.size(); i++) { + // fprintf(stderr, "vardecl %2d: ", i); + // sdecls[i]->print(); printf("\n"); fflush(stdout); + //} + + + //fprintf(stderr, "omegatools.cc, exp2formula() NOW WHAT\n"); + //exit(0); + + if (e == NULL) { // s must be a free variable + //fprintf(stderr, "'%s' must be free variable\n\n", s.c_str()); + //fprintf(stderr, "SO WE WILL CREATE A MACRO ???\n"); + + Free_Var_Decl *t = NULL; + + // keep adding underscores until we have created a unique name based on the original + do { + s += "_"; + t = NULL; + for (unsigned i = 0; i < freevars.size(); i++) { + std::string ss = freevars[i]->base_name(); + + if (s == ss) { + t = freevars[i]; + break; + } + } + } while (t != NULL); + + if (!need_new_fsymbol) + t = new Free_Var_Decl(s, ref->n_dim()); + else + t = new Free_Var_Decl(s, max_dim); + freevars.insert(freevars.end(), t); // add index_____ to freevars + + + std::vector< std::string > Vargs; // vector of args + std::string args; + std::vector<omega::CG_outputRepr *> reprs; + std::vector<omega::CG_outputRepr *> reprs2; + for (std::set<std::string>::iterator it = vars.begin(); + it != vars.end(); it++) { + if (it == vars.begin()) + args += "("; + else + args += ","; + args += *it; + //fprintf(stderr, "an argument to the macro: %s\n", it->c_str()); + Vargs.push_back( (*it) ); + reprs.push_back(ir->builder()->CreateIdent(*it)); + reprs2.push_back(ir->builder()->CreateIdent(*it)); + } + args += ")"; + + //fprintf(stderr, "args '%s'\n", args.c_str()); + //fprintf(stderr, "Vargs "); + //for (int i=0; i<Vargs.size(); i++) fprintf(stderr, "%s ",Vargs[i].c_str()); + //fprintf(stderr, "\n"); + + //fprintf(stderr, "omegatools.cc ir->CreateDefineMacro( s (%s), args(%s), repr)\n", s.c_str(), args.c_str()); + + // TODO repr, the rhs of the macro, needs to NOT refer to an actual variable ??? + + + ir->CreateDefineMacro(s, Vargs, repr); + + + + // index_(i) uses i outputrepr + //fprintf(stderr,"omegatools.cc making uninterpreted symbol %s\n",s.c_str()); + uninterpreted_symbols.insert( // adding to uninterpreted_symbols + std::pair<std::string, std::vector<omega::CG_outputRepr *> >( + s, reprs)); + uninterpreted_symbols_stringrepr.insert( // adding to uninterpreted_symbols_stringrepr + std::pair<std::string, std::vector<omega::CG_outputRepr *> >(s, reprs2)); + + + e = r.get_local(t, Input_Tuple); + + if (rel == IR_COND_GE || rel == IR_COND_GT) { + GEQ_Handle h = f_root->add_GEQ(); + h.update_coef(lhs, 1); + h.update_coef(e, -1); + if (rel == IR_COND_GT) + h.update_const(-1); + } else if (rel == IR_COND_LE || rel == IR_COND_LT) { + GEQ_Handle h = f_root->add_GEQ(); + h.update_coef(lhs, -1); + h.update_coef(e, 1); + if (rel == IR_COND_LT) + h.update_const(-1); + } else if (rel == IR_COND_EQ) { + EQ_Handle h = f_root->add_EQ(); + h.update_coef(lhs, 1); + h.update_coef(e, -1); + } else + throw std::invalid_argument("unsupported condition type"); + } + // delete v[0]; + delete ref; + if (destroy) delete repr; + + //fprintf(stderr, "FINALLY DONE with IR_OP_ARRAY_VARIABLE\n\n"); + break; } - case IR_OP_NULL: + + + case IR_OP_NULL: + fprintf(stderr, "IR_OP_NULL\n"); break; + + default: throw ir_exp_error("unsupported operand type"); } } + + + +//----------------------------------------------------------------------------- +// Build dependence relation for two array references. +// ----------------------------------------------------------------------------- Relation arrays2relation(IR_Code *ir, std::vector<Free_Var_Decl*> &freevars, const IR_ArrayRef *ref_src, const Relation &IS_w, - const IR_ArrayRef *ref_dst, const Relation &IS_r) { + const IR_ArrayRef *ref_dst, const Relation &IS_r, + std::map<std::string, std::vector<omega::CG_outputRepr *> > &uninterpreted_symbols, + std::map<std::string, std::vector<omega::CG_outputRepr *> > &uninterpreted_symbols_stringrepr) { + + //fprintf(stderr, "arrays2relation()\n"); + //fprintf(stderr, "%d freevars\n", freevars.size()); + //for (int i=0; i<freevars.size(); i++) fprintf(stderr, "freevar %d %s\n", i, (const char *)(freevars[i]->base_name())); + + Relation &IS1 = const_cast<Relation &>(IS_w); Relation &IS2 = const_cast<Relation &>(IS_r); + //Relation *helper; + //helper = new Relation(IS1); fprintf(stderr, "IS1 "); helper->print(); fflush(stdout); + //helper = new Relation(IS2); fprintf(stderr, "IS2 "); helper->print(); fflush(stdout); + Relation r(IS1.n_set(), IS2.n_set()); + //helper = new Relation(r); fprintf(stderr, "r "); helper->print(); fflush(stdout); for (int i = 1; i <= IS1.n_set(); i++) r.name_input_var(i, IS1.set_var(i)->name()); @@ -513,9 +902,25 @@ Relation arrays2relation(IR_Code *ir, std::vector<Free_Var_Decl*> &freevars, for (int i = 1; i <= IS2.n_set(); i++) r.name_output_var(i, IS2.set_var(i)->name()+"'"); + //fprintf(stderr, "omegatools.cc sym_src\n"); IR_Symbol *sym_src = ref_src->symbol(); IR_Symbol *sym_dst = ref_dst->symbol(); + //fprintf(stderr, "omegatools.cc going to do IR_Symbol operator==\n"); + //fprintf(stderr, "omegatools.cc comparing symbol 0x%x to symbol 0x%x\n", sym_src, sym_dst); + + //if (!(*sym_src == *sym_dst)) fprintf(stderr, "!(*sym_src == *sym_dst)\n"); + + //fprintf(stderr, "calling !=\n"); + //if (*sym_src != *sym_dst) fprintf(stderr, "omegatools.cc (*sym_src != *sym_dst) TRUE\n"); + //else fprintf(stderr, "omegatools.cc (*sym_src != *sym_dst) FALSE\n"); + + //fprintf(stderr, "calling ==\n"); + //if ((*sym_src == *sym_dst)) fprintf(stderr, "(*sym_src == *sym_dst)) TRUE \n"); + //else fprintf(stderr, "(*sym_src == *sym_dst) FALSE \n"); + if (*sym_src != *sym_dst) { + //if (!(*sym_src == *sym_dst)) { + //fprintf(stderr, "False Relation\n"); r.add_or(); // False Relation delete sym_src; delete sym_dst; @@ -526,9 +931,13 @@ Relation arrays2relation(IR_Code *ir, std::vector<Free_Var_Decl*> &freevars, delete sym_dst; } + //fprintf(stderr, "f_root\n"); F_And *f_root = r.add_and(); + //fprintf(stderr, "omegatools.cc ref_src->n_dim() %d\n", ref_src->n_dim()); for (int i = 0; i < ref_src->n_dim(); i++) { + //fprintf(stderr, "arrays2 i %d\n", i); + F_Exists *f_exists = f_root->add_exists(); Variable_ID e1 = f_exists->declare(tmp_e()); Variable_ID e2 = f_exists->declare(tmp_e()); @@ -538,20 +947,29 @@ Relation arrays2relation(IR_Code *ir, std::vector<Free_Var_Decl*> &freevars, CG_outputRepr *repr_dst = ref_dst->index(i); bool has_complex_formula = false; - try { - exp2formula(ir, r, f_and, freevars, repr_src, e1, 'w', IR_COND_EQ, false); - exp2formula(ir, r, f_and, freevars, repr_dst, e2, 'r', IR_COND_EQ, false); - } - catch (const ir_exp_error &e) { + + if (ir->QueryExpOperation(repr_src) == IR_OP_ARRAY_VARIABLE + || ir->QueryExpOperation(repr_dst) == IR_OP_ARRAY_VARIABLE) has_complex_formula = true; - } if (!has_complex_formula) { - EQ_Handle h = f_and->add_EQ(); - h.update_coef(e1, 1); - h.update_coef(e2, -1); + + try { + exp2formula(ir, r, f_and, freevars, repr_src, e1, 'w', IR_COND_EQ, false, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + exp2formula(ir, r, f_and, freevars, repr_dst, e2, 'r', IR_COND_EQ, false, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + } + catch (const ir_exp_error &e) { + has_complex_formula = true; + } + + if (!has_complex_formula) { + EQ_Handle h = f_and->add_EQ(); + h.update_coef(e1, 1); + h.update_coef(e2, -1); + } } - repr_src->clear(); repr_dst->clear(); delete repr_src; @@ -566,32 +984,61 @@ Relation arrays2relation(IR_Code *ir, std::vector<Free_Var_Decl*> &freevars, for (int i = 1; i <= IS2.n_set(); i++) r.name_output_var(i, IS2.set_var(i)->name()+"'"); + //helper = new Relation(r); fprintf(stderr, "r "); helper->print(); fflush(stdout); + //fprintf(stderr, "leaving arrays2relation\n"); return r; } -std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > relation2dependences (const IR_ArrayRef *ref_src, const IR_ArrayRef *ref_dst, const Relation &r) { + +//----------------------------------------------------------------------------- +// Convert array dependence relation into set of dependence vectors, assuming +// ref_w is lexicographically before ref_r in the source code. +// ----------------------------------------------------------------------------- +std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > relation2dependences ( + const IR_ArrayRef *ref_src, + const IR_ArrayRef *ref_dst, + const Relation &r) { + //fprintf(stderr, "relation2dependences()\n"); assert(r.n_inp() == r.n_out()); std::vector<DependenceVector> dependences1, dependences2; + //std::vector<DependenceVector*> dep1, dep2; std::stack<DependenceLevel> working; working.push(DependenceLevel(r, r.n_inp())); while (!working.empty()) { + //fprintf(stderr, "!empty size %d\n", working.size()); + DependenceLevel dep = working.top(); working.pop(); + //if (!dep.r.is_satisfiable()) fprintf(stderr, "NOT dep.r.is_satisfiable()\n"); + //else fprintf(stderr, " dep.r.is_satisfiable()\n"); + // No dependence exists, move on. - if (!dep.r.is_satisfiable()) + if (!dep.r.is_satisfiable()) { + //fprintf(stderr, "No dependence exists, move on.\n"); continue; + } + //fprintf(stderr, "satisfiable\n"); + //fprintf(stderr, "dep.level %d r.n_inp() %d\n", dep.level, r.n_inp()); if (dep.level == r.n_inp()) { + //fprintf(stderr, "dep.level == r.n_inp()\n"); DependenceVector dv; + //fprintf(stderr, "\ndv created in if ***\n"); + //DependenceVector *dv2 = new DependenceVector; + + //fprintf(stderr, "for loop independent dependence dep.dir %d\n", dep.dir); // for loop independent dependence, use lexical order to // determine the correct source and destination if (dep.dir == 0) { - if (*ref_src == *ref_dst) + //fprintf(stderr, "dep.dir == 0\n"); + if (*ref_src == *ref_dst) { // c == c + //fprintf(stderr, "trivial\n"); continue; // trivial self zero-dependence + } if (ref_src->is_write()) { if (ref_dst->is_write()) @@ -608,6 +1055,7 @@ std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > relatio } else if (dep.dir == 1) { + //fprintf(stderr, "dep.dir == 1\n"); if (ref_src->is_write()) { if (ref_dst->is_write()) dv.type = DEP_W2W; @@ -622,6 +1070,7 @@ std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > relatio } } else { // dep.dir == -1 + //fprintf(stderr, "dep.dir == -1\n"); if (ref_dst->is_write()) { if (ref_src->is_write()) dv.type = DEP_W2W; @@ -638,27 +1087,74 @@ std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > relatio dv.lbounds = dep.lbounds; dv.ubounds = dep.ubounds; + + //fprintf(stderr, "omegatools.cc calling ref_src->symbol();\n"); dv.sym = ref_src->symbol(); + //fprintf(stderr, "dv.sym = %p\n", dv.sym); + + //fprintf(stderr, "symbol %s ADDING A DEPENDENCE OF TYPE ", dv.sym->name().c_str()); + //switch (dv.type) { + //case DEP_W2W: fprintf(stderr, "DEP_W2W to "); break; + //case DEP_W2R: fprintf(stderr, "DEP_W2R to "); break; + //case DEP_R2W: fprintf(stderr, "DEP_R2W to "); break; + //case DEP_R2R: fprintf(stderr, "DEP_R2R to "); break; + //default: fprintf(stderr, "DEP_UNKNOWN to "); break; + //} + //if (dep.dir == 0 || dep.dir == 1) fprintf(stderr, "dependences1\n"); + //else fprintf(stderr, "dependences2\n"); - if (dep.dir == 0 || dep.dir == 1) + if (dep.dir == 0 || dep.dir == 1) { + //fprintf(stderr, "pushing dv\n"); dependences1.push_back(dv); - else + //fprintf(stderr, "DONE pushing dv\n"); + + //fprintf(stderr, "now %d dependences1\n", dependences1.size() ); + //for (int i=0; i<dependences1.size(); i++) { + // fprintf(stderr, "dependences1[%d]: ", i ); + // //fprintf(stderr, "symbol %p ", dependences1[i].sym); + // fprintf(stderr, "symbol "); + // fprintf(stderr, "%s\n", dependences1[i].sym->name().c_str()); + //} + //fprintf(stderr, "\n"); + } + else { + //fprintf(stderr, "pushing dv\n"); dependences2.push_back(dv); + //fprintf(stderr, "DONE pushing dv\n"); + + //fprintf(stderr, "now %d dependences2\n", dependences2.size() ); + //for (int i=0; i<dependences2.size(); i++) { + // fprintf(stderr, "dependences2[%d]: ", i); + // //fprintf(stderr, "symbol %p ", dependences2[i].sym); + // fprintf(stderr, "symbol "); + // fprintf(stderr, "%s\n", dependences2[i].sym->name().c_str()); + //} + //fprintf(stderr, "\n"); + } + + //fprintf(stderr, "dv goes out of scope ***\n"); } else { + //fprintf(stderr, "now work on the next dimension level\n"); // now work on the next dimension level int level = ++dep.level; + //fprintf(stderr, "level %d\n", level); coef_t lbound, ubound; Relation delta = Deltas(copy(dep.r)); + //delta.print(); fflush(stdout); delta.query_variable_bounds(delta.set_var(level), lbound, ubound); + //fprintf(stderr, "delta lb " coef_fmt " 0x%llx ub " coef_fmt " 0x%llx\n", lbound,lbound,ubound,ubound); + if (dep.dir == 0) { + //fprintf(stderr, "dep.dir == 0\n"); if (lbound > 0) { dep.dir = 1; dep.lbounds[level-1] = lbound; dep.ubounds[level-1] = ubound; + //fprintf(stderr, "push 1\n"); working.push(dep); } else if (ubound < 0) { @@ -666,6 +1162,7 @@ std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > relatio dep.lbounds[level-1] = -ubound; dep.ubounds[level-1] = -lbound; + //fprintf(stderr, "push 2\n"); working.push(dep); } else { @@ -683,10 +1180,16 @@ std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > relatio h.update_coef(dep2.r.input_var(level), 1); h.update_coef(dep2.r.output_var(level), -1); + //fprintf(stderr, "push 3\n"); working.push(dep2); } - if (lbound < 0 && *ref_src != *ref_dst) { + //fprintf(stderr, "lbound %lld 0x%llx\n", lbound, lbound); + //if (lbound < 0LL) fprintf(stderr, "lbound < 0LL\n"); + //if (*ref_src != *ref_dst) fprintf(stderr, "(*ref_src != *ref_dst)\n"); + //else fprintf(stderr, "(*ref_src EQUAL *ref_dst)\n"); + + if (lbound < 0LL && (*ref_src != *ref_dst)) { // c == c DependenceLevel dep2 = dep; F_And *f_root = dep2.r.and_with_and(); @@ -702,12 +1205,14 @@ std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > relatio lbound, ubound); dep2.dir = -1; - dep2.lbounds[level-1] = max(-ubound,static_cast<coef_t>(1)); // use max() to avoid Omega retardness + dep2.lbounds[level-1] = std::max(-ubound,static_cast<coef_t>(1)); // use max() to avoid Omega retardedness dep2.ubounds[level-1] = -lbound; + //fprintf(stderr, "push 4\n"); working.push(dep2); } + //fprintf(stderr, "ubound %d\n", ubound); if (ubound > 0) { DependenceLevel dep2 = dep; @@ -723,9 +1228,10 @@ std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > relatio delta.query_variable_bounds(delta.set_var(level), lbound, ubound); dep2.dir = 1; - dep2.lbounds[level-1] = max(lbound,static_cast<coef_t>(1)); // use max() to avoid Omega retardness + dep2.lbounds[level-1] = std::max(lbound,static_cast<coef_t>(1)); // use max() to avoid Omega retardness dep2.ubounds[level-1] = ubound; + //fprintf(stderr, "push 5\n"); working.push(dep2); } } @@ -733,6 +1239,7 @@ std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > relatio // now deal with dependence vector with known direction // determined at previous levels else { + //fprintf(stderr, "else messy\n"); // For messy bounds, further test to see if the dependence distance // can be reduced to positive/negative. This is an omega hack. if (lbound == negInfinity && ubound == posInfinity) { @@ -788,59 +1295,167 @@ std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > relatio dep.ubounds[level-1] = ubound; } + //fprintf(stderr, "push 6\n"); working.push(dep); } } + //fprintf(stderr, "at bottom, size %d\n", working.size()); + } + //fprintf(stderr, "leaving relation2dependences, %d and %d dependences\n", dependences1.size(), dependences2.size()); + + + //for (int i=0; i<dependences1.size(); i++) { + //fprintf(stderr, "dependences1[%d]: ", i); + //fprintf(stderr, "symbol %s\n", dependences1[i].sym->name().c_str()); + + //fprintf(stderr, "symbol %s HAS A left DEPENDENCE OF TYPE ", dependences1[i].sym->name().c_str()); + //switch (dependences1[i].type) { + //case DEP_W2W: fprintf(stderr, "DEP_W2W\n"); break; + //case DEP_W2R: fprintf(stderr, "DEP_W2R\n"); break; + //case DEP_R2W: fprintf(stderr, "DEP_R2W\n"); break; + //case DEP_R2R: fprintf(stderr, "DEP_R2R\n"); break; + //default: fprintf(stderr, "DEP_UNKNOWN\n"); break; + //} + //} + + + //for (int i=0; i<dependences2.size(); i++) { + + //fprintf(stderr, "symbol %s HAS A right DEPENDENCE OF TYPE ", dependences2[i].sym->name().c_str()); + //switch (dependences2[i].type) { + //case DEP_W2W: fprintf(stderr, "DEP_W2W\n"); break; + //case DEP_W2R: fprintf(stderr, "DEP_W2R\n"); break; + //case DEP_R2W: fprintf(stderr, "DEP_R2W\n"); break; + //case DEP_R2R: fprintf(stderr, "DEP_R2R\n"); break; + //default: fprintf(stderr, "DEP_UNKNOWN\n"); break; + //} + //} + + + return std::make_pair(dependences1, dependences2); } + +//----------------------------------------------------------------------------- +// Convert a boolean expression to omega relation. "destroy" means shallow +// deallocation of "repr", not freeing the actual code inside. +//----------------------------------------------------------------------------- void exp2constraint(IR_Code *ir, Relation &r, F_And *f_root, std::vector<Free_Var_Decl *> &freevars, - CG_outputRepr *repr, bool destroy) { + CG_outputRepr *repr, + bool destroy, + std::map<std::string, std::vector<omega::CG_outputRepr *> > &uninterpreted_symbols, + std::map<std::string, std::vector<omega::CG_outputRepr *> > &uninterpreted_symbols_stringrepr) +{ IR_CONDITION_TYPE cond = ir->QueryBooleanExpOperation(repr); switch (cond) { case IR_COND_LT: case IR_COND_LE: case IR_COND_EQ: case IR_COND_GT: - case IR_COND_GE: { - F_Exists *f_exist = f_root->add_exists(); - Variable_ID e = f_exist->declare(); - F_And *f_and = f_exist->add_and(); - std::vector<omega::CG_outputRepr *> op = ir->QueryExpOperand(repr); - exp2formula(ir, r, f_and, freevars, op[0], e, 's', IR_COND_EQ, true); - exp2formula(ir, r, f_and, freevars, op[1], e, 's', cond, true); - if (destroy) - delete repr; - break; - } - case IR_COND_NE: { - F_Exists *f_exist = f_root->add_exists(); - Variable_ID e = f_exist->declare(); - F_Or *f_or = f_exist->add_or(); - F_And *f_and = f_or->add_and(); - std::vector<omega::CG_outputRepr *> op = ir->QueryExpOperand(repr); - exp2formula(ir, r, f_and, freevars, op[0], e, 's', IR_COND_EQ, false); - exp2formula(ir, r, f_and, freevars, op[1], e, 's', IR_COND_GT, false); - - f_and = f_or->add_and(); - exp2formula(ir, r, f_and, freevars, op[0], e, 's', IR_COND_EQ, true); - exp2formula(ir, r, f_and, freevars, op[1], e, 's', IR_COND_LT, true); - - if (destroy) - delete repr; - break; - } + case IR_COND_GE: + { + F_Exists *f_exist = f_root->add_exists(); + Variable_ID e = f_exist->declare(); + F_And *f_and = f_exist->add_and(); + std::vector<omega::CG_outputRepr *> op = ir->QueryExpOperand(repr); + exp2formula(ir, r, f_and, freevars, op[0], e, 's', IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + exp2formula(ir, r, f_and, freevars, op[1], e, 's', cond, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + + if (destroy) + delete repr; + break; + } + case IR_COND_NE: + { + F_Exists *f_exist = f_root->add_exists(); + Variable_ID e = f_exist->declare(); + F_Or *f_or = f_exist->add_or(); + F_And *f_and = f_or->add_and(); + std::vector<omega::CG_outputRepr *> op = ir->QueryExpOperand(repr); + exp2formula(ir, r, f_and, freevars, op[0], e, 's', IR_COND_EQ, false, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + exp2formula(ir, r, f_and, freevars, op[1], e, 's', IR_COND_GT, false, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + + f_and = f_or->add_and(); + exp2formula(ir, r, f_and, freevars, op[0], e, 's', IR_COND_EQ, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + exp2formula(ir, r, f_and, freevars, op[1], e, 's', IR_COND_LT, true, + uninterpreted_symbols, uninterpreted_symbols_stringrepr); + + if (destroy) + delete repr; + break; + } default: throw ir_exp_error("unrecognized conditional expression"); } } -bool is_single_loop_iteration(const Relation &r, int level, const Relation &known) { + + + + +//----------------------------------------------------------------------------- +// Generate iteration space constraints +//----------------------------------------------------------------------------- + +// void add_loop_stride_constraints(Relation &r, F_And *f_root, +// std::vector<Free_Var_Decl*> &freevars, +// tree_for *tnf, char side) { + +// std::string name(tnf->index()->name()); +// int dim = 0; +// for (;dim < r.n_set(); dim++) +// if (r.set_var(dim+1)->name() == name) +// break; + +// Relation bound = get_loop_bound(r, dim); + +// operand op = tnf->step_op(); +// if (!op.is_null()) { +// if (op.is_immed()) { +// immed im = op.immediate(); +// if (im.is_integer()) { +// int c = im.integer(); + +// if (c != 1 && c != -1) +// add_loop_stride(r, bound, dim, c); +// } +// else +// assert(0); // messy stride +// } +// else +// assert(0); // messy stride +// } +// } + + + + +//----------------------------------------------------------------------------- +// Determine whether the loop (starting from 0) in the iteration space +// has only one iteration. +//----------------------------------------------------------------------------- +bool is_single_loop_iteration(const Relation &r, + int level, + const Relation &known) { int n = r.n_set(); - Relation r1 = Intersection(copy(r), Extend_Set(copy(known), n-known.n_set())); + Relation r1; + if(n > known.n_set()) { + r1 = Intersection(copy(r), Extend_Set(copy(known), n - known.n_set())); + } + else{ + r1 = Intersection(copy(known), Extend_Set(copy(r), known.n_set() - n)); + n = known.n_set(); + } + Relation mapping(n, n); F_And *f_root = mapping.add_and(); @@ -869,6 +1484,8 @@ bool is_single_loop_iteration(const Relation &r, int level, const Relation &know } + + bool is_single_iteration(const Relation &r, int dim) { assert(r.is_set()); const int n = r.n_set(); @@ -878,6 +1495,11 @@ bool is_single_iteration(const Relation &r, int dim) { Relation bound = get_loop_bound(r, dim); + // if (!bound.has_single_conjunct()) + // return false; + + // Conjunct *c = bound.query_DNF()->single_conjunct(); + for (DNF_Iterator di(bound.query_DNF()); di; di++) { bool is_single = false; for (EQ_Iterator ei((*di)->EQs()); ei; ei++) @@ -891,8 +1513,78 @@ bool is_single_iteration(const Relation &r, int dim) { } return true; + + + + + // Relation r = copy(r_); + // const int n = r.n_set(); + + // if (dim >= n) + // return true; + + // Relation bound = get_loop_bound(r, dim); + // bound = Approximate(bound); + // Conjunct *c = bound.query_DNF()->single_conjunct(); + + // return c->n_GEQs() == 0; + + + + + + // Relation r = copy(r_); + // r.simplify(); + // const int n = r.n_set(); + + // if (dim >= n) + // return true; + + // for (DNF_Iterator i(r.query_DNF()); i; i++) { + // std::vector<bool> is_single(n); + // for (int j = 0; j < dim; j++) + // is_single[j] = true; + // for (int j = dim; j < n; j++) + // is_single[j] = false; + + // bool found_new_single = true; + // while (found_new_single) { + // found_new_single = false; + + // for (EQ_Iterator j = (*i)->EQs(); j; j++) { + // int saved_pos = -1; + // for (Constr_Vars_Iter k(*j); k; k++) + // if ((*k).var->kind() == Set_Var || (*k).var->kind() == Input_Var) { + // int pos = (*k).var->get_position() - 1; + // if (!is_single[pos]) + // if (saved_pos == -1) + // saved_pos = pos; + // else { + // saved_pos = -1; + // break; + // } + // } + + // if (saved_pos != -1) { + // is_single[saved_pos] = true; + // found_new_single = true; + // } + // } + + // if (is_single[dim]) + // break; + // } + + // if (!is_single[dim]) + // return false; + // } + + // return true; } +//----------------------------------------------------------------------------- +// Set/get the value of a variable which is know to be constant. +//----------------------------------------------------------------------------- void assign_const(Relation &r, int dim, int val) { const int n = r.n_out(); @@ -917,10 +1609,14 @@ void assign_const(Relation &r, int dim, int val) { int get_const(const Relation &r, int dim, Var_Kind type) { + // Relation rr = copy(r); Relation &rr = const_cast<Relation &>(r); Variable_ID v; switch (type) { + // case Set_Var: + // v = rr.set_var(dim+1); + // break; case Input_Var: v = rr.input_var(dim+1); break; @@ -939,10 +1635,19 @@ int get_const(const Relation &r, int dim, Var_Kind type) { throw std::runtime_error("cannot get variable's constant value"); } + + + + + +//--------------------------------------------------------------------------- +// Get the bound for a specific loop. +//--------------------------------------------------------------------------- Relation get_loop_bound(const Relation &r, int dim) { assert(r.is_set()); const int n = r.n_set(); + // Relation r1 = project_onto_levels(copy(r), dim+1, true); Relation mapping(n,n); F_And *f_root = mapping.add_and(); for (int i = 1; i <= dim+1; i++) { @@ -959,9 +1664,20 @@ Relation get_loop_bound(const Relation &r, int dim) { return Gist(r1, r2, 1); } + + Relation get_loop_bound(const Relation &r, int level, const Relation &known) { - int n = r.n_set(); - Relation r1 = Intersection(copy(r), Extend_Set(copy(known), n-known.n_set())); + int n1 = r.n_set(); + int n = n1; + Relation r1; + if(n > known.n_set()) + r1 = Intersection(copy(r), + Extend_Set(copy(known), n - known.n_set())); + else{ + r1 = Intersection(copy(known), + Extend_Set(copy(r), known.n_set() - n)); + n = known.n_set(); + } Relation mapping(n, n); F_And *f_root = mapping.add_and(); @@ -974,7 +1690,7 @@ Relation get_loop_bound(const Relation &r, int level, const Relation &known) { Relation r2 = Project(copy(r1), level, Set_Var); r1 = Gist(r1, r2, 1); - for (int i = 1; i <= n; i++) + for (int i = 1; i <= n1; i++) r1.name_set_var(i, const_cast<Relation &>(r).set_var(i)->name()); r1.setup_names(); @@ -1017,6 +1733,12 @@ Relation get_min_loop_bound(const std::vector<Relation> &r, int dim) { return res; } +//----------------------------------------------------------------------------- +// Add strident to a loop. +// Issues: +// - Don't work with relations with multiple disjuncts. +// - Omega's dealing with max lower bound is awkward. +//----------------------------------------------------------------------------- void add_loop_stride(Relation &r, const Relation &bound_, int dim, int stride) { F_And *f_root = r.and_with_and(); Relation &bound = const_cast<Relation &>(bound_); @@ -1042,30 +1764,32 @@ void add_loop_stride(Relation &r, const Relation &bound_, int dim, int stride) { for (Constr_Vars_Iter ci(*gi); ci; ci++) { switch ((*ci).var->kind()) { // case Set_Var: - case Input_Var: { - int pos = (*ci).var->get_position(); - if (pos == dim + 1) { - h1.update_coef(e1, (*ci).coef); - h2.update_coef(e1, (*ci).coef); - } - else { - if (!r.is_set()) { - h1.update_coef(r.output_var(pos), (*ci).coef); - h2.update_coef(r.output_var(pos), (*ci).coef); + case Input_Var: + { + int pos = (*ci).var->get_position(); + if (pos == dim + 1) { + h1.update_coef(e1, (*ci).coef); + h2.update_coef(e1, (*ci).coef); } else { - h1.update_coef(r.set_var(pos), (*ci).coef); - h2.update_coef(r.set_var(pos), (*ci).coef); - } + if (!r.is_set()) { + h1.update_coef(r.output_var(pos), (*ci).coef); + h2.update_coef(r.output_var(pos), (*ci).coef); + } + else { + h1.update_coef(r.set_var(pos), (*ci).coef); + h2.update_coef(r.set_var(pos), (*ci).coef); + } + } + break; + } + case Global_Var: + { + Global_Var_ID g = (*ci).var->get_global_var(); + h1.update_coef(r.get_local(g, (*ci).var->function_of()), (*ci).coef); + h2.update_coef(r.get_local(g, (*ci).var->function_of()), (*ci).coef); + break; } - break; - } - case Global_Var: { - Global_Var_ID g = (*ci).var->get_global_var(); - h1.update_coef(r.get_local(g, (*ci).var->function_of()), (*ci).coef); - h2.update_coef(r.get_local(g, (*ci).var->function_of()), (*ci).coef); - break; - } default: break; } @@ -1078,8 +1802,18 @@ void add_loop_stride(Relation &r, const Relation &bound_, int dim, int stride) { } -bool is_inner_loop_depend_on_level(const Relation &r, int level, const Relation &known) { - Relation r1 = Intersection(copy(r), Extend_Set(copy(known), r.n_set()-known.n_set())); +bool is_inner_loop_depend_on_level(const Relation &r, + int level, + const Relation &known) { + + Relation r1; + if(r.n_set() > known.n_set()) + r1 = Intersection(copy(r), + Extend_Set(copy(known), r.n_set() - known.n_set())); + else + r1 = Intersection(copy(known), + Extend_Set(copy(r), known.n_set() - r.n_set())); + Relation r2 = copy(r1); for (int i = level+1; i <= r2.n_set(); i++) r2 = Project(r2, r2.set_var(i)); @@ -1100,6 +1834,15 @@ bool is_inner_loop_depend_on_level(const Relation &r, int level, const Relation return false; } + +//----------------------------------------------------------------------------- +// Suppose loop dim is i. Replace i with i+adjustment in loop bounds. +// e.g. do i = 1, n +// do j = i, n +// after call with dim = 0 and adjustment = 1: +// do i = 1, n +// do j = i+1, n +// ----------------------------------------------------------------------------- Relation adjust_loop_bound(const Relation &r, int level, int adjustment) { if (adjustment == 0) return copy(r); @@ -1136,6 +1879,236 @@ Relation adjust_loop_bound(const Relation &r, int level, int adjustment) { return r1; } + +// commented out on 07/14/2010 +// void adjust_loop_bound(Relation &r, int dim, int adjustment, std::vector<Free_Var_Decl *> globals) { +// assert(r.is_set()); + +// if (adjustment == 0) +// return; + +// const int n = r.n_set(); +// Tuple<std::string> name(n); +// for (int i = 1; i <= n; i++) +// name[i] = r.set_var(i)->name(); + +// Relation r1 = project_onto_levels(copy(r), dim+1, true); +// Relation r2 = Gist(copy(r), copy(r1)); + +// // remove old bogus global variable conditions since we are going to +// // update the value. +// if (globals.size() > 0) +// r1 = Gist(r1, project_onto_levels(copy(r), 0, true)); + +// Relation r4 = Relation::True(n); + +// for (DNF_Iterator di(r2.query_DNF()); di; di++) { +// for (EQ_Iterator ei = (*di)->EQs(); ei; ei++) { +// EQ_Handle h = r4.and_with_EQ(*ei); + +// Variable_ID v = r2.set_var(dim+1); +// coef_t c = (*ei).get_coef(v); +// if (c != 0) +// h.update_const(c*adjustment); + +// for (int i = 0; i < globals.size(); i++) { +// Variable_ID v = r2.get_local(globals[i]); +// coef_t c = (*ei).get_coef(v); +// if (c != 0) +// h.update_const(c*adjustment); +// } +// } + +// for (GEQ_Iterator gi = (*di)->GEQs(); gi; gi++) { +// GEQ_Handle h = r4.and_with_GEQ(*gi); + +// Variable_ID v = r2.set_var(dim+1); +// coef_t c = (*gi).get_coef(v); +// if (c != 0) +// h.update_const(c*adjustment); + +// for (int i = 0; i < globals.size(); i++) { +// Variable_ID v = r2.get_local(globals[i]); +// coef_t c = (*gi).get_coef(v); +// if (c != 0) +// h.update_const(c*adjustment); +// } +// } +// } +// r = Intersection(r1, r4); +// // } +// // else +// // r = Intersection(r1, r2); + +// for (int i = 1; i <= n; i++) +// r.name_set_var(i, name[i]); +// r.setup_names(); +// } + + +// void adjust_loop_bound(Relation &r, int dim, int adjustment) { +// assert(r.is_set()); +// const int n = r.n_set(); +// Tuple<String> name(n); +// for (int i = 1; i <= n; i++) +// name[i] = r.set_var(i)->name(); + +// Relation r1 = project_onto_levels(copy(r), dim+1, true); +// Relation r2 = Gist(r, copy(r1)); + +// Relation r3(n, n); +// F_And *f_root = r3.add_and(); +// for (int i = 0; i < n; i++) { +// EQ_Handle h = f_root->add_EQ(); +// h.update_coef(r3.output_var(i+1), 1); +// h.update_coef(r3.input_var(i+1), -1); +// if (i == dim) +// h.update_const(adjustment); +// } + +// r2 = Range(Restrict_Domain(r3, r2)); +// r = Intersection(r1, r2); + +// for (int i = 1; i <= n; i++) +// r.name_set_var(i, name[i]); +// r.setup_names(); +// } + +// void adjust_loop_bound(Relation &r, int dim, Free_Var_Decl *global_var, int adjustment) { +// assert(r.is_set()); +// const int n = r.n_set(); +// Tuple<String> name(n); +// for (int i = 1; i <= n; i++) +// name[i] = r.set_var(i)->name(); + +// Relation r1 = project_onto_levels(copy(r), dim+1, true); +// Relation r2 = Gist(r, copy(r1)); + +// Relation r3(n); +// Variable_ID v = r2.get_local(global_var); + +// for (DNF_Iterator di(r2.query_DNF()); di; di++) { +// for (EQ_Iterator ei = (*di)->EQs(); ei; ei++) { +// coef_t c = (*ei).get_coef(v); +// EQ_Handle h = r3.and_with_EQ(*ei); +// if (c != 0) +// h.update_const(c*adjustment); +// } +// for (GEQ_Iterator gi = (*di)->GEQs(); gi; gi++) { +// coef_t c = (*gi).get_coef(v); +// GEQ_Handle h = r3.and_with_GEQ(*gi); +// if (c != 0) +// h.update_const(c*adjustment); +// } +// } + +// r = Intersection(r1, r3); +// for (int i = 1; i <= n; i++) +// r.name_set_var(i, name[i]); +// r.setup_names(); +// } + + + +//------------------------------------------------------------------------------ +// If the dimension has value posInfinity, the statement should be privatized +// at this dimension. +//------------------------------------------------------------------------------ +// boolean is_private_statement(const Relation &r, int dim) { +// int n; +// if (r.is_set()) +// n = r.n_set(); +// else +// n = r.n_out(); + +// if (dim >= n) +// return false; + +// try { +// coef_t c; +// if (r.is_set()) +// c = get_const(r, dim, Set_Var); +// else +// c = get_const(r, dim, Output_Var); +// if (c == posInfinity) +// return true; +// else +// return false; +// } +// catch (loop_error e){ +// } + +// return false; +// } + + + +// // ---------------------------------------------------------------------------- +// // Calculate v mod dividend based on equations inside relation r. +// // Return posInfinity if it is not a constant. +// // ---------------------------------------------------------------------------- +// static coef_t mod_(const Relation &r_, Variable_ID v, int dividend, std::set<Variable_ID> &working_on) { +// assert(dividend > 0); +// if (v->kind() == Forall_Var || v->kind() == Exists_Var || v->kind() == Wildcard_Var) +// return posInfinity; + +// working_on.insert(v); + +// Relation &r = const_cast<Relation &>(r_); +// Conjunct *c = r.query_DNF()->single_conjunct(); + +// for (EQ_Iterator ei(c->EQs()); ei; ei++) { +// int coef = mod((*ei).get_coef(v), dividend); +// if (coef != 1 && coef != dividend - 1 ) +// continue; + +// coef_t result = 0; +// for (Constr_Vars_Iter cvi(*ei); cvi; cvi++) +// if ((*cvi).var != v) { +// int p = mod((*cvi).coef, dividend); + +// if (p == 0) +// continue; + +// if (working_on.find((*cvi).var) != working_on.end()) { +// result = posInfinity; +// break; +// } + +// coef_t q = mod_(r, (*cvi).var, dividend, working_on); +// if (q == posInfinity) { +// result = posInfinity; +// break; +// } +// result += p * q; +// } + +// if (result != posInfinity) { +// result += (*ei).get_const(); +// if (coef == 1) +// result = -result; +// working_on.erase(v); + +// return mod(result, dividend); +// } +// } + +// working_on.erase(v); +// return posInfinity; +// } + + +// coef_t mod(const Relation &r, Variable_ID v, int dividend) { +// std::set<Variable_ID> working_on = std::set<Variable_ID>(); + +// return mod_(r, v, dividend, working_on); +// } + + + +//----------------------------------------------------------------------------- +// Generate mapping relation for permuation. +//----------------------------------------------------------------------------- Relation permute_relation(const std::vector<int> &pi) { const int n = pi.size(); @@ -1151,6 +2124,11 @@ Relation permute_relation(const std::vector<int> &pi) { return r; } + + +//--------------------------------------------------------------------------- +// Find the position index variable in a Relation by name. +//--------------------------------------------------------------------------- Variable_ID find_index(Relation &r, const std::string &s, char side) { // Omega quirks: assure the names are propagated inside the relation r.setup_names(); @@ -1183,3 +2161,1104 @@ Variable_ID find_index(Relation &r, const std::string &s, char side) { return NULL; } +// EQ_Handle get_eq(const Relation &r, int dim, Var_Kind type) { +// Variable_ID v; +// switch (type) { +// case Set_Var: +// v = r.set_var(dim+1); +// break; +// case Input_Var: +// v = r.input_var(dim+1); +// break; +// case Output_Var: +// v = r.output_var(dim+1); +// break; +// default: +// return NULL; +// } +// for (DNF_iterator di(r.query_DNF()); di; di++) +// for (EQ_Iterator ei = (*di)->EQs(); ei; ei++) +// if ((*ei).get_coef(v) != 0) +// return (*ei); + +// return NULL; +// } + + +// std::Pair<Relation, Relation> split_loop(const Relation &r, const Relation &cond) { +// Relation r1 = Intersection(copy(r), copy(cond)); +// Relation r2 = Intersection(copy(r), Complement(copy(cond))); + +// return std::Pair<Relation, Relation>(r1, r2); +// } + + + +//---------------------------------------------------------------------------- +//check if loop is normalized to zero +//---------------------------------------------------------------------------- +bool lowerBoundIsZero(const omega::Relation &bound, int dim) { + Relation &IS = const_cast<Relation &>(bound); + Variable_ID v = IS.input_var(dim); + bool found = false; + for (DNF_Iterator di(IS.query_DNF()); di; di++) { + bool is_single = false; + for (GEQ_Iterator gi((*di)->GEQs()); gi; gi++) + if ((*gi).get_coef(v) >= 0 && !(*gi).is_const(v) + && (*gi).get_const() != 0) { + return false; + } + else if ((*gi).get_coef(v) >= 0 && (*gi).is_const(v) + && (*gi).get_const() == 0) + found = true; + } + + return found; +} + + + +Relation replicate_IS_and_add_bound(const omega::Relation &R, int level, + omega::Relation &bound) { + + if (!R.is_set()) + throw std::invalid_argument("Input R has to be a set not a relation!"); + + Relation r(R.n_set()); + + for (int i = 1; i <= R.n_set(); i++) { + r.name_set_var(i + 1, const_cast<Relation &>(R).set_var(i)->name()); + } + + std::string new_var = bound.set_var(1)->name(); + + r.name_set_var(level, new_var); + + F_Exists *f_exists = r.add_and()->add_exists(); + F_And *f_root = f_exists->add_and(); + std::map<Variable_ID, Variable_ID> exists_mapping; + + for (DNF_Iterator di(const_cast<Relation &>(R).query_DNF()); di; di++) { + for (GEQ_Iterator gi((*di)->GEQs()); gi; gi++) { + GEQ_Handle h = f_root->add_GEQ(); + + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + + h.update_coef(r.input_var(v->get_position()), + cvi.curr_coef()); + + break; + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const((*gi).get_const()); + } + } + + for (DNF_Iterator di(const_cast<Relation &>(R).query_DNF()); di; di++) { + for (EQ_Iterator gi((*di)->EQs()); gi; gi++) { + EQ_Handle h1 = f_root->add_EQ(); + + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + + h1.update_coef(r.input_var(v->get_position()), + cvi.curr_coef()); + + break; + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h1.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h1.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h1.update_const((*gi).get_const()); + } + } + + for (DNF_Iterator di(bound.query_DNF()); di; di++) { + for (GEQ_Iterator gi((*di)->GEQs()); gi; gi++) { + GEQ_Handle h = f_root->add_GEQ(); + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + + h.update_coef(r.input_var(level), cvi.curr_coef()); + + break; + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const((*gi).get_const()); + } + } + + for (DNF_Iterator di(bound.query_DNF()); di; di++) { + for (EQ_Iterator gi((*di)->EQs()); gi; gi++) { + EQ_Handle h = f_root->add_EQ(); + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + h.update_coef(r.input_var(level), cvi.curr_coef()); + + break; + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const((*gi).get_const()); + } + } + r.simplify(); + r.setup_names(); + return r; +} + + + + +// Replicates old_relation's bounds for set var at old_pos int o new_relation at new_pos, but position's bounds must involve constants +// only supports GEQs +// +Relation replace_set_var_as_another_set_var(const omega::Relation &new_relation, + const omega::Relation &old_relation, int new_pos, int old_pos) { + + Relation r = copy(new_relation); + r.copy_names(new_relation); + r.setup_names(); + + F_Exists *f_exists = r.and_with_and()->add_exists(); + F_And *f_root = f_exists->add_and(); + std::map<Variable_ID, Variable_ID> exists_mapping; + + for (DNF_Iterator di(const_cast<Relation &>(old_relation).query_DNF()); di; + di++) + for (GEQ_Iterator gi((*di)->GEQs()); gi; gi++) { + GEQ_Handle h = f_root->add_GEQ(); + if (((*gi).get_coef( + const_cast<Relation &>(old_relation).set_var(old_pos)) != 0) + && (*gi).is_const_except_for_global( + const_cast<Relation &>(old_relation).set_var( + old_pos))) { + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + { + + if (v->get_position() == old_pos) + h.update_coef(r.input_var(new_pos), + cvi.curr_coef()); + else + throw omega_error( + "relation contains set vars other than that to be replicated!"); + break; + + } + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition( + old_relation, v, r, f_exists, f_root, + exists_mapping); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const((*gi).get_const()); + } + } + return r; + +} + + + + + +//----------------------------------------------------------------------------- +// Copy all relations from r and add new bound at position indicated by level. +// ----------------------------------------------------------------------------- + +Relation replicate_IS_and_add_at_pos(const omega::Relation &R, int level, + omega::Relation &bound) { + + if (!R.is_set()) + throw std::invalid_argument("Input R has to be a set not a relation!"); + + Relation r(R.n_set() + 1); + + for (int i = 1; i <= R.n_set(); i++) { + if (i < level) + r.name_set_var(i, const_cast<Relation &>(R).set_var(i)->name()); + else + r.name_set_var(i + 1, const_cast<Relation &>(R).set_var(i)->name()); + + } + + std::string new_var = bound.set_var(1)->name(); + + r.name_set_var(level, new_var); + + F_Exists *f_exists = r.add_and()->add_exists(); + F_And *f_root = f_exists->add_and(); + std::map<Variable_ID, Variable_ID> exists_mapping; + + for (int i = 1; i <= R.n_set(); i++) + for (DNF_Iterator di(const_cast<Relation &>(R).query_DNF()); di; di++) { + for (GEQ_Iterator gi((*di)->GEQs()); gi; gi++) { + GEQ_Handle h = f_root->add_GEQ(); + if ((*gi).get_coef(const_cast<Relation &>(R).set_var(i)) != 0) { + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + { + if (i < level) + h.update_coef(r.input_var(v->get_position()), + cvi.curr_coef()); + else + h.update_coef( + r.input_var(v->get_position() + 1), + cvi.curr_coef()); + break; + } + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + + } + h.update_const((*gi).get_const()); + } + } + } + + for (int i = 1; i <= R.n_set(); i++) + for (DNF_Iterator di(const_cast<Relation &>(R).query_DNF()); di; di++) { + for (EQ_Iterator gi((*di)->EQs()); gi; gi++) { + EQ_Handle h1 = f_root->add_EQ(); + if ((*gi).get_coef(const_cast<Relation &>(R).set_var(i)) != 0) { + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + { + if (i < level) + h1.update_coef(r.input_var(v->get_position()), + cvi.curr_coef()); + else + h1.update_coef( + r.input_var(v->get_position() + 1), + cvi.curr_coef()); + break; + } + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h1.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h1.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h1.update_const((*gi).get_const()); + } + } + } + + for (DNF_Iterator di(bound.query_DNF()); di; di++) { + for (GEQ_Iterator gi((*di)->GEQs()); gi; gi++) { + GEQ_Handle h = f_root->add_GEQ(); + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + { + if (cvi.curr_var()->get_position() < level) + h.update_coef(r.input_var(level), cvi.curr_coef()); + else + h.update_coef(r.input_var(level), cvi.curr_coef()); + break; + } + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + h.update_const((*gi).get_const()); + } + } + } + + for (DNF_Iterator di(bound.query_DNF()); di; di++) { + for (EQ_Iterator gi((*di)->EQs()); gi; gi++) { + EQ_Handle h = f_root->add_EQ(); + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + { + if (cvi.curr_var()->get_position() < level) + h.update_coef(r.input_var(level), cvi.curr_coef()); + else + h.update_coef(r.input_var(level), cvi.curr_coef()); + break; + } + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const((*gi).get_const()); + } + } + r.simplify(); + r.setup_names(); + return r; +} + + + + +omega::Relation replace_set_var_as_Global(const omega::Relation &R, int pos, + std::vector<omega::Relation> &bound) { + + if (!R.is_set()) + throw std::invalid_argument("Input R has to be a set not a relation!"); + + Relation r(R.n_set()); + F_Exists *f_exists = r.add_and()->add_exists(); + F_And *f_root = f_exists->add_and(); + std::map<Variable_ID, Variable_ID> exists_mapping; + int count = 1; + for (int i = 1; i <= R.n_set(); i++) { + + if (i != pos) { + r.name_set_var(i, const_cast<Relation &>(R).set_var(i)->name()); + + } + else + r.name_set_var(i, "void"); + } + + Free_Var_Decl *repl = new Free_Var_Decl( + const_cast<Relation &>(R).set_var(pos)->name()); + + Variable_ID v3 = r.get_local(repl); + + for (DNF_Iterator di(const_cast<Relation &>(R).query_DNF()); di; di++) { + for (EQ_Iterator gi((*di)->EQs()); gi; gi++) { + EQ_Handle h1 = f_root->add_EQ(); + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + { + if (v->get_position() != pos) + h1.update_coef(r.input_var(v->get_position()), + cvi.curr_coef()); + else + + h1.update_coef(v3, cvi.curr_coef()); + break; + } + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h1.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h1.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h1.update_const((*gi).get_const()); + } + } + + for (int i = 0; i < bound.size(); i++) + for (DNF_Iterator di(bound[i].query_DNF()); di; di++) { + for (GEQ_Iterator gi((*di)->GEQs()); gi; gi++) { + GEQ_Handle h = f_root->add_GEQ(); + if ((*gi).get_coef(bound[i].set_var(pos)) == 0) { + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + { + //if (i < level) + if (v->get_position() != pos) + h.update_coef(r.input_var(v->get_position()), + cvi.curr_coef()); + else + + h.update_coef(v3, cvi.curr_coef()); + break; + + //else + // h.update_coef( + // r.input_var(v->get_position() + 1), + // cvi.curr_coef()); + break; + } + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + + } + h.update_const((*gi).get_const()); + } + } + } + return r; +} + + + + + +//----------------------------------------------------------------------------- +// Replace an input variable's constraints as an existential in order +// to simplify other constraints in Relation +// ----------------------------------------------------------------------------- +std::pair<Relation, bool> replace_set_var_as_existential( + const omega::Relation &R, int pos, + std::vector<omega::Relation> &bound) { + + if (!R.is_set()) + throw std::invalid_argument("Input R has to be a set not a relation!"); + + Relation r(R.n_set()); + for (int i = 1; i <= R.n_set(); i++) + r.name_set_var(i, const_cast<Relation &>(R).set_var(i)->name()); + + F_Exists *f_exists = r.add_and()->add_exists(); + F_And *f_root = f_exists->add_and(); + std::map<Variable_ID, Variable_ID> exists_mapping; + int coef_in_equality = 0; + for (DNF_Iterator di(const_cast<Relation &>(R).query_DNF()); di; di++) + for (EQ_Iterator gi((*di)->EQs()); gi; gi++) + if (((*gi).get_coef(const_cast<Relation &>(R).set_var(pos)) != 0) + && (!(*gi).has_wildcards())) + if (coef_in_equality == 0) + coef_in_equality = (*gi).get_coef( + const_cast<Relation &>(R).set_var(pos)); + else + return std::pair<Relation, bool>(copy(R), false); + + if (coef_in_equality < 0) + coef_in_equality = -coef_in_equality; + + std::pair<EQ_Handle, Variable_ID> result = find_simplest_stride( + const_cast<Relation &>(R), const_cast<Relation &>(R).set_var(pos)); + + if (result.second == NULL && coef_in_equality != 1) + return std::pair<Relation, bool>(copy(R), false); + + if (result.second != NULL) { + if (result.first.get_coef(const_cast<Relation &>(R).set_var(pos)) != 1) + return std::pair<Relation, bool>(copy(R), false); + + if (result.first.get_coef(result.second) != coef_in_equality) + return std::pair<Relation, bool>(copy(R), false); + } + Variable_ID v3 = f_exists->declare(); + + for (DNF_Iterator di(const_cast<Relation &>(R).query_DNF()); di; di++) { + for (EQ_Iterator gi((*di)->EQs()); gi; gi++) { + EQ_Handle h1 = f_root->add_EQ(); + if ((*gi).get_coef(const_cast<Relation &>(R).set_var(pos)) == 0 + || !(*gi).has_wildcards()) { + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + { + if (v->get_position() != pos) + h1.update_coef(r.input_var(v->get_position()), + cvi.curr_coef()); + else + + h1.update_coef(v3, cvi.curr_coef()); + break; + } + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h1.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h1.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h1.update_const((*gi).get_const()); + } + } + } + + for (int i = 0; i < bound.size(); i++) + for (DNF_Iterator di(bound[i].query_DNF()); di; di++) { + for (GEQ_Iterator gi((*di)->GEQs()); gi; gi++) { + GEQ_Handle h = f_root->add_GEQ(); + //if ((*gi).get_coef(const_cast<Relation &>(R).set_var(i)) != 0) { + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + { + //if (i < level) + if (v->get_position() != pos) + + h.update_coef(r.set_var(v->get_position()), + cvi.curr_coef()); + else + + h.update_coef(v3, cvi.curr_coef()); + + //else + // h.update_coef( + // r.input_var(v->get_position() + 1), + // cvi.curr_coef()); + break; + } + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + + } + h.update_const((*gi).get_const()); + //} + } + } + + //for (int i = 1; i <= R.n_set(); i++) + return std::pair<Relation, bool>(r, true); +} + + + + + +//----------------------------------------------------------------------------- +// Copy all relations from r except those for set var v. +// And with GEQ given by g +// NOTE: This function only removes the relations involving v if they are simple relations +// involving only v but not complex relations that have v in other variables' constraints +// ----------------------------------------------------------------------------- +Relation and_with_relation_and_replace_var(const Relation &R, Variable_ID v1, + Relation &g) { + if (!R.is_set()) + throw std::invalid_argument("Input R has to be a set not a relation!"); + + Relation r(R.n_set()); + + F_Exists *f_exists = r.add_and()->add_exists(); + F_And *f_root = f_exists->add_and(); + std::map<Variable_ID, Variable_ID> exists_mapping; + EQ_Handle h = f_root->add_EQ(); + for (DNF_Iterator di(const_cast<Relation &>(R).query_DNF()); di; di++) { + for (EQ_Iterator gi((*di)->EQs()); gi; gi++) { + EQ_Handle h = f_root->add_EQ(); + if (!(*gi).is_const(v1) && !(*gi).is_const_except_for_global(v1)) { + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + { + h.update_coef(r.input_var(v->get_position()), + cvi.curr_coef()); + break; + } + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + + h.update_const((*gi).get_const()); + } + } + + for (GEQ_Iterator gi((*di)->GEQs()); gi; gi++) { + GEQ_Handle h = f_root->add_GEQ(); + if ((*gi).get_coef(v1) == 0) { + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + { + h.update_coef(r.input_var(v->get_position()), + cvi.curr_coef()); + break; + } + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const((*gi).get_const()); + } + } + } + for (DNF_Iterator di(const_cast<Relation &>(g).query_DNF()); di; di++) + for (GEQ_Iterator gi((*di)->GEQs()); gi; gi++) + r.and_with_GEQ(*gi); + + for (DNF_Iterator di(const_cast<Relation &>(g).query_DNF()); di; di++) + for (EQ_Iterator gi((*di)->EQs()); gi; gi++) + r.and_with_EQ(*gi); + + r.simplify(); + r.copy_names(R); + r.setup_names(); + return r; +} + + + + + +omega::Relation extract_upper_bound(const Relation &R, Variable_ID v1) { + if (!R.is_set()) + throw std::invalid_argument("Input R has to be a set not a relation!"); + + Relation r(R.n_set()); + + F_Exists *f_exists = r.add_and()->add_exists(); + F_And *f_root = f_exists->add_and(); + std::map<Variable_ID, Variable_ID> exists_mapping; + GEQ_Handle h = f_root->add_GEQ(); + for (DNF_Iterator di(const_cast<Relation &>(R).query_DNF()); di; di++) + for (GEQ_Iterator gi((*di)->GEQs()); gi; gi++) + if ((*gi).get_coef(v1) < 0) { + + for (Constr_Vars_Iter cvi(*gi); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + h.update_coef(r.input_var(v->get_position()), + cvi.curr_coef()); + break; + case Wildcard_Var: + { + Variable_ID v2 = replicate_floor_definition(R, v, r, + f_exists, f_root, exists_mapping); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Global_Var: + { + Global_Var_ID g = v->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const((*gi).get_const()); + } + + r.simplify(); + + return r; + +} + +/*CG_outputRepr * modified_output_subs_repr(CG_outputBuilder * ocg, const Relation &R, const EQ_Handle &h, Variable_ID v,const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::map<std::string, std::vector<CG_outputRepr *> > unin){ + + + + + } +*/ + + + + + +CG_outputRepr * construct_int_floor(CG_outputBuilder * ocg, const Relation &R, + const GEQ_Handle &h, Variable_ID v, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::map<std::string, std::vector<CG_outputRepr *> > unin) { + + std::set<Variable_ID> excluded_floor_vars; + const_cast<Relation &>(R).setup_names(); // hack + assert(v->kind() == Set_Var); + + int a = h.get_coef(v); + + CG_outputRepr *lhs = ocg->CreateIdent(v->name()); + excluded_floor_vars.insert(v); + std::vector<std::pair<bool, GEQ_Handle> > result2; + CG_outputRepr *repr = NULL; + for (Constr_Vars_Iter cvi(h); cvi; cvi++) + if (cvi.curr_var() != v) { + CG_outputRepr *t; + if (cvi.curr_var()->kind() == Wildcard_Var) { + std::pair<bool, GEQ_Handle> result = find_floor_definition(R, + cvi.curr_var(), excluded_floor_vars); + if (!result.first) { + coef_t coef_ = cvi.curr_coef(); + result2 = find_floor_definition_temp(R, cvi.curr_var(), + excluded_floor_vars); + + for (Constr_Vars_Iter cvi_( + result2[result2.size() - 1].second); cvi_; cvi_++) { + if (cvi_.curr_var()->kind() != Wildcard_Var + && cvi_.curr_var()->kind() != Set_Var) { + t = output_ident(ocg, R, cvi_.curr_var(), + assigned_on_the_fly, unin); + coef_t coef2 = cvi_.curr_coef(); + assert(cvi_.curr_coef() == -1 && a == 1); + repr = ocg->CreateIntegerFloor(t, + ocg->CreateInt(-coef_)); + repr = ocg->CreateTimes(ocg->CreateInt(-coef_), + repr); + + return repr; + + } + + } + + }; + if (!result.first) { + delete repr; + throw omega_error( + "Can't generate bound expression with wildcard not involved in floor definition"); + } + + try { + t = output_inequality_repr(ocg, result.second, + cvi.curr_var(), R, assigned_on_the_fly, unin, + excluded_floor_vars); + } catch (const std::exception &e) { + delete repr; + throw e; + } + } + else + t = output_ident(ocg, R, cvi.curr_var(), assigned_on_the_fly, + unin); + + coef_t coef = cvi.curr_coef(); + if (a > 0) { + if (coef > 0) { + if (coef == 1) + repr = ocg->CreateMinus(repr, t); + else + repr = ocg->CreateMinus(repr, + ocg->CreateTimes(ocg->CreateInt(coef), t)); + } + else { + if (coef == -1) + repr = ocg->CreatePlus(repr, t); + else + repr = ocg->CreatePlus(repr, + ocg->CreateTimes(ocg->CreateInt(-coef), t)); + } + } + else { + if (coef > 0) { + if (coef == 1) + repr = ocg->CreatePlus(repr, t); + else + repr = ocg->CreatePlus(repr, + ocg->CreateTimes(ocg->CreateInt(coef), t)); + } + else { + if (coef == -1) + repr = ocg->CreateMinus(repr, t); + else + repr = ocg->CreateMinus(repr, + ocg->CreateTimes(ocg->CreateInt(-coef), t)); + } + } + } + coef_t c = h.get_const(); + if (c > 0) { + if (a > 0) + repr = ocg->CreateMinus(repr, ocg->CreateInt(c)); + else + repr = ocg->CreatePlus(repr, ocg->CreateInt(c)); + } + else if (c < 0) { + if (a > 0) + repr = ocg->CreatePlus(repr, ocg->CreateInt(-c)); + else + repr = ocg->CreateMinus(repr, ocg->CreateInt(-c)); + } + + if (abs(a) == 1) + ocg->CreateAssignment(0, lhs, repr); + else if (a > 0) + return ocg->CreateAssignment(0, lhs, + ocg->CreateIntegerCeil(repr, ocg->CreateInt(a))); + else + // a < 0 + return ocg->CreateAssignment(0, lhs, + ocg->CreateIntegerFloor(repr, ocg->CreateInt(-a))); + +} + + + + |