diff options
author | Tuowen Zhao <ztuowen@gmail.com> | 2016-09-21 22:35:47 -0600 |
---|---|---|
committer | Tuowen Zhao <ztuowen@gmail.com> | 2016-09-21 22:35:47 -0600 |
commit | ab016596602a4c6bdc27adf01c308b325af221f0 (patch) | |
tree | 4e86bfcf1f38fb00cc58082d540dc3570e0f126b | |
parent | 6983c09937baac3ffb7d3a45c3c5009c0eba7e6c (diff) | |
download | chill-ab016596602a4c6bdc27adf01c308b325af221f0.tar.gz chill-ab016596602a4c6bdc27adf01c308b325af221f0.tar.bz2 chill-ab016596602a4c6bdc27adf01c308b325af221f0.zip |
something that only builds ...
48 files changed, 27465 insertions, 8086 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index ff2bd43..2c6e2dd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -2,21 +2,15 @@ cmake_minimum_required(VERSION 2.8) project(chill) set(CHILL_VERSION 0.2.1) # 2.8 doesn't support project version clause -if(NOT DEFINED ROSEHOME) - message( FATAL_ERROR "ROSEHOME is not set, try use -DROSEHOME" ) -endif() -if (NOT DEFINED BOOSTHOME) - message( FATAL_ERROR "BOOSTHOME is not set, try use -DBOOSTHOME" ) -endif() - find_package(PythonLibs 2.7 REQUIRED) +find_package(LLVM REQUIRED CONFIG) + +add_definitions(${LLVM_DEFINITIONS}) string(TIMESTAMP build_date "\\\"%m/%d/%Y\\\"") set(CORE_LIBS - m rose rt util omega codegen rosecg dl parseRel - boost_date_time boost_filesystem boost_program_options - boost_regex boost_system boost_wave boost_iostreams) + omega codegen chillcg parseRel) set(CORE_SRC src/dep.cc @@ -31,14 +25,37 @@ set(CORE_SRC ) set(IR_CHILL_SRC - src/ir_rose.cc - src/ir_rose_utils.cc + src/ir_clang.cc + src/chill_ast.cc ) set(PYTHON_SRC src/chillmodule.cc ) +llvm_map_components_to_libnames(llvm_libs all) +set(clang_libs + clangTooling + clangFrontendTool + clangFrontend + clangDriver + clangSerialization + clangCodeGen + clangParse + clangSema + clangStaticAnalyzerFrontend + clangStaticAnalyzerCheckers + clangStaticAnalyzerCore + clangAnalysis + clangARCMigrate + clangRewrite + clangRewriteFrontend + clangEdit + clangAST + clangLex + clangBasic + ) + set(COMMON_FLAGS "-DCHILL_BUILD_DATE=\"${build_date}\" -DCHILL_BUILD_VERSION=\"\\\"${CHILL_VERSION}\\\"\"") set(CMAKE_CXX_FLAGS "${COMMON_FLAGS} ${CMAKE_CXX_FLAGS}") @@ -51,18 +68,16 @@ else() ${CMAKE_CURRENT_SOURCE_DIR}/lib/omega/include ${CMAKE_CURRENT_SOURCE_DIR}/lib/parserel/include ${CMAKE_CURRENT_SOURCE_DIR}/lib/codegen/include + ${CMAKE_CURRENT_SOURCE_DIR}/lib/chillcg/include ) endif() -link_directories(${ROSEHOME}/lib ${BOOSTOME}/lib) - include_directories( include - lib/rosecg/include + lib/chillcg/include + lib/iegenlib/src ${OMEGA_INC} - ${ROSEHOME}/include - ${ROSEHOME}/include/rose - ${BOOSTHOME}/include + ${LLVM_INCLUDE_DIRS} ${PYTHON_INCLUDE_DIRS}) add_executable(chill @@ -73,15 +88,17 @@ add_executable(chill target_link_libraries(chill ${CORE_LIBS} + ${llvm_libs} + ${clang_libs} ${PYTHON_LIBRARY}) -add_dependencies(chill omega codegen rosecg parseRel) +add_dependencies(chill omega codegen chillcg parseRel) install(TARGETS chill RUNTIME DESTINATION bin) add_subdirectory(lib/omega) add_subdirectory(lib/codegen) -add_subdirectory(lib/rosecg) +add_subdirectory(lib/chillcg) add_subdirectory(lib/parserel) add_subdirectory(doc) diff --git a/include/chill_ast.hh b/include/chill_ast.hh new file mode 100644 index 0000000..0803254 --- /dev/null +++ b/include/chill_ast.hh @@ -0,0 +1,2365 @@ + + +#ifndef _CHILL_AST_H_ +#define _CHILL_AST_H_ + + +#define CHILL_INDENT_AMOUNT 2 + +#include <iostream> +#include <stdio.h> +#include <string.h> +#include <stdlib.h> +#include <assert.h> +#include <vector> // std::vector + +#include <ir_enums.hh> // for IR_CONDITION_* + +char *parseUnderlyingType( char *sometype ); +char *parseArrayParts( char *sometype ); +bool isRestrict( const char *sometype ); +char *splitTypeInfo( char *underlyingtype ); +char *ulhack( char *brackets ); // change "1024UL" to "1024" +char *restricthack( char *typeinfo ); // remove __restrict__ , MODIFIES the argument! + + +enum CHILL_ASTNODE_TYPE { + CHILLAST_NODETYPE_UNKNOWN=0, + CHILLAST_NODETYPE_SOURCEFILE, + CHILLAST_NODETYPE_TYPEDEFDECL, + CHILLAST_NODETYPE_VARDECL, + // CHILLAST_NODETYPE_PARMVARDECL, not used any more + CHILLAST_NODETYPE_FUNCTIONDECL, + CHILLAST_NODETYPE_RECORDDECL, // struct or union (or class) + CHILLAST_NODETYPE_MACRODEFINITION, + CHILLAST_NODETYPE_COMPOUNDSTMT, + CHILLAST_NODETYPE_LOOP, // AKA ForStmt + CHILLAST_NODETYPE_TERNARYOPERATOR, + CHILLAST_NODETYPE_BINARYOPERATOR, + CHILLAST_NODETYPE_UNARYOPERATOR, + CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR, + CHILLAST_NODETYPE_MEMBEREXPR, // structs/unions + CHILLAST_NODETYPE_DECLREFEXPR, + CHILLAST_NODETYPE_INTEGERLITERAL, + CHILLAST_NODETYPE_FLOATINGLITERAL, + CHILLAST_NODETYPE_IMPLICITCASTEXPR, + CHILLAST_NODETYPE_RETURNSTMT, + CHILLAST_NODETYPE_CALLEXPR, + CHILLAST_NODETYPE_DECLSTMT, + CHILLAST_NODETYPE_PARENEXPR, + CHILLAST_NODETYPE_CSTYLECASTEXPR, + CHILLAST_NODETYPE_CSTYLEADDRESSOF, + CHILLAST_NODETYPE_IFSTMT, + CHILLAST_NODETYPE_SIZEOF, + CHILLAST_NODETYPE_MALLOC, + CHILLAST_NODETYPE_FREE, + CHILLAST_NODETYPE_PREPROCESSING, // comments, #define, #include, whatever else works + CHILLAST_NODETYPE_NOOP, // NO OP + // CUDA specific + CHILLAST_NODETYPE_CUDAMALLOC, + CHILLAST_NODETYPE_CUDAFREE, + CHILLAST_NODETYPE_CUDAMEMCPY, + CHILLAST_NODETYPE_CUDAKERNELCALL, + CHILLAST_NODETYPE_CUDASYNCTHREADS, + CHILLAST_NODETYPE_NULL // explicit non-statement + // TODO + +} ; + +#define CHILLAST_NODETYPE_FORSTMT CHILLAST_NODETYPE_LOOP +#define CHILLAST_NODETYPE_TRANSLATIONUNIT CHILLAST_NODETYPE_SOURCEFILE + +enum CHILL_FUNCTION_TYPE { + CHILL_FUNCTION_CPU = 0, + CHILL_FUNCTION_GPU +}; + +enum CHILL_MEMBER_EXP_TYPE { + CHILL_MEMBER_EXP_DOT = 0, + CHILL_MEMBER_EXP_ARROW +}; + +enum CHILL_PREPROCESSING_TYPE { + CHILL_PREPROCESSING_TYPEUNKNOWN = 0, + CHILL_PREPROCESSING_COMMENT, + CHILL_PREPROCESSING_POUNDDEFINE, + CHILL_PREPROCESSING_POUNDINCLUDE, + CHILL_PREPROCESSING_PRAGMA // unused so far +}; + +enum CHILL_PREPROCESSING_POSITION { // when tied to another statement + CHILL_PREPROCESSING_POSITIONUNKNOWN = 0, + CHILL_PREPROCESSING_LINEBEFORE, // previous line + CHILL_PREPROCESSING_LINEAFTER, // next line + CHILL_PREPROCESSING_TOTHERIGHT, // for this kind of comment, on same line + CHILL_PREPROCESSING_IMMEDIATELYBEFORE // on same line +}; + + + + + +extern const char* Chill_AST_Node_Names[]; // WARNING MUST BE KEPT IN SYNC WITH BELOW LIST + + +// fwd declarations +class chillAST_node; // the generic node. specific types derive from this +class chillAST_NULL; // empty +class chillAST_SourceFile; // ast for an entire source file (translationunit) + +class chillAST_TypedefDecl; +class chillAST_VarDecl; +//class chillAST_ParmVarDecl; +class chillAST_FunctionDecl; +class chillAST_RecordDecl; // structs and unions (and classes?) +class chillAST_MacroDefinition; +class chillAST_CompoundStmt; // just a bunch of other statements +class chillAST_ForStmt; // AKA a LOOP +class chillAST_TernaryOperator; +class chillAST_BinaryOperator; +class chillAST_ArraySubscriptExpr; +class chillAST_MemberExpr; +class chillAST_DeclRefExpr; +class chillAST_IntegerLiteral; +class chillAST_FloatingLiteral; +class chillAST_UnaryOperator; +class chillAST_ImplicitCastExpr; +class chillAST_CStyleCastExpr; +class chillAST_CStyleAddressOf; +class chillAST_ReturnStmt; +class chillAST_CallExpr; +class chillAST_ParenExpr; +class chillAST_Sizeof; +class chillAST_Malloc; +class chillAST_Free; +class chillAST_NoOp; +class chillAST_CudaMalloc; +class chillAST_CudaFree; +class chillAST_CudaMemcpy; +class chillAST_CudaKernelCall; +class chillAST_CudaSyncthreads; +class chillAST_Preprocessing; + +typedef std::vector<chillAST_VarDecl *> chillAST_SymbolTable; // typedef +typedef std::vector<chillAST_TypedefDecl *> chillAST_TypedefTable; // typedef + +bool symbolTableHasVariableNamed( chillAST_SymbolTable *table, const char *name ); // fwd decl +chillAST_VarDecl *symbolTableFindVariableNamed( chillAST_SymbolTable *table, const char *name ); // fwd decl TODO too many similar named functions + +void printSymbolTable( chillAST_SymbolTable *st ); // fwd decl +void printSymbolTableMoreInfo( chillAST_SymbolTable *st ); // fwd decl + + +chillAST_node *lessthanmacro( chillAST_node *left, chillAST_node *right); // fwd declaration +chillAST_SymbolTable *addSymbolToTable( chillAST_SymbolTable *st, chillAST_VarDecl *vd ); // fwd decl +chillAST_TypedefTable *addTypedefToTable( chillAST_TypedefTable *tt, chillAST_TypedefDecl *td ); // fwd decl + + +bool streq( const char *a, const char *b); // fwd decl +void chillindent( int i, FILE *fp ); // fwd declaration +void insertNewDeclAtLocationOfOldIfNeeded( chillAST_VarDecl *newdecl, chillAST_VarDecl *olddecl); + +chillAST_DeclRefExpr *buildDeclRefExpr( chillAST_VarDecl *); + + + + + + +// an actual chill ast. +// nodes based on clang AST which are in turn based on C++ + +class chillAST_node { // generic node. a tree of these is the AST. this is virtual (can't instantiate) +public: + + static int chill_scalar_counter; // for manufactured scalars + static int chill_array_counter ; // for manufactured arrays + static int chill_pointer_counter ; // for manufactured arrays + + + CHILL_ASTNODE_TYPE asttype; + + bool isSourceFile() { return (asttype == CHILLAST_NODETYPE_SOURCEFILE); }; + bool isTypeDefDecl() { return (asttype == CHILLAST_NODETYPE_TYPEDEFDECL); }; + bool isVarDecl() { return (asttype == CHILLAST_NODETYPE_VARDECL); }; + bool isFunctionDecl() { return (asttype == CHILLAST_NODETYPE_FUNCTIONDECL); }; + bool isRecordDecl() { return (asttype == CHILLAST_NODETYPE_RECORDDECL); }; + bool isMacroDefinition() { return (asttype == CHILLAST_NODETYPE_MACRODEFINITION); }; + bool isCompoundStmt() { return (asttype == CHILLAST_NODETYPE_COMPOUNDSTMT); }; + bool isLoop() { return (asttype == CHILLAST_NODETYPE_LOOP); }; // AKA ForStmt + bool isForStmt() { return (asttype == CHILLAST_NODETYPE_LOOP); }; // AKA Loop + bool isIfStmt() { return (asttype == CHILLAST_NODETYPE_IFSTMT); }; + bool isTernaryOperator() { return (asttype == CHILLAST_NODETYPE_TERNARYOPERATOR);}; + bool isBinaryOperator() { return (asttype == CHILLAST_NODETYPE_BINARYOPERATOR); }; + bool isUnaryOperator() { return (asttype == CHILLAST_NODETYPE_UNARYOPERATOR); }; + bool isArraySubscriptExpr() { return (asttype == CHILLAST_NODETYPE_ARRAYSUBSCRIPTEXPR); }; + bool isMemberExpr() { return (asttype == CHILLAST_NODETYPE_MEMBEREXPR); }; + bool isDeclRefExpr() { return (asttype == CHILLAST_NODETYPE_DECLREFEXPR); }; + bool isIntegerLiteral() { return (asttype == CHILLAST_NODETYPE_INTEGERLITERAL); }; + bool isFloatingLiteral() { return (asttype == CHILLAST_NODETYPE_FLOATINGLITERAL); }; + bool isImplicitCastExpr() { return (asttype == CHILLAST_NODETYPE_IMPLICITCASTEXPR); }; + bool isReturnStmt() { return (asttype == CHILLAST_NODETYPE_RETURNSTMT); }; + bool isCallExpr() { return (asttype == CHILLAST_NODETYPE_CALLEXPR); }; + bool isParenExpr() { return (asttype == CHILLAST_NODETYPE_PARENEXPR); }; + bool isSizeof() { return (asttype == CHILLAST_NODETYPE_SIZEOF); }; + bool isMalloc() { return (asttype == CHILLAST_NODETYPE_MALLOC); }; + bool isFree() { return (asttype == CHILLAST_NODETYPE_FREE); }; + bool isPreprocessing() { return (asttype == CHILLAST_NODETYPE_PREPROCESSING); }; + bool isNoOp() { return (asttype == CHILLAST_NODETYPE_NOOP); }; + bool isNull() { return (asttype == CHILLAST_NODETYPE_NULL); }; + bool isCStyleCastExpr() { return (asttype == CHILLAST_NODETYPE_CSTYLECASTEXPR); }; + bool isCStyleAddressOf() { return (asttype == CHILLAST_NODETYPE_CSTYLEADDRESSOF); }; + bool isCudaMalloc() { return (asttype == CHILLAST_NODETYPE_CUDAMALLOC); }; + bool isCudaFree() { return (asttype == CHILLAST_NODETYPE_CUDAFREE); }; + bool isCudaMemcpy() { return (asttype == CHILLAST_NODETYPE_CUDAMEMCPY); }; + bool isCudaKERNELCALL() { return (asttype == CHILLAST_NODETYPE_CUDAKERNELCALL); }; + bool isCudaSYNCTHREADS() { return (asttype == CHILLAST_NODETYPE_CUDASYNCTHREADS); }; + + bool isDeclStmt() { return (asttype == CHILLAST_NODETYPE_DECLSTMT); }; // doesn't exist + + bool isConstant() { return (asttype == CHILLAST_NODETYPE_INTEGERLITERAL) || (asttype == CHILLAST_NODETYPE_FLOATINGLITERAL); } + + + virtual bool isAssignmentOp() { return false; }; + virtual bool isComparisonOp() { return false; }; + virtual bool isNotLeaf() { return false; }; + virtual bool isLeaf() { return true; }; + virtual bool isParmVarDecl() { return false; }; + + virtual bool isPlusOp() { return false; }; + virtual bool isMinusOp() { return false; }; + virtual bool isPlusMinusOp() { return false; }; + virtual bool isMultDivOp() { return false; }; + + virtual bool isAStruct() { return false; }; + virtual bool isAUnion() { return false; }; + + virtual bool hasSymbolTable() { return false; } ; // most nodes do NOT have a symbol table + virtual bool hasTypedefTable() { return false; } ; // most nodes do NOT have a typedef table + virtual chillAST_SymbolTable *getSymbolTable() { return NULL; } // most nodes do NOT have a symbol table + + virtual chillAST_VarDecl *findVariableNamed( const char *name ); // recursive + + chillAST_RecordDecl *findRecordDeclNamed( const char *name ); // recursive + + // void addDecl( chillAST_VarDecl *vd); // recursive, adds to first symbol table it can find + + // TODO decide how to hide some data + chillAST_node *parent; + bool isFromSourceFile; // false = #included + char *filename; // file this node is from + + void segfault() { fprintf(stderr, "segfaulting on purpose\n"); int *i=0; int j = i[0]; }; // seg fault + int getNumChildren() { return children.size(); }; + std::vector<chillAST_node*> children; + std::vector<chillAST_node*> getChildren() { return children; } ; // not usually useful + void setChildren( std::vector<chillAST_node*>&c ) { children = c; } ; // does not set parent. probably should + chillAST_node *getChild( int which) { return children[which]; }; + void setChild( int which, chillAST_node *n ) { children[which] = n; children[which]->parent = this; } ; + + char *metacomment; // for compiler internals, formerly a comment + void setMetaComment( char *c ) { metacomment = strdup(c); }; + + std::vector<chillAST_Preprocessing*> preprocessinginfo; + + virtual void addChild( chillAST_node* c) { + //if (c->isFunctionDecl()) fprintf(stderr, "addchild FunctionDecl\n"); + c->parent = this; + // check to see if it's already there + for (int i=0; i<children.size(); i++) { + if (c == children[i]) { + //fprintf(stderr, "addchild ALREADY THERE\n"); + return; // already there + } + } + children.push_back(c); + } ; // not usually useful + + virtual void insertChild(int i, chillAST_node* node) { + //fprintf(stderr, "%s inserting child of type %s at location %d\n", getTypeString(), node->getTypeString(), i); + node->parent = this; + children.insert( children.begin()+i, node ); + }; + + virtual void removeChild(int i) { + children.erase( children.begin()+i ); + }; + + int findChild( chillAST_node *c ) { + for (int i=0; i<children.size(); i++) { + if (children[i] == c) return i; + } + return -1; + } + + virtual void replaceChild( chillAST_node *old, chillAST_node *newchild ) { + fprintf(stderr,"(%s) forgot to implement replaceChild() ... using generic\n" ,Chill_AST_Node_Names[asttype]); + fprintf(stderr, "%d children\n", children.size()); + for (int i=0; i<children.size(); i++) { + if (children[i] == old) { + children[i] = newchild; + newchild->setParent( this ); + return; + } + } + fprintf(stderr, "%s %p generic replaceChild called with oldchild that was not a child\n", + getTypeString(), this) ; + fprintf(stderr, "printing\n"); + print(); fprintf(stderr, "\nchild: "); + if (!old) fprintf(stderr, "oldchild NULL!\n"); + old->print(); fprintf(stderr, "\nnew: "); + newchild->print(); fprintf(stderr, "\n"); + segfault(); // make easier for gdb + }; + + virtual void loseLoopWithLoopVar( char *var ) { + // walk tree. If a loop has this loop variable, replace the loop with the loop body, + // removing the loop. The loop will be spread across a bunch of cores that will each + // calculate their own loop variable. + + // things that can not have loops as substatements can have a null version of this method + // things that have more complicated sets of "children" will have specialized versions + + // this is the generic version of the method. It just recurses among its children. + // ForStmt is the only one that can actually remove itself. When it does, it will + // potentially change the children vector, which is not the simple array it might appear. + // so you have to make a copy of the vector to traverse + + std::vector<chillAST_node*> dupe = children; // simple enough? + //fprintf(stderr, "node XXX has %d children\n", dupe.size()); + //fprintf(stderr, "generic node %s has %d children\n", getTypeString(), dupe.size()); + for (int i=0; i<dupe.size(); i++) { // recurse on all children + dupe[i]->loseLoopWithLoopVar( var ); + } + } + + virtual int evalAsInt() { + fprintf(stderr,"(%s) can't be evaluated as an integer??\n", Chill_AST_Node_Names[asttype]); + print(); fprintf(stderr, "\n"); + segfault(); + } + + virtual const char* getUnderlyingType() { + fprintf(stderr,"(%s) forgot to implement getUnderlyingType()\n", Chill_AST_Node_Names[asttype]); + dump(); + print(); + fprintf(stderr, "\n\n"); + segfault(); + }; + + virtual chillAST_VarDecl* getUnderlyingVarDecl() { + fprintf(stderr,"(%s) forgot to implement getUnderlyingVarDecl()\n", Chill_AST_Node_Names[asttype]); + dump(); + print(); + fprintf(stderr, "\n\n"); + segfault(); + }; + + + virtual chillAST_node *findref(){// find the SINGLE constant or data reference at this node or below + fprintf(stderr,"(%s) forgot to implement findref()\n" ,Chill_AST_Node_Names[asttype]); + dump(); + print(); + fprintf(stderr, "\n\n"); + segfault(); + }; + + virtual void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ) { + fprintf(stderr,"(%s) forgot to implement gatherArrayRefs()\n" ,Chill_AST_Node_Names[asttype]); + dump(); + print(); + fprintf(stderr, "\n\n"); + }; + + // TODO we MIGHT want the VarDecl // NOTHING IMPLEMENTS THIS? ??? + virtual void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) { + fprintf(stderr,"(%s) forgot to implement gatherScalarRefs()\n" ,Chill_AST_Node_Names[asttype]); + dump(); + print(); + fprintf(stderr, "\n\n"); + }; + + virtual void gatherLoopIndeces( std::vector<chillAST_VarDecl*> &indeces ) { // recursive walk parent links, looking for loops, and grabbing the declRefExpr in the loop init and cond. + // you can quit when you get to certain nodes + + //fprintf(stderr, "%s::gatherLoopIndeces()\n", getTypeString()); + + if (isSourceFile() || isFunctionDecl() ) return; // end of the line + + // just for debugging + //if (parent) { + // fprintf(stderr, "%s has parent of type %s\n", getTypeString(), parent->getTypeString()); + //} + //else fprintf(stderr, "this %s %p has no parent???\n", getTypeString(), this); + + + if (!parent) return; // should not happen, but be careful + + // for most nodes, this just recurses upwards + //fprintf(stderr, "%s::gatherLoopIndeces() %p recursing up\n", this); + parent->gatherLoopIndeces( indeces ); + } + + + chillAST_ForStmt* findContainingLoop() { // recursive walk parent links, looking for loops + //fprintf(stderr, "%s::findContainingLoop() ", getTypeString()); + //if (parent) fprintf(stderr, "parents is a %s\n", parent->getTypeString()); + //else fprintf(stderr, "no parent\n"); + // do not check SELF type, as we may want to find the loop containing a loop + if (!parent) return NULL; + if (parent->isForStmt()) return (chillAST_ForStmt*)parent; + return parent->findContainingLoop(); // recurse upwards + } + + chillAST_node* findContainingNonLoop() { // recursive walk parent links, avoiding loops + fprintf(stderr, "%s::findContainingNonLoop() ", getTypeString()); + //if (parent) fprintf(stderr, "parent is a %s\n", parent->getTypeString()); + //else fprintf(stderr, "no parent\n"); + // do not check SELF type, as we may want to find the loop containing a loop + if (!parent) return NULL; + if (parent->isCompoundStmt() && parent->getParent()->isForStmt()) return parent->getParent()->findContainingNonLoop(); // keep recursing + if (parent->isForStmt()) return parent->findContainingNonLoop(); // keep recursing + return (chillAST_node*)parent; // return non-loop + } + + // TODO gather loop init and cond (and if cond) like gatherloopindeces + + virtual void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ){ // both scalar and arrays + fprintf(stderr,"(%s) forgot to implement gatherDeclRefExpr()\n" ,Chill_AST_Node_Names[asttype]); + }; + + + + virtual void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ) { + fprintf(stderr,"(%s) forgot to implement gatherVarUsage()\n" ,Chill_AST_Node_Names[asttype]); + }; + + virtual void gatherVarLHSUsage( std::vector<chillAST_VarDecl*> &decls ) { + fprintf(stderr,"(%s) forgot to implement gatherVarLHSUsage()\n" ,Chill_AST_Node_Names[asttype]); + }; + + + virtual void gatherVarDecls( std::vector<chillAST_VarDecl*> &decls ) { // ACTUAL Declaration + fprintf(stderr,"(%s) forgot to implement gatherVarDecls()\n" ,Chill_AST_Node_Names[asttype]); + }; + + + virtual void gatherVarDeclsMore( std::vector<chillAST_VarDecl*> &decls ) { // even if the decl itself is not in the ast. + fprintf(stderr,"(%s) forgot to implement gatherVarDeclsMore()\n" ,Chill_AST_Node_Names[asttype]); + }; + + virtual void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ) { // ACTUAL Declaration + fprintf(stderr,"(%s) forgot to implement gatherScalarVarDecls()\n" ,Chill_AST_Node_Names[asttype]); + }; + + virtual void gatherArrayVarDecls( std::vector<chillAST_VarDecl*> &decls ) { // ACTUAL Declaration + fprintf(stderr,"(%s) forgot to implement gatherArrayVarDecls()\n" ,Chill_AST_Node_Names[asttype]); + }; + + virtual chillAST_VarDecl *findArrayDecl( const char *name ) { // scoping TODO + if (!hasSymbolTable()) return parent->findArrayDecl( name ); // most things + else + fprintf(stderr,"(%s) forgot to implement gatherArrayVarDecls()\n" ,Chill_AST_Node_Names[asttype]); + } + + + virtual void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) { + fprintf(stderr,"(%s) forgot to implement replaceVarDecls()\n" ,Chill_AST_Node_Names[asttype]); + }; + + virtual bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ) { + // this just looks for ForStmts with preferred index metacomment attached + fprintf(stderr,"(%s) forgot to implement findLoopIndexesToReplace()\n" ,Chill_AST_Node_Names[asttype]); + return false; + } + + + virtual chillAST_node* constantFold() { // hacky. TODO. make nice + fprintf(stderr,"(%s) forgot to implement constantFold()\n" ,Chill_AST_Node_Names[asttype]); + exit(-1); ; + }; + + virtual chillAST_node* clone() { // makes a deep COPY (?) + fprintf(stderr,"(%s) forgot to implement clone()\n" ,Chill_AST_Node_Names[asttype]); + exit(-1); ; + }; + virtual void dump( int indent=0, FILE *fp = stderr ) { + fflush(fp); + fprintf(fp,"(%s) forgot to implement dump()\n" ,Chill_AST_Node_Names[asttype]); };// print ast + + virtual void print( int indent=0, FILE *fp = stderr ) { + fflush(fp); + //fprintf(stderr, "generic chillAST_node::print() called!\n"); + //fprintf(stderr, "asttype is %d\n", asttype); + fprintf(fp, "\n"); + chillindent(indent, fp); + fprintf(fp,"(%s) forgot to implement print()\n" ,Chill_AST_Node_Names[asttype]); + };// print CODE + + virtual void printName( int indent=0, FILE *fp = stderr ) { + fflush(fp); + //fprintf(stderr, "generic chillAST_node::printName() called!\n"); + //fprintf(stderr, "asttype is %d\n", asttype); + fprintf(fp, "\n"); + chillindent(indent, fp); + fprintf(fp,"(%s) forgot to implement printName()\n" ,Chill_AST_Node_Names[asttype]); + };// print CODE + + virtual char *stringRep(int indent=0 ) { // the ast's print version + fflush(stdout); + // chillindent(indent, fp); TODO + fprintf(stderr,"(%s) forgot to implement stringRep()\n" ,Chill_AST_Node_Names[asttype]); + segfault(); + } + + + virtual void printonly( int indent=0, FILE *fp = stderr ) { print( indent, fp); }; + + //virtual void printString( std::string &s ) { + // fprintf(stderr,"(%s) forgot to implement printString()\n" ,Chill_AST_Node_Names[asttype]); + //} + + + virtual void get_top_level_loops( std::vector<chillAST_ForStmt *> &loops) { + int n = children.size(); + //fprintf(stderr, "get_top_level_loops of a %s with %d children\n", getTypeString(), n); + for (int i=0; i<n; i++) { + //fprintf(stderr, "child %d is a %s\n", i, children[i]->getTypeString()); + if (children[i]->isForStmt()) { + loops.push_back( ((chillAST_ForStmt *)(children[i])) ); + } + } + //fprintf(stderr, "found %d top level loops\n", loops.size()); + } + + + virtual void repairParentChild() { // for nodes where all subnodes are children + int n = children.size(); + for (int i=0; i<n; i++) { + if (children[i]->parent != this) { + fprintf(stderr, "fixing child %s that didn't know its parent\n", children[i]->getTypeString()); + children[i]->parent = this; + } + } + } + + + + virtual void get_deep_loops( std::vector<chillAST_ForStmt *> &loops) { // this is probably broken - returns ALL loops under it + int n = children.size(); + //fprintf(stderr, "get_deep_loops of a %s with %d children\n", getTypeString(), n); + for (int i=0; i<n; i++) { + //fprintf(stderr, "child %d is a %s\n", i, children[i]->getTypeString()); + children[i]->get_deep_loops( loops ); + } + //fprintf(stderr, "found %d deep loops\n", loops.size()); + } + + + // generic for chillAST_node with children + virtual void find_deepest_loops( std::vector<chillAST_ForStmt *> &loops) { // returns DEEPEST nesting of loops + std::vector<chillAST_ForStmt *>deepest; // deepest below here + + int n = children.size(); + //fprintf(stderr, "find_deepest_loops of a %s with %d children\n", getTypeString(), n); + for (int i=0; i<n; i++) { + std::vector<chillAST_ForStmt *> subloops; // loops below here among a child of mine + + //fprintf(stderr, "child %d is a %s\n", i, children[i]->getTypeString()); + children[i]->find_deepest_loops( subloops ); + + if (subloops.size() > deepest.size()) { + deepest = subloops; + } + } + + // append deepest we see at this level to loops + for ( int i=0; i<deepest.size(); i++) { + loops.push_back( deepest[i] ); + } + + //fprintf(stderr, "found %d deep loops\n", loops.size()); + + } + + + + + const char *getTypeString() { return Chill_AST_Node_Names[asttype]; } ; + int getType() { return asttype; }; + void setParent( chillAST_node *p) { parent = p; } ; + chillAST_node *getParent() { return parent; } ; + + chillAST_SourceFile *getSourceFile() { + if (isSourceFile()) return ((chillAST_SourceFile *)this); + if (parent != NULL) return parent->getSourceFile(); + fprintf(stderr, "UHOH, getSourceFile() called on node %p %s that does not have a parent and is not a source file\n", this, this->getTypeString()); + this->print(); printf("\n\n"); fflush(stdout); + exit(-1); + } + + virtual chillAST_node *findDatatype( char *t ) { + fprintf(stderr, "%s looking for datatype %s\n", getTypeString(), t); + if (parent != NULL) return parent->findDatatype(t); // most nodes do this + return NULL; + } + + + virtual chillAST_SymbolTable *addVariableToSymbolTable( chillAST_VarDecl *vd ) { + if (!parent) { + fprintf(stderr, "%s with no parent addVariableToSymbolTable()\n", getTypeString()); + exit(-1); + } + //fprintf(stderr, "%s::addVariableToSymbolTable() (default) headed up\n", getTypeString()); + return parent->addVariableToSymbolTable( vd ); // default, defer to parent + } + + virtual void addTypedefToTypedefTable( chillAST_TypedefDecl *tdd ) { + parent->addTypedefToTypedefTable( tdd ); // default, defer to parent + } + + void walk_parents() { + fprintf(stderr, "wp: (%s) ", getTypeString()); + print(); printf("\n"); fflush(stdout); + if (isSourceFile()) { fprintf(stderr, "(top sourcefile)\n\n"); return;} + + if (parent) parent->walk_parents(); + else fprintf(stderr, "UHOH, %s has no parent??\n", getTypeString()); + return; + } + + virtual chillAST_node *getEnclosingStatement( int level = 0 ); + virtual chillAST_VarDecl *multibase() { + fprintf(stderr,"(%s) forgot to implement multibase()\n", Chill_AST_Node_Names[asttype]); + exit(-1); + } + virtual chillAST_node *multibase2() { + fprintf(stderr,"(%s) forgot to implement multibase2()\n", Chill_AST_Node_Names[asttype]); + exit(-1); + } + + + virtual void gatherStatements( std::vector<chillAST_node*> &statements ) { + fprintf(stderr,"(%s) forgot to implement gatherStatements()\n" ,Chill_AST_Node_Names[asttype]); + dump();fflush(stdout); + print(); + fprintf(stderr, "\n\n"); + } + + + virtual bool isSameAs( chillAST_node *other ){ // for tree comparison + fprintf(stderr,"(%s) forgot to implement isSameAs()\n" ,Chill_AST_Node_Names[asttype]); + dump(); fflush(stdout); + print(); + fprintf(stderr, "\n\n"); } + + void printPreprocBEFORE( int indent, FILE *fp ); + void printPreprocAFTER( int indent, FILE *fp ); + + + +}; + +class chillAST_NULL: public chillAST_node { // NOOP? +public: + chillAST_NULL(chillAST_node *p = NULL) { parent = p; asttype = CHILLAST_NODETYPE_NULL; }; + void print( int indent=0, FILE *fp = stderr ) { + chillindent( indent, fp ); + fprintf(fp, "/* (NULL statement); */ "); + fflush(fp); + } + void dump( int indent=0, FILE *fp = stderr ) { + chillindent( indent, fp ); + fprintf(fp, "(NULL statement) "); fflush(fp); + } +}; + + +class chillAST_Preprocessing: public chillAST_node { +public: + // variables that are special for this type of node + CHILL_PREPROCESSING_POSITION position; + CHILL_PREPROCESSING_TYPE pptype; + char *blurb; + + // constructors + chillAST_Preprocessing(); // not sure what this is good for + chillAST_Preprocessing( CHILL_PREPROCESSING_POSITION pos, CHILL_PREPROCESSING_TYPE t, char *text ); + + // other methods particular to this type of node + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + //void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc +}; + + +//typedef is a keyword in the C and C++ programming languages. The purpose of typedef is to assign alternative names to existing types, most often those whose standard declaration is cumbersome, potentially confusing, or likely to vary from one implementation to another. +class chillAST_TypedefDecl: public chillAST_node { +private: + bool isStruct; + bool isUnion; + char *structname; // get rid of this? + +public: + char *newtype; // the new type name ?? + char *underlyingtype; // float, int, "struct bubba" ? + char *arraypart; // string like "[1234][56]" ?? + + chillAST_RecordDecl *rd; // if it's a struct, point to the recorddecl ?? + // TODO what if "typedef int[10] tenints; " ?? + void setStructInfo( chillAST_RecordDecl *arrdee ) { rd = arrdee; }; + chillAST_RecordDecl * getStructDef(); + + + bool isAStruct() { return isStruct; }; + bool isAUnion() { return isUnion; }; + void setStruct(bool tf) { isStruct = tf; fprintf(stderr, "%s isStruct %d\n", structname, isStruct); }; + void setUnion( bool tf) { isUnion = tf; }; + void setStructName( const char *newname) { structname = strdup(newname); }; + char *getStructName( ) { return structname; }; + bool nameis( const char *n ) { return !strcmp(n, structname); }; + + // special for struct/unions rethink TODO + std::vector<chillAST_VarDecl *> subparts; + chillAST_VarDecl *findSubpart( const char *name ); + + //TODO hide data, set/get type and alias + chillAST_TypedefDecl(); + chillAST_TypedefDecl(char *t, char *nt, chillAST_node *p); + chillAST_TypedefDecl(char *t, char *nt, char *a, chillAST_node *par); + + const char* getUnderlyingType() { fprintf(stderr, "TypedefDecl getUnderLyingType()\n"); return underlyingtype; }; + //virtual chillAST_VarDecl* getUnderlyingVarDecl() { return this; }; // ?? + + void dump( int indent=0, FILE *fp = stderr ) { + fprintf(fp, "(TypedefDecl %s %s %s)\n", underlyingtype, newtype, arraypart); }; + void print( int indent=0, FILE *fp = stderr ) ; + //void printString( std::string &s ); + +}; + + +class chillAST_VarDecl: public chillAST_node { +public: + char *vartype; // should probably be an enum, except it's used for unnamed structs too + + chillAST_RecordDecl *vardef;// the thing that says what the struct looks like + chillAST_TypedefDecl *typedefinition; // NULL for float, int, etc. + chillAST_RecordDecl * getStructDef(); // TODO make vardef private? + + //bool insideAStruct; // this variable is itself part of a struct + + char *underlyingtype; + char *varname; + char *arraypart; // [ 12 ] [ 34 ] if that is how it was defined + char *arraypointerpart; + char *arraysetpart; + void splitarraypart(); + + int numdimensions; + int *arraysizes; // TODO + bool knownArraySizes; // if this float *a or float a[128] ? true means we know ALL dimensions + int cudamallocsize; // usually specified in lua/python transformation file + + bool isRestrict; // C++ __restrict__ + bool isShared; // CUDA __shared__ + bool isDevice; // CUDA __device__ + bool isStruct; + + int isAParameter; + bool byreference; + void setByReference( bool tf ) { byreference = tf; fprintf(stderr, "byref %d\n", tf); }; + + bool isABuiltin; // if variable is builtin, we don't need to declare it + void *uniquePtr; // DO NOT REFERENCE THROUGH THIS! just used to differentiate declarations + bool isArray() { return (numdimensions != 0); }; + bool isAStruct() { return (isStruct || (typedefinition && typedefinition->isAStruct())); } + void setStruct( bool b ) {isStruct = b;/*fprintf(stderr,"vardecl %s IS A STRUCT\n",varname);*/ }; + bool isPointer() { return isArray() && !knownArraySizes; } // + + bool knowAllDimensions() { return knownArraySizes; } ; + + chillAST_node *init; + void setInit( chillAST_node *i ) { init = i; i->setParent(this); }; + bool hasInit() { return init != NULL; }; + chillAST_node *getInit() { return init; }; + + chillAST_VarDecl(); + chillAST_VarDecl( const char *t, const char *n, const char *a, chillAST_node *p); + chillAST_VarDecl( const char *t, const char *n, const char *a, void *ptr, chillAST_node *p); + chillAST_VarDecl( chillAST_TypedefDecl *tdd, const char *n, const char *arraypart, chillAST_node *par); + chillAST_VarDecl( chillAST_RecordDecl *astruct, const char *n, const char *arraypart, chillAST_node *par); + + void dump( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ); + void printName( int indent=0, FILE *fp = stderr ); + bool isParmVarDecl() { return( isAParameter == 1 ); }; + bool isBuiltin() { return( isABuiltin == 1 ); }; // designate variable as a builtin + void setLocation( void *ptr ) { uniquePtr = ptr; } ; + + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ) {}; // does nothing + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ) {}; // does nothing + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) {}; + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + const char* getUnderlyingType() { /* fprintf(stderr, "VarDecl getUnderLyingType()\n"); */return underlyingtype; }; + virtual chillAST_VarDecl* getUnderlyingVarDecl() { return this; }; + + chillAST_node* constantFold(); + chillAST_node* clone(); + +}; + + +class chillAST_DeclRefExpr: public chillAST_node { +public: + // variables that are special for this type of node + char *declarationType; + char *declarationName; + chillAST_node *decl; // the declaration of this variable or function ... uhoh + //char *functionparameters; // TODO probably should split this node into 2 types, one for variables, one for functions + + // constructors + chillAST_DeclRefExpr(); + chillAST_DeclRefExpr( const char *variablename, chillAST_node *p); + chillAST_DeclRefExpr( const char *vartype, const char *variablename, chillAST_node *p); + chillAST_DeclRefExpr( const char *vartype, const char *variablename, chillAST_node *dec, chillAST_node *p); + chillAST_DeclRefExpr( chillAST_VarDecl *vd, chillAST_node *p=NULL); + chillAST_DeclRefExpr( chillAST_FunctionDecl *fd, chillAST_node *p=NULL); + + // other methods particular to this type of node + bool operator!=( chillAST_DeclRefExpr &other ) { return decl != other.decl ; }; + bool operator==( chillAST_DeclRefExpr &other ) { return decl == other.decl ; }; // EXACT SAME VARECL BY ADDRESS + + chillAST_node *getDecl() { return decl; }; + + chillAST_VarDecl *getVarDecl() { + if (!decl) return NULL; // should never happen + if (decl->isVarDecl()) return (chillAST_VarDecl *)decl; + return NULL; + }; + + chillAST_FunctionDecl *getFunctionDecl() { + if (!decl) return NULL; // should never happen + if (decl->isFunctionDecl()) return (chillAST_FunctionDecl *)decl; + return NULL; + }; + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE + void dump( int indent=0, FILE *fp = stderr ); // print ast + char *stringRep(int indent=0 ); + + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ) {}; // do nothing + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ); + + // this is the AST node where these 2 differ + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ) {}; // does nothing, to get the cvardecl using this method, the actual vardecl must be in the AST + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ); // returns the decl this declrefexpr references, even if the decl is not in the AST + + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + chillAST_node *findref(){return this;}// find the SINGLE constant or data reference at this node or below + + const char* getUnderlyingType() {fprintf(stderr, "DeclRefExpr getUnderLyingType()\n"); return decl->getUnderlyingType();}; + + virtual chillAST_VarDecl* getUnderlyingVarDecl() { return decl->getUnderlyingVarDecl(); } // functions?? TODO + + chillAST_VarDecl* multibase(); + chillAST_node *multibase2() { return (chillAST_node *)multibase(); } +}; + + + + + +class chillAST_CompoundStmt: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_SymbolTable *symbol_table; // symbols defined inside this compound statement + chillAST_TypedefTable *typedef_table; + + bool hasSymbolTable() { return true; } ; + bool hasTypeDefTable() { return true; } ; + chillAST_node *findDatatype( char *t ) { + fprintf(stderr, "chillAST_CompoundStmt::findDatatype( %s )\n", t); + if (typedef_table) { + for (int i=0; i< typedef_table->size(); i++) { + chillAST_TypedefDecl *tdd = (*typedef_table)[i]; + if (tdd->nameis( t )) return tdd; + } + } + if (parent) return parent->findDatatype(t); + return NULL; // should not happen + } + + chillAST_SymbolTable *getSymbolTable() { return symbol_table; } + + chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_CompoundStmt method + //fprintf(stderr, "\nchillAST_CompoundStmt addVariableToSymbolTable( %s )\n", vd->varname); + symbol_table = addSymbolToTable( symbol_table, vd ); + //printSymbolTable( symbol_table ); + return symbol_table; + } + + void addTypedefToTypedefTable( chillAST_TypedefDecl *tdd ) { + typedef_table = addTypedefToTable( typedef_table, tdd ); + } + + // constructors + chillAST_CompoundStmt(); // never has any args ??? + + // other methods particular to this type of node + + + // required methods + void replaceChild( chillAST_node *old, chillAST_node *newchild ); + void dump( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ); + chillAST_node* constantFold(); + chillAST_node* clone(); + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ); + void loseLoopWithLoopVar( char *var ); // special case this for not for debugging + + void gatherStatements( std::vector<chillAST_node*> &statements ); +}; + + + + +class chillAST_RecordDecl: public chillAST_node { // declaration of the shape of a struct or union +private: + char *name; // could be NULL? for unnamed structs? + char *originalname; + bool isStruct; + + bool isUnion; + std::vector<chillAST_VarDecl *> subparts; + +public: + chillAST_RecordDecl(); + chillAST_RecordDecl( const char *nam, chillAST_node *p ); + chillAST_RecordDecl( const char *nam, const char *orig, chillAST_node *p ); + + void setName( const char *newname) { name = strdup(newname); }; + char *getName( ) { return name; }; + + bool isAUnion() { return isUnion; }; + bool isAStruct() { return isStruct; }; + bool isUnnamed; + void setUnnamed( bool b ) { isUnnamed = b; }; + + + void setStruct(bool tf) { isStruct = tf; }; + //fprintf(stderr, "%s isStruct %d\n", structname, isStruct); }; + void setUnion( bool tf) { isUnion = tf; }; + + chillAST_SymbolTable *addVariableToSymbolTable( chillAST_VarDecl *vd ); // RecordDecl does NOTHING + + int numSubparts() { return subparts.size(); }; + void addSubpart( chillAST_VarDecl *s ) { subparts.push_back(s); }; + chillAST_VarDecl *findSubpart( const char *name ); + chillAST_VarDecl *findSubpartByType( const char *typ ); + + void dump( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ) ; + void printStructure( int indent=0, FILE *fp = stderr ) ; +}; + + + + +class chillAST_FunctionDecl: public chillAST_node { +private: + chillAST_CompoundStmt *body; // always a compound statement? + CHILL_FUNCTION_TYPE function_type; // CHILL_FUNCTION_CPU or CHILL_FUNCTION_GPU + bool externfunc; // function is external + bool builtin; // function is a builtin + bool forwarddecl; + +public: + char *returnType; + char *functionName; + + // parameters + int numParameters() { return parameters.size(); } ; + chillAST_SymbolTable parameters; + + // this is probably a mistake, but symbol_table here is pointing to BODY'S symbol table + //chillAST_SymbolTable *symbol_table; // symbols defined inside this function. REALLY the body's symbol table? + + chillAST_TypedefTable *typedef_table; // function typedef table + + + bool hasSymbolTable() { return true; } ; // COULD HAVE + bool hasTypeDefTable(){ return true; } ; // COULD HAVE + + + //char *parametertypes; // a single string?? + void printParameterTypes( FILE *fp ); + void setName( char *n ) { functionName = strdup(n); /* probable memory leak */ }; + + void setBuiltin() { builtin = true; } ; // designate function as a builtin + bool isBuiltin() { return builtin; } ; // report whether is a builtin + + void setExtern() { externfunc = true; }; // designate function as external + bool isExtern() { return externfunc; }; // report whether function is external + + void setForward() { forwarddecl = true; }; // designate function as fwd declaration + bool isForward() { return forwarddecl; }; // report whether function is external + + bool isFunctionCPU() { return( function_type == CHILL_FUNCTION_CPU ); }; + bool isFunctionGPU() { return( function_type == CHILL_FUNCTION_GPU ); }; + void setFunctionCPU() { function_type = CHILL_FUNCTION_CPU; }; + void setFunctionGPU() { function_type = CHILL_FUNCTION_GPU; }; + + void *uniquePtr; // DO NOT REFERENCE THROUGH THIS! USED AS A UNIQUE ID + + + + + chillAST_FunctionDecl(); // { asttype = CHILLAST_NODETYPE_FUNCTIONDECL; numparameters = 0;}; + chillAST_FunctionDecl(const char *rt, const char *fname, chillAST_node *p=NULL ) ; + chillAST_FunctionDecl(const char *rt, const char *fname, chillAST_node *p, void *unique ) ; + + void addParameter( chillAST_VarDecl *p); + chillAST_VarDecl *hasParameterNamed( const char *name ); + chillAST_VarDecl *findParameterNamed( const char *name ) { return hasParameterNamed( name ); }; + + void addDecl( chillAST_VarDecl *vd); // just adds to symbol table?? TODO + + chillAST_VarDecl *funcHasVariableNamed( const char *name ); // functiondecl::hasVariableNamed + //chillAST_VarDecl *findVariableNamed( const char *name ) { return hasVariableNamed( name ); }; + + void addChild(chillAST_node* node); // special because inserts into BODY + void insertChild(int i, chillAST_node* node); // special because inserts into BODY + + void setBody( chillAST_node * bod ); + chillAST_CompoundStmt *getBody() { return( body); } + + void print( int indent=0, FILE *fp = stderr ); // in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // in chill_ast.cc + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + chillAST_VarDecl *findArrayDecl( const char *name ); + //void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + //void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + void cleanUpVarDecls(); + + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ); + + chillAST_node* constantFold(); + + chillAST_node *findDatatype( char *t ) { + fprintf(stderr, "%s looking for datatype %s\n", getTypeString(), t); + if (!typedef_table) { // not here + if (parent) return parent->findDatatype(t); // not here, check parents + else return NULL; // not defined here and no parent + } + + //fprintf(stderr, "%d typedefs\n", typedef_table->size()); + for (int i=0; i< typedef_table->size(); i++) { + chillAST_TypedefDecl *tdd = (*typedef_table)[i]; + if ( tdd->nameis( t )) return tdd; + } + if (parent) return parent->findDatatype(t); + return NULL; // should not happen + } + + chillAST_SymbolTable *getParameterSymbolTable() { return ¶meters; } + chillAST_SymbolTable *getSymbolTable() { return body->getSymbolTable(); } //symbol_table; } // + void setSymbolTable( chillAST_SymbolTable *tab ) { + // no longer keeping a local ?? symbol_table = tab; + if (!body) { // can never happen now + body = new chillAST_CompoundStmt(); + } // only if func is empty! + body->symbol_table = tab; + } + + chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_FunctionDecl method + //fprintf(stderr, "\nchillAST_FunctionDecl addVariableToSymbolTable( %s )\n", vd->varname); + + // this is all dealing with the body's symbol table + // the function has a symbol table called "parameters" but that is a special case + + addSymbolToTable( getSymbolTable(), vd ); + if (!vd->parent) { + //fprintf(stderr, "setting parent of vardecl to be the function whose symbol table it is going into\n"); // ?? + vd->setParent( this ); + insertChild(0,vd); + } + //printSymbolTable( getSymbolTable() ); + return getSymbolTable(); + } + + + void addTypedefToTypedefTable( chillAST_TypedefDecl *tdd ) { + typedef_table = addTypedefToTable( typedef_table, tdd ); + } + + void replaceChild( chillAST_node *old, chillAST_node *newchild ) { + body->replaceChild( old, newchild ); + } +}; // end FunctionDecl + + + + +class chillAST_SourceFile: public chillAST_node { +public: + + // constructors + chillAST_SourceFile(); // defined in chill_ast.cc + chillAST_SourceFile(const char *filename ); // defined in chill_ast.cc + + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printToFile( char *filename = NULL ); + + char *SourceFileName; // where this originated + char *FileToWrite; + char *frontend; + + void setFileToWrite( char *f ) { FileToWrite = strdup( f ); }; + + void setFrontend( const char *compiler ) { if (frontend) free(frontend); frontend = strdup(compiler); } + // get, set filename ? + + chillAST_SymbolTable *global_symbol_table; // (global) symbols defined inside this source file + chillAST_TypedefTable *global_typedef_table; // source file + chillAST_VarDecl *findVariableNamed( const char *name ); // looks in global_symbol_table; + + bool hasSymbolTable() { return true; } ; // "has" vs "can have" TODO + bool hasTypeDefTable() { return true; } ; + + chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_SourceFile method + fprintf(stderr, "\nchillAST_SourceFile addVariableToSymbolTable( %s )\n", vd->varname); + global_symbol_table = addSymbolToTable( global_symbol_table, vd ); + //addChild( vd ); // ?? + //printSymbolTable( global_symbol_table ); + return global_symbol_table; + } + + void addTypedefToTypedefTable( chillAST_TypedefDecl *tdd ) { + //fprintf(stderr, "SOURCEFILE adding typedef %s to typedeftable\n", tdd->getStructName()); + global_typedef_table = addTypedefToTable( global_typedef_table, tdd ); + //fprintf(stderr, "now global typedef table has %d entries\n", global_typedef_table->size()); + } + + chillAST_node *findDatatype( char *t ) { + fprintf(stderr, "%s looking for datatype %s\n", getTypeString(), t); + fprintf(stderr, "%d global typedefs\n", global_typedef_table->size()); + for (int i=0; i< global_typedef_table->size(); i++) { + + chillAST_TypedefDecl *tdd = (*global_typedef_table)[i]; + //fprintf(stderr, "comparing to %s\n", tdd->getStructName()); + if (tdd->nameis( t )) { + //fprintf(stderr, "found it\n"); + return (chillAST_node *)tdd; + } + } + return NULL; + } + + std::vector< chillAST_FunctionDecl *> functions; // at top level, or anywhere? + std::vector< chillAST_MacroDefinition *> macrodefinitions; + + chillAST_MacroDefinition* findMacro( const char *name ); // TODO ignores arguments + chillAST_FunctionDecl *findFunction( const char *name ); // TODO ignores arguments + chillAST_node *findCall( const char *name ); + void addMacro(chillAST_MacroDefinition* md) { + macrodefinitions.push_back(md); + //fprintf(stderr, "addMacro(), now %d macros\n", macrodefinitions.size()); + } + void addFunc(chillAST_FunctionDecl* fd) { + //fprintf(stderr, "chillAST_SourceFile::addFunc( %s %p)\n", fd->functionName, fd); + + bool already = false; + for (int i=0; i<functions.size(); i++) { + //fprintf(stderr, "function %d is %s %p\n", i, functions[i]->functionName, functions[i]); + if (functions[i] == fd) { + //fprintf(stderr, "function %s was already in source functions\n", fd->functionName); + already = true; + } + } + if (!already) functions.push_back(fd); + + // PROBABLY fd was created with sourcefile as its parent. Don't add it twice + addChild( (chillAST_node *)fd); } + +}; + + +/* + class chillAST_VarDecl: public chillAST_node { // now a SINGLE DECL. multiples in + public: + int howmany; // usually 1 but sometimes multiple declarations in a decl; + std::vector<class chillAST_SingleVarDecl*> decls; + + chillAST_VarDecl(); + chillAST_VarDecl( char *t, char *n, char *a); + void addDecl( char *t, char *n, char *a); + + void dump( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ); + }; +*/ + + +/* +class chillAST_ParmVarDecl: public chillAST_node { // no longer used? +public: + char *vartype; // should probably be an enum + char *varname; + char *arraypart; + int numdimensions; // TODO + int *arraysizes; // TODO + // hasDefaultArg + // getDefaultArg + + chillAST_ParmVarDecl(); + chillAST_ParmVarDecl( const char *type, const char *name, const char *ap, chillAST_node *p ); + + void dump( int indent=0, FILE *fp = stderr ) { + fprintf(fp, "(2VarDecl'%s' '%s' '%s')", vartype, varname, arraypart); }; + void print( int indent=0, FILE *fp = stderr ); +}; +*/ + + + +class chillAST_MacroDefinition: public chillAST_node { +private: + chillAST_node *body; // rhs always a compound statement? + chillAST_SymbolTable *symbol_table; +public: + char *macroName; + char *rhsString; + + // parameters - these will be odd, in that they HAVE NO TYPE + int numParameters() { return parameters.size(); } ; + std::vector<chillAST_VarDecl *>parameters; + + void setName( char *n ) { macroName = strdup(n); /* probable memory leak */ }; + void setRhsString( char *n ) { rhsString = strdup(n); /* probable memory leak */ }; + char *getRhsString() { return rhsString; } + + chillAST_MacroDefinition(); + chillAST_MacroDefinition( const char *name, chillAST_node *par); + chillAST_MacroDefinition( const char *name, const char *rhs, chillAST_node *par); + + void addParameter( chillAST_VarDecl *p); // parameters have no TYPE ?? + chillAST_VarDecl *hasParameterNamed( const char *name ); + chillAST_VarDecl *findParameterNamed( const char *name ) { return hasParameterNamed( name ); }; + void addChild(chillAST_node* node); // special because inserts into BODY + void insertChild(int i, chillAST_node* node); // special because inserts into BODY + + void setBody( chillAST_node * bod ); + chillAST_node *getBody() { return( body); } + + void print( int indent=0, FILE *fp = stderr ); // in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // in chill_ast.cc + + bool hasSymbolTable() { return true; } ; + + //const std::vector<chillAST_VarDecl *> getSymbolTable() { return symbol_table; } + chillAST_SymbolTable *getSymbolTable() { return symbol_table; } + chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_MacroDefinition method ?? + //fprintf(stderr, "\nchillAST_MacroDefinition addVariableToSymbolTable( %s )\n", vd->varname); + symbol_table = addSymbolToTable( symbol_table, vd ); + //printSymbolTable( symbol_table ); + return symbol_table; + } + + + chillAST_node* clone(); + + // none of these make sense for macros + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ){}; + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ){}; + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ){}; + chillAST_VarDecl *findArrayDecl( const char *name ){}; + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ){}; + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ){}; + void cleanUpVarDecls(); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){}; + chillAST_node* constantFold(){}; +}; + + + + + + +class chillAST_ForStmt: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *init; + chillAST_node *cond; + chillAST_node *incr; + chillAST_node *body; // always a compoundstmt? + IR_CONDITION_TYPE conditionoperator; // from ir_code.hh + + chillAST_SymbolTable *symbol_table; // symbols defined inside this forstmt (in init but not body?) body is compound stmt + bool hasSymbolTable() { return true; } ; + + // constructors + chillAST_ForStmt(); + chillAST_ForStmt( chillAST_node *ini, chillAST_node *con, chillAST_node *inc, chillAST_node *bod, chillAST_node *p); + + // other methods particular to this type of node + void addSyncs(); + void removeSyncComment(); + chillAST_node *getInit() { return init; }; + chillAST_node *getCond() { return cond; }; + chillAST_node *getInc() { return incr; }; + chillAST_node *getBody() { //fprintf(stderr, "chillAST_ForStmt::getBody(), returning a chillAST_node of type %s\n", body->getTypeString()); + return body; }; + void setBody( chillAST_node *b ) { body = b; b->parent = this; }; + + bool isNotLeaf() { return true; }; + bool isLeaf() { return false; }; + + + // required methods that I can't seem to get to inherit + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printControl( int indent=0, FILE *fp = stderr ); // print just for ( ... ) but not body + + chillAST_node* constantFold(); + chillAST_node* clone(); + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); // will get called on inner loops + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ); + + void gatherLoopIndeces( std::vector<chillAST_VarDecl*> &indeces ); + void gatherLoopVars( std::vector<std::string> &loopvars ); // gather as strings ?? + + void get_deep_loops( std::vector<chillAST_ForStmt *> &loops) { // chillAST_ForStmt version + // ADD MYSELF! + loops.push_back( this ); + + int n = body->children.size(); + //fprintf(stderr, "get_deep_loops of a %s with %d children\n", getTypeString(), n); + for (int i=0; i<n; i++) { + //fprintf(stderr, "child %d is a %s\n", i, body->children[i]->getTypeString()); + body->children[i]->get_deep_loops( loops ); + } + //fprintf(stderr, "found %d deep loops\n", loops.size()); + } + + + void find_deepest_loops( std::vector<chillAST_ForStmt *> &loops) { + std::vector<chillAST_ForStmt *> b; // deepest loops below me + + int n = body->children.size(); + for (int i=0; i<n; i++) { + std::vector<chillAST_ForStmt *> l; // deepest loops below one child + body->children[i]->find_deepest_loops( l ); + if ( l.size() > b.size() ) { // a deeper nesting than we've seen + b = l; + } + } + + loops.push_back( this ); // add myself + for (int i=0; i<b.size(); i++) loops.push_back(b[i]); + } + + + void loseLoopWithLoopVar( char *var ); // chillAST_ForStmt + void replaceChild( chillAST_node *old, chillAST_node *newchild ) ; + + chillAST_SymbolTable* addVariableToSymbolTable( chillAST_VarDecl *vd ) { // chillAST_ForStmt method + //fprintf(stderr, "\nchillAST_ForStmt addVariableToSymbolTable( %s )\n", vd->varname); + symbol_table = addSymbolToTable( symbol_table, vd ); + //printSymbolTable( symbol_table ); + return symbol_table; + } + + void gatherStatements( std::vector<chillAST_node*> &statements ); + bool lowerBound( int &l ); + bool upperBound( int &u ); + +}; + + + +class chillAST_TernaryOperator: public chillAST_node { +public: + // variables that are special for this type of node + char *op; // TODO need enum so far, only "?" conditional operator + chillAST_node *condition; + chillAST_node *lhs; // keep name from binary + chillAST_node *rhs; + + + // constructors + chillAST_TernaryOperator(); + chillAST_TernaryOperator(const char *op, chillAST_node *cond, chillAST_node *lhs, chillAST_node *rhs, chillAST_node *p=NULL); + + // other methods particular to this type of node + bool isNotLeaf() { return true; }; + bool isLeaf() { return false; }; + + + char *getOp() { return op; }; // dangerous. could get changed! + chillAST_node *getCond() { return condition; }; + chillAST_node *getRHS() { return rhs; }; + chillAST_node *getLHS() { return lhs; }; + + void setCond( chillAST_node *newc ) { condition = newc; newc->setParent( this ); } + void setLHS( chillAST_node *newlhs ) { lhs = newlhs; newlhs->setParent( this ); } + void setRHS( chillAST_node *newrhs ) { rhs = newrhs; newrhs->setParent( this ); } + + + + + // required methods that I can't seem to get to inherit + void dump( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printonly( int indent=0, FILE *fp = stderr ); + + chillAST_node* constantFold(); + chillAST_node* clone(); + void replaceChild( chillAST_node *old, chillAST_node *newchild ) ; + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + void gatherVarLHSUsage( std::vector<chillAST_VarDecl*> &decls ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + void loseLoopWithLoopVar( char *var ){}; // ternop can't have loop as child? +}; + + + +class chillAST_BinaryOperator: public chillAST_node { +public: + // variables that are special for this type of node + char *op; // TODO need enum + chillAST_node *lhs; + chillAST_node *rhs; + + + // constructors + chillAST_BinaryOperator(); + chillAST_BinaryOperator(chillAST_node *lhs, const char *op, chillAST_node *rhs, chillAST_node *p=NULL); + + // other methods particular to this type of node + int evalAsInt(); + chillAST_IntegerLiteral *evalAsIntegerLiteral(); + + bool isNotLeaf() { return true; }; + bool isLeaf() { return false; }; + + chillAST_node *getRHS() { return rhs; }; + chillAST_node *getLHS() { return lhs; }; + void setLHS( chillAST_node *newlhs ) { lhs = newlhs; newlhs->setParent( this ); } + void setRHS( chillAST_node *newrhs ) { rhs = newrhs; newrhs->setParent( this ); } + + char *getOp() { return op; }; // dangerous. could get changed! + bool isAugmentedAssignmentOp() { + return + (!strcmp(op, "*=")) || // BO_MulAssign, + (!strcmp(op, "/=")) || // BO_DivAssign + (!strcmp(op, "%=")) || // BO_RemAssign + (!strcmp(op, "+=")) || // BO_AddAssign + (!strcmp(op, "-=")) || // BO_SubAssign + + (!strcmp(op, "<<=")) || // BO_ShlAssign + (!strcmp(op, ">>=")) || // BO_ShrAssign + (!strcmp(op, "&&=")) || // BO_AndAssign + (!strcmp(op, "||=")) || // BO_OrAssign + + (!strcmp(op, "^=")) // BO_XorAssign + ; + } + bool isAssignmentOp() { + return( (!strcmp(op, "=")) || // BO_Assign, + isAugmentedAssignmentOp() ); + }; + bool isComparisonOp() { return (!strcmp(op,"<")) || (!strcmp(op,">")) || (!strcmp(op,"<=")) || (!strcmp(op,">=")); }; + + bool isPlusOp() { return (!strcmp(op,"+")); }; + bool isMinusOp() { return (!strcmp(op,"-")); }; + bool isPlusMinusOp() { return (!strcmp(op,"+")) || (!strcmp(op,"-")); }; + bool isMultDivOp() { return (!strcmp(op,"*")) || (!strcmp(op,"/")); }; + + bool isStructOp() { return (!strcmp(op,".")) || (!strcmp(op,"->")); }; + + + // required methods that I can't seem to get to inherit + void dump( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printonly( int indent=0, FILE *fp = stderr ); + char *stringRep(int indent=0 ); + + chillAST_node* constantFold(); + chillAST_node* clone(); + void replaceChild( chillAST_node *old, chillAST_node *newchild ) ; + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); // chillAST_BinaryOperator + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + void gatherVarLHSUsage( std::vector<chillAST_VarDecl*> &decls ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + void loseLoopWithLoopVar( char *var ){}; // binop can't have loop as child? + + void gatherStatements( std::vector<chillAST_node*> &statements ); // + + bool isSameAs( chillAST_node *other ); + +}; + + + + + + + + +class chillAST_ArraySubscriptExpr: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *base; // always a decl ref expr? No, for multidimensional array, is another ASE + chillAST_node *index; + bool imwrittento; + bool imreadfrom; // WARNING: ONLY used when both writtento and readfrom are true x += 1 and so on + chillAST_VarDecl *basedecl; // the vardecl that this refers to + void *uniquePtr; // DO NOT REFERENCE THROUGH THIS! + + // constructors + chillAST_ArraySubscriptExpr(); + chillAST_ArraySubscriptExpr( chillAST_node *bas, chillAST_node *indx, chillAST_node *p, void *unique); + chillAST_ArraySubscriptExpr( chillAST_node *bas, chillAST_node *indx, bool writtento, chillAST_node *p, void *unique); + + chillAST_ArraySubscriptExpr( chillAST_VarDecl *v, std::vector<chillAST_node *> indeces, chillAST_node *p); + + // other methods particular to this type of node + bool operator!=( const chillAST_ArraySubscriptExpr& ) ; + bool operator==( const chillAST_ArraySubscriptExpr& ) ; + chillAST_VarDecl *multibase(); // method for finding the basedecl + chillAST_node *multibase2() { return base->multibase2(); } + + chillAST_node *getIndex(int dim); + void gatherIndeces( std::vector< chillAST_node * > &ind ); + + void replaceChild( chillAST_node *old, chillAST_node *newchild ); // will examine index + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printonly( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ) const; // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + char *stringRep(int indent=0 ); + + chillAST_node* constantFold(); + chillAST_node* clone(); + chillAST_node *findref(){return this;}// find the SINGLE constant or data reference at this node or below + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + + const char* getUnderlyingType() { + //fprintf(stderr, "ASE getUnderlyingType() base of type %s\n", base->getTypeString()); base->print(); printf("\n"); fflush(stderr); + return base->getUnderlyingType(); }; + + virtual chillAST_VarDecl* getUnderlyingVarDecl() { return base->getUnderlyingVarDecl(); }; + +}; + + + +class chillAST_MemberExpr: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *base; // always a decl ref expr? No, can be Array Subscript Expr + char *member; + char *printstring; + + chillAST_VarDecl *basedecl; // the vardecl that this refers to + void *uniquePtr; // DO NOT REFERENCE THROUGH THIS! + + CHILL_MEMBER_EXP_TYPE exptype; + + + // constructors + chillAST_MemberExpr(); + chillAST_MemberExpr( chillAST_node *bas, const char *mem, chillAST_node *p, void *unique, CHILL_MEMBER_EXP_TYPE t=CHILL_MEMBER_EXP_DOT); + + // other methods particular to this type of node + bool operator!=( const chillAST_MemberExpr& ) ; + bool operator==( const chillAST_MemberExpr& ) ; + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printonly( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ) const; // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + char *stringRep( int indent = 0); + + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + + chillAST_VarDecl* getUnderlyingVarDecl(); + + void replaceChild( chillAST_node *old, chillAST_node *newchild ); + + void setType( CHILL_MEMBER_EXP_TYPE t ) { exptype = t; }; + CHILL_MEMBER_EXP_TYPE getType( CHILL_MEMBER_EXP_TYPE t ) { return exptype; }; + + chillAST_VarDecl* multibase(); // this one will return the member decl + chillAST_node* multibase2(); // this one will return the member expression +}; + + + + +class chillAST_IntegerLiteral: public chillAST_node { +public: + // variables that are special for this type of node + int value; + + // constructors + chillAST_IntegerLiteral(int val, chillAST_node *p = NULL); + + // other methods particular to this type of node + int evalAsInt() { return value; } + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool w ){}; // does nothing + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ){}; // does nothing + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ){}; // does nothing + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ){}; // does nothing + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ){}; // does nothing + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ) {}; // does nothing + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ) {}; // does nothing + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl) {}; + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + + chillAST_node *findref(){return this;}// find the SINGLE constant or data reference at this node or below +}; + + +class chillAST_FloatingLiteral: public chillAST_node { +public: + // variables that are special for this type of node + float value; + double doublevalue; + int float0double1; + + char *allthedigits; // if not NULL, use this as printable representation + int precision; // float == 1, double == 2, ??? + + // constructors + chillAST_FloatingLiteral( float val, chillAST_node *p); + chillAST_FloatingLiteral( double val, chillAST_node *p); + chillAST_FloatingLiteral( float val, int pre, chillAST_node *p); + chillAST_FloatingLiteral( double val, int pre, chillAST_node *p); + chillAST_FloatingLiteral( float val, const char *printable, chillAST_node *p); + chillAST_FloatingLiteral( float val, int pre, const char *printable, chillAST_node *p); + chillAST_FloatingLiteral( chillAST_FloatingLiteral *old ); + + // other methods particular to this type of node + void setPrecision( int precis ) { precision = precis; }; + int getPrecision() { return precision; } + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool w ){}; // does nothing + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ){}; // does nothing + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ){}; // does nothing + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ){}; // does nothing ; + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ){}; // does nothing ; + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ) {}; // does nothing + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ){}; // does nothing + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){}; + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + chillAST_node *findref(){return this;};// find the SINGLE constant or data reference at this node or below + + bool isSameAs( chillAST_node *other ); +}; + + + + +class chillAST_UnaryOperator: public chillAST_node { +public: + // variables that are special for this type of node + char *op; // TODO enum + bool prefix; // or post + chillAST_node *subexpr; + + // constructors + chillAST_UnaryOperator( const char *oper, bool pre, chillAST_node *sub, chillAST_node *p ); + + // other methods particular to this type of node + bool isAssignmentOp() { + return( (!strcmp(op, "++")) || + (!strcmp(op, "--")) ); // are there more ??? TODO + } + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); // chillAST_UnaryOperator + + void gatherVarLHSUsage( std::vector<chillAST_VarDecl*> &decls ); + + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + + int evalAsInt(); + bool isSameAs( chillAST_node *other ); + +}; + + + + + +class chillAST_ImplicitCastExpr: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *subexpr; + + // constructors + chillAST_ImplicitCastExpr(chillAST_node *sub, chillAST_node *p); + + // other methods particular to this type of node + bool isNotLeaf() { return true; }; + bool isLeaf() { return false; }; + + // required methods that I can't seem to get to inherit + void replaceChild( chillAST_node *old, chillAST_node *newchild ); + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void printonly( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ) { print( indent, fp); }; // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + chillAST_VarDecl *multibase(); // just recurse on subexpr + +}; + + + +class chillAST_CStyleCastExpr: public chillAST_node { +public: + // variables that are special for this type of node + char * towhat; + chillAST_node *subexpr; + // constructors + chillAST_CStyleCastExpr(const char *to, chillAST_node *sub, chillAST_node *p=NULL); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void replaceChild( chillAST_node *old, chillAST_node *newchild ); + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + chillAST_node *findref(){return subexpr;};// find the SINGLE constant or data reference at this node or below + +}; + + +class chillAST_CStyleAddressOf: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *subexpr; + // constructors + chillAST_CStyleAddressOf(chillAST_node *sub, chillAST_node *p=NULL); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + + +}; + + +class chillAST_CudaMalloc:public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *devPtr; // Pointer to allocated device memory + chillAST_node *sizeinbytes; + + // constructors + chillAST_CudaMalloc(chillAST_node *devmemptr, chillAST_node *size, chillAST_node *p=NULL); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + //void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + +class chillAST_CudaFree:public chillAST_node { +public: + // variables that are special for this type of node + chillAST_VarDecl *variable; + + // constructors + chillAST_CudaFree(chillAST_VarDecl *var, chillAST_node *p=NULL); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + //void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + + + + +class chillAST_Malloc:public chillAST_node { // malloc( sizeof(int) * 2048 ); +public: + // variables that are special for this type of node + char *thing; // to void if this is null , sizeof(thing) if it is not + chillAST_node *sizeexpr; // bytes + + // constructors + chillAST_Malloc(chillAST_node *size, chillAST_node *p=NULL); + chillAST_Malloc(char *thething, chillAST_node *numthings, chillAST_node *p=NULL); // malloc (sizeof(int) *1024) + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + //void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + + + +class chillAST_Free:public chillAST_node { +public: + + + + +}; + + + + +class chillAST_CudaMemcpy:public chillAST_node { +public: + // variables that are special for this type of node + chillAST_VarDecl *dest; // Pointer to allocated device memory + chillAST_VarDecl *src; + chillAST_node *size; + char *cudaMemcpyKind; // could use the actual enum + + // constructors + chillAST_CudaMemcpy(chillAST_VarDecl *d, chillAST_VarDecl *s, chillAST_node *size, char *kind, chillAST_node *p=NULL); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + //void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + +class chillAST_CudaSyncthreads:public chillAST_node { +public: + // variables that are special for this type of node + + // constructors + chillAST_CudaSyncthreads(chillAST_node *p=NULL); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + //chillAST_node* constantFold() {}; + //chillAST_node* clone(); + //void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ){}; + //void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ) {}; // does nothing + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ) {}; // does nothing + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ) {}; // does nothing + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ) {}; // does nothing + //void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + //bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; + +}; + + + +class chillAST_ReturnStmt: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *returnvalue; + + // constructors + chillAST_ReturnStmt( chillAST_node *retval, chillAST_node *p ); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + + +class chillAST_CallExpr: public chillAST_node { // a function call +public: + // variables that are special for this type of node + chillAST_node *callee; // the function declaration (what about builtins?) + int numargs; + std::vector<class chillAST_node*> args; + chillAST_VarDecl *grid; + chillAST_VarDecl *block; + + // constructors + chillAST_CallExpr(chillAST_node *function, chillAST_node *p ); + void addArg( chillAST_node *newarg ); + + // other methods particular to this type of node + // TODO get/set grid, block + + // required methods that I can't seem to get to inherit + chillAST_node* constantFold(); + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + chillAST_node* clone(); +}; + + + +class chillAST_ParenExpr: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *subexpr; + + // constructors + chillAST_ParenExpr( chillAST_node *sub, chillAST_node *p=NULL ); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + +class chillAST_Sizeof: public chillAST_node { +public: + // variables that are special for this type of node + char *thing; + + // constructors + chillAST_Sizeof( char *t, chillAST_node *p = NULL ); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc + chillAST_node* constantFold(); + chillAST_node* clone(); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){}; + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; }; // no loops under here + +}; + + + +class chillAST_NoOp: public chillAST_node { +public: + chillAST_NoOp( chillAST_node *p = NULL ); // { parent = p; }; + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ) {}; // print CODE in chill_ast.cc + void dump( int indent=0, FILE *fp = stderr ) {}; // print ast in chill_ast.cc + chillAST_node* constantFold() {}; + chillAST_node* clone() { return new chillAST_NoOp( parent ); }; // ?? + + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ) {}; + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) {}; + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ){}; + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ){}; + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ){}; + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ){}; + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ){}; + void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl){}; + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ){ return false; };//no loops under here +}; + + + +class chillAST_IfStmt: public chillAST_node { +public: + // variables that are special for this type of node + chillAST_node *cond; + chillAST_node *thenpart; + chillAST_node *elsepart; + IR_CONDITION_TYPE conditionoperator; // from ir_code.hh + + // constructors + chillAST_IfStmt(); + chillAST_IfStmt( chillAST_node *c, chillAST_node *t, chillAST_node *e, chillAST_node *p); + + // other methods particular to this type of node + chillAST_node *getCond() { return cond; }; + chillAST_node *getThen() { return thenpart; }; + chillAST_node *getElse() { return elsepart; }; + + void setCond( chillAST_node *b ) { cond = b; if (cond) cond->parent = this; }; + void setThen( chillAST_node *b ) { thenpart = b; if (thenpart) thenpart->parent = this; }; + void setElse( chillAST_node *b ) { elsepart = b; if (elsepart) elsepart->parent = this; }; + + // required methods that I can't seem to get to inherit + void dump( int indent=0, FILE *fp = stderr ); + void print( int indent=0, FILE *fp = stderr ); + + chillAST_node* constantFold(); + chillAST_node* clone(); + + void gatherVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherVarDeclsMore ( std::vector<chillAST_VarDecl*> &decls ) { gatherVarDecls(decls); } ; + + void gatherScalarVarDecls( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayVarDecls ( std::vector<chillAST_VarDecl*> &decls ); + void gatherArrayRefs( std::vector<chillAST_ArraySubscriptExpr*> &refs, bool writtento ); + void gatherScalarRefs( std::vector<chillAST_DeclRefExpr*> &refs, bool writtento ) ; + + void gatherVarUsage( std::vector<chillAST_VarDecl*> &decls ); + void gatherDeclRefExprs( std::vector<chillAST_DeclRefExpr *>&refs ); + //void replaceVarDecls( chillAST_VarDecl *olddecl, chillAST_VarDecl *newdecl); + bool findLoopIndexesToReplace( chillAST_SymbolTable *symtab, bool forcesync=false ); + + void gatherStatements( std::vector<chillAST_node*> &statements ); + +}; + + + + + + + + +class chillAST_something: public chillAST_node { +public: + // variables that are special for this type of node + + // constructors + chillAST_something(); + + // other methods particular to this type of node + + + // required methods that I can't seem to get to inherit + void print( int indent=0, FILE *fp = stderr ); // print CODE in chill_ast.cc + //void dump( int indent=0, FILE *fp = stderr ); // print ast in chill_ast.cc +}; + + + + +chillAST_FunctionDecl *findFunctionDecl( chillAST_node *node, const char *procname); + + + +#endif + diff --git a/include/chill_error.hh b/include/chill_error.hh index 88e49fc..c5601ae 100644 --- a/include/chill_error.hh +++ b/include/chill_error.hh @@ -21,4 +21,8 @@ struct ir_exp_error: public ir_error { ir_exp_error(const std::string &msg): ir_error(msg){} }; +struct omega_error: public std::runtime_error { + omega_error(const std::string &msg): std::runtime_error(msg){} +}; + #endif diff --git a/include/dep.hh b/include/dep.hh index 6c535ce..ed5a83d 100644 --- a/include/dep.hh +++ b/include/dep.hh @@ -1,19 +1,6 @@ #ifndef DEP_HH #define DEP_HH -/*! - * \file - * \brief Data dependence vector and graph. - * - * All dependence vectors are normalized, i.e., the first non-zero distance - * must be positve. Thus the correct dependence meaning can be given based on - * source/destination pair's read/write type. Suppose for a dependence vector - * 1, 0~5, -3), we want to permute the first and the second dimension, - * the result would be two dependence vectors (0, 1, -3) and (1~5, 1, -3). - * All operations on dependence vectors are non-destructive, i.e., new - * dependence vectors are returned. - */ - #include <omega.h> #include "graph.hh" #include "ir_code.hh" @@ -27,9 +14,12 @@ typedef std::vector<DependenceVector> DependenceList; struct DependenceVector { DependenceType type; IR_Symbol *sym; - - bool is_reduction; //!< used to identify a class of flow dependence - //!< that can be broken + + bool from_same_stmt; // Manu + bool is_reduction_cand; // Manu + + bool is_reduction; // used to identify a class of flow dependence + // that can be broken std::vector<omega::coef_t> lbounds; std::vector<omega::coef_t> ubounds; @@ -39,11 +29,14 @@ struct DependenceVector { type = DEP_UNKNOWN; sym = NULL; is_reduction = false; + from_same_stmt = false; // Manu + is_reduction_cand = false; // Manu quasi = false; is_scalar_dependence = false; } + // DependenceVector(int size); DependenceVector(const DependenceVector &that); - ~DependenceVector() {delete sym;} + ~DependenceVector() { delete sym; } // is this legal? TODO DependenceVector &operator=(const DependenceVector &that); bool is_data_dependence() const; @@ -52,7 +45,7 @@ struct DependenceVector { bool has_been_carried_at(int dim) const; bool has_been_carried_before(int dim) const; - // TODO the following functions will be cleaned up or removed later + // the following functions will be cleaned up or removed later bool isZero() const; bool isPositive() const; bool isNegative() const; @@ -67,6 +60,7 @@ struct DependenceVector { std::vector<DependenceVector> normalize() const; std::vector<DependenceVector> permute(const std::vector<int> &pi) const; DependenceVector reverse() const; + // std::vector<DependenceVector> matrix(const std::vector<std::vector<int> > &M) const; DependenceType getType() const; friend std::ostream& operator<<(std::ostream &os, const DependenceVector &d); }; @@ -83,8 +77,10 @@ public: DependenceGraph() { num_dim_ = 0; } ~DependenceGraph() {} int num_dim() const { return num_dim_; } +// DependenceGraph permute(const std::vector<int> &pi) const; DependenceGraph permute(const std::vector<int> &pi, const std::set<int> &active = std::set<int>()) const; + // DependenceGraph matrix(const std::vector<std::vector<int> > &M) const; DependenceGraph subspace(int dim) const; bool isPositive() const; bool hasPositive(int dim) const; diff --git a/include/ir_clang.hh b/include/ir_clang.hh new file mode 100755 index 0000000..7c3d451 --- /dev/null +++ b/include/ir_clang.hh @@ -0,0 +1,479 @@ +#ifndef IR_CLANG_HH +#define IR_CLANG_HH + +#include <omega.h> +#include "ir_code.hh" +//#include <AstInterface_CLANG.h> +#include "chill_error.hh" + +#define __STDC_CONSTANT_MACROS +#include "clang/AST/Decl.h" +#include "clang/AST/Expr.h" +#include "clang/AST/ParentMap.h" + +#include "clang/AST/ASTConsumer.h" +#include "clang/AST/ASTContext.h" +#include "clang/AST/GlobalDecl.h" +#include "clang/AST/RecursiveASTVisitor.h" +#include "clang/Basic/SourceManager.h" +#include "clang/Frontend/ASTConsumers.h" +#include "clang/Frontend/FrontendActions.h" + +#include "clang/CodeGen/CodeGenAction.h" +#include "clang/Driver/Compilation.h" +#include "clang/Driver/Driver.h" +#include "clang/Driver/Tool.h" +#include "clang/Frontend/CompilerInvocation.h" +#include "clang/Frontend/CompilerInstance.h" +#include "clang/Frontend/FrontendDiagnostic.h" +#include "clang/Frontend/TextDiagnosticPrinter.h" +#include "clang/Basic/DiagnosticOptions.h" + +#include "chill_ast.hh" + +// using namespace clang; // NEVER EVER do this in a header file +// using namespace clang::driver; // NEVER EVER do this in a header file + +extern std::vector<chillAST_VarDecl *> VariableDeclarations; // a global. TODO + +typedef llvm::SmallVector<clang::Stmt *, 16> StmtList; // TODO delete + +struct IR_chillScalarSymbol: public IR_ScalarSymbol { + chillAST_VarDecl *chillvd; + + IR_chillScalarSymbol(const IR_Code *ir, chillAST_VarDecl *vd) { + fprintf(stderr, "making scalar symbol %s\n", vd->varname); + ir_ = ir; + chillvd = vd; + } + + std::string name() const; + int size() const; + bool operator==(const IR_Symbol &that) const; + IR_Symbol *clone() const; +}; + + + +struct IR_chillArraySymbol: public IR_ArraySymbol { + //int indirect_; // what was this? + int offset_; // what is this? + chillAST_VarDecl *chillvd; + + IR_chillArraySymbol(const IR_Code *ir, chillAST_VarDecl *vd, int offset = 0) { + //if ( vd == 0 ) + //fprintf(stderr, "IR_chillArraySymbol::IR_chillArraySymbol (%s) vd 0x%x\n", vd->varname, vd); + ir_ = ir; + chillvd = vd; + //indirect_ = indirect; + offset_ = offset; + } + + + // No Fortran support! + IR_ARRAY_LAYOUT_TYPE layout_type() const { + return IR_ARRAY_LAYOUT_ROW_MAJOR; + } + + std::string name() const; + int elem_size() const; + int n_dim() const; + omega::CG_outputRepr *size(int dim) const; + bool operator!=(const IR_Symbol &that) const; + bool operator==(const IR_Symbol &that) const; + IR_Symbol *clone() const; + // TODO Hack to pass build + IR_CONSTANT_TYPE elem_type() const {return IR_CONSTANT_UNKNOWN;}; + +}; + + + +struct IR_chillConstantRef: public IR_ConstantRef { + union { + omega::coef_t i_; + double f_; + }; + + IR_chillConstantRef(const IR_Code *ir, omega::coef_t i) { + ir_ = ir; + type_ = IR_CONSTANT_INT; + i_ = i; + } + IR_chillConstantRef(const IR_Code *ir, double f) { + ir_ = ir; + type_ = IR_CONSTANT_FLOAT; + f_ = f; + } + omega::coef_t integer() const { + assert(is_integer()); + return i_; + } + bool operator==(const IR_Ref &that) const; + omega::CG_outputRepr *convert(); + IR_Ref *clone() const; + +}; + +enum OP_POSITION { OP_DEST =-1, OP_UNKNOWN, OP_SRC }; +#define OP_LEFT OP_DEST +#define OP_RIGHT OP_SRC + +struct IR_chillScalarRef: public IR_ScalarRef { + OP_POSITION op_pos_; // -1 means destination operand, 0== unknown, 1 == source operand + //chillAST_BinaryOperator *bop; // binary op that contains this scalar? + chillAST_DeclRefExpr *dre; // declrefexpr that uses this scalar ref, if that exists + chillAST_VarDecl *chillvd; // the vardecl for this scalar + + IR_chillScalarRef(const IR_Code *ir, chillAST_BinaryOperator *ins, OP_POSITION pos) { + fprintf(stderr, "\n***** new IR_xxxxScalarRef( ir, ins, pos ) *****\n\n"); + exit(-1); + // this constructor takes a binary operation and an indicator of which side of the op to use, + // and finds the scalar in the lhs or rhs of the binary op. + ir_ = ir; + dre = NULL; + //bop = ins; // do we need this? + if (pos == OP_LEFT) { + chillAST_node *lhs = ins->lhs; + if (lhs->isDeclRefExpr()) { + chillAST_DeclRefExpr *DRE = (chillAST_DeclRefExpr *) lhs; + dre = DRE; + chillvd = DRE->getVarDecl(); + } + else if (lhs->isVarDecl()) { + chillvd = (chillAST_VarDecl *)lhs; + } + else { + fprintf(stderr, "IR_chillScalarRef constructor, I'm confused\n"); exit(-1); + } + } + else { + chillAST_node *rhs = ins->rhs; + if (rhs->isDeclRefExpr()) { + chillAST_DeclRefExpr *DRE = (chillAST_DeclRefExpr *) rhs; + dre = DRE; + chillvd = DRE->getVarDecl(); + } + else if (rhs->isVarDecl()) { + chillvd = (chillAST_VarDecl *)rhs; + } + else { + fprintf(stderr, "IR_chillScalarRef constructor, I'm confused\n"); exit(-1); + } + } + op_pos_ = pos; + } + + IR_chillScalarRef(const IR_Code *ir, chillAST_DeclRefExpr *d) { + // fprintf(stderr, "\n***** new IR_xxxxScalarRef( ir, REF EXPR sym %s ) *****\n\n", d->getVarDecl()->varname); + //fprintf(stderr, "new IR_chillScalarRef with a DECLREFEXPR (has dre) \n"); + ir_ = ir; + dre = d; + //bop = NULL; + chillvd = d->getVarDecl(); + op_pos_ = OP_UNKNOWN; + + //fprintf(stderr, "\nScalarRef has:\n"); + //fprintf(stderr, "assignment op DOESNT EXIST\n"); + //fprintf(stderr, "ins_pos %d\n", ins_pos_); + //fprintf(stderr, "op_pos %d\n", op_pos_); + //fprintf(stderr, "ref expr dre = 0x%x\n", dre); + } + + IR_chillScalarRef(const IR_Code *ir, chillAST_VarDecl *vardecl) { + fprintf(stderr, "\n***** new IR_xxxxScalarRef( ir, sym 0x1234567 ) ***** THIS SHOULD NEVER HAPPEN\n\n"); + fprintf(stderr, "vardecl %s\n", vardecl->varname); + ir_ = ir; + dre = NULL; fprintf(stderr, "new IR_chillScalarRef with a vardecl but no dre\n"); + //bop = NULL; + chillvd = vardecl; + op_pos_ = OP_UNKNOWN; + + //fprintf(stderr, "\nScalarRef has:\n"); + //fprintf(stderr, "assignment op DOESNT EXIST\n"); + //fprintf(stderr, "ins_pos %d\n", ins_pos_); + //fprintf(stderr, "op_pos %d\n", op_pos_); + //fprintf(stderr, "ref expr dre = 0x%x\n", dre); + } + + + bool is_write() const; + IR_ScalarSymbol *symbol() const; + bool operator==(const IR_Ref &that) const; + omega::CG_outputRepr *convert(); + IR_Ref *clone() const; +}; + + + +struct IR_chillArrayRef: public IR_ArrayRef { + //DeclRefExpr *as_; + //chillAST_DeclRefExpr *chillDRE; + chillAST_ArraySubscriptExpr* chillASE; + int iswrite; + + + // IR_chillArrayRef(const IR_Code *ir, DeclRefExpr *as, ParentMap *pMap = NULL) { + // ir_ = ir; + // fprintf(stderr, "new IR_chillArrayRef() CLANG ERROR\n"); exit(-1); + //} + + IR_chillArrayRef(const IR_Code *ir, chillAST_ArraySubscriptExpr *ase, int write ) { + //fprintf(stderr, "IR_chillArrayRef::IR_chillArrayRef() write %d\n", write); + ir_ = ir; + chillASE = ase; + iswrite = write; // ase->imwrittento; + } + + bool is_write() const; + omega::CG_outputRepr *index(int dim) const; + IR_ArraySymbol *symbol() const; + bool operator!=(const IR_Ref &that) const; + bool operator==(const IR_Ref &that) const; + omega::CG_outputRepr *convert(); + IR_Ref *clone() const; + virtual void Dump() const; +}; + + + +struct IR_chillLoop: public IR_Loop { + int step_size_; + + chillAST_DeclRefExpr *chillindex; // the loop index variable (I) // was DeclRefExpr + chillAST_ForStmt *chillforstmt; + chillAST_node *chilllowerbound; + chillAST_node *chillupperbound; + chillAST_node *chillbody; // presumably a compound statement, but not guaranteeed + IR_CONDITION_TYPE conditionoperator; + + IR_chillLoop(const IR_Code *ir, clang::ForStmt *tf); + IR_chillLoop(const IR_Code *ir, chillAST_ForStmt *forstmt); + + ~IR_chillLoop() {} + IR_ScalarSymbol *index() const { return new IR_chillScalarSymbol(ir_, chillindex->getVarDecl()); } + omega::CG_outputRepr *lower_bound() const; + omega::CG_outputRepr *upper_bound() const; + IR_CONDITION_TYPE stop_cond() const; + IR_Block *body() const; + + // Handle following types of increment expressions: + + // Unary increment/decrement + // i += K OR i -= K + // i = i + K OR i = i - K + // where K is positive + int step_size() const { return step_size_; } // K is always an integer ??? + IR_Control *clone() const; + IR_Block *convert() ; + virtual void dump() const; +}; + + + + +struct IR_chillBlock: public IR_Block { // ONLY ONE OF bDecl or cs_ will be nonNULL ?? +private: + //StmtList bDecl_; // declarations in the block?? + //clang::CompoundStmt *cs_; // will a block always have a compound statement? (no) + //StmtList *stmts; // ?? +public: + + // Block is a basic block?? (no, just a chunk of code ) + std::vector<chillAST_node *>statements; + chillAST_node *chillAST; // how about for now we say if there are statements, which is presumably the top level of statements from ... somewhere, otherwise the code is in chillAST + + //IR_chillBlock(const IR_Code *ir, const StmtList& bDecl) : bDecl_(bDecl), cs_(NULL) { + // fprintf(stderr, "MISTAKE IR_chillBlock bdecl\n"); exit(-1); + // ir_ = ir; + //} + //IR_chillBlock(const IR_Code *ir, clang::CompoundStmt *cs) : cs_(cs) { + // fprintf(stderr, "MISTAKE IR_chillBlock cs\n"); exit(-1); + // ir_ = ir; + //} + IR_chillBlock( const IR_chillBlock *CB ) { // clone existing IR_chillBlock + ir_ = CB->ir_; + for (int i=0; i<CB->statements.size(); i++) statements.push_back( CB->statements[i] ); + chillAST = CB->chillAST; + } + + IR_chillBlock(const IR_Code *ir, chillAST_node *ast) { + ir_ = ir; + chillAST = ast; + } + + IR_chillBlock(const IR_Code *ir) { // : cs_(NULL), bDecl_(NULL) { + chillAST = NULL; + ir_ = ir; + } + + + ~IR_chillBlock() {} + omega::CG_outputRepr *extract() const; + omega::CG_outputRepr *original() const; + IR_Control *clone() const; + //StmtList getStmtList() const; + std::vector<chillAST_node*> getStmtList() const; + int numstatements() { return statements.size(); } ; + void addStatement( chillAST_node* s ); + + void dump() const; +}; + + +#ifdef NOTYET +struct IR_clangIf: public IR_If { + SgNode *ti_; + + IR_clangIf(const IR_Code *ir, SgNode *ti) { + ir_ = ir; + ti_ = ti; + } + ~IR_clangIf() { + } + omega::CG_outputRepr *condition() const; + IR_Block *then_body() const; + IR_Block *else_body() const; + IR_Block *convert(); + IR_Control *clone() const; +}; +#endif + + + + + +class aClangCompiler { +private: + //Chill_ASTConsumer *astConsumer_; + clang::ASTContext *astContext_; + + clang::DiagnosticOptions *diagnosticOptions; + clang::TextDiagnosticPrinter *pTextDiagnosticPrinter; + clang::DiagnosticIDs *diagID ; + clang::DiagnosticsEngine *diagnosticsEngine; + clang::CompilerInstance *Clang; + clang::Preprocessor *preprocessor; + //FileManager *FileMgr; + //clang::CompilerInvocation *CI; + + clang::FileManager *fileManager; + clang::SourceManager *sourceManager; + + // UNUSED? + clang::Diagnostic *diagnostic; + clang::LangOptions *languageOptions; + clang::HeaderSearchOptions *headerSearchOptions; + //clang::HeaderSearch *headerSearch; + clang::TargetOptions *targetOptions; + clang::TargetInfo *pTargetInfo; + clang::PreprocessorOptions *preprocessorOptions; + clang::FrontendOptions *frontendOptions; + clang::IdentifierTable *idTable; + clang::SelectorTable *selTable; + clang::Builtin::Context *builtinContext; + + +public: + char *SourceFileName; + chillAST_SourceFile * entire_file_AST; // TODO move out of public + + aClangCompiler( char *filename ); // constructor + chillAST_FunctionDecl *findprocedurebyname( char *name ); // someday, return the chill AST + clang::FunctionDecl *FD; + //Chill_ASTConsumer *getASTConsumer() { return astConsumer_; } + clang::ASTContext *getASTContext() { return astContext_; } + clang::SourceManager *getASTSourceManager() { return sourceManager; }; +}; + + +// singleton class for global clang initialization +// TODO: Add support for multiple files in same script +class IR_clangCode_Global_Init { +private: + static IR_clangCode_Global_Init *pinstance; // the one and only + // protecting the constructor is the SINGLETON PATTERN. a global by any other name + // IR_clangCode_Global_Init(); + ~IR_clangCode_Global_Init(); // is this hidden, too? + chillAST_FunctionDecl * chillFD; // the original C code + + clang::ASTContext *astContext_; + clang::SourceManager *sourceManager; +public: + clang::ASTContext *getASTContext() { return astContext_; } + clang::SourceManager *getSourceManager() { return sourceManager; }; + static IR_clangCode_Global_Init *Instance(char **argv); + static IR_clangCode_Global_Init *Instance() { return pinstance; } ; + aClangCompiler *ClangCompiler; // this is the thing we really just want one of + + + void setCurrentFunction( chillAST_node *F ) { chillFD = (chillAST_FunctionDecl *)F; } ; + chillAST_FunctionDecl *getCurrentFunction( ) { return chillFD; } ; + + + void setCurrentASTContext( clang::ASTContext *A ) { astContext_ = A;}; + clang::ASTContext *getCurrentASTContext() { return astContext_; } ; + + void setCurrentASTSourceManager( clang::SourceManager *S ) { sourceManager = S; } ; + clang::SourceManager *getCurrentASTSourceManager() { return sourceManager; } ; +}; + + + +class IR_clangCode: public IR_Code{ // for an entire file? A single function? +protected: + + // + char *filename; + char *procedurename; + + + chillAST_node *entire_file_AST; + chillAST_FunctionDecl * chillfunc; // the function we're currenly modifying + + std::vector<chillAST_VarDecl> entire_file_symbol_table; + // loop symbol table?? for (int i=0; ... ) ?? + + + + clang::FunctionDecl *func_; // a clang construct the function we're currenly modifying + clang::ASTContext *astContext_; + clang::SourceManager *sourceManager; + + // firstScope; + // symboltable1,2,3 ?? + // topleveldecls + // + +public: + clang::ASTContext *getASTContext() { return astContext_; } ; + clang::SourceManager *getASTSourceManager() { return sourceManager; } ; + + IR_clangCode(const char *filename, char *proc_name); + ~IR_clangCode(); + + IR_ScalarSymbol *CreateScalarSymbol(const IR_Symbol *sym, int i); + IR_ArraySymbol *CreateArraySymbol(const IR_Symbol *sym, std::vector<omega::CG_outputRepr *> &size, int i); + IR_ScalarRef *CreateScalarRef(const IR_ScalarSymbol *sym); + IR_ArrayRef *CreateArrayRef(const IR_ArraySymbol *sym, std::vector<omega::CG_outputRepr *> &index); + int ArrayIndexStartAt() { return 0;} // TODO FORTRAN + + std::vector<IR_ScalarRef *> FindScalarRef(const omega::CG_outputRepr *repr) const; + std::vector<IR_ArrayRef *> FindArrayRef(const omega::CG_outputRepr *repr) const; + std::vector<IR_Control *> FindOneLevelControlStructure(const IR_Block *block) const; + IR_Block *MergeNeighboringControlStructures(const std::vector<IR_Control *> &controls) const; + IR_Block *GetCode() const; + void ReplaceCode(IR_Control *old, omega::CG_outputRepr *repr); + void ReplaceExpression(IR_Ref *old, omega::CG_outputRepr *repr); + + IR_CONDITION_TYPE QueryBooleanExpOperation(const omega::CG_outputRepr*) const; + IR_OPERATION_TYPE QueryExpOperation(const omega::CG_outputRepr *repr) const; + std::vector<omega::CG_outputRepr *> QueryExpOperand(const omega::CG_outputRepr *repr) const; + IR_Ref *Repr2Ref(const omega::CG_outputRepr *) const; + + friend class IR_chillArraySymbol; + friend class IR_chillArrayRef; +}; + + +#endif diff --git a/include/ir_code.hh b/include/ir_code.hh index d695474..0946610 100644 --- a/include/ir_code.hh +++ b/include/ir_code.hh @@ -8,7 +8,7 @@ extra code generation. . Notes: - Unlike CG_outputRepr, IR_Symbol,IR_Ref and IR_Control are place holders + Unlike CG_outputRepr, IR_Symbol, IR_Ref and IR_Control are place holders to the underlying code, thus deleting or duplicating them does not affect the actual code. Similar to Omega builder's memory allocation strategy, all non-const pointer parameters of CG_outputRepr/IR_Symbol/IR_Ref/IR_Control @@ -22,60 +22,49 @@ #ifndef IR_CODE_HH #define IR_CODE_HH -/*! - * \file - * \brief CHiLL's compiler intermediate representation interface that extends Omega's builder interface to accomodate compiler analyses and extra code generation. - * - * Unlike CG_outputRepr, IR_Symbol,IR_Ref and IR_Control are place holders - * to the underlying code, thus deleting or duplicating them does not affect - * the actual code. Similar to Omega builder's memory allocation strategy, - * all non-const pointer parameters of CG_outputRepr/IR_Symbol/IR_Ref/IR_Control - * are destroyed after the call. - */ +#include <ir_enums.hh> +#include <chill_ast.hh> + +#include <vector> + +// needed for omega::coef_t below +#include <basic/util.h> // in omega ... why is this not in CG_output*.h? #include <code_gen/CG_outputRepr.h> #include <code_gen/CG_outputBuilder.h> -#include <vector> -enum IR_OPERATION_TYPE {IR_OP_CONSTANT, IR_OP_VARIABLE, - IR_OP_PLUS, IR_OP_MINUS, IR_OP_MULTIPLY, IR_OP_DIVIDE, - IR_OP_POSITIVE, IR_OP_NEGATIVE, - IR_OP_MIN, IR_OP_MAX, - IR_OP_ASSIGNMENT, - IR_OP_NULL, IR_OP_UNKNOWN}; -enum IR_CONTROL_TYPE {IR_CONTROL_LOOP, IR_CONTROL_IF, IR_CONTROL_WHILE, IR_CONTROL_BLOCK}; -enum IR_CONSTANT_TYPE {IR_CONSTANT_INT, IR_CONSTANT_FLOAT, - IR_CONSTANT_UNKNOWN}; -enum IR_CONDITION_TYPE {IR_COND_LT, IR_COND_LE, - IR_COND_GT, IR_COND_GE, - IR_COND_EQ, IR_COND_NE, - IR_COND_UNKNOWN}; -enum IR_ARRAY_LAYOUT_TYPE {IR_ARRAY_LAYOUT_ROW_MAJOR, - IR_ARRAY_LAYOUT_COLUMN_MAJOR, - IR_ARRAY_LAYOUT_SPACE_FILLING}; - -class IR_Code; - - -//! Base abstract class for scalar and array symbols. -/*! This is a place holder for related declaration in IR code.*/ + + +class IR_Code; // forward declaration + + +// Base abstract class for scalar and array symbols. This is a place +// holder for related declaration in IR code. struct IR_Symbol { const IR_Code *ir_; - + virtual ~IR_Symbol() {/* ir_ is not the responsibility of this object */} - virtual int n_dim() const = 0; + virtual int n_dim() const = 0; // IR_Symbol virtual std::string name() const = 0; virtual bool operator==(const IR_Symbol &that) const = 0; virtual bool operator!=(const IR_Symbol &that) const {return !(*this == that);} virtual IR_Symbol *clone() const = 0; /* shallow copy */ + + virtual bool isScalar() const { return false; } // default + virtual bool isArray() const { return false; } // default + virtual bool isPointer() const { return false; } // default + + //IR_SYMBOL_TYPE symtype; // base type: int, float, double, struct, .... typedef'd something + //IR_SYMBOL_TYPE getDatatype() ; }; struct IR_ScalarSymbol: public IR_Symbol { virtual ~IR_ScalarSymbol() {} - int n_dim() const {return 0;} + int n_dim() const {return 0;} // IR_ScalarSymbol virtual int size() const = 0; + bool isScalar() const { return true; } }; @@ -84,23 +73,33 @@ struct IR_ArraySymbol: public IR_Symbol { virtual int elem_size() const = 0; virtual omega::CG_outputRepr *size(int dim) const = 0; virtual IR_ARRAY_LAYOUT_TYPE layout_type() const = 0; + virtual IR_CONSTANT_TYPE elem_type() const = 0; + bool isArray() const { return true; } }; -//! Base abstract class for scalar and array references. -/*! This is a place holder for related code in IR code. */ +struct IR_PointerSymbol: public IR_Symbol { + virtual ~IR_PointerSymbol() {} + virtual omega::CG_outputRepr *size(int dim) const = 0; + virtual void set_size(int dim, omega::CG_outputRepr*) = 0; + virtual IR_CONSTANT_TYPE elem_type() const = 0; + bool isPointer() const { return true; } +}; + +// Base abstract class for scalar and array references. This is a +// place holder for related code in IR code. struct IR_Ref { const IR_Code *ir_; virtual ~IR_Ref() {/* ir_ is not the responsibility of this object */} - virtual int n_dim() const = 0; + virtual int n_dim() const = 0; // IR_Ref virtual bool is_write() const = 0; virtual std::string name() const = 0; virtual bool operator==(const IR_Ref &that) const = 0; virtual bool operator!=(const IR_Ref &that) const {return !(*this == that);} virtual omega::CG_outputRepr *convert() = 0; - //! shallow copy - virtual IR_Ref *clone() const = 0; + virtual IR_Ref *clone() const = 0; /* shallow copy */ + virtual void Dump() const { fprintf(stderr, "some IR_*Ref needs to implement Dump()\n"); int *i=0; int j=i[0]; }; }; @@ -108,7 +107,7 @@ struct IR_ConstantRef: public IR_Ref { IR_CONSTANT_TYPE type_; virtual ~IR_ConstantRef() {} - int n_dim() const {return 0;} + int n_dim() const {return 0;} // IR_ConstantRef bool is_write() const {return false;} std::string name() const {return std::string();} virtual bool is_integer() const {return type_ == IR_CONSTANT_INT;} @@ -118,10 +117,10 @@ struct IR_ConstantRef: public IR_Ref { struct IR_ScalarRef: public IR_Ref { virtual ~IR_ScalarRef() {} - int n_dim() const {return 0;} + int n_dim() const {return 0;} // IR_ScalarRef virtual IR_ScalarSymbol *symbol() const = 0; std::string name() const { - IR_ScalarSymbol *sym = symbol(); + IR_ScalarSymbol *sym = symbol(); // really inefficient. MAKE a symbol, just to get a name std::string s = sym->name(); delete sym; return s; @@ -137,54 +136,78 @@ struct IR_ScalarRef: public IR_Ref { struct IR_ArrayRef: public IR_Ref { virtual ~IR_ArrayRef() {} - int n_dim() const { + int n_dim() const { // IR_ArrayRef returns the size of the array IR_ArraySymbol *sym = symbol(); int n = sym->n_dim(); - delete sym; + // ?? delete sym; return n; } virtual omega::CG_outputRepr *index(int dim) const = 0; virtual IR_ArraySymbol *symbol() const = 0; - std::string name() const { - IR_ArraySymbol *sym = symbol(); + virtual std::string name() const { + // makes (constructs!) a symbol, just to copy a string! + IR_ArraySymbol *sym = symbol(); // TODO exceedingly wasteful std::string s = sym->name(); - delete sym; - return s; + // ?? delete sym; (goes out of scope, so deletes itself) + return s; // s ALSO goes out of scope but perhaps the info is copied at the other end } virtual int elem_size() const { IR_ArraySymbol *sym = symbol(); int s = sym->elem_size(); - delete sym; + // ?? delete sym; return s; } virtual IR_ARRAY_LAYOUT_TYPE layout_type() const { IR_ArraySymbol *sym = symbol(); IR_ARRAY_LAYOUT_TYPE t = sym->layout_type(); - delete sym; + // ?? delete sym; return t; } + virtual void Dump() const { fprintf(stderr, "IR_ArrayRef needs to implement Dump()\n"); }; +}; + +struct IR_PointerArrayRef: public IR_Ref { + + const IR_Code *ir_; + + virtual ~IR_PointerArrayRef() {} + int n_dim() const { // IR_PointerArrayRef returns size of the ... symbol? + IR_PointerSymbol *sym = symbol(); + int n = sym->n_dim(); + //Anand: Hack, fix later + //delete sym; + return n; + } + virtual omega::CG_outputRepr *index(int dim) const = 0; + virtual IR_PointerSymbol *symbol() const = 0; + std::string name() const { + IR_PointerSymbol *sym = symbol(); + std::string s = sym->name(); +//Anand: Hack, fix later + //delete sym; + return s; + } + + }; struct IR_Block; -//! Base abstract class for code structures. -/*! - * This is a place holder for the actual structure in the IR code. - * However, in cases that original source code may be transformed during - * loop initialization such as converting a while loop to a for loop or - * reconstructing the loop from low level IR code, the helper loop class (NOT - * IMPLEMENTED) must contain the transformed code that needs to be - * freed when out of service. - */ +// Base abstract class for code structures. This is a place holder +// for the actual structure in the IR code. However, in cases that +// original source code may be transformed during loop initialization +// such as converting a while loop to a for loop or reconstructing the +// loop from low level IR code, the helper loop class (NOT +// IMPLEMENTED) must contain the transformed code that needs to be +// freed when out of service. struct IR_Control { - const IR_Code *ir_; + const IR_Code *ir_; // hate this virtual ~IR_Control() {/* ir_ is not the responsibility of this object */} virtual IR_CONTROL_TYPE type() const = 0; virtual IR_Block *convert() = 0; - //! shallow copy - virtual IR_Control *clone() const = 0; + virtual IR_Control *clone() const = 0; /* shallow copy */ }; @@ -224,55 +247,98 @@ struct IR_While: public IR_Control { }; -//! Abstract class for compiler IR. +// Abstract class for compiler IR. class IR_Code { protected: - omega::CG_outputBuilder *ocg_; + // the only data members in IR_Code are Omega classes + omega::CG_outputBuilder *ocg_; // Omega Code Gen omega::CG_outputRepr *init_code_; omega::CG_outputRepr *cleanup_code_; + // OK, I lied + static int ir_pointer_counter; + static int ir_array_counter; + public: + + int getPointerCounter() { return ir_pointer_counter; } + int getArrayCounter() { return ir_array_counter; } + + // TODO can't get the initialize of counters to work !! + int getAndIncrementPointerCounter() { if (ir_pointer_counter == 0) ir_pointer_counter= 1; ir_pointer_counter++; return ir_pointer_counter-1; } + int getAndIncrementArrayCounter() { if (ir_array_counter == 0) ir_array_counter= 1; ir_array_counter += 1; return ir_array_counter-1; } + + // if all flavors of ir_code use chillAST internally ... + chillAST_FunctionDecl * func_defn; // the function we're modifying + chillAST_FunctionDecl *GetChillFuncDefinition() { return func_defn; }; + IR_Code() {ocg_ = NULL; init_code_ = cleanup_code_ = NULL;} - virtual ~IR_Code() { delete ocg_; delete init_code_; delete cleanup_code_; } - /* the content of init and cleanup code have already been released in derived classes */ + virtual ~IR_Code() { delete ocg_; delete init_code_; delete cleanup_code_; } /* the content of init and cleanup code have already been released in derived classes */ - /*! - * \param memory_type is for differentiating the location of - * where the new memory is allocated. this is useful for - * processors with heterogeneous memory hierarchy. - */ + omega::CG_outputRepr* init_code(){ return init_code_; } + + // memory_type is for differentiating the location of where the new memory is allocated. + // this is useful for processors with heterogeneous memory hierarchy. virtual IR_ScalarSymbol *CreateScalarSymbol(const IR_Symbol *sym, int memory_type) = 0; - virtual IR_ArraySymbol *CreateArraySymbol(const IR_Symbol *sym, std::vector<omega::CG_outputRepr *> &size, int memory_type) = 0; - + virtual IR_ScalarSymbol *CreateScalarSymbol(IR_CONSTANT_TYPE type, int memory_type, std::string name="" ) =0; + + virtual IR_ArraySymbol *CreateArraySymbol(const IR_Symbol *sym, + std::vector<omega::CG_outputRepr *> &size, + int memory_type) = 0; + virtual IR_ArraySymbol *CreateArraySymbol(omega::CG_outputRepr *type, + std::vector<omega::CG_outputRepr *> &size_repr) =0; + + virtual IR_PointerSymbol *CreatePointerSymbol(const IR_Symbol *sym, + std::vector<omega::CG_outputRepr *> &size_repr) =0; + virtual IR_PointerSymbol *CreatePointerSymbol(const IR_CONSTANT_TYPE type, + std::vector<omega::CG_outputRepr *> &size_repr, + std::string name="") =0; + + virtual IR_PointerSymbol *CreatePointerSymbol(omega::CG_outputRepr *type, + std::vector<omega::CG_outputRepr *> &size_repr) =0; + virtual IR_ScalarRef *CreateScalarRef(const IR_ScalarSymbol *sym) = 0; virtual IR_ArrayRef *CreateArrayRef(const IR_ArraySymbol *sym, std::vector<omega::CG_outputRepr *> &index) = 0; + + virtual omega::CG_outputRepr* CreateArrayRefRepr(const IR_ArraySymbol *sym, + std::vector<omega::CG_outputRepr *> &index) { + //IR_ArrayRef *AR = CreateArrayRef(sym, index); + //return new omega::CG_outputRepr(AR); + fprintf(stderr, "ir_code.hh SOME SUBCLASS OF ir_code did not implement CreateArrayRefRepr()\n"); + return NULL; + } + + virtual IR_PointerArrayRef *CreatePointerArrayRef( IR_PointerSymbol *sym, + std::vector<omega::CG_outputRepr *> &index) =0; virtual int ArrayIndexStartAt() {return 0;} - /*! - * Array references should be returned in their accessing order. - * - * ~~~ - * e.g. s1: A[i] = A[i-1] - * s2: B[C[i]] = D[i] + E[i] - * return A[i-1], A[i], D[i], E[i], C[i], B[C[i]] in this order. - * ~~~ - */ + virtual void CreateDefineMacro(std::string s,std::string args, omega::CG_outputRepr *repr) = 0; + virtual void CreateDefineMacro(std::string s,std::string args, std::string repr) = 0; + virtual void CreateDefineMacro(std::string s, std::vector<std::string> args,omega::CG_outputRepr *repr) {}; // TODO make pure virtual + + virtual omega::CG_outputRepr *CreateArrayType(IR_CONSTANT_TYPE type, omega::CG_outputRepr* size)=0; + virtual omega::CG_outputRepr *CreatePointerType(IR_CONSTANT_TYPE type)=0; + virtual omega::CG_outputRepr *CreatePointerType(omega::CG_outputRepr *type)=0; + virtual omega::CG_outputRepr *CreateScalarType(IR_CONSTANT_TYPE type)=0; + // Array references should be returned in their accessing order. + // e.g. s1: A[i] = A[i-1] + // s2: B[C[i]] = D[i] + E[i] + // return A[i-1], A[i], D[i], E[i], C[i], B[C[i]] in this order. virtual std::vector<IR_ArrayRef *> FindArrayRef(const omega::CG_outputRepr *repr) const = 0; + virtual std::vector<IR_PointerArrayRef *> FindPointerArrayRef(const omega::CG_outputRepr *repr) const = 0 ; virtual std::vector<IR_ScalarRef *> FindScalarRef(const omega::CG_outputRepr *repr) const = 0; + virtual bool parent_is_array(IR_ArrayRef *a)=0; - /*! - * If there is no sub structure interesting inside the block, return empty, - * so we know when to stop looking inside. - */ + // If there is no sub structure interesting inside the block, return empty, + // so we know when to stop looking inside. virtual std::vector<IR_Control *> FindOneLevelControlStructure(const IR_Block *block) const = 0; - /*! - * All controls must be in the same block, at the same level and in - * contiguous lexical order as appeared in parameter vector. - */ + // All controls must be in the same block, at the same level and in + // contiguous lexical order as appeared in parameter vector. virtual IR_Block *MergeNeighboringControlStructures(const std::vector<IR_Control *> &controls) const = 0; virtual IR_Block *GetCode() const = 0; + virtual IR_Control *GetCode(omega::CG_outputRepr *code) const = 0; virtual void ReplaceCode(IR_Control *old, omega::CG_outputRepr *repr) = 0; virtual void ReplaceExpression(IR_Ref *old, omega::CG_outputRepr *repr) = 0; @@ -280,10 +346,34 @@ public: virtual IR_CONDITION_TYPE QueryBooleanExpOperation(const omega::CG_outputRepr *repr) const = 0; virtual std::vector<omega::CG_outputRepr *> QueryExpOperand(const omega::CG_outputRepr *repr) const = 0; virtual IR_Ref *Repr2Ref(const omega::CG_outputRepr *repr) const = 0; - - //! Codegen Omega code builder interface - omega::CG_outputBuilder *builder() const {return ocg_;} + + // Manu:: Added functions required for reduction operation + // virtual omega::CG_outputRepr * FromSameStmt(IR_ArrayRef *A, IR_ArrayRef *B) = 0; + virtual bool FromSameStmt(IR_ArrayRef *A, IR_ArrayRef *B) = 0; + virtual void printStmt(const omega::CG_outputRepr *repr) = 0; + virtual int getStmtType(const omega::CG_outputRepr *repr) = 0; + virtual IR_OPERATION_TYPE getReductionOp(const omega::CG_outputRepr *repr) = 0; + virtual IR_Control * FromForStmt(const omega::CG_outputRepr *repr) = 0; + + // Manu:: Added functions for scalar expansion + virtual IR_ArraySymbol *CreateArraySymbol(omega::CG_outputRepr *size, const IR_Symbol *sym) = 0; + virtual bool ReplaceRHSExpression(omega::CG_outputRepr *code, IR_Ref *ref) = 0; + virtual omega::CG_outputRepr * GetRHSExpression(omega::CG_outputRepr *code) = 0; + virtual omega::CG_outputRepr * GetLHSExpression(omega::CG_outputRepr *code) = 0; + virtual omega::CG_outputRepr *CreateMalloc(const IR_CONSTANT_TYPE type, std::string lhs, + omega::CG_outputRepr * size_repr)=0; + virtual omega::CG_outputRepr *CreateMalloc(omega::CG_outputRepr *type, std::string variable, + omega::CG_outputRepr * size_repr)=0; + virtual omega::CG_outputRepr *CreateFree(omega::CG_outputRepr * exp)=0; + + //void Dump() { ocg_->Dump(); }; + //--------------------------------------------------------------------------- + // CC Omega code builder interface here + + //--------------------------------------------------------------------------- + omega::CG_outputBuilder *builder() const { return ocg_;} }; #endif + diff --git a/include/ir_enums.hh b/include/ir_enums.hh new file mode 100644 index 0000000..742dbe8 --- /dev/null +++ b/include/ir_enums.hh @@ -0,0 +1,24 @@ + +#ifndef IR_ENUMS_HH +#define IR_ENUMS_HH +enum IR_OPERATION_TYPE {IR_OP_CONSTANT, IR_OP_VARIABLE, IR_OP_ARRAY_VARIABLE, + IR_OP_PLUS, IR_OP_MINUS, IR_OP_MULTIPLY, IR_OP_DIVIDE, + IR_OP_POSITIVE, IR_OP_NEGATIVE, IR_OP_NEQ, + IR_OP_MIN, IR_OP_MAX,IR_OP_EQ, IR_OP_LE, IR_OP_GE, + IR_OP_ASSIGNMENT, IR_OP_PLUS_ASSIGNMENT, IR_OP_CCAST, + IR_OP_NULL, IR_OP_MOD, IR_OP_UNKNOWN}; +enum IR_CONTROL_TYPE {IR_CONTROL_LOOP, IR_CONTROL_IF, IR_CONTROL_WHILE, IR_CONTROL_BLOCK}; + +enum IR_CONSTANT_TYPE {IR_CONSTANT_INT, IR_CONSTANT_FLOAT, IR_CONSTANT_DOUBLE, + IR_CONSTANT_UNKNOWN}; + +enum IR_SYMBOL_TYPE {IR_SYMBOL_UNKNOWN=0, IR_SYMBOL_INT, IR_SYMBOL_FLOAT, IR_SYMBOL_DOUBLE}; // structs, etc ?? are UNKNOWN + +enum IR_CONDITION_TYPE {IR_COND_LT, IR_COND_LE, + IR_COND_GT, IR_COND_GE, + IR_COND_EQ, IR_COND_NE, + IR_COND_UNKNOWN}; +enum IR_ARRAY_LAYOUT_TYPE {IR_ARRAY_LAYOUT_ROW_MAJOR, + IR_ARRAY_LAYOUT_COLUMN_MAJOR, + IR_ARRAY_LAYOUT_SPACE_FILLING}; +#endif diff --git a/include/ir_rose.hh b/include/ir_rose.hh deleted file mode 100644 index 03ea50d..0000000 --- a/include/ir_rose.hh +++ /dev/null @@ -1,267 +0,0 @@ -#ifndef IR_ROSE_HH -#define IR_ROSE_HH - -/*! - * \file - * \brief CHiLL's rose interface. - */ - -#include <omega.h> -#include "ir_code.hh" -#include "ir_rose_utils.hh" -#include <AstInterface_ROSE.h> -#include "chill_error.hh" -#include "staticSingleAssignment.h" -#include "VariableRenaming.h" -#include "ssaUnfilteredCfg.h" -#include "virtualCFG.h" -#include <omega.h> - -struct IR_roseScalarSymbol: public IR_ScalarSymbol { - SgVariableSymbol* vs_; - - IR_roseScalarSymbol(const IR_Code *ir, SgVariableSymbol *vs) { - ir_ = ir; - vs_ = vs; - } - - std::string name() const; - int size() const; - bool operator==(const IR_Symbol &that) const; - IR_Symbol *clone() const; -}; - -struct IR_roseArraySymbol: public IR_ArraySymbol { - - SgVariableSymbol* vs_; - - IR_roseArraySymbol(const IR_Code *ir, SgVariableSymbol* vs) { - ir_ = ir; - vs_ = vs; - } - std::string name() const; - int elem_size() const; - int n_dim() const; - omega::CG_outputRepr *size(int dim) const; - bool operator==(const IR_Symbol &that) const; - IR_ARRAY_LAYOUT_TYPE layout_type() const; - IR_Symbol *clone() const; - -}; - -struct IR_roseConstantRef: public IR_ConstantRef { - union { - omega::coef_t i_; - double f_; - }; - - IR_roseConstantRef(const IR_Code *ir, omega::coef_t i) { - ir_ = ir; - type_ = IR_CONSTANT_INT; - i_ = i; - } - IR_roseConstantRef(const IR_Code *ir, double f) { - ir_ = ir; - type_ = IR_CONSTANT_FLOAT; - f_ = f; - } - omega::coef_t integer() const { - assert(is_integer()); - return i_; - } - bool operator==(const IR_Ref &that) const; - omega::CG_outputRepr *convert(); - IR_Ref *clone() const; - -}; - -struct IR_roseScalarRef: public IR_ScalarRef { - SgAssignOp *ins_pos_; - int op_pos_; // -1 means destination operand, otherwise source operand - SgVarRefExp *vs_; - int is_write_; - IR_roseScalarRef(const IR_Code *ir, SgVarRefExp *sym) { - ir_ = ir; - ins_pos_ = isSgAssignOp(sym->get_parent()); - op_pos_ = 0; - if (ins_pos_ != NULL) - if (sym == isSgVarRefExp(ins_pos_->get_lhs_operand())) - op_pos_ = -1; - - vs_ = sym; - } - IR_roseScalarRef(const IR_Code *ir, SgVarRefExp *ins, int pos) { - ir_ = ir; - /* ins_pos_ = ins; - op_pos_ = pos; - SgExpression* op; - if (pos == -1) - op = ins->get_lhs_operand(); - else - op = ins->get_rhs_operand(); - - */ - - is_write_ = pos; - - /* if (vs_ == NULL || pos > 0) - throw ir_error( - "Src operand not a variable or more than one src operand!!"); - */ - - vs_ = ins; - - } - bool is_write() const; - IR_ScalarSymbol *symbol() const; - bool operator==(const IR_Ref &that) const; - omega::CG_outputRepr *convert(); - IR_Ref *clone() const; -}; - -struct IR_roseArrayRef: public IR_ArrayRef { - - SgPntrArrRefExp *ia_; - - int is_write_; - IR_roseArrayRef(const IR_Code *ir, SgPntrArrRefExp *ia, int write) { - ir_ = ir; - ia_ = ia; - is_write_ = write; - } - bool is_write() const; - omega::CG_outputRepr *index(int dim) const; - IR_ArraySymbol *symbol() const; - bool operator==(const IR_Ref &that) const; - omega::CG_outputRepr *convert(); - IR_Ref *clone() const; -}; - -struct IR_roseLoop: public IR_Loop { - SgNode *tf_; - - IR_roseLoop(const IR_Code *ir, SgNode *tf) { - ir_ = ir; - tf_ = tf; - } - - IR_ScalarSymbol *index() const; - omega::CG_outputRepr *lower_bound() const; - omega::CG_outputRepr *upper_bound() const; - IR_CONDITION_TYPE stop_cond() const; - IR_Block *body() const; - IR_Block *convert(); - int step_size() const; - IR_Control *clone() const; -}; - -struct IR_roseBlock: public IR_Block { - SgNode* tnl_; - SgNode *start_, *end_; - - IR_roseBlock(const IR_Code *ir, SgNode *tnl, SgNode *start, SgNode *end) { - ir_ = ir; - tnl_ = tnl; - start_ = start; - end_ = end; - } - - IR_roseBlock(const IR_Code *ir, SgNode *tnl) { - ir_ = ir; - tnl_ = tnl; - start_ = tnl_->get_traversalSuccessorByIndex(0); - end_ = tnl_->get_traversalSuccessorByIndex( - (tnl_->get_numberOfTraversalSuccessors()) - 1); - } - omega::CG_outputRepr *extract() const; - omega::CG_outputRepr *original() const; - IR_Control *clone() const; -}; - -struct IR_roseIf: public IR_If { - SgNode *ti_; - - IR_roseIf(const IR_Code *ir, SgNode *ti) { - ir_ = ir; - ti_ = ti; - } - ~IR_roseIf() { - } - omega::CG_outputRepr *condition() const; - IR_Block *then_body() const; - IR_Block *else_body() const; - IR_Block *convert(); - IR_Control *clone() const; -}; - -class IR_roseCode_Global_Init { -private: - static IR_roseCode_Global_Init *pinstance; -public: - SgProject* project; - static IR_roseCode_Global_Init *Instance(char** argv); -}; - -class IR_roseCode: public IR_Code { -protected: - SgSourceFile* file; - SgGlobal *root; - SgGlobal *firstScope; - SgSymbolTable* symtab_; - SgSymbolTable* symtab2_; - SgSymbolTable* symtab3_; - SgDeclarationStatementPtrList::iterator p; - SgFunctionDeclaration *func; - bool is_fortran_; - int i_; - StaticSingleAssignment *ssa_for_scalar; - ssa_unfiltered_cfg::SSA_UnfilteredCfg *main_ssa; - VariableRenaming *varRenaming_for_scalar; -public: - IR_roseCode(const char *filename, const char* proc_name); - ~IR_roseCode(); - - IR_ScalarSymbol *CreateScalarSymbol(const IR_Symbol *sym, int memory_type = - 0); - IR_ArraySymbol *CreateArraySymbol(const IR_Symbol *sym, - std::vector<omega::CG_outputRepr *> &size, int memory_type = 0); - IR_ScalarRef *CreateScalarRef(const IR_ScalarSymbol *sym); - IR_ArrayRef *CreateArrayRef(const IR_ArraySymbol *sym, - std::vector<omega::CG_outputRepr *> &index); - int ArrayIndexStartAt() { - if (is_fortran_) - return 1; - else - return 0; - } - - void populateLists(SgNode* tnl_1, SgStatementPtrList* list_1, - SgStatementPtrList& output_list_1); - void populateScalars(const omega::CG_outputRepr *repr1, - std::map<SgVarRefExp*, IR_ScalarRef*> &read_scalars_1, - std::map<SgVarRefExp*, IR_ScalarRef*> &write_scalars_1, - std::set<std::string> &indices, std::vector<std::string> &index); - std::vector<IR_ArrayRef *> FindArrayRef( - const omega::CG_outputRepr *repr) const; - std::vector<IR_ScalarRef *> FindScalarRef( - const omega::CG_outputRepr *repr) const; - std::vector<IR_Control *> FindOneLevelControlStructure( - const IR_Block *block) const; - IR_Block *MergeNeighboringControlStructures( - const std::vector<IR_Control *> &controls) const; - IR_Block *GetCode() const; - void ReplaceCode(IR_Control *old, omega::CG_outputRepr *repr); - void ReplaceExpression(IR_Ref *old, omega::CG_outputRepr *repr); - - IR_OPERATION_TYPE QueryExpOperation(const omega::CG_outputRepr *repr) const; - IR_CONDITION_TYPE QueryBooleanExpOperation( - const omega::CG_outputRepr *repr) const; - std::vector<omega::CG_outputRepr *> QueryExpOperand( - const omega::CG_outputRepr *repr) const; - IR_Ref *Repr2Ref(const omega::CG_outputRepr *) const; - void finalizeRose(); - friend class IR_roseArraySymbol; - friend class IR_roseArrayRef; -}; - -#endif diff --git a/include/ir_rose_utils.hh b/include/ir_rose_utils.hh deleted file mode 100644 index 350aa24..0000000 --- a/include/ir_rose_utils.hh +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef IR_ROSE_UTILS_HH -#define IR_ROSE_UTILS_HH - -/*! - * \file - * \brief ROSE interface utilities - */ -#include <vector> -#include <rose.h> -#include <sageBuilder.h> - -std::vector<SgForStatement *> find_deepest_loops(SgNode *tnl); -std::vector<SgForStatement *> find_loops(SgNode *tnl); - -SgNode* loop_body_at_level(SgNode* tnl, int level); -SgNode* loop_body_at_level(SgForStatement* loop, int level); -void swap_node_for_node_list(SgNode* tn, SgNode* new_tnl); - -#endif diff --git a/include/irtools.hh b/include/irtools.hh index 6648847..d85b76b 100644 --- a/include/irtools.hh +++ b/include/irtools.hh @@ -1,29 +1,22 @@ #ifndef IRTOOLS_HH #define IRTOOLS_HH -/*! - * \file - * \brief Useful tools to analyze code in compiler IR format. - */ - #include <vector> #include <omega.h> #include <code_gen/CG_outputRepr.h> #include "ir_code.hh" #include "dep.hh" +#define DEP_DEBUG 0 -//! It is used to initialize a loop. +// IR tree is used to initialize a loop. For a loop node, payload is +// its mapped iteration space dimension. For a simple block node, +// payload is its mapped statement number. Normal if-else is split +// into two nodes where the one with odd payload represents then-part and +// the one with even payload represents else-part. struct ir_tree_node { IR_Control *content; ir_tree_node *parent; std::vector<ir_tree_node *> children; -/*! - * * For a loop node, payload is its mapped iteration space dimension. - * * For a simple block node, payload is its mapped statement number. - * * Normal if-else is splitted into two nodes - * * the one with odd payload represents then-part and - * * the one with even payload represents else-part. - */ int payload; ~ir_tree_node() { @@ -33,45 +26,32 @@ struct ir_tree_node { } }; -//! Build IR tree from the source code -/*! - * Block type node can only be leaf, i.e., there is no further stuctures inside a block allowed - * @param control - * @param parent - * @return - */ std::vector<ir_tree_node *> build_ir_tree(IR_Control *control, ir_tree_node *parent = NULL); -//! Extract statements from IR tree -/*! - * Statements returned are ordered in lexical order in the source code - * @param ir_tree - * @return - */ std::vector<ir_tree_node *> extract_ir_stmts( const std::vector<ir_tree_node *> &ir_tree); bool is_dependence_valid(ir_tree_node *src_node, ir_tree_node *dst_node, const DependenceVector &dv, bool before); -//! test data dependeces between two statements -/*! - * The first statement in parameter must be lexically before the second statement in parameter. - * Returned dependences are all lexicographically positive - * @param ir - * @param repr1 - * @param IS1 - * @param repr2 - * @param IS2 - * @param freevar - * @param index - * @param i - * @param j - * @return Dependecies between the two statements. First vector is dependencies from first to second, - * second vector is the reverse - */ std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > test_data_dependences( IR_Code *ir, const omega::CG_outputRepr *repr1, const omega::Relation &IS1, const omega::CG_outputRepr *repr2, const omega::Relation &IS2, std::vector<omega::Free_Var_Decl*> &freevar, - std::vector<std::string> index, int i, int j); + std::vector<std::string> index, int i, int j, + std::map<std::string, std::vector<omega::CG_outputRepr * > > &uninterpreted_symbols, + std::map<std::string, std::vector<omega::CG_outputRepr * > > &uninterpreted_symbols_stringrepr); + +std::vector<omega::CG_outputRepr *> collect_loop_inductive_and_conditionals(ir_tree_node * stmt_node); + +// Manu +typedef std::map<int, std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > > tempResultMap; +typedef std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > DVPair; + +// Manu:: this function is required for reduction operation +//omega::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); +int stmtType(IR_Code *ir, const omega::CG_outputRepr *repr); +IR_OPERATION_TYPE getReductionOperator(IR_Code *ir, const omega::CG_outputRepr *repr); +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); +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 ); #endif diff --git a/include/loop.hh b/include/loop.hh index e02b7e9..3909e6c 100644 --- a/include/loop.hh +++ b/include/loop.hh @@ -1,24 +1,6 @@ #ifndef LOOP_HH #define LOOP_HH -/*! - * \file - * \brief Core loop transformation functionality. - * - * "level" (starting from 1) means loop level and it corresponds to "dim" - * (starting from 0) in transformed iteration space [c_1,l_1,c_2,l_2,...., - * c_n,l_n,c_(n+1)], e.g., l_2 is loop level 2 in generated code, dim 3 - * in transformed iteration space, and variable 4 in Omega relation. - * All c's are constant numbers only and they will not show up as actual loops. - * - * Formula: - * - * ~~~ - * dim = 2*level - 1 - * var = dim + 1 - * ~~~ - */ - #include <omega.h> #include <code_gen/codegen.h> @@ -29,6 +11,10 @@ #include "dep.hh" #include "ir_code.hh" #include "irtools.hh" +#include <code_gen/CG_stringBuilder.h> + +#include "stencil.hh" + class IR_Code; @@ -36,30 +22,35 @@ enum TilingMethodType { StridedTile, CountedTile }; enum LoopLevelType { LoopLevelOriginal, LoopLevelTile, LoopLevelUnknown }; -//! Describes properties of each loop level of a statement. +// Describes properties of each loop level of a statement. "payload" +// for LoopLevelOriginal means iteration space dimension, for +// LoopLevelTile means tiled loop level. Special value -1 for +// LoopLevelTile means purely derived loop. For dependence dimension +// payloads, the values must be in an increasing order. +// "parallel_level" will be used by code generation to support +// multi-level parallelization (default 0 means sequential loop under +// the current parallelization level). struct LoopLevel { LoopLevelType type; -/*! - * For LoopLevelOriginal means iteration space dimension - * For LoopLevelTile means tiled loop level. Special value -1 for - * LoopLevelTile means purely derived loop. For dependence dimension - * payloads, the values must be in an increasing order. - */ int payload; -/*! - * Used by code generation to support - * multi-level parallelization (default 0 means sequential loop under - * the current parallelization level). - */ int parallel_level; + bool segreducible; + std::string segment_descriptor; }; + struct Statement { omega::CG_outputRepr *code; omega::Relation IS; omega::Relation xform; std::vector<LoopLevel> loop_level; ir_tree_node *ir_stmt_node; + bool has_inspector; + int reduction; // Manu:: 0 == reduction not possible, 1 == reduction possible, 2 == reduction with some processing + IR_OPERATION_TYPE reductionOp; // Manu + + class stencilInfo *statementStencil; + //protonu--temporarily putting this back here //omega::Tuple<int> nonSplitLevels; //end--protonu. @@ -72,22 +63,30 @@ protected: static const std::string tmp_loop_var_name_prefix; int overflow_var_name_counter; static const std::string overflow_var_name_prefix; - std::vector<int> stmt_nesting_level_; + std::vector<int> stmt_nesting_level_; // UNDERLINE std::vector<std::string> index; std::map<int, omega::CG_outputRepr *> replace; + std::map<int, std::pair<int, std::string> > reduced_statements; public: + void debugRelations() const; IR_Code *ir; + std::vector<IR_PointerSymbol *> ptr_variables; std::vector<omega::Free_Var_Decl*> freevar; std::vector<Statement> stmt; + std::vector<omega::CG_outputRepr*> actual_code; // ????? std::vector<ir_tree_node *> ir_stmt; std::vector<ir_tree_node *> ir_tree; + std::set<std::string> reduced_write_refs; + std::map<std::string, int> array_dims; DependenceGraph dep; int num_dep_dim; omega::Relation known; omega::CG_outputRepr *init_code; omega::CG_outputRepr *cleanup_code; std::map<int, std::vector<omega::Free_Var_Decl *> > overflow; + std::vector<std::map<std::string, std::vector<omega::CG_outputRepr * > > > uninterpreted_symbols; + std::vector<std::map<std::string, std::vector<omega::CG_outputRepr * > > >uninterpreted_symbols_stringrepr; protected: @@ -110,15 +109,20 @@ protected: void apply_xform(std::set<int> &active); void apply_xform(); std::set<int> getSubLoopNest(int stmt_num, int level) const; - + int getMinLexValue(std::set<int> stmts, int level); + public: Loop() { ir = NULL; tmp_loop_var_name_counter = 1; init_code = NULL; } Loop(const IR_Control *control); ~Loop(); - omega::CG_outputRepr *getCode(int effort = 1) const; - void printCode(int effort = 1) const; + omega::CG_outputRepr *getCode(int effort = 3) const; // TODO was 1 + //chillAST_node* LoopCuda::getCode(int effort, std::set<int> stmts) const; + + void stencilASEPadded(int stmt_num); + + void printCode(int effort = 3) const; void addKnown(const omega::Relation &cond); void print_internal_loop_structure() const; bool isInitialized() const; @@ -130,16 +134,14 @@ public: std::vector<std::set <int > > sort_by_same_loops(std::set<int > active, int level); // - //! legacy unimodular transformations for perfectly nested loops - /*! - * e.g. \f$M*(i,j)^T = (i',j')^T or M*(i,j,1)^T = (i',j')^T\f$ - */ + // legacy unimodular transformations for perfectly nested loops + // e.g. M*(i,j)^T = (i',j')^T or M*(i,j,1)^T = (i',j')^T + // bool nonsingular(const std::vector<std::vector<int> > &M); - /*! - * \defgroup hltrans High-level loop transformations - * @{ - */ + // + // high-level loop transformations + // void permute(const std::set<int> &active, const std::vector<int> &pi); void permute(int stmt_num, int level, const std::vector<int> &pi); void permute(const std::vector<int> &pi); @@ -148,46 +150,19 @@ public: void tile(int stmt_num, int level, int tile_size, int outer_level = 1, TilingMethodType method = StridedTile, int alignment_offset = 0, int alignment_multiple = 1); std::set<int> split(int stmt_num, int level, const omega::Relation &cond); std::set<int> unroll(int stmt_num, int level, int unroll_amount, std::vector< std::vector<std::string> >idxNames= std::vector< std::vector<std::string> >(), int cleanup_split_level = 0); - - //! Datacopy function by reffering arrays by numbers - /*! - * for example - * ~~~ - * 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] - * - * @param array_ref_nums - * @param level - * @param allow_extra_read - * @param fastest_changing_dimension - * @param padding_stride - * @param padding_alignment - * @param memory_type - * @return - */ + bool datacopy(const std::vector<std::pair<int, std::vector<int> > > &array_ref_nums, int level, bool allow_extra_read = false, int fastest_changing_dimension = -1, int padding_stride = 1, int padding_alignment = 4, int memory_type = 0); - //! Datacopy function by reffering arrays by name - /*! - * parameter array_name=A means to copy data touched by A[i-1] and A[i] - * @param stmt_num - * @param level - * @param array_name - * @param allow_extra_read - * @param fastest_changing_dimension - * @param padding_stride - * @param padding_alignment - * @param memory_type - * @return - */ bool datacopy(int stmt_num, int level, const std::string &array_name, bool allow_extra_read = false, int fastest_changing_dimension = -1, int padding_stride = 1, int padding_alignment = 4, int memory_type = 0); bool datacopy_privatized(int stmt_num, int level, const std::string &array_name, const std::vector<int> &privatized_levels, bool allow_extra_read = false, int fastest_changing_dimension = -1, int padding_stride = 1, int padding_alignment = 1, int memory_type = 0); bool 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 = false, int fastest_changing_dimension = -1, int padding_stride = 1, int padding_alignment = 1, int memory_type = 0); bool 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 = 0); + //std::set<int> scalar_replacement_inner(int stmt_num); + bool find_stencil_shape( int stmt_num ); Graph<std::set<int>, bool> construct_induced_graph_at_level(std::vector<std::set<int> > s, DependenceGraph dep, int dep_dim); - std::vector<std::set<int> > typed_fusion(Graph<std::set<int>, bool> g); + std::vector<std::set<int> > typed_fusion(Graph<std::set<int>, bool> g, std::vector<bool> &types); + void fuse(const std::set<int> &stmt_nums, int level); void distribute(const std::set<int> &stmt_nums, int level); void skew(const std::set<int> &stmt_nums, int level, const std::vector<int> &skew_amount); @@ -195,36 +170,44 @@ public: void scale(const std::set<int> &stmt_nums, int level, int scale_amount); void reverse(const std::set<int> &stmt_nums, int level); void peel(int stmt_num, int level, int peel_amount = 1); - /*! - * \defgroup hlfancy fancy loop transformations - * @{ - */ + // + // more fancy loop transformations + // void modular_shift(int stmt_num, int level, int shift_amount) {} void diagonal_map(int stmt_num, const std::pair<int, int> &levels, int offset) {} void modular_partition(int stmt_num, int level, int stride) {} - /*! @} */ + void flatten(int stmt_num, std::string index_name, std::vector<int> &loop_levels, std::string inspector_name); + void normalize(int stmt_num, int loop_level); + + void generate_ghostcells_v2(std::vector<int> stmt, int loop_num, int ghost_value, int hold_inner_loop_constant=0 ); - /*! - * \defgroup hlderived derived loop transformations - * @{ - */ + + // + // derived loop transformations + // void shift_to(int stmt_num, int level, int absolute_position); std::set<int> unroll_extra(int stmt_num, int level, int unroll_amount, int cleanup_split_level = 0); bool is_dependence_valid_based_on_lex_order(int i, int j, - const DependenceVector &dv, bool before); - /*! @} */ + const DependenceVector &dv, bool before); + void split_with_alignment(int stmt_num, int level, int alignment, + int direction=0); + + // Manu:: reduction operation + void reduce(int stmt_num, std::vector<int> &level, int param, std::string func_name, std::vector<int> &seq_levels, std::vector<int> cudaized_levels = std::vector<int>(), int bound_level = -1); + void scalar_expand(int stmt_num, const std::vector<int> &levels, std::string arrName, int memory_type =0, int padding_alignment=0, int assign_then_accumulate = 1, int padding_stride = 0); + void ELLify(int stmt_num, std::vector<std::string> arrays_to_pad, int pad_to, bool dense_pad = false, std::string dense_pad_pos_array = ""); + void compact(int stmt_num, int level, std::string new_array, int zero, + std::string data_array); + void make_dense(int stmt_num, int loop_level, std::string new_loop_index); + void set_array_size(std::string name, int size ); + omega::CG_outputRepr * iegen_parser(std::string &str, std::vector<std::string> &index_names); - /*! - * \defgroup hlother other public operations - * @{ - */ + // + // other public operations + // void pragma(int stmt_num, int level, const std::string &pragmaText); void prefetch(int stmt_num, int level, const std::string &arrName, int hint); - /*! @} */ - - /*! @} */ + //void prefetch(int stmt_num, int level, const std::string &arrName, const std::string &indexName, int offset, int hint); }; - - #endif diff --git a/include/omegatools.hh b/include/omegatools.hh index b51b2bd..2f56971 100644 --- a/include/omegatools.hh +++ b/include/omegatools.hh @@ -1,11 +1,6 @@ #ifndef OMEGATOOLS_HH #define OMEGATOOLS_HH -/*! - * \file - * \brief Useful tools involving Omega manipulation. - */ - #include <string> #include <omega.h> #include "dep.hh" @@ -13,81 +8,92 @@ std::string tmp_e(); -//! Convert expression tree to omega relation. -/*! - * \param destroy shallow deallocation of "repr", not freeing the actual code inside. - */ -void exp2formula(IR_Code *ir, omega::Relation &r, omega::F_And *f_root, +void exp2formula(IR_Code *ir, + omega::Relation &r, + omega::F_And *f_root, std::vector<omega::Free_Var_Decl *> &freevars, - omega::CG_outputRepr *repr, omega::Variable_ID lhs, char side, - IR_CONDITION_TYPE rel, bool destroy); + omega::CG_outputRepr *repr, + omega::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); -//! Build dependence relation for two array references. omega::Relation arrays2relation(IR_Code *ir, std::vector<omega::Free_Var_Decl*> &freevars, const IR_ArrayRef *ref_src, const omega::Relation &IS_w, - const IR_ArrayRef *ref_dst, const omega::Relation &IS_r); -//! Convert array dependence relation into set of dependence vectors -/*! - * assuming ref_w is lexicographically before ref_r in the source code. - */ + const IR_ArrayRef *ref_dst, const omega::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); + std::pair<std::vector<DependenceVector>, std::vector<DependenceVector> > relation2dependences( - const IR_ArrayRef *ref_src, const IR_ArrayRef *ref_dst, const omega::Relation &r); + const IR_ArrayRef *ref_src, const IR_ArrayRef *ref_dst, const omega::Relation &r); -//! Convert a boolean expression to omega relation. -/*! - * \param destroy shallow deallocation of "repr", not freeing the actual code inside. - */ void exp2constraint(IR_Code *ir, omega::Relation &r, omega::F_And *f_root, std::vector<omega::Free_Var_Decl *> &freevars, - omega::CG_outputRepr *repr, bool destroy); + omega::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); + bool is_single_iteration(const omega::Relation &r, int dim); -//! Set/get the value of a variable which is know to be constant. void assign_const(omega::Relation &r, int dim, int val); - int get_const(const omega::Relation &r, int dim, omega::Var_Kind type); - -//! Find the position index variable in a Relation by name. omega::Variable_ID find_index(omega::Relation &r, const std::string &s, char side); - -//! Generate mapping relation for permuation. omega::Relation permute_relation(const std::vector<int> &pi); - omega::Relation get_loop_bound(const omega::Relation &r, int dim); - -//! Determine whether the loop (starting from 0) in the iteration space has only one iteration. bool is_single_loop_iteration(const omega::Relation &r, int level, const omega::Relation &known); -//! Get the bound for a specific loop. omega::Relation get_loop_bound(const omega::Relation &r, int level, const omega::Relation &known); omega::Relation get_max_loop_bound(const std::vector<omega::Relation> &r, int dim); omega::Relation get_min_loop_bound(const std::vector<omega::Relation> &r, int dim); - -//! 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(omega::Relation &r, const omega::Relation &bound, int dim, int stride); bool is_inner_loop_depend_on_level(const omega::Relation &r, int level, const omega::Relation &known); -/*! - * Suppose loop dim is i. Replace i with i+adjustment in loop bounds. - * - * ~~~ - * 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 - * ~~~ - */ +// void adjust_loop_bound(omega::Relation &r, int dim, int adjustment, std::vector<omega::Free_Var_Decl *> globals = std::vector<omega::Free_Var_Decl *>()); omega::Relation adjust_loop_bound(const omega::Relation &r, int level, int adjustment); +bool lowerBoundIsZero(const omega::Relation &bound, int dim); +omega::Relation and_with_relation_and_replace_var(const omega::Relation &R, omega::Variable_ID v1, + omega::Relation &g); +omega::Relation replicate_IS_and_add_at_pos(const omega::Relation &R, int level, omega::Relation &bound); +omega::Relation replicate_IS_and_add_bound(const omega::Relation &R, int level, omega::Relation &bound) ; + +omega::CG_outputRepr * construct_int_floor(omega::CG_outputBuilder * ocg, const omega::Relation &R, const omega::GEQ_Handle &h, omega::Variable_ID v,const std::vector<std::pair<omega::CG_outputRepr *, int> > &assigned_on_the_fly, + std::map<std::string, std::vector<omega::CG_outputRepr *> > unin); +//omega::CG_outputRepr * modified_output_subs_repr(omega::CG_outputBuilder * ocg, const omega::Relation &R, const omega::EQ_Handle &h, omega::Variable_ID v,const std::vector<std::pair<omega::CG_outputRepr *, int> > &assigned_on_the_fly, +// std::map<std::string, std::vector<omega::CG_outputRepr *> > unin); +std::pair<omega::Relation, bool> replace_set_var_as_existential(const omega::Relation &R,int pos, std::vector<omega::Relation> &bound); +omega::Relation replace_set_var_as_Global(const omega::Relation &R,int pos,std::vector<omega::Relation> &bound); +omega::Relation replace_set_var_as_another_set_var(const omega::Relation &old_relation, const omega::Relation &new_relation, int old_pos, int new_pos); +omega::Relation extract_upper_bound(const omega::Relation &R, omega::Variable_ID v1); + +// void adjust_loop_bound(Relation &r, int dim, int adjustment); +// void adjust_loop_bound(Relation &r, int dim, Free_Var_Decl *global_var, int adjustment); +// boolean is_private_statement(const omega::Relation &r, int dim); + +// coef_t mod(const Relation &r, Variable_ID v, int dividend); + enum LexicalOrderType {LEX_MATCH, LEX_BEFORE, LEX_AFTER, LEX_UNKNOWN}; +// template <typename T> +// LexicalOrderType lexical_order(const std::vector<T> &a, const std::vector<T> &b) { +// int size = min(a.size(), b.size()); +// for (int i = 0; i < size; i++) { +// if (a[i] < b[i]) +// return LEX_BEFORE; +// else if (b[i] < a[i]) +// return LEX_AFTER; +// } +// if (a.size() < b.size()) +// return LEX_BEFORE; +// else if (b.size() < a.size()) +// return LEX_AFTER; +// else +// return LEX_MATCH; +// } + +// struct LoopException { +// std::string descr; +// LoopException(const std::string &s): descr(s) {}; +// }; + #endif diff --git a/include/stencil.hh b/include/stencil.hh new file mode 100644 index 0000000..69eec42 --- /dev/null +++ b/include/stencil.hh @@ -0,0 +1,55 @@ + +#pragma once + +#include "ir_clang.hh" +#include "chill_ast.hh" + +//#include <omega.h> +#include <omegatools.hh> +#include "code_gen/CG_chillRepr.h" + +// #include "loop.hh" +#include "ir_code.hh" + + + +// *extern Loop *myloop; // ??? + + +//void stencil( chillAST_node *topstatement, class stencilInfo &SI ); // stencilInfo was originally a struct, and this was the way it got filled in. TODO remove + + +class stencilInfo { +public: + uint dimensions; // number of dimensions in the stencil + uint elements; // total number of elements in the stencil + chillAST_VarDecl* srcArrayVariable; // the variable of the source array + chillAST_VarDecl* dstArrayVariable; // the variable of the destination array + + int minOffset[3]; // the minimum offset for each dimension NOTE hardcoded to 3 dimensions TODO + int maxOffset[3]; // the maximum offset for each dimension + + chillAST_VarDecl* indexVariables[3]; // the variable used for indexing each dimension + + std::vector< std::vector< int > > offsets; // k+1, j-47, i+0 etc + + + std::vector< std::vector<chillAST_node*> > coefficients; // the coefficients of for each element, NOT IN ANY SET ORDER + chillAST_node* find_coefficient( int i, int j, int k ) ; // hardcoded 3 dimensions TODO + + // constructors + stencilInfo(); + stencilInfo( chillAST_node *topstatement ) ; + + void walktree( chillAST_node *node, std::vector< chillAST_node * > &coeffstohere ); + + void print( FILE *fp=stdout ); + + int radius(); + + bool isSymmetric(); + +}; // class stencilInfo + + + diff --git a/lib/chillcg/CMakeLists.txt b/lib/chillcg/CMakeLists.txt new file mode 100644 index 0000000..b204c69 --- /dev/null +++ b/lib/chillcg/CMakeLists.txt @@ -0,0 +1,17 @@ +set(CODEGEN_CHILL_SRC + src/CG_chillBuilder.cc + src/CG_chillRepr.cc + ) + +include_directories( + include + ${OMEGA_INC} + ) + +add_library(chillcg ${CODEGEN_CHILL_SRC}) + +install(TARGETS chillcg + DESTINATION lib) + +install(DIRECTORY include/code_gen + DESTINATION include) diff --git a/lib/chillcg/include/code_gen/CG_chillBuilder.h b/lib/chillcg/include/code_gen/CG_chillBuilder.h new file mode 100755 index 0000000..172f198 --- /dev/null +++ b/lib/chillcg/include/code_gen/CG_chillBuilder.h @@ -0,0 +1,196 @@ +#ifndef CG_chillBuilder_h +#define CG_chillBuilder_h + +#include <basic/Tuple.h> +#include <code_gen/CG_outputBuilder.h> +#include <code_gen/CG_chillRepr.h> +#include <string> + + + + +namespace omega { + +class CG_chillBuilder : public CG_outputBuilder { +private: + + chillAST_SourceFile *toplevel; + chillAST_FunctionDecl *currentfunction; + + chillAST_SymbolTable *symtab_; // symbol table for FUNC (parameters?) + chillAST_SymbolTable *symtab2_; // symbol table for func BODY + +public: + CG_chillBuilder() ; + CG_chillBuilder(chillAST_SourceFile *top, chillAST_FunctionDecl *func ) ; + ~CG_chillBuilder(); + + const char *ClassName() { return "chillBuilder"; }; + + //--------------------------------------------------------------------------- + // place holder generation not in CG_outputBuilder ?? or CG_roseBuilder + //--------------------------------------------------------------------------- + CG_outputRepr* CreatePlaceHolder(int indent, + CG_outputRepr *stmt, + Tuple<CG_outputRepr*> &funcList, + Tuple<std::string> &loop_vars) const; + + //--------------------------------------------------------------------------- + // substitute variables in stmt + //--------------------------------------------------------------------------- + + + CG_outputRepr *CreateSubstitutedStmt(int indent, + CG_outputRepr *stmt, + const std::vector<std::string> &vars, + std::vector<CG_outputRepr *> &subs, + bool actuallyPrint =true) const; + + + + //--------------------------------------------------------------------------- + // assignment generation + //--------------------------------------------------------------------------- + CG_outputRepr* CreateAssignment(int indent, CG_outputRepr* lhs, CG_outputRepr* rhs) const; + + CG_outputRepr *CreatePlusAssignment(int indent, + CG_outputRepr *lhs, + CG_outputRepr *rhs) const; + + + //--------------------------------------------------------------------------- + // function invocation generation + //--------------------------------------------------------------------------- + CG_outputRepr* CreateInvoke(const std::string &funcName, + std::vector<CG_outputRepr*> &argList, + bool is_array = true) const; + + //--------------------------------------------------------------------------- + // comment generation + //--------------------------------------------------------------------------- + CG_outputRepr* CreateComment(int indent, const std::string &commentText) const; + + //--------------------------------------------------------------------------- + // Attribute generation + //--------------------------------------------------------------------------- + CG_outputRepr* CreateAttribute(CG_outputRepr *control, + const std::string &commentText) const; + + //--------------------------------------------------------------------------- + // Pragma Attribute + //--------------------------------------------------------------------------- + CG_outputRepr* CreatePragmaAttribute(CG_outputRepr *scopeStmt, int looplevel, + const std::string &pragmaText) const; + + //--------------------------------------------------------------------------- + // Prefetch Attribute + //--------------------------------------------------------------------------- + CG_outputRepr* CreatePrefetchAttribute(CG_outputRepr *scopeStmt, int looplevel, + const std::string &arrName, int hint) const; + + //--------------------------------------------------------------------------- + // if stmt gen operations + //--------------------------------------------------------------------------- + CG_outputRepr* CreateIf(int indent, + CG_outputRepr* guardCondition, + CG_outputRepr* true_stmtList, + CG_outputRepr* false_stmtList) const; + + //--------------------------------------------------------------------------- + // inductive variable generation, to be used in CreateLoop as control + //--------------------------------------------------------------------------- + CG_outputRepr* CreateInductive(CG_outputRepr* index, + CG_outputRepr* lower, + CG_outputRepr* upper, + CG_outputRepr* step) const; + + //--------------------------------------------------------------------------- + // loop stmt generation + //--------------------------------------------------------------------------- + CG_outputRepr* CreateLoop(int indent, + CG_outputRepr* control, + CG_outputRepr* stmtList) const; + + //--------------------------------------------------------------------------- + // basic operations + //--------------------------------------------------------------------------- + CG_outputRepr* CreateInt(int num ) const; // create Integer constant? + CG_outputRepr* CreateFloat(float num ) const; // + CG_outputRepr* CreateDouble(double num ) const; // should these all be chillRepr ??? + + + + + bool isInteger(CG_outputRepr *op) const; + CG_outputRepr* CreateIdent(const std::string &idStr) const; // create a new INTEGER identifier + + + CG_outputRepr* CreateDotExpression(CG_outputRepr *l, CG_outputRepr *r) const; + CG_outputRepr* CreateArrayRefExpression(const std::string &_s, + CG_outputRepr *rop) const; + CG_outputRepr* CreateArrayRefExpression(CG_outputRepr *lop, + CG_outputRepr *rop) const; + CG_outputRepr* ObtainInspectorData(const std::string &_s, const std::string &member_name) const; + bool QueryInspectorType(const std::string &varName) const; + CG_outputRepr* CreateNullStatement() const; + + //--------------------------------------------------------------------------- + // binary arithmetic operations + //--------------------------------------------------------------------------- + CG_outputRepr* CreatePlus( CG_outputRepr* lop, CG_outputRepr* rop) const; + CG_outputRepr* CreateMinus( CG_outputRepr* lop, CG_outputRepr* rop) const; + CG_outputRepr* CreateTimes( CG_outputRepr* lop, CG_outputRepr* rop) const; + CG_outputRepr* CreateIntegerDivide(CG_outputRepr* lop, CG_outputRepr* rop) const; + CG_outputRepr* CreateIntegerFloor( CG_outputRepr* lop, CG_outputRepr* rop) const; + CG_outputRepr* CreateIntegerMod( CG_outputRepr* lop, CG_outputRepr* rop) const; + CG_outputRepr* CreateIntegerCeil( CG_outputRepr* lop, CG_outputRepr* rop) const; + + //--------------------------------------------------------------------------- + // binary logical operations + //--------------------------------------------------------------------------- + CG_outputRepr* CreateAnd(CG_outputRepr* lop, CG_outputRepr* rop) const; + + //--------------------------------------------------------------------------- + // binary relational operations + //--------------------------------------------------------------------------- + //CG_outputRepr* CreateGE(CG_outputRepr* lop, CG_outputRepr* rop) const; + CG_outputRepr* CreateLE(CG_outputRepr* lop, CG_outputRepr* rop) const; + CG_outputRepr* CreateEQ(CG_outputRepr* lop, CG_outputRepr* rop) const; + CG_outputRepr* CreateNEQ(CG_outputRepr* lop, CG_outputRepr* rop) const; + + //--------------------------------------------------------------------------- + // stmt list gen operations + //--------------------------------------------------------------------------- + CG_outputRepr* + CreateStmtList(CG_outputRepr *singleton = NULL) const; + CG_outputRepr* + StmtListInsertLast(CG_outputRepr* list, CG_outputRepr* node) const; + CG_outputRepr* + StmtListAppend(CG_outputRepr* list1, CG_outputRepr* list2) const; + + CG_outputRepr *CreateAddressOf(CG_outputRepr *op) const ; + CG_outputRepr *CreateBreakStatement(void) const; + CG_outputRepr *CreateStatementFromExpression(CG_outputRepr *exp) const; + + //--------------------------------------------------------------------------- + // Utility Functions + //--------------------------------------------------------------------------- + //CompoundStmt *StmtV2Compound(StmtList *slist) const // ?? + //{ return new (astContext_)CompoundStmt(*astContext_, &(*slist)[0], (*slist).size(), SourceLocation(), SourceLocation()); } + + //bool substitute(clang::Expr *in, std::string sym, clang::Expr* expr, clang::Expr *parent) const; + + CG_outputRepr *CreateStruct(const std::string struct_name, + std::vector<std::string> data_members, + std::vector<CG_outputRepr *> data_types); + + CG_outputRepr *CreateClassInstance(std::string name , CG_outputRepr *class_def); + CG_outputRepr *lookup_member_data(CG_outputRepr* scope, std::string varName, CG_outputRepr *instance); + CG_outputRepr* CreatePointer(std::string &name) const; + CG_outputRepr* ObtainInspectorRange(const std::string &_s, const std::string &_name) const; + +}; + +} // namespace omega + +#endif diff --git a/lib/chillcg/include/code_gen/CG_chillRepr.h b/lib/chillcg/include/code_gen/CG_chillRepr.h new file mode 100755 index 0000000..3d19de7 --- /dev/null +++ b/lib/chillcg/include/code_gen/CG_chillRepr.h @@ -0,0 +1,87 @@ + +#ifndef CG_chillRepr_h +#define CG_chillRepr_h + +// Repr using chillAst internally +#include <stdio.h> +#include <string.h> +#include <code_gen/CG_outputRepr.h> + +#ifndef __STDC_CONSTANT_MACROS +#define __STDC_CONSTANT_MACROS +#endif + + +#include "chill_ast.hh" + + +namespace omega { + +class CG_chillRepr : public CG_outputRepr { + friend class CG_chillBuilder; +public: + CG_chillRepr() { stmtclassname = strdup("NOTHING"); } + + + char *type() const { return strdup("chill"); }; + // + std::vector<chillAST_node*> chillnodes; // TODO make private + void printChillNodes() const { + for (int i=0; i<chillnodes.size(); i++) { + chillnodes[i]->print(); printf("\n"); } + fflush(stdout); + }; + + CG_chillRepr( std::vector<chillAST_node*> cnodes ) { + chillnodes = cnodes; + } + + CG_chillRepr( chillAST_node *chillast ) { + stmtclassname = strdup(chillast->getTypeString()); + //fprintf(stderr, "made new chillRepr of class %s\n", stmtclassname); + if (chillast->asttype == CHILLAST_NODETYPE_COMPOUNDSTMT) { + std::vector<chillAST_node*> children = chillast->getChildren(); + int numchildren = children.size(); + for (int i=0; i<numchildren; i++) { + chillnodes.push_back( children[i] ); + //fprintf(stderr, "adding a statement from a CompoundStmt\n"); + } + } + else { // for now, assume it's a single statement + chillnodes.push_back( chillast ); // ?? + } + } + void addStatement( chillAST_node *s ) { chillnodes.push_back( s ); } ; + + std::vector<chillAST_node*> getChillCode() const { return chillnodes; }; + + chillAST_node *GetCode() ; + + + ~CG_chillRepr(); + CG_outputRepr *clone() const; + void clear(); + + + + + + + //--------------------------------------------------------------------------- + // Dump operations + //--------------------------------------------------------------------------- + void dump() const { printChillNodes(); }; + void Dump() const; + //void DumpToFile(FILE *fp = stderr) const; +private: + + + char *stmtclassname; // chill + +}; + + + +} // namespace + +#endif diff --git a/lib/chillcg/src/CG_chillBuilder.cc b/lib/chillcg/src/CG_chillBuilder.cc new file mode 100755 index 0000000..4593b26 --- /dev/null +++ b/lib/chillcg/src/CG_chillBuilder.cc @@ -0,0 +1,1897 @@ + +/***************************************************************************** + Copyright (C) 2008 University of Southern California + Copyright (C) 2009-2010 University of Utah + All Rights Reserved. + + Purpose: + generate chill AST code for omega + + Notes: + + History: + 02/01/06 created by Chun Chen + +*****************************************************************************/ + +#include <iostream> +#include <stack> +#include <code_gen/CG_chillBuilder.h> + +namespace omega { + + // substitute at chill AST level + // forward declarations + chillAST_node *substituteChill( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + chillAST_node *SubABinaryOperator( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + chillAST_node *SubUnaryOperator( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + chillAST_node *SubDeclRefExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + chillAST_node *SubArraySubscriptExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + chillAST_node *SubImplicitCastExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + chillAST_node *SubCStyleCastExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + chillAST_node *SubParenExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + chillAST_node *SubCallExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + chillAST_node *SubReturnStmt( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + chillAST_node *SubIfStmt( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + chillAST_node *SubCompoundStmt( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + chillAST_node *SubMemberExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); + + + + // chillAST_node *Sub( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent ); // fwd decl + + + + + chillAST_node *substituteChill( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + if (n == NULL) { + fprintf(stderr, "substituteChill() pointer n == NULL\n"); // DIE + int *crash = 0; + crash[0] = 1; + exit(-1); + } + + //fprintf(stderr, "substituteChill() subbing statement of type "); + //fprintf(stderr, "%s\n", n->getTypeString()); + //if (n->isImplicitCastExpr()) { + // chillAST_ImplicitCastExpr *ICE = (chillAST_ImplicitCastExpr *) n; + // fprintf(stderr, "ICE subexpr type %s\n", ICE->subexpr->getTypeString()); + //} + //fprintf(stderr, "subbing '%s' in statement ", oldvar); n->print(0, stderr); fprintf(stderr, "\n"); + + chillAST_node *r = n; + if (n->isBinaryOperator()) {r= SubABinaryOperator(oldvar, newvar, n, parent ); + } else if (n->isUnaryOperator()) {r= SubUnaryOperator(oldvar, newvar, n, parent ); + } else if (n->isDeclRefExpr()) {r= SubDeclRefExpr(oldvar, newvar, n, parent ); + } else if (n->isArraySubscriptExpr()) {r=SubArraySubscriptExpr(oldvar, newvar, n, parent ); + } else if (n->isImplicitCastExpr()) {r= SubImplicitCastExpr(oldvar, newvar, n, parent ); + } else if (n->isParenExpr()) {r= SubParenExpr(oldvar, newvar, n, parent ); + } else if (n->isCStyleCastExpr()) {r= SubCStyleCastExpr(oldvar, newvar, n, parent ); + } else if (n->isReturnStmt()) {r= SubReturnStmt(oldvar, newvar, n, parent ); + } else if (n->isIfStmt()) {r= SubIfStmt(oldvar, newvar, n, parent ); + } else if (n->isCallExpr()) {r= SubCallExpr(oldvar, newvar, n, parent ); + } else if (n->isCompoundStmt()) {r= SubCompoundStmt(oldvar, newvar, n, parent ); + } else if (n->isMemberExpr()) {r= SubMemberExpr(oldvar, newvar, n, parent ); + + } else if (n->isFloatingLiteral()) { //fprintf(stderr, "sub in FL\n"); // do nothing + } else if (n->isIntegerLiteral()) { // do nothing + + } else { + fprintf(stderr, "\nCG_chillBuilder.cc substituteChill() UNHANDLED statement of type "); + n->dump(); printf(" "); n->print(); printf("\n"); fflush(stdout); + fprintf(stderr, "%s\n", n->getTypeString()); + exit(-1); + } + + /* + if (isa<DeclStmt>(s)) { SubDeclStmt(oldvar, newvar, n, parent ); + } else if (isa<UnaryOperator>(s)) { SubUnaryOperator(oldvar, newvar, n, parent ); + } else if (isa<ForStmt>(s)) { SubLoop(oldvar, newvar, n, parent ); + */ + + return r; + } + + + chillAST_node *SubABinaryOperator( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + chillAST_BinaryOperator *b = (chillAST_BinaryOperator *) n; + //fprintf(stderr,"SubABinaryOperator() 0x%x subbing old variable %s in \n", b, oldvar); + + + //fprintf(stderr,"SubABinaryOperator() subbing old variable %s in \n", oldvar); + //if (b->lhs!=NULL && b->rhs!=NULL) { + // b->print(); printf("\n"); fflush(stdout); + //} + + chillAST_node *lhs = b->lhs; + chillAST_node *rhs = b->rhs; + + //if (!strcmp(b->op, "=") && rhs->isBinaryOperator() ) { + // chillAST_BinaryOperator *r = (chillAST_BinaryOperator *) rhs; + // fprintf(stderr, "a(%p) = b(%p) %s c(%p)\n", lhs, r->lhs, r->op, r->rhs ); + //} + + //fprintf(stderr, "op %s rhs type ", b->op); + //fprintf(stderr, "%s\n", rhs->getTypeString()); + //rhs->dump(); printf("\n"); fflush(stdout); + + + b->lhs = substituteChill( oldvar, newvar, lhs, b); + b->rhs = substituteChill( oldvar, newvar, rhs, b); + return b; + } + + + + chillAST_node *SubUnaryOperator( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + chillAST_UnaryOperator *u = (chillAST_UnaryOperator *) n; + chillAST_node *sub = u->subexpr; + u->subexpr = substituteChill( oldvar, newvar, sub, u); + return u; + } + + + chillAST_node *SubDeclRefExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + //fprintf(stderr, "SubDeclRefExpr() subbing statement of type %s\n", n->getTypeString()); + + chillAST_DeclRefExpr *DRE = (chillAST_DeclRefExpr *) n; + //const char *variable = DRE->declarationName; // should be the same as oldvar ?? + + //fprintf(stderr, "looking for oldvar %s in old DRE code ", oldvar); + //n->print(); printf("\n"); fflush(stdout); + + //fprintf(stderr, "old DRE name was %s\n", DRE->declarationName); + if (streq( oldvar, DRE->declarationName)) { + //fprintf(stderr, "yep. replacing\n"); + + + //fprintf(stderr, "\nNEED TO REPLACE VARIABLE %s with new thing ", oldvar); + //newvar->printChillNodes(); + + + // newvar->Dump(); printf("\n"); fflush(stdout); + // //fprintf(stderr, " in statement of type %s\n",s->getTypeString()); + //} + + std::vector<chillAST_node*> newnodes = newvar->chillnodes; + //fprintf(stderr, "%d nodes in newvar\n", newnodes.size()); + chillAST_node *firstn = newnodes[0]; + firstn->parent = parent; + return firstn; // it's that simple! + + } + //else fprintf(stderr, "nope. not the right thing to replace\n\n"); + + + return DRE; // unchanged + } // subdeclrefexpr + + + + + + chillAST_node *SubArraySubscriptExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + chillAST_ArraySubscriptExpr *ASE = (chillAST_ArraySubscriptExpr *) n; + + //fprintf(stderr, "subASE ASE 0x%x\n", ASE); + //fprintf(stderr, "SubArraySubscriptExpr subbing old variable %s with new thing in ASE 0x%x ", oldvar, ASE); + + //ASE->print(); printf("\n"); fflush(stdout); + + chillAST_node *Base = ASE->base; + chillAST_node *Index = ASE->index; + //fprintf(stderr, "Index is of type %s\n", Index->getTypeString()); + + ASE->base = substituteChill( oldvar, newvar, Base, ASE); // this should not do anything + ASE->index = substituteChill( oldvar, newvar, Index, ASE); // this should + + //if (Index != ASE->index) { + // fprintf(stderr, "ASE was "); + // Base->print(); + // printf("["); + // Index->print(); + // printf("]\n"); + // printf("SWAPPED INDEX ASE 0x%x is ", ASE); ASE->print(); printf("\n"); fflush(stdout); + //} + //else fprintf(stderr, "ASE is "); ASE->print(); printf("\n"); fflush(stdout); + return ASE; + } + + + + chillAST_node *SubImplicitCastExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + //fprintf(stderr, "SubImplicitCastExpr subbing statement of type %s at 0x%x parent 0x%x\n", n->getTypeString(), n, parent); + chillAST_ImplicitCastExpr *IC = (chillAST_ImplicitCastExpr *) n; + chillAST_node *oldsub = IC->subexpr; + IC->subexpr = substituteChill( oldvar, newvar, oldsub, IC); + + //if (oldsub != IC->subexpr) { + //fprintf(stderr, "ImplicitCastExpr has CHANGED\n"); + //IC->print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "ICE was "); + //oldsub->print(); + //printf("\nSWAPPED subexpr ICE 0x%x is ", IC); IC->print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "PARENT 0x%x is now ",IC->parent); + //IC->parent->print(); printf("\n"); fflush(stdout); + //} + return IC; + } + + chillAST_node *SubCStyleCastExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + //fprintf(stderr, "SubCStyleCastExpr() subexpr is type "); + chillAST_CStyleCastExpr *CSCE = (chillAST_CStyleCastExpr *) n; + //fprintf(stderr, "%s\n", CSCE->subexpr->getTypeString()); + CSCE->subexpr = substituteChill( oldvar, newvar, CSCE->subexpr, CSCE); + return CSCE; + } + + + chillAST_node *SubParenExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + chillAST_ParenExpr *PE = (chillAST_ParenExpr *) n; + PE->subexpr = substituteChill( oldvar, newvar, PE->subexpr, PE); + return PE; + } + + chillAST_node *SubCallExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + chillAST_CallExpr *CE = (chillAST_CallExpr *) n; + + //fprintf(stderr, "substituting for oldvar %s in ", oldvar ); + //CE->print(); printf("\n"); fflush(stdout); + + int nargs = CE->numargs; + for (int i=0; i<nargs; i++) { + CE->args[i] = substituteChill( oldvar, newvar, CE->args[i], CE); + } + return CE; + } + + + + chillAST_node *SubReturnStmt( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + //fprintf(stderr, "SubReturnStmt()\n"); + + chillAST_ReturnStmt *RS = (chillAST_ReturnStmt *)n; + if (RS->returnvalue) RS->returnvalue = substituteChill(oldvar, newvar, RS->returnvalue, RS); + return RS; + } + + + chillAST_node *SubIfStmt( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + //fprintf(stderr, "SubIfStmt()\n"); + chillAST_IfStmt *IS = (chillAST_IfStmt *)n; + //IS->print(0, stderr); fprintf(stderr, "\n\n"); + chillAST_node *sub; + if ( sub = IS->getCond() ) IS->setCond( substituteChill(oldvar, newvar, sub, IS)); + if ( sub = IS->getThen() ) IS->setThen( substituteChill(oldvar, newvar, sub, IS)); + sub = IS->getElse(); //fprintf(stderr, "sub(else) = %p\n", sub); + if ( sub = IS->getElse() ) IS->setElse( substituteChill(oldvar, newvar, sub, IS)); + + return IS; + } + + + chillAST_node *SubCompoundStmt( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + //fprintf(stderr, "SubCompoundStmt()\n"); + chillAST_CompoundStmt *CS = (chillAST_CompoundStmt *)n; + + int numchildren = CS->getNumChildren(); + for (int i=0; i<numchildren; i++) { + CS->setChild( i, substituteChill(oldvar, newvar, CS->getChild(i), CS )); + } + + return CS; + } + + + + chillAST_node *SubMemberExpr( const char *oldvar, CG_chillRepr *newvar, chillAST_node *n, chillAST_node *parent = NULL ) { + //fprintf(stderr, "SubMemberExpr( oldvar %s ) \n", oldvar); + chillAST_MemberExpr *ME = (chillAST_MemberExpr *)n; + + ME->base = substituteChill(oldvar, newvar, ME->base, ME ); + + + // + return ME; + } + + + + CG_chillBuilder::CG_chillBuilder() { + toplevel = NULL; + currentfunction = NULL; // not very useful + symtab_ = symtab2_ = NULL; + } + + CG_chillBuilder::CG_chillBuilder(chillAST_SourceFile *top, chillAST_FunctionDecl *func) { + //fprintf(stderr, "\nCG_chillBuilder::CG_chillBuilder()\n"); + toplevel = top; + currentfunction = func; + + //fprintf(stderr, "\nfunction is:\n"); currentfunction->print(); printf("\n\n"); fflush(stdout); + + symtab_ = &(currentfunction->parameters); // getSymbolTable(); // TODO rename + symtab2_ = currentfunction->getBody()->getSymbolTable(); // TODO rename + + //printf("\nsymtab_:\n"); fflush(stdout); + //printSymbolTable( symtab_ ); + //printf("\n\nsymtab2_:\n"); fflush(stdout); + //printSymbolTable( symtab2_ ); + } + + CG_chillBuilder::~CG_chillBuilder() { + + } + + //----------------------------------------------------------------------------- + // place holder generation NOT IN CG_outputBuilder + //----------------------------------------------------------------------------- + // + // FIXME: Function isn't working fully yet + // + CG_outputRepr* CG_chillBuilder::CreatePlaceHolder (int indent, + CG_outputRepr *stmt, + Tuple<CG_outputRepr*> &funcList, + Tuple<std::string> &loop_vars) const { + fprintf(stderr, "CG_chillBuilder::CreatePlaceHolder() TODO \n"); + exit(-1); // DFL + return NULL; + /* + if(Expr *expr = static_cast<CG_chillRepr *>(stmt)->GetExpression()) { + for(int i=1; i<= funcList.size(); ++i) { + if (funcList[i] == NULL) + continue; + + CG_chillRepr *repr = static_cast<CG_chillRepr*>(funcList[i]); + Expr* op = repr->GetExpression(); + delete repr; + + Expr *exp = expr; + + if(isa<BinaryOperator>(exp)) { + //substitute(static_cast<BinaryOperator*>(exp)->getLHS(), loop_vars[i], op, exp); + //substitute(static_cast<BinaryOperator*>(exp)->getRHS(), loop_vars[i], op, exp); + } + else if(isa<UnaryOperator>(exp)) + //substitute(static_cast<UnaryOperator*>(exp)->getSubExpr(), loop_vars[i], op, exp); + + } + return new CG_chillRepr(expr); + } else { + StmtList *tnl = static_cast<CG_chillRepr *>(stmt)->GetCode(); + for(int i=1; i<= funcList.size(); ++i) { + if (funcList[i] == NULL) + continue; + + CG_chillRepr *repr = static_cast<CG_chillRepr*>(funcList[i]); + Expr* op = repr->GetExpression(); + delete repr; + + for(unsigned j=0; j<tnl->size(); ++j) { + Expr *exp = static_cast<Expr *>((*tnl)[j]); + if(isa<BinaryOperator>(exp)) { + //substitute(static_cast<BinaryOperator*>(exp)->getLHS(), loop_vars[i], op, exp); + //substitute(static_cast<BinaryOperator*>(exp)->getRHS(), loop_vars[i], op, exp); + } + else if(isa<UnaryOperator>(exp)) + //substitute(static_cast<UnaryOperator*>(exp)->getSubExpr(), loop_vars[i], op, exp); + + } + } + return new CG_chillRepr(*tnl); + } + */ + + + } + + + + + //---------------------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateSubstitutedStmt(int indent, + CG_outputRepr *stmt, + const std::vector<std::string> &vars, + std::vector<CG_outputRepr*> &subs, + bool actuallyPrint) const { + + int numvars = vars.size(); + int numsubs = subs.size(); + fflush(stdout); + fprintf(stderr, "\n\nin CG_xxxxBuilder.cc (OMEGA) CG_xxxxBuilder::CreateSubstitutedStmt()\n"); + fprintf(stderr, "%d vars and %d substitutions\n", numvars, (int)subs.size()); + + + if (numvars != numsubs) { + //fprintf(stderr, "umwut?\n"); exit(-1); + } + + + //{ + // std::vector<chillAST_node*> nodes = ((CG_chillRepr *) stmt)->getChillCode(); + // // + // fprintf(stderr, "%d nodes in old code. was:\n", nodes.size()); + // for(int i=0; i<nodes.size(); i++) + // { + // printf("stmt(%d) = ",i); + // nodes[i]->print(); + // printf("\n"); + // } + // //printf("\nreally subbing in %d top level statements\n", nodes.size()); + // fflush(stdout); + //} + + //for (int i=0; i< numsubs; i++) { + // fprintf(stderr, "sub %d ", i); + // if (subs[i]) { ((CG_chillRepr *)subs[i])->Dump(); fflush( stdout ); } + // else { + // //int *crash = NULL; *crash = 1; + // fprintf(stderr, "(NULL error!)"); + // } + // //fprintf(stderr, "\n"); + //} + //fprintf(stderr, "\n"); + + + if (numsubs == 0) { + + std::vector<chillAST_node*> nodes = ((CG_chillRepr *) stmt)->getChillCode(); + + // + //fprintf(stderr, "nosubs old code was:\n"); + //for(int i=0; i<nodes.size(); i++) + // { + // printf("stmt = "); + // nodes[i]->print(); + // printf("\n"); + // } + //printf("\nreally subbing in %d top level statements\n", nodes.size()); + //fflush(stdout); + + + + // no cloning !! + return new CG_chillRepr( nodes ); + + //fprintf(stderr, "since nothing actually being substituted, this is just a clone\n"); + //fprintf(stderr, "old code was AND new code is:\n"); + //for (int i=0; i<nodes.size(); i++) { + // fprintf(stderr, "stmt = "); + // nodes[i]->print(); fflush(stdout); + // fprintf(stderr, "\n"); + //} + //fprintf(stderr, "cloning()\n"); + //return stmt->clone(); + + } + + + + //fprintf(stderr, "numsubs %d\n", numsubs); + + // debugging: print the substitutions we'll do + + //if (numsubs > 0) { + // for (int i=0; i< numsubs; i++) { + // fprintf(stderr, "subbing "); + // if (subs[i]) { + // ((CG_chillRepr *)subs[i])->Dump(); fflush( stdout ); + // fprintf(stderr, "for %s\n", vars[i].c_str() ); + //} else { + // //int *crash = NULL; *crash = 1; + // fprintf(stderr, "(NULL error!)"); + // } + // //fprintf(stderr, "\n"); + // } + // fprintf(stderr, "\n"); + //} + + + + //fprintf(stderr, "OK, now to really substitute ...\n"); + //CG_outputRepr *newstmt = stmt->clone(); + //CG_chillRepr *n = (CG_chillRepr *) newstmt; + //vector<chillAST_node*> newnodes = n->getChillCode(); + + CG_chillRepr *old = (CG_chillRepr *) stmt; + std::vector<chillAST_node*> oldnodes = old->getChillCode(); + + + for (int j=0; j<numsubs; j++) { + if (subs[j] != NULL) { + + //fprintf(stderr, "substitution %d %s -> ", j,vars[j].c_str()); + //if (subs[j]) { ((CG_chillRepr *)subs[j])->Dump(); fflush( stdout ); } + + + // find the type of thing we'll be using to replace the old variable + CG_chillRepr *CRSub = (CG_chillRepr *)(subs[j]); + std::vector<chillAST_node*> nodes = CRSub->chillnodes; + if (1 != nodes.size() ) { // always just one? + fprintf(stderr, "CG_chillBuilder::CreateSubstitutedStmt(), replacement is not one statement??\n"); + exit(-1); + } + chillAST_node *node = nodes[0]; // always just one? + + for (int i=0; i<oldnodes.size(); i++) { + //fprintf(stderr, " statement %d ", i); + //oldnodes[i]->print(); printf("\n\n"); fflush(stdout); + oldnodes[i] = substituteChill( vars[j].c_str(), CRSub, oldnodes[i]); + } + } + } + + //fprintf(stderr, "\ncode after substituting variables:\n"); + //for(int i=0; i<oldnodes.size(); ++i){ printf("stmt = ");oldnodes[i]->print();printf("\n");} + //fflush(stdout); + + return new CG_chillRepr( oldnodes ); + } + + + + //----------------------------------------------------------------------------- + // assignment generation + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateAssignment(int indent, + CG_outputRepr *lhs, + CG_outputRepr *rhs) const { + //fprintf(stderr, "CG_chillBuilder::CreateAssignment()\n"); + if(lhs == NULL || rhs == NULL) { + fprintf(stderr, "Code generation: Missing lhs or rhs\n"); + return NULL; + } + + CG_chillRepr *clhs = (CG_chillRepr *) lhs; + CG_chillRepr *crhs = (CG_chillRepr *) rhs; + chillAST_node *lAST = clhs->chillnodes[0]; // always just one? + chillAST_node *rAST = crhs->chillnodes[0]; // always just one? + + chillAST_BinaryOperator *bop = new chillAST_BinaryOperator(lAST->clone(), "=", rAST->clone(), NULL); // clone?? + + delete lhs; delete rhs; + return new CG_chillRepr(bop); + } + + + + + CG_outputRepr* CG_chillBuilder::CreatePlusAssignment(int indent, // += + CG_outputRepr *lhs, + CG_outputRepr *rhs) const { + //fprintf(stderr, "CG_chillBuilder::CreatePlusAssignment()\n"); + if(lhs == NULL || rhs == NULL) { + fprintf(stderr, "Code generation: Missing lhs or rhs\n"); + return NULL; + } + + CG_chillRepr *clhs = (CG_chillRepr *) lhs; + CG_chillRepr *crhs = (CG_chillRepr *) rhs; + chillAST_node *lAST = clhs->chillnodes[0]; // always just one? + chillAST_node *rAST = crhs->chillnodes[0]; // always just one? + + chillAST_BinaryOperator *bop = new chillAST_BinaryOperator(lAST->clone(), "+=", rAST->clone(), NULL); // clone?? + + delete lhs; delete rhs; + return new CG_chillRepr(bop); + } + + + + + //----------------------------------------------------------------------------- + // function invocation generation + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateInvoke(const std::string &fname, + std::vector<CG_outputRepr*> &list, + bool is_array) const { // WHAT is an array? + fprintf(stderr, "CG_roseBuilder::CreateInvoke( fname %s, ...)\n", fname.c_str()); + //fprintf(stderr, "%d things in list\n", list.size()); + + // debugging output. print the "call" + //fprintf(stderr, "%s", fname.c_str()); + //if (is_array) fprintf(stderr, "["); else fprintf(stderr, "("); + //int numparams = list.size(); + //for (int i=0; i<numparams; i++) { + // CG_chillRepr *CR = (CG_chillRepr *) list[i]; + // if (i) printf(","); + // printf(" "); + // CR->GetCode()->print(); + // fflush(stdout); + //} + //if (numparams) printf(" "); + //if (is_array) printf("]\n"); else printf(")\n"); + //fflush(stdout); + + + + if (is_array) { + //fprintf(stderr, "CG_chillBuilder::CreateInvoke() %s is_array\n", fname.c_str()); + const char *arrayname = fname.c_str(); + + CG_chillRepr *CR = (CG_chillRepr *) list[0]; + chillAST_node *cast = CR->GetCode(); + + //fprintf(stderr, "%s[", arrayname); + //cast->print(); printf("] ???\n"); fflush(stdout); + + // find the array variable (scope ?? TODO) + chillAST_VarDecl *array = currentfunction->findArrayDecl( arrayname ); + if (!array) { + fprintf(stderr, "CG_chillBuilder::CreateInvoke(), can't find array %s\n", fname.c_str()); + } + + // make a declrefexpr that refers to vardecl of array ? + chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr( array ); + chillAST_ArraySubscriptExpr *ASE = new chillAST_ArraySubscriptExpr( DRE, cast, NULL, NULL); + return new CG_chillRepr( ASE ); + } + + + if (fname == std::string("max") || fname == std::string("min")) { + if (list.size() == 0) { return NULL; } + else if (list.size() == 1) { return list[1]; } + else { + //fprintf(stderr, "else\n"); + int last = list.size()-1; + CG_outputRepr *CGOR; + CG_chillRepr *CGCR; + + //fprintf(stderr, "going to create call to %s( ", fname.c_str()); + //for (int i=0; i<list.size(); i++) { + // CGCR = (CG_chillRepr*) list[i]; + // CGCR->chillnodes[0]->print(0, stderr); + // if (i<(list.size()-1)) fprintf(stderr, ", "); + //} + //fprintf(stderr, ")\n"); + + char macroname[32]; + char op; + + if (fname == std::string("max")) op = '>'; + else op = '<'; + + // TODO >, check number of args etc + chillAST_node *ternary = lessthanmacro( ((CG_chillRepr*) list[0])->chillnodes[0], + ((CG_chillRepr*) list[1])->chillnodes[0]); + + //fprintf(stderr, "just made ternary "); + //ternary->print(0, stdout); + + + CG_chillRepr *repr = new CG_chillRepr( ternary ); + //fprintf(stderr, "returning callexpr with ternary\n", macroname); + return repr; + } + } + //else { // special case for reduce? + //} + else { + //do a simple function call + fprintf(stderr, "building a function call expression\n"); + + // try to find the function name, for a function in this file + const char *name = fname.c_str(); + //fprintf(stderr, "fname '%s'\n", name); + chillAST_SourceFile *src = toplevel; // todo don't be dumb + + chillAST_node *def = src->findCall(name); + if (!def) { // can't find it + fprintf(stderr, "CG_chillBuilder::CreateInvoke( %s ), can't find a function or macro by that name\n", name); + exit(-1); + } + + //fprintf(stderr, "%s is a %s\n", name, def->getTypeString()); + if (def->isMacroDefinition()) { + chillAST_CallExpr *CE = new chillAST_CallExpr( def, toplevel ); + int numparams = list.size(); + for (int i=0; i<numparams; i++) { + CG_chillRepr *CR = (CG_chillRepr *) list[i]; + CE->addArg( CR->GetCode() ); + } + return new CG_chillRepr( CE ); + } + else if (def->isFunctionDecl()) { + // TODO are these cases exactly the same? + chillAST_CallExpr *CE = new chillAST_CallExpr( def, toplevel ); + int numparams = list.size(); + for (int i=0; i<numparams; i++) { + CG_chillRepr *CR = (CG_chillRepr *) list[i]; + CE->addArg( CR->GetCode() ); + } + return new CG_chillRepr( CE ); + } + else { + } + + + // chillAST_CallExpr::chillAST_CallExpr(chillAST_node *function, chillAST_node *p ); + + // todo addarg() + //int numargs; + //std::vector<class chillAST_node*> args; + fprintf(stderr, "Code generation: invoke function io_call not implemented\n"); + return NULL; + } + } + + + //----------------------------------------------------------------------------- + // comment generation - NOTE: Not handled + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateComment(int indent, const std::string &commentText) const { + return NULL; + } + + + + CG_outputRepr* CG_chillBuilder::CreateNullStatement() const { + return new CG_chillRepr( new chillAST_NoOp() ); + } + + + + //--------------------------------------------------------------------------- + // Attribute generation + //--------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateAttribute(CG_outputRepr *control, + const std::string &commentText) const { + + //fprintf(stderr, "in CG_chillBuilder.cc (OMEGA) CG_chillBuilder::CreateAttribute()\n"); + //fprintf(stderr, "comment = '%s'\n", commentText.c_str()); + + CG_chillRepr *CR = (CG_chillRepr *) control; + int numnodes = CR->chillnodes.size(); + //fprintf(stderr, "%d chill nodes\n", numnodes); + if (numnodes > 0) { + //fprintf(stderr, "adding a comment to a %s\n", CR->chillnodes[0]->getTypeString()); + CR->chillnodes[0]->metacomment = strdup( commentText.c_str()); + } + else { + fprintf(stderr, "CG_chillBuilder::CreateAttribute no chillnodes to attach comment to???\n"); + } + return static_cast<CG_chillRepr*>(control); + }; + + + + + + //----------------------------------------------------------------------------- + // if stmt gen operations + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateIf(int indent, + CG_outputRepr *guardList, + CG_outputRepr *true_stmtList, + CG_outputRepr *false_stmtList) const { + //fprintf(stderr, "CG_chillBuilder::CreateIf()\n"); + + if (true_stmtList == NULL && false_stmtList == NULL) { + delete guardList; + return NULL; + } + else if (guardList == NULL) { // this seems odd + return StmtListAppend(true_stmtList, false_stmtList); + } + + std::vector<chillAST_node*> vectorcode = static_cast<CG_chillRepr*>(guardList)->getChillCode(); + if (vectorcode.size() != 1 ) { + fprintf(stderr, "CG_chillBuilder.cc IfStmt conditional is multiple statements?\n"); + exit(-1); + } + chillAST_node *conditional = vectorcode[0]; + chillAST_CompoundStmt *then_part = NULL; + chillAST_CompoundStmt *else_part = NULL; + + + if (true_stmtList != NULL) { + then_part = new chillAST_CompoundStmt( ); + vectorcode = static_cast<CG_chillRepr*>(true_stmtList)->getChillCode(); + for (int i=0; i<vectorcode.size(); i++) then_part->addChild( vectorcode[i] ); + } + + if (false_stmtList != NULL) { + else_part = new chillAST_CompoundStmt( ); + vectorcode = static_cast<CG_chillRepr*>(false_stmtList)->getChillCode(); + for (int i=0; i<vectorcode.size(); i++) else_part->addChild( vectorcode[i] ); + } + + + chillAST_IfStmt *if_stmt = new chillAST_IfStmt( conditional, then_part, else_part, NULL); + + delete guardList; + delete true_stmtList; + delete false_stmtList; + + return new CG_chillRepr( if_stmt ); + } + + + //----------------------------------------------------------------------------- + // inductive variable generation, to be used in CreateLoop as control + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateInductive(CG_outputRepr *index, + CG_outputRepr *lower, + CG_outputRepr *upper, + CG_outputRepr *step) const { + fprintf(stderr, "\nCG_chillBuilder::CreateInductive()\n"); + if (index == NULL || lower == NULL || upper == NULL) { + fprintf(stderr, "Code generation: invalid arguments to CreateInductive\n"); + return NULL; + } + + + if (step == NULL) { + //IntegerLiteral *ilit = new (astContext_)IntegerLiteral(*astContext_, llvm::APInt(32, 1), bint->desugar(), SourceLocation()); + //step = new CG_chillRepr(ilit); + + chillAST_IntegerLiteral *intlit = new chillAST_IntegerLiteral(1); + step = new CG_chillRepr(intlit); + } + + //static_cast<CG_chillRepr*>(index)->printChillNodes(); + //static_cast<CG_chillRepr*>(lower)->printChillNodes(); + //static_cast<CG_chillRepr*>(upper)->printChillNodes(); + //static_cast<CG_chillRepr*>(step )->printChillNodes(); + + // index should be a DeclRefExpr + std::vector<chillAST_node*> nodes = static_cast<CG_chillRepr*>(index)->getChillCode(); + //fprintf(stderr, "%d index nodes\n", nodes.size()); + chillAST_node *indexnode = nodes[0]; + if (!streq("DeclRefExpr", indexnode->getTypeString())) { + fprintf(stderr, "CG_chillBuilder::CreateInductive index is not a DeclRefExpr\n"); + if (indexnode->isIntegerLiteral()) fprintf(stderr, "isIntegerLiteral()\n"); + + fprintf(stderr, "index is %s\n", indexnode->getTypeString()); + indexnode->print(); printf("\n"); fflush(stdout); + indexnode->dump(); printf("\n\n"); fflush(stdout); + int *i = 0; int j = i[0]; + exit(-1); + } + + nodes = static_cast<CG_chillRepr*>(lower)->getChillCode(); + //fprintf(stderr, "%d lower nodes\n", nodes.size()); + chillAST_node *lowernode = nodes[0]; + //fprintf(stderr, "lower node is %s\n", lowernode->getTypeString()); + + nodes = static_cast<CG_chillRepr*>(upper)->getChillCode(); + //fprintf(stderr, "%d upper nodes\n", nodes.size()); + chillAST_node *uppernode = nodes[0]; + //fprintf(stderr, "upper node is %s\n", uppernode->getTypeString()); + + nodes = static_cast<CG_chillRepr*>(step)->getChillCode(); + //fprintf(stderr, "%d step nodes\n", nodes.size()); + chillAST_node *stepnode = nodes[0]; + //fprintf(stderr, "step node is %s\n", stepnode->getTypeString()); + + // unclear is this will always be the same + // TODO error checking && incr vs decr + chillAST_BinaryOperator *init = new chillAST_BinaryOperator( indexnode, "=", lowernode, NULL); + chillAST_BinaryOperator *cond = new chillAST_BinaryOperator( indexnode, "<=", uppernode, NULL); + + //chillAST_BinaryOperator *inc = new chillAST_BinaryOperator( indexnode, "+", stepnode, NULL); + chillAST_BinaryOperator *incr = new chillAST_BinaryOperator( indexnode, "+=", stepnode, NULL); + + chillAST_ForStmt *loop = new chillAST_ForStmt( init, cond, incr, NULL /* NULL BODY DANGER! */, NULL); + + return new CG_chillRepr(loop); + + /* + //vector<chillAST_node*> indexnodes = static_cast<CG_chillRepr*>(index)->getChillCode(); + chillAST_DeclRefExpr *index_decl + Expr *lower_bound; // = static_cast<CG_chillRepr*>(lower)->getChillCode(); + Expr *upper_bound; // = static_cast<CG_chillRepr*>(upper)->getChillCode(); + Expr *step_size ; // = static_cast<CG_chillRepr*>(step)->getChillCode(); + + fprintf(stderr, "gonna die in CG_chillBuilder ~line 459\n"); + + chillAST_BinaryOperator *for_init_stmt = NULL; // new (astContext_)BinaryOperator(index_decl, lower_bound, BO_Assign, index_decl->getType(), SourceLocation()); + chillAST_BinaryOperator *test = NULL; // new (astContext_)BinaryOperator(index_decl, upper_bound, BO_LT, index_decl->getType(), SourceLocation()); + chillAST_BinaryOperator *increment = NULL; // new (astContext_)BinaryOperator(index_decl, step_size, BO_AddAssign, index_decl->getType(), SourceLocation()); + + // For Body is null.. Take care of unnecessary parens! + ForStmt *for_stmt = NULL; // new (astContext_)ForStmt(*astContext_, for_init_stmt, test, static_cast<VarDecl*>(index_decl->getDecl()), increment, NULL, SourceLocation(), SourceLocation(), SourceLocation()); + + delete index; + delete lower; + delete upper; + delete step; + + StmtList sl; + sl.push_back(for_stmt); + return new CG_chillRepr(sl); + */ + } + + + + //----------------------------------------------------------------------------- + // Pragma Attribute + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreatePragmaAttribute(CG_outputRepr *stmt, int looplevel, const std::string &pragmaText) const { + fprintf(stderr, "CG_chillBuilder::CreatePragmaAttribute() TODO\n"); + exit(-1); + // TODO effectively a comment? + /* + SgNode *tnl = static_cast<CG_chillRepr*>(stmt)->tnl_; + CodeInsertionAttribute* attr = NULL; + if (!tnl->attributeExists("code_insertion")) { + attr = new CodeInsertionAttribute(); + tnl->setAttribute("code_insertion", attr); + } + else { + attr = static_cast<CodeInsertionAttribute*>(tnl->getAttribute("code_insertion")); + } + attr->add(new PragmaInsertion(looplevel, pragmaText)); + */ + return stmt; + } + + //----------------------------------------------------------------------------- + // Prefetch Attribute + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreatePrefetchAttribute(CG_outputRepr* stmt, int looplevel, const std::string &arrName, int hint) const { + fprintf(stderr, "CG_chillBuilder::CreatePrefetchAttribute() TODO\n"); + exit(-1); + // TODO + /* + SgNode *tnl = static_cast<CG_chillRepr*>(stmt)->tnl_; + CodeInsertionAttribute *attr = getOrCreateCodeInsertionAttribute(tnl); + attr->add(new MMPrefetchInsertion(looplevel, arrName, hint)); + */ + return stmt; + } + + + + + + + + //----------------------------------------------------------------------------- + // loop stmt generation + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateLoop(int indent, + CG_outputRepr *control, + CG_outputRepr *stmtList) const { + //fprintf(stderr, "CG_chillBuilder::CreateLoop( indent %d)\n", indent); + + if (stmtList == NULL) { + delete control; + return NULL; + } + else if (control == NULL) { + fprintf(stderr, "Code generation: no inductive for this loop\n"); + return stmtList; + } + + // We assume the for statement is already created (using CreateInductive) + std::vector<chillAST_node*> code = static_cast<CG_chillRepr*>(control)->getChillCode(); + chillAST_ForStmt *forstmt = (chillAST_ForStmt *)(code[0]); + + std::vector<chillAST_node*> statements = static_cast<CG_chillRepr*>(stmtList)->getChillCode(); + //static_cast<CG_chillRepr*>(stmtList)->printChillNodes(); printf("\n"); fflush(stdout); + + chillAST_CompoundStmt *cs = new chillAST_CompoundStmt(); + for (int i=0; i<statements.size(); i++) { + cs->addChild( statements[i] ); + } + + forstmt->setBody(cs); + + delete stmtList; + return control; + } + + //--------------------------------------------------------------------------- + // copy operation, NULL parameter allowed. this function makes pointer + // handling uniform regardless NULL status + //--------------------------------------------------------------------------- + /* + virtual CG_outputRepr* CG_chillBuilder::CreateCopy(CG_outputRepr *original) const { + if (original == NULL) + return NULL; + else + return original->clone(); + } + */ + + //----------------------------------------------------------------------------- + // basic int, identifier gen operations + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateInt(int i) const { + fprintf(stderr, "CG_chillBuilder::CreateInt( %d )\n",i); + chillAST_IntegerLiteral *il = new chillAST_IntegerLiteral(i, NULL); // parent not available + return new CG_chillRepr(il); + } + CG_outputRepr* CG_chillBuilder::CreateFloat(float f) const { + //fprintf(stderr, "CG_chillBuilder::CreateFloat( %f )\n", f); + chillAST_FloatingLiteral *fl = new chillAST_FloatingLiteral(f, NULL); // parent not available + return new CG_chillRepr(fl); + } + CG_outputRepr* CG_chillBuilder::CreateDouble(double d) const { + //fprintf(stderr, "CG_chillBuilder::CreateInt( %f )\n",d); + chillAST_FloatingLiteral *dl = new chillAST_FloatingLiteral(d, NULL); // parent not available + return new CG_chillRepr(dl); + } + + + //---------------------------------------------------------------------------------------- + bool CG_chillBuilder::isInteger(CG_outputRepr *op) const{ + CG_chillRepr *cr = (CG_chillRepr *)op; + return cr->chillnodes[0]->isIntegerLiteral(); + } + + + //---------------------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateIdent(const std::string &_s) const { + fprintf(stderr, "CG_chillBuilder::CreateIdent( %s )\n", _s.c_str()); + + bool already_parameter = symbolTableHasVariableNamed(symtab_, _s.c_str()); + bool already_internal = symbolTableHasVariableNamed(symtab2_, _s.c_str()); + if ( already_parameter ) { + fprintf(stderr, "%s was already a parameter??\n", _s.c_str()); + } + if ( already_internal ) { + //fprintf(stderr, "%s was already defined in the function body\n", _s.c_str()); + //printSymbolTable(symtab2_); printf("dammit\n"); fflush(stdout); + } + + if ( (!already_parameter) && (! already_internal)) { + fprintf(stderr, "CG_roseBuilder.cc L919 adding symbol %s to symtab2_ because it was not already there\n", _s.c_str()); + + //fprintf(stderr, "parameters were: %p\n", symtab_); + //printSymbolTable( symtab_ ); + //fprintf(stderr, "\nbody symbols were: %p\n", symtab2_); + //printSymbolTable( symtab2_ ); + //fprintf(stderr, "\n\n"); + //fprintf(stderr, "there were already %d entries in body\n", symtab2_->size()); + + // this is copying roseBuilder, but is probably wrong. it is assuming + // that the ident is a direct child of the current function + + chillAST_VarDecl *vd = new chillAST_VarDecl( "int", _s.c_str(), "", currentfunction->getBody()); // parent not available TODO + currentfunction->addVariableToSymbolTable( vd ); // use symtab2_ ?? + + + chillAST_DeclRefExpr *dre = new chillAST_DeclRefExpr( "int", _s.c_str(), (chillAST_node*)vd, NULL ); // parent not available + //fprintf(stderr, "made a new chillRepr from "); dre->dump(); fflush(stdout); + return new CG_chillRepr( dre ); + } + + + // variable was already defined as either a parameter or internal variable to the function. + + // NOW WHAT?? gotta return something + chillAST_VarDecl *vd = currentfunction->funcHasVariableNamed( _s.c_str() ); + //fprintf(stderr, "vd %p\n", vd); + + chillAST_DeclRefExpr *dre = new chillAST_DeclRefExpr( "int", _s.c_str(), (chillAST_node*)vd, NULL ); // parent not available + return new CG_chillRepr( dre ); + } + + + + + + //----------------------------------------------------------------------------- + // binary arithmetic operations + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreatePlus(CG_outputRepr *lop, + CG_outputRepr *rop) const { + fprintf(stderr, "CG_chillBuilder::CreatePlus()\n"); + + + if(rop == NULL) return lop; // ?? + else if(lop == NULL) return rop; + + chillAST_node *left = ((CG_chillRepr*)lop)->chillnodes[0]; + chillAST_node *right = ((CG_chillRepr*)rop)->chillnodes[0]; + chillAST_BinaryOperator *bop = new chillAST_BinaryOperator( left, "+", right, NULL ); // parent not available + return new CG_chillRepr( bop ); + /* + Expr *lhs = static_cast<CG_chillRepr*>(lop)->GetExpression(); + Expr *rhs = static_cast<CG_chillRepr*>(rop)->GetExpression(); + + // Not sure about type!! + fprintf(stderr, "about to die in CG_chillBuilder ~line 628 CREATE PLUS\n"); + BinaryOperator *ins = new (astContext_)BinaryOperator(lhs, + rhs, + BO_Add, + lhs->getType(), // qualifyier type + VK_LValue, //Expression Value Kind, following the C++11 scheme + OK_Ordinary, // expression object kind, A further classification of the kind of object referenced by an l-value or x-value. + SourceLocation(), + false ); // fpContractable ?? + + delete lop; delete rop; + + //fprintf(stderr, " NEW binary operator 0x%x\n", ins); + fprintf(stderr, "CG_chillBuilder::CreatePlus ins 0x%x\n", ins); + return new CG_chillRepr(ins); + */ + } + + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateMinus(CG_outputRepr *lop, + CG_outputRepr *rop) const { + //fprintf(stderr, "CG_chillBuilder::CreateMinus( lop %p rop %p)\n", lop, rop); + fprintf(stderr, "CG_chillBuilder::CreateMinus()\n"); + + if(rop == NULL) { + fprintf(stderr, "CG_chillBuilder::CreateMinus(), right side is NULL\n"); + return lop; // from protonu's version. + + int *i = 0; + int j = i[0]; // segfault + } + + CG_chillRepr *clop = (CG_chillRepr *) lop; + CG_chillRepr *crop = (CG_chillRepr *) rop; + + if(clop == NULL) { // this is really a unary operator ??? + //fprintf(stderr, "CG_chillBuilder::CreateMinus() unary\n"); + chillAST_node *rAST = crop->chillnodes[0]; // always just one? + chillAST_UnaryOperator *ins = new chillAST_UnaryOperator("-", true, rAST->clone(), NULL); // clone? + delete crop; // ?? note: the chillRepr, not the chillAST_node + return new CG_chillRepr(ins); + } else { + //fprintf(stderr, "binary\n"); + chillAST_node *lAST = clop->chillnodes[0]; // always just one? + chillAST_node *rAST = crop->chillnodes[0]; // always just one? + //lAST->print(); printf(" - "); + //rAST->print(); printf("\n"); fflush(stdout); + + chillAST_BinaryOperator *bop = new chillAST_BinaryOperator(lAST->clone(), "-", rAST->clone(), NULL); // clone?? + + delete clop; delete crop; // ?? note: the chillReprs, not the chillAST_nodes + return new CG_chillRepr(bop); + } + } + + + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateTimes(CG_outputRepr *lop, + CG_outputRepr *rop) const { + fprintf(stderr, "CG_chillBuilder::CreateTimes()\n"); + if (rop == NULL || lop == NULL) { + if (rop != NULL) { + rop->clear(); + delete rop; + } + if (lop != NULL) { + lop->clear(); + delete lop; + } + return NULL; + } + + CG_chillRepr *clop = (CG_chillRepr *) lop; + CG_chillRepr *crop = (CG_chillRepr *) rop; + + chillAST_node *lAST = clop->chillnodes[0]; // always just one? + chillAST_node *rAST = crop->chillnodes[0]; // always just one? + + fprintf(stderr, "building "); + lAST->print(0, stderr); + fprintf(stderr, " * "); + rAST->print(0, stderr); + fprintf(stderr, "\n"); + + chillAST_BinaryOperator *binop = new chillAST_BinaryOperator( lAST, "*", rAST, NULL); + delete lop; delete rop; // ?? + //fprintf(stderr, "CG_chillBuilder::CreateTimes() returning a CG_chillRepr with a binop inside\n"); + return new CG_chillRepr( binop ); + } + + + + //----------------------------------------------------------------------------- + // CG_outputRepr *CG_chillBuilder::CreateDivide(CG_outputRepr *lop, CG_outputRepr *rop) const { + // return CreateIntegerFloor(lop, rop); + // } + + + + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateIntegerDivide(CG_outputRepr *lop, + CG_outputRepr *rop) const { + //fprintf(stderr, "CG_chillBuilder::CreatIntegerDivide()\n"); + if (rop == NULL) { + fprintf(stderr, "Code generation: divide by NULL\n"); + return NULL; + } + else if ( lop == NULL ) { + delete rop; + return NULL; + } + + CG_chillRepr *clop = (CG_chillRepr *) lop; + CG_chillRepr *crop = (CG_chillRepr *) rop; + + chillAST_node *lAST = clop->chillnodes[0]; // always just one? + chillAST_node *rAST = crop->chillnodes[0]; // always just one? + + //fprintf(stderr, "building "); + //lAST->print(0, stderr); + //fprintf(stderr, " / "); + //rAST->print(0, stderr); + //fprintf(stderr, " ??\n"); + + chillAST_BinaryOperator *binop = new chillAST_BinaryOperator( lAST, "/", rAST, NULL); + delete lop; delete rop; // ?? + return new CG_chillRepr( binop ); + } + + + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateIntegerFloor(CG_outputRepr* lop, CG_outputRepr* rop) const { + //fprintf(stderr, "CG_chillBuilder::CreateIntegerFloor()\n"); + + CG_chillRepr *clop = (CG_chillRepr *) lop; + CG_chillRepr *crop = (CG_chillRepr *) rop; + + chillAST_node *lAST = clop->chillnodes[0]; // always just one? + chillAST_node *rAST = crop->chillnodes[0]; // always just one? + + //fprintf(stderr, "building "); + //lAST->print(0, stderr); + //fprintf(stderr, " / "); + //rAST->print(0, stderr); + //fprintf(stderr, " ??\n"); + + chillAST_BinaryOperator *binop = new chillAST_BinaryOperator( lAST, "/", rAST, NULL); + return new CG_chillRepr( binop ); + } + + + + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateIntegerMod(CG_outputRepr *lop, + CG_outputRepr *rop) const { + //fprintf(stderr, "CG_chillBuilder::CreateIntegerMod() NEEDS WORK\n"); + //fprintf(stderr, "LHS "); lop->dump(); + //fprintf(stderr, "RHS "); rop->dump(); + + CG_chillRepr *l = (CG_chillRepr *) lop; + CG_chillRepr *r = (CG_chillRepr *) rop; + + chillAST_node *lhs = l->GetCode(); + chillAST_node *rhs = r->GetCode(); + + chillAST_BinaryOperator *BO = new chillAST_BinaryOperator(lhs, "%", rhs ); + return new CG_chillRepr(BO); + + /* + if (rop == NULL || lop == NULL) { + return NULL; + } + + Expr *op1 = static_cast<CG_chillRepr*>(lop)->GetExpression(); + Expr *op2 = static_cast<CG_chillRepr*>(rop)->GetExpression(); + + // Not sure about type!! + fprintf(stderr, "gonna die in CG_chillBuilder.cc ~line 394\n"); + BinaryOperator *ins = NULL; // new (astContext_)BinaryOperator(op1, op2, BO_Rem, op1->getType(), SourceLocation()); + + delete lop; delete rop; + return new CG_chillRepr(ins); + */ + } + + + + //----------------------------------------------------------------------------- + CG_outputRepr *CG_chillBuilder::CreateIntegerCeil(CG_outputRepr *lop, CG_outputRepr *rop) const { + return CreateMinus(NULL, CreateIntegerFloor(CreateMinus(NULL, lop), rop)); + } + + + + //----------------------------------------------------------------------------- + // binary logical operations + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateAnd(CG_outputRepr *lop, + CG_outputRepr *rop) const { + fprintf(stderr, "CG_chillBuilder::CreateAnd()\n"); + if (rop == NULL) + return lop; + else if (lop == NULL) + return rop; + + /* if (rop == NULL || lop == NULL ) { + fprintf(stderr, "returning NULL!\n"); + return NULL; + }*/ + + CG_chillRepr *clop = (CG_chillRepr *) lop; + CG_chillRepr *crop = (CG_chillRepr *) rop; + + chillAST_node *lAST = clop->chillnodes[0]; // always just one? + chillAST_node *rAST = crop->chillnodes[0]; // always just one? + + //fprintf(stderr, "building "); + //lAST->print(0, stderr); + //fprintf(stderr, " && "); + //rAST->print(0, stderr); + //fprintf(stderr, " ??\n"); + + chillAST_BinaryOperator *binop = new chillAST_BinaryOperator( lAST, "&&", rAST, NULL); + return new CG_chillRepr( binop ); + } + + + //----------------------------------------------------------------------------- + // binary relational operations + //----------------------------------------------------------------------------- + // CG_outputRepr* CG_chillBuilder::CreateGE(CG_outputRepr *lop, // use the outputBuilder version + // CG_outputRepr *rop) const { + // + // Expr *op1 = static_cast<CG_chillRepr*>(lop)->GetExpression(); + // Expr *op2 = static_cast<CG_chillRepr*>(rop)->GetExpression(); + + // Not sure about type!! + // fprintf(stderr, "about to die in CG_chillBuilder ~line 480\n"); + + // BinaryOperator *ins = NULL; // new (astContext_)BinaryOperator(op1, op2, BO_GE, op1->getType(), SourceLocation()); + + // delete lop; delete rop; + // return new CG_chillRepr(ins); + // } + + + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateLE(CG_outputRepr *lop, + CG_outputRepr *rop) const { + //fprintf(stderr, "CG_chillBuilder::CreateLE()\n"); + if (rop == NULL || lop == NULL) { + return NULL; + } + + CG_chillRepr *clop = (CG_chillRepr *) lop; + CG_chillRepr *crop = (CG_chillRepr *) rop; + + chillAST_node *lAST = clop->chillnodes[0]; // always just one? + chillAST_node *rAST = crop->chillnodes[0]; // always just one? + + //fprintf(stderr, "building "); + //lAST->print(0, stderr); + //fprintf(stderr, " <= "); + //rAST->print(0, stderr); + //fprintf(stderr, " ??\n"); + + chillAST_BinaryOperator *binop = new chillAST_BinaryOperator( lAST, "<=", rAST, NULL); + delete lop; delete rop; // ?? + return new CG_chillRepr( binop ); + } + + + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateEQ(CG_outputRepr *lop, + CG_outputRepr *rop) const { + //fprintf(stderr, "CG_chillBuilder::CreateEQ()\n"); + if (rop == NULL || lop == NULL) { + return NULL; + } + + CG_chillRepr *clop = (CG_chillRepr *) lop; + CG_chillRepr *crop = (CG_chillRepr *) rop; + + chillAST_node *lAST = clop->chillnodes[0]; // always just one? + chillAST_node *rAST = crop->chillnodes[0]; // always just one? + + //fprintf(stderr, "building "); + //lAST->print(0, stderr); + //fprintf(stderr, " = "); + //rAST->print(0, stderr); + //fprintf(stderr, " ??\n"); + + chillAST_BinaryOperator *binop = new chillAST_BinaryOperator( lAST, "==", rAST, NULL); + delete lop; delete rop; // ?? + return new CG_chillRepr( binop ); + } + + + + + CG_outputRepr* CG_chillBuilder::CreateNEQ(CG_outputRepr *lop, + CG_outputRepr *rop) const { + //fprintf(stderr, "CG_chillBuilder::CreateNEQ()\n"); + if (rop == NULL || lop == NULL) { + return NULL; + } + + CG_chillRepr *clop = (CG_chillRepr *) lop; + CG_chillRepr *crop = (CG_chillRepr *) rop; + + chillAST_node *lAST = clop->chillnodes[0]; // always just one? + chillAST_node *rAST = crop->chillnodes[0]; // always just one? + + //fprintf(stderr, "building "); + //lAST->print(0, stderr); + //fprintf(stderr, " != "); + //rAST->print(0, stderr); + //fprintf(stderr, " ??\n"); + + chillAST_BinaryOperator *binop = new chillAST_BinaryOperator( lAST, "!=", rAST, NULL); + delete lop; delete rop; // ?? + return new CG_chillRepr( binop ); + } + + + CG_outputRepr* CG_chillBuilder::CreateDotExpression(CG_outputRepr *lop, + CG_outputRepr *rop) const { + //fprintf(stderr, "\nCG_chillBuilder::CreateDotExpression()\n"); + if (rop == NULL || lop == NULL) { + return NULL; + } + + CG_chillRepr *clop = (CG_chillRepr *) lop; + CG_chillRepr *crop = (CG_chillRepr *) rop; + + chillAST_node *lAST = clop->chillnodes[0]; // always just one? + chillAST_node *rAST = crop->chillnodes[0]; // always just one? + //fprintf(stderr, "left is %s, right is %s\n", lAST->getTypeString(), rAST->getTypeString()); + + if ( !rAST->isVarDecl()) { + fprintf(stderr, "CG_chillBuilder::CreateDotExpression() right is a %s, not a vardecl\n", + rAST->getTypeString()); + exit(-1); + } + chillAST_VarDecl *rvd = (chillAST_VarDecl *)rAST; + //fprintf(stderr, "building "); + //lAST->print(0, stderr); + //fprintf(stderr, "."); + //rAST->print(0, stderr); + //fprintf(stderr, " ??\n"); + + //chillAST_BinaryOperator *binop = new chillAST_BinaryOperator( lAST, ".", rAST, NULL); + + + // MemberExpr should be a DeclRefExpr on the left? + chillAST_DeclRefExpr *DRE = NULL; + if (lAST->isDeclRefExpr()) DRE = (chillAST_DeclRefExpr *)lAST; + if (lAST->isVarDecl()) { + // make a DeclRefExpr ? probably an error upstream of here in this case + DRE = new chillAST_DeclRefExpr( (chillAST_VarDecl *)lAST ); + } + if (!DRE) { + fprintf(stderr, "CG_chillBuilder::CreateDotExpression(), can't create base\n"); + exit(-1); + } + chillAST_MemberExpr *memexpr = new chillAST_MemberExpr( DRE, rvd->varname, NULL, NULL, CHILL_MEMBER_EXP_DOT ); + + + //delete lop; delete rop; // ?? + return new CG_chillRepr( memexpr ); + } + + + //----------------------------------------------------------------------------- + // stmt list gen operations + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::CreateStmtList(CG_outputRepr *singleton) const { + //fprintf(stderr, "CG_chillBuilder::CreateStmtList()\n"); + if(singleton == NULL) return NULL; + + exit(-1); // DFL + return( NULL ); + /* + StmtList *tnl = static_cast<CG_chillRepr *>(singleton)->GetCode(); + + if(tnl->empty()) { + StmtList foo; + fprintf(stderr, "gonna die soon CG_chillBuilder::CreateStmtList()\n"); exit(-1); + //foo.push_back(static_cast<CG_chillRepr*>(singleton)->op_); + return new CG_chillRepr(foo); + } + delete singleton; + return new CG_chillRepr(*tnl); + */ + } + + + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::StmtListInsertLast(CG_outputRepr *list, + CG_outputRepr *node) const { + return StmtListAppend(list, node); + } + + + //----------------------------------------------------------------------------- + CG_outputRepr* CG_chillBuilder::StmtListAppend(CG_outputRepr *list1, + CG_outputRepr *list2) const { + + //fprintf(stderr, "CG_chillBuilder::StmtListAppend()\n"); + + if(list1 == NULL) return list2; + else if(list2 == NULL) return list1; + + CG_chillRepr *cr1 = (CG_chillRepr *)list1; + CG_chillRepr *cr2 = (CG_chillRepr *)list2; + + int numtoadd = cr2->chillnodes.size(); + //fprintf(stderr, "before: %d nodes and %d nodes\n", cr1->chillnodes.size(), numtoadd ); + for (int i=0; i<numtoadd; i++){ + (cr1->chillnodes).push_back(cr2->chillnodes[i] ); + } + //fprintf(stderr, "after %d nodes\n", cr1->chillnodes.size() ); + + delete list2; + return list1; + + } + + + bool CG_chillBuilder::QueryInspectorType(const std::string &varName) const { + fprintf(stderr, "CG_chillBuilder::QueryInspectorType( %s )\n", varName.c_str()); + int *i=0; int j= i[0]; + return false; + } + + + CG_outputRepr* CG_chillBuilder::CreateArrayRefExpression(const std::string &_s, + CG_outputRepr *rop) const { + fprintf(stderr, "CG_chillBuilder::CreateArrayRefExpression() DIE\n"); + fprintf(stderr, "string s '%s'\n", _s.c_str()); + rop->dump(); + + int *i=0; int j = i[0]; + exit(-1); + } + + + CG_outputRepr* CG_chillBuilder::CreateArrayRefExpression(CG_outputRepr*left, + CG_outputRepr*right) const{ + + chillAST_node *l = ((CG_chillRepr *)left)->GetCode(); + chillAST_node *r = ((CG_chillRepr *)right)->GetCode(); + + chillAST_node *base = NULL; + + if (l->isDeclRefExpr()) base = l; + if (l->isMemberExpr()) base = l; + if (l->isVarDecl()) { // ?? + // make a declRefExpr that uses VarDecl l + base = (chillAST_node *) new chillAST_DeclRefExpr( (chillAST_VarDecl *)l ); + } + + if (!base) { + fprintf(stderr, "CG_chillBuilder::CreateArrayRefExpression(), left is %s\n", l->getTypeString()); + + exit(-1); + } + + + + chillAST_ArraySubscriptExpr *ASE = new chillAST_ArraySubscriptExpr( base, r, NULL, 0); // unique TODO + return new CG_chillRepr( ASE ); + } + + + CG_outputRepr* CG_chillBuilder::ObtainInspectorData(const std::string &_s, const std::string &member_name) const{ + fprintf(stderr, "CG_chillBuilder::ObtainInspectorData( %s, %s)\n", + _s.c_str(), member_name.c_str()); + + //WTF + + return ObtainInspectorRange( _s, member_name ); + } + + + CG_outputRepr *CG_chillBuilder::CreateAddressOf(CG_outputRepr* op) const { + fprintf(stderr, "CG_chillBuilder::CreateAddressOf()\n"); + exit(-1); + } + + CG_outputRepr* CG_chillBuilder::CreateBreakStatement() const { + fprintf(stderr, "CG_chillBuilder::CreateBreakStatement()\n"); + exit(-1); + } + + + CG_outputRepr *CG_chillBuilder::CreateStatementFromExpression(CG_outputRepr *exp) const { + fprintf(stderr, "CG_chillBuilder::CreateStatementFromExpression()\n"); + exit(-1); + } + + + + + CG_outputRepr *CG_chillBuilder::CreateStruct(const std::string struct_name, + std::vector<std::string> data_members, + std::vector<CG_outputRepr *> data_types) + { + + fprintf(stderr, "\nCG_chillBuilder::CreateStruct( %s )\n", struct_name.c_str()); + +/* WRONG - a typedef + // NEED TO ADD TYPEDEF TO ... SOMETHING + + chillAST_TypedefDecl *tdd = new chillAST_TypedefDecl( ) ; + + tdd->setStructName(struct_name.c_str()); + tdd->setStruct( true ); + int n_memb = data_members.size(); + int n_data_types = data_types.size(); + for (int i=0; i<n_memb; i++) { + chillAST_VarDecl *vd; + fprintf(stderr, "member %s type ", data_members[i].c_str()); + if (i <n_data_types) { + vd = (chillAST_VarDecl *) ((CG_chillRepr *)data_types[i])->GetCode(); + vd->varname = strdup( data_members[i].c_str() ); + bool simplepointer = (vd->numdimensions == 1 && !vd->knownArraySizes); + if (simplepointer) fprintf(stderr, "pointer to "); + fprintf(stderr, "%s\n", vd->vartype ); + if (vd->numdimensions > 0 && vd->knownArraySizes) { + for (int k=0; k<vd->numdimensions; k++) fprintf(stderr, "[%d]", vd->arraysizes[k]); + } + } + else { + fprintf(stderr, "type int BY DEFAULT (bad idea)\n"); + vd = new chillAST_VarDecl( "int", data_members[i].c_str(), "", NULL); + } + // add vd to suparts of the struct typedef + tdd->subparts.push_back( vd ); + + fprintf(stderr, "\n"); + } + + // put the typedef in the top level ... for now TODO + toplevel->insertChild( 0, tdd); + return new CG_chillRepr( tdd ); +*/ + + + chillAST_RecordDecl *rd = new chillAST_RecordDecl(struct_name.c_str(), toplevel); + rd->setStruct( true ); + // SO FAR, struct has no members! + + toplevel->insertChild(0, rd); // inserts at beginning of file, (after defines?) + // note: parent at top level so far TODO + //toplevel->print(); printf("\n\n"); fflush(stdout); + + int n_memb = data_members.size(); + int n_data_types = data_types.size(); + // add struct members + for (int i=0; i<n_memb; i++) { + chillAST_VarDecl *vd = NULL; + //fprintf(stderr, "%d member %s type ", i, data_members[i].c_str()); + if (i < n_data_types) { + // this should always happen, formerly, if no data type was + // specified, it was an int. bad idea + vd = (chillAST_VarDecl *) ((CG_chillRepr *)data_types[i])->GetCode(); + + // vd did not have a name before + vd->varname = strdup( data_members[i].c_str() ); + + vd->parent = rd; // ?? + + bool simplepointer = (vd->numdimensions == 1 && !vd->knownArraySizes); + if (simplepointer) { + fprintf(stderr, "struct member %s is pointer to %s\n", vd->varname, vd->vartype); + vd->arraypointerpart = strdup("*"); // ?? + } + else { + //fprintf(stderr, "struct member %s is not a pointer TODO!\n", vd->varname); + fprintf(stderr, "struct member %s is %s\n", vd->varname, vd->vartype); + + // it should be good to go ??? + } + //vd->print(); printf("\n"); fflush(stdout); + //fprintf(stderr, "%s\n", vd->vartype ); + //if (vd->numdimensions > 0 && vd->knownArraySizes) { + // for (int k=0; k<vd->numdimensions; k++) fprintf(stderr, "[%d]", vd->arraysizes[k]); + //} + } + else { + fprintf(stderr, "int BY DEFAULT (bad idea) FIXME\n"); // TODO + vd = new chillAST_VarDecl( "int", data_members[i].c_str(), "", NULL); + } + rd->addSubpart( vd ); + //fprintf(stderr, "\n"); + } + fprintf(stderr, "\n"); + return new CG_chillRepr( rd ); + } + + + + CG_outputRepr *CG_chillBuilder::CreateClassInstance(std::string name , // TODO can't make array + CG_outputRepr *class_def){ + fprintf(stderr, "CG_chillBuilder::CreateClassInstance( %s )\n", name.c_str()); + + CG_chillRepr *CD = (CG_chillRepr *)class_def; + chillAST_node *n = CD->GetCode(); + //fprintf(stderr, "class def is of type %s\n", n->getTypeString()); + //n->print(); printf("\n"); fflush(stdout); + + if (n->isTypeDefDecl()) { + chillAST_TypedefDecl *tdd = (chillAST_TypedefDecl *)n; + //tdd->print(); printf("\n"); fflush(stdout); + + chillAST_VarDecl *vd = new chillAST_VarDecl( tdd, name.c_str(), "", NULL); + + // we need to add this to function ?? TODO + //fprintf(stderr, "adding typedef instance to symbolTable\n"); + chillAST_SymbolTable *st = currentfunction->getBody()->getSymbolTable(); + //printSymbolTable(st); + + currentfunction->getBody()->addVariableToSymbolTable( vd ); // TODO + currentfunction->getBody()->insertChild(0, vd); // TODO + //printSymbolTable(st); + + return new CG_chillRepr( vd ); + } + if (n->isRecordDecl()) { + fprintf(stderr, "a RecordDecl\n"); + + chillAST_RecordDecl *rd = (chillAST_RecordDecl *) n; + rd->print(); printf("\n"); fflush(stdout); + rd->dump(); printf("\n"); fflush(stdout); + + chillAST_VarDecl *vd = new chillAST_VarDecl( rd, name.c_str(), "", NULL); + + //fprintf(stderr, "CG_chillBuilder.cc, adding struct instance to body of function's symbolTable\n"); + + + // we need to add this to function ?? TODO + currentfunction->getBody()->addVariableToSymbolTable( vd ); // TODO + currentfunction->getBody()->insertChild(0, vd); // TODO + //printf("\nafter adding vardecl, source is:\n"); + currentfunction->getBody()->print(); fflush(stdout); + + //printf("\nafter adding vardecl, symbol table is:\n"); + chillAST_SymbolTable *st = currentfunction->getBody()->getSymbolTable(); + //printSymbolTable(st); fflush(stdout); + + return new CG_chillRepr( vd ); + } + + fprintf(stderr, "ERROR: CG_chillBuilder::CreateClassInstance() not sent a class or struct\n"); + int *i=0; int j = i[0]; + return NULL; + } + + + + CG_outputRepr *CG_chillBuilder::lookup_member_data(CG_outputRepr* classtype, + std::string varName, + CG_outputRepr *instance) { + + + //fprintf(stderr, "CG_chillBuilder::lookup_member_data( %s )\n", varName.c_str()); + + chillAST_VarDecl* sub = NULL; + + CG_chillRepr *CR = (CG_chillRepr *)classtype; + chillAST_node *classnode = CR->GetCode(); + //fprintf(stderr, "classnode is %s\n", classnode->getTypeString()); classnode->print(); printf("\n"); fflush(stdout); + if (! ( classnode->isTypeDefDecl() || + classnode->isRecordDecl() )) { + fprintf(stderr, "ERROR: CG_chillBuilder::lookup_member_data(), classnode is not a TypeDefDecl or a RecordDecl\n"); + exit(-1); + } + + + CG_chillRepr *CI = (CG_chillRepr *)instance; + + chillAST_node *in = CI->GetCode(); + //fprintf(stderr, "instance is %s\n", in->getTypeString()); + //in->print(); printf("\n"); fflush(stdout); + + if ( !in->isVarDecl() ) { // error, instance needs to be a vardecl + fprintf(stderr, "ERROR: CG_chillBuilder::lookup_member_data() instance needs to be a VarDecl, not a %s", in->getTypeString()); + exit(-1); + } + chillAST_VarDecl *vd = (chillAST_VarDecl *)in; + if (vd->typedefinition != classnode && + vd->vardef != classnode) { + fprintf(stderr, "vd: typedef %p vardev %p classnode %p\n", vd->typedefinition, vd->vardef, classnode); + fprintf(stderr, "CG_chillBuilder::lookup_member_data(), instance is not of correct class \n"); + + exit(-1); + } + + + + if (classnode->isTypeDefDecl()){ + chillAST_TypedefDecl *tdd = (chillAST_TypedefDecl *)classnode; + if ( !tdd->isAStruct() ) { + fprintf(stderr, "ERROR: CG_chillBuilder::lookup_member_data() instance must be a struct or class\n"); + exit(-1); + } + + sub = tdd->findSubpart( varName.c_str() ); + } + + if (classnode->isRecordDecl()){ + chillAST_RecordDecl *rd = (chillAST_RecordDecl *)classnode; + if ( !rd->isAStruct() ) { + fprintf(stderr, "ERROR: CG_chillBuilder::lookup_member_data() instance must be a struct or class\n"); + exit(-1); + } + + //fprintf(stderr, "looking for member (subpart) %s in RecordDecl\n", varName.c_str()); + sub = rd->findSubpart( varName.c_str() ); + } + + if (!sub) { + fprintf(stderr, "CG_chillBuilder::lookup_member_data(), variable %s is not submember of class/struct\n"); + exit(-1); + } + + //fprintf(stderr, "subpart (member) %s is\n", varName.c_str()); sub->print(); printf("\n"); fflush(stdout); + + return( new CG_chillRepr( sub ) ); // the vardecl inside the struct typedef + } + + + CG_outputRepr* CG_chillBuilder::CreatePointer(std::string &name) const { + //fprintf(stderr, "CG_chillBuilder::CreatePointer( %s )\n", name.c_str()); + + chillAST_VarDecl *vd = new chillAST_VarDecl( "int", name.c_str(), "*", currentfunction->getBody()); + //vd->print(); printf("\n"); fflush(stdout); + //vd->dump(); printf("\n"); fflush(stdout); + + //printSymbolTable( currentfunction->getBody()->getSymbolTable() ); + + chillAST_DeclRefExpr *dre = new chillAST_DeclRefExpr( vd ); // ?? + return new CG_chillRepr( dre ); // need a declrefexpr? + } + + + CG_outputRepr* CG_chillBuilder::ObtainInspectorRange(const std::string &structname, const std::string &member) const { + //fprintf(stderr, "CG_chillBuilder::ObtainInspectorRange(%s, %s )\n", structname.c_str(), member.c_str()); + + // find a struct/class with name structname and member member + // return a Member access (or binary dot op ) + // seems like you need to know where (scoping) to look for the struct definition + + std::vector<chillAST_VarDecl*> decls; + currentfunction->gatherVarDecls( decls ); + //fprintf(stderr, "\nfunc has %d vardecls (looking for %s)\n", decls.size(), structname.c_str()); + + chillAST_VarDecl *thestructvd = NULL; + for (int i=0; i<decls.size(); i++) { + chillAST_VarDecl *vd = decls[i]; + //vd->print(); printf("\n"); fflush(stdout); + + if (structname == vd->varname) { + //fprintf(stderr, "found it!\n"); + thestructvd = vd; + break; + } + } + + if (!thestructvd) { + fprintf(stderr, "CG_chillBuilder::ObtainInspectorRange could not find variable named %s in current function\n", structname.c_str()); + exit(-1); + } + + // make sure the variable is a struct with a member with the correct name + chillAST_RecordDecl *rd = thestructvd->getStructDef(); + if ( !rd ) { + fprintf(stderr, "CG_chillBuilder::ObtainInspectorRange(), variable %s is not a struct/class\n", structname.c_str()); + exit(-1); + } + + + chillAST_VarDecl *sub = rd->findSubpart( member.c_str() ); + if (!sub) { + fprintf(stderr, "CG_chillBuilder::ObtainInspectorRange(), struct/class %s has no member named %s\n", structname.c_str(), member.c_str()); + exit(-1); + } + + + // build up a member expression (or a binop with dot operation?? ) + // make a declrefexpr that refers to this variable definition + chillAST_DeclRefExpr *DRE = new chillAST_DeclRefExpr( thestructvd ); + chillAST_MemberExpr *ME = new chillAST_MemberExpr( DRE, member.c_str(), NULL, NULL ); // uniq TODO + + return new CG_chillRepr( ME ); + } + +} // namespace + + diff --git a/lib/chillcg/src/CG_chillRepr.cc b/lib/chillcg/src/CG_chillRepr.cc new file mode 100755 index 0000000..0fd72a5 --- /dev/null +++ b/lib/chillcg/src/CG_chillRepr.cc @@ -0,0 +1,127 @@ +/***************************************************************************** + Copyright (C) 2008 University of Southern California. + All Rights Reserved. + + Purpose: + omega holder for chill AST implementaion + + Notes: + + History: + 02/01/06 - Chun Chen - created + LLVM/CLANG interface created by Saurav Muralidharan +*****************************************************************************/ + +#include <code_gen/CG_chillRepr.h> +#include <stdio.h> +#include <stdlib.h> // for exit() + +namespace omega { + + CG_chillRepr::~CG_chillRepr() { + } + + //void CG_chillRepr::AppendStmt(Stmt *s) const { + // tree_node_list_->push_back(s); + //} + + //void CG_chillRepr::AppendV(StmtList *sl) const { + // for(int i=0; i<sl->size(); ++i) tree_node_list_->push_back((*sl)[i]); + //} + + + chillAST_node * CG_chillRepr::GetCode() { + //fprintf(stderr, "CG_chillRepr::GetCode() this %p size %d\n", this, chillnodes.size()); + + if (0 == chillnodes.size()) return NULL; // error? + + if (1 == chillnodes.size()) return chillnodes[0]; + + // make a compoundstatement with all the code ??? probably should be that way already + fprintf(stderr, "CG_chillRepr GetCode(), multiple (%d) statements in the code??\n", chillnodes.size()); + for (int i=0; i<chillnodes.size(); i++) { + fprintf(stderr, "chillnode %d %p\n", i, chillnodes[i] ); + } + + + chillAST_CompoundStmt *CS = new chillAST_CompoundStmt(); + for (int i=0; i<chillnodes.size(); i++) { + CS->addChild( chillnodes[i] ); + } + return CS; + } + + + + CG_outputRepr* CG_chillRepr::clone() const { // make a deep/shallow COPY of all the nodes + //fprintf(stderr, "CG_chillRepr::clone() %d chill nodes\n", chillnodes.size()); + //for (int i=0; i<chillnodes.size(); i++) { chillnodes[i]->print(); printf("\n"); } fflush(stdout); + + CG_chillRepr *newrepr = new CG_chillRepr(); // empty + + // deep ( nothing is the same as in the source ) + for (int i=0; i<chillnodes.size(); i++) newrepr->addStatement( chillnodes[i]->clone() ); + + // shallow (the submembers are the same ) + //for (int i=0; i<chillnodes.size(); i++) newrepr->addStatement( chillnodes[i] ); + //fprintf(stderr, "done cloning\n"); + return newrepr; + } + + + + void CG_chillRepr::clear() { + chillnodes.clear(); + } + + + // TODO this is duplicated and shouldn't be here anyway + static std::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 std::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. + }; + + + + //void CG_chillRepr::dump() const { Dump(); } + + + void CG_chillRepr::Dump() const { + CG_chillRepr *me = (CG_chillRepr *)this; // ?? + //fprintf(stderr, "repr of type "); + //fprintf(stderr, "%s\n", this->type()); + int numnodes = me->chillnodes.size(); + //fprintf(stderr, "repr %p %d nodes\n", this, numnodes); + for (int i=0; i<numnodes; i++) { + me->chillnodes[i]->print(); printf("\n"); fflush(stdout); + } + return; + } + +} // namespace diff --git a/lib/codegen/include/code_gen/CG.h b/lib/codegen/include/code_gen/CG.h index ce56768..4dd629c 100644 --- a/lib/codegen/include/code_gen/CG.h +++ b/lib/codegen/include/code_gen/CG.h @@ -22,9 +22,13 @@ struct CG_result { virtual std::pair<CG_result *, Relation> liftOverhead(int depth, bool propagate_up) = 0; virtual Relation hoistGuard() = 0; virtual void removeGuard(const Relation &guard) = 0; - virtual CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const = 0; - CG_outputRepr *printRepr(CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts) const; - std::string printString() const; + virtual CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly,std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > unin, bool printString = false) const = 0; + CG_outputRepr *printRepr(CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, std::vector<std::map<std::string,std::vector<CG_outputRepr *> > >uninterpreted_symbols, bool printString = false) const; + std::string printString(std::vector<std::map<std::string, std::vector<CG_outputRepr *> > >uninterpreted_symbols = std::vector<std::map<std::string, std::vector<CG_outputRepr *> > >()) const; + + //virtual CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const = 0; + //CG_outputRepr *printRepr(CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts) const; + //std::string printString() const; int num_level() const; virtual CG_result *clone() const = 0; virtual void dump(int indent) const {} @@ -52,7 +56,8 @@ struct CG_split: public CG_result { std::pair<CG_result *, Relation> liftOverhead(int depth, bool propagate_up); Relation hoistGuard(); void removeGuard(const Relation &guard); - CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const; + CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > unin, bool printString=false) const; + // CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const; CG_result *clone() const; void dump(int indent) const; @@ -85,8 +90,11 @@ struct CG_loop: public CG_result { std::pair<CG_result *, Relation> liftOverhead(int depth, bool propagate_up); Relation hoistGuard(); void removeGuard(const Relation &guard); - CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const; - CG_outputRepr *printRepr(bool do_print_guard, int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const; + CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly,std::vector<std::map<std::string, std::vector<CG_outputRepr *> > >unin, bool printString = false) const; + CG_outputRepr *printRepr(bool do_print_guard, int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > unin, bool printString = false) const; + + // CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const; + //CG_outputRepr *printRepr(bool do_print_guard, int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const; CG_result *clone() const; void dump(int indent) const; }; @@ -108,7 +116,8 @@ struct CG_leaf: public CG_result { std::pair<CG_result *, Relation> liftOverhead(int depth, bool propagate_up); Relation hoistGuard(); void removeGuard(const Relation &guard); - CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const; + CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > unin, bool printString = false) const; + // CG_outputRepr *printRepr(int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const; CG_result *clone() const; void dump(int indent) const; }; diff --git a/lib/codegen/include/code_gen/CG_outputBuilder.h b/lib/codegen/include/code_gen/CG_outputBuilder.h index 19dc440..ce86c91 100644 --- a/lib/codegen/include/code_gen/CG_outputBuilder.h +++ b/lib/codegen/include/code_gen/CG_outputBuilder.h @@ -4,7 +4,7 @@ All Rights Reserved. Purpose: - abstract base class of comiler IR code builder + abstract base class of compiler IR code builder Notes: All "CG_outputRepr *" parameters are consumed inside the the function @@ -29,57 +29,98 @@ namespace omega { -//! abstract base class of comiler IR code builder class CG_outputBuilder { +private: + public: + CG_outputBuilder() {} virtual ~CG_outputBuilder() {} - //! substitute variables in stmt - virtual CG_outputRepr *CreateSubstitutedStmt(int indent, CG_outputRepr *stmt, - const std::vector<std::string> &vars, - std::vector<CG_outputRepr *> &subs) const = 0; - //! assignment stmt generation - virtual CG_outputRepr *CreateAssignment(int indent, CG_outputRepr *lhs, + virtual CG_outputRepr *CreateStruct(const std::string class_name, + std::vector<std::string> class_data_members, // why not just vector< CG_outputRepr> subparts; + std::vector<CG_outputRepr *> class_data_types )=0; + virtual CG_outputRepr *CreateClassInstance(std::string name , CG_outputRepr *class_def)=0; + virtual CG_outputRepr *lookup_member_data(CG_outputRepr* scope, std::string varName, CG_outputRepr *instance)=0; + virtual CG_outputRepr* CreatePointer(std::string &name) const = 0; + virtual CG_outputRepr* ObtainInspectorRange(const std::string &_s, const std::string &_name) const=0; + + + + //--------------------------------------------------------------------------- + // substitute variables in stmt + //--------------------------------------------------------------------------- + virtual CG_outputRepr *CreateSubstitutedStmt(int indent, + CG_outputRepr *stmt, + const std::vector<std::string> &vars, + std::vector<CG_outputRepr *> &subs, + bool actuallyPrint =true) const = 0; + + //--------------------------------------------------------------------------- + // assignment stmt generation + //--------------------------------------------------------------------------- + virtual CG_outputRepr *CreateAssignment(int indent, + CG_outputRepr *lhs, CG_outputRepr *rhs) const = 0; - //! function invocation generation + virtual CG_outputRepr *CreatePlusAssignment(int indent, + CG_outputRepr *lhs, + CG_outputRepr *rhs) const = 0; + + //--------------------------------------------------------------------------- + // function invocation generation + //--------------------------------------------------------------------------- virtual CG_outputRepr *CreateInvoke(const std::string &funcName, - std::vector<CG_outputRepr *> &argList) const = 0; + std::vector<CG_outputRepr *> &argList, + bool is_array=false) const = 0; - //! comment generation + //--------------------------------------------------------------------------- + // comment generation + //--------------------------------------------------------------------------- virtual CG_outputRepr *CreateComment(int indent, const std::string &commentText) const = 0; - //! Attribute generation + //--------------------------------------------------------------------------- + // Attribute generation + //--------------------------------------------------------------------------- virtual CG_outputRepr* CreateAttribute(CG_outputRepr *control, const std::string &commentText) const = 0; - //! Pragma Attribute + //--------------------------------------------------------------------------- + // Pragma Attribute + // -------------------------------------------------------------------------- virtual CG_outputRepr* CreatePragmaAttribute(CG_outputRepr *scopeStmt, int looplevel, const std::string &pragmaText) const = 0; - //! Prefetch Attribute + //--------------------------------------------------------------------------- + // Prefetch Attribute + //--------------------------------------------------------------------------- virtual CG_outputRepr* CreatePrefetchAttribute(CG_outputRepr *scopeStmt, int looplevel, const std::string &arrName, int hint) const = 0; - //! generate if stmt, true/false stmt can be NULL but not the condition + //--------------------------------------------------------------------------- + // generate if stmt, true/false stmt can be NULL but not the condition + //--------------------------------------------------------------------------- virtual CG_outputRepr *CreateIf(int indent, CG_outputRepr *guardCondition, CG_outputRepr *true_stmtList, CG_outputRepr *false_stmtList) const = 0; - //! generate loop inductive variable (loop control structure) + //--------------------------------------------------------------------------- + // generate loop inductive variable (loop control structure) + //--------------------------------------------------------------------------- virtual CG_outputRepr *CreateInductive(CG_outputRepr *index, CG_outputRepr *lower, CG_outputRepr *upper, CG_outputRepr *step) const = 0; - //! generate loop stmt from loop control and loop body, NULL parameter allowed + //--------------------------------------------------------------------------- + // generate loop stmt from loop control and loop body, NULL parameter allowed + //--------------------------------------------------------------------------- virtual CG_outputRepr *CreateLoop(int indent, CG_outputRepr *control, CG_outputRepr *stmtList) const = 0; - //! copy operation, NULL parameter allowed. - /*! - * this function makes pointer handling uniform regardless NULL status - */ + //--------------------------------------------------------------------------- + // copy operation, NULL parameter allowed. this function makes pointer + // handling uniform regardless NULL status + //--------------------------------------------------------------------------- virtual CG_outputRepr *CreateCopy(CG_outputRepr *original) const { if (original == NULL) return NULL; @@ -87,73 +128,87 @@ public: return original->clone(); } - //! basic integer number creation + //--------------------------------------------------------------------------- + // basic integer number creation + //--------------------------------------------------------------------------- virtual CG_outputRepr *CreateInt(int num) const = 0; - virtual bool isInteger(CG_outputRepr *op) const = 0; + virtual CG_outputRepr *CreateFloat(float num) const = 0; + virtual CG_outputRepr *CreateDouble(double num) const = 0; + virtual bool isInteger(CG_outputRepr *op) const = 0; + virtual bool QueryInspectorType(const std::string &varName) const = 0; - //! basic identity/variable creation + //--------------------------------------------------------------------------- + // basic identity/variable creation + //--------------------------------------------------------------------------- virtual CG_outputRepr *CreateIdent(const std::string &varName) const = 0; - - //! Addition operations, NULL parameter means 0, + virtual CG_outputRepr* CreateDotExpression(CG_outputRepr *lop, + CG_outputRepr *rop) const =0; + virtual CG_outputRepr* CreateArrayRefExpression(const std::string &_s, + CG_outputRepr *rop) const =0; + virtual CG_outputRepr* CreateArrayRefExpression(CG_outputRepr *lop, + CG_outputRepr *rop) const=0; + virtual CG_outputRepr* ObtainInspectorData(const std::string &_s, const std::string &member_name) const=0; + virtual CG_outputRepr* CreateNullStatement() const=0; + + //--------------------------------------------------------------------------- + // binary arithmetic operations, NULL parameter means 0, + // Note: + // integer division truncation method undefined, only use when lop is known + // to be multiple of rop, otherwise use integer floor instead + //--------------------------------------------------------------------------- virtual CG_outputRepr *CreatePlus(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - //! Subtraction operations, NULL parameter means 0, virtual CG_outputRepr *CreateMinus(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - //! Multiplication operations, NULL parameter means 0, virtual CG_outputRepr *CreateTimes(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - //! Division operations, NULL parameter means 0, - /*! - * integer division truncation method undefined, only use when lop is known - * to be multiple of rop, otherwise use integer floor instead - */ virtual CG_outputRepr *CreateDivide(CG_outputRepr *lop, CG_outputRepr *rop) const { return CreateIntegerFloor(lop, rop); } - //! integer floor functions, NULL parameter means 0 - /*! - * second parameter must be postive (i.e. b > 0 below), otherwise function undefined - * - * floor(a, b) - * * = a/b if a >= 0 - * * = (a-b+1)/b if a < 0 - */ + //--------------------------------------------------------------------------- + // integer arithmetic functions, NULL parameter means 0, second parameter + // must be postive (i.e. b > 0 below), otherwise function undefined + // Note: + // ceil(a, b) = -floor(-a, b) or floor(a+b-1, b) or floor(a-1, b)+1 + // mod(a, b) = a-b*floor(a, b) + // where result must lie in range [0,b) + // floor(a, b) = a/b if a >= 0 + // (a-b+1)/b if a < 0 + // where native '/' operator behaves as 5/2 = 2, (-5)/2 = -2 + //--------------------------------------------------------------------------- virtual CG_outputRepr *CreateIntegerFloor(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - //! integer mod functions, NULL parameter means 0 - /*! - * second parameter must be postive (i.e. b > 0 below), otherwise function undefined - * - * mod(a, b) = a-b*floor(a, b) where result must lie in range [0,b) - */ virtual CG_outputRepr *CreateIntegerMod(CG_outputRepr *lop, CG_outputRepr *rop) const { CG_outputRepr *lop2 = CreateCopy(lop); CG_outputRepr *rop2 = CreateCopy(rop); return CreateMinus(lop2, CreateTimes(rop2, CreateIntegerFloor(lop, rop))); } - //! integer ceil functions, NULL parameter means 0 - /*! - * second parameter must be postive (i.e. b > 0 below), otherwise function undefined - * - * ceil(a, b) = -floor(-a, b) or floor(a+b-1, b) or floor(a-1, b)+1 - */ virtual CG_outputRepr *CreateIntegerCeil(CG_outputRepr *lop, CG_outputRepr *rop) const { return CreateMinus(NULL, CreateIntegerFloor(CreateMinus(NULL, lop), rop)); } - //! binary logical operation, NULL parameter means TRUE + //--------------------------------------------------------------------------- + // binary logical operation, NULL parameter means TRUE + //--------------------------------------------------------------------------- virtual CG_outputRepr *CreateAnd(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - //! binary conditional Greater than or equal to + //--------------------------------------------------------------------------- + // binary condition operations + //--------------------------------------------------------------------------- virtual CG_outputRepr *CreateGE(CG_outputRepr *lop, CG_outputRepr *rop) const { return CreateLE(rop, lop); } - //! binary conditional Less than or equal to virtual CG_outputRepr *CreateLE(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; - //! binary conditional equal to virtual CG_outputRepr *CreateEQ(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; + virtual CG_outputRepr *CreateNEQ(CG_outputRepr *lop, CG_outputRepr *rop) const = 0; + virtual CG_outputRepr *CreateAddressOf(CG_outputRepr *op) const = 0; + virtual CG_outputRepr *CreateBreakStatement(void) const = 0; - //! join stmts together, NULL parameter allowed + //--------------------------------------------------------------------------- + // join stmts together, NULL parameter allowed + //--------------------------------------------------------------------------- virtual CG_outputRepr *StmtListAppend(CG_outputRepr *list1, CG_outputRepr *list2) const = 0; + virtual CG_outputRepr *CreateStatementFromExpression(CG_outputRepr *exp) const = 0; + + virtual const char *ClassName() { return "UNKNOWN"; } }; } diff --git a/lib/codegen/include/code_gen/CG_outputRepr.h b/lib/codegen/include/code_gen/CG_outputRepr.h index 0897007..d72ae6f 100644 --- a/lib/codegen/include/code_gen/CG_outputRepr.h +++ b/lib/codegen/include/code_gen/CG_outputRepr.h @@ -15,17 +15,19 @@ #ifndef _CG_OUTPUTREPR_H #define _CG_OUTPUTREPR_H +#include <string.h> + namespace omega { class CG_outputRepr { public: + CG_outputRepr() {} - //! shallow delete - virtual ~CG_outputRepr() { } + virtual ~CG_outputRepr() { /* shallow delete */ } virtual CG_outputRepr *clone() const = 0; - //! delete actual IR code wrapped inside - virtual void clear() { } + virtual void clear() { /* delete actual IR code wrapped inside */ } virtual void dump() const {} + virtual char *type() const = 0; }; } diff --git a/lib/codegen/include/code_gen/CG_stringBuilder.h b/lib/codegen/include/code_gen/CG_stringBuilder.h index 09d3503..390039a 100644 --- a/lib/codegen/include/code_gen/CG_stringBuilder.h +++ b/lib/codegen/include/code_gen/CG_stringBuilder.h @@ -8,22 +8,39 @@ namespace omega { class CG_stringBuilder: public CG_outputBuilder { public: + CG_stringBuilder() {} ~CG_stringBuilder() {} bool isInteger(CG_outputRepr *op) const; - CG_stringRepr *CreateSubstitutedStmt(int indent, CG_outputRepr *stmt, const std::vector<std::string> &vars, std::vector<CG_outputRepr *> &subs) const; + bool QueryInspectorType(const std::string &varName) const; + + CG_stringRepr *CreateInt(int num) const; + CG_stringRepr *CreateFloat(float num) const; + CG_stringRepr *CreateDouble(double num) const; + + CG_stringRepr *CreateSubstitutedStmt(int indent, CG_outputRepr *stmt, const std::vector<std::string> &vars, std::vector<CG_outputRepr *> &subs, bool actuallyPrint) const; CG_stringRepr *CreateAssignment(int indent, CG_outputRepr *lhs, CG_outputRepr *rhs) const; - CG_stringRepr *CreateInvoke(const std::string &funcName, std::vector<CG_outputRepr *> &argList) const; + CG_stringRepr *CreatePlusAssignment(int indent, CG_outputRepr *lhs, CG_outputRepr *rhs) const; + CG_stringRepr *CreateInvoke(const std::string &funcName, std::vector<CG_outputRepr *> &argList,bool is_array=false) const; CG_stringRepr *CreateComment(int indent, const std::string &commentText) const; CG_stringRepr* CreateAttribute(CG_outputRepr *control, const std::string &commentText) const; CG_outputRepr *CreatePragmaAttribute(CG_outputRepr *scopeStmt, int looplevel, const std::string &pragmaText) const; CG_outputRepr *CreatePrefetchAttribute(CG_outputRepr *scopeStmt, int looplevel, const std::string &arrName, int hint) const; + CG_stringRepr* CreateNullStatement() const; CG_stringRepr *CreateIf(int indent, CG_outputRepr *guardCondition, CG_outputRepr *true_stmtList, CG_outputRepr *false_stmtList) const; CG_stringRepr *CreateInductive(CG_outputRepr *index, CG_outputRepr *lower, CG_outputRepr *upper, CG_outputRepr *step) const; CG_stringRepr *CreateLoop(int indent, CG_outputRepr *control, CG_outputRepr *stmtList) const; - CG_stringRepr *CreateInt(int num) const; + + CG_stringRepr *CreateAddressOf(CG_outputRepr *op) const ; CG_stringRepr *CreateIdent(const std::string &varName) const; + CG_stringRepr *CreateDotExpression(CG_outputRepr *lop, + CG_outputRepr *rop) const; + CG_stringRepr *CreateArrayRefExpression(const std::string &_s, + CG_outputRepr *rop) const; + CG_stringRepr* CreateArrayRefExpression(CG_outputRepr *lop, + CG_outputRepr *rop) const; + CG_stringRepr *ObtainInspectorData(const std::string &_s, const std::string &member_name) const; CG_stringRepr *CreatePlus(CG_outputRepr *lop, CG_outputRepr *rop) const; CG_stringRepr *CreateMinus(CG_outputRepr *lop, CG_outputRepr *rop) const; CG_stringRepr *CreateTimes(CG_outputRepr *lop, CG_outputRepr *rop) const; @@ -35,7 +52,21 @@ public: CG_stringRepr *CreateGE(CG_outputRepr *lop, CG_outputRepr *rop) const; CG_stringRepr *CreateLE(CG_outputRepr *lop, CG_outputRepr *rop) const; CG_stringRepr *CreateEQ(CG_outputRepr *lop, CG_outputRepr *rop) const; + CG_stringRepr *CreateNEQ(CG_outputRepr *lop, CG_outputRepr *rop) const; + CG_stringRepr *CreateBreakStatement(void) const; CG_stringRepr *StmtListAppend(CG_outputRepr *list1, CG_outputRepr *list2) const; + CG_stringRepr *CreateStatementFromExpression(CG_outputRepr *exp) const; + + CG_outputRepr *CreateStruct(const std::string struct_name, + std::vector<std::string> data_members, + std::vector<CG_outputRepr *> data_types); + + CG_outputRepr *CreateClassInstance(std::string name , CG_outputRepr *class_def); + CG_outputRepr *lookup_member_data(CG_outputRepr* scope, std::string varName, CG_outputRepr *instance); + const char *ClassName() { return "stringBuilder"; }; + CG_outputRepr* CreatePointer(std::string &name) const; + CG_outputRepr* ObtainInspectorRange(const std::string &_s, const std::string &_name) const; + }; diff --git a/lib/codegen/include/code_gen/CG_stringRepr.h b/lib/codegen/include/code_gen/CG_stringRepr.h index a6df85d..b483bdb 100644 --- a/lib/codegen/include/code_gen/CG_stringRepr.h +++ b/lib/codegen/include/code_gen/CG_stringRepr.h @@ -18,6 +18,7 @@ #include <code_gen/CG_outputRepr.h> #include <string> #include <iostream> +#include <stdio.h> namespace omega { @@ -26,11 +27,16 @@ private: std::string s_; public: - CG_stringRepr() {} - CG_stringRepr(const std::string &s) { s_ = s; } - ~CG_stringRepr() {} + char *type() const { return strdup("string"); }; + + + CG_stringRepr() {}; + CG_stringRepr(const std::string &s){ s_ = s; } + ~CG_stringRepr() {} CG_outputRepr *clone() const { return new CG_stringRepr(s_); } void dump() const { std::cout << s_ << std::endl; } + void Dump() const; + void DumpToFile(FILE *fp = stderr) const; //--------------------------------------------------------------------------- // basic operation diff --git a/lib/codegen/include/code_gen/CG_utils.h b/lib/codegen/include/code_gen/CG_utils.h index a6128bc..c0995d1 100755 --- a/lib/codegen/include/code_gen/CG_utils.h +++ b/lib/codegen/include/code_gen/CG_utils.h @@ -12,20 +12,29 @@ namespace omega { class CG_loop; -CG_outputRepr *output_inequality_repr(CG_outputBuilder *ocg, const GEQ_Handle &inequality, Variable_ID v, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, std::set<Variable_ID> excluded_floor_vars = std::set<Variable_ID>()); -CG_outputRepr *output_substitution_repr(CG_outputBuilder *ocg, const EQ_Handle &equality, Variable_ID v, bool apply_v_coef, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly); -CG_outputRepr *output_upper_bound_repr(CG_outputBuilder *ocg, const GEQ_Handle &inequality, Variable_ID v, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly); -CG_outputRepr *output_lower_bound_repr(CG_outputBuilder *ocg, const GEQ_Handle &inequality, Variable_ID v, const EQ_Handle &stride_eq, Variable_ID wc, const Relation &R, const Relation &known, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly); +CG_outputRepr *output_inequality_repr(CG_outputBuilder *ocg, const GEQ_Handle &inequality, Variable_ID v, const Relation &R, 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 = std::set<Variable_ID>()); +CG_outputRepr *output_substitution_repr(CG_outputBuilder *ocg, const EQ_Handle &equality, Variable_ID v, bool apply_v_coef, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly,std::map<std::string, std::vector<CG_outputRepr *> > unin); -CG_outputRepr *output_ident(CG_outputBuilder *ocg, const Relation &R, Variable_ID v, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly); -std::pair<CG_outputRepr *, std::pair<CG_outputRepr *, int> > output_assignment(CG_outputBuilder *ocg, const Relation &R, int level, const Relation &known, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly); -CG_outputRepr *output_loop(CG_outputBuilder *ocg, const Relation &R, int level, const Relation &known, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly); -CG_outputRepr *output_guard(CG_outputBuilder *ocg, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly); -std::vector<CG_outputRepr *> output_substitutions(CG_outputBuilder *ocg, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly); +CG_outputRepr *output_upper_bound_repr(CG_outputBuilder *ocg, + const GEQ_Handle &inequality, + Variable_ID v, + const Relation &R, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::map<std::string, std::vector<CG_outputRepr *> > unin); + +CG_outputRepr *output_lower_bound_repr(CG_outputBuilder *ocg, const GEQ_Handle &inequality, Variable_ID v, const EQ_Handle &stride_eq, Variable_ID wc, const Relation &R, const Relation &known, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly,std::map<std::string, std::vector<CG_outputRepr *> > unin); + +CG_outputRepr *output_ident(CG_outputBuilder *ocg, const Relation &R, 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::pair<CG_outputRepr *, std::pair<CG_outputRepr *, int> > output_assignment(CG_outputBuilder *ocg, const Relation &R, int level, const Relation &known, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly,std::map<std::string, std::vector<CG_outputRepr *> > unin); +CG_outputRepr *output_loop(CG_outputBuilder *ocg, const Relation &R, int level, const Relation &known, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly,std::map<std::string, std::vector<CG_outputRepr *> > unin); +CG_outputRepr *output_guard(CG_outputBuilder *ocg, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly,std::map<std::string, std::vector<CG_outputRepr *> > unin); +std::vector<CG_outputRepr *> output_substitutions(CG_outputBuilder *ocg, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly,std::map<std::string, std::vector<CG_outputRepr *> > unin); bool bound_must_hit_stride(const GEQ_Handle &inequality, Variable_ID v, const EQ_Handle &stride_eq, Variable_ID wc, const Relation &bounds, const Relation &known); -std::pair<EQ_Handle, int> find_simplest_assignment(const Relation &R, Variable_ID v, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly = std::vector<std::pair<CG_outputRepr *, int> >()); +std::pair<EQ_Handle, int> find_simplest_assignment(const Relation &R, Variable_ID v, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly = std::vector<std::pair<CG_outputRepr *, int> >(), bool *has_global_inspector= NULL); std::pair<bool, GEQ_Handle> find_floor_definition(const Relation &R, Variable_ID v, std::set<Variable_ID> excluded_floor_vars = std::set<Variable_ID>()); +//Anand: 07/31/2013 -- Added the followinng temporary function needs cleanup +std::vector<std::pair<bool, GEQ_Handle> > find_floor_definition_temp(const Relation &R, Variable_ID v, std::set<Variable_ID> excluded_floor_vars = std::set<Variable_ID>()); std::pair<EQ_Handle, Variable_ID> find_simplest_stride(const Relation &R, Variable_ID v); Variable_ID replicate_floor_definition(const Relation &R, const Variable_ID floor_var, Relation &r, F_Exists *f_exists, F_And *f_root, std::map<Variable_ID, Variable_ID> &exists_mapping); @@ -34,12 +43,15 @@ CG_outputRepr *leaf_print_repr(BoolSet<> active, const std::map<int, Relation> & CG_outputRepr *guard_repr, const Relation &known, int indent, CG_outputBuilder *ocg, const std::vector<int> &remap, const std::vector<Relation> &xforms, const std::vector<CG_outputRepr *> &stmts, - const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly); -CG_outputRepr *loop_print_repr(const std::vector<CG_loop *> &loops, int start, int end, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > unin); +CG_outputRepr *loop_print_repr(BoolSet<> active,const std::vector<CG_loop *> &loops, int start, int end, const Relation &guard, CG_outputRepr *guard_repr, - int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, - const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly); + int indent, const std::vector<int> &remap, const std::vector<Relation> &xforms,CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > unin); +Relation checkAndRestoreIfProjectedByGlobal(const Relation &R1, const Relation &R2, Variable_ID v); +//Relation addInequalitiesToRelation( const Relation &R, std::vector<GEQ_Handle> &inequalities); +std::string print_to_iegen_string(Relation &R); } #endif diff --git a/lib/codegen/src/CG.cc b/lib/codegen/src/CG.cc index 42bd172..5d903c4 100644..100755 --- a/lib/codegen/src/CG.cc +++ b/lib/codegen/src/CG.cc @@ -1,4 +1,6 @@ + /***************************************************************************** + Copyright (C) 1994-2000 the Omega Project Team Copyright (C) 2005-2011 Chun Chen All Rights Reserved. @@ -19,7 +21,7 @@ 08/03/10 collect CG classes into one place, by Chun Chen 08/04/10 track dynamically substituted variables in printRepr, by chun 04/02/11 rewrite the CG node classes, by chun - *****************************************************************************/ +*****************************************************************************/ #include <typeinfo> #include <assert.h> @@ -34,1130 +36,1666 @@ #include <string.h> namespace omega { - -extern std::vector<std::vector<int> > smtNonSplitLevels; -extern std::vector<std::vector<std::string> > loopIdxNames; //per stmt -extern std::vector<std::pair<int, std::string> > syncs; - -extern int checkLoopLevel; -extern int stmtForLoopCheck; -extern int upperBoundForLevel; -extern int lowerBoundForLevel; -extern bool fillInBounds; - -//----------------------------------------------------------------------------- -// Class: CG_result -//----------------------------------------------------------------------------- - -CG_outputRepr *CG_result::printRepr(CG_outputBuilder *ocg, - const std::vector<CG_outputRepr *> &stmts) const { - return printRepr(1, ocg, stmts, - std::vector<std::pair<CG_outputRepr *, int> >(num_level(), - std::make_pair(static_cast<CG_outputRepr *>(NULL), 0))); -} - -std::string CG_result::printString() const { - CG_stringBuilder ocg; - std::vector<CG_outputRepr *> stmts(codegen_->xforms_.size()); - for (int i = 0; i < stmts.size(); i++) - stmts[i] = new CG_stringRepr("s" + to_string(i)); - CG_stringRepr *repr = static_cast<CG_stringRepr *>(printRepr(&ocg, stmts)); - for (int i = 0; i < stmts.size(); i++) - delete stmts[i]; - - if (repr != NULL) { - std::string s = repr->GetString(); - delete repr; - return s; - } else - return std::string(); -} - -int CG_result::num_level() const { - return codegen_->num_level(); -} - -//----------------------------------------------------------------------------- -// Class: CG_split -//----------------------------------------------------------------------------- - -CG_result *CG_split::recompute(const BoolSet<> &parent_active, - const Relation &known, const Relation &restriction) { - active_ &= parent_active; - if (active_.empty()) { - delete this; - return NULL; - } - - - int i = 0; - while (i < restrictions_.size()) { - Relation new_restriction = Intersection(copy(restrictions_[i]), - copy(restriction)); - - new_restriction.simplify(2, 4); - //new_restriction.simplify(); - clauses_[i] = clauses_[i]->recompute(active_, copy(known), - new_restriction); - if (clauses_[i] == NULL) { - restrictions_.erase(restrictions_.begin() + i); - clauses_.erase(clauses_.begin() + i); - } else - i++; - } - - - if (restrictions_.size() == 0) { - delete this; - return NULL; - } else - return this; -} - -int CG_split::populateDepth() { - int max_depth = 0; - for (int i = 0; i < clauses_.size(); i++) { - int t = clauses_[i]->populateDepth(); - if (t > max_depth) - max_depth = t; - } - return max_depth; -} - -std::pair<CG_result *, Relation> CG_split::liftOverhead(int depth, - bool propagate_up) { - for (int i = 0; i < clauses_.size();) { - std::pair<CG_result *, Relation> result = clauses_[i]->liftOverhead( - depth, propagate_up); - if (result.first == NULL) - clauses_.erase(clauses_.begin() + i); - else { - clauses_[i] = result.first; - if (!result.second.is_obvious_tautology()) - return std::make_pair(this, result.second); - i++; - } - - } - - if (clauses_.size() == 0) { - delete this; - return std::make_pair(static_cast<CG_result *>(NULL), - Relation::True(num_level())); - } else - return std::make_pair(this, Relation::True(num_level())); -} - -Relation CG_split::hoistGuard() { - std::vector<Relation> guards; - for (int i = 0; i < clauses_.size(); i++) - guards.push_back(clauses_[i]->hoistGuard()); - - return SimpleHull(guards, true, true); -} - -void CG_split::removeGuard(const Relation &guard) { - for (int i = 0; i < clauses_.size(); i++) - clauses_[i]->removeGuard(guard); -} - -std::vector<CG_result *> CG_split::findNextLevel() const { - std::vector<CG_result *> result; - for (int i = 0; i < clauses_.size(); i++) { - CG_split *splt = dynamic_cast<CG_split *>(clauses_[i]); - if (splt != NULL) { - std::vector<CG_result *> t = splt->findNextLevel(); - result.insert(result.end(), t.begin(), t.end()); - } else - result.push_back(clauses_[i]); - } - - return result; -} - -CG_outputRepr *CG_split::printRepr(int indent, CG_outputBuilder *ocg, - const std::vector<CG_outputRepr *> &stmts, - const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const { - CG_outputRepr *stmtList = NULL; - std::vector<CG_result *> next_level = findNextLevel(); - - std::vector<CG_loop *> cur_loops; - for (int i = 0; i < next_level.size(); i++) { - CG_loop *lp = dynamic_cast<CG_loop *>(next_level[i]); - if (lp != NULL) { - cur_loops.push_back(lp); - } else { - stmtList = ocg->StmtListAppend(stmtList, - loop_print_repr(cur_loops, 0, cur_loops.size(), - Relation::True(num_level()), NULL, indent, ocg, - stmts, assigned_on_the_fly)); - stmtList = ocg->StmtListAppend(stmtList, - next_level[i]->printRepr(indent, ocg, stmts, - assigned_on_the_fly)); - cur_loops.clear(); - } - } - - stmtList = ocg->StmtListAppend(stmtList, - loop_print_repr(cur_loops, 0, cur_loops.size(), - Relation::True(num_level()), NULL, indent, ocg, stmts, - assigned_on_the_fly)); - return stmtList; -} - -CG_result *CG_split::clone() const { - std::vector<CG_result *> clauses(clauses_.size()); - for (int i = 0; i < clauses_.size(); i++) - clauses[i] = clauses_[i]->clone(); - return new CG_split(codegen_, active_, restrictions_, clauses); -} - -void CG_split::dump(int indent) const { - std::string prefix; - for (int i = 0; i < indent; i++) - prefix += " "; - std::cout << prefix << "SPLIT: " << active_ << std::endl; - for (int i = 0; i < restrictions_.size(); i++) { - std::cout << prefix << "restriction: "; - const_cast<CG_split *>(this)->restrictions_[i].print(); - clauses_[i]->dump(indent + 1); - } - -} - -//----------------------------------------------------------------------------- -// Class: CG_loop -//----------------------------------------------------------------------------- - -CG_result *CG_loop::recompute(const BoolSet<> &parent_active, - const Relation &known, const Relation &restriction) { - known_ = copy(known); - restriction_ = copy(restriction); - active_ &= parent_active; - - std::vector<Relation> Rs; - for (BoolSet<>::iterator i = active_.begin(); i != active_.end(); i++) { - Relation r = Intersection(copy(restriction), - copy(codegen_->projected_IS_[level_ - 1][*i])); - - //r.simplify(2, 4); - r.simplify(); - if (!r.is_upper_bound_satisfiable()) { - active_.unset(*i); - continue; - } - Rs.push_back(copy(r)); - } - - if (active_.empty()) { - delete this; - return NULL; - } - - Relation hull = SimpleHull(Rs, true, true); - - //hull.simplify(2,4); - - // check if actual loop is needed - std::pair<EQ_Handle, int> result = find_simplest_assignment(hull, - hull.set_var(level_)); - if (result.second < INT_MAX) { - needLoop_ = false; - - bounds_ = Relation(hull.n_set()); - F_Exists *f_exists = bounds_.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 (Constr_Vars_Iter cvi(result.first); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - switch (v->kind()) { - case Input_Var: - h.update_coef(bounds_.input_var(v->get_position()), - cvi.curr_coef()); - break; - case Wildcard_Var: { - Variable_ID v2 = replicate_floor_definition(hull, v, bounds_, - 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 = bounds_.get_local(g); - else - v2 = bounds_.get_local(g, v->function_of()); - h.update_coef(v2, cvi.curr_coef()); - break; - } - default: - assert(false); - } - } - h.update_const(result.first.get_const()); - bounds_.simplify(); - } - // loop iterates more than once, extract bounds now - else { - needLoop_ = true; - - bounds_ = Relation(hull.n_set()); - F_Exists *f_exists = bounds_.add_and()->add_exists(); - F_And *f_root = f_exists->add_and(); - std::map<Variable_ID, Variable_ID> exists_mapping; - - Relation b = Gist(copy(hull), copy(known), 1); - bool has_unresolved_bound = false; - - std::set<Variable_ID> excluded_floor_vars; - excluded_floor_vars.insert(b.set_var(level_)); - for (GEQ_Iterator e(b.single_conjunct()->GEQs()); e; e++) - if ((*e).get_coef(b.set_var(level_)) != 0) { - bool is_bound = true; - for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) { - std::pair<bool, GEQ_Handle> result = find_floor_definition( - b, cvi.curr_var(), excluded_floor_vars); - if (!result.first) { - is_bound = false; - has_unresolved_bound = true; - break; - } - } - - if (!is_bound) - continue; - - GEQ_Handle h = f_root->add_GEQ(); - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - switch (v->kind()) { - case Input_Var: - h.update_coef(bounds_.input_var(v->get_position()), - cvi.curr_coef()); - break; - case Wildcard_Var: { - Variable_ID v2 = replicate_floor_definition(b, v, - bounds_, 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 = bounds_.get_local(g); - else - v2 = bounds_.get_local(g, v->function_of()); - h.update_coef(v2, cvi.curr_coef()); - break; - } - default: - assert(false); - } - } - h.update_const((*e).get_const()); - } - - if (has_unresolved_bound) { - b = Approximate(b); - b.simplify(2, 4); - //Simplification of Hull - hull = Approximate(hull); - hull.simplify(2, 4); - //end : Anand - for (GEQ_Iterator e(b.single_conjunct()->GEQs()); e; e++) - if ((*e).get_coef(b.set_var(level_)) != 0) - f_root->add_GEQ(*e); - } - bounds_.simplify(); - hull.simplify(2,4); - // Since current SimpleHull does not support max() upper bound or min() lower bound, - // we have to forcefully split the loop when hull approximation does not return any bound. - bool has_lb = false; - bool has_ub = false; - for (GEQ_Iterator e = bounds_.single_conjunct()->GEQs(); e; e++) { - if ((*e).get_coef(bounds_.set_var(level_)) > 0) - has_lb = true; - else if ((*e).get_coef(bounds_.set_var(level_)) < 0) - has_ub = true; - if (has_lb && has_ub) - break; - } - - if (!has_lb) { - for (int i = 0; i < Rs.size(); i++) { - Relation r = Approximate(copy(Rs[i])); - r.simplify(2, 4); - for (GEQ_Iterator e = r.single_conjunct()->GEQs(); e; e++) - if ((*e).get_coef(r.input_var(level_)) > 0) { - Relation r2 = Relation::True(num_level()); - r2.and_with_GEQ(*e); - r2.simplify(); - std::vector<Relation> restrictions(2); - restrictions[0] = Complement(copy(r2)); - restrictions[0].simplify(); - restrictions[1] = r2; - std::vector<CG_result *> clauses(2); - clauses[0] = this; - clauses[1] = this->clone(); - CG_result *cgr = new CG_split(codegen_, active_, - restrictions, clauses); - cgr = cgr->recompute(active_, copy(known), - copy(restriction)); - return cgr; - } - } - for (int i = 0; i < Rs.size(); i++) { - Relation r = Approximate(copy(Rs[i])); - r.simplify(2, 4); - for (EQ_Iterator e = r.single_conjunct()->EQs(); e; e++) - if ((*e).get_coef(r.input_var(level_)) != 0) { - Relation r2 = Relation::True(num_level()); - r2.and_with_GEQ(*e); - r2.simplify(); - std::vector<Relation> restrictions(2); - if ((*e).get_coef(r.input_var(level_)) > 0) { - restrictions[0] = Complement(copy(r2)); - restrictions[0].simplify(); - restrictions[1] = r2; - } else { - restrictions[0] = r2; - restrictions[1] = Complement(copy(r2)); - restrictions[1].simplify(); - } - std::vector<CG_result *> clauses(2); - clauses[0] = this; - clauses[1] = this->clone(); - CG_result *cgr = new CG_split(codegen_, active_, - restrictions, clauses); - cgr = cgr->recompute(active_, copy(known), - copy(restriction)); - return cgr; - } - } - } else if (!has_ub) { - for (int i = 0; i < Rs.size(); i++) { - Relation r = Approximate(copy(Rs[i])); - r.simplify(2, 4); - for (GEQ_Iterator e = r.single_conjunct()->GEQs(); e; e++) - if ((*e).get_coef(r.input_var(level_)) < 0) { - Relation r2 = Relation::True(num_level()); - r2.and_with_GEQ(*e); - r2.simplify(); - std::vector<Relation> restrictions(2); - restrictions[1] = Complement(copy(r2)); - restrictions[1].simplify(); - restrictions[0] = r2; - std::vector<CG_result *> clauses(2); - clauses[0] = this; - clauses[1] = this->clone(); - CG_result *cgr = new CG_split(codegen_, active_, - restrictions, clauses); - cgr = cgr->recompute(active_, copy(known), - copy(restriction)); - return cgr; - } - } - for (int i = 0; i < Rs.size(); i++) { - Relation r = Approximate(copy(Rs[i])); - r.simplify(2, 4); - for (EQ_Iterator e = r.single_conjunct()->EQs(); e; e++) - if ((*e).get_coef(r.input_var(level_)) != 0) { - Relation r2 = Relation::True(num_level()); - r2.and_with_GEQ(*e); - r2.simplify(); - std::vector<Relation> restrictions(2); - if ((*e).get_coef(r.input_var(level_)) > 0) { - restrictions[0] = Complement(copy(r2)); - restrictions[0].simplify(); - restrictions[1] = r2; - } else { - restrictions[0] = r2; - restrictions[1] = Complement(copy(r2)); - restrictions[1].simplify(); - } - std::vector<CG_result *> clauses(2); - clauses[0] = this; - clauses[1] = this->clone(); - CG_result *cgr = new CG_split(codegen_, active_, - restrictions, clauses); - cgr = cgr->recompute(active_, copy(known), - copy(restriction)); - return cgr; - } - } - } - - if (!has_lb && !has_ub) - throw codegen_error( - "can't find any bound at loop level " + to_string(level_)); - else if (!has_lb) - throw codegen_error( - "can't find lower bound at loop level " - + to_string(level_)); - else if (!has_ub) - throw codegen_error( - "can't find upper bound at loop level " - + to_string(level_)); - } - bounds_.copy_names(hull); - bounds_.setup_names(); - - // additional guard/stride condition extraction - if (needLoop_) { - Relation cur_known = Intersection(copy(bounds_), copy(known_)); - cur_known.simplify(); - hull = Gist(hull, copy(cur_known), 1); - - std::pair<EQ_Handle, Variable_ID> result = find_simplest_stride(hull, - hull.set_var(level_)); - if (result.second != NULL) - if (abs(result.first.get_coef(hull.set_var(level_))) == 1) { - F_Exists *f_exists = bounds_.and_with_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 (Constr_Vars_Iter cvi(result.first); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - switch (v->kind()) { - case Input_Var: - h.update_coef(bounds_.input_var(v->get_position()), - cvi.curr_coef()); - break; - case Wildcard_Var: { - Variable_ID v2; - if (v == result.second) - v2 = f_exists->declare(); - else - v2 = replicate_floor_definition(hull, v, bounds_, - 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 = bounds_.get_local(g); - else - v2 = bounds_.get_local(g, v->function_of()); - h.update_coef(v2, cvi.curr_coef()); - break; - } - default: - assert(false); - } - } - h.update_const(result.first.get_const()); - } else { - // since gist is not powerful enough on modular constraints for now, - // make an educated guess - coef_t stride = abs(result.first.get_coef(result.second)) - / gcd(abs(result.first.get_coef(result.second)), - abs( - result.first.get_coef( - hull.set_var(level_)))); - - Relation r1(hull.n_inp()); - F_Exists *f_exists = r1.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 (Constr_Vars_Iter cvi(result.first); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - switch (v->kind()) { - case Input_Var: - h.update_coef(r1.input_var(v->get_position()), - cvi.curr_coef()); - break; - case Wildcard_Var: { - Variable_ID v2; - if (v == result.second) - v2 = f_exists->declare(); - else - v2 = replicate_floor_definition(hull, v, r1, - 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 = r1.get_local(g); - else - v2 = r1.get_local(g, v->function_of()); - h.update_coef(v2, cvi.curr_coef()); - break; - } - default: - assert(false); - } - } - h.update_const(result.first.get_const()); - r1.simplify(); - - bool guess_success = false; - for (GEQ_Iterator e(bounds_.single_conjunct()->GEQs()); e; e++) - if ((*e).get_coef(bounds_.set_var(level_)) == 1) { - Relation r2(hull.n_inp()); - F_Exists *f_exists = r2.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(); - h.update_coef(f_exists->declare(), stride); - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - switch (v->kind()) { - case Input_Var: - h.update_coef(r2.input_var(v->get_position()), - cvi.curr_coef()); - break; - case Wildcard_Var: { - Variable_ID v2 = replicate_floor_definition( - hull, v, r2, 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 = r2.get_local(g); - else - v2 = r2.get_local(g, v->function_of()); - h.update_coef(v2, cvi.curr_coef()); - break; - } - default: - assert(false); - } - } - h.update_const((*e).get_const()); - r2.simplify(); - - if (Gist(copy(r1), - Intersection(copy(cur_known), copy(r2)), 1).is_obvious_tautology() - && Gist(copy(r2), - Intersection(copy(cur_known), copy(r1)), - 1).is_obvious_tautology()) { - bounds_ = Intersection(bounds_, r2); - bounds_.simplify(); - guess_success = true; - break; - } - } - - // this is really a stride with non-unit coefficient for this loop variable - if (!guess_success) { - // TODO: for stride ax = b mod n it might be beneficial to - // generate modular linear equation solver code for - // runtime to get the starting position in printRepr, - // and stride would be n/gcd(|a|,n), thus this stride - // can be put into bounds_ too. - } - - } - - hull = Project(hull, hull.set_var(level_)); - hull.simplify(2, 4); - guard_ = Gist(hull, Intersection(copy(bounds_), copy(known_)), 1); - } - // don't generate guard for non-actual loop, postpone it. otherwise - // redundant if-conditions might be generated since for-loop semantics - // includes implicit comparison checking. -- by chun 09/14/10 - else - guard_ = Relation::True(num_level()); - guard_.copy_names(bounds_); - guard_.setup_names(); - - //guard_.simplify(); - // recursively down the AST - Relation new_known = Intersection(copy(known), - Intersection(copy(bounds_), copy(guard_))); - new_known.simplify(2, 4); - Relation new_restriction = Intersection(copy(restriction), - Intersection(copy(bounds_), copy(guard_))); - new_restriction.simplify(2, 4); - body_ = body_->recompute(active_, new_known, new_restriction); - if (body_ == NULL) { - delete this; - return NULL; - } else - return this; -} - -int CG_loop::populateDepth() { - int depth = body_->populateDepth(); - if (needLoop_) - depth_ = depth + 1; - else - depth_ = depth; - return depth_; -} - -std::pair<CG_result *, Relation> CG_loop::liftOverhead(int depth, - bool propagate_up) { - if (depth_ > depth) { - assert(propagate_up == false); - std::pair<CG_result *, Relation> result = body_->liftOverhead(depth, - false); - body_ = result.first; - return std::make_pair(this, Relation::True(num_level())); - } else { // (depth_ <= depth) - if (propagate_up) { - Relation r = pick_one_guard(guard_, level_); - if (!r.is_obvious_tautology()) - return std::make_pair(this, r); - } - - std::pair<CG_result *, Relation> result; - if (propagate_up || needLoop_) - result = body_->liftOverhead(depth, true); - else - result = body_->liftOverhead(depth, false); - body_ = result.first; - if (result.second.is_obvious_tautology()) - return std::make_pair(this, result.second); - - // loop is an assignment, replace this loop variable in overhead condition - if (!needLoop_) { - result.second = Intersection(result.second, copy(bounds_)); - result.second = Project(result.second, - result.second.set_var(level_)); - result.second.simplify(2, 4); - } - - - int max_level = 0; - bool has_wildcard = false; - bool direction = true; - for (EQ_Iterator e(result.second.single_conjunct()->EQs()); e; e++) - if ((*e).has_wildcards()) { - if (has_wildcard) - assert(false); - else - has_wildcard = true; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - if (cvi.curr_var()->kind() == Input_Var - && cvi.curr_var()->get_position() > max_level) - max_level = cvi.curr_var()->get_position(); - } else - assert(false); - - if (!has_wildcard) { - int num_simple_geq = 0; - for (GEQ_Iterator e(result.second.single_conjunct()->GEQs()); e; - e++) - if (!(*e).has_wildcards()) { - num_simple_geq++; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - if (cvi.curr_var()->kind() == Input_Var - && cvi.curr_var()->get_position() > max_level) { - max_level = cvi.curr_var()->get_position(); - direction = (cvi.curr_coef() < 0) ? true : false; - } - } else { - has_wildcard = true; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - if (cvi.curr_var()->kind() == Input_Var - && cvi.curr_var()->get_position() > max_level) { - max_level = cvi.curr_var()->get_position(); - } - } - assert( - (has_wildcard && num_simple_geq == 0) || (!has_wildcard && num_simple_geq == 1)); - } - - // check if this is the top loop level for splitting for this overhead - if (!propagate_up || (has_wildcard && max_level == level_ - 1) - || (!has_wildcard && max_level == level_)) { - std::vector<Relation> restrictions(2); - std::vector<CG_result *> clauses(2); - int saved_num_level = num_level(); - if (has_wildcard || direction) { - restrictions[1] = Complement(copy(result.second)); - restrictions[1].simplify(); - clauses[1] = this->clone(); - restrictions[0] = result.second; - clauses[0] = this; - } else { - restrictions[0] = Complement(copy(result.second)); - restrictions[0].simplify(); - clauses[0] = this->clone(); - restrictions[1] = result.second; - clauses[1] = this; - } - CG_result *cgr = new CG_split(codegen_, active_, restrictions, - clauses); - CG_result *new_cgr = cgr->recompute(active_, copy(known_), - copy(restriction_)); - new_cgr->populateDepth(); - assert(new_cgr==cgr); - if (static_cast<CG_split *>(new_cgr)->clauses_.size() == 1) - // infinite recursion detected, bail out - return std::make_pair(new_cgr, Relation::True(saved_num_level)); - else - return cgr->liftOverhead(depth, propagate_up); - } else - return std::make_pair(this, result.second); - } -} - -Relation CG_loop::hoistGuard() { - - Relation r = body_->hoistGuard(); - - // TODO: should bookkeep catched contraints in loop output as enforced and check if anything missing - // if (!Gist(copy(b), copy(enforced)).is_obvious_tautology()) { - // fprintf(stderr, "need to generate extra guard inside the loop\n"); - // } - - if (!needLoop_) - r = Intersection(r, copy(bounds_)); - r = Project(r, r.set_var(level_)); - r = Gist(r, copy(known_), 1); - - Relation eliminate_existentials_r; - Relation eliminate_existentials_known; - - eliminate_existentials_r = copy(r); - if (!r.is_obvious_tautology()) { - eliminate_existentials_r = Approximate(copy(r)); - eliminate_existentials_r.simplify(2,4); - eliminate_existentials_known = Approximate(copy(known_)); - eliminate_existentials_known.simplify(2,4); - - eliminate_existentials_r = Gist( eliminate_existentials_r, eliminate_existentials_known, 1); - } + + extern std::vector<std::vector<int> > smtNonSplitLevels; + extern std::vector<std::vector<std::string> > loopIdxNames; //per stmt + extern std::vector<std::pair<int, std::string> > syncs; + + extern int checkLoopLevel; + extern int stmtForLoopCheck; + extern int upperBoundForLevel; + extern int lowerBoundForLevel; + extern bool fillInBounds; + + //----------------------------------------------------------------------------- + // Class: CG_result + //----------------------------------------------------------------------------- + + CG_outputRepr *CG_result::printRepr(CG_outputBuilder *ocg, + const std::vector<CG_outputRepr *> &stmts, + std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > uninterpreted_symbols, + bool printString) const { + fprintf(stderr, "\nCG_result::printRepr(ocg, stmts) \n"); + //Anand: making a tweak to allocate twice the original number of dynamically allocated variables + //for use with Uninterpreted function symbols + + //Anand: adding support for Replacing substituted variables within + //Uninterpreted function symbols or global variables with arity > 0 here + //--begin + + // check for an error that happened once + int num_unin = uninterpreted_symbols.size(); + int num_active = active_.size(); + if (num_unin < num_active) { + fprintf(stderr, "CG.cc CG_result::printRepr(), not enough uninterpreted symbols (%d) for active statements (5d)\n", num_unin, num_active); + exit(-1); + } + + std::vector<std::pair<CG_outputRepr *, int> > aotf = std::vector< + std::pair<CG_outputRepr *, int> >(2 * num_level(), + std::make_pair(static_cast<CG_outputRepr *>(NULL), 0)); + +#define DYINGHERE +#ifdef DYINGHERE + int num_levels = num_level(); + + for (int s = 0; s < active_.size(); s++) { + fprintf(stderr, "\ns %d\n", s); + std::vector<std::string> loop_vars; + if (active_.get(s)) { + + Relation mapping = Inverse( + copy((codegen_->xforms_[codegen_->remap_[s]]))); + + mapping.simplify(); + mapping.setup_names(); + + for (int i = 1; i <= mapping.n_out(); i++) + loop_vars.push_back(mapping.output_var(i)->name()); + + std::vector<CG_outputRepr *> subs_; + for (int i = 1; i <= mapping.n_out(); i++) { + Relation mapping1(mapping.n_out(), 1); + F_And *f_root = mapping1.add_and(); + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping1.output_var(1), 1); + h.update_coef(mapping1.input_var(i), -1); + Relation r = Composition(mapping1, copy(mapping)); + r.simplify(); - - if (!eliminate_existentials_r.is_obvious_tautology()) { - // if (!r.is_obvious_tautology()) { - body_->removeGuard(r); - guard_ = Intersection(guard_, copy(r)); - guard_.simplify(); - } - - return guard_; - - // return ifList; - // } - - -} - -void CG_loop::removeGuard(const Relation &guard) { - known_ = Intersection(known_, copy(guard)); - known_.simplify(); - - guard_ = Gist(guard_, copy(known_), 1); - guard_.copy_names(known_); - guard_.setup_names(); -} - -CG_outputRepr *CG_loop::printRepr(int indent, CG_outputBuilder *ocg, - const std::vector<CG_outputRepr *> &stmts, - const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const { - return printRepr(true, indent, ocg, stmts, assigned_on_the_fly); -} - -CG_outputRepr *CG_loop::printRepr(bool do_print_guard, int indent, - CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, - const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const { - CG_outputRepr *guardRepr; - if (do_print_guard) - guardRepr = output_guard(ocg, guard_, assigned_on_the_fly); - else - guardRepr = NULL; - - Relation cur_known = Intersection(copy(known_), copy(guard_)); - cur_known.simplify(); - if (needLoop_) { - - if (checkLoopLevel) - if (level_ == checkLoopLevel) - if (active_.get(stmtForLoopCheck)) - fillInBounds = true; - - CG_outputRepr *ctrlRepr = output_loop(ocg, bounds_, level_, cur_known, - assigned_on_the_fly); - - fillInBounds = false; - - CG_outputRepr *bodyRepr = body_->printRepr( - (guardRepr == NULL) ? indent + 1 : indent + 2, ocg, stmts, - assigned_on_the_fly); - CG_outputRepr * loopRepr; - - if (guardRepr == NULL) - loopRepr = ocg->CreateLoop(indent, ctrlRepr, bodyRepr); - else - loopRepr = ocg->CreateLoop(indent + 1, ctrlRepr, bodyRepr); - - if (!smtNonSplitLevels.empty()) { - bool blockLoop = false; - bool threadLoop = false; - bool sync = false; - int firstActiveStmt = -1; - for (int s = 0; s < active_.size(); s++) { - if (active_.get(s)) { - if (firstActiveStmt < 0) - firstActiveStmt = s; - //We assume smtNonSplitLevels is only used to mark the first of - //the block or thread loops to be reduced in CUDA-CHiLL. Here we - //place some comments to help with final code generation. - //int idx = smtNonSplitLevels[s].index(level_); - - if (s < smtNonSplitLevels.size()) { - if (smtNonSplitLevels[s].size() > 0) - if (smtNonSplitLevels[s][0] == level_) { - blockLoop = true; - } - //Assume every stmt marked with a thread loop index also has a block loop idx - if (smtNonSplitLevels[s].size() > 1) - if (smtNonSplitLevels[s][1] == level_) { - threadLoop = true; - } - } - } - } - if (blockLoop && threadLoop) { - fprintf(stderr, - "Warning, have %d level more than once in smtNonSplitLevels\n", - level_); - threadLoop = false; - } - std::string preferredIdx; - if (loopIdxNames.size() - && (level_ / 2) - 1 < loopIdxNames[firstActiveStmt].size()) - preferredIdx = loopIdxNames[firstActiveStmt][(level_ / 2) - 1]; - for (int s = 0; s < active_.size(); s++) { - if (active_.get(s)) { - for (int i = 0; i < syncs.size(); i++) { - if (syncs[i].first == s - && strcmp(syncs[i].second.c_str(), - preferredIdx.c_str()) == 0) { - sync = true; - //printf("FOUND SYNC\n"); - } - - } - } - - } - if (threadLoop || blockLoop || preferredIdx.length() != 0) { - char buf[1024]; - std::string loop; - if (blockLoop) - loop = "blockLoop "; - if (threadLoop) - loop = "threadLoop "; - if (preferredIdx.length() != 0 && sync) { - sprintf(buf, "~cuda~ %spreferredIdx: %s sync", loop.c_str(), - preferredIdx.c_str()); - } else if (preferredIdx.length() != 0) { - sprintf(buf, "~cuda~ %spreferredIdx: %s", loop.c_str(), - preferredIdx.c_str()); - } else { - sprintf(buf, "~cuda~ %s", loop.c_str()); - } - - - loopRepr = ocg->CreateAttribute(loopRepr, buf); - } - - } - if (guardRepr == NULL) - return loopRepr; - else - return ocg->CreateIf(indent, guardRepr, loopRepr, NULL); - } else { - std::pair<CG_outputRepr *, std::pair<CG_outputRepr *, int> > result = - output_assignment(ocg, bounds_, level_, cur_known, - assigned_on_the_fly); - guardRepr = ocg->CreateAnd(guardRepr, result.first); - - if (result.second.second < CodeGen::var_substitution_threshold) { - std::vector<std::pair<CG_outputRepr *, int> > atof = - assigned_on_the_fly; - atof[level_ - 1] = result.second; - CG_outputRepr *bodyRepr = body_->printRepr( - (guardRepr == NULL) ? indent : indent + 1, ocg, stmts, - atof); - delete atof[level_ - 1].first; - if (guardRepr == NULL) - return bodyRepr; - else - return ocg->CreateIf(indent, guardRepr, bodyRepr, NULL); - } else { - CG_outputRepr *assignRepr = ocg->CreateAssignment( - (guardRepr == NULL) ? indent : indent + 1, - output_ident(ocg, bounds_, - const_cast<CG_loop *>(this)->bounds_.set_var( - level_), assigned_on_the_fly), - result.second.first); - CG_outputRepr *bodyRepr = body_->printRepr( - (guardRepr == NULL) ? indent : indent + 1, ocg, stmts, - assigned_on_the_fly); - if (guardRepr == NULL) - return ocg->StmtListAppend(assignRepr, bodyRepr); - else - return ocg->CreateIf(indent, guardRepr, - ocg->StmtListAppend(assignRepr, bodyRepr), NULL); - } - - } -} - -CG_result *CG_loop::clone() const { - return new CG_loop(codegen_, active_, level_, body_->clone()); -} - -void CG_loop::dump(int indent) const { - std::string prefix; - for (int i = 0; i < indent; i++) - prefix += " "; - std::cout << prefix << "LOOP (level " << level_ << "): " << active_ - << std::endl; - std::cout << prefix << "known: "; - const_cast<CG_loop *>(this)->known_.print(); - std::cout << prefix << "restriction: "; - const_cast<CG_loop *>(this)->restriction_.print(); - std::cout << prefix << "bounds: "; - const_cast<CG_loop *>(this)->bounds_.print(); - std::cout << prefix << "guard: "; - const_cast<CG_loop *>(this)->guard_.print(); - body_->dump(indent + 1); -} - -//----------------------------------------------------------------------------- -// Class: CG_leaf -//----------------------------------------------------------------------------- - -CG_result* CG_leaf::recompute(const BoolSet<> &parent_active, - const Relation &known, const Relation &restriction) { - active_ &= parent_active; - known_ = copy(known); - - guards_.clear(); - for (BoolSet<>::iterator i = active_.begin(); i != active_.end(); i++) { - Relation r = Intersection( - copy(codegen_->projected_IS_[num_level() - 1][*i]), - copy(restriction)); - r.simplify(2, 4); - if (!r.is_upper_bound_satisfiable()) - active_.unset(*i); - else { - r = Gist(r, copy(known), 1); - if (!r.is_obvious_tautology()) { - guards_[*i] = r; - guards_[*i].copy_names(known); - guards_[*i].setup_names(); - } - } - } - - - if (active_.empty()) { - delete this; - return NULL; - } else - return this; -} - -std::pair<CG_result *, Relation> CG_leaf::liftOverhead(int depth, bool) { - if (depth == 0) - return std::make_pair(this, Relation::True(num_level())); - - for (std::map<int, Relation>::iterator i = guards_.begin(); - i != guards_.end(); i++) { - Relation r = pick_one_guard(i->second); - if (!r.is_obvious_tautology()) { - bool has_wildcard = false; - int max_level = 0; - for (EQ_Iterator e(r.single_conjunct()->EQs()); e; e++) { - if ((*e).has_wildcards()) - has_wildcard = true; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - if (cvi.curr_var()->kind() == Input_Var - && cvi.curr_var()->get_position() > max_level) - max_level = cvi.curr_var()->get_position(); - } - for (GEQ_Iterator e(r.single_conjunct()->GEQs()); e; e++) { - if ((*e).has_wildcards()) - has_wildcard = true; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - if (cvi.curr_var()->kind() == Input_Var - && cvi.curr_var()->get_position() > max_level) - max_level = cvi.curr_var()->get_position(); - } - - if (!(has_wildcard && max_level == codegen_->num_level())) - return std::make_pair(this, r); - } - } - - return std::make_pair(this, Relation::True(num_level())); -} - -Relation CG_leaf::hoistGuard() { - std::vector<Relation> guards; - for (BoolSet<>::iterator i = active_.begin(); i != active_.end(); i++) { - std::map<int, Relation>::iterator j = guards_.find(*i); - if (j == guards_.end()) { - Relation r = Relation::True(num_level()); - r.copy_names(known_); - r.setup_names(); - return r; - } else { - guards.push_back(j->second); - } - } - - return SimpleHull(guards, true, true); -} - -void CG_leaf::removeGuard(const Relation &guard) { - known_ = Intersection(known_, copy(guard)); - known_.simplify(); - - std::map<int, Relation>::iterator i = guards_.begin(); - while (i != guards_.end()) { - i->second = Gist(i->second, copy(known_), 1); - if (i->second.is_obvious_tautology()) - guards_.erase(i++); - else - ++i; - } -} - -CG_outputRepr *CG_leaf::printRepr(int indent, CG_outputBuilder *ocg, - const std::vector<CG_outputRepr *> &stmts, - const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) const { - return leaf_print_repr(active_, guards_, NULL, known_, indent, ocg, - codegen_->remap_, codegen_->xforms_, stmts, assigned_on_the_fly); -} - -CG_result *CG_leaf::clone() const { - return new CG_leaf(codegen_, active_); -} - -void CG_leaf::dump(int indent) const { - std::string prefix; - for (int i = 0; i < indent; i++) - prefix += " "; - std::cout << prefix << "LEAF: " << active_ << std::endl; - std::cout << prefix << "known: "; - const_cast<CG_leaf *>(this)->known_.print(); - for (std::map<int, Relation>::const_iterator i = guards_.begin(); - i != guards_.end(); i++) { - std::cout << prefix << "guard #" << i->first << ":"; - const_cast<Relation &>(i->second).print(); - } -} - + //Relation r = copy(mapping); + + Variable_ID v = r.output_var(1); + loop_vars.push_back(mapping.output_var(i)->name()); + + std::pair<EQ_Handle, int> result = find_simplest_assignment(r, + v, aotf); + + std::string hand = result.first.print_to_string(); + //fprintf(stderr, "result: %s, %d\n", hand.c_str(), result.second); + if (result.second < INT_MAX) { + + CG_outputRepr *subs = output_substitution_repr(ocg, + result.first, + v, + true, + r, + aotf, + uninterpreted_symbols[s]); + + subs_.push_back(subs->clone()); + + aotf[num_levels + i - 1] = std::make_pair(subs, 999); + + } else { + CG_outputRepr* repr = NULL; + + aotf[num_levels + i - 1] = std::make_pair(repr, 999); + } + } + if(!printString) + for (std::map<std::string, std::vector<CG_outputRepr *> >::iterator it = + uninterpreted_symbols[s].begin(); + it != uninterpreted_symbols[s].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 *> subs2; + for (int l = 0; l < subs_.size(); l++) { + + subs2.push_back(subs_[l]->clone()); + } + CG_outputRepr * temp = + ocg->CreateSubstitutedStmt(0, reprs_[k]->clone(), + loop_vars, subs2, false); + + if (temp != NULL) + reprs_2.push_back(temp); + // reprs_2.push_back(subs_[k]->clone()); + + } + if(reprs_2.size() > 0) + it->second = reprs_2; + } + + //break; + } + } + +//--end + +#endif + + fprintf(stderr, "\n\n\n\nprintRepr recursing ??? return printRepr( ... )\n"); + return printRepr(1, ocg, stmts, aotf, uninterpreted_symbols, printString); + } + + + + std::string CG_result::printString( + std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > uninterpreted_symbols) const { + + fprintf(stderr, "CG.cc line 164, CG_result::printString()\n"); + CG_stringBuilder ocg; + std::vector<CG_outputRepr *> stmts(codegen_->xforms_.size()); + + fprintf(stderr, "stmts.size() %d\n", stmts.size()); + for (int i = 0; i < stmts.size(); i++) + stmts[i] = new CG_stringRepr("s" + to_string(i)); + + CG_stringRepr *repr = static_cast<CG_stringRepr *>(printRepr(&ocg, + stmts, + uninterpreted_symbols, + true)); + + for (int i = 0; i < stmts.size(); i++) + delete stmts[i]; + + if (repr != NULL) { + std::string s = repr->GetString(); + //fprintf(stderr, "\nCG.cc L197 repr->GetString() = '%s'\n\n\n", s.c_str()); + delete repr; + return s; + } else + return std::string(); + } + + int CG_result::num_level() const { + return codegen_->num_level(); + } + + //----------------------------------------------------------------------------- + // Class: CG_split + //----------------------------------------------------------------------------- + + CG_result *CG_split::recompute(const BoolSet<> &parent_active, + const Relation &known, const Relation &restriction) { + active_ &= parent_active; + if (active_.empty()) { + delete this; + return NULL; + } + + + int i = 0; + while (i < restrictions_.size()) { + Relation new_restriction = Intersection(copy(restrictions_[i]), + copy(restriction)); + + new_restriction.simplify(2, 4); + //new_restriction.simplify(); + clauses_[i] = clauses_[i]->recompute(active_, copy(known), + new_restriction); + if (clauses_[i] == NULL) { + restrictions_.erase(restrictions_.begin() + i); + clauses_.erase(clauses_.begin() + i); + } else + i++; + } + + + if (restrictions_.size() == 0) { + delete this; + return NULL; + } else + return this; + } + + int CG_split::populateDepth() { + int max_depth = 0; + for (int i = 0; i < clauses_.size(); i++) { + int t = clauses_[i]->populateDepth(); + if (t > max_depth) + max_depth = t; + } + return max_depth; + } + + std::pair<CG_result *, Relation> CG_split::liftOverhead(int depth, + bool propagate_up) { + for (int i = 0; i < clauses_.size();) { + std::pair<CG_result *, Relation> result = clauses_[i]->liftOverhead( + depth, propagate_up); + if (result.first == NULL) + clauses_.erase(clauses_.begin() + i); + else { + clauses_[i] = result.first; + if (!result.second.is_obvious_tautology()) + return std::make_pair(this, result.second); + i++; + } + + } + + if (clauses_.size() == 0) { + delete this; + return std::make_pair(static_cast<CG_result *>(NULL), + Relation::True(num_level())); + } else + return std::make_pair(this, Relation::True(num_level())); + } + + Relation CG_split::hoistGuard() { + std::vector<Relation> guards; + for (int i = 0; i < clauses_.size(); i++) + guards.push_back(clauses_[i]->hoistGuard()); + + return SimpleHull(guards, true, true); + } + + void CG_split::removeGuard(const Relation &guard) { + for (int i = 0; i < clauses_.size(); i++) + clauses_[i]->removeGuard(guard); + } + + std::vector<CG_result *> CG_split::findNextLevel() const { + std::vector<CG_result *> result; + for (int i = 0; i < clauses_.size(); i++) { + CG_split *splt = dynamic_cast<CG_split *>(clauses_[i]); + if (splt != NULL) { + std::vector<CG_result *> t = splt->findNextLevel(); + result.insert(result.end(), t.begin(), t.end()); + } else + result.push_back(clauses_[i]); + } + + return result; + } + + + + + CG_outputRepr *CG_split::printRepr(int indent, + CG_outputBuilder *ocg, + const std::vector<CG_outputRepr *> &stmts, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > unin, + bool printString) const { + + fprintf(stderr, "CG_split::printRepr()\n"); + int numfly = assigned_on_the_fly.size(); + //fprintf(stderr, "assigned on the fly %d\n", numfly ); + //for (int i=0; i<numfly; i++) { + // fprintf(stderr, "i %d\n", i); + // std::pair<CG_outputRepr *, int>p = assigned_on_the_fly[i]; + // CG_outputRepr *tr = NULL; + // if (p.first != NULL) tr = p.first->clone(); + // int val = p.second; + // fprintf(stderr, "0x%x %d\n", tr, val); + //} + + CG_outputRepr *stmtList = NULL; + std::vector<CG_result *> next_level = findNextLevel(); + + std::vector<CG_loop *> cur_loops; + for (int i = 0; i < next_level.size(); i++) { + CG_loop *lp = dynamic_cast<CG_loop *>(next_level[i]); + if (lp != NULL) { + cur_loops.push_back(lp); + } else { + stmtList = ocg->StmtListAppend(stmtList, + loop_print_repr(active_, + cur_loops, + 0, + cur_loops.size(), + Relation::True(num_level()), + NULL, + indent, + codegen_->remap_, + codegen_->xforms_, + ocg, + stmts, + assigned_on_the_fly, + unin)); + stmtList = ocg->StmtListAppend(stmtList, + next_level[i]->printRepr(indent, + ocg, + stmts, + assigned_on_the_fly, + unin, + printString)); + cur_loops.clear(); + } + } + + stmtList = ocg->StmtListAppend(stmtList, + loop_print_repr(active_, + cur_loops, + 0, + cur_loops.size(), + Relation::True(num_level()), + NULL, + indent, + codegen_->remap_, + codegen_->xforms_, + ocg, + stmts, + assigned_on_the_fly, + unin)); + return stmtList; + } + + CG_result *CG_split::clone() const { + //fprintf(stderr, "CG_split::clone()\n"); + std::vector<CG_result *> clauses(clauses_.size()); + for (int i = 0; i < clauses_.size(); i++) + clauses[i] = clauses_[i]->clone(); + return new CG_split(codegen_, active_, restrictions_, clauses); + } + + void CG_split::dump(int indent) const { + std::string prefix; + for (int i = 0; i < indent; i++) + prefix += " "; + std::cout << prefix << "SPLIT: " << active_ << std::endl; + for (int i = 0; i < restrictions_.size(); i++) { + std::cout << prefix << "restriction: "; + const_cast<CG_split *>(this)->restrictions_[i].print(); + clauses_[i]->dump(indent + 1); + } + + } + + //----------------------------------------------------------------------------- + // Class: CG_loop + //----------------------------------------------------------------------------- + + CG_result *CG_loop::recompute(const BoolSet<> &parent_active, + const Relation &known, const Relation &restriction) { + known_ = copy(known); + restriction_ = copy(restriction); + active_ &= parent_active; + + std::vector<Relation> Rs; + for (BoolSet<>::iterator i = active_.begin(); i != active_.end(); i++) { + Relation r = Intersection(copy(restriction), + copy(codegen_->projected_IS_[level_ - 1][*i])); + + //r.simplify(2, 4); + r.simplify(); + if (!r.is_upper_bound_satisfiable()) { + active_.unset(*i); + continue; + } + Rs.push_back(copy(r)); + } + + if (active_.empty()) { + delete this; + return NULL; + } + + Relation hull = SimpleHull(Rs, true, true); + + //hull.simplify(2,4); + //Anand:Variables for inspector constraint check + bool has_insp = false; + bool found_insp = false; + + //Global_Var_ID global_insp; + //Argument_Tuple arg; + // check if actual loop is needed + std::pair<EQ_Handle, int> result = find_simplest_assignment(hull, + hull.set_var(level_)); + if (result.second < INT_MAX) { + needLoop_ = false; + + bounds_ = Relation(hull.n_set()); + F_Exists *f_exists = bounds_.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 (Constr_Vars_Iter cvi(result.first); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + h.update_coef(bounds_.input_var(v->get_position()), + cvi.curr_coef()); + break; + case Wildcard_Var: { + Variable_ID v2 = replicate_floor_definition(hull, v, bounds_, + 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 = bounds_.get_local(g); + else + v2 = bounds_.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const(result.first.get_const()); + bounds_.simplify(); + } + // loop iterates more than once, extract bounds now + else { + fprintf(stderr, "loop iterates more than once, extract bounds now\n"); + needLoop_ = true; + + bounds_ = Relation(hull.n_set()); + F_Exists *f_exists = bounds_.add_and()->add_exists(); + F_And *f_root = f_exists->add_and(); + std::map<Variable_ID, Variable_ID> exists_mapping; + + Relation b = Gist(copy(hull), copy(known), 1); + bool has_unresolved_bound = false; + + std::set<Variable_ID> excluded_floor_vars; + excluded_floor_vars.insert(b.set_var(level_)); + for (GEQ_Iterator e(b.single_conjunct()->GEQs()); e; e++) + if ((*e).get_coef(b.set_var(level_)) != 0) { + bool is_bound = true; + for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) { + std::pair<bool, GEQ_Handle> result = find_floor_definition( + b, cvi.curr_var(), excluded_floor_vars); + if (!result.first) { + is_bound = false; + has_unresolved_bound = true; + //break; + } + + if (!is_bound) { + std::vector<std::pair<bool, GEQ_Handle> > result = + find_floor_definition_temp(b, cvi.curr_var(), + excluded_floor_vars); + + if (result.size() != 2) + break; + + has_unresolved_bound = false; + for (int i = 0; i < result.size(); i++) { + + GEQ_Handle h = f_root->add_GEQ(); + + for (Constr_Vars_Iter cvi(result[i].second); cvi; + cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + h.update_coef( + bounds_.input_var( + v->get_position()), + cvi.curr_coef()); + break; + case Wildcard_Var: { + Variable_ID v2; + + v2 = replicate_floor_definition(b, v, + bounds_, 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 = bounds_.get_local(g); + else + v2 = bounds_.get_local(g, + v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const((result[i].second).get_const()); + } + break; + } + } + + if (!is_bound) + continue; + + GEQ_Handle h = f_root->add_GEQ(); + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + h.update_coef(bounds_.input_var(v->get_position()), + cvi.curr_coef()); + break; + case Wildcard_Var: { + Variable_ID v2 = replicate_floor_definition(b, v, + bounds_, 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 = bounds_.get_local(g); + else + v2 = bounds_.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const((*e).get_const()); + } + + if (has_unresolved_bound) { + b = Approximate(b); + b.simplify(2, 4); + //Simplification of Hull + hull = Approximate(hull); + hull.simplify(2, 4); + //end : Anand + for (GEQ_Iterator e(b.single_conjunct()->GEQs()); e; e++) + if ((*e).get_coef(b.set_var(level_)) != 0) + f_root->add_GEQ(*e); + } + bounds_.simplify(); + hull.simplify(2,4); + // Since current SimpleHull does not support max() upper bound or min() lower bound, + // we have to forcefully split the loop when hull approximation does not return any bound. + bool has_lb = false; + bool has_ub = false; + for (GEQ_Iterator e = bounds_.single_conjunct()->GEQs(); e; e++) { + if ((*e).get_coef(bounds_.set_var(level_)) > 0) + has_lb = true; + else if ((*e).get_coef(bounds_.set_var(level_)) < 0) + has_ub = true; + if (has_lb && has_ub) + break; + } + + if (!has_lb) { + for (int i = 0; i < Rs.size(); i++) { + Relation r = Approximate(copy(Rs[i])); + r.simplify(2, 4); + for (GEQ_Iterator e = r.single_conjunct()->GEQs(); e; e++) + if ((*e).get_coef(r.input_var(level_)) > 0) { + Relation r2 = Relation::True(num_level()); + r2.and_with_GEQ(*e); + r2.simplify(); + std::vector<Relation> restrictions(2); + restrictions[0] = Complement(copy(r2)); + restrictions[0].simplify(); + restrictions[1] = r2; + std::vector<CG_result *> clauses(2); + clauses[0] = this; + clauses[1] = this->clone(); + CG_result *cgr = new CG_split(codegen_, active_, + restrictions, clauses); + cgr = cgr->recompute(active_, copy(known), + copy(restriction)); + return cgr; + } + } + for (int i = 0; i < Rs.size(); i++) { + Relation r = Approximate(copy(Rs[i])); + r.simplify(2, 4); + for (EQ_Iterator e = r.single_conjunct()->EQs(); e; e++) + if ((*e).get_coef(r.input_var(level_)) != 0) { + Relation r2 = Relation::True(num_level()); + r2.and_with_GEQ(*e); + r2.simplify(); + std::vector<Relation> restrictions(2); + if ((*e).get_coef(r.input_var(level_)) > 0) { + restrictions[0] = Complement(copy(r2)); + restrictions[0].simplify(); + restrictions[1] = r2; + } else { + restrictions[0] = r2; + restrictions[1] = Complement(copy(r2)); + restrictions[1].simplify(); + } + std::vector<CG_result *> clauses(2); + clauses[0] = this; + clauses[1] = this->clone(); + CG_result *cgr = new CG_split(codegen_, active_, + restrictions, clauses); + cgr = cgr->recompute(active_, copy(known), + copy(restriction)); + return cgr; + } + } + } else if (!has_ub) { + for (int i = 0; i < Rs.size(); i++) { + Relation r = Approximate(copy(Rs[i])); + r.simplify(2, 4); + for (GEQ_Iterator e = r.single_conjunct()->GEQs(); e; e++) + if ((*e).get_coef(r.input_var(level_)) < 0) { + Relation r2 = Relation::True(num_level()); + r2.and_with_GEQ(*e); + r2.simplify(); + std::vector<Relation> restrictions(2); + restrictions[1] = Complement(copy(r2)); + restrictions[1].simplify(); + restrictions[0] = r2; + std::vector<CG_result *> clauses(2); + clauses[0] = this; + clauses[1] = this->clone(); + CG_result *cgr = new CG_split(codegen_, active_, + restrictions, clauses); + cgr = cgr->recompute(active_, copy(known), + copy(restriction)); + return cgr; + } + } + for (int i = 0; i < Rs.size(); i++) { + Relation r = Approximate(copy(Rs[i])); + r.simplify(2, 4); + for (EQ_Iterator e = r.single_conjunct()->EQs(); e; e++) + if ((*e).get_coef(r.input_var(level_)) != 0) { + Relation r2 = Relation::True(num_level()); + r2.and_with_GEQ(*e); + r2.simplify(); + std::vector<Relation> restrictions(2); + if ((*e).get_coef(r.input_var(level_)) > 0) { + restrictions[0] = Complement(copy(r2)); + restrictions[0].simplify(); + restrictions[1] = r2; + } else { + restrictions[0] = r2; + restrictions[1] = Complement(copy(r2)); + restrictions[1].simplify(); + } + std::vector<CG_result *> clauses(2); + clauses[0] = this; + clauses[1] = this->clone(); + CG_result *cgr = new CG_split(codegen_, active_, + restrictions, clauses); + cgr = cgr->recompute(active_, copy(known), + copy(restriction)); + return cgr; + } + } + } + + if (!has_lb && !has_ub) + throw codegen_error( + "can't find any bound at loop level " + to_string(level_)); + else if (!has_lb) + throw codegen_error( + "can't find lower bound at loop level " + + to_string(level_)); + else if (!has_ub) + throw codegen_error( + "can't find upper bound at loop level " + + to_string(level_)); + } + bounds_.copy_names(hull); + bounds_.setup_names(); + + // additional guard/stride condition extraction + if (needLoop_) { + Relation cur_known = Intersection(copy(bounds_), copy(known_)); + cur_known.simplify(); + hull = Gist(hull, copy(cur_known), 1); + + std::pair<EQ_Handle, Variable_ID> result = find_simplest_stride(hull, + hull.set_var(level_)); + if (result.second != NULL) + if (abs(result.first.get_coef(hull.set_var(level_))) == 1) { + F_Exists *f_exists = bounds_.and_with_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 (Constr_Vars_Iter cvi(result.first); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + h.update_coef(bounds_.input_var(v->get_position()), + cvi.curr_coef()); + break; + case Wildcard_Var: { + Variable_ID v2; + if (v == result.second) + v2 = f_exists->declare(); + else + v2 = replicate_floor_definition(hull, v, bounds_, + 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 = bounds_.get_local(g); + else + v2 = bounds_.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const(result.first.get_const()); + } else { + // since gist is not powerful enough on modular constraints for now, + // make an educated guess + coef_t stride = abs(result.first.get_coef(result.second)) + / gcd(abs(result.first.get_coef(result.second)), + abs( + result.first.get_coef( + hull.set_var(level_)))); + + Relation r1(hull.n_inp()); + F_Exists *f_exists = r1.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 (Constr_Vars_Iter cvi(result.first); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + h.update_coef(r1.input_var(v->get_position()), + cvi.curr_coef()); + break; + case Wildcard_Var: { + Variable_ID v2; + if (v == result.second) + v2 = f_exists->declare(); + else + v2 = replicate_floor_definition(hull, v, r1, + 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 = r1.get_local(g); + else + v2 = r1.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const(result.first.get_const()); + r1.simplify(); + + bool guess_success = false; + for (GEQ_Iterator e(bounds_.single_conjunct()->GEQs()); e; e++) + if ((*e).get_coef(bounds_.set_var(level_)) == 1) { + Relation r2(hull.n_inp()); + F_Exists *f_exists = r2.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(); + h.update_coef(f_exists->declare(), stride); + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + h.update_coef(r2.input_var(v->get_position()), + cvi.curr_coef()); + break; + case Wildcard_Var: { + Variable_ID v2 = replicate_floor_definition( + hull, v, r2, 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 = r2.get_local(g); + else + v2 = r2.get_local(g, v->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(false); + } + } + h.update_const((*e).get_const()); + r2.simplify(); + + if (Gist(copy(r1), + Intersection(copy(cur_known), copy(r2)), 1).is_obvious_tautology() + && Gist(copy(r2), + Intersection(copy(cur_known), copy(r1)), + 1).is_obvious_tautology()) { + bounds_ = Intersection(bounds_, r2); + bounds_.simplify(); + guess_success = true; + break; + } + } + + // this is really a stride with non-unit coefficient for this loop variable + if (!guess_success) { + // TODO: for stride ax = b mod n it might be beneficial to + // generate modular linear equation solver code for + // runtime to get the starting position in printRepr, + // and stride would be n/gcd(|a|,n), thus this stride + // can be put into bounds_ too. + } + + } + + hull = Project(hull, hull.set_var(level_)); + hull.simplify(2, 4); + guard_ = Gist(hull, Intersection(copy(bounds_), copy(known_)), 1); + } + // don't generate guard for non-actual loop, postpone it. otherwise + // redundant if-conditions might be generated since for-loop semantics + // includes implicit comparison checking. -- by chun 09/14/10 + else + guard_ = Relation::True(num_level()); + guard_.copy_names(bounds_); + guard_.setup_names(); + + //guard_.simplify(); + // recursively down the AST + Relation new_known = Intersection(copy(known), + Intersection(copy(bounds_), copy(guard_))); + //Anand: IF inspector present in equality and GEQ add the equality constraint to known + //So as to avoid unnecessary IF condition + new_known.simplify(2, 4); + Relation new_restriction = Intersection(copy(restriction), + Intersection(copy(bounds_), copy(guard_))); + new_restriction.simplify(2, 4); + body_ = body_->recompute(active_, new_known, new_restriction); + if (body_ == NULL) { + delete this; + return NULL; + } else + return this; + } + + int CG_loop::populateDepth() { + int depth = body_->populateDepth(); + if (needLoop_) + depth_ = depth + 1; + else + depth_ = depth; + return depth_; + } + + std::pair<CG_result *, Relation> CG_loop::liftOverhead(int depth, + bool propagate_up) { + if (depth_ > depth) { + assert(propagate_up == false); + std::pair<CG_result *, Relation> result = body_->liftOverhead(depth, + false); + body_ = result.first; + return std::make_pair(this, Relation::True(num_level())); + } else { // (depth_ <= depth) + if (propagate_up) { + Relation r = pick_one_guard(guard_, level_); + if (!r.is_obvious_tautology()) + return std::make_pair(this, r); + } + + std::pair<CG_result *, Relation> result; + if (propagate_up || needLoop_) + result = body_->liftOverhead(depth, true); + else + result = body_->liftOverhead(depth, false); + body_ = result.first; + if (result.second.is_obvious_tautology()) + return std::make_pair(this, result.second); + + // loop is an assignment, replace this loop variable in overhead condition + if (!needLoop_) { + result.second = Intersection(result.second, copy(bounds_)); + result.second = Project(result.second, + result.second.set_var(level_)); + result.second.simplify(2, 4); + } + + int max_level = 0; + bool has_wildcard = false; + bool direction = true; + for (EQ_Iterator e(result.second.single_conjunct()->EQs()); e; e++) + if ((*e).has_wildcards()) { + if (has_wildcard) + assert(false); + else + has_wildcard = true; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + if (cvi.curr_var()->kind() == Input_Var + && cvi.curr_var()->get_position() > max_level) + max_level = cvi.curr_var()->get_position(); + } else + assert(false); + + if (!has_wildcard) { + int num_simple_geq = 0; + for (GEQ_Iterator e(result.second.single_conjunct()->GEQs()); e; + e++) + if (!(*e).has_wildcards()) { + num_simple_geq++; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + if (cvi.curr_var()->kind() == Input_Var + && cvi.curr_var()->get_position() > max_level) { + max_level = cvi.curr_var()->get_position(); + direction = (cvi.curr_coef() < 0) ? true : false; + } + } else { + has_wildcard = true; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + if (cvi.curr_var()->kind() == Input_Var + && cvi.curr_var()->get_position() > max_level) { + max_level = cvi.curr_var()->get_position(); + } + } + assert( + (has_wildcard && num_simple_geq == 0) + || (!has_wildcard && num_simple_geq == 1)); + } + + // check if this is the top loop level for splitting for this overhead + if (!propagate_up || (has_wildcard && max_level == level_ - 1) + || (!has_wildcard && max_level == level_)) { + std::vector<Relation> restrictions(2); + std::vector<CG_result *> clauses(2); + int saved_num_level = num_level(); + if (has_wildcard || direction) { + restrictions[1] = Complement(copy(result.second)); + restrictions[1].simplify(); + clauses[1] = this->clone(); + restrictions[0] = result.second; + clauses[0] = this; + } else { + restrictions[0] = Complement(copy(result.second)); + restrictions[0].simplify(); + clauses[0] = this->clone(); + restrictions[1] = result.second; + clauses[1] = this; + } + CG_result *cgr = new CG_split(codegen_, active_, restrictions, + clauses); + CG_result *new_cgr = cgr->recompute(active_, copy(known_), + copy(restriction_)); + new_cgr->populateDepth(); + assert(new_cgr==cgr); + if (static_cast<CG_split *>(new_cgr)->clauses_.size() == 1) + // infinite recursion detected, bail out + return std::make_pair(new_cgr, Relation::True(saved_num_level)); + else + return cgr->liftOverhead(depth, propagate_up); + } else + return std::make_pair(this, result.second); + } + } + + + + Relation CG_loop::hoistGuard() { + + Relation r = body_->hoistGuard(); + + // TODO: should bookkeep catched contraints in loop output as enforced and check if anything missing + // if (!Gist(copy(b), copy(enforced)).is_obvious_tautology()) { + // fprintf(stderr, "need to generate extra guard inside the loop\n"); + // } + + if (!needLoop_) + r = Intersection(r, copy(bounds_)); + r = Project(r, r.set_var(level_)); + r = Gist(r, copy(known_), 1); + + Relation eliminate_existentials_r; + Relation eliminate_existentials_known; + + eliminate_existentials_r = copy(r); + if (!r.is_obvious_tautology()) { + eliminate_existentials_r = Approximate(copy(r)); + eliminate_existentials_r.simplify(2,4); + eliminate_existentials_known = Approximate(copy(known_)); + eliminate_existentials_known.simplify(2,4); + + eliminate_existentials_r = Gist(eliminate_existentials_r, + eliminate_existentials_known, 1); + } + + + if (!eliminate_existentials_r.is_obvious_tautology()) { + // if (!r.is_obvious_tautology()) { + body_->removeGuard(r); + guard_ = Intersection(guard_, copy(r)); + guard_.simplify(); + } + + return guard_; + } + + + + void CG_loop::removeGuard(const Relation &guard) { + known_ = Intersection(known_, copy(guard)); + known_.simplify(); + + guard_ = Gist(guard_, copy(known_), 1); + guard_.copy_names(known_); + guard_.setup_names(); + } + + + + + CG_outputRepr *CG_loop::printRepr(int indent, + CG_outputBuilder *ocg, + const std::vector<CG_outputRepr *> &stmts, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > unin, bool printString) const { + + fprintf(stderr, "CG_loop::printRepr() w assigned_on_the_fly gonna call printRepr with more arguments\n"); + //int numfly = assigned_on_the_fly.size(); + //fprintf(stderr, "assigned on the fly %d\n", numfly ); + //for (int i=0; i<numfly; i++) { + // //fprintf(stderr, "i %d\n", i); + // std::pair<CG_outputRepr *, int>p = assigned_on_the_fly[i]; + // CG_outputRepr *tr = NULL; + // if (p.first != NULL) tr = p.first->clone(); + // int val = p.second; + // //fprintf(stderr, "0x%x %d\n", tr, val); + //} + + return printRepr(true, indent, ocg, stmts, assigned_on_the_fly, unin, printString); + } + + + + + + CG_outputRepr *CG_loop::printRepr(bool do_print_guard, + int indent, + CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > unin, bool printString) const { + fprintf(stderr, "\n*** CG.cc CG_loop printrepr with more arguments\n"); + + + // debugging output + int numfly = assigned_on_the_fly.size(); + fprintf(stderr, "assigned on the fly %d\n", numfly ); // Anand makes twice as many + for (int i=0; i<numfly; i++) { + //fprintf(stderr, "i %d\n", i); + std::pair<CG_outputRepr *, int>p = assigned_on_the_fly[i]; + CG_outputRepr *tr = NULL; + if (p.first != NULL) tr = p.first->clone(); + int val = p.second; + //fprintf(stderr, "0x%x %d\n", tr, val); + } + + //Anand: adding support for Replacing substituted variables within + //Uninterpreted function symbols or global variables with arity > 0 here + //--begin + std::vector<std::pair<CG_outputRepr *, int> > aotf = assigned_on_the_fly; + int stmt_num = -1; + for (int s = 0; s < active_.size(); s++) + if (active_.get(s)) + stmt_num = s; + + assert(stmt_num != -1); + + CG_outputRepr *guardRepr; + if (do_print_guard) + guardRepr = output_guard(ocg, guard_, aotf, unin[stmt_num]); + else + guardRepr = NULL; + + fprintf(stderr, "after guard assigned on the fly %d\n", numfly ); + for (int i=0; i<numfly; i++) { + //fprintf(stderr, "i %d\n", i); + std::pair<CG_outputRepr *, int>p = assigned_on_the_fly[i]; + CG_outputRepr *tr = NULL; + if (p.first != NULL) tr = p.first->clone(); + int val = p.second; + //fprintf(stderr, "0x%x %d\n", tr, val); + } + fprintf(stderr, "done flying\n"); + + Relation cur_known = Intersection(copy(known_), copy(guard_)); + + cur_known.simplify(); + fprintf(stderr, "checking needloop\n"); + if (needLoop_) { + fprintf(stderr, "needLoop_\n"); + + if (checkLoopLevel) + if (level_ == checkLoopLevel) + if (active_.get(stmtForLoopCheck)) + fillInBounds = true; + + fprintf(stderr, "ctrlRepr = output_loop()\n"); + CG_outputRepr *ctrlRepr = output_loop(ocg, bounds_, level_, cur_known, + aotf, unin[stmt_num]); + + fillInBounds = false; + + fprintf(stderr, "in needLoop_ bodyrepr = \n"); + int ind = (guardRepr == NULL) ? indent + 1 : indent + 2; + CG_outputRepr *bodyRepr = body_->printRepr(ind, + ocg, + stmts, + aotf, + unin, + printString); + CG_outputRepr * loopRepr; + + if (guardRepr == NULL) + loopRepr = ocg->CreateLoop(indent, ctrlRepr, bodyRepr); + else + loopRepr = ocg->CreateLoop(indent + 1, ctrlRepr, bodyRepr); + + + if (!smtNonSplitLevels.empty()) { + fprintf(stderr, "!smtNonSplitLevels.empty()\n"); + bool blockLoop = false; + bool threadLoop = false; + bool sync = false; + int firstActiveStmt = -1; + for (int s = 0; s < active_.size(); s++) { + if (active_.get(s)) { + if (firstActiveStmt < 0) + firstActiveStmt = s; + //We assume smtNonSplitLevels is only used to mark the first of + //the block or thread loops to be reduced in CUDA-CHiLL. Here we + //place some comments to help with final code generation. + //int idx = smtNonSplitLevels[s].index(level_); + + if (s < smtNonSplitLevels.size()) { + if (smtNonSplitLevels[s].size() > 0) + if (smtNonSplitLevels[s][0] == level_) { + blockLoop = true; + } + //Assume every stmt marked with a thread loop index also has a block loop idx + if (smtNonSplitLevels[s].size() > 1) + if (smtNonSplitLevels[s][1] == level_) { + threadLoop = true; + } + } + } + } + if (blockLoop && threadLoop) { + fprintf(stderr, + "Warning, have %d level more than once in smtNonSplitLevels\n", + level_); + threadLoop = false; + } + std::string preferredIdx; + + fprintf(stderr, "loopIdxNames.size() %d\n", loopIdxNames.size()); + for (int i=0; i<loopIdxNames.size(); i++) { + fprintf(stderr, "\n"); + for (int j=0; j<loopIdxNames[i].size(); j++) { + fprintf(stderr, "i %d j %d %s\n", i, j,loopIdxNames[i][j].c_str() ); + } + } + + fprintf(stderr, "firstActiveStmt %d\n", firstActiveStmt); + fprintf(stderr, "loopIdxNames[firstActiveStmt].size() %d\n", loopIdxNames[firstActiveStmt].size()); + fprintf(stderr, "level_ %d /2 %d\n", level_, level_/2); + + if (loopIdxNames.size() + && (level_ / 2) - 1 < loopIdxNames[firstActiveStmt].size()) { + + preferredIdx = loopIdxNames[firstActiveStmt][(level_ / 2) - 1]; + } + for (int s = 0; s < active_.size(); s++) { + if (active_.get(s)) { + for (int ii = 0; ii < syncs.size(); ii++) { + if (syncs[ii].first == s + && strcmp(syncs[ii].second.c_str(), + preferredIdx.c_str()) == 0) { + sync = true; + //printf("FOUND SYNC\n"); + } + + } + } + } + + if ( preferredIdx.length() != 0) { + fprintf(stderr, "CG.cc preferredIdx %s\n", preferredIdx.c_str()); + } + + if (threadLoop || blockLoop || preferredIdx.length() != 0) { + char buf[1024]; + std::string loop; + if (blockLoop) + loop = "blockLoop "; + if (threadLoop) + loop = "threadLoop "; + + if ( preferredIdx.length() != 0) { + fprintf(stderr, "CG.cc adding comment with preferredIdx %s\n", preferredIdx.c_str()); + } + + if (preferredIdx.length() != 0 && sync) { + sprintf(buf, "~cuda~ %spreferredIdx: %s sync", loop.c_str(), + preferredIdx.c_str()); + } else if (preferredIdx.length() != 0) { + sprintf(buf, "~cuda~ %spreferredIdx: %s", loop.c_str(), + preferredIdx.c_str()); + } else { + sprintf(buf, "~cuda~ %s", loop.c_str()); + } + + + loopRepr = ocg->CreateAttribute(loopRepr, buf); + } + + } + if (guardRepr == NULL) + return loopRepr; + else + return ocg->CreateIf(indent, guardRepr, loopRepr, NULL); + } + else { + fprintf(stderr, "NOT needloop_\n"); + + std::pair<CG_outputRepr *, std::pair<CG_outputRepr *, int> > result = + output_assignment(ocg, bounds_, level_, cur_known, aotf, unin[stmt_num]); + + //fprintf(stderr, "RESULT 0x%x 0x%x %d\n", result.first, result.second.first, result.second.second ); + + + guardRepr = ocg->CreateAnd(guardRepr, result.first); + //fprintf(stderr, "RESULT 0x%x 0x%x %d\n", result.first, result.second.first, result.second.second ); + + //fprintf(stderr, "after guardRepr assigned on the fly %d\n", numfly ); + for (int i=0; i<numfly; i++) { + //fprintf(stderr, "i %d\n", i); + std::pair<CG_outputRepr *, int>p = assigned_on_the_fly[i]; + CG_outputRepr *tr = NULL; + if (p.first != NULL) tr = p.first->clone(); + int val = p.second; + //fprintf(stderr, "0x%x %d\n", tr, val); + } + + + if (result.second.second < CodeGen::var_substitution_threshold) { + //fprintf(stderr, "var_substitution_threshold %d < %d level_ = %d\n", result.second.second, CodeGen::var_substitution_threshold, level_); + std::vector<std::pair<CG_outputRepr *, int> > aotf = + assigned_on_the_fly; + aotf[level_ - 1] = result.second; + //fprintf(stderr, "RESULT 0x%x second 0x%x %d\n", result.first, result.second.first, result.second.second ); + + if(!printString) { + for (std::map<std::string, std::vector<CG_outputRepr *> >::iterator i = + unin[stmt_num].begin(); i != unin[stmt_num].end(); i++) { + + + std::vector<CG_outputRepr *> to_push; + for (int j = 0; j < i->second.size(); j++) { + std::string index = + const_cast<CG_loop *>(this)->bounds_.set_var(level_)->name(); + std::vector<std::string> loop_vars; + loop_vars.push_back(index); + std::vector<CG_outputRepr *> subs; + subs.push_back(result.second.first->clone()); + CG_outputRepr * new_repr = ocg->CreateSubstitutedStmt(0, + i->second[j]->clone(), loop_vars, subs); + to_push.push_back(new_repr); + } + i->second = to_push; + } // for + } // if + + //fprintf(stderr, "aotf !!\n"); + for (int i=0; i<numfly; i++) { + //fprintf(stderr, "i %d\n", i); + std::pair<CG_outputRepr *, int>p = aotf[i]; + CG_outputRepr *tr = NULL; + if (p.first != NULL) { tr = p.first->clone(); } + int val = p.second; + } + + //fprintf(stderr, "\nbodyRepr =\n"); + //body_->dump(); // this dies + int ind = (guardRepr == NULL) ? indent : indent + 1; + CG_outputRepr *bodyRepr = body_->printRepr(ind, ocg, stmts, aotf, unin, + printString); + + delete aotf[level_ - 1].first; + if (guardRepr == NULL) + return bodyRepr; + else + return ocg->CreateIf(indent, guardRepr, bodyRepr, NULL); + } else { + //fprintf(stderr, "NOT var_substitution_threshold gonna call output_ident()\n"); + int ind = (guardRepr == NULL) ? indent : indent + 1; + CG_outputRepr *assignRepr = ocg->CreateAssignment( + ind, + output_ident(ocg, bounds_, + const_cast<CG_loop *>(this)->bounds_.set_var( + level_), aotf, unin[stmt_num]), + result.second.first); + + CG_outputRepr *bodyRepr = body_->printRepr(ind, ocg, stmts, aotf, unin, + printString); + + if (guardRepr == NULL) + return ocg->StmtListAppend(assignRepr, bodyRepr); + else + return ocg->CreateIf(indent, guardRepr, + ocg->StmtListAppend(assignRepr, bodyRepr), NULL); + + /* DEAD CODE + std::pair<EQ_Handle, int> result_ = find_simplest_assignment( + copy(bounds_), copy(bounds_).set_var(level_), + assigned_on_the_fly); + bool found_func = false; + Variable_ID v2; + int arity; + for (Constr_Vars_Iter cvi(result_.first); cvi; cvi++) + if (cvi.curr_var()->kind() == Global_Var) { + Global_Var_ID g = cvi.curr_var()->get_global_var(); + if ((g->arity() > 0)) { + + found_func = true; + arity = g->arity(); + //copy(R).print(); + v2 = copy(bounds_).get_local(g, + cvi.curr_var()->function_of()); + + break; + } + } + + bool is_array = false; + if (found_func) { + + is_array = ocg->QueryInspectorType( + v2->get_global_var()->base_name()); + + } + if (!found_func || !is_array) { + + CG_outputRepr *assignRepr = ocg->CreateAssignment( + (guardRepr == NULL) ? indent : indent + 1, + output_ident(ocg, bounds_, + const_cast<CG_loop *>(this)->bounds_.set_var( + level_), assigned_on_the_fly), + result.second.first); + + CG_outputRepr *bodyRepr = body_->printRepr( + (guardRepr == NULL) ? indent : indent + 1, ocg, stmts, + assigned_on_the_fly); + if (guardRepr == NULL) + return ocg->StmtListAppend(assignRepr, bodyRepr); + else + return ocg->CreateIf(indent, guardRepr, + ocg->StmtListAppend(assignRepr, bodyRepr), NULL); + + } else { + + std::vector<CG_outputRepr *> index_expr; + + CG_outputRepr* lb = ocg->CreateArrayRefExpression( + v2->get_global_var()->base_name(), + output_ident(ocg, bounds_, + const_cast<CG_loop *>(this)->bounds_.set_var(2), + assigned_on_the_fly)); + + for (int i = arity; i > 1; i--) { + + index_expr.push_back( + ocg->CreateArrayRefExpression( + v2->get_global_var()->base_name(), + output_ident(ocg, bounds_, + const_cast<CG_loop *>(this)->bounds_.set_var( + 2 * i), + assigned_on_the_fly))); + + //} + + } + + CG_outputRepr *ub; + if (index_expr.size() > 1) + ub = ocg->CreateInvoke("max", index_expr); + else + ub = index_expr[0]; + CG_outputRepr *le = ocg->CreateMinus(ub, ocg->CreateInt(1)); + CG_outputRepr *inductive = ocg->CreateInductive( + output_ident(ocg, bounds_, + const_cast<CG_loop *>(this)->bounds_.set_var( + level_), assigned_on_the_fly), lb, le, + NULL); + + CG_outputRepr *bodyRepr = body_->printRepr( + (guardRepr == NULL) ? indent : indent + 1, ocg, stmts, + assigned_on_the_fly); + + if (guardRepr == NULL) { + return ocg->CreateLoop(indent, inductive, bodyRepr); + } else + return ocg->CreateIf(indent, guardRepr, + ocg->CreateLoop(indent + 1, inductive, bodyRepr), + NULL); + } + */ + } + } + } + + +/* +//Protonu--adding a helper function to get the ids of the nested loops +//to help with OpenMP code generation + std::vector<std::string> get_idxs( CG_result * cgl, std::vector<std::string>& idxs) + { + CG_loop * _lp; + CG_split *_sp; + + _lp = dynamic_cast<CG_loop *>(cgl); + _sp = dynamic_cast<CG_split *>(cgl); + + if(_lp){ + if (_lp->needLoop_) + idxs.push_back((copy(_lp->bounds_).set_var(_lp->level_))->name()); + if (_lp->depth() > 0 ){ + cgl = _lp->body_; + get_idxs(cgl, idxs); + } + if (_lp->depth() == 0) + return idxs; + } + if(_sp){ + for(int i=0; i<_sp->clauses_.size(); i++) + { + get_idxs(_sp->clauses_[i], idxs); + } + } + + return idxs; + + } +//end. +*/ + + + CG_result *CG_loop::clone() const { + //fprintf(stderr, "CG_loop::clone()\n"); + return new CG_loop(codegen_, active_, level_, body_->clone()); + } + + void CG_loop::dump(int indent) const { + std::string prefix; + for (int i = 0; i < indent; i++) + prefix += " "; + std::cout << prefix << "LOOP (level " << level_ << "): " << active_ + << std::endl; + std::cout << prefix << "known: "; + const_cast<CG_loop *>(this)->known_.print(); + std::cout << prefix << "restriction: "; + const_cast<CG_loop *>(this)->restriction_.print(); + std::cout << prefix << "bounds: "; + const_cast<CG_loop *>(this)->bounds_.print(); + std::cout << prefix << "guard: "; + const_cast<CG_loop *>(this)->guard_.print(); + body_->dump(indent + 1); + } + + //----------------------------------------------------------------------------- + // Class: CG_leaf + //----------------------------------------------------------------------------- + + CG_result* CG_leaf::recompute(const BoolSet<> &parent_active, + const Relation &known, const Relation &restriction) { + active_ &= parent_active; + known_ = copy(known); + + guards_.clear(); + for (BoolSet<>::iterator i = active_.begin(); i != active_.end(); i++) { + Relation r = Intersection( + copy(codegen_->projected_IS_[num_level() - 1][*i]), + copy(restriction)); + r.simplify(2, 4); + if (!r.is_upper_bound_satisfiable()) + active_.unset(*i); + else { + r = Gist(r, copy(known), 1); + if (!r.is_obvious_tautology()) { + guards_[*i] = r; + guards_[*i].copy_names(known); + guards_[*i].setup_names(); + } + } + } + + + if (active_.empty()) { + delete this; + return NULL; + } else + return this; + } + + std::pair<CG_result *, Relation> CG_leaf::liftOverhead(int depth, bool) { + if (depth == 0) + return std::make_pair(this, Relation::True(num_level())); + + for (std::map<int, Relation>::iterator i = guards_.begin(); + i != guards_.end(); i++) { + Relation r = pick_one_guard(i->second); + if (!r.is_obvious_tautology()) { + bool has_wildcard = false; + int max_level = 0; + for (EQ_Iterator e(r.single_conjunct()->EQs()); e; e++) { + if ((*e).has_wildcards()) + has_wildcard = true; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + if (cvi.curr_var()->kind() == Input_Var + && cvi.curr_var()->get_position() > max_level) + max_level = cvi.curr_var()->get_position(); + } + for (GEQ_Iterator e(r.single_conjunct()->GEQs()); e; e++) { + if ((*e).has_wildcards()) + has_wildcard = true; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + if (cvi.curr_var()->kind() == Input_Var + && cvi.curr_var()->get_position() > max_level) + max_level = cvi.curr_var()->get_position(); + } + + if (!(has_wildcard && max_level == codegen_->num_level())) + return std::make_pair(this, r); + } + } + + return std::make_pair(this, Relation::True(num_level())); + } + + Relation CG_leaf::hoistGuard() { + std::vector<Relation> guards; + for (BoolSet<>::iterator i = active_.begin(); i != active_.end(); i++) { + std::map<int, Relation>::iterator j = guards_.find(*i); + if (j == guards_.end()) { + Relation r = Relation::True(num_level()); + r.copy_names(known_); + r.setup_names(); + return r; + } else { + guards.push_back(j->second); + } + } + + return SimpleHull(guards, true, true); + } + + void CG_leaf::removeGuard(const Relation &guard) { + known_ = Intersection(known_, copy(guard)); + known_.simplify(); + + std::map<int, Relation>::iterator i = guards_.begin(); + while (i != guards_.end()) { + i->second = Gist(i->second, copy(known_), 1); + if (i->second.is_obvious_tautology()) + guards_.erase(i++); + else + ++i; + } + } + + CG_outputRepr *CG_leaf::printRepr(int indent, CG_outputBuilder *ocg, + const std::vector<CG_outputRepr *> &stmts, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > unin, + bool printString) const { + fprintf(stderr, "CG_leaf::printRepr()\n"); + int numfly = assigned_on_the_fly.size(); + //fprintf(stderr, "assigned on the fly %d\n", numfly ); + for (int i=0; i<numfly; i++) { + //fprintf(stderr, "i %d\n", i); + std::pair<CG_outputRepr *, int>p = assigned_on_the_fly[i]; + CG_outputRepr *tr = NULL; + if (p.first != NULL) tr = p.first->clone(); + int val = p.second; + //fprintf(stderr, "0x%x %d\n", tr, val); + } + + return leaf_print_repr(active_, guards_, NULL, known_, indent, ocg, + codegen_->remap_, codegen_->xforms_, stmts, + assigned_on_the_fly, unin); + } + + + + CG_result *CG_leaf::clone() const { + //fprintf(stderr, "CG_leaf::clone()\n"); + return new CG_leaf(codegen_, active_); + } + + void CG_leaf::dump(int indent) const { + + std::string prefix; + for (int i = 0; i < indent; i++) + prefix += " "; + std::cout << prefix << "LEAF: " << active_ << std::endl; + std::cout << prefix << "known: "; + std::cout.flush(); + const_cast<CG_leaf *>(this)->known_.print(); + for (std::map<int, Relation>::const_iterator i = guards_.begin(); + i != guards_.end(); i++) { + std::cout << prefix << "guard #" << i->first << ":"; + const_cast<Relation &>(i->second).print(); + } + } + } diff --git a/lib/codegen/src/CG_stringBuilder.cc b/lib/codegen/src/CG_stringBuilder.cc index 2f9286f..d0f6693 100644..100755 --- a/lib/codegen/src/CG_stringBuilder.cc +++ b/lib/codegen/src/CG_stringBuilder.cc @@ -11,7 +11,7 @@ in other IR interface implementation. They are for debugging purpose. intMod implements modular function that returns positve remainder no matter lop is postive or nagative and rop is guranteed to be positive here. - + History: 04/17/96 - Lei Zhou - created 08/31/09 add parenthesis to string operands, Chun Chen @@ -26,462 +26,641 @@ #include <string.h> namespace { - -std::string SafeguardString(const std::string &s, char op) { - int len = s.length(); - int paren_level = 0; - int num_plusminus = 0; - int num_mul = 0; - int num_div = 0; - for (int i = 0; i < len; i++) - switch (s[i]) { - case '(': - paren_level++; - break; - case ')': - paren_level--; - break; - case '+': + + std::string SafeguardString(const std::string &s, char op) { + int len = s.length(); + int paren_level = 0; + int num_plusminus = 0; + int num_mul = 0; + int num_div = 0; + for (int i = 0; i < len; i++) + switch (s[i]) { + case '(': + paren_level++; + break; + case ')': + paren_level--; + break; + case '+': + case '-': + if (paren_level == 0) + num_plusminus++; + break; + case '*': + if (paren_level == 0) + num_mul++; + break; + case '/': + if (paren_level == 0) + num_div++; + break; + default: + break; + } + + bool need_paren = false; + switch (op) { case '-': - if (paren_level == 0) - num_plusminus++; + if (num_plusminus > 0) + need_paren = true; break; case '*': - if (paren_level == 0) - num_mul++; + if (num_plusminus > 0 || num_div > 0) + need_paren = true; break; case '/': - if (paren_level == 0) - num_div++; + if (num_plusminus > 0 || num_div > 0 || num_mul > 0) + need_paren = true; break; default: break; } - - bool need_paren = false; - switch (op) { - case '-': - if (num_plusminus > 0) - need_paren = true; - break; - case '*': - if (num_plusminus > 0 || num_div > 0) - need_paren = true; - break; - case '/': - if (num_plusminus > 0 || num_div > 0 || num_mul > 0) - need_paren = true; - break; - default: - break; + + if (need_paren) + return "(" + s + ")"; + else + return s; } - - if (need_paren) - return "(" + s + ")"; - else - return s; -} - - -std::string GetIndentSpaces(int indent) { - std::string indentStr; - for (int i = 1; i < indent; i++) { - indentStr += " "; + + + std::string GetIndentSpaces(int indent) { + std::string indentStr; + for (int i = 1; i < indent; i++) { + indentStr += " "; + } + return indentStr; } - return indentStr; -} - - -// A shortcut to extract the string enclosed in the CG_outputRepr and delete -// the original holder. -std::string GetString(omega::CG_outputRepr *repr) { - std::string result = static_cast<omega::CG_stringRepr *>(repr)->GetString(); - delete repr; - return result; -} - + + + // A shortcut to extract the string enclosed in the CG_outputRepr and delete + // the original holder. + std::string GetString(omega::CG_outputRepr *repr) { + std::string result = static_cast<omega::CG_stringRepr *>(repr)->GetString(); + delete repr; + return result; + } + } namespace omega { - - - -//----------------------------------------------------------------------------- -// Class: CG_stringBuilder -//----------------------------------------------------------------------------- - -CG_stringRepr *CG_stringBuilder::CreateSubstitutedStmt(int indent, CG_outputRepr *stmt, - const std::vector<std::string> &vars, - std::vector<CG_outputRepr *> &subs) const { - std::string listStr = ""; - - for (int i = 0; i < subs.size(); i++) { - if (subs[i] == NULL) - listStr += "N/A"; - else - listStr += GetString(subs[i]); - if (i < subs.size() - 1) - listStr += ","; - } - - std::string stmtName = GetString(stmt); - std::string indentStr = GetIndentSpaces(indent); - - return new CG_stringRepr(indentStr + stmtName + "(" + listStr + ");\n"); -} - -CG_stringRepr *CG_stringBuilder::CreateAssignment(int indent, - CG_outputRepr *lhs, - CG_outputRepr *rhs) const { - if (lhs == NULL || rhs == NULL) - throw std::invalid_argument("missing lhs or rhs in assignment"); - - std::string lhsStr = GetString(lhs); - std::string rhsStr = GetString(rhs); - - std::string indentStr = GetIndentSpaces(indent); - - return new CG_stringRepr(indentStr + lhsStr + "=" + rhsStr + ";\n"); -} - - -CG_stringRepr *CG_stringBuilder::CreateInvoke(const std::string &funcName, - std::vector<CG_outputRepr *> &list) const { - std::string listStr = ""; - - for (int i = 0; i < list.size(); i++) { - listStr += GetString(list[i]); - if ( i < list.size()-1) - listStr += ","; + + + + //----------------------------------------------------------------------------- + // Class: CG_stringBuilder + //----------------------------------------------------------------------------- + + CG_stringRepr *CG_stringBuilder::CreateSubstitutedStmt(int indent, + CG_outputRepr *stmt, + const std::vector<std::string> &vars, + std::vector<CG_outputRepr *> &subs, + bool actuallyPrint) const { + std::string listStr = ""; + + for (int i = 0; i < subs.size(); i++) { + if (subs[i] == NULL) + listStr += "N/A"; + else + listStr += GetString(subs[i]); + if (i < subs.size() - 1) + listStr += ","; + } + + std::string stmtName = GetString(stmt); + std::string indentStr = GetIndentSpaces(indent); + + return new CG_stringRepr(indentStr + stmtName + "(" + listStr + ");\n"); } - - return new CG_stringRepr(funcName + "(" + listStr + ")"); -} + + + CG_stringRepr *CG_stringBuilder::CreateStatementFromExpression(CG_outputRepr *exp) const { + std::string expStr = GetString(exp); + return new CG_stringRepr(expStr + ";\n"); + } + + CG_stringRepr *CG_stringBuilder::CreateAssignment(int indent, + CG_outputRepr *lhs, + CG_outputRepr *rhs) const { + if (lhs == NULL || rhs == NULL) + throw std::invalid_argument("missing lhs or rhs in assignment"); - -CG_stringRepr *CG_stringBuilder::CreateComment(int indent, const std::string &commentText) const { - if (commentText == std::string("")) { - return NULL; + std::string lhsStr = GetString(lhs); + std::string rhsStr = GetString(rhs); + + std::string indentStr = GetIndentSpaces(indent); + + return new CG_stringRepr(indentStr + lhsStr + "=" + rhsStr + ";\n"); } + + + CG_stringRepr *CG_stringBuilder::CreatePlusAssignment(int indent, + CG_outputRepr *lhs, + CG_outputRepr *rhs) const { + if (lhs == NULL || rhs == NULL) + throw std::invalid_argument("missing lhs or rhs in assignment"); + + std::string lhsStr = GetString(lhs); + std::string rhsStr = GetString(rhs); + + std::string indentStr = GetIndentSpaces(indent); + + return new CG_stringRepr(indentStr + lhsStr + "+=" + rhsStr + ";\n"); + } + + + + CG_stringRepr *CG_stringBuilder::CreateAddressOf(CG_outputRepr *op) const { + if (op == NULL) + throw std::invalid_argument("missining op in create address of"); + + std::string opStr = GetString(op); + + + return new CG_stringRepr( "&" + opStr); + } + + + CG_stringRepr *CG_stringBuilder::CreateInvoke(const std::string &funcName, + std::vector<CG_outputRepr *> &list, + bool is_array) const { + fprintf(stderr, "CG_stringBuilder::CreateInvoke( %s, ..., is_array ", funcName.c_str()); + if (is_array) fprintf(stderr, " true )\n"); + else fprintf(stderr, " false )\n"); - std::string indentStr = GetIndentSpaces(indent); - - return new CG_stringRepr(indentStr + "// " + commentText + "\n"); -} - -CG_stringRepr* CG_stringBuilder::CreateAttribute(CG_outputRepr *control, - const std::string &commentText) const { - if (commentText == std::string("")) { - return static_cast<CG_stringRepr *> (control); - } - std::string controlString = GetString(control); + std::string listStr = ""; + + fprintf(stderr, "list has %d elements\n", list.size()); - return new CG_stringRepr("// " + commentText + "\n" + controlString); + for (int i = 0; i < list.size(); i++) { + fprintf(stderr, "accessing list[%d]\n", i); + listStr += GetString(list[i]); + if ( i < list.size()-1) + listStr += ","; + } -} + fprintf(stderr, "returning %s\n", (funcName + "(" + listStr + ")").c_str()); + return new CG_stringRepr(funcName + "(" + listStr + ")"); + } + + + CG_stringRepr *CG_stringBuilder::CreateComment(int indent, const std::string &commentText) const { + if (commentText == std::string("")) { + return NULL; + } + + std::string indentStr = GetIndentSpaces(indent); + + return new CG_stringRepr(indentStr + "// " + commentText + "\n"); + } + -CG_outputRepr* CG_stringBuilder::CreatePragmaAttribute(CG_outputRepr *scopeStmt, int looplevel, const std::string &pragmaText) const { - // -- Not Implemented - return scopeStmt; -} -CG_outputRepr* CG_stringBuilder::CreatePrefetchAttribute(CG_outputRepr* scopeStmt, int looplevel, const std::string& arrName, int hint) const { - // -- Not Implemented - return scopeStmt; -} + CG_stringRepr* CG_stringBuilder::CreateAttribute(CG_outputRepr *control, + const std::string &commentText) const { + + //fprintf(stderr, "CG_stringBuilder::CreateAttribute( jkadskjh, '%s')\n", commentText.c_str()); -CG_stringRepr *CG_stringBuilder::CreateIf(int indent, CG_outputRepr *guardList, - CG_outputRepr *true_stmtList, CG_outputRepr *false_stmtList) const { - if (guardList == NULL) - throw std::invalid_argument("missing if condition"); + if (commentText == std::string("")) { + return static_cast<CG_stringRepr *> (control); + } + + std::string controlString = GetString(control); + + std::string spaces = ""; + const char *con = controlString.c_str(); + const char *ptr = con; + while (*ptr++ == ' ') spaces = spaces + " "; + return new CG_stringRepr(spaces + "// " + commentText + "\n" + controlString); + + } - if (true_stmtList == NULL && false_stmtList == NULL) { - delete guardList; - return NULL; + CG_outputRepr* CG_stringBuilder::CreatePragmaAttribute(CG_outputRepr *scopeStmt, int looplevel, const std::string &pragmaText) const { + // -- Not Implemented + return scopeStmt; } - - std::string guardListStr = GetString(guardList); - std::string indentStr = GetIndentSpaces(indent); - std::string s; - if (true_stmtList != NULL && false_stmtList == NULL) { - s = indentStr + "if (" + guardListStr + ") {\n" - + GetString(true_stmtList) - + indentStr + "}\n"; + + CG_outputRepr* CG_stringBuilder::CreatePrefetchAttribute(CG_outputRepr* scopeStmt, int looplevel, const std::string& arrName, int hint) const { + // -- Not Implemented + return scopeStmt; } - else if (true_stmtList == NULL && false_stmtList != NULL) { - s = indentStr + "if !(" + guardListStr + ") {\n" - + GetString(false_stmtList) - + indentStr + "}\n"; + + + + + CG_stringRepr *CG_stringBuilder::CreateBreakStatement(void) const { + std::string s= "break;\n"; + return new CG_stringRepr(s); + } + + + + CG_stringRepr *CG_stringBuilder::CreateIf(int indent, CG_outputRepr *guardList, + CG_outputRepr *true_stmtList, CG_outputRepr *false_stmtList) const { + if (guardList == NULL) + throw std::invalid_argument("missing if condition"); + + if (true_stmtList == NULL && false_stmtList == NULL) { + delete guardList; + return NULL; + } + + std::string guardListStr = GetString(guardList); + std::string indentStr = GetIndentSpaces(indent); + std::string s; + if (true_stmtList != NULL && false_stmtList == NULL) { + s = indentStr + "if (" + guardListStr + ") {\n" + + GetString(true_stmtList) + + indentStr + "}\n"; + } + else if (true_stmtList == NULL && false_stmtList != NULL) { + s = indentStr + "if !(" + guardListStr + ") {\n" + + GetString(false_stmtList) + + indentStr + "}\n"; + } + else { + s = indentStr + "if (" + guardListStr + ") {\n" + + GetString(true_stmtList) + + indentStr + "}\n" + + indentStr + "else {\n" + + GetString(false_stmtList) + + indentStr + "}\n"; + } + + return new CG_stringRepr(s); } - else { - s = indentStr + "if (" + guardListStr + ") {\n" - + GetString(true_stmtList) - + indentStr + "}\n" - + indentStr + "else {\n" - + GetString(false_stmtList) + + + + CG_stringRepr *CG_stringBuilder::CreateInductive(CG_outputRepr *index, + CG_outputRepr *lower, CG_outputRepr *upper, + CG_outputRepr *step) const { + if (index == NULL) + throw std::invalid_argument("missing loop index"); + if (lower == NULL) + throw std::invalid_argument("missing loop lower bound"); + if (upper == NULL) + throw std::invalid_argument("missing loop upper bound"); + //if (step == NULL) + // throw std::invalid_argument("missing loop step size"); + + std::string indexStr = GetString(index); + std::string lowerStr = GetString(lower); + std::string upperStr = GetString(upper); + + std::string doStr = "for(" + indexStr + " = " + lowerStr + "; " + + indexStr + " <= " + upperStr + "; " + + indexStr; + + if (step != NULL) { + std::string stepStr = GetString(step); + if (stepStr == to_string(1)) + doStr += "++"; + else + doStr += " += " + stepStr; + } + else + doStr += "++"; // a default ?? + doStr += ")"; + + return new CG_stringRepr(doStr); + } + + + CG_stringRepr *CG_stringBuilder::CreateLoop(int indent, CG_outputRepr *control, + CG_outputRepr *stmtList) const { + if (stmtList == NULL) { + delete control; + return NULL; + } + else if (control == NULL) + return static_cast<CG_stringRepr *>(stmtList); + + std::string ctrlStr = GetString(control); + std::string stmtStr = GetString(stmtList); + + std::string indentStr = GetIndentSpaces(indent); + + std::string s = indentStr + ctrlStr + " {\n" + + stmtStr + indentStr + "}\n"; + + return new CG_stringRepr(s); } - return new CG_stringRepr(s); -} - - - -CG_stringRepr *CG_stringBuilder::CreateInductive(CG_outputRepr *index, - CG_outputRepr *lower, CG_outputRepr *upper, - CG_outputRepr *step) const { - if (index == NULL) - throw std::invalid_argument("missing loop index"); - if (lower == NULL) - throw std::invalid_argument("missing loop lower bound"); - if (upper == NULL) - throw std::invalid_argument("missing loop upper bound"); - if (step == NULL) - throw std::invalid_argument("missing loop step size"); - - std::string indexStr = GetString(index); - std::string lowerStr = GetString(lower); - std::string upperStr = GetString(upper); - - std::string doStr = "for(" + indexStr + " = " + lowerStr + "; " - + indexStr + " <= " + upperStr + "; " - + indexStr; - - std::string stepStr = GetString(step); - if (stepStr == to_string(1)) - doStr += "++"; - else - doStr += " += " + stepStr; - - doStr += ")"; - - return new CG_stringRepr(doStr); -} - - -CG_stringRepr *CG_stringBuilder::CreateLoop(int indent, CG_outputRepr *control, - CG_outputRepr *stmtList) const { - if (stmtList == NULL) { - delete control; - return NULL; - } - else if (control == NULL) - return static_cast<CG_stringRepr *>(stmtList); - - std::string ctrlStr = GetString(control); - std::string stmtStr = GetString(stmtList); - - std::string indentStr = GetIndentSpaces(indent); - - std::string s = indentStr + ctrlStr + " {\n" - + stmtStr - + indentStr + "}\n"; - - return new CG_stringRepr(s); -} - - - -CG_stringRepr *CG_stringBuilder::CreateInt(int num) const { - std::string s = to_string(num); - return new CG_stringRepr(s); -} - - - -bool CG_stringBuilder::isInteger(CG_outputRepr *op) const { - - char * cstr; - std::string s = GetString(op); - cstr = new char [s.size()+1]; - strcpy (cstr, s.c_str()); - int count = 0; - while(cstr[count] != '\n' && cstr[count] != '\0' ) - if( !isdigit(cstr[count])) - return false; - - - return true; -} - - - -CG_stringRepr *CG_stringBuilder::CreateIdent(const std::string &varName) const { - if (varName == std::string("")) { - return NULL; + + + CG_stringRepr *CG_stringBuilder::CreateInt(int num) const { + std::string s = to_string(num); + return new CG_stringRepr(s); } - - return new CG_stringRepr(varName); -} - - -CG_stringRepr *CG_stringBuilder::CreatePlus(CG_outputRepr *lop, CG_outputRepr *rop) const { - if (rop == NULL) { - return static_cast<CG_stringRepr *>(lop); + + CG_stringRepr *CG_stringBuilder::CreateFloat(float num) const { + std::string s = to_string(num); + return new CG_stringRepr(s); } - else if (lop == NULL) { - return static_cast<CG_stringRepr *>(rop); + + CG_stringRepr *CG_stringBuilder::CreateDouble(double num) const { + std::string s = to_string(num); + return new CG_stringRepr(s); } - - std::string lopStr = GetString(lop); - std::string ropStr = GetString(rop); - - return new CG_stringRepr(lopStr + "+" + ropStr); -} - - -CG_stringRepr *CG_stringBuilder::CreateMinus(CG_outputRepr *lop, CG_outputRepr *rop) const { - if (rop == NULL) { - return static_cast<CG_stringRepr *>(lop); + + + + bool CG_stringBuilder::isInteger(CG_outputRepr *op) const { + + char * cstr; + std::string s = GetString(op); + cstr = new char [s.size()+1]; + strcpy (cstr, s.c_str()); + int count = 0; + while(cstr[count] != '\n' && cstr[count] != '\0' ) + if( !isdigit(cstr[count])) + return false; + + + return true; + } + + bool CG_stringBuilder::QueryInspectorType(const std::string &varName) const{ + if (varName == std::string("index")) { // special cased? ?????? TODO + return true; + } + return false; + } + + CG_stringRepr* CG_stringBuilder::ObtainInspectorData(const std::string &_s, const std::string &member_name) const { + return new CG_stringRepr(_s); + } + + + + CG_stringRepr *CG_stringBuilder::CreateIdent(const std::string &varName) const { + if (varName == std::string("")) { + return NULL; + } + + return new CG_stringRepr(varName); + } + + + CG_stringRepr* CG_stringBuilder::CreateDotExpression(CG_outputRepr *lop, + CG_outputRepr *rop) const { + + std::string op1 = GetString(lop); + std::string op2 = GetString(rop); + + std::string s = op1 + "." + op2; + return new CG_stringRepr(s); + } + + + + CG_stringRepr* CG_stringBuilder::CreateNullStatement() const{ + return new CG_stringRepr(""); + } + + + + CG_stringRepr* CG_stringBuilder::CreateArrayRefExpression(const std::string &_s, + CG_outputRepr *rop) const { + if (_s == std::string("")) { + return NULL; + } + + std::string refStr = GetString(rop); + //std::string s = _s + "[" + refStr + "]"; + + return new CG_stringRepr( _s + "[" + refStr + "]"); } - else if (lop == NULL) { + + + + CG_stringRepr* CG_stringBuilder::CreateArrayRefExpression(CG_outputRepr *lop, + CG_outputRepr *rop) const { + + std::string refStr1 = GetString(lop); + std::string refStr2 = GetString(rop); + //std::string s = _s + "[" + refStr + "]"; + + return new CG_stringRepr( refStr1 + "[" + refStr2 + "]"); + + } + + + + CG_stringRepr *CG_stringBuilder::CreatePlus(CG_outputRepr *lop, CG_outputRepr *rop) const { + if (rop == NULL) { + return static_cast<CG_stringRepr *>(lop); + } + else if (lop == NULL) { + return static_cast<CG_stringRepr *>(rop); + } + + std::string lopStr = GetString(lop); std::string ropStr = GetString(rop); - return new CG_stringRepr("-" + SafeguardString(ropStr, '-')); + + return new CG_stringRepr(lopStr + "+" + ropStr); } - - std::string lopStr = GetString(lop); - std::string ropStr = GetString(rop); - - return new CG_stringRepr(lopStr + "-" + SafeguardString(ropStr, '-')); -} - - -CG_stringRepr *CG_stringBuilder::CreateTimes(CG_outputRepr *lop, CG_outputRepr *rop) const { - if (rop == NULL || lop == NULL) { - delete rop; - delete lop; - return NULL; + + + CG_stringRepr *CG_stringBuilder::CreateMinus(CG_outputRepr *lop, CG_outputRepr *rop) const { + if (rop == NULL) { + return static_cast<CG_stringRepr *>(lop); + } + else if (lop == NULL) { + std::string ropStr = GetString(rop); + return new CG_stringRepr("-" + SafeguardString(ropStr, '-')); + } + + std::string lopStr = GetString(lop); + std::string ropStr = GetString(rop); + + return new CG_stringRepr(lopStr + "-" + SafeguardString(ropStr, '-')); } - - std::string lopStr = GetString(lop); - std::string ropStr = GetString(rop); - - return new CG_stringRepr(SafeguardString(lopStr, '*') + "*" + SafeguardString(ropStr, '*')); -} - - -CG_stringRepr *CG_stringBuilder::CreateDivide(CG_outputRepr *lop, CG_outputRepr *rop) const { - if (rop == NULL) - throw codegen_error("integer division by zero"); - else if (lop == NULL) { - delete rop; - return NULL; + + + CG_stringRepr *CG_stringBuilder::CreateTimes(CG_outputRepr *lop, CG_outputRepr *rop) const { + if (rop == NULL || lop == NULL) { + delete rop; + delete lop; + return NULL; + } + + std::string lopStr = GetString(lop); + std::string ropStr = GetString(rop); + + return new CG_stringRepr(SafeguardString(lopStr, '*') + "*" + SafeguardString(ropStr, '*')); } - - std::string lopStr = GetString(lop); - std::string ropStr = GetString(rop); - - return new CG_stringRepr(SafeguardString(lopStr, '/') + "/" + SafeguardString(ropStr, '/')); -} - - -CG_stringRepr *CG_stringBuilder::CreateIntegerFloor(CG_outputRepr *lop, CG_outputRepr *rop) const { - if (rop == NULL) - throw codegen_error("integer division by zero"); - else if (lop == NULL) { - delete rop; - return NULL; + + + CG_stringRepr *CG_stringBuilder::CreateDivide(CG_outputRepr *lop, CG_outputRepr *rop) const { + if (rop == NULL) + throw codegen_error("integer division by zero"); + else if (lop == NULL) { + delete rop; + return NULL; + } + + std::string lopStr = GetString(lop); + std::string ropStr = GetString(rop); + + return new CG_stringRepr(SafeguardString(lopStr, '/') + "/" + SafeguardString(ropStr, '/')); } - - std::string lopStr = GetString(lop); - std::string ropStr = GetString(rop); - - return new CG_stringRepr("intFloor(" + lopStr + "," + ropStr + ")"); -} - - -CG_stringRepr *CG_stringBuilder::CreateIntegerMod(CG_outputRepr *lop, CG_outputRepr *rop) const { - if (rop == NULL) - throw codegen_error("integer modulo by zero"); - else if (lop == NULL) { - delete rop; - return NULL; + + + CG_stringRepr *CG_stringBuilder::CreateIntegerFloor(CG_outputRepr *lop, CG_outputRepr *rop) const { + if (rop == NULL) + throw codegen_error("integer division by zero"); + else if (lop == NULL) { + delete rop; + return NULL; + } + + std::string lopStr = GetString(lop); + std::string ropStr = GetString(rop); + + return new CG_stringRepr("intFloor(" + lopStr + "," + ropStr + ")"); } - - std::string lopStr = GetString(lop); - std::string ropStr = GetString(rop); - - return new CG_stringRepr("intMod(" + lopStr + "," + ropStr + ")"); -} - -CG_stringRepr *CG_stringBuilder::CreateIntegerCeil(CG_outputRepr *lop, CG_outputRepr *rop) const { - if (rop == 0) - throw codegen_error("integer ceiling by zero"); - else if (lop == NULL) { - delete rop; - return NULL; + + + CG_stringRepr *CG_stringBuilder::CreateIntegerMod(CG_outputRepr *lop, CG_outputRepr *rop) const { + if (rop == NULL) + throw codegen_error("integer modulo by zero"); + else if (lop == NULL) { + delete rop; + return NULL; + } + + std::string lopStr = GetString(lop); + std::string ropStr = GetString(rop); + + return new CG_stringRepr("intMod(" + lopStr + "," + ropStr + ")"); } - - std::string lopStr = GetString(lop); - std::string ropStr = GetString(rop); - - return new CG_stringRepr("intCeil(" + lopStr + "," + ropStr + ")"); -} - - -CG_stringRepr *CG_stringBuilder::CreateAnd(CG_outputRepr *lop, CG_outputRepr *rop) const { - if (rop == NULL) - return static_cast<CG_stringRepr *>(lop); - else if (lop == NULL) - return static_cast<CG_stringRepr *>(rop); - - std::string lopStr = GetString(lop); - std::string ropStr = GetString(rop); - - return new CG_stringRepr(lopStr + " && " + ropStr); -} - - -CG_stringRepr *CG_stringBuilder::CreateGE(CG_outputRepr *lop, CG_outputRepr *rop) const { - if (rop == NULL || lop == NULL) - throw std::invalid_argument("missing operand in greater than equal comparison condition"); - - std::string lopStr = GetString(lop); - std::string ropStr = GetString(rop); - - return new CG_stringRepr(lopStr + " >= " + ropStr); -} - - - -CG_stringRepr *CG_stringBuilder::CreateLE(CG_outputRepr *lop, CG_outputRepr *rop) const { - if (rop == NULL || lop == NULL) - throw std::invalid_argument("missing operand in less than equal comparison condition"); - - std::string lopStr = GetString(lop); - std::string ropStr = GetString(rop); - - return new CG_stringRepr(lopStr + " <= " + ropStr); -} - - - -CG_stringRepr *CG_stringBuilder::CreateEQ(CG_outputRepr *lop, CG_outputRepr *rop) const { - if (rop == NULL || lop == NULL) - throw std::invalid_argument("missing operand in equal comparison condition"); - - std::string lopStr = GetString(lop); - std::string ropStr = GetString(rop); - - return new CG_stringRepr(lopStr + " == " + ropStr); -} - - - -CG_stringRepr *CG_stringBuilder::StmtListAppend(CG_outputRepr *list1, CG_outputRepr *list2) const { - if (list2 == NULL) { - return static_cast<CG_stringRepr *>(list1); + + CG_stringRepr *CG_stringBuilder::CreateIntegerCeil(CG_outputRepr *lop, CG_outputRepr *rop) const { + if (rop == 0) + throw codegen_error("integer ceiling by zero"); + else if (lop == NULL) { + delete rop; + return NULL; + } + + std::string lopStr = GetString(lop); + std::string ropStr = GetString(rop); + + return new CG_stringRepr("intCeil(" + lopStr + "," + ropStr + ")"); + } + + + CG_stringRepr *CG_stringBuilder::CreateAnd(CG_outputRepr *lop, CG_outputRepr *rop) const { + if (rop == NULL) + return static_cast<CG_stringRepr *>(lop); + else if (lop == NULL) + return static_cast<CG_stringRepr *>(rop); + + std::string lopStr = GetString(lop); + std::string ropStr = GetString(rop); + + return new CG_stringRepr(lopStr + " && " + ropStr); + } + + + CG_stringRepr *CG_stringBuilder::CreateGE(CG_outputRepr *lop, CG_outputRepr *rop) const { + if (rop == NULL || lop == NULL) + throw std::invalid_argument("missing operand in greater than equal comparison condition"); + + std::string lopStr = GetString(lop); + std::string ropStr = GetString(rop); + + return new CG_stringRepr(lopStr + " >= " + ropStr); + } + + + + CG_stringRepr *CG_stringBuilder::CreateLE(CG_outputRepr *lop, CG_outputRepr *rop) const { + if (rop == NULL || lop == NULL) + throw std::invalid_argument("missing operand in less than equal comparison condition"); + + std::string lopStr = GetString(lop); + std::string ropStr = GetString(rop); + + return new CG_stringRepr(lopStr + " <= " + ropStr); + } + + + + CG_stringRepr *CG_stringBuilder::CreateEQ(CG_outputRepr *lop, CG_outputRepr *rop) const { + if (rop == NULL || lop == NULL) + throw std::invalid_argument("missing operand in equal comparison condition"); + + std::string lopStr = GetString(lop); + std::string ropStr = GetString(rop); + + return new CG_stringRepr(lopStr + " == " + ropStr); + } + + + CG_stringRepr *CG_stringBuilder::CreateNEQ(CG_outputRepr *lop, CG_outputRepr *rop) const { + if (rop == NULL || lop == NULL) + throw std::invalid_argument("missing operand in equal comparison condition"); + + std::string lopStr = GetString(lop); + std::string ropStr = GetString(rop); + + return new CG_stringRepr(lopStr + " != " + ropStr); + } + + + + CG_stringRepr *CG_stringBuilder::StmtListAppend(CG_outputRepr *list1, CG_outputRepr *list2) const { + if (list2 == NULL) { + return static_cast<CG_stringRepr *>(list1); + } + else if (list1 == NULL) { + return static_cast<CG_stringRepr *>(list2); + } + + std::string list1Str = GetString(list1); + std::string list2Str = GetString(list2); + + return new CG_stringRepr(list1Str + list2Str); } - else if (list1 == NULL) { - return static_cast<CG_stringRepr *>(list2); + + CG_outputRepr *CG_stringBuilder::CreateStruct(const std::string struct_name, + std::vector<std::string> data_members, + std::vector<CG_outputRepr *> data_types) + { + fprintf(stderr, "CG_stringBuilder::CreateStruct( %s )\n", struct_name.c_str()); + fprintf(stderr, "that makes no sense\n"); + exit(0); + } + + CG_outputRepr *CG_stringBuilder::CreateClassInstance(std::string name , + CG_outputRepr *class_def){ + fprintf(stderr, "CG_stringBuilder::CreateClassInstance( %s )\n", name.c_str()); + exit(0); + + } + + CG_outputRepr *CG_stringBuilder::lookup_member_data(CG_outputRepr* scope, + std::string varName, + CG_outputRepr *instance) { + fprintf(stderr, "CG_stringBuilder::lookup_member_data( )\n"); + exit(0); + } + + CG_outputRepr* CG_stringBuilder::CreatePointer(std::string &name) const { + fprintf(stderr, "CG_chillBuilder::CreatePointer( %s )\n", name.c_str()); + exit(0); } - std::string list1Str = GetString(list1); - std::string list2Str = GetString(list2); + CG_outputRepr* CG_stringBuilder::ObtainInspectorRange(const std::string &_s, const std::string &_name) const { + fprintf(stderr, "CG_stringBuilder::ObtainInspectorRange(%s, %s )\n", _s.c_str(), _name.c_str()); + exit(0); + } - return new CG_stringRepr(list1Str + list2Str); -} + } diff --git a/lib/codegen/src/CG_stringRepr.cc b/lib/codegen/src/CG_stringRepr.cc new file mode 100755 index 0000000..f1a7cad --- /dev/null +++ b/lib/codegen/src/CG_stringRepr.cc @@ -0,0 +1,32 @@ +/***************************************************************************** + Copyright (C) 1994-2000 University of Maryland + Copyright (C) 2008 University of Southern California + Copyright (C) 2009 University of Utah + All Rights Reserved. + + Purpose: + omega holder for string implementation. + + Notes: + + History: + 04/17/96 - Lei Zhou - created +*****************************************************************************/ + + +#include <code_gen/CG_stringRepr.h> +#include <stdio.h> +#include <string.h> + +namespace omega { + + //----------------------------------------------------------------------------- + // Dump operations + //----------------------------------------------------------------------------- + void CG_stringRepr::Dump() const { dump(); } // TODO combine dump() and Dump() + + void CG_stringRepr::DumpToFile(FILE *fp) const { + fprintf(fp,"%s", s_.c_str()); + } + +} // namespace diff --git a/lib/codegen/src/CG_utils.cc b/lib/codegen/src/CG_utils.cc index d3a5f71..19bb6c9 100755 --- a/lib/codegen/src/CG_utils.cc +++ b/lib/codegen/src/CG_utils.cc @@ -7,7 +7,7 @@ Utility functions for processing CG tree. Notes: - + History: 07/19/07 when generating output variable substitutions for a mapping relation, map it to each output to get correct equality, -chun @@ -24,309 +24,456 @@ #include <stack> namespace omega { - -int checkLoopLevel; -int stmtForLoopCheck; -int upperBoundForLevel; -int lowerBoundForLevel; -bool fillInBounds; - + + int checkLoopLevel; + int stmtForLoopCheck; + int upperBoundForLevel; + int lowerBoundForLevel; + bool fillInBounds; + //trick to static init checkLoopLevel to 0 -class JunkStaticInit{ public: JunkStaticInit(){ checkLoopLevel=0; fillInBounds=false;} }; -static JunkStaticInit junkInitInstance__; - - - - -namespace { - -Relation find_best_guard(const Relation &R, const BoolSet<> &active, const std::map<int, Relation> &guards) { - std::pair<int, int> best_cost = std::make_pair(0, 0); - Relation best_cond = Relation::True(R.n_set()); + class JunkStaticInit{ + public: + JunkStaticInit(){ checkLoopLevel=0; fillInBounds=false;} + }; + static JunkStaticInit junkInitInstance__; - Relation r = copy(R); - int max_iter_count = 2*(r.single_conjunct()->n_EQs()) + r.single_conjunct()->n_GEQs(); - int iter_count = 0; - while (!r.is_obvious_tautology()) { - std::pair<int, int> cost = std::make_pair(0, 0); - Relation cond = pick_one_guard(r); - Relation complement_cond = Complement(copy(cond)); - complement_cond.simplify(); - for (BoolSet<>::const_iterator i = active.begin(); i != active.end(); i++) { - std::map<int, Relation>::const_iterator j = guards.find(*i); - if (j == guards.end()) - continue; - if (Must_Be_Subset(copy(j->second), copy(cond))) - cost.first++; - else if (Must_Be_Subset(copy(j->second), copy(complement_cond))) - cost.second++; - } - if (cost > best_cost) { - best_cost = cost; - best_cond = copy(cond); - } - r = Gist(r, cond, 1); - - if (iter_count > max_iter_count) - throw codegen_error("guard condition too complex to handle"); - - iter_count++; - } - - return best_cond; -} - - -Relation find_best_guard(const Relation &R, const std::vector<CG_loop *> &loops, int start, int end) { - std::pair<int, int> best_cost = std::make_pair(0, 0); - Relation best_cond = Relation::True(R.n_set()); - Relation r = copy(R); - int max_iter_count = 2*(r.single_conjunct()->n_EQs()) + r.single_conjunct()->n_GEQs(); - int iter_count = 0; - while (!r.is_obvious_tautology()) { - std::pair<int, int> cost = std::make_pair(0, 0); - Relation cond = pick_one_guard(r); - int i = start; - for ( ; i < end; i++) { - if (Must_Be_Subset(copy(loops[i]->guard_), copy(cond))) - cost.first++; - else - break; - } - Relation complement_cond = Complement(copy(cond)); - complement_cond.simplify(); - for (int j = i; j < end; j++) - if (Must_Be_Subset(copy(loops[j]->guard_), copy(complement_cond))) - cost.second++; - else - break; - - if (cost > best_cost) { - best_cost = cost; - best_cond = copy(cond); - } - r = Gist(r, cond, 1); - - if (iter_count > max_iter_count) - throw codegen_error("guard condition too complex to handle"); - - iter_count++; - } - - return best_cond; -} - -} - -bool bound_must_hit_stride(const GEQ_Handle &inequality, Variable_ID v, const EQ_Handle &stride_eq, Variable_ID wc, const Relation &bounds, const Relation &known) { - assert(inequality.get_coef(v) != 0 && abs(stride_eq.get_coef(v)) == 1 && wc->kind() == Wildcard_Var && abs(stride_eq.get_coef(wc)) > 1); - - // if bound expression uses floor operation, bail out for now - // TODO: in the future, handle this - if (abs(inequality.get_coef(v)) != 1) - return false; - coef_t stride = abs(stride_eq.get_coef(wc)); - Relation r1(known.n_set()); - F_Exists *f_exists1 = r1.add_and()->add_exists(); - F_And *f_root1 = f_exists1->add_and(); - std::map<Variable_ID, Variable_ID> exists_mapping1; - EQ_Handle h1 = f_root1->add_EQ(); - Relation r2(known.n_set()); - F_Exists *f_exists2 = r2.add_and()->add_exists(); - F_And *f_root2 = f_exists2->add_and(); - std::map<Variable_ID, Variable_ID> exists_mapping2; - EQ_Handle h2 = f_root2->add_EQ(); - for (Constr_Vars_Iter cvi(inequality); cvi; cvi++) { - Variable_ID v = cvi.curr_var(); - switch (v->kind()) { - case Input_Var: - h1.update_coef(r1.input_var(v->get_position()), cvi.curr_coef()); - h2.update_coef(r2.input_var(v->get_position()), cvi.curr_coef()); - break; - case Global_Var: { - Global_Var_ID g = v->get_global_var(); - Variable_ID v1, v2; - if (g->arity() == 0) { - v1 = r1.get_local(g); - v2 = r2.get_local(g); - } - else { - v1 = r1.get_local(g, v->function_of()); - v2 = r2.get_local(g, v->function_of()); + namespace { + + Relation find_best_guard(const Relation &R, const BoolSet<> &active, const std::map<int, Relation> &guards) { + std::pair<int, int> best_cost = std::make_pair(0, 0); + Relation best_cond = Relation::True(R.n_set()); + + Relation r = copy(R); + int max_iter_count = 2*(r.single_conjunct()->n_EQs()) + r.single_conjunct()->n_GEQs(); + int iter_count = 0; + while (!r.is_obvious_tautology()) { + std::pair<int, int> cost = std::make_pair(0, 0); + Relation cond = pick_one_guard(r); + Relation complement_cond = Complement(copy(cond)); + complement_cond.simplify(); + for (BoolSet<>::const_iterator i = active.begin(); i != active.end(); i++) { + std::map<int, Relation>::const_iterator j = guards.find(*i); + if (j == guards.end()) + continue; + if (Must_Be_Subset(copy(j->second), copy(cond))) + cost.first++; + else if (Must_Be_Subset(copy(j->second), copy(complement_cond))) + cost.second++; + } + if (cost > best_cost) { + best_cost = cost; + best_cond = copy(cond); + } + r = Gist(r, cond, 1); + + if (iter_count > max_iter_count) { + //Relation s = copy(R); + //s.simplify(2,4); + //return s; + throw codegen_error("guard condition too complex to handle"); + } + + iter_count++; } - h1.update_coef(v1, cvi.curr_coef()); - h2.update_coef(v2, cvi.curr_coef()); - break; - } - case Wildcard_Var: { - Variable_ID v1 = replicate_floor_definition(bounds, v, r1, f_exists1, f_root1, exists_mapping1); - Variable_ID v2 = replicate_floor_definition(bounds, v, r2, f_exists2, f_root2, exists_mapping2); - h1.update_coef(v1, cvi.curr_coef()); - h2.update_coef(v2, cvi.curr_coef()); - break; + + return best_cond; } - default: - assert(false); + + + Relation find_best_guard(const Relation &R, const std::vector<CG_loop *> &loops, int start, int end) { + std::pair<int, int> best_cost = std::make_pair(0, 0); + Relation best_cond = Relation::True(R.n_set()); + + Relation r = copy(R); + int max_iter_count = 2*(r.single_conjunct()->n_EQs()) + + r.single_conjunct()->n_GEQs(); + int iter_count = 0; + while (!r.is_obvious_tautology()) { + std::pair<int, int> cost = std::make_pair(0, 0); + + // was Relation cond = pick_one_guard(r); + Relation cond = pick_one_guard(r,loops[start]->level_); + int i = start; + for ( ; i < end; i++) { + if (Must_Be_Subset(copy(loops[i]->guard_), copy(cond))) + cost.first++; + else + break; + } + Relation complement_cond = Complement(copy(cond)); + complement_cond.simplify(); + for (int j = i; j < end; j++) + if (Must_Be_Subset(copy(loops[j]->guard_), copy(complement_cond))) + cost.second++; + else + break; + + if (cost > best_cost) { + best_cost = cost; + best_cond = copy(cond); + } + r = Gist(r, cond, 1); + + if (iter_count > max_iter_count) + throw codegen_error("guard condition too complex to handle"); + + iter_count++; + } + + return best_cond; } + } - h1.update_const(inequality.get_const()); - h1.update_coef(f_exists1->declare(), stride); - h2.update_const(inequality.get_const()); - r1.simplify(); - r2.simplify(); + - Relation all_known = Intersection(copy(bounds), copy(known)); - all_known.simplify(); - if (Gist(r1, copy(all_known), 1).is_obvious_tautology()) { - Relation r3(known.n_set()); - F_Exists *f_exists3 = r3.add_and()->add_exists(); - F_And *f_root3 = f_exists3->add_and(); - std::map<Variable_ID, Variable_ID> exists_mapping3; - EQ_Handle h3 = f_root3->add_EQ(); - for (Constr_Vars_Iter cvi(stride_eq); cvi; cvi++) { - Variable_ID v= cvi.curr_var(); + + bool bound_must_hit_stride(const GEQ_Handle &inequality, + Variable_ID v, + const EQ_Handle &stride_eq, + Variable_ID wc, + const Relation &bounds, + const Relation &known) { + assert(inequality.get_coef(v) != 0 + && abs(stride_eq.get_coef(v)) == 1 + && wc->kind() == Wildcard_Var + && abs(stride_eq.get_coef(wc)) > 1); + + // if bound expression uses floor operation, bail out for now + // TODO: in the future, handle this + if (abs(inequality.get_coef(v)) != 1) + return false; + + coef_t stride = abs(stride_eq.get_coef(wc)); + + Relation r1(known.n_set()); + F_Exists *f_exists1 = r1.add_and()->add_exists(); + F_And *f_root1 = f_exists1->add_and(); + std::map<Variable_ID, Variable_ID> exists_mapping1; + EQ_Handle h1 = f_root1->add_EQ(); + Relation r2(known.n_set()); + F_Exists *f_exists2 = r2.add_and()->add_exists(); + F_And *f_root2 = f_exists2->add_and(); + std::map<Variable_ID, Variable_ID> exists_mapping2; + EQ_Handle h2 = f_root2->add_EQ(); + for (Constr_Vars_Iter cvi(inequality); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); switch (v->kind()) { - case Input_Var: - h3.update_coef(r3.input_var(v->get_position()), cvi.curr_coef()); + case Input_Var: + h1.update_coef(r1.input_var(v->get_position()), cvi.curr_coef()); + h2.update_coef(r2.input_var(v->get_position()), cvi.curr_coef()); break; - case Global_Var: { + case Global_Var: { Global_Var_ID g = v->get_global_var(); - Variable_ID v3; - if (g->arity() == 0) - v3 = r3.get_local(g); - else - v3 = r3.get_local(g, v->function_of()); - h3.update_coef(v3, cvi.curr_coef()); - break; - } - case Wildcard_Var: - if (v == wc) - h3.update_coef(f_exists3->declare(), cvi.curr_coef()); + Variable_ID v1, v2; + if (g->arity() == 0) { + v1 = r1.get_local(g); + v2 = r2.get_local(g); + } else { - Variable_ID v3 = replicate_floor_definition(bounds, v, r3, f_exists3, f_root3, exists_mapping3); - h3.update_coef(v3, cvi.curr_coef()); + v1 = r1.get_local(g, v->function_of()); + v2 = r2.get_local(g, v->function_of()); } + h1.update_coef(v1, cvi.curr_coef()); + h2.update_coef(v2, cvi.curr_coef()); break; + } + case Wildcard_Var: { + Variable_ID v1 = replicate_floor_definition(bounds, + v, + r1, + f_exists1, + f_root1, + exists_mapping1); + Variable_ID v2 = replicate_floor_definition(bounds, + v, + r2, + f_exists2, + f_root2, + exists_mapping2); + h1.update_coef(v1, cvi.curr_coef()); + h2.update_coef(v2, cvi.curr_coef()); + break; + } default: assert(false); } } - h3.update_const(stride_eq.get_const()); - r3.simplify(); + h1.update_const(inequality.get_const()); + h1.update_coef(f_exists1->declare(), stride); + h2.update_const(inequality.get_const()); + r1.simplify(); + r2.simplify(); - if (Gist(r3, Intersection(r2, all_known), 1).is_obvious_tautology()) - return true; - else + Relation all_known = Intersection(copy(bounds), copy(known)); + all_known.simplify(); + + if (Gist(r1, copy(all_known), 1).is_obvious_tautology()) { + Relation r3(known.n_set()); + F_Exists *f_exists3 = r3.add_and()->add_exists(); + F_And *f_root3 = f_exists3->add_and(); + std::map<Variable_ID, Variable_ID> exists_mapping3; + EQ_Handle h3 = f_root3->add_EQ(); + for (Constr_Vars_Iter cvi(stride_eq); cvi; cvi++) { + Variable_ID v= cvi.curr_var(); + switch (v->kind()) { + case Input_Var: + h3.update_coef(r3.input_var(v->get_position()), cvi.curr_coef()); + break; + case Global_Var: { + Global_Var_ID g = v->get_global_var(); + Variable_ID v3; + if (g->arity() == 0) + v3 = r3.get_local(g); + else + v3 = r3.get_local(g, v->function_of()); + h3.update_coef(v3, cvi.curr_coef()); + break; + } + case Wildcard_Var: + if (v == wc) + h3.update_coef(f_exists3->declare(), cvi.curr_coef()); + else { + Variable_ID v3 = replicate_floor_definition(bounds, + v, + r3, + f_exists3, + f_root3, + exists_mapping3); + h3.update_coef(v3, cvi.curr_coef()); + } + break; + default: + assert(false); + } + } + h3.update_const(stride_eq.get_const()); + r3.simplify(); + + if (Gist(r3, Intersection(r2, all_known), 1).is_obvious_tautology()) + return true; + else + return false; + } + else { return false; + } } - else - return false; -} - - + + // // output variable by its name, however if this variable need to be substituted, // return the substitution. // -CG_outputRepr *output_ident(CG_outputBuilder *ocg, const Relation &R, Variable_ID v, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) { - const_cast<Relation &>(R).setup_names(); // hack - - if (v->kind() == Input_Var) { - int pos = v->get_position(); - if (assigned_on_the_fly[pos-1].first != NULL) - return assigned_on_the_fly[pos-1].first->clone(); - else - return ocg->CreateIdent(v->name()); - } - else if (v->kind() == Global_Var) { - if (v->get_global_var()->arity() == 0) - return ocg->CreateIdent(v->name()); - else { - /* This should be improved to take into account the possible elimination - of the set variables. */ - int arity = v->get_global_var()->arity(); - std::vector<CG_outputRepr *> argList; - for(int i = 1; i <= arity; i++) - argList.push_back(ocg->CreateIdent(const_cast<Relation &>(R).input_var(i)->name())); - CG_outputRepr *call = ocg->CreateInvoke(v->get_global_var()->base_name(), argList); - return call; + CG_outputRepr *output_ident(CG_outputBuilder *ocg, + const Relation &R, + Variable_ID v, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::map<std::string, std::vector<CG_outputRepr *> > unin) { + fprintf(stderr, "output_ident( %s )\n", v->name().c_str()); + + const_cast<Relation &>(R).setup_names(); // hack + + if (v->kind() == Input_Var) { + int pos = v->get_position(); + if (assigned_on_the_fly[pos - 1].first != NULL) { + //fprintf(stderr, "on the fly pos=%d\n", pos); + CG_outputRepr *tmp = assigned_on_the_fly[pos-1].first->clone(); + //fprintf(stderr, "tmp on the fly (0x%x)\n", tmp); + return tmp; + } + else { + //fprintf(stderr, "creating Ident for %s\n", v->name().c_str()); + CG_outputRepr *tmp = ocg->CreateIdent(v->name()); + //fprintf(stderr, "ident created for %s\n", v->name().c_str()); + return tmp; + } } + else if (v->kind() == Global_Var) { + //fprintf(stderr, "CG_utils.cc output_ident() Global_Var\n"); + if (v->get_global_var()->arity() == 0) { + //fprintf(stderr, "arity 0\n"); + return ocg->CreateIdent(v->name()); + } + else { + /* This should be improved to take into account the possible elimination + of the set variables. */ + int arity = v->get_global_var()->arity(); + //fprintf(stderr, "arity %dn", arity ); + std::vector<CG_outputRepr *> argList; + if (unin.find(v->get_global_var()->base_name()) != unin.end()) { + + std::vector<CG_outputRepr *> argList_ = unin.find( + v->get_global_var()->base_name())->second; + + for (int l = 0; l < argList_.size(); l++) + argList.push_back(argList_[l]->clone()); + + } + else { + for (int i = 1; i <= arity; i++) { + + /* + */ + if (assigned_on_the_fly.size() > (R.n_inp() + i - 1)) { + if (assigned_on_the_fly[R.n_inp() + i - 1].first != NULL) + argList.push_back( + assigned_on_the_fly[R.n_inp() + i - 1].first->clone()); + else + argList.push_back( + ocg->CreateIdent( + const_cast<Relation &>(R).input_var( + 2 * i)->name())); + } else + argList.push_back( + ocg->CreateIdent( + const_cast<Relation &>(R).input_var( + 2 * i)->name())); + + /*if (assigned_on_the_fly[2*i - 1].first == NULL) + argList.push_back( + ocg->CreateIdent( + const_cast<Relation &>(R).input_var(2 * i)->name())); + else + argList.push_back(assigned_on_the_fly[2*i - 1].first->clone()); + */ + } + } + CG_outputRepr *call = ocg->CreateInvoke( + v->get_global_var()->base_name(), argList); + return call; + } + } + else + assert(false); } - else - assert(false); -} - + + // // return pair<if condition, <assignment rhs, assignment cost> > // -std::pair<CG_outputRepr *, std::pair<CG_outputRepr *, int> > output_assignment(CG_outputBuilder *ocg, const Relation &R, int level, const Relation &known, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) { - Variable_ID v = const_cast<Relation &>(R).set_var(level); - Conjunct *c = const_cast<Relation &>(R).single_conjunct(); - - std::pair<EQ_Handle, int> result = find_simplest_assignment(R, v, assigned_on_the_fly); - - if (result.second == INT_MAX) - return std::make_pair(static_cast<CG_outputRepr *>(NULL), std::make_pair(static_cast<CG_outputRepr *>(NULL), INT_MAX)); - - CG_outputRepr *if_repr = NULL; - CG_outputRepr *assign_repr = NULL; - // check whether to generate if-conditions from equality constraints - if (abs(result.first.get_coef(v)) != 1) { - 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; - exists_mapping[v] = f_exists->declare(); - - EQ_Handle h = f_root->add_EQ(); - for (Constr_Vars_Iter cvi(result.first); cvi; cvi++) - switch (cvi.curr_var()->kind()) { - case Input_Var: { - if (cvi.curr_var() == v) - h.update_coef(exists_mapping[v], cvi.curr_coef()); - else - h.update_coef(r.set_var(cvi.curr_var()->get_position()), cvi.curr_coef()); - break; - } - case Global_Var: { - Global_Var_ID g = cvi.curr_var()->get_global_var(); - Variable_ID v2; - if (g->arity() == 0) - v2 = r.get_local(g); - else - v2 = r.get_local(g, cvi.curr_var()->function_of()); - h.update_coef(v2, cvi.curr_coef()); - break; - } - case Wildcard_Var: { - std::map<Variable_ID, Variable_ID>::iterator p = exists_mapping.find(cvi.curr_var()); - Variable_ID v2; - if (p == exists_mapping.end()) { - v2 = f_exists->declare(); - exists_mapping[cvi.curr_var()] = v2; + std::pair<CG_outputRepr *, std::pair<CG_outputRepr *, int> > output_assignment( + CG_outputBuilder *ocg, const Relation &R, int level, + const Relation &known, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::map<std::string, std::vector<CG_outputRepr *> > unin) { + + //fprintf(stderr, "output_assignment( )\n"); + int numfly = assigned_on_the_fly.size(); + //fprintf(stderr, "assigned on the fly %d\n", numfly ); + for (int i=0; i<numfly; i++) { + //fprintf(stderr, "i %d\n", i); + std::pair<CG_outputRepr *, int>p = assigned_on_the_fly[i]; + CG_outputRepr *tr = NULL; + if (p.first != NULL) tr = p.first->clone(); + int val = p.second; + //fprintf(stderr, "0x%x %d\n", tr, val); + } + + + Variable_ID v = const_cast<Relation &>(R).set_var(level); + Conjunct *c = const_cast<Relation &>(R).single_conjunct(); + + std::pair<EQ_Handle, int> result = find_simplest_assignment(R, v, assigned_on_the_fly); + + if (result.second == INT_MAX) + return std::make_pair(static_cast<CG_outputRepr *>(NULL), std::make_pair(static_cast<CG_outputRepr *>(NULL), INT_MAX)); + + CG_outputRepr *if_repr = NULL; + CG_outputRepr *assign_repr = NULL; + // check whether to generate if-conditions from equality constraints + if (abs(result.first.get_coef(v)) != 1) { + 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; + exists_mapping[v] = f_exists->declare(); + + EQ_Handle h = f_root->add_EQ(); + for (Constr_Vars_Iter cvi(result.first); cvi; cvi++) + switch (cvi.curr_var()->kind()) { + case Input_Var: { + if (cvi.curr_var() == v) + h.update_coef(exists_mapping[v], cvi.curr_coef()); + else + h.update_coef(r.set_var(cvi.curr_var()->get_position()), cvi.curr_coef()); + break; } - else - v2 = p->second; - h.update_coef(v2, cvi.curr_coef()); - break; - } - default: - assert(0); - } - h.update_const(result.first.get_const()); + case Global_Var: { + Global_Var_ID g = cvi.curr_var()->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, cvi.curr_var()->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Wildcard_Var: { + std::map<Variable_ID, Variable_ID>::iterator p = exists_mapping.find(cvi.curr_var()); + Variable_ID v2; + if (p == exists_mapping.end()) { + v2 = f_exists->declare(); + exists_mapping[cvi.curr_var()] = v2; + } + else + v2 = p->second; + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(0); + } + h.update_const(result.first.get_const()); - for (EQ_Iterator e(c->EQs()); e; e++) - if (!((*e) == result.first)) { - EQ_Handle h = f_root->add_EQ(); + for (EQ_Iterator e(c->EQs()); e; e++) + if (!((*e) == result.first)) { + EQ_Handle h = f_root->add_EQ(); + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + switch (cvi.curr_var()->kind()) { + case Input_Var: { + assert(cvi.curr_var() != v); + h.update_coef(r.set_var(cvi.curr_var()->get_position()), cvi.curr_coef()); + break; + } + case Global_Var: { + Global_Var_ID g = cvi.curr_var()->get_global_var(); + Variable_ID v2; + if (g->arity() == 0) + v2 = r.get_local(g); + else + v2 = r.get_local(g, cvi.curr_var()->function_of()); + h.update_coef(v2, cvi.curr_coef()); + break; + } + case Wildcard_Var: { + std::map<Variable_ID, Variable_ID>::iterator p = exists_mapping.find(cvi.curr_var()); + Variable_ID v2; + if (p == exists_mapping.end()) { + v2 = f_exists->declare(); + exists_mapping[cvi.curr_var()] = v2; + } + else + v2 = p->second; + h.update_coef(v2, cvi.curr_coef()); + break; + } + default: + assert(0); + } + h.update_const((*e).get_const()); + } + + for (GEQ_Iterator e(c->GEQs()); e; e++) { + GEQ_Handle h = f_root->add_GEQ(); for (Constr_Vars_Iter cvi(*e); cvi; cvi++) switch (cvi.curr_var()->kind()) { case Input_Var: { - assert(cvi.curr_var() != v); h.update_coef(r.set_var(cvi.curr_var()->get_position()), cvi.curr_coef()); break; } @@ -357,1379 +504,2303 @@ std::pair<CG_outputRepr *, std::pair<CG_outputRepr *, int> > output_assignment(C } h.update_const((*e).get_const()); } - - for (GEQ_Iterator e(c->GEQs()); e; e++) { - GEQ_Handle h = f_root->add_GEQ(); - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - switch (cvi.curr_var()->kind()) { - case Input_Var: { - h.update_coef(r.set_var(cvi.curr_var()->get_position()), cvi.curr_coef()); - break; - } - case Global_Var: { - Global_Var_ID g = cvi.curr_var()->get_global_var(); - Variable_ID v2; - if (g->arity() == 0) - v2 = r.get_local(g); - else - v2 = r.get_local(g, cvi.curr_var()->function_of()); - h.update_coef(v2, cvi.curr_coef()); - break; - } - case Wildcard_Var: { - std::map<Variable_ID, Variable_ID>::iterator p = exists_mapping.find(cvi.curr_var()); - Variable_ID v2; - if (p == exists_mapping.end()) { - v2 = f_exists->declare(); - exists_mapping[cvi.curr_var()] = v2; - } - else - v2 = p->second; - h.update_coef(v2, cvi.curr_coef()); - break; - } - default: - assert(0); - } - h.update_const((*e).get_const()); - } - r.simplify(); - if (!Gist(r, copy(known), 1).is_obvious_tautology()) { - CG_outputRepr *lhs = output_substitution_repr(ocg, result.first, v, false, R, assigned_on_the_fly); - if_repr = ocg->CreateEQ(ocg->CreateIntegerMod(lhs->clone(), ocg->CreateInt(abs(result.first.get_coef(v)))), ocg->CreateInt(0)); - assign_repr = ocg->CreateDivide(lhs, ocg->CreateInt(abs(result.first.get_coef(v)))); + r.simplify(); + if (!Gist(r, copy(known), 1).is_obvious_tautology()) { + CG_outputRepr *lhs = output_substitution_repr(ocg, result.first, v, + false, R, assigned_on_the_fly, unin); + if_repr = ocg->CreateEQ(ocg->CreateIntegerMod(lhs->clone(), + ocg->CreateInt(abs(result.first.get_coef(v)))), + ocg->CreateInt(0)); + assign_repr = ocg->CreateDivide(lhs, ocg->CreateInt(abs(result.first.get_coef(v)))); + } + else { + assign_repr = output_substitution_repr(ocg, result.first, v, true, R, + assigned_on_the_fly, unin); + } } - else - assign_repr = output_substitution_repr(ocg, result.first, v, true, R, assigned_on_the_fly); + else { + assign_repr = output_substitution_repr(ocg, result.first, v, true, R, + assigned_on_the_fly, unin); + } + + if (assign_repr == NULL) { + assign_repr = ocg->CreateInt(0); + } + + //fprintf(stderr, "assigned on the fly %d\n", numfly ); + //for (int i=0; i<numfly; i++) { + // //fprintf(stderr, "i %d\n", i); + // std::pair<CG_outputRepr *, int>p = assigned_on_the_fly[i]; + // CG_outputRepr *tr = NULL; + // if (p.first != NULL) tr = p.first->clone(); + // int val = p.second; + // //fprintf(stderr, "0x%x %d\n", tr, val); + //} + + return std::make_pair(if_repr, std::make_pair(assign_repr, result.second)); } - else - assign_repr = output_substitution_repr(ocg, result.first, v, true, R, assigned_on_the_fly); - - if (assign_repr == NULL) - assign_repr = ocg->CreateInt(0); + - return std::make_pair(if_repr, std::make_pair(assign_repr, result.second)); -} - - // // return NULL if 0 // -CG_outputRepr *output_substitution_repr(CG_outputBuilder *ocg, const EQ_Handle &equality, Variable_ID v, bool apply_v_coef, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) { - const_cast<Relation &>(R).setup_names(); // hack - - coef_t a = equality.get_coef(v); - assert(a != 0); - - CG_outputRepr *repr = NULL; - for (Constr_Vars_Iter cvi(equality); 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()); - if (!result.first) { - delete repr; - throw codegen_error("can't output non floor defined wildcard"); + CG_outputRepr *output_substitution_repr(CG_outputBuilder *ocg, + const EQ_Handle &equality, + Variable_ID v, + bool apply_v_coef, + const Relation &R, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::map<std::string, std::vector<CG_outputRepr *> > unin) { + //fprintf(stderr, "output_substitution_repr( v = '%s' )\n", v->char_name()); + const_cast<Relation &>(R).setup_names(); // hack + + coef_t a = equality.get_coef(v); + assert(a != 0); + + CG_outputRepr *repr = NULL; + for (Constr_Vars_Iter cvi(equality); cvi; cvi++) + if (cvi.curr_var() != v) { + //fprintf(stderr, "cvi\n"); + CG_outputRepr *t; + if (cvi.curr_var()->kind() == Wildcard_Var) { + std::pair<bool, GEQ_Handle> result = find_floor_definition(R, cvi.curr_var()); + if (!result.first) { + delete repr; + throw codegen_error("can't output non floor defined wildcard"); + } + t = output_inequality_repr(ocg, result.second, cvi.curr_var(), R, assigned_on_the_fly, unin); } - t = output_inequality_repr(ocg, result.second, cvi.curr_var(), R, assigned_on_the_fly); - } - else - t = output_ident(ocg, R, cvi.curr_var(), assigned_on_the_fly); - 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 { + //fprintf(stderr, "else t = output_ident()\n"); + t = output_ident(ocg, R, cvi.curr_var(), assigned_on_the_fly, unin); + //if (t== NULL) fprintf(stderr, "t NULL\n"); } - else { // coef < 0 - 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)); + coef_t coef = cvi.curr_coef(); + //fprintf(stderr, "coef %d\n", coef); + + //fprintf(stderr, "a %d\n", a); + 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 { // coef < 0 + if (coef == -1) { + //fprintf(stderr, "repr = ocg->CreatePlus(repr, t);\n"); + repr = ocg->CreatePlus(repr, t); + //if (repr == NULL) fprintf(stderr, "repr NULL\n"); + //else fprintf(stderr, "repr NOT NULL\n"); + } + 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 { // coef < 0 + if (coef == -1) + repr = ocg->CreateMinus(repr, t); + else + repr = ocg->CreateMinus(repr, ocg->CreateTimes(ocg->CreateInt(-coef), t)); + } } - else { // coef < 0 - if (coef == -1) - repr = ocg->CreateMinus(repr, t); - else - repr = ocg->CreateMinus(repr, ocg->CreateTimes(ocg->CreateInt(-coef), t)); - } + } + + //if (repr == NULL) fprintf(stderr, "before inequality, repr == NULL\n"); + int c = equality.get_const(); + if (a > 0) { + if (c > 0) + repr = ocg->CreateMinus(repr, ocg->CreateInt(c)); + else if (c < 0) + repr = ocg->CreatePlus(repr, ocg->CreateInt(-c)); + } + else { + if (c > 0) { + repr = ocg->CreatePlus(repr, ocg->CreateInt(c)); + } + else if (c < 0) { + repr = ocg->CreateMinus(repr, ocg->CreateInt(-c)); } } - - int c = equality.get_const(); - if (a > 0) { - if (c > 0) - repr = ocg->CreateMinus(repr, ocg->CreateInt(c)); - else if (c < 0) - repr = ocg->CreatePlus(repr, ocg->CreateInt(-c)); - } - else { - if (c > 0) - repr = ocg->CreatePlus(repr, ocg->CreateInt(c)); - else if (c < 0) - repr = ocg->CreateMinus(repr, ocg->CreateInt(-c)); - } - if (apply_v_coef && abs(a) != 1) - repr = ocg->CreateDivide(repr, ocg->CreateInt(abs(a))); - - return repr; -} - - + if (apply_v_coef && abs(a) != 1) + repr = ocg->CreateDivide(repr, ocg->CreateInt(abs(a))); + + //if (repr == NULL) fprintf(stderr, "at end, repr == NULL\n"); + //fprintf(stderr, "leaving output_substitution_repr()\n"); + return repr; + } + + // // original Substitutions class from omega can't handle integer // division, this is new way. // -std::vector<CG_outputRepr*> output_substitutions(CG_outputBuilder *ocg, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) { - std::vector<CG_outputRepr *> subs; - - for (int i = 1; i <= R.n_out(); i++) { - Relation mapping(R.n_out(), 1); - F_And *f_root = mapping.add_and(); - EQ_Handle h = f_root->add_EQ(); - h.update_coef(mapping.output_var(1), 1); - h.update_coef(mapping.input_var(i), -1); - Relation r = Composition(mapping, copy(R)); - r.simplify(); - - Variable_ID v = r.output_var(1); - CG_outputRepr *repr = NULL; - std::pair<EQ_Handle, int> result = find_simplest_assignment(r, v, assigned_on_the_fly); - if (result.second < INT_MAX) - repr = output_substitution_repr(ocg, result.first, v, true, r, assigned_on_the_fly); - else { - std::pair<bool, GEQ_Handle> result = find_floor_definition(R, v); - if (result.first) - try { - repr = output_inequality_repr(ocg, result.second, v, R, assigned_on_the_fly); - } - catch (const codegen_error &) { - } + std::vector<CG_outputRepr*> output_substitutions(CG_outputBuilder *ocg, + const Relation &R, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::map<std::string, std::vector<CG_outputRepr *> > unin) { + std::vector<CG_outputRepr *> subs; + + fprintf(stderr, "CG_utils.cc output_substitutions()\n"); + + for (int i = 1; i <= R.n_out(); i++) { + Relation mapping(R.n_out(), 1); + F_And *f_root = mapping.add_and(); + EQ_Handle h = f_root->add_EQ(); + h.update_coef(mapping.output_var(1), 1); + h.update_coef(mapping.input_var(i), -1); + Relation r = Composition(mapping, copy(R)); + r.simplify(); + + Variable_ID v = r.output_var(1); + CG_outputRepr *repr = NULL; + + fprintf(stderr, "v %s\n", v->char_name()); + std::pair<EQ_Handle, int> result = find_simplest_assignment(r, v, assigned_on_the_fly); + if (result.second < INT_MAX) { + //fprintf(stderr, "output_substitutions() calling output_substitution_repr()\n"); + repr = output_substitution_repr(ocg, result.first, v, true, r, + assigned_on_the_fly, unin); + if (repr == NULL) fprintf(stderr, "IN IF, repr for %s assigned NULL\n", v->char_name()); + } + else { + //fprintf(stderr, "else\n"); + std::pair<bool, GEQ_Handle> result = find_floor_definition(R, v); + if (result.first) + try { + repr = output_inequality_repr(ocg, result.second, v, R, + assigned_on_the_fly, unin); + } + catch (const codegen_error &) { + } + } + + if (repr == NULL) fprintf(stderr, "repr NULL\n"); + if (repr != NULL) { + subs.push_back(repr); + } + else { + //Anand:Add additional checks for variables that have been mapped to inspector/global variables + for (int k = 1; k <= R.n_out(); k++) { + //Relation mapping1(mapping.n_out(), 1); + //F_And *f_root = mapping1.add_and(); + //EQ_Handle h = f_root->add_EQ(); + //h.update_coef(mapping1.output_var(1), 1); + //h.update_coef(mapping1.input_var(i), -1); + //Relation r = Composition(mapping1, copy(mapping)); + //r.simplify(); + + Relation r = copy(R); + + Variable_ID v = r.output_var(k); + CG_outputRepr* inspector = NULL; + bool has_insp = false; + Global_Var_ID global_insp; + + std::pair<EQ_Handle, int> result = find_simplest_assignment( + copy(r), v, assigned_on_the_fly); + CG_outputRepr *repr_ = NULL; + if (result.second < INT_MAX) { + /*std::vector<Variable_ID> variables; + //Anand: commenting this out as well : 05/29/2013 + variables.push_back(r.input_var(2 * k)); + for (Constr_Vars_Iter cvi(result.first); cvi; cvi++) { + Variable_ID v1 = cvi.curr_var(); + if (v1->kind() == Input_Var) + variables.push_back(v1); + + } + */ + repr_ = output_substitution_repr(ocg, result.first, v, true, + copy(r), assigned_on_the_fly, unin); + + for (DNF_Iterator di(copy(r).query_DNF()); di; di++) + for (GEQ_Iterator ci = (*di)->GEQs(); ci; ci++) { + + //Anand: temporarily commenting this out as it causes problems 5/28/2013 + /*int j; + for (j = 0; j < variables.size(); j++) + if ((*ci).get_coef(variables[j]) == 0) + break; + if (j != variables.size()) + continue; + */ + for (Constr_Vars_Iter cvi(*ci); cvi; cvi++) { + Variable_ID v1 = cvi.curr_var(); + if (v1->kind() == Global_Var) + if (v1->get_global_var()->arity() > 0) { + + if (i + <= v1->get_global_var()->arity()) { + + /* std::pair<EQ_Handle, int> result = + find_simplest_assignment( + copy(r), v, + assigned_on_the_fly); + + if (result.second < INT_MAX) { + CG_outputRepr *repr = + output_substitution_repr( + ocg, + result.first, v, + true, copy(r), + assigned_on_the_fly); + + inspector = + ocg->CreateArrayRefExpression( + ocg->CreateDotExpression( + ocg->ObtainInspectorData( + v1->get_global_var()->base_name()), + ocg->CreateIdent( + copy( + R).output_var( + i)->name())), + repr); + } else + */ + inspector = + /* ocg->CreateArrayRefExpression( + ocg->CreateDotExpression( + ocg->ObtainInspectorData( + v1->get_global_var()->base_name()), + ocg->CreateIdent( + copy( + R).output_var( + i)->name())), + repr);*/ + + ocg->CreateArrayRefExpression( + + ocg->ObtainInspectorData( + v1->get_global_var()->base_name(), + + copy(R).output_var( + i)->name()), + repr_); + //ocg->CreateIdent( + // v->name())); + + } + } + + } + } + } + + if (inspector != NULL) { + subs.push_back(inspector); + break; + } else if (k == i && repr_ != NULL) { + subs.push_back(repr_); + + } + + //std::pair<EQ_Handle, int> result = find_simplest_assignment(r, + // v, assigned_on_the_fly, &has_insp); + + /*if (has_insp) { + + bool found_insp = false; + //Anand: check if inspector constraint present in equality + for (Constr_Vars_Iter cvi(result.first); cvi; cvi++) { + Variable_ID v = cvi.curr_var(); + if (v->kind() == Global_Var) + if (v->get_global_var()->arity() > 0) { + global_insp = v->get_global_var(); + found_insp = true; + } + + } + if (found_insp) + if (i <= global_insp->arity()) + inspector = + ocg->CreateArrayRefExpression( + ocg->CreateDotExpression( + ocg->ObtainInspectorData( + global_insp->base_name()), + ocg->CreateIdent( + copy(R).output_var( + i)->name())), + ocg->CreateIdent(v->name())); + + + } + */ + } // for int k + } } - - subs.push_back(repr); - } - - return subs; -} - + fprintf(stderr, "CG_utils.cc output_substitutions() DONE\n\n"); + return subs; + } + + // // handle floor definition wildcards in equality, the second in returned pair // is the cost. // -std::pair<EQ_Handle, int> find_simplest_assignment(const Relation &R, Variable_ID v, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) { - Conjunct *c = const_cast<Relation &>(R).single_conjunct(); - - int min_cost = INT_MAX; - EQ_Handle eq; - for (EQ_Iterator e(c->EQs()); e; e++) - if (!(*e).has_wildcards() && (*e).get_coef(v) != 0) { - int cost = 0; - - if (abs((*e).get_coef(v)) != 1) - cost += 4; // divide cost - - int num_var = 0; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - if (cvi.curr_var() != v) { + std::pair<EQ_Handle, int> find_simplest_assignment(const Relation &R, + Variable_ID v, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + bool *found_inspector_global) { + Conjunct *c = const_cast<Relation &>(R).single_conjunct(); + + int min_cost = INT_MAX; + EQ_Handle eq; + for (EQ_Iterator e(c->EQs()); e; e++) + if (!(*e).has_wildcards() && (*e).get_coef(v) != 0) { + int cost = 0; + + if (abs((*e).get_coef(v)) != 1) + cost += 4; // divide cost + + int num_var = 0; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + if (cvi.curr_var() != v) { + num_var++; + if (abs(cvi.curr_coef()) != 1) + cost += 2; // multiply cost + if (cvi.curr_var()->kind() == Global_Var && cvi.curr_var()->get_global_var()->arity() > 0) { + //Anand --start: Check for Global Variable not being involved in any GEQ + Conjunct *d = + const_cast<Relation &>(R).single_conjunct(); + bool found = false; + for (GEQ_Iterator g(d->GEQs()); g; g++) + if ((*g).get_coef(v) != 0) { + found = true; + break; + } + if (!found) + cost += 10; // function cost + else { + cost = INT_MAX; + eq = *e; + if (found_inspector_global != NULL) + *found_inspector_global = true; + return std::make_pair(eq, cost); + } //Anand --end: Check for Global Variable not being involved in any GEQ + } + else if (cvi.curr_var()->kind() + == Input_Var&& + assigned_on_the_fly.size() >= cvi.curr_var()->get_position() && + assigned_on_the_fly[cvi.curr_var()->get_position()-1].first != NULL) { + cost += assigned_on_the_fly[cvi.curr_var()->get_position()-1].second; // substitution cost on record + } + } + if ((*e).get_const() != 0) num_var++; - if (abs(cvi.curr_coef()) != 1) - cost += 2; // multiply cost - if (cvi.curr_var()->kind() == Global_Var && cvi.curr_var()->get_global_var()->arity() > 0) - cost += 10; // function cost - else if (cvi.curr_var()->kind() == Input_Var && - assigned_on_the_fly.size() >= cvi.curr_var()->get_position() && - assigned_on_the_fly[cvi.curr_var()->get_position()-1].first != NULL) - cost += assigned_on_the_fly[cvi.curr_var()->get_position()-1].second; // substitution cost on record + if (num_var > 1) + cost += num_var - 1; // addition cost + + if (cost < min_cost) { + min_cost = cost; + eq = *e; + if (found_inspector_global != NULL) + *found_inspector_global = true; } - if ((*e).get_const() != 0) - num_var++; - if (num_var > 1) - cost += num_var - 1; // addition cost - - if (cost < min_cost) { - min_cost = cost; - eq = *e; } - } - if (min_cost < INT_MAX) - return std::make_pair(eq, min_cost); - - for (EQ_Iterator e(c->EQs()); e; e++) - if ((*e).has_wildcards() && (*e).get_coef(v) != 0) { - bool is_assignment = true; - for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) { - std::pair<bool, GEQ_Handle> result = find_floor_definition(R, v); - if (!result.first) { - is_assignment = false; - break; + if (min_cost < INT_MAX) + return std::make_pair(eq, min_cost); + + for (EQ_Iterator e(c->EQs()); e; e++) + if ((*e).has_wildcards() && (*e).get_coef(v) != 0) { + bool is_assignment = true; + for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) { + std::pair<bool, GEQ_Handle> result = find_floor_definition(R, v); + if (!result.first) { + is_assignment = false; + break; + } } - } - if (!is_assignment) - continue; - - int cost = 0; - - if (abs((*e).get_coef(v)) != 1) - cost += 4; // divide cost - - int num_var = 0; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - if (cvi.curr_var() != v) { + if (!is_assignment) + continue; + + int cost = 0; + + if (abs((*e).get_coef(v)) != 1) + cost += 4; // divide cost + + int num_var = 0; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + if (cvi.curr_var() != v) { + num_var++; + if (abs(cvi.curr_coef()) != 1) + cost += 2; // multiply cost + if (cvi.curr_var()->kind() == Wildcard_Var) + cost += 10; // floor operation cost + else if (cvi.curr_var()->kind() == Global_Var && + cvi.curr_var()->get_global_var()->arity() > 0) { + cost += 20; // function cost + } + else if (cvi.curr_var()->kind() == Input_Var && + assigned_on_the_fly.size() >= cvi.curr_var()->get_position() && + assigned_on_the_fly[cvi.curr_var()->get_position()-1].first != NULL) { + cost += assigned_on_the_fly[cvi.curr_var()->get_position()-1].second; // substitution cost on record + } + } + if ((*e).get_const() != 0) num_var++; - if (abs(cvi.curr_coef()) != 1) - cost += 2; // multiply cost - if (cvi.curr_var()->kind() == Wildcard_Var) - cost += 10; // floor operation cost - else if (cvi.curr_var()->kind() == Global_Var && cvi.curr_var()->get_global_var()->arity() > 0) - cost += 20; // function cost - else if (cvi.curr_var()->kind() == Input_Var && - assigned_on_the_fly.size() >= cvi.curr_var()->get_position() && - assigned_on_the_fly[cvi.curr_var()->get_position()-1].first != NULL) - cost += assigned_on_the_fly[cvi.curr_var()->get_position()-1].second; // substitution cost on record + if (num_var > 1) + cost += num_var - 1; // addition cost + + if (cost < min_cost) { + min_cost = cost; + eq = *e; + if (found_inspector_global != NULL) + *found_inspector_global = true; } - if ((*e).get_const() != 0) - num_var++; - if (num_var > 1) - cost += num_var - 1; // addition cost - - if (cost < min_cost) { - min_cost = cost; - eq = *e; } - } - - return std::make_pair(eq, min_cost); -} - - + + return std::make_pair(eq, min_cost); + } + + // // find floor definition for variable v, e.g. m-c <= 4v <= m, (c is // constant and 0 <= c < 4). this translates to v = floor(m, 4) and // return 4v<=m in this case. All wildcards in such inequality are // also floor defined. // -std::pair<bool, GEQ_Handle> find_floor_definition(const Relation &R, Variable_ID v, std::set<Variable_ID> excluded_floor_vars) { - Conjunct *c = const_cast<Relation &>(R).single_conjunct(); - - excluded_floor_vars.insert(v); - for (GEQ_Iterator e = c->GEQs(); e; e++) { - coef_t a = (*e).get_coef(v); - if (a >= -1) - continue; - a = -a; - - bool interested = true; - for (std::set<Variable_ID>::const_iterator i = excluded_floor_vars.begin(); i != excluded_floor_vars.end(); i++) - if ((*i) != v && (*e).get_coef(*i) != 0) { - interested = false; - break; - } - if (!interested) - continue; - - // check if any wildcard is floor defined - bool has_undefined_wc = false; - for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) - if (excluded_floor_vars.find(cvi.curr_var()) == excluded_floor_vars.end()) { - std::pair<bool, GEQ_Handle> result = find_floor_definition(R, cvi.curr_var(), excluded_floor_vars); - if (!result.first) { - has_undefined_wc = true; + std::pair<bool, GEQ_Handle> find_floor_definition(const Relation &R, + Variable_ID v, + std::set<Variable_ID> excluded_floor_vars) { + Conjunct *c = const_cast<Relation &>(R).single_conjunct(); + + excluded_floor_vars.insert(v); + for (GEQ_Iterator e = c->GEQs(); e; e++) { + coef_t a = (*e).get_coef(v); + if (a >= -1) + continue; + a = -a; + + bool interested = true; + for (std::set<Variable_ID>::const_iterator i = excluded_floor_vars.begin(); + i != excluded_floor_vars.end(); + i++) { + if ((*i) != v && (*e).get_coef(*i) != 0) { + interested = false; break; } } - if (has_undefined_wc) - continue; - - // find the matching upper bound for floor definition - for (GEQ_Iterator e2 = c->GEQs(); e2; e2++) - if ((*e2).get_coef(v) == a && (*e).get_const() + (*e2).get_const() < a) { - bool match = true; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - if ((*e2).get_coef(cvi.curr_var()) != -cvi.curr_coef()) { - match = false; + if (!interested) + continue; + + // check if any wildcard is floor defined + bool has_undefined_wc = false; + for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) + if (excluded_floor_vars.find(cvi.curr_var()) == excluded_floor_vars.end()) { + std::pair<bool, GEQ_Handle> result = find_floor_definition(R, + cvi.curr_var(), + excluded_floor_vars); + if (!result.first) { + has_undefined_wc = true; break; } - if (!match) - continue; - for (Constr_Vars_Iter cvi(*e2); cvi; cvi++) - if ((*e).get_coef(cvi.curr_var()) != -cvi.curr_coef()) { - match = false; + } + if (has_undefined_wc) + continue; + + // find the matching upper bound for floor definition + for (GEQ_Iterator e2 = c->GEQs(); e2; e2++) + if ((*e2).get_coef(v) == a && (*e).get_const() + (*e2).get_const() < a) { + bool match = true; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + if ((*e2).get_coef(cvi.curr_var()) != -cvi.curr_coef()) { + match = false; + break; + } + if (!match) + continue; + for (Constr_Vars_Iter cvi(*e2); cvi; cvi++) + if ((*e).get_coef(cvi.curr_var()) != -cvi.curr_coef()) { + match = false; + break; + } + if (match) + return std::make_pair(true, *e); + } + } + + return std::make_pair(false, GEQ_Handle()); + } + + //Anand- adding the following just for debug + std::vector<std::pair<bool, GEQ_Handle> > find_floor_definition_temp( + const Relation &R, Variable_ID v, + std::set<Variable_ID> excluded_floor_vars) { + Conjunct *c = const_cast<Relation &>(R).single_conjunct(); + std::vector<std::pair<bool, GEQ_Handle> > to_return; + excluded_floor_vars.insert(v); + for (GEQ_Iterator e = c->GEQs(); e; e++) { + coef_t a = (*e).get_coef(v); + if (a >= -1) + continue; + a = -a; + + //Anand: commenting out the following for debug 7/28/2013 + bool interested = true; + Variable_ID possibly_interfering; + for (std::set<Variable_ID>::const_iterator i = + excluded_floor_vars.begin(); i != excluded_floor_vars.end(); + i++) + if ((*i) != v && (*e).get_coef(*i) != 0) { + possibly_interfering = *i; + interested = false; + break; + } + + // continue; + + // check if any wildcard is floor defined + bool has_undefined_wc = false; + for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) + if (excluded_floor_vars.find(cvi.curr_var()) + == excluded_floor_vars.end()) { + std::pair<bool, GEQ_Handle> result = find_floor_definition(R, + cvi.curr_var(), excluded_floor_vars); + if (!result.first) { + has_undefined_wc = true; break; } - if (match) - return std::make_pair(true, *e); - } + } + if (has_undefined_wc) + continue; + +// find the matching upper bound for floor definition + for (GEQ_Iterator e2 = c->GEQs(); e2; e2++) + if ((*e2).get_coef(v) == a + && (*e).get_const() + (*e2).get_const() < a) { + bool match = true; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + if (v == cvi.curr_var() + && (*e2).get_coef(cvi.curr_var()) + != -cvi.curr_coef()) { + match = false; + break; + } + if (!match) + continue; + for (Constr_Vars_Iter cvi(*e2); cvi; cvi++) + if (v == cvi.curr_var() + && (*e).get_coef(cvi.curr_var()) + != -cvi.curr_coef()) { + match = false; + break; + } + if (match) { + to_return.push_back(std::make_pair(true, *e)); + if (!interested) + to_return.push_back(std::make_pair(true, *e2)); + return to_return; + + } + } + } + + to_return.push_back(std::make_pair(false, GEQ_Handle())); + + return to_return; } - return std::make_pair(false, GEQ_Handle()); -} - // // find the stride involving the specified variable, the stride // equality can have other wildcards as long as they are defined as // floor variables. // -std::pair<EQ_Handle, Variable_ID> find_simplest_stride(const Relation &R, Variable_ID v) { - int best_num_var = INT_MAX; - coef_t best_coef; - EQ_Handle best_eq; - Variable_ID best_stride_wc; - for (EQ_Iterator e(const_cast<Relation &>(R).single_conjunct()->EQs()); e; e++) - if ((*e).has_wildcards() && (*e).get_coef(v) != 0) { - bool is_stride = true; - bool found_free = false; - int num_var = 0; - int num_floor = 0; - Variable_ID stride_wc; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { - switch (cvi.curr_var()->kind()) { - case Wildcard_Var: { - bool is_free = true; - for (GEQ_Iterator e2(const_cast<Relation &>(R).single_conjunct()->GEQs()); e2; e2++) - if ((*e2).get_coef(cvi.curr_var()) != 0) { - is_free = false; - break; + std::pair<EQ_Handle, Variable_ID> find_simplest_stride(const Relation &R, + Variable_ID v) { + int best_num_var = INT_MAX; + coef_t best_coef; + EQ_Handle best_eq; + Variable_ID best_stride_wc; + for (EQ_Iterator e(const_cast<Relation &>(R).single_conjunct()->EQs()); e; e++) + if ((*e).has_wildcards() && (*e).get_coef(v) != 0) { + bool is_stride = true; + bool found_free = false; + int num_var = 0; + int num_floor = 0; + Variable_ID stride_wc; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { + switch (cvi.curr_var()->kind()) { + case Wildcard_Var: { + bool is_free = true; + for (GEQ_Iterator e2(const_cast<Relation &>(R).single_conjunct()->GEQs()); + e2; + e2++) + if ((*e2).get_coef(cvi.curr_var()) != 0) { + is_free = false; + break; + } + if (is_free) { + if (found_free) + is_stride = false; + else { + found_free = true; + stride_wc = cvi.curr_var(); + } } - if (is_free) { - if (found_free) - is_stride = false; else { - found_free = true; - stride_wc = cvi.curr_var(); + std::pair<bool, GEQ_Handle> result = find_floor_definition(R, cvi.curr_var()); + if (result.first) + num_floor++; + else + is_stride = false; } + break; } - else { - std::pair<bool, GEQ_Handle> result = find_floor_definition(R, cvi.curr_var()); - if (result.first) - num_floor++; - else - is_stride = false; + case Input_Var: + num_var++; + break; + default: + ; } - break; - } - case Input_Var: - num_var++; - break; - default: - ; + + if (!is_stride) + break; } - if (!is_stride) - break; - } - - if (is_stride) { - coef_t coef = abs((*e).get_coef(v)); - if (best_num_var == INT_MAX || coef < best_coef || - (coef == best_coef && num_var < best_num_var)) { - best_coef = coef; - best_num_var = num_var; - best_eq = *e; - best_stride_wc = stride_wc; + if (is_stride) { + coef_t coef = abs((*e).get_coef(v)); + if (best_num_var == INT_MAX || coef < best_coef || + (coef == best_coef && num_var < best_num_var)) { + best_coef = coef; + best_num_var = num_var; + best_eq = *e; + best_stride_wc = stride_wc; + } } } - } - - if (best_num_var != INT_MAX) - return std::make_pair(best_eq, best_stride_wc); - else - return std::make_pair(EQ_Handle(), static_cast<Variable_ID>(NULL)); -} - + + if (best_num_var != INT_MAX) + return std::make_pair(best_eq, best_stride_wc); + else + return std::make_pair(EQ_Handle(), static_cast<Variable_ID>(NULL)); + } + // // convert relation to if-condition // -CG_outputRepr *output_guard(CG_outputBuilder *ocg, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) { - assert(R.n_out()==0); - - CG_outputRepr *result = NULL; - Conjunct *c = const_cast<Relation &>(R).single_conjunct(); - - // e.g. 4i=5*j - for (EQ_Iterator e = c->EQs(); e; e++) - if (!(*e).has_wildcards()) { - CG_outputRepr *lhs = NULL; - CG_outputRepr *rhs = NULL; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { - CG_outputRepr *v = output_ident(ocg, R, cvi.curr_var(), assigned_on_the_fly); - coef_t coef = cvi.curr_coef(); - if (coef > 0) { - if (coef == 1) - lhs = ocg->CreatePlus(lhs, v); - else - lhs = ocg->CreatePlus(lhs, ocg->CreateTimes(ocg->CreateInt(coef), v)); + CG_outputRepr *output_guard(CG_outputBuilder *ocg, + const Relation &R, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::map<std::string, std::vector<CG_outputRepr *> > unin) { + fprintf(stderr, "output_guard()\n"); + assert(R.n_out()==0); + + CG_outputRepr *result = NULL; + Conjunct *c = const_cast<Relation &>(R).single_conjunct(); + + // e.g. 4i=5*j + for (EQ_Iterator e = c->EQs(); e; e++) + if (!(*e).has_wildcards()) { + //fprintf(stderr, "EQ\n"); + CG_outputRepr *lhs = NULL; + CG_outputRepr *rhs = NULL; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { + CG_outputRepr *v = output_ident(ocg, R, cvi.curr_var(), assigned_on_the_fly, unin); + coef_t coef = cvi.curr_coef(); + if (coef > 0) { + if (coef == 1) + lhs = ocg->CreatePlus(lhs, v); + else + lhs = ocg->CreatePlus(lhs, + ocg->CreateTimes(ocg->CreateInt(coef), v)); + } + else { // coef < 0 + if (coef == -1) + rhs = ocg->CreatePlus(rhs, v); + else + rhs = ocg->CreatePlus(rhs, + ocg->CreateTimes(ocg->CreateInt(-coef), v)); + } } - else { // coef < 0 - if (coef == -1) - rhs = ocg->CreatePlus(rhs, v); - else - rhs = ocg->CreatePlus(rhs, ocg->CreateTimes(ocg->CreateInt(-coef), v)); + coef_t c = (*e).get_const(); + + CG_outputRepr *term; + if (lhs == NULL) + term = ocg->CreateEQ(rhs, ocg->CreateInt(c)); + else { + if (c > 0) + rhs = ocg->CreateMinus(rhs, ocg->CreateInt(c)); + else if (c < 0) + rhs = ocg->CreatePlus(rhs, ocg->CreateInt(-c)); + else if (rhs == NULL) + rhs = ocg->CreateInt(0); + term = ocg->CreateEQ(lhs, rhs); } + result = ocg->CreateAnd(result, term); } - coef_t c = (*e).get_const(); - - CG_outputRepr *term; - if (lhs == NULL) - term = ocg->CreateEQ(rhs, ocg->CreateInt(c)); - else { - if (c > 0) - rhs = ocg->CreateMinus(rhs, ocg->CreateInt(c)); - else if (c < 0) - rhs = ocg->CreatePlus(rhs, ocg->CreateInt(-c)); - else if (rhs == NULL) - rhs = ocg->CreateInt(0); - term = ocg->CreateEQ(lhs, rhs); - } - result = ocg->CreateAnd(result, term); - } - - // e.g. i>5j - for (GEQ_Iterator e = c->GEQs(); e; e++) - if (!(*e).has_wildcards()) { - CG_outputRepr *lhs = NULL; - CG_outputRepr *rhs = NULL; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { - CG_outputRepr *v = output_ident(ocg, R, cvi.curr_var(), assigned_on_the_fly); - coef_t coef = cvi.curr_coef(); - if (coef > 0) { - if (coef == 1) - lhs = ocg->CreatePlus(lhs, v); - else - lhs = ocg->CreatePlus(lhs, ocg->CreateTimes(ocg->CreateInt(coef), v)); + + // e.g. i>5j + for (GEQ_Iterator e = c->GEQs(); e; e++) + if (!(*e).has_wildcards()) { + //fprintf(stderr, "GEQ\n"); + CG_outputRepr *lhs = NULL; + CG_outputRepr *rhs = NULL; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { + CG_outputRepr *v = output_ident(ocg, + R, + cvi.curr_var(), + assigned_on_the_fly, + unin); + coef_t coef = cvi.curr_coef(); + if (coef > 0) { + if (coef == 1) + lhs = ocg->CreatePlus(lhs, v); + else + lhs = ocg->CreatePlus(lhs, + ocg->CreateTimes(ocg->CreateInt(coef), v)); + } + else { // coef < 0 + if (coef == -1) + rhs = ocg->CreatePlus(rhs, v); + else + rhs = ocg->CreatePlus(rhs, + ocg->CreateTimes(ocg->CreateInt(-coef), v)); + } } - else { // coef < 0 - if (coef == -1) - rhs = ocg->CreatePlus(rhs, v); - else - rhs = ocg->CreatePlus(rhs, ocg->CreateTimes(ocg->CreateInt(-coef), v)); + coef_t c = (*e).get_const(); + + CG_outputRepr *term; + if (lhs == NULL) + term = ocg->CreateLE(rhs, ocg->CreateInt(c)); + else { + if (c > 0) + rhs = ocg->CreateMinus(rhs, ocg->CreateInt(c)); + else if (c < 0) + rhs = ocg->CreatePlus(rhs, ocg->CreateInt(-c)); + else if (rhs == NULL) + rhs = ocg->CreateInt(0); + term = ocg->CreateGE(lhs, rhs); } + //fprintf(stderr, "result = ocg->CreateAnd(result, term);\n"); + result = ocg->CreateAnd(result, term); } - coef_t c = (*e).get_const(); - - CG_outputRepr *term; - if (lhs == NULL) - term = ocg->CreateLE(rhs, ocg->CreateInt(c)); - else { - if (c > 0) - rhs = ocg->CreateMinus(rhs, ocg->CreateInt(c)); - else if (c < 0) - rhs = ocg->CreatePlus(rhs, ocg->CreateInt(-c)); - else if (rhs == NULL) - rhs = ocg->CreateInt(0); - term = ocg->CreateGE(lhs, rhs); - } - result = ocg->CreateAnd(result, term); - } - - // e.g. 4i=5j+4alpha - for (EQ_Iterator e = c->EQs(); e; e++) - if ((*e).has_wildcards()) { - Variable_ID wc; - int num_wildcard = 0; - int num_positive = 0; - int num_negative = 0; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { - if (cvi.curr_var()->kind() == Wildcard_Var) { - num_wildcard++; - wc = cvi.curr_var(); + + // e.g. 4i=5j+4alpha + for (EQ_Iterator e = c->EQs(); e; e++) + if ((*e).has_wildcards()) { + //fprintf(stderr, "EQ ??\n"); + Variable_ID wc; + int num_wildcard = 0; + int num_positive = 0; + int num_negative = 0; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { + if (cvi.curr_var()->kind() == Wildcard_Var) { + num_wildcard++; + wc = cvi.curr_var(); + } + else { + if (cvi.curr_coef() > 0) + num_positive++; + else + num_negative++; + } + } + + if (num_wildcard > 1) { + delete result; + throw codegen_error( + "Can't generate equality condition with multiple wildcards"); + } + int sign = (num_positive>=num_negative)?1:-1; + + CG_outputRepr *lhs = NULL; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { + if (cvi.curr_var() != wc) { + CG_outputRepr *v = output_ident(ocg, R, cvi.curr_var(), + assigned_on_the_fly, unin); + coef_t coef = cvi.curr_coef(); + if (sign == 1) { + if (coef > 0) { + if (coef == 1) + lhs = ocg->CreatePlus(lhs, v); + else + lhs = ocg->CreatePlus(lhs, + ocg->CreateTimes(ocg->CreateInt(coef), v)); + } + else { // coef < 0 + if (coef == -1) + lhs = ocg->CreateMinus(lhs, v); + else + lhs = ocg->CreateMinus(lhs, + ocg->CreateTimes(ocg->CreateInt(-coef), v)); + } + } + else { + if (coef > 0) { + if (coef == 1) + lhs = ocg->CreateMinus(lhs, v); + else + lhs = ocg->CreateMinus(lhs, + ocg->CreateTimes(ocg->CreateInt(coef), v)); + } + else { // coef < 0 + if (coef == -1) + lhs = ocg->CreatePlus(lhs, v); + else + lhs = ocg->CreatePlus(lhs, + ocg->CreateTimes(ocg->CreateInt(-coef), v)); + } + } + } + } + coef_t c = (*e).get_const(); + if (sign == 1) { + if (c > 0) + lhs = ocg->CreatePlus(lhs, ocg->CreateInt(c)); + else if (c < 0) + lhs = ocg->CreateMinus(lhs, ocg->CreateInt(-c)); } else { - if (cvi.curr_coef() > 0) - num_positive++; - else - num_negative++; + if (c > 0) + lhs = ocg->CreateMinus(lhs, ocg->CreateInt(c)); + else if (c < 0) + lhs = ocg->CreatePlus(lhs, ocg->CreateInt(-c)); } + + lhs = ocg->CreateIntegerMod(lhs, + ocg->CreateInt(abs((*e).get_coef(wc)))); + CG_outputRepr *term = ocg->CreateEQ(lhs, ocg->CreateInt(0)); + result = ocg->CreateAnd(result, term); } - - if (num_wildcard > 1) { - delete result; - throw codegen_error("Can't generate equality condition with multiple wildcards"); - } - int sign = (num_positive>=num_negative)?1:-1; - - CG_outputRepr *lhs = NULL; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { - if (cvi.curr_var() != wc) { - CG_outputRepr *v = output_ident(ocg, R, cvi.curr_var(), assigned_on_the_fly); - coef_t coef = cvi.curr_coef(); + + // e.g. 4alpha<=i<=5alpha + for (GEQ_Iterator e = c->GEQs(); e; e++) + if ((*e).has_wildcards()) { + //fprintf(stderr, "GEQ ??\n"); + Variable_ID wc; + int num_wildcard = 0; + for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) + if (num_wildcard == 0) { + wc = cvi.curr_var(); + num_wildcard = 1; + } + else + num_wildcard++; + + if (num_wildcard > 1) { + delete result; + // e.g. c*alpha - x >= 0 (*) + // -d*alpha + y >= 0 (*) + // e1*alpha + f1*beta + g1 >= 0 (**) + // e2*alpha + f2*beta + g2 >= 0 (**) + // ... + // TODO: should generate a testing loop for alpha using its lower and + // upper bounds from (*) constraints and do the same if-condition test + // for beta from each pair of opposite (**) constraints as above, + // and exit the loop when if-condition satisfied. + throw codegen_error( + "Can't generate multiple wildcard GEQ guards right now"); + } + + coef_t c = (*e).get_coef(wc); + int sign = (c>0)?1:-1; + + GEQ_Iterator e2 = e; + e2++; + for ( ; e2; e2++) { + coef_t c2 = (*e2).get_coef(wc); + if (c2 == 0) + continue; + int sign2 = (c2>0)?1:-1; + if (sign != -sign2) + continue; + int num_wildcard2 = 0; + for (Constr_Vars_Iter cvi(*e2, true); cvi; cvi++) + num_wildcard2++; + if (num_wildcard2 > 1) + continue; + + GEQ_Handle lb, ub; if (sign == 1) { - if (coef > 0) { - if (coef == 1) - lhs = ocg->CreatePlus(lhs, v); - else - lhs = ocg->CreatePlus(lhs, ocg->CreateTimes(ocg->CreateInt(coef), v)); - } - else { // coef < 0 - if (coef == -1) - lhs = ocg->CreateMinus(lhs, v); - else - lhs = ocg->CreateMinus(lhs, ocg->CreateTimes(ocg->CreateInt(-coef), v)); - } + lb = (*e); + ub = (*e2); } else { - if (coef > 0) { - if (coef == 1) - lhs = ocg->CreateMinus(lhs, v); - else - lhs = ocg->CreateMinus(lhs, ocg->CreateTimes(ocg->CreateInt(coef), v)); + lb = (*e2); + ub = (*e); + } + + CG_outputRepr *lhs = NULL; + for (Constr_Vars_Iter cvi(lb); cvi; cvi++) + if (cvi.curr_var() != wc) { + CG_outputRepr *v = output_ident(ocg, R, cvi.curr_var(), + assigned_on_the_fly, unin); + coef_t coef = cvi.curr_coef(); + if (coef > 0) { + if (coef == 1) + lhs = ocg->CreateMinus(lhs, v); + else + lhs = ocg->CreateMinus(lhs, + ocg->CreateTimes(ocg->CreateInt(coef), v)); + } + else { // coef < 0 + if (coef == -1) + lhs = ocg->CreatePlus(lhs, v); + else + lhs = ocg->CreatePlus(lhs, + ocg->CreateTimes(ocg->CreateInt(-coef), v)); + } } - else { // coef < 0 - if (coef == -1) - lhs = ocg->CreatePlus(lhs, v); - else - lhs = ocg->CreatePlus(lhs, ocg->CreateTimes(ocg->CreateInt(-coef), v)); + coef_t c = lb.get_const(); + if (c > 0) + lhs = ocg->CreateMinus(lhs, ocg->CreateInt(c)); + else if (c < 0) + lhs = ocg->CreatePlus(lhs, ocg->CreateInt(-c)); + + CG_outputRepr *rhs = NULL; + for (Constr_Vars_Iter cvi(ub); cvi; cvi++) + if (cvi.curr_var() != wc) { + CG_outputRepr *v = output_ident(ocg, R, cvi.curr_var(), + assigned_on_the_fly, unin); + coef_t coef = cvi.curr_coef(); + if (coef > 0) { + if (coef == 1) + rhs = ocg->CreatePlus(rhs, v); + else + rhs = ocg->CreatePlus(rhs, + ocg->CreateTimes(ocg->CreateInt(coef), v)); + } + else { // coef < 0 + if (coef == -1) + rhs = ocg->CreateMinus(rhs, v); + else + rhs = ocg->CreateMinus(rhs, + ocg->CreateTimes(ocg->CreateInt(-coef), v)); + } } - } + c = ub.get_const(); + if (c > 0) + rhs = ocg->CreatePlus(rhs, ocg->CreateInt(c)); + else if (c < 0) + rhs = ocg->CreateMinus(rhs, ocg->CreateInt(-c)); + + rhs = ocg->CreateIntegerFloor(rhs, ocg->CreateInt(-ub.get_coef(wc))); + rhs = ocg->CreateTimes(ocg->CreateInt(lb.get_coef(wc)), rhs); + CG_outputRepr *term = ocg->CreateLE(lhs, rhs); + result = ocg->CreateAnd(result, term); } } - coef_t c = (*e).get_const(); - if (sign == 1) { - if (c > 0) - lhs = ocg->CreatePlus(lhs, ocg->CreateInt(c)); - else if (c < 0) - lhs = ocg->CreateMinus(lhs, ocg->CreateInt(-c)); - } - else { - if (c > 0) - lhs = ocg->CreateMinus(lhs, ocg->CreateInt(c)); - else if (c < 0) - lhs = ocg->CreatePlus(lhs, ocg->CreateInt(-c)); - } - - lhs = ocg->CreateIntegerMod(lhs, ocg->CreateInt(abs((*e).get_coef(wc)))); - CG_outputRepr *term = ocg->CreateEQ(lhs, ocg->CreateInt(0)); - result = ocg->CreateAnd(result, term); - } + + //fprintf(stderr, "output_guard returning at bottom 0x%x\n", result); + return result; + } + + +// +// return NULL if 0 +// + CG_outputRepr *output_inequality_repr(CG_outputBuilder *ocg, + const GEQ_Handle &inequality, + Variable_ID v, + const Relation &R, + 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) { + fprintf(stderr, "output_inequality_repr() v %s\n", v->name().c_str()); + + const_cast<Relation &>(R).setup_names(); // hack + + coef_t a = inequality.get_coef(v); + assert(a != 0); + excluded_floor_vars.insert(v); + + std::vector<std::pair<bool, GEQ_Handle> > result2; + CG_outputRepr *repr = NULL; + for (Constr_Vars_Iter cvi(inequality); 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) { + fprintf(stderr, "\n\n*** heading into NEW CODE\n"); + + 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); + + fprintf(stderr, "returning a TIMES\n"); + return repr; + + } + + } + + }; - // e.g. 4alpha<=i<=5alpha - for (GEQ_Iterator e = c->GEQs(); e; e++) - if ((*e).has_wildcards()) { - Variable_ID wc; - int num_wildcard = 0; - for (Constr_Vars_Iter cvi(*e, true); cvi; cvi++) - if (num_wildcard == 0) { - wc = cvi.curr_var(); - num_wildcard = 1; + if (!result.first) { + delete repr; + throw codegen_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 - num_wildcard++; - - if (num_wildcard > 1) { - delete result; - // e.g. c*alpha - x >= 0 (*) - // -d*alpha + y >= 0 (*) - // e1*alpha + f1*beta + g1 >= 0 (**) - // e2*alpha + f2*beta + g2 >= 0 (**) - // ... - // TODO: should generate a testing loop for alpha using its lower and - // upper bounds from (*) constraints and do the same if-condition test - // for beta from each pair of opposite (**) constraints as above, - // and exit the loop when if-condition satisfied. - throw codegen_error("Can't generate multiple wildcard GEQ guards right now"); - } - - coef_t c = (*e).get_coef(wc); - int sign = (c>0)?1:-1; - - GEQ_Iterator e2 = e; - e2++; - for ( ; e2; e2++) { - coef_t c2 = (*e2).get_coef(wc); - if (c2 == 0) - continue; - int sign2 = (c2>0)?1:-1; - if (sign != -sign2) - continue; - int num_wildcard2 = 0; - for (Constr_Vars_Iter cvi(*e2, true); cvi; cvi++) - num_wildcard2++; - if (num_wildcard2 > 1) - continue; - - GEQ_Handle lb, ub; - if (sign == 1) { - lb = (*e); - ub = (*e2); + 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 { - lb = (*e2); - ub = (*e); - } - - CG_outputRepr *lhs = NULL; - for (Constr_Vars_Iter cvi(lb); cvi; cvi++) - if (cvi.curr_var() != wc) { - CG_outputRepr *v = output_ident(ocg, R, cvi.curr_var(), assigned_on_the_fly); - coef_t coef = cvi.curr_coef(); - if (coef > 0) { - if (coef == 1) - lhs = ocg->CreateMinus(lhs, v); - else - lhs = ocg->CreateMinus(lhs, ocg->CreateTimes(ocg->CreateInt(coef), v)); - } - else { // coef < 0 - if (coef == -1) - lhs = ocg->CreatePlus(lhs, v); - else - lhs = ocg->CreatePlus(lhs, ocg->CreateTimes(ocg->CreateInt(-coef), v)); - } + if (coef > 0) { + if (coef == 1) + repr = ocg->CreatePlus(repr, t); + else + repr = ocg->CreatePlus(repr, + ocg->CreateTimes(ocg->CreateInt(coef),t)); } - coef_t c = lb.get_const(); - if (c > 0) - lhs = ocg->CreateMinus(lhs, ocg->CreateInt(c)); - else if (c < 0) - lhs = ocg->CreatePlus(lhs, ocg->CreateInt(-c)); - - CG_outputRepr *rhs = NULL; - for (Constr_Vars_Iter cvi(ub); cvi; cvi++) - if (cvi.curr_var() != wc) { - CG_outputRepr *v = output_ident(ocg, R, cvi.curr_var(), assigned_on_the_fly); - coef_t coef = cvi.curr_coef(); - if (coef > 0) { - if (coef == 1) - rhs = ocg->CreatePlus(rhs, v); - else - rhs = ocg->CreatePlus(rhs, ocg->CreateTimes(ocg->CreateInt(coef), v)); - } - else { // coef < 0 - if (coef == -1) - rhs = ocg->CreateMinus(rhs, v); - else - rhs = ocg->CreateMinus(rhs, ocg->CreateTimes(ocg->CreateInt(-coef), v)); - } + else { + if (coef == -1) + repr = ocg->CreateMinus(repr, t); + else + repr = ocg->CreateMinus(repr, + ocg->CreateTimes(ocg->CreateInt(-coef),t)); } - c = ub.get_const(); - if (c > 0) - rhs = ocg->CreatePlus(rhs, ocg->CreateInt(c)); - else if (c < 0) - rhs = ocg->CreateMinus(rhs, ocg->CreateInt(-c)); - - rhs = ocg->CreateIntegerFloor(rhs, ocg->CreateInt(-ub.get_coef(wc))); - rhs = ocg->CreateTimes(ocg->CreateInt(lb.get_coef(wc)), rhs); - CG_outputRepr *term = ocg->CreateLE(lhs, rhs); - result = ocg->CreateAnd(result, term); + } } + coef_t c = inequality.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) + return repr; + else if (a > 0) + return ocg->CreateIntegerCeil(repr, ocg->CreateInt(a)); + else // a < 0 + return ocg->CreateIntegerFloor(repr, ocg->CreateInt(-a)); + } + - return result; -} - - // -// return NULL if 0 +// nothing special, just an alias // -CG_outputRepr *output_inequality_repr(CG_outputBuilder *ocg, const GEQ_Handle &inequality, Variable_ID v, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, std::set<Variable_ID> excluded_floor_vars) { - const_cast<Relation &>(R).setup_names(); // hack + CG_outputRepr *output_upper_bound_repr(CG_outputBuilder *ocg, + const GEQ_Handle &inequality, + Variable_ID v, + const Relation &R, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::map<std::string, std::vector<CG_outputRepr *> > unin) { + assert(inequality.get_coef(v) < 0); + CG_outputRepr* zero_; + + zero_ = output_inequality_repr(ocg, inequality, v, R, assigned_on_the_fly, + unin); + + if(!zero_) + zero_ = ocg->CreateInt(0); + + return zero_; + } - coef_t a = inequality.get_coef(v); - assert(a != 0); - excluded_floor_vars.insert(v); - CG_outputRepr *repr = NULL; - for (Constr_Vars_Iter cvi(inequality); 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) { - delete repr; - throw codegen_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, excluded_floor_vars); - } - catch (const std::exception &e) { - delete repr; - throw e; - } +// +// output lower bound with respect to lattice +// + CG_outputRepr *output_lower_bound_repr(CG_outputBuilder *ocg, + const GEQ_Handle &inequality, + Variable_ID v, + const EQ_Handle &stride_eq, + Variable_ID wc, + const Relation &R, + const Relation &known, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::map<std::string, std::vector<CG_outputRepr *> > unin) { + + fprintf(stderr, "output_lower_bound_repr()\n"); + assert(inequality.get_coef(v) > 0); + CG_outputRepr* zero_; + if (wc == NULL + || bound_must_hit_stride(inequality, v, stride_eq, wc, R, known)){ + zero_ = output_inequality_repr(ocg, inequality, v, R, + assigned_on_the_fly, unin); + if(!zero_) + zero_ = ocg->CreateInt(0); + + return zero_; + } + CG_outputRepr *strideBoundRepr = NULL; + int sign = (stride_eq.get_coef(v)>0)?1:-1; + for (Constr_Vars_Iter cvi(stride_eq); cvi; cvi++) { + Variable_ID v2 = cvi.curr_var(); + if (v2 == v || v2 == wc) + continue; + + CG_outputRepr *v_repr; + if (v2->kind() == Input_Var || v2->kind() == Global_Var) + v_repr = output_ident(ocg, R, v2, assigned_on_the_fly,unin); + else if (v2->kind() == Wildcard_Var) { + std::pair<bool, GEQ_Handle> result = find_floor_definition(R, v2); + assert(result.first); + v_repr = output_inequality_repr(ocg, result.second, v2, R, + assigned_on_the_fly, unin); } - else - t = output_ident(ocg, R, cvi.curr_var(), assigned_on_the_fly); - + coef_t coef = cvi.curr_coef(); - if (a > 0) { + if (sign < 0) { if (coef > 0) { if (coef == 1) - repr = ocg->CreateMinus(repr, t); + strideBoundRepr = ocg->CreatePlus(strideBoundRepr, v_repr); else - repr = ocg->CreateMinus(repr, ocg->CreateTimes(ocg->CreateInt(coef), t)); + strideBoundRepr = ocg->CreatePlus(strideBoundRepr, + ocg->CreateTimes(ocg->CreateInt(coef), v_repr)); } - else { + else { // coef < 0 if (coef == -1) - repr = ocg->CreatePlus(repr, t); + strideBoundRepr = ocg->CreateMinus(strideBoundRepr, v_repr); else - repr = ocg->CreatePlus(repr, ocg->CreateTimes(ocg->CreateInt(-coef), t)); + strideBoundRepr = ocg->CreateMinus(strideBoundRepr, + ocg->CreateTimes(ocg->CreateInt(-coef), v_repr)); } } else { if (coef > 0) { if (coef == 1) - repr = ocg->CreatePlus(repr, t); + strideBoundRepr = ocg->CreateMinus(strideBoundRepr, v_repr); else - repr = ocg->CreatePlus(repr, ocg->CreateTimes(ocg->CreateInt(coef), t)); + strideBoundRepr = ocg->CreateMinus(strideBoundRepr, + ocg->CreateTimes(ocg->CreateInt(coef), v_repr)); } - else { + else { // coef < 0 if (coef == -1) - repr = ocg->CreateMinus(repr, t); + strideBoundRepr = ocg->CreatePlus(strideBoundRepr, v_repr); else - repr = ocg->CreateMinus(repr, ocg->CreateTimes(ocg->CreateInt(-coef), t)); + strideBoundRepr = ocg->CreatePlus(strideBoundRepr, + ocg->CreateTimes(ocg->CreateInt(-coef), v_repr)); } } + } + coef_t c = stride_eq.get_const(); + fprintf(stderr, "stride eq const %d\n", c); + fprintf(stderr, "sign %d\n", sign ); + if (c > 0) { + if (sign < 0) + strideBoundRepr = ocg->CreatePlus(strideBoundRepr, ocg->CreateInt(c)); + else + strideBoundRepr = ocg->CreateMinus(strideBoundRepr, ocg->CreateInt(c)); } - coef_t c = inequality.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) - return repr; - else if (a > 0) - return ocg->CreateIntegerCeil(repr, ocg->CreateInt(a)); - else // a < 0 - return ocg->CreateIntegerFloor(repr, ocg->CreateInt(-a)); -} - - -// -// nothing special, just an alias -// -CG_outputRepr *output_upper_bound_repr(CG_outputBuilder *ocg, const GEQ_Handle &inequality, Variable_ID v, const Relation &R, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) { - assert(inequality.get_coef(v) < 0); - CG_outputRepr* zero_; - - zero_ = output_inequality_repr(ocg, inequality, v, R, assigned_on_the_fly); - - if(!zero_) - zero_ = ocg->CreateInt(0); - - return zero_; - -} - - -// -// output lower bound with respect to lattice -// -CG_outputRepr *output_lower_bound_repr(CG_outputBuilder *ocg, const GEQ_Handle &inequality, Variable_ID v, const EQ_Handle &stride_eq, Variable_ID wc, const Relation &R, const Relation &known, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) { - assert(inequality.get_coef(v) > 0); - CG_outputRepr* zero_; - if (wc == NULL || bound_must_hit_stride(inequality, v, stride_eq, wc, R, known)){ - zero_ = output_inequality_repr(ocg, inequality, v, R, assigned_on_the_fly); - if(!zero_) - zero_ = ocg->CreateInt(0); - - return zero_; - } - CG_outputRepr *strideBoundRepr = NULL; - int sign = (stride_eq.get_coef(v)>0)?1:-1; - for (Constr_Vars_Iter cvi(stride_eq); cvi; cvi++) { - Variable_ID v2 = cvi.curr_var(); - if (v2 == v || v2 == wc) - continue; - - CG_outputRepr *v_repr; - if (v2->kind() == Input_Var || v2->kind() == Global_Var) - v_repr = output_ident(ocg, R, v2, assigned_on_the_fly); - else if (v2->kind() == Wildcard_Var) { - std::pair<bool, GEQ_Handle> result = find_floor_definition(R, v2); - assert(result.first); - v_repr = output_inequality_repr(ocg, result.second, v2, R, assigned_on_the_fly); + else if (c < 0) { + if (sign < 0) + strideBoundRepr = ocg->CreateMinus(strideBoundRepr, ocg->CreateInt(-c)); + else + strideBoundRepr = ocg->CreatePlus(strideBoundRepr, ocg->CreateInt(-c)); } + + CG_outputRepr *repr = output_inequality_repr(ocg, inequality, v, R, + assigned_on_the_fly, unin); + //fprintf(stderr, "inequality repr %p\n", repr); + CG_outputRepr *repr2 = ocg->CreateCopy(repr); + + fprintf(stderr, "stride_eq.get_coef(wc) %d\n", stride_eq.get_coef(wc)); + fprintf(stderr, "repr + mod( strideBoundRepr - repr, %d )\n", stride_eq.get_coef(wc)); - coef_t coef = cvi.curr_coef(); - if (sign < 0) { - if (coef > 0) { - if (coef == 1) - strideBoundRepr = ocg->CreatePlus(strideBoundRepr, v_repr); - else - strideBoundRepr = ocg->CreatePlus(strideBoundRepr, ocg->CreateTimes(ocg->CreateInt(coef), v_repr)); - } - else { // coef < 0 - if (coef == -1) - strideBoundRepr = ocg->CreateMinus(strideBoundRepr, v_repr); - else - strideBoundRepr = ocg->CreateMinus(strideBoundRepr, ocg->CreateTimes(ocg->CreateInt(-coef), v_repr)); - } - } - else { - if (coef > 0) { - if (coef == 1) - strideBoundRepr = ocg->CreateMinus(strideBoundRepr, v_repr); - else - strideBoundRepr = ocg->CreateMinus(strideBoundRepr, ocg->CreateTimes(ocg->CreateInt(coef), v_repr)); - } - else { // coef < 0 - if (coef == -1) - strideBoundRepr = ocg->CreatePlus(strideBoundRepr, v_repr); - else - strideBoundRepr = ocg->CreatePlus(strideBoundRepr, ocg->CreateTimes(ocg->CreateInt(-coef), v_repr)); - } - } - } - coef_t c = stride_eq.get_const(); - if (c > 0) { - if (sign < 0) - strideBoundRepr = ocg->CreatePlus(strideBoundRepr, ocg->CreateInt(c)); - else - strideBoundRepr = ocg->CreateMinus(strideBoundRepr, ocg->CreateInt(c)); - } - else if (c < 0) { - if (sign < 0) - strideBoundRepr = ocg->CreateMinus(strideBoundRepr, ocg->CreateInt(-c)); - else - strideBoundRepr = ocg->CreatePlus(strideBoundRepr, ocg->CreateInt(-c)); + repr = ocg->CreatePlus(repr2, + ocg->CreateIntegerMod(ocg->CreateMinus(strideBoundRepr, repr), + ocg->CreateInt(abs(stride_eq.get_coef(wc))))); + + return repr; } - - CG_outputRepr *repr = output_inequality_repr(ocg, inequality, v, R, assigned_on_the_fly); - CG_outputRepr *repr2 = ocg->CreateCopy(repr); - repr = ocg->CreatePlus(repr2, ocg->CreateIntegerMod(ocg->CreateMinus(strideBoundRepr, repr), ocg->CreateInt(abs(stride_eq.get_coef(wc))))); - - return repr; -} - + // // return loop control structure only // -CG_outputRepr *output_loop(CG_outputBuilder *ocg, const Relation &R, int level, const Relation &known, const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) { - std::pair<EQ_Handle, Variable_ID> result = find_simplest_stride(R, const_cast<Relation &>(R).set_var(level)); - if (result.second != NULL) - assert(abs(result.first.get_coef(const_cast<Relation &>(R).set_var(level))) == 1); - - std::vector<CG_outputRepr *> lbList, ubList; - try { - - coef_t const_lb = negInfinity, const_ub = posInfinity; + CG_outputRepr *output_loop(CG_outputBuilder *ocg, + const Relation &R, + int level, + const Relation &known, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::map<std::string, std::vector<CG_outputRepr *> > unin) { + + fprintf(stderr, "CG_utils.cc output_loop()\n"); + std::pair<EQ_Handle, Variable_ID> result = find_simplest_stride(R, const_cast<Relation &>(R).set_var(level)); + fprintf(stderr, "found stride\n"); - for (GEQ_Iterator e(const_cast<Relation &>(R).single_conjunct()->GEQs()); e; e++) { - coef_t coef = (*e).get_coef(const_cast<Relation &>(R).set_var(level)); + if (result.second != NULL) + assert(abs(result.first.get_coef(const_cast<Relation &>(R).set_var(level))) == 1); + + std::vector<CG_outputRepr *> lbList, ubList; + try { + + coef_t const_lb = negInfinity, const_ub = posInfinity; + + for (GEQ_Iterator e(const_cast<Relation &>(R).single_conjunct()->GEQs()); + e; + e++) { + fprintf(stderr, "new e\n"); + coef_t coef = (*e).get_coef(const_cast<Relation &>(R).set_var(level)); + + fprintf(stderr, "coef %d\n", coef); + if (coef > 0) { + CG_outputRepr *repr = output_lower_bound_repr(ocg, *e, const_cast<Relation &>(R).set_var(level), result.first, result.second, R, known, assigned_on_the_fly, unin); + fprintf(stderr, "got a repr\n"); + if (repr == NULL) fprintf(stderr, "repr NULL\n"); - if (coef > 0) { - CG_outputRepr *repr = output_lower_bound_repr(ocg, *e, const_cast<Relation &>(R).set_var(level), result.first, result.second, R, known, assigned_on_the_fly); if (repr == NULL) - repr = ocg->CreateInt(0); - lbList.push_back(repr); - - if ((*e).is_const(const_cast<Relation &>(R).set_var(level))){ - if(!result.second) { - - //no variables but v in constr - coef_t L,m; - L = -((*e).get_const()); - - m = (*e).get_coef(const_cast<Relation &>(R).set_var(level)); - coef_t sb = (int) (ceil(((float) L) /m)); - set_max(const_lb, sb); + repr = ocg->CreateInt(0); + lbList.push_back(repr); + + if ((*e).is_const(const_cast<Relation &>(R).set_var(level))){ + if(!result.second) { + + //no variables but v in constr + coef_t L,m; + L = -((*e).get_const()); + + m = (*e).get_coef(const_cast<Relation &>(R).set_var(level)); + coef_t sb = (int) (ceil(((float) L) /m)); + set_max(const_lb, sb); } - else{ - - coef_t L,m,s,c; - L = -((*e).get_const()); - m = (*e).get_coef(const_cast<Relation &>(R).set_var(level)); - s = abs(result.first.get_coef(result.second)); - c = result.first.get_const(); - coef_t sb = (s * (int) (ceil( (float) (L - (c * m)) /(s*m))))+ c; - set_max(const_lb, sb); - - } + else{ + + coef_t L,m,s,c; + L = -((*e).get_const()); + m = (*e).get_coef(const_cast<Relation &>(R).set_var(level)); + s = abs(result.first.get_coef(result.second)); + c = result.first.get_const(); + coef_t sb = (s * (int) (ceil( (float) (L - (c * m)) /(s*m))))+ c; + set_max(const_lb, sb); + + } + } + } - - } - else if (coef < 0) { - CG_outputRepr *repr = output_upper_bound_repr(ocg, *e, const_cast<Relation &>(R).set_var(level), R, assigned_on_the_fly); - if (repr == NULL) - repr = ocg->CreateInt(0); - ubList.push_back(repr); - - if ((*e).is_const(const_cast<Relation &>(R).set_var(level))) { - // no variables but v in constraint - set_min(const_ub,-(*e).get_const()/(*e).get_coef(const_cast<Relation &>(R).set_var(level))); + else if (coef < 0) { + CG_outputRepr *repr = output_upper_bound_repr(ocg, + *e, + const_cast<Relation &>(R).set_var(level), + R, + assigned_on_the_fly, + unin); + if (repr == NULL) + repr = ocg->CreateInt(0); + ubList.push_back(repr); + + if ((*e).is_const(const_cast<Relation &>(R).set_var(level))) { + // no variables but v in constraint + set_min(const_ub,-(*e).get_const()/(*e).get_coef(const_cast<Relation &>(R).set_var(level))); + } + } - } + + if(fillInBounds && lbList.size() == 1 && const_lb != negInfinity) + lowerBoundForLevel = const_lb; + + if(fillInBounds && const_ub != posInfinity) { + upperBoundForLevel = const_ub; + } + if (lbList.size() == 0) + throw codegen_error( + "missing lower bound at loop level " + to_string(level)); + if (ubList.size() == 0) + throw codegen_error( + "missing upper bound at loop level " + to_string(level)); + } + catch (const std::exception &e) { + for (int i = 0; i < lbList.size(); i++) + delete lbList[i]; + for (int i = 0; i < ubList.size(); i++) + delete ubList[i]; + throw e; } - if(fillInBounds && lbList.size() == 1 && const_lb != negInfinity) - lowerBoundForLevel = const_lb; + CG_outputRepr *lbRepr = NULL; + if (lbList.size() > 1) { + fprintf(stderr, "CG_utils.cc output_loop() createInvoke( max )\n"); + lbRepr = ocg->CreateInvoke("max", lbList); + } + else { // (lbList.size() == 1) + lbRepr = lbList[0]; + } - if(fillInBounds && const_ub != posInfinity) - upperBoundForLevel = const_ub; - if (lbList.size() == 0) - throw codegen_error("missing lower bound at loop level " + to_string(level)); - if (ubList.size() == 0) - throw codegen_error("missing upper bound at loop level " + to_string(level)); - } - catch (const std::exception &e) { - for (int i = 0; i < lbList.size(); i++) - delete lbList[i]; - for (int i = 0; i < ubList.size(); i++) - delete ubList[i]; - throw e; + CG_outputRepr *ubRepr = NULL; + if (ubList.size() > 1) { + fprintf(stderr, "CG_utils.cc output_loop() createInvoke( min )\n"); + ubRepr = ocg->CreateInvoke("min", ubList); + } + else { // (ubList.size() == 1) + ubRepr = ubList[0]; + } + + CG_outputRepr *stRepr; + if (result.second == NULL) + stRepr = ocg->CreateInt(1); + else + stRepr = ocg->CreateInt(abs(result.first.get_coef(result.second))); + CG_outputRepr *indexRepr = output_ident(ocg, + R, + const_cast<Relation &>(R).set_var(level), + assigned_on_the_fly, + unin); + //fprintf(stderr,"CG_utils.cc output_loop() returning CreateInductive()\n"); + return ocg->CreateInductive(indexRepr, lbRepr, ubRepr, stRepr); } - - CG_outputRepr *lbRepr = NULL; - if (lbList.size() > 1) - lbRepr = ocg->CreateInvoke("max", lbList); - else // (lbList.size() == 1) - lbRepr = lbList[0]; - - CG_outputRepr *ubRepr = NULL; - if (ubList.size() > 1) - ubRepr = ocg->CreateInvoke("min", ubList); - else // (ubList.size() == 1) - ubRepr = ubList[0]; - - CG_outputRepr *stRepr; - if (result.second == NULL) - stRepr = ocg->CreateInt(1); - else - stRepr = ocg->CreateInt(abs(result.first.get_coef(result.second))); - CG_outputRepr *indexRepr = output_ident(ocg, R, const_cast<Relation &>(R).set_var(level), assigned_on_the_fly); - return ocg->CreateInductive(indexRepr, lbRepr, ubRepr, stRepr); -} - - + + // // parameter f_root is inside f_exists, not the other way around. // return replicated variable in new relation, with all cascaded floor definitions // using wildcards defined in the same way as in the original relation. // -Variable_ID replicate_floor_definition(const Relation &R, const Variable_ID floor_var, - Relation &r, F_Exists *f_exists, F_And *f_root, - std::map<Variable_ID, Variable_ID> &exists_mapping) { - assert(R.n_out() == 0 && r.n_out() == 0 && R.n_inp() == r.n_inp()); - - std::set<Variable_ID> excluded_floor_vars; - std::stack<Variable_ID> to_fill; - to_fill.push(floor_var); + Variable_ID replicate_floor_definition(const Relation &R, + const Variable_ID floor_var, + Relation &r, + F_Exists *f_exists, + F_And *f_root, + std::map<Variable_ID, Variable_ID> &exists_mapping) { + //Anand: commenting the assertion out 8/4/2013 + //assert(R.n_out() == 0 && r.n_out() == 0 && R.n_inp() == r.n_inp()); + bool is_mapping = false; + if (r.n_out() > 0) + is_mapping = true; + + std::set<Variable_ID> excluded_floor_vars; + std::set<Variable_ID> excluded_floor_vars2; + std::stack<Variable_ID> to_fill; + to_fill.push(floor_var); + + while (!to_fill.empty()) { + Variable_ID v = to_fill.top(); + to_fill.pop(); + if (excluded_floor_vars.find(v) != excluded_floor_vars.end()) + continue; + + std::pair<bool, GEQ_Handle> result = find_floor_definition(R, v, + excluded_floor_vars); + std::vector<std::pair<bool, GEQ_Handle> > result2; + + if (!result.first) { + + result2 = find_floor_definition_temp(R, v, excluded_floor_vars2); + assert(result2.size() >= 1); + result = result2[0]; + } + else + result2.push_back(result); - while (!to_fill.empty()) { - Variable_ID v = to_fill.top(); - to_fill.pop(); - if (excluded_floor_vars.find(v) != excluded_floor_vars.end()) - continue; - - std::pair<bool, GEQ_Handle> result = find_floor_definition(R, v, excluded_floor_vars); - assert(result.first); - excluded_floor_vars.insert(v); + assert(result.first); + excluded_floor_vars.insert(v); + excluded_floor_vars2.insert(v); - GEQ_Handle h1 = f_root->add_GEQ(); - GEQ_Handle h2 = f_root->add_GEQ(); - for (Constr_Vars_Iter cvi(result.second); cvi; cvi++) { - Variable_ID v2 = cvi.curr_var(); - switch (v2->kind()) { - case Input_Var: { - int pos = v2->get_position(); - h1.update_coef(r.input_var(pos), cvi.curr_coef()); - h2.update_coef(r.input_var(pos), -cvi.curr_coef()); - break; - } - case Wildcard_Var: { - std::map<Variable_ID, Variable_ID>::iterator p = exists_mapping.find(v2); - Variable_ID v3; - if (p == exists_mapping.end()) { - v3 = f_exists->declare(); - exists_mapping[v2] = v3; + for (int i = 0; i < result2.size(); i++) { + + GEQ_Handle h1 = f_root->add_GEQ(); + GEQ_Handle h2 = f_root->add_GEQ(); + for (Constr_Vars_Iter cvi(result2[i].second); cvi; cvi++) { + Variable_ID v2 = cvi.curr_var(); + switch (v2->kind()) { + case Input_Var: { + int pos = v2->get_position(); + if (!is_mapping) { + h1.update_coef(r.input_var(pos), cvi.curr_coef()); + h2.update_coef(r.input_var(pos), -cvi.curr_coef()); + } + else { + h1.update_coef(r.output_var(pos), cvi.curr_coef()); + h2.update_coef(r.output_var(pos), -cvi.curr_coef()); + } + break; + } + case Wildcard_Var: { + std::map<Variable_ID, Variable_ID>::iterator p=exists_mapping.find(v2); + Variable_ID v3; + if (p == exists_mapping.end()) { + v3 = f_exists->declare(); + exists_mapping[v2] = v3; + } + else + v3 = p->second; + h1.update_coef(v3, cvi.curr_coef()); + h2.update_coef(v3, -cvi.curr_coef()); + if (v2 != v) + to_fill.push(v2); + break; + } + case Global_Var: { + Global_Var_ID g = v2->get_global_var(); + Variable_ID v3; + if (g->arity() == 0) + v3 = r.get_local(g); + else + v3 = r.get_local(g, v2->function_of()); + h1.update_coef(v3, cvi.curr_coef()); + h2.update_coef(v3, -cvi.curr_coef()); + break; + } + default: + assert(false); + } } - else - v3 = p->second; - h1.update_coef(v3, cvi.curr_coef()); - h2.update_coef(v3, -cvi.curr_coef()); - if (v2 != v) - to_fill.push(v2); - break; - } - case Global_Var: { - Global_Var_ID g = v2->get_global_var(); - Variable_ID v3; - if (g->arity() == 0) - v3 = r.get_local(g); - else - v3 = r.get_local(g, v2->function_of()); - h1.update_coef(v3, cvi.curr_coef()); - h2.update_coef(v3, -cvi.curr_coef()); - break; - } - default: - assert(false); + h1.update_const(result2[i].second.get_const()); + h2.update_const( + -result2[i].second.get_const() + - result2[i].second.get_coef(v) - 1); } } - h1.update_const(result.second.get_const()); - h2.update_const(-result.second.get_const()-result.second.get_coef(v)-1); + if (floor_var->kind() == Input_Var) + return r.input_var(floor_var->get_position()); + else if (floor_var->kind() == Wildcard_Var) + return exists_mapping[floor_var]; + else + assert(false); } - - if (floor_var->kind() == Input_Var) - return r.input_var(floor_var->get_position()); - else if (floor_var->kind() == Wildcard_Var) - return exists_mapping[floor_var]; - else - assert(false); -} - - + + // // pick one guard condition from relation. it can involve multiple // constraints when involving wildcards, as long as its complement // is a single conjunct. // -Relation pick_one_guard(const Relation &R, int level) { - assert(R.n_out()==0); - - Relation r = Relation::True(R.n_set()); - - for (GEQ_Iterator e(const_cast<Relation &>(R).single_conjunct()->GEQs()); e; e++) - if (!(*e).has_wildcards()) { - r.and_with_GEQ(*e); - r.simplify(); - r.copy_names(R); - r.setup_names(); - return r; - } - - for (EQ_Iterator e(const_cast<Relation &>(R).single_conjunct()->EQs()); e; e++) - if (!(*e).has_wildcards()) { - r.and_with_GEQ(*e); - r.simplify(); - r.copy_names(R); - r.setup_names(); - return r; - } - - for (EQ_Iterator e(const_cast<Relation &>(R).single_conjunct()->EQs()); e; e++) - if ((*e).has_wildcards()) { - int num_wildcard = 0; - int max_level = 0; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - switch (cvi.curr_var()->kind()) { - case Wildcard_Var: - num_wildcard++; - break; - case Input_Var: - if (cvi.curr_var()->get_position() > max_level) - max_level = cvi.curr_var()->get_position(); - break; - default: - ; - } - - if (num_wildcard == 1 && max_level != level-1) { - r.and_with_EQ(*e); + Relation pick_one_guard(const Relation &R, int level) { + //fprintf(stderr, "pick_one_guard()\n"); + assert(R.n_out()==0); + + Relation r = Relation::True(R.n_set()); + + for (GEQ_Iterator e(const_cast<Relation &>(R).single_conjunct()->GEQs()); + e; + e++) + if (!(*e).has_wildcards()) { + r.and_with_GEQ(*e); r.simplify(); r.copy_names(R); r.setup_names(); return r; } - } - - for (GEQ_Iterator e(const_cast<Relation &>(R).single_conjunct()->GEQs()); e; e++) - if ((*e).has_wildcards()) { - int num_wildcard = 0; - int max_level = 0; - bool direction; - Variable_ID wc; - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) - switch (cvi.curr_var()->kind()) { - case Wildcard_Var: - num_wildcard++; - wc = cvi.curr_var(); - direction = cvi.curr_coef()>0?true:false; - break; - case Input_Var: - if (cvi.curr_var()->get_position() > max_level) - max_level = cvi.curr_var()->get_position(); - break; - default: - ; + + for (EQ_Iterator e(const_cast<Relation &>(R).single_conjunct()->EQs()); + e; + e++) + if (!(*e).has_wildcards()) { + r.and_with_GEQ(*e); + r.simplify(); + r.copy_names(R); + r.setup_names(); + return r; + } + + for (EQ_Iterator e(const_cast<Relation &>(R).single_conjunct()->EQs()); + e; + e++) + if ((*e).has_wildcards()) { + int num_wildcard = 0; + int max_level = 0; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + switch (cvi.curr_var()->kind()) { + case Wildcard_Var: + num_wildcard++; + break; + case Input_Var: + if (cvi.curr_var()->get_position() > max_level) + max_level = cvi.curr_var()->get_position(); + break; + default: + ; + } + + if (num_wildcard == 1 && max_level != level-1) { + r.and_with_EQ(*e); + r.simplify(); + r.copy_names(R); + r.setup_names(); + return r; } - - if (num_wildcard == 1 && max_level != level-1) { - // find the pairing inequality - GEQ_Iterator e2 = e; - e2++; - for ( ; e2; e2++) { - int num_wildcard2 = 0; - int max_level2 = 0; - bool direction2; - Variable_ID wc2; - for (Constr_Vars_Iter cvi(*e2); cvi; cvi++) - switch (cvi.curr_var()->kind()) { - case Wildcard_Var: - num_wildcard2++; - wc2 = cvi.curr_var(); - direction2 = cvi.curr_coef()>0?true:false; - break; - case Input_Var: - if (cvi.curr_var()->get_position() > max_level2) - max_level2 = cvi.curr_var()->get_position(); - break; - default: - ; - } - - if (num_wildcard2 == 1 && max_level2 != level-1 && wc2 == wc && direction2 == not direction) { - F_Exists *f_exists = r.and_with_and()->add_exists(); - Variable_ID wc3 = f_exists->declare(); - F_And *f_root = f_exists->add_and(); - GEQ_Handle h = f_root->add_GEQ(); - for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { + } + + for (GEQ_Iterator e(const_cast<Relation &>(R).single_conjunct()->GEQs()); + e; + e++) + if ((*e).has_wildcards()) { + int num_wildcard = 0; + int max_level = 0; + bool direction; + Variable_ID wc; + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) + switch (cvi.curr_var()->kind()) { + case Wildcard_Var: + num_wildcard++; + wc = cvi.curr_var(); + direction = cvi.curr_coef()>0?true:false; + break; + case Input_Var: + if (cvi.curr_var()->get_position() > max_level) + max_level = cvi.curr_var()->get_position(); + break; + default: + ; + } + + if (num_wildcard == 1 && max_level != level-1) { + // find the pairing inequality + GEQ_Iterator e2 = e; + e2++; + for ( ; e2; e2++) { + int num_wildcard2 = 0; + int max_level2 = 0; + bool direction2; + Variable_ID wc2; + for (Constr_Vars_Iter cvi(*e2); cvi; cvi++) switch (cvi.curr_var()->kind()) { case Wildcard_Var: - h.update_coef(wc3, cvi.curr_coef()); + num_wildcard2++; + wc2 = cvi.curr_var(); + direction2 = cvi.curr_coef()>0?true:false; break; case Input_Var: - h.update_coef(r.input_var(cvi.curr_var()->get_position()), cvi.curr_coef()); - break; - case Global_Var: { - Global_Var_ID g = cvi.curr_var()->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = r.get_local(g); - else - v = r.get_local(g, cvi.curr_var()->function_of()); - h.update_coef(v, cvi.curr_coef()); + if (cvi.curr_var()->get_position() > max_level2) + max_level2 = cvi.curr_var()->get_position(); break; - } default: - assert(false); + ; } - } - h.update_const((*e).get_const()); - h = f_root->add_GEQ(); - for (Constr_Vars_Iter cvi(*e2); cvi; cvi++) { - switch (cvi.curr_var()->kind()) { - case Wildcard_Var: - h.update_coef(wc3, cvi.curr_coef()); - break; - case Input_Var: - h.update_coef(r.input_var(cvi.curr_var()->get_position()), cvi.curr_coef()); - break; - case Global_Var: { - Global_Var_ID g = cvi.curr_var()->get_global_var(); - Variable_ID v; - if (g->arity() == 0) - v = r.get_local(g); - else - v = r.get_local(g, cvi.curr_var()->function_of()); - h.update_coef(v, cvi.curr_coef()); - break; + if (num_wildcard2 == 1 + && max_level2 != level-1 + && wc2 == wc + && direction2 == not direction) { + F_Exists *f_exists = r.and_with_and()->add_exists(); + Variable_ID wc3 = f_exists->declare(); + F_And *f_root = f_exists->add_and(); + GEQ_Handle h = f_root->add_GEQ(); + for (Constr_Vars_Iter cvi(*e); cvi; cvi++) { + switch (cvi.curr_var()->kind()) { + case Wildcard_Var: + h.update_coef(wc3, cvi.curr_coef()); + break; + case Input_Var: + h.update_coef(r.input_var(cvi.curr_var()->get_position()), + cvi.curr_coef()); + break; + case Global_Var: { + Global_Var_ID g = cvi.curr_var()->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = r.get_local(g); + else + v = r.get_local(g, cvi.curr_var()->function_of()); + h.update_coef(v, cvi.curr_coef()); + break; + } + default: + assert(false); + } } - default: - assert(false); + h.update_const((*e).get_const()); + + h = f_root->add_GEQ(); + for (Constr_Vars_Iter cvi(*e2); cvi; cvi++) { + switch (cvi.curr_var()->kind()) { + case Wildcard_Var: + h.update_coef(wc3, cvi.curr_coef()); + break; + case Input_Var: + h.update_coef(r.input_var(cvi.curr_var()->get_position()), + cvi.curr_coef()); + break; + case Global_Var: { + Global_Var_ID g = cvi.curr_var()->get_global_var(); + Variable_ID v; + if (g->arity() == 0) + v = r.get_local(g); + else + v = r.get_local(g, cvi.curr_var()->function_of()); + h.update_coef(v, cvi.curr_coef()); + break; + } + default: + assert(false); + } } + h.update_const((*e2).get_const()); + + r.simplify(); + r.copy_names(R); + r.setup_names(); + return r; } - h.update_const((*e2).get_const()); - - r.simplify(); - r.copy_names(R); - r.setup_names(); - return r; } } } + } + + +// +// heavy lifting for code output for one leaf node +// + CG_outputRepr *leaf_print_repr(BoolSet<> active, + const std::map<int, + Relation> &guards, + CG_outputRepr *guard_repr, + const Relation &known, + int indent, + CG_outputBuilder *ocg, + const std::vector<int> &remap, + const std::vector<Relation> &xforms, + const std::vector<CG_outputRepr *> &stmts, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > unin) { + //fprintf(stderr, "\n\nleaf_print_repr()\n"); + + if (active.num_elem() == 0) + return NULL; + + CG_outputRepr *stmt_list = NULL; + for (BoolSet<>::iterator i = active.begin(); i != active.end(); i++) { + std::map<int, Relation>::const_iterator j = guards.find(*i); + if (j == guards.end() || Must_Be_Subset(copy(known), copy(j->second))) { + Relation mapping = Inverse(copy((xforms[remap[*i]]))); + mapping.simplify(); + mapping.setup_names(); + std::vector<std::string> loop_vars; + for (int k = 1; k <= mapping.n_out(); k++) + loop_vars.push_back(mapping.output_var(k)->name()); + + + std::vector<CG_outputRepr *> sList = output_substitutions(ocg, + mapping, + assigned_on_the_fly, + unin[*i]); + + stmt_list = ocg->StmtListAppend(stmt_list, + ocg->CreateSubstitutedStmt( + (guard_repr==NULL)?indent:indent+1, + stmts[remap[*i]]->clone(), + loop_vars, + sList)); + active.unset(*i); + } } -} + + if (stmt_list != NULL) { + if (active.num_elem() != 0) + stmt_list = ocg->StmtListAppend(stmt_list, + leaf_print_repr(active, + guards, + NULL, + known, + (guard_repr==NULL)?indent:indent+1, + ocg, + remap, + xforms, + stmts, + assigned_on_the_fly, + unin)); + + if (guard_repr == NULL) + return stmt_list; + else { + fprintf(stderr, "CG_utils.cc leaf_print_repr() CreateIf()\n"); + return ocg->CreateIf(indent, guard_repr, stmt_list, NULL); + } + } + else { + Relation then_cond = + find_best_guard( + const_cast<std::map<int, Relation> &>(guards)[*(active.begin())], + active, guards); + + assert(!then_cond.is_obvious_tautology()); + Relation new_then_known = Intersection(copy(known), copy(then_cond)); + new_then_known.simplify(); + Relation else_cond = Complement(copy(then_cond)); + else_cond.simplify(); + Relation new_else_known = Intersection(copy(known), copy(else_cond)); + new_else_known.simplify(); + + BoolSet<> then_active(active.size()); + BoolSet<> else_active(active.size()); + BoolSet<> indep_active(active.size()); + std::map<int, Relation> then_guards, else_guards; + for (BoolSet<>::iterator i = active.begin(); i != active.end(); i++) { + Relation &r = const_cast<std::map<int, Relation> &>(guards)[*i]; + if (Must_Be_Subset(copy(r), copy(then_cond))) { + Relation r2 = Gist(copy(r), copy(then_cond), 1); + if (!r2.is_obvious_tautology()) + then_guards[*i] = r2; + then_active.set(*i); + } + else if (Must_Be_Subset(copy(r), copy(else_cond))) { + Relation r2 = Gist(copy(r), copy(else_cond), 1); + if (!r2.is_obvious_tautology()) + else_guards[*i] = r2; + else_active.set(*i); + } + else + indep_active.set(*i); + } + assert(!then_active.empty()); + + //Anand: adding support for Replacing substituted variables within + //Uninterpreted function symbols or global variables with arity > 0 here + //--begin + std::vector<std::pair<CG_outputRepr *, int> > aotf = assigned_on_the_fly; + + CG_outputRepr *new_guard_repr = output_guard(ocg, then_cond, aotf, + unin[*(active.begin())]); + if (else_active.empty() && indep_active.empty()) { + guard_repr = ocg->CreateAnd(guard_repr, new_guard_repr); + return leaf_print_repr(then_active, + then_guards, + guard_repr, + new_then_known, + indent, + ocg, + remap, + xforms, + stmts, + assigned_on_the_fly, + unin); + + + } + else if (else_active.empty() && !indep_active.empty()) { + int new_indent = (guard_repr==NULL)?indent:indent+1; + stmt_list = leaf_print_repr(then_active, + then_guards, + new_guard_repr, + new_then_known, + new_indent, + ocg, + remap, + xforms, + stmts, + assigned_on_the_fly, + unin); + + stmt_list = ocg->StmtListAppend(stmt_list, + leaf_print_repr(indep_active, + guards, + NULL, + known, + new_indent, + ocg, + remap, + xforms, + stmts, + assigned_on_the_fly, + unin)); + + if (guard_repr == NULL) + return stmt_list; + else { + fprintf(stderr, "CG_utils.cc leaf_print_repr() CreateIf() 2\n"); + return ocg->CreateIf(indent, guard_repr, stmt_list, NULL); + } + } + else { // (!else_active.empty()) + int new_indent = (guard_repr==NULL)?indent:indent+1; + + CG_outputRepr *then_stmt_list = leaf_print_repr(then_active, + then_guards, + NULL, + new_then_known, + new_indent+1, + ocg, + remap, + xforms, + stmts, + assigned_on_the_fly, + unin); + + CG_outputRepr *else_stmt_list = leaf_print_repr(else_active, + else_guards, + NULL, + new_else_known, + new_indent+1, + ocg, + remap, + xforms, + stmts, + assigned_on_the_fly, + unin); + + fprintf(stderr, "CG_utils.cc leaf_print_repr() CreateIf() 3\n"); + stmt_list = ocg->CreateIf(new_indent, + new_guard_repr, + then_stmt_list, + else_stmt_list); + + if (!indep_active.empty()) + stmt_list = ocg->StmtListAppend(stmt_list, + leaf_print_repr(indep_active, + guards, + NULL, + known, + new_indent, + ocg, + remap, + xforms, + stmts, + assigned_on_the_fly, + unin)); + + if (guard_repr == NULL) + return stmt_list; + else { + fprintf(stderr, "CG_utils.cc leaf_print_repr() CreateIf() 4\n"); + return ocg->CreateIf(indent, guard_repr, stmt_list, NULL); + } + } + } + } + + + + + + std::string print_to_iegen_string(Relation &R) { + std::string s = ""; + for (GEQ_Iterator e(R.single_conjunct()->GEQs()); e; e++) { + if (s != "") + s += " && "; + s += (*e).print_to_string(); + } + + for (EQ_Iterator e(R.single_conjunct()->EQs()); e; e++) { + if (s != "") + s += " && "; + s += (*e).print_to_string(); + } + return s; + } + // -// heavy lifting for code output for one leaf node +// Check if a set/input var is projected out of a inequality by a global variable with arity > 0 // -CG_outputRepr *leaf_print_repr(BoolSet<> active, const std::map<int, Relation> &guards, - CG_outputRepr *guard_repr, const Relation &known, - int indent, CG_outputBuilder *ocg, const std::vector<int> &remap, - const std::vector<Relation> &xforms, const std::vector<CG_outputRepr *> &stmts, - const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) { - if (active.num_elem() == 0) - return NULL; - - CG_outputRepr *stmt_list = NULL; - for (BoolSet<>::iterator i = active.begin(); i != active.end(); i++) { - std::map<int, Relation>::const_iterator j = guards.find(*i); - if (j == guards.end() || Must_Be_Subset(copy(known), copy(j->second))) { - Relation mapping = Inverse(copy((xforms[remap[*i]]))); - mapping.simplify(); - mapping.setup_names(); - std::vector<std::string> loop_vars; - for (int k = 1; k <= mapping.n_out(); k++) { - loop_vars.push_back(mapping.output_var(k)->name()); -// std::cout << "CG_Utils:: " << k << ", " << mapping.output_var(k)->name().c_str() << "\n"; + Relation checkAndRestoreIfProjectedByGlobal(const Relation &R1, + const Relation &R2, Variable_ID v) { + + Relation to_return(R2.n_set()); + +//1. detect if a variable is not involved in a GEQ. + for (DNF_Iterator di(copy(R1).query_DNF()); di; di++) + for (GEQ_Iterator ci = (*di)->GEQs(); ci; ci++) + if ((*ci).get_coef(v) != 0) + return copy(R2); + + bool found_global_eq = false; + Global_Var_ID g1; + EQ_Handle e; +//2. detect if its involved in an eq involving a global with arity >= 1 + for (DNF_Iterator di(copy(R1).query_DNF()); di; di++) + for (EQ_Iterator ci = (*di)->EQs(); ci; ci++) + if ((*ci).get_coef(v) != 0) + for (Constr_Vars_Iter cvi(*ci); cvi; cvi++) { + v = cvi.curr_var(); + if (v->kind() == Global_Var) + if (v->get_global_var()->arity() > 0) { + found_global_eq = true; + g1 = v->get_global_var(); + e = (*ci); + } + } + + if (!found_global_eq) + return copy(R2); + +//3. check if the global is involved in a geq + + bool found_global_lb = false; + bool found_global_ub = false; + + std::vector<GEQ_Handle> ub; + std::vector<GEQ_Handle> lb; + for (DNF_Iterator di(copy(R1).query_DNF()); di; di++) + for (GEQ_Iterator ci = (*di)->GEQs(); 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 + && v->get_global_var() == g1) { + if (cvi.curr_coef() > 0) { + found_global_lb = true; + + lb.push_back(*ci); + } + else if (cvi.curr_coef() < 0) { + found_global_ub = true; + + ub.push_back(*ci); + } + + } + } + + if (!found_global_lb || !found_global_ub) + return copy(R2); + +// + + F_And *root = to_return.add_and(); + + for (int i = 0; i < lb.size(); i++) { + GEQ_Handle lower = root->add_GEQ(); + for (Constr_Vars_Iter cvi(lb[i]); cvi; cvi++) { + Variable_ID v2 = cvi.curr_var(); + + if (v2->kind() == Wildcard_Var) + return copy(R2); + if (v2->kind() != Global_Var + || (v2->kind() == Global_Var && v2->get_global_var() != g1)) { + if (v2->kind() != Global_Var) + lower.update_coef(v2, cvi.curr_coef()); + else { + Variable_ID lb1 = to_return.get_local(v2->get_global_var(), + Input_Tuple); + lower.update_coef(lb1, cvi.curr_coef()); + } + + } + else + lower.update_coef(v, cvi.curr_coef()); } - std::vector<CG_outputRepr *> sList = output_substitutions(ocg, mapping, assigned_on_the_fly); - stmt_list = ocg->StmtListAppend(stmt_list, ocg->CreateSubstitutedStmt((guard_repr==NULL)?indent:indent+1, stmts[remap[*i]]->clone(), loop_vars, sList)); - active.unset(*i); + + lower.update_const(lb[i].get_const()); } + + for (int i = 0; i < ub.size(); i++) { + GEQ_Handle upper = root->add_GEQ(); + for (Constr_Vars_Iter cvi(ub[i]); cvi; cvi++) { + Variable_ID v2 = cvi.curr_var(); + + if (v2->kind() == Wildcard_Var) + return copy(R2); + if (v2->kind() != Global_Var + || (v2->kind() == Global_Var && v2->get_global_var() != g1)) { + if (v2->kind() != Global_Var) + upper.update_coef(v2, cvi.curr_coef()); + else { + Variable_ID ub1 = to_return.get_local(v2->get_global_var(), + Input_Tuple); + upper.update_coef(ub1, cvi.curr_coef()); + } + + } + else + upper.update_coef(v, cvi.curr_coef()); + } + + upper.update_const(ub[i].get_const()); + } + +//Relation to_return2 = copy(R2); + + for (EQ_Iterator g(const_cast<Relation &>(R2).single_conjunct()->EQs()); g; + g++) + to_return.and_with_EQ(*g); + + for (GEQ_Iterator g(const_cast<Relation &>(R2).single_conjunct()->GEQs()); + g; g++) { + bool found_glob = false; + for (Constr_Vars_Iter cvi(*g); cvi; cvi++) { + Variable_ID v2 = cvi.curr_var(); + if (v2->kind() == Global_Var && v2->get_global_var() == g1) { + found_glob = true; + break; + } + } + if (!found_glob) + to_return.and_with_GEQ(*g); + + } +//to_return.and_with_EQ(e); + + to_return.copy_names(copy(R2)); + to_return.setup_names(); + to_return.finalize(); + return to_return; } - - if (stmt_list != NULL) { - if (active.num_elem() != 0) - stmt_list = ocg->StmtListAppend(stmt_list, leaf_print_repr(active, guards, NULL, known, (guard_repr==NULL)?indent:indent+1, ocg, remap, xforms, stmts, assigned_on_the_fly)); - if (guard_repr == NULL) - return stmt_list; - else - return ocg->CreateIf(indent, guard_repr, stmt_list, NULL); +/*Relation addInequalitiesToRelation(const Relation &R, + std::vector<GEQ_Handle> &inequalities) { + Relation to_return(R.n_set()); + + return to_return; } - else { - Relation then_cond = find_best_guard(const_cast<std::map<int, Relation> &>(guards)[*(active.begin())], active, guards); + +*/ + + + + + +// +// heavy lifting for code output for one level of loop nodes +// + CG_outputRepr *loop_print_repr(BoolSet<> active, + const std::vector<CG_loop *> &loops, + int start, + int end, + const Relation &guard, + CG_outputRepr *guard_repr, + int indent, + const std::vector<int> &remap, + const std::vector<Relation> &xforms, + CG_outputBuilder *ocg, + const std::vector<CG_outputRepr *> &stmts, + const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly, + std::vector<std::map<std::string, std::vector<CG_outputRepr *> > > unin) { + + fprintf(stderr, "loop_print_repr() guard_repr "); + if (guard_repr == NULL) fprintf(stderr, "NULL\n"); + else fprintf(stderr, "NOT NULL\n"); + + if (start >= end) + return NULL; + + Relation R = Gist(copy(loops[start]->guard_), copy(guard), 1); + if (Must_Be_Subset(Intersection(copy(loops[start]->known_), copy(guard)), + copy(R))) { + int new_indent = (guard_repr==NULL)?indent:indent+1; + int i = start+1; + for ( ; i < end; i++) + if (!Gist(copy(loops[i]->guard_), copy(guard), 1).is_obvious_tautology()) + break; + CG_outputRepr *stmt_list = NULL; + for (int j = start; j < i; j++) + stmt_list = ocg->StmtListAppend(stmt_list, + loops[j]->printRepr(false, + new_indent, + ocg, + stmts, + assigned_on_the_fly, + unin)); + + fprintf(stderr,"CG_utils.cc loop_print_repr recursive\n"); + stmt_list = ocg->StmtListAppend(stmt_list, + loop_print_repr(active, + loops, + i, + end, + guard, + NULL, + new_indent, + remap, + xforms, + ocg, + stmts, + assigned_on_the_fly, + unin)); + + //fprintf(stderr, "guard_repr 0x%x\n", guard_repr); + if (guard_repr == NULL) + return stmt_list; + else { + fprintf(stderr, "CG_utils.cc loop_print_repr() CreateIf()\n"); + return ocg->CreateIf(indent, guard_repr, stmt_list, NULL); + } + } + + Relation then_cond = find_best_guard(R, loops, start, end); + fprintf(stderr, "then_cond "); then_cond.print(stderr); assert(!then_cond.is_obvious_tautology()); - Relation new_then_known = Intersection(copy(known), copy(then_cond)); - new_then_known.simplify(); Relation else_cond = Complement(copy(then_cond)); else_cond.simplify(); - Relation new_else_known = Intersection(copy(known), copy(else_cond)); - new_else_known.simplify(); - BoolSet<> then_active(active.size()), else_active(active.size()), indep_active(active.size()); - std::map<int, Relation> then_guards, else_guards; - for (BoolSet<>::iterator i = active.begin(); i != active.end(); i++) { - Relation &r = const_cast<std::map<int, Relation> &>(guards)[*i]; - if (Must_Be_Subset(copy(r), copy(then_cond))) { - Relation r2 = Gist(copy(r), copy(then_cond), 1); - if (!r2.is_obvious_tautology()) - then_guards[*i] = r2; - then_active.set(*i); - } - else if (Must_Be_Subset(copy(r), copy(else_cond))) { - Relation r2 = Gist(copy(r), copy(else_cond), 1); - if (!r2.is_obvious_tautology()) - else_guards[*i] = r2; - else_active.set(*i); - } - else - indep_active.set(*i); - } - assert(!then_active.empty()); + std::vector<CG_loop *> then_loops, else_loops, indep_loops; + int i = start; + for ( ; i < end; i++) + if (!Must_Be_Subset(copy(loops[i]->guard_), copy(then_cond))) + break; + int j = i; + for ( ; j < end; j++) + if (!Must_Be_Subset(copy(loops[j]->guard_), copy(else_cond))) + break; + assert(i>start); - CG_outputRepr *new_guard_repr = output_guard(ocg, then_cond, assigned_on_the_fly); - if (else_active.empty() && indep_active.empty()) { + //Anand: adding support for Replacing substituted variables within + //Uninterpreted function symbols or global variables with arity > 0 here + //--begin + std::vector<std::pair<CG_outputRepr *, int> > aotf = assigned_on_the_fly; + CG_outputRepr *new_guard_repr = output_guard(ocg, then_cond, aotf, unin[*(active.begin())]); + + //fprintf(stderr, "new_guard_repr 0x%x\n", new_guard_repr); + if (j == i && end == j) { guard_repr = ocg->CreateAnd(guard_repr, new_guard_repr); - return leaf_print_repr(then_active, then_guards, guard_repr, new_then_known, indent, ocg, remap, xforms, stmts, assigned_on_the_fly); + Relation new_guard = Intersection(copy(guard), copy(then_cond)); + new_guard.simplify(); + fprintf(stderr,"CG_utils.cc loop_print_repr recursive 2\n"); + return loop_print_repr(active, loops, start, end, new_guard, guard_repr, + indent, remap, xforms, ocg, stmts, aotf, unin); } - else if (else_active.empty() && !indep_active.empty()) { + else if (j == i && end > j) { int new_indent = (guard_repr==NULL)?indent:indent+1; - stmt_list = leaf_print_repr(then_active, then_guards, new_guard_repr, new_then_known, new_indent, ocg, remap, xforms, stmts, assigned_on_the_fly); - stmt_list = ocg->StmtListAppend(stmt_list, leaf_print_repr(indep_active, guards, NULL, known, new_indent, ocg, remap, xforms, stmts, assigned_on_the_fly)); + Relation new_guard = Intersection(copy(guard), copy(then_cond)); + new_guard.print(stderr); + new_guard.print_with_subs(stderr); + new_guard.simplify(); + new_guard.print(stderr); + new_guard.print_with_subs(stderr); + + fprintf(stderr,"CG_utils.cc loop_print_repr recursive 3\n"); + CG_outputRepr *stmt_list = loop_print_repr(active, + loops, + start, + i, + new_guard, + new_guard_repr, + new_indent, + remap, + xforms, + ocg, + stmts, + aotf, + unin); + + fprintf(stderr,"CG_utils.cc loop_print_repr recursive 4\n"); + stmt_list = ocg->StmtListAppend(stmt_list, + loop_print_repr(active, + loops, + j, + end, + guard, + NULL, + new_indent, + remap, + xforms, + ocg, + stmts, + aotf, + unin)); + if (guard_repr == NULL) return stmt_list; - else + else { + fprintf(stderr, "CG_utils.cc loop_print_repr() CreateIf() 2\n"); return ocg->CreateIf(indent, guard_repr, stmt_list, NULL); + } } - else { // (!else_active.empty()) + else { // (j > i) int new_indent = (guard_repr==NULL)?indent:indent+1; - CG_outputRepr *then_stmt_list = leaf_print_repr(then_active, then_guards, NULL, new_then_known, new_indent+1, ocg, remap, xforms, stmts, assigned_on_the_fly); - CG_outputRepr *else_stmt_list = leaf_print_repr(else_active, else_guards, NULL, new_else_known, new_indent+1, ocg, remap, xforms, stmts, assigned_on_the_fly); - stmt_list = ocg->CreateIf(new_indent, new_guard_repr, then_stmt_list, else_stmt_list); - if (!indep_active.empty()) - stmt_list = ocg->StmtListAppend(stmt_list, leaf_print_repr(indep_active, guards, NULL, known, new_indent, ocg, remap, xforms, stmts, assigned_on_the_fly)); + Relation then_new_guard = Intersection(copy(guard), copy(then_cond)); + then_new_guard.simplify(); + + fprintf(stderr,"CG_utils.cc loop_print_repr recursive 5\n"); + CG_outputRepr *then_stmt_list = loop_print_repr(active, + loops, + start, + i, + then_new_guard, + NULL, + new_indent+1, + remap, + xforms, + ocg, + stmts, + aotf, + unin); + + Relation else_new_guard = Intersection(copy(guard), copy(else_cond)); + else_new_guard.simplify(); + + fprintf(stderr,"CG_utils.cc loop_print_repr recursive 6\n"); + CG_outputRepr *else_stmt_list = loop_print_repr(active, + loops, + i, + j, + else_new_guard, + NULL, + new_indent+1, + remap, + xforms, + ocg, + stmts, + aotf, + unin); + + fprintf(stderr, "CG_utils.cc loop_print_repr() CreateIf() 3\n"); + CG_outputRepr *stmt_list = ocg->CreateIf(new_indent, + new_guard_repr, + then_stmt_list, + else_stmt_list); + + fprintf(stderr,"CG_utils.cc loop_print_repr recursive 7\n"); + stmt_list = ocg->StmtListAppend(stmt_list, + loop_print_repr(active, + loops, + j, + end, + guard, + NULL, + new_indent, + remap, + xforms, + ocg, + stmts, + aotf, + unin)); + + if (guard_repr == NULL) return stmt_list; - else + else { + fprintf(stderr, "CG_utils.cc loop_print_repr() CreateIf() 4\n"); return ocg->CreateIf(indent, guard_repr, stmt_list, NULL); + } } } -} - - -// -// heavy lifting for code output for one level of loop nodes -// -CG_outputRepr *loop_print_repr(const std::vector<CG_loop *> &loops, int start, int end, - const Relation &guard, CG_outputRepr *guard_repr, - int indent, CG_outputBuilder *ocg, const std::vector<CG_outputRepr *> &stmts, - const std::vector<std::pair<CG_outputRepr *, int> > &assigned_on_the_fly) { - if (start >= end) - return NULL; - - Relation R = Gist(copy(loops[start]->guard_), copy(guard), 1); - if (Must_Be_Subset(Intersection(copy(loops[start]->known_), copy(guard)), copy(R))) { - int new_indent = (guard_repr==NULL)?indent:indent+1; - int i = start+1; - for ( ; i < end; i++) - if (!Gist(copy(loops[i]->guard_), copy(guard), 1).is_obvious_tautology()) - break; - CG_outputRepr *stmt_list = NULL; - for (int j = start; j < i; j++) - stmt_list = ocg->StmtListAppend(stmt_list, loops[j]->printRepr(false, new_indent, ocg, stmts, assigned_on_the_fly)); - stmt_list = ocg->StmtListAppend(stmt_list, loop_print_repr(loops, i, end, guard, NULL, new_indent, ocg, stmts, assigned_on_the_fly)); - if (guard_repr == NULL) - return stmt_list; - else - return ocg->CreateIf(indent, guard_repr, stmt_list, NULL); - } - - Relation then_cond = find_best_guard(R, loops, start, end); - assert(!then_cond.is_obvious_tautology()); - Relation else_cond = Complement(copy(then_cond)); - else_cond.simplify(); - std::vector<CG_loop *> then_loops, else_loops, indep_loops; - int i = start; - for ( ; i < end; i++) - if (!Must_Be_Subset(copy(loops[i]->guard_), copy(then_cond))) - break; - int j = i; - for ( ; j < end; j++) - if (!Must_Be_Subset(copy(loops[j]->guard_), copy(else_cond))) - break; - assert(i>start); - - CG_outputRepr *new_guard_repr = output_guard(ocg, then_cond, assigned_on_the_fly); - if (j == i && end == j) { - guard_repr = ocg->CreateAnd(guard_repr, new_guard_repr); - Relation new_guard = Intersection(copy(guard), copy(then_cond)); - new_guard.simplify(); - return loop_print_repr(loops, start, end, new_guard, guard_repr, indent, ocg, stmts, assigned_on_the_fly); - } - else if (j == i && end > j) { - int new_indent = (guard_repr==NULL)?indent:indent+1; - Relation new_guard = Intersection(copy(guard), copy(then_cond)); - new_guard.simplify(); - CG_outputRepr *stmt_list = loop_print_repr(loops, start, i, new_guard, new_guard_repr, new_indent, ocg, stmts, assigned_on_the_fly); - stmt_list = ocg->StmtListAppend(stmt_list, loop_print_repr(loops, j, end, guard, NULL, new_indent, ocg, stmts, assigned_on_the_fly)); - if (guard_repr == NULL) - return stmt_list; - else - return ocg->CreateIf(indent, guard_repr, stmt_list, NULL); - } - else { // (j > i) - int new_indent = (guard_repr==NULL)?indent:indent+1; - Relation then_new_guard = Intersection(copy(guard), copy(then_cond)); - then_new_guard.simplify(); - CG_outputRepr *then_stmt_list = loop_print_repr(loops, start, i, then_new_guard, NULL, new_indent+1, ocg, stmts, assigned_on_the_fly); - Relation else_new_guard = Intersection(copy(guard), copy(else_cond)); - else_new_guard.simplify(); - CG_outputRepr *else_stmt_list = loop_print_repr(loops, i, j, else_new_guard, NULL, new_indent+1, ocg, stmts, assigned_on_the_fly); - CG_outputRepr *stmt_list = ocg->CreateIf(new_indent, new_guard_repr, then_stmt_list, else_stmt_list); - stmt_list = ocg->StmtListAppend(stmt_list, loop_print_repr(loops, j, end, guard, NULL, new_indent, ocg, stmts, assigned_on_the_fly)); - if (guard_repr == NULL) - return stmt_list; - else - return ocg->CreateIf(indent, guard_repr, stmt_list, NULL); - } -} - } diff --git a/lib/rosecg/CMakeLists.txt b/lib/rosecg/CMakeLists.txt deleted file mode 100644 index 4da3bcf..0000000 --- a/lib/rosecg/CMakeLists.txt +++ /dev/null @@ -1,21 +0,0 @@ -set(CODEGEN_ROSE_SRC - src/CG_roseBuilder.cc - src/CG_roseRepr.cc - src/rose_attributes.cc - ) - -include_directories( - include - ${OMEGA_INC} - ${ROSEHOME}/include - ${ROSEHOME}/include/rose - ${BOOSTHOME}/include - ) - -add_library(rosecg ${CODEGEN_ROSE_SRC}) - -install(TARGETS rosecg - DESTINATION lib) - -install(DIRECTORY include/code_gen - DESTINATION include) diff --git a/lib/rosecg/include/code_gen/CG_roseBuilder.h b/lib/rosecg/include/code_gen/CG_roseBuilder.h deleted file mode 100644 index ca33f7e..0000000 --- a/lib/rosecg/include/code_gen/CG_roseBuilder.h +++ /dev/null @@ -1,108 +0,0 @@ -#ifndef CG_roseBuilder_h -#define CG_roseBuilder_h - -#include <basic/Tuple.h> -#include "code_gen/rose_attributes.h" -#include <code_gen/CG_outputBuilder.h> -#include "code_gen/CG_roseRepr.h" -#include <string> - -namespace omega { - -class CG_roseBuilder : public CG_outputBuilder { -public: - CG_roseBuilder(int isFortran, SgGlobal* global, SgGlobal* global_scope, SgSymbolTable* symtab1, SgSymbolTable* symtab2, SgNode* root); - ~CG_roseBuilder(); - - //! substitute variables in stmt - CG_outputRepr *CreateSubstitutedStmt(int indent, CG_outputRepr *stmt, - const std::vector<std::string> &vars, - std::vector<CG_outputRepr *> &subs) const; - - - - //! assignment generation - CG_outputRepr* CreateAssignment(int indent, CG_outputRepr* lhs, - CG_outputRepr* rhs) const; - - //! function invocation generation - CG_outputRepr* CreateInvoke(const std::string &funcName, - std::vector<CG_outputRepr *> &argList) const; - - //! comment generation - CG_outputRepr* CreateComment(int indent, const std::string &commentText) const; - //! Attribute generation - CG_outputRepr* CreateAttribute(CG_outputRepr *control, - const std::string &commentText) const; - //! Pragma Attribute - CG_outputRepr* CreatePragmaAttribute(CG_outputRepr *scopeStmt, int looplevel, - const std::string &pragmaText) const; - - //! Prefetch Attribute - CG_outputRepr* CreatePrefetchAttribute(CG_outputRepr *scopeStmt, int looplevel, - const std::string &arrName, int hint) const; - - //! if stmt gen operations - CG_outputRepr* CreateIf(int indent, CG_outputRepr* guardCondition, - CG_outputRepr* true_stmtList, CG_outputRepr* false_stmtList) const; - - //! inductive variable generation, to be used in CreateLoop as control - CG_outputRepr* CreateInductive(CG_outputRepr* index, - CG_outputRepr* lower, - CG_outputRepr* upper, - CG_outputRepr* step) const; - - //! loop stmt generation - CG_outputRepr* CreateLoop(int indent, CG_outputRepr* control, - CG_outputRepr* stmtList) const; - - CG_outputRepr* CreateInt(int num ) const; - bool isInteger(CG_outputRepr *op) const; - CG_outputRepr* CreateIdent(const std::string &varName) const; - - //! binary arithmetic operations - CG_outputRepr* CreatePlus(CG_outputRepr* lop, CG_outputRepr* rop) const; - CG_outputRepr* CreateMinus(CG_outputRepr* lop, CG_outputRepr* rop) const; - CG_outputRepr* CreateTimes(CG_outputRepr* lop, CG_outputRepr* rop) const; - CG_outputRepr* CreateIntegerFloor(CG_outputRepr* lop, CG_outputRepr* rop) const; - CG_outputRepr* CreateIntegerMod(CG_outputRepr* lop, CG_outputRepr* rop) const; - - //! binary logical operations - CG_outputRepr* CreateAnd(CG_outputRepr* lop, CG_outputRepr* rop) const; - - //--------------------------------------------------------------------------- - // binary relational operations - //--------------------------------------------------------------------------- - // CG_outputRepr* CreateGE(CG_outputRepr*, CG_outputRepr*) const; - CG_outputRepr* CreateLE(CG_outputRepr* lop, CG_outputRepr* rop) const; - CG_outputRepr* CreateEQ(CG_outputRepr* lop, CG_outputRepr* rop) const; - - //--------------------------------------------------------------------------- - // stmt list gen operations - //--------------------------------------------------------------------------- - CG_outputRepr* - StmtListAppend(CG_outputRepr* list1, CG_outputRepr* list2) const; - - CG_outputRepr* CreateDim3(const char* varName, CG_outputRepr* arg1, CG_outputRepr* arg2, CG_outputRepr* arg3 = NULL) const; - - // Manu:: added for fortran support - bool isInputFortran() const; - -private: - SgSymbolTable *symtab_; - SgSymbolTable *symtab2_; - SgNode* root_; - SgGlobal* global_; - SgGlobal* global_scope; - int isFortran; // Manu:: added for fortran support -}; - -extern char *k_ocg_comment; -std::vector<SgVarRefExp *>substitute(SgNode *tnl, const SgVariableSymbol *sym, SgExpression *expr,SgNode* root) ; - - - - -} // namespace - -#endif diff --git a/lib/rosecg/include/code_gen/CG_roseRepr.h b/lib/rosecg/include/code_gen/CG_roseRepr.h deleted file mode 100644 index 28553e7..0000000 --- a/lib/rosecg/include/code_gen/CG_roseRepr.h +++ /dev/null @@ -1,46 +0,0 @@ -#ifndef CG_roseRepr_h -#define CG_roseRepr_h - -#include <code_gen/CG_outputRepr.h> -#include "rose.h" - -namespace omega { - -class CG_roseRepr : public CG_outputRepr { - friend class CG_roseBuilder; -public: - CG_roseRepr(); - CG_roseRepr(SgNode *tnl); - CG_roseRepr(SgExpression *exp); - CG_roseRepr(SgStatementPtrList* stmtlist); - - ~CG_roseRepr(); - CG_outputRepr *clone() const; - void clear(); - - SgNode* GetCode() const; - SgStatementPtrList* GetList() const; - SgExpression *GetExpression() const; - - - - - //--------------------------------------------------------------------------- - // Dump operations - //--------------------------------------------------------------------------- - void Dump() const; -private: - // only one of _tnl and _op would be active at any time, depending on - // whether it is building a statement list or an expression tree - SgNode *tnl_; - SgExpression *op_; - SgStatementPtrList *list_; - void DumpFileHelper(SgNode* node, FILE* fp) const; - //operand op_; -}; - - - -} // namespace - -#endif diff --git a/lib/rosecg/include/code_gen/rose_attributes.h b/lib/rosecg/include/code_gen/rose_attributes.h deleted file mode 100644 index 9766f52..0000000 --- a/lib/rosecg/include/code_gen/rose_attributes.h +++ /dev/null @@ -1,91 +0,0 @@ -#ifndef ROSE_ATTRIBUTES_HH -#define ROSE_ATTRIBUTES_HH - -#include "rose.h" -#include <algorithm> -#include <string> -#include <vector> - -namespace omega { - -class CodeInsertion; - -typedef std::vector<CodeInsertion*> CodeInsertionPtrList; -typedef std::vector<CodeInsertion*>::iterator CodeInsertionPtrListItr; - -class CodeInsertion { -public: - int loop_level; - bool marked; - CodeInsertion(int looplevel) { this->loop_level = looplevel; marked = false; } - ~CodeInsertion() {} - virtual SgStatement* getStatement(SgScopeStatement* scopeStmt = NULL) = 0; -}; - -class PragmaInsertion : public CodeInsertion { -private: - std::string name; -public: - PragmaInsertion(int loop_level, const std::string &pragma) : CodeInsertion(loop_level) { this->name = std::string(pragma); } - ~PragmaInsertion() { } - virtual SgStatement* getStatement(SgScopeStatement* scopeStmt = NULL); -}; - -class MMPrefetchInsertion : public CodeInsertion { -private: - std::string arrName; - std::vector<std::string*> indecies; - std::vector<int> offsets; - int indexCount; - int cacheHint; - void initialize(const std::string& arrName, int hint); - void addDim(int offset); - void addDim(int offset, const std::string& indexer); - SgExpression* buildArrArg(SgScopeStatement* scopeStmt); - SgExpression* makeIndexExp(int dim, SgScopeStatement* scopeStmt); -public: - MMPrefetchInsertion(int loop_level, const std::string &arr, int hint) : CodeInsertion(loop_level) - { this->initialize(arr, hint); } - ~MMPrefetchInsertion() { } - virtual SgStatement* getStatement(SgScopeStatement* scopeStmt = NULL); -}; - -class CodeInsertionAttribute : public AstAttribute { -private: - std::vector<CodeInsertion*> code_insertions; -public: - CodeInsertionAttribute() { code_insertions = std::vector<CodeInsertion*>(); } - ~CodeInsertionAttribute() {} - - void add(CodeInsertion* ci) { code_insertions.push_back(ci); } - CodeInsertionPtrListItr begin() { return code_insertions.begin(); } - CodeInsertionPtrListItr end() { return code_insertions.end(); } - void remove(CodeInsertion* ci) { std::remove(code_insertions.begin(), code_insertions.end(), ci); } - int countCodeInsertions() { return code_insertions.size(); } -}; - -struct CodeInsertionMark { -public: - SgStatement* stmt; - CodeInsertion* ci; -}; - -class CodeInsertionVisitor : public AstPrePostProcessing { -private: - int loop_level; - std::vector<CodeInsertionMark*> ci_marks; - void markStmt(SgStatement* stmt, CodeInsertion* ci); -public: - void initialize(); - virtual void preOrderVisit(SgNode* n); - virtual void postOrderVisit(SgNode* n); - void insertCode(); -}; - -void postProcessRoseCodeInsertion(SgProject* proj); -void copyAttributes(SgNode* s, SgNode* d); -CodeInsertionAttribute* getOrCreateCodeInsertionAttribute(SgNode* node); - -} - -#endif diff --git a/lib/rosecg/src/CG_roseBuilder.cc b/lib/rosecg/src/CG_roseBuilder.cc deleted file mode 100644 index 8f7e3df..0000000 --- a/lib/rosecg/src/CG_roseBuilder.cc +++ /dev/null @@ -1,1093 +0,0 @@ -/***************************************************************************** - Copyright (C) 2008 University of Southern California - Copyright (C) 2009-2010 University of Utah - All Rights Reserved. - - Purpose: - generate suif code for omega - - Notes: - - History: - 02/01/06 created by Chun Chen - *****************************************************************************/ - -#include <stack> -#include "code_gen/CG_roseBuilder.h" -#include <string> - -struct ir_error: public std::runtime_error { - ir_error(const std::string &msg) : - std::runtime_error(msg) { - } -}; - -using namespace SageBuilder; -using namespace SageInterface; -using namespace OmpSupport; - -namespace omega { - -//----------------------------------------------------------------------------- -// make suif initilization happy -//----------------------------------------------------------------------------- -char *k_ocg_comment; - -CG_roseBuilder::CG_roseBuilder(int is_fortran, SgGlobal* global, SgGlobal* firstScope, - SgSymbolTable* symtab, SgSymbolTable* symtab2, SgNode* root) : - isFortran(is_fortran), global_(global), global_scope(firstScope), symtab_(symtab), symtab2_( - symtab2), root_(root) { -} - - -CG_roseBuilder::~CG_roseBuilder() { -} - -// Manu:: returns true if input is in fortran, else returns false -bool CG_roseBuilder::isInputFortran() const{ - if (isFortran) - return true; - else - return false; -} - -//----------------------------------------------------------------------------- -// place holder generation -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreateSubstitutedStmt(int, CG_outputRepr *stmt, - const std::vector<std::string> &vars, std::vector<CG_outputRepr*> &subs) const { - - SgStatementPtrList* list = static_cast<CG_roseRepr *>(stmt)->list_; - SgNode *tnl; - SgStatement* statement; - if (list != NULL) { - delete stmt; - for (int i = 0; i < subs.size(); i++) { - if (subs[i] == NULL) - continue; - - CG_roseRepr *repr = static_cast<CG_roseRepr*>(subs[i]); - SgExpression* op = repr->op_; - - for (SgStatementPtrList::iterator it = (*list).begin(); - it != (*list).end(); it++) { - statement = (*it); - tnl = isSgNode(statement); - - int j; - int not_in_symtab_; - - not_in_symtab_ = 0; - - SgVariableSymbol *vs = symtab_->find_variable( - SgName(vars[i].c_str())); - - if (vs == NULL) { - - not_in_symtab_ = 1; - - vs = symtab2_->find_variable(SgName(vars[i].c_str())); - } - if (vs != NULL) { - - std::vector<SgVarRefExp *> array = substitute(tnl, - (const SgVariableSymbol*) vs, op, root_); - for (std::vector<SgVarRefExp *>::iterator it = - array.begin(); it != array.end(); it++) { - - if (isSgVarRefExp(op)) { - if (strcmp( - isSgVarRefExp(op)->get_symbol()->get_name().getString().c_str(), - vs->get_name().getString().c_str())) { - - (*it)->set_symbol( - isSgVarRefExp(op)->get_symbol()); - - } - } else if (isSgExpression(op)) { - - if (isSgBinaryOp((*it)->get_parent())) - isSgBinaryOp((*it)->get_parent())->replace_expression( - *it, op); - else if (isSgUnaryOp((*it)->get_parent())) - isSgUnaryOp((*it)->get_parent())->replace_expression( - *it, op); - else if (isSgExprListExp((*it)->get_parent())) - isSgExprListExp((*it)->get_parent())->replace_expression( - *it, op); - else - throw ir_error("unrecognized expression type"); - } - - } - } - - } - - delete repr; - subs[i] = NULL; - - if (subs[i] != NULL) - throw ir_error("not freed properly"); - - } - - return new CG_roseRepr(list); - - } else { - tnl = static_cast<CG_roseRepr *>(stmt)->tnl_; - - if (tnl == NULL) - throw ir_error("both list and tnl are null!!"); - - delete stmt; - int j; - int not_in_symtab_; - for (int i = 0; i < subs.size(); i++) { - if (subs[i] == NULL) - continue; - not_in_symtab_ = 0; - - - CG_roseRepr *repr = static_cast<CG_roseRepr*>(subs[i]); - SgExpression* op = repr->op_; - delete repr; - subs[i] = NULL; - - SgVariableSymbol *vs = symtab_->find_variable( - SgName(vars[i].c_str())); - - if (vs == NULL) { - - not_in_symtab_ = 1; - - vs = symtab2_->find_variable(SgName(vars[i].c_str())); - } - if (vs != NULL) { - std::vector<SgVarRefExp *> array = substitute(tnl, vs, op, - root_); - - if (not_in_symtab_ && isSgVarRefExp(op)) { - if (strcmp( - isSgVarRefExp(op)->get_symbol()->get_name().getString().c_str(), - vs->get_name().getString().c_str())) { - } - } - - for (std::vector<SgVarRefExp *>::iterator j = array.begin(); - j != array.end(); j++) { - - if (isSgVarRefExp(op)) { - if (strcmp( - isSgVarRefExp(op)->get_symbol()->get_name().getString().c_str(), - vs->get_name().getString().c_str())) { - (*j)->set_symbol(isSgVarRefExp(op)->get_symbol()); - - } - } else if (isSgExpression(op)) { - - if (isSgBinaryOp((*j)->get_parent())) - isSgBinaryOp((*j)->get_parent())->replace_expression( - *j, op); - else if (isSgUnaryOp((*j)->get_parent())) - isSgUnaryOp((*j)->get_parent())->replace_expression( - *j, op); - else if (isSgExprListExp((*j)->get_parent())) { // Manu:: fortran indices are stored this way - isSgExprListExp((*j)->get_parent())->replace_expression(*j, op); - } - else - throw ir_error("unrecognized expression type"); - - } - - } - } - } - return new CG_roseRepr(tnl); - } - -} - -//----------------------------------------------------------------------------- -// assignment generation -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreateAssignment(int, CG_outputRepr *lhs, - CG_outputRepr *rhs) const { - if (lhs == NULL || rhs == NULL) { - fprintf(stderr, "Code generation: Missing lhs or rhs\n"); - return NULL; - } - - SgExpression* src = static_cast<CG_roseRepr*>(rhs)->op_; - SgExpression* dst = static_cast<CG_roseRepr*>(lhs)->op_; - - SgExprStatement* ins = buildAssignStatement(dst, src); - src->set_parent(ins); - dst->set_parent(ins); - - SgStatementPtrList* new_list = new SgStatementPtrList; - - (*new_list).push_back(isSgStatement(ins)); - - delete lhs; - delete rhs; - - return new CG_roseRepr(new_list); - -} - -//----------------------------------------------------------------------------- -// function invocation generation -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreateInvoke(const std::string &fname, - std::vector<CG_outputRepr *> &list) const { - - if (fname == std::string("max") || fname == std::string("min")) { - if (list.size() == 0) { - return NULL; - } else if (list.size() == 1) { - return list[0]; - } else { - int last = list.size() - 1; - SgExpression* op2 = static_cast<CG_roseRepr*>(list[last])->op_; - delete list[last]; - list.erase(list.end()-1); - CG_roseRepr *repr = static_cast<CG_roseRepr*>(CreateInvoke(fname, - list)); - SgExpression* op1 = repr->op_; - - - SgExpression *ins; - SgExprListExp* arg_list = buildExprListExp(); - appendExpression(arg_list, op1); - appendExpression(arg_list, op2); - SgVarRefExp* opaque_var; - - - if (fname == std::string("max")) { - opaque_var = buildOpaqueVarRefExp("__rose_gt", global_); - ins = isSgExpression(buildFunctionCallExp(opaque_var, arg_list)); - - // Manu:: fortran support - if (isInputFortran()) { - SgName fName("merge"); - SgTypeInt *retType = buildIntType(); - - SgExpression *cond = static_cast<CG_roseRepr *>(CreateLE(new CG_roseRepr(op2), new CG_roseRepr(op1)))->op_; - appendExpression(arg_list, cond); - ins = isSgExpression(buildFunctionCallExp(fName, retType, arg_list, global_)); - } - - } else { - opaque_var = buildOpaqueVarRefExp("__rose_lt", global_); - ins = isSgExpression(buildFunctionCallExp(opaque_var, arg_list)); - - // Manu:: fortran support - if (isInputFortran()) { - SgName fName("merge"); - SgTypeInt *retType = buildIntType(); - - SgExpression *cond = static_cast<CG_roseRepr *>(CreateLE(new CG_roseRepr(op1), new CG_roseRepr(op2)))->op_; - appendExpression(arg_list, cond); - ins = isSgExpression(buildFunctionCallExp(fName, retType, arg_list, global_)); - } - - } - - repr->op_ = ins; - return repr; - } - } else { - fprintf(stderr, - "Code generation: invoke function io_call not implemented\n"); - return NULL; - } - -} - -//----------------------------------------------------------------------------- -// comment generation -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreateComment(int, - const std::string &commentText) const { - if (commentText == std::string("")) { - return NULL; - } - - SgLocatedNode *tnl = new SgLocatedNode(); - buildComment(tnl, "//omega_comment: " + commentText); - - return new CG_roseRepr(isSgNode(tnl)); - -} - -//----------------------------------------------------------------------------- -// if stmt gen operations -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreateIf(int, CG_outputRepr *guardList, - CG_outputRepr *true_stmtList, CG_outputRepr *false_stmtList) const { - - if (true_stmtList == NULL && false_stmtList == NULL) { - delete guardList; - return NULL; - } else if (guardList == NULL) { - return StmtListAppend(true_stmtList, false_stmtList); - } - - SgExpression* header = static_cast<CG_roseRepr*>(guardList)->op_; - - SgStatementPtrList *then_part1, *else_part1; - SgStatement* then_part; - SgStatement* else_part; - SgBasicBlock* then_part2; - SgBasicBlock* else_part2; - if (true_stmtList != NULL) { - then_part1 = static_cast<CG_roseRepr*>(true_stmtList)->list_; - if (then_part1 != NULL) { - then_part = *((*then_part1).begin()); - - if ((*then_part1).size() > 1) { - then_part2 = buildBasicBlock(); - for (SgStatementPtrList::iterator it = (*then_part1).begin(); - it != (*then_part1).end(); it++) { - then_part2->append_statement(*it); - - } - then_part = isSgStatement(then_part2); - - } - } else { - // Manu:: fortran support (if part) - if (isInputFortran()) { - then_part2 = buildBasicBlock(); - then_part2->append_statement(isSgStatement(static_cast<CG_roseRepr*>(true_stmtList)->tnl_)); - then_part = isSgStatement(then_part2); - } else - then_part = isSgStatement(static_cast<CG_roseRepr*>(true_stmtList)->tnl_); - } - } else { - then_part = NULL; - } - if (false_stmtList != NULL) { - else_part1 = static_cast<CG_roseRepr*>(false_stmtList)->list_; - if (else_part1 != NULL) { - else_part = *((*else_part1).begin()); - if ((*else_part1).size() > 1) { - else_part2 = buildBasicBlock(); - for (SgStatementPtrList::iterator it2 = (*else_part1).begin(); - it2 != (*else_part1).end(); it2++) { - else_part2->append_statement(*it2); - - } - else_part = isSgStatement(else_part2); - - } - } else { - // Manu:: fortran support (if part) - if (isInputFortran()) { - else_part2 = buildBasicBlock(); - else_part2->append_statement(isSgStatement(static_cast<CG_roseRepr*>(false_stmtList)->tnl_)); - else_part = isSgStatement(else_part2); - } else - else_part = isSgStatement(static_cast<CG_roseRepr*>(false_stmtList)->tnl_); - } - } else { - else_part = NULL; - } - - SgIfStmt* ti = buildIfStmt(header, isSgStatement(then_part), - isSgStatement(else_part)); - - delete guardList; - delete true_stmtList; - delete false_stmtList; - - return new CG_roseRepr(isSgNode(ti)); - -} - -//----------------------------------------------------------------------------- -// inductive variable generation, to be used in CreateLoop as control -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreateInductive(CG_outputRepr *index, - CG_outputRepr *lower, CG_outputRepr *upper, CG_outputRepr *step) const { - - if (index == NULL || lower == NULL || upper == NULL) { - fprintf(stderr, - "Code generation: something wrong in CreateInductive\n"); - return NULL; - } - - if (step == NULL) - step = new CG_roseRepr(isSgExpression(buildIntVal(1))); - - SgVarRefExp *index_sym = isSgVarRefExp( - static_cast<CG_roseRepr*>(index)->op_); - SgExpression* lower_bound = static_cast<CG_roseRepr*>(lower)->op_; - SgExpression* upper_bound = static_cast<CG_roseRepr*>(upper)->op_; - SgExpression* step_size = static_cast<CG_roseRepr*>(step)->op_; - - SgStatement* for_init_stmt = buildAssignStatement(index_sym, lower_bound); - SgLessOrEqualOp* cond = buildLessOrEqualOp(index_sym, upper_bound); - SgExprStatement* test = buildExprStatement(cond); - SgPlusAssignOp* increment = buildPlusAssignOp(index_sym, step_size); - SgForStatement *for_stmt = buildForStatement(for_init_stmt, - isSgStatement(test), increment, NULL); - - delete index; - delete lower; - delete upper; - delete step; - - - // Manu - if (isInputFortran()) { - SgFortranDo * forStmt=new SgFortranDo(Sg_File_Info::generateDefaultFileInfoForTransformationNode()); - forStmt->set_has_end_statement(true); - forStmt->set_bound(upper_bound); - forStmt->set_increment(step_size); - forStmt->set_initialization(isSgExprStatement(for_init_stmt)->get_expression()); - return new CG_roseRepr(isSgNode(forStmt)); - } else { - - return new CG_roseRepr(isSgNode(for_stmt)); - - } - -} - -//----------------------------------------------------------------------------- -// Attribute Creation -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreateAttribute(CG_outputRepr *control, - const std::string &commentText) const { - - SgNode *tnl = static_cast<CG_roseRepr*>(control)->tnl_; - - tnl->setAttribute("omega_comment", new AstTextAttribute(commentText)); - - return static_cast<CG_roseRepr*>(control); - -} - -//----------------------------------------------------------------------------- -// Pragma Attribute -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreatePragmaAttribute(CG_outputRepr *stmt, int looplevel, const std::string &pragmaText) const { - SgNode *tnl = static_cast<CG_roseRepr*>(stmt)->tnl_; - CodeInsertionAttribute* attr = NULL; - if (!tnl->attributeExists("code_insertion")) { - attr = new CodeInsertionAttribute(); - tnl->setAttribute("code_insertion", attr); - } - else { - attr = static_cast<CodeInsertionAttribute*>(tnl->getAttribute("code_insertion")); - } - attr->add(new PragmaInsertion(looplevel, pragmaText)); - return stmt; -} - -//----------------------------------------------------------------------------- -// Prefetch Attribute -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreatePrefetchAttribute(CG_outputRepr* stmt, int looplevel, const std::string &arrName, int hint) const { - SgNode *tnl = static_cast<CG_roseRepr*>(stmt)->tnl_; - CodeInsertionAttribute *attr = getOrCreateCodeInsertionAttribute(tnl); - attr->add(new MMPrefetchInsertion(looplevel, arrName, hint)); -} - -//----------------------------------------------------------------------------- -// loop stmt generation -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreateLoop(int, CG_outputRepr *control, - CG_outputRepr *stmtList) const { - if (stmtList == NULL) { - delete control; - return NULL; - } else if (control == NULL) { - fprintf(stderr, "Code generation: no inductive for this loop\n"); - return stmtList; - } - - SgNode *tnl = static_cast<CG_roseRepr*>(control)->tnl_; - SgForStatement *tf = isSgForStatement(tnl); - - // Manu :: fortran support - SgFortranDo *tfd = NULL; - if (isInputFortran()) { - tfd = isSgFortranDo(tnl); - } - SgStatementPtrList * body = static_cast<CG_roseRepr*>(stmtList)->list_; - - if (body != NULL) { - if (!((*body).empty())) { - if ((*body).size() == 1) { - if (!isInputFortran()) { // Manu:: added if-else for fortran support - tf->set_loop_body(*((*body).begin())); - (*((*body).begin()))->set_parent(tf); - } else { - SgBasicBlock* bb1 = buildBasicBlock(); - bb1->set_parent(tfd); - bb1->append_statement(*((*body).begin())); - tfd->set_body(bb1); - } - } else { - // Manu:: support for fortran label (do - continue) - SgName *sname = NULL; - - SgBasicBlock* bb = buildBasicBlock(); - if (!isInputFortran()) - bb->set_parent(tf); - else - bb->set_parent(tfd); - for (SgStatementPtrList::iterator it = (*body).begin(); - it != (*body).end(); it++) { - bb->append_statement(*it); - (*it)->set_parent(bb); - } - if (!isInputFortran()) - tf->set_loop_body(bb); - else { - tfd->set_body(bb); - } - } - } - } else { - SgNode* tnl2 = static_cast<CG_roseRepr*>(stmtList)->tnl_; - - if (tnl2 != NULL) { - if (!isInputFortran()) { - tf->set_loop_body(isSgStatement(tnl2)); - tnl2->set_parent(tf); - } else { - SgBasicBlock* bb1 = buildBasicBlock(); - bb1->set_parent(tfd); - bb1->append_statement(isSgStatement(tnl2)); - tfd->set_body(bb1); - tnl2->set_parent(bb1); - } - } - } - - delete stmtList; - - return control; -} - -//----------------------------------------------------------------------------- -// basic int, identifier gen operations -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreateInt(int _i) const { - return new CG_roseRepr(isSgExpression(buildIntVal(_i))); -} -bool CG_roseBuilder::isInteger(CG_outputRepr *op) const{ - - SgExpression *op1 = static_cast<CG_roseRepr *>(op)->op_; - - if(op1) - if(isSgIntVal(op1)) - return true; - - return false; -} -CG_outputRepr* CG_roseBuilder::CreateIdent(const std::string &_s) const { - - SgVariableSymbol *vs = symtab_->find_variable(SgName(_s.c_str())); - SgVariableSymbol *vs2 = symtab2_->find_variable(SgName(_s.c_str())); - - if (vs == NULL && vs2 == NULL) { - - SgVariableDeclaration* defn = buildVariableDeclaration( - SgName(_s.c_str()), buildIntType()); - SgInitializedNamePtrList& variables = defn->get_variables(); - SgInitializedNamePtrList::const_iterator i = variables.begin(); - SgInitializedName* initializedName = *i; - vs = new SgVariableSymbol(initializedName); - prependStatement(defn, isSgScopeStatement(root_)); - - vs->set_parent(symtab2_); - symtab2_->insert(SgName(_s.c_str()), vs); - return new CG_roseRepr(isSgExpression(buildVarRefExp(vs))); - - } - - /* May have problem */ - - if (!isSgExpression(buildVarRefExp(SgName(_s.c_str())))) - throw ir_error("error in Create ident!!"); - if (vs2 != NULL) - return new CG_roseRepr(isSgExpression(buildVarRefExp(vs2))); - - return new CG_roseRepr(isSgExpression(buildVarRefExp(vs))); - -} - -//----------------------------------------------------------------------------- -// binary arithmetic operations -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreatePlus(CG_outputRepr *lop, - CG_outputRepr *rop) const { - if (rop == NULL) { - return lop; - } else if (lop == NULL) { - return rop; - } - - SgExpression* op1 = static_cast<CG_roseRepr*>(lop)->op_; - SgExpression* op2 = static_cast<CG_roseRepr*>(rop)->op_; - - SgAddOp *ins = buildAddOp(op1, op2); - op1->set_parent(ins); - op2->set_parent(ins); - delete lop; - delete rop; - - return new CG_roseRepr(isSgExpression(ins)); - -} - -CG_outputRepr* CG_roseBuilder::CreateMinus(CG_outputRepr *lop, - CG_outputRepr *rop) const { - if (rop == NULL) { - return lop; /* May Cause Problem */ - } else if (lop == NULL) { - SgExpression *op = static_cast<CG_roseRepr*>(rop)->op_; - SgMinusOp *ins = buildMinusOp(op); - - delete rop; - - return new CG_roseRepr(isSgExpression(ins)); - } else { - SgExpression* op1 = static_cast<CG_roseRepr*>(lop)->op_; - SgExpression* op2 = static_cast<CG_roseRepr*>(rop)->op_; - - SgSubtractOp *ins = buildSubtractOp(op1, op2); - op1->set_parent(ins); - op2->set_parent(ins); - delete lop; - delete rop; - return new CG_roseRepr(isSgExpression(ins)); - } - -} - -CG_outputRepr* CG_roseBuilder::CreateTimes(CG_outputRepr *lop, - CG_outputRepr *rop) const { - if (rop == NULL || lop == NULL) { - if (rop != NULL) { - rop->clear(); - delete rop; - } - if (lop != NULL) { - lop->clear(); - delete lop; - } - return NULL; - } - - SgExpression* op1 = static_cast<CG_roseRepr*>(lop)->op_; - SgExpression* op2 = static_cast<CG_roseRepr*>(rop)->op_; - - SgMultiplyOp *ins = buildMultiplyOp(op1, op2); - op1->set_parent(ins); - op2->set_parent(ins); - delete lop; - delete rop; - - return new CG_roseRepr(isSgExpression(ins)); - -} - -CG_outputRepr* CG_roseBuilder::CreateIntegerFloor(CG_outputRepr *lop, - CG_outputRepr *rop) const { - if (rop == NULL) { - fprintf(stderr, "Code generation: divide by NULL\n"); - return NULL; - } else if (lop == NULL) { - delete rop; - return NULL; - } - - // (6+5)*10 / 4 - SgExpression* op1 = static_cast<CG_roseRepr*>(lop)->op_; - SgExpression* op2 = static_cast<CG_roseRepr*>(rop)->op_; - - // bugs in SUIF prevent use of correct io_divfloor - SgDivideOp *ins = buildDivideOp(op1, op2); - - delete lop; - delete rop; - - return new CG_roseRepr(isSgExpression(ins)); - -} - -CG_outputRepr* CG_roseBuilder::CreateIntegerMod(CG_outputRepr *lop, - CG_outputRepr *rop) const { - if (rop == NULL || lop == NULL) { - return NULL; - } - - SgExpression* op1 = static_cast<CG_roseRepr*>(lop)->op_; - SgExpression* op2 = static_cast<CG_roseRepr*>(rop)->op_; - - // bugs in SUIF prevent use of correct io_mod - SgModOp *ins; - if (!isInputFortran()) { - ins = buildModOp(op1, op2); - delete lop; - delete rop; - - return new CG_roseRepr(isSgExpression(ins)); - } else { // Manu:: fortran mod is a function call and not an operator (f77 and f90) - SgExpression *fins; - SgName fName("MOD"); - SgExprListExp* arg_list = buildExprListExp(); - appendExpression(arg_list, op1); - appendExpression(arg_list, op2); - SgTypeInt *retType = buildIntType(); - fins = isSgExpression(buildFunctionCallExp(fName, retType, arg_list, global_)); - return new CG_roseRepr(isSgExpression(fins)); - } - -} - -//----------------------------------------------------------------------------- -// binary logical operations -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreateAnd(CG_outputRepr *lop, - CG_outputRepr *rop) const { - - if (rop == NULL) - return lop; - else if (lop == NULL) - return rop; - - SgExpression* op1 = static_cast<CG_roseRepr*>(lop)->op_; - SgExpression* op2 = static_cast<CG_roseRepr*>(rop)->op_; - - SgAndOp *ins = buildAndOp(op1, op2); - - delete lop; - delete rop; - - return new CG_roseRepr(isSgExpression(ins)); - -} - -//----------------------------------------------------------------------------- -// binary relational operations -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::CreateLE(CG_outputRepr *lop, - CG_outputRepr *rop) const { - if (rop == NULL || lop == NULL) { - return NULL; - } - - SgExpression* op1 = static_cast<CG_roseRepr*>(lop)->op_; - SgExpression* op2 = static_cast<CG_roseRepr*>(rop)->op_; - - SgLessOrEqualOp *ins = buildLessOrEqualOp(op1, op2); - - delete lop; - delete rop; - - return new CG_roseRepr(isSgExpression(ins)); - -} - -CG_outputRepr* CG_roseBuilder::CreateEQ(CG_outputRepr *lop, - CG_outputRepr *rop) const { - if (rop == NULL || lop == NULL) { - return NULL; - } - - SgExpression* op1 = static_cast<CG_roseRepr*>(lop)->op_; - SgExpression* op2 = static_cast<CG_roseRepr*>(rop)->op_; - - SgEqualityOp *ins = buildEqualityOp(op1, op2); - - delete lop; - delete rop; - - return new CG_roseRepr(isSgExpression(ins)); - -} - -//----------------------------------------------------------------------------- -// stmt list gen operations -//----------------------------------------------------------------------------- -CG_outputRepr* CG_roseBuilder::StmtListAppend(CG_outputRepr *list1, - CG_outputRepr *list2) const { - - if (list2 == NULL) { - return list1; - } else if (list1 == NULL) { - return list2; - } - - SgStatementPtrList* new_list; - - SgStatementPtrList* tnl1 = static_cast<CG_roseRepr *>(list1)->list_; - SgStatementPtrList* tnl2 = static_cast<CG_roseRepr *>(list2)->list_; - SgNode* one = static_cast<CG_roseRepr *>(list1)->tnl_; - SgNode* two = static_cast<CG_roseRepr *>(list2)->tnl_; - - SgExpression* exp1 = static_cast<CG_roseRepr *>(list1)->op_; - SgExpression* exp2 = static_cast<CG_roseRepr *>(list2)->op_; - - if (exp1 || exp2) - throw ir_error("error in stmtlistappend!!"); - - if (tnl1 && one) - throw ir_error("error in stmtlistappend!!"); - - if (tnl2 && two) - throw ir_error("error in stmtlistappend!!"); - if ((tnl1 == NULL) && (tnl2 == NULL)) { - - if ((one != NULL) && (two != NULL)) { - - new_list = new SgStatementPtrList; - - (*new_list).push_back(isSgStatement(one)); - (*new_list).push_back(isSgStatement(two)); - - CG_roseRepr* new_rep = new CG_roseRepr(new_list); - - return static_cast<CG_outputRepr *>(new_rep); - - } else if ((one != NULL) && (two == NULL)) { - - return static_cast<CG_outputRepr *>(new CG_roseRepr(one)); - - } else if ((two != NULL) && (one == NULL)) { - return static_cast<CG_outputRepr *>(new CG_roseRepr(two)); - - } - - } else { - if ((tnl2 != NULL) && (tnl1 == NULL)) { - if (one == NULL) - return list2; - else { - new_list = new SgStatementPtrList; - (*new_list).push_back(isSgStatement(one)); - - for (SgStatementPtrList::iterator it = (*tnl2).begin(); - it != (*tnl2).end(); it++) { - (*new_list).push_back(*it); - - } - return static_cast<CG_outputRepr *>(new CG_roseRepr(new_list)); - } - } else if ((tnl1 != NULL) && (tnl2 == NULL)) { - if (two == NULL) - return list1; - else { - - (*tnl1).push_back(isSgStatement(two)); - return static_cast<CG_outputRepr *>(new CG_roseRepr(tnl1)); - - } - - } else if ((tnl1 != NULL) && (tnl2 != NULL)) { - - for (SgStatementPtrList::iterator it = (*tnl2).begin(); - it != (*tnl2).end(); it++) { - (*tnl1).push_back(*it); - - } - - return static_cast<CG_outputRepr *>(new CG_roseRepr(tnl1)); - } - - } - -} - - -CG_outputRepr* CG_roseBuilder::CreateDim3(const char* varName, CG_outputRepr* arg1, - CG_outputRepr* arg2, CG_outputRepr* arg3) const { - - SgFunctionSymbol * ctor_symbol = global_scope->lookup_function_symbol( - SgName("dim3")); - - SgExprListExp * ctor_args; - if(arg3 != NULL) - ctor_args = buildExprListExp(static_cast<CG_roseRepr*>(arg1)->op_, - static_cast<CG_roseRepr*>(arg2)->op_, static_cast<CG_roseRepr*>(arg3)->op_); - else - ctor_args = buildExprListExp(static_cast<CG_roseRepr*>(arg1)->op_, - static_cast<CG_roseRepr*>(arg2)->op_); - SgFunctionCallExp * dim3_func_call = buildFunctionCallExp( - buildFunctionRefExp(ctor_symbol->get_declaration()), ctor_args); - - char joined_str[20]; - - strcpy(joined_str, "dim3 "); - strcat(joined_str, varName); - - SgExprStatement* decl = buildAssignStatement( - buildOpaqueVarRefExp(joined_str, isSgScopeStatement(root_)), - dim3_func_call); - - SgStatementPtrList *tnl2 = new SgStatementPtrList; - - (*tnl2).push_back(decl); - return new CG_roseRepr(tnl2); - -} - -std::vector<SgVarRefExp *> substitute(SgNode *in, const SgVariableSymbol *sym, - SgExpression* expr, SgNode* root) { - - SgStatement* stmt; - SgExpression* op; - std::vector<SgVarRefExp *> arrays; - - if (in != NULL) { - if (stmt = isSgStatement(in)) { - if (isSgBasicBlock(stmt)) { - SgStatementPtrList& stmts = - isSgBasicBlock(stmt)->get_statements(); - for (int i = 0; i < stmts.size(); i++) { - stmts[i]->set_parent(stmt); - std::vector<SgVarRefExp *> a = substitute( - isSgNode(stmts[i]), sym, expr, root); - std::copy(a.begin(), a.end(), back_inserter(arrays)); - } - } else if (isSgForStatement(stmt)) { - SgForStatement *tnf = isSgForStatement(stmt); - tnf->get_for_init_stmt()->set_parent(tnf); - tnf->get_test()->set_parent(tnf); - tnf->get_increment()->set_parent(tnf); - tnf->get_loop_body()->set_parent(tnf); - std::vector<SgVarRefExp *> a = substitute( - isSgNode(tnf->get_for_init_stmt()), sym, expr, root); - std::copy(a.begin(), a.end(), back_inserter(arrays)); - std::vector<SgVarRefExp *> a1 = substitute( - isSgNode(tnf->get_test()), sym, expr, root); - std::copy(a1.begin(), a1.end(), back_inserter(arrays)); - std::vector<SgVarRefExp *> a2 = substitute( - isSgNode(tnf->get_increment()), sym, expr, root); - std::copy(a2.begin(), a2.end(), back_inserter(arrays)); - std::vector<SgVarRefExp *> a3 = substitute( - isSgNode(tnf->get_loop_body()), sym, expr, root); - std::copy(a3.begin(), a3.end(), back_inserter(arrays)); - } else if (isSgFortranDo(stmt)) { // Manu:: fortran support - SgFortranDo *tnf = isSgFortranDo(stmt); - tnf->get_initialization()->set_parent(tnf); - tnf->get_bound()->set_parent(tnf); - tnf->get_increment()->set_parent(tnf); - tnf->get_body()->set_parent(tnf); - std::vector<SgVarRefExp *> a = substitute( - isSgNode(tnf->get_initialization()), sym, expr, root); - std::copy(a.begin(), a.end(), back_inserter(arrays)); - std::vector<SgVarRefExp *> a1 = substitute( - isSgNode(tnf->get_bound()), sym, expr, root); - std::copy(a1.begin(), a1.end(), back_inserter(arrays)); - std::vector<SgVarRefExp *> a2 = substitute( - isSgNode(tnf->get_increment()), sym, expr, root); - std::copy(a2.begin(), a2.end(), back_inserter(arrays)); - std::vector<SgVarRefExp *> a3 = substitute( - isSgNode(tnf->get_body()), sym, expr, root); - std::copy(a3.begin(), a3.end(), back_inserter(arrays)); - } else if (isSgForInitStatement(stmt)) { - - SgStatementPtrList& stmts = - isSgForInitStatement(stmt)->get_init_stmt(); - - for (SgStatementPtrList::iterator it = stmts.begin(); - it != stmts.end(); it++) { - std::vector<SgVarRefExp *> a = substitute(isSgNode(*it), - sym, expr, root); - - std::copy(a.begin(), a.end(), back_inserter(arrays)); - } - } - else if (isSgVariableDeclaration(stmt)) { - if (SgExpression *init = - isSgVariableDeclaration(stmt)->get_variables().front()->get_initializer()) { - if (isSgAssignInitializer(init)) { - std::vector<SgVarRefExp *> a = substitute( - isSgAssignInitializer(init)->get_operand(), sym, - expr, root); - std::copy(a.begin(), a.end(), back_inserter(arrays)); - } - } - } else if (isSgIfStmt(stmt)) { - SgIfStmt* tni = isSgIfStmt(stmt); - std::vector<SgVarRefExp *> a = substitute( - isSgNode(tni->get_conditional()), sym, expr, root); - std::copy(a.begin(), a.end(), back_inserter(arrays)); - std::vector<SgVarRefExp *> a1 = substitute( - isSgNode(tni->get_true_body()), sym, expr, root); - std::copy(a1.begin(), a1.end(), back_inserter(arrays)); - std::vector<SgVarRefExp *> a2 = substitute( - isSgNode(tni->get_false_body()), sym, expr, root); - std::copy(a2.begin(), a2.end(), back_inserter(arrays)); - } else if (isSgExprStatement(stmt)) { - (isSgExprStatement(stmt)->get_expression())->set_parent( - isSgExprStatement(stmt)); - std::vector<SgVarRefExp *> a = substitute( - isSgNode(isSgExprStatement(stmt)->get_expression()), - sym, expr, root); - std::copy(a.begin(), a.end(), back_inserter(arrays)); - } - } - else { - op = isSgExpression(in); - std::string y = sym->get_name().getString(); - - if (isSgBinaryOp(op)) { - - isSgBinaryOp(op)->get_lhs_operand()->set_parent(op); - isSgBinaryOp(op)->get_rhs_operand()->set_parent(op); - - std::vector<SgVarRefExp *> a = substitute( - isSgBinaryOp(op)->get_lhs_operand(), sym, expr, root); - std::copy(a.begin(), a.end(), back_inserter(arrays)); - std::vector<SgVarRefExp *> a1 = substitute( - isSgBinaryOp(op)->get_rhs_operand(), sym, expr, root); - std::copy(a1.begin(), a1.end(), back_inserter(arrays)); - } else if (isSgUnaryOp(op)) { - std::vector<SgVarRefExp *> a = substitute( - isSgUnaryOp(op)->get_operand(), sym, expr, root); - std::copy(a.begin(), a.end(), back_inserter(arrays)); - } else if (isSgVarRefExp(op)) { - std::string z = - isSgVarRefExp(op)->get_symbol()->get_name().getString(); - if (!strcmp(z.c_str(), y.c_str())) { - arrays.push_back(isSgVarRefExp(op)); - } - } - else if (isSgCallExpression(op)) { - SgExprListExp* exprs = isSgCallExpression(op)->get_args(); - SgExpressionPtrList &expr_list = exprs->get_expressions(); - - for (SgExpressionPtrList::iterator it = expr_list.begin(); - it != expr_list.end(); it++) { - std::vector<SgVarRefExp *> a = substitute(isSgNode(*it), - sym, expr, root); - std::copy(a.begin(), a.end(), back_inserter(arrays)); - } - } else if (isSgExprListExp(op)) { // Manu:: fortran indices are stored this way - SgExpressionPtrList &expr_list = isSgExprListExp(op)->get_expressions(); - - for (SgExpressionPtrList::iterator it = expr_list.begin(); - it != expr_list.end(); it++) { - std::vector<SgVarRefExp *> a = substitute(isSgNode(*it), - sym, expr, root); - std::copy(a.begin(), a.end(), back_inserter(arrays)); - } - - } - - } - } - - return arrays; -} - -} // namespace diff --git a/lib/rosecg/src/CG_roseRepr.cc b/lib/rosecg/src/CG_roseRepr.cc deleted file mode 100644 index 5472239..0000000 --- a/lib/rosecg/src/CG_roseRepr.cc +++ /dev/null @@ -1,125 +0,0 @@ -/***************************************************************************** - Copyright (C) 2008 University of Southern California. - All Rights Reserved. - - Purpose: - omega holder for suif implementaion - - Notes: - - History: - 02/01/06 - Chun Chen - created -*****************************************************************************/ - -#include "code_gen/CG_roseRepr.h" -#include "code_gen/rose_attributes.h" -#include <stdio.h> -#include <string.h> -#include <cstring> -namespace omega { - - - - -CG_roseRepr::CG_roseRepr(): tnl_(NULL), op_(NULL), list_(NULL){ - -} - -CG_roseRepr::CG_roseRepr(SgNode *tnl): tnl_(tnl), op_(NULL),list_(NULL) { -} - -CG_roseRepr::CG_roseRepr(SgExpression* op): tnl_(NULL), op_(op),list_(NULL){ -} -CG_roseRepr::CG_roseRepr(SgStatementPtrList* stmtlist):tnl_(NULL), op_(NULL), list_(stmtlist){ -} - -CG_roseRepr::~CG_roseRepr() { - // delete nothing here. operand or tree_node_list should already be - // grafted to other expression tree or statement list -} - -CG_outputRepr* CG_roseRepr::clone() const { - - if( tnl_ != NULL) { - SgTreeCopy tc; - SgNode *tnl = tnl_->copy(tc); - copyAttributes(tnl_, tnl); - - tnl->set_parent(tnl_->get_parent()); - return new CG_roseRepr(tnl); - } - else if(op_ != NULL) - { - SgTreeCopy tc1; - SgNode* op = isSgNode(op_)->copy(tc1); - copyAttributes(op_, op); - - op->set_parent(isSgNode(op_)->get_parent()); - return new CG_roseRepr(isSgExpression(op)); - } - else if(list_ != NULL) - { - SgStatementPtrList* list2 = new SgStatementPtrList; - - for(SgStatementPtrList::iterator it = (*list_).begin(); it != (*list_).end(); it++){ - SgTreeCopy tc3; - SgNode *tnl2 = isSgNode(*it)->copy(tc3); - copyAttributes(*it, tnl2); - - tnl2->set_parent(isSgNode(*it)->get_parent()); - - (*list2).push_back(isSgStatement(tnl2)); - } - return new CG_roseRepr(list2); - } - - return NULL; -} - -void CG_roseRepr::clear() { - if(tnl_ != NULL) { - delete tnl_; - tnl_ = NULL; - } -} - -SgNode* CG_roseRepr::GetCode() const { - return tnl_; -} - -SgStatementPtrList* CG_roseRepr::GetList() const { - return list_; -} - -SgExpression* CG_roseRepr::GetExpression() const { - return op_; -} -void CG_roseRepr::Dump() const { -SgNode* tnl = tnl_; -SgExpression* op = op_ ; - if(tnl != NULL) - DumpFileHelper(tnl, stdout); - else if(op != NULL) - DumpFileHelper(isSgNode(op), stdout); - -} - -void CG_roseRepr::DumpFileHelper(SgNode* node, FILE *fp) const{ - std::string x; - size_t numberOfSuccessors = node->get_numberOfTraversalSuccessors(); - if(numberOfSuccessors == 0){ - x = node->unparseToString (); - fprintf(fp, "%s", x.c_str()); - } - else{ - for (size_t idx = 0; idx < numberOfSuccessors; idx++) - { - SgNode *child = NULL; - child = node->get_traversalSuccessorByIndex(idx); - DumpFileHelper(child, fp); - } - -} -} - -} // namespace diff --git a/lib/rosecg/src/rose_attributes.cc b/lib/rosecg/src/rose_attributes.cc deleted file mode 100644 index c5ba30b..0000000 --- a/lib/rosecg/src/rose_attributes.cc +++ /dev/null @@ -1,183 +0,0 @@ -#include "code_gen/rose_attributes.h" - -namespace omega { - -CodeInsertionAttribute* getOrCreateCodeInsertionAttribute(SgNode* node) { - CodeInsertionAttribute* attr; - if(node->attributeExists("code_insertion")) - return static_cast<CodeInsertionAttribute*>(node->getAttribute("code_insertion")); - attr = new CodeInsertionAttribute(); - node->setAttribute("code_insertion", attr); - return attr; -} - -void postProcessRoseCodeInsertion(SgProject* proj) { - //generatePDF(*proj); - CodeInsertionVisitor visitor = CodeInsertionVisitor(); - visitor.initialize(); - visitor.traverseInputFiles(proj); - visitor.insertCode(); -} - -// Swap a code insertion from one node (sn) to another (dn) -// -- note that this function does not currently remove the insertion from the sn node -void moveCodeInsertion(SgNode* sn, CodeInsertion* ci, SgNode* dn) { - CodeInsertionAttribute* new_attr; - // TODO in the near future: replace the above statement with 'new_attr = getOrCreateCodeInsertionAttribute(...)' - CodeInsertionAttribute* old_attr = static_cast<CodeInsertionAttribute*>(sn->getAttribute("code_insertion")); - if(dn->attributeExists("code_insertion")) { - new_attr = static_cast<CodeInsertionAttribute*>(dn->getAttribute("code_insertion")); - } - else { - new_attr = new CodeInsertionAttribute(); - dn->setAttribute("code_insertion", new_attr); - } - new_attr->add(ci); -} - -// A function that copies a specific attribute from one node to another -// this function exists to get around a ROSE limitation that does not -// copy attributes -void copyAttribute(std::string attr_name, SgNode* s, SgNode* d) { - if(s->attributeExists(attr_name)) { - d->setAttribute(attr_name,s->getAttribute(attr_name)); - } -} - -// TODO: find all existng attributes and iterate over them instead of doing them -// individually -void copyAttributes(SgNode* s, SgNode* d) { - copyAttribute("code_insertion", s, d); - //...any other attributes... -} - -void CodeInsertionVisitor::initialize() { - this->loop_level = 0; - this->ci_marks = std::vector<CodeInsertionMark*>(); -} - -void CodeInsertionVisitor::markStmt(SgStatement* stmt, CodeInsertion* ci) { - // this check prevents multiple copies of stmts - // -- may be changed in the future - if(!ci->marked) { - CodeInsertionMark* pos = new CodeInsertionMark(); - pos->stmt = stmt; - pos->ci = ci; - this->ci_marks.push_back(pos); - ci->marked = true; - } -} - -// increase loop_level as the visitor descends -void CodeInsertionVisitor::preOrderVisit(SgNode* n) { - if (isSgForStatement(n)) { - this->loop_level++; - } -} - -void CodeInsertionVisitor::postOrderVisit(SgNode* n) { - if(isSgForStatement(n)) { - this->loop_level--; - } - if(isSgStatement(n)) { - if(n->attributeExists("code_insertion")) { - CodeInsertionAttribute *attr = static_cast<CodeInsertionAttribute*>(n->getAttribute("code_insertion")); - for(CodeInsertionPtrListItr itr = attr->begin(); itr != attr->end(); ++itr) { - CodeInsertion *insertion = *itr; - // check loop level -- if it is equivelent, mark statement for insertion - // -- else, move attribute up to parent - if(insertion->loop_level != this->loop_level) { - moveCodeInsertion(n, insertion, n->get_parent()); - } - else { - this->markStmt(isSgStatement(n), insertion); - } - } - } - } -} - -// final stage of algorithm that inserts marked statements -void CodeInsertionVisitor::insertCode() { - for(std::vector<CodeInsertionMark*>::iterator itr = this->ci_marks.begin(); itr != this->ci_marks.end(); ++itr) { - CodeInsertionMark* mark = *itr; - SgScopeStatement* scope = static_cast<SgScopeStatement*>(mark->stmt->get_parent()); - SageInterface::insertStatementBefore(mark->stmt, mark->ci->getStatement(scope)); - } -} - -SgStatement* PragmaInsertion::getStatement(SgScopeStatement* scopeStmt) { - SgStatement* stmt = SageBuilder::buildPragmaDeclaration(this->name); - return stmt; -} - -//SgStatement* MMPrefetchInsertion::getStatement(SgScopeStatement* scopeStmt) { -// const SgName& name = SgName("_mm_prefetch"); -// SgType* rtype = SageBuilder::buildVoidType(); -// SgExpression* arr_arg = SageBuilder::buildVarRefExp(this->arrName); -// SgExpression* hint_arg = SageBuilder::buildShortVal(this->cacheHint); -// SgExprListExp* args = SageBuilder::buildExprListExp(arr_arg,hint_arg); -// SgStatement* stmt = SageBuilder::buildFunctionCallStmt(name, rtype, args, scopeStmt); -// return stmt; -//} - -SgStatement* MMPrefetchInsertion::getStatement(SgScopeStatement* scopeStmt) { - const SgName fname = SgName("_mm_prefetch"); - SgType* rtype = SageBuilder::buildVoidType(); - SgExpression* arr_arg = this->buildArrArg(scopeStmt); - SgExpression* hint_arg = SageBuilder::buildShortVal(this->cacheHint); - SgExprListExp* args = SageBuilder::buildExprListExp(arr_arg, hint_arg); - return SageBuilder::buildFunctionCallStmt(fname, rtype, args, scopeStmt); -} - -SgExpression* MMPrefetchInsertion::buildArrArg(SgScopeStatement* scopeStmt) { - // if there are no index arguments given, just return a variable reference - if(this->indexCount == 0) { - const SgName aname = SgName(this->arrName); - return SageBuilder::buildVarRefExp(aname, scopeStmt); - } - std::vector<SgExpression*> argList = std::vector<SgExpression*>(); - // foreach dimension - for(int i = 0; i < this->indexCount; i++) { - argList.push_back(this->makeIndexExp(i, scopeStmt)); - } - return SageBuilder::buildExprListExp(argList); -} - -SgExpression* MMPrefetchInsertion::makeIndexExp(int dim, SgScopeStatement* scopeStmt) { - //(i + offset) or (offset) or (i) - std::string* indexer = this->indecies.at(dim); - int offset = this->offsets.at(dim); - if(indexer == NULL) { - return SageBuilder::buildIntVal(offset); - } - else { - const SgName name = SgName(*indexer); - SgVarRefExp* iref = SageBuilder::buildVarRefExp(name, scopeStmt); - if(offset == 0) { - return iref; - } - else { - return SageBuilder::buildAddOp(iref, SageBuilder::buildIntVal(offset)); - } - } -} - -void MMPrefetchInsertion::initialize(const std::string& arrName, int hint) { - this->arrName = std::string(arrName); - this->cacheHint = hint; - this->indecies = std::vector<std::string*>(); - this->offsets = std::vector<int>(); - this->indexCount = 0; -} -void MMPrefetchInsertion::addDim(int offset) { - this->offsets.push_back(offset); - this->indecies.push_back(NULL); - this->indexCount++; -} -void MMPrefetchInsertion::addDim(int offset, const std::string& indexer) { - this->offsets.push_back(offset); - this->indecies.push_back(new std::string(indexer)); - this->indexCount++; -} -} 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))); + +} + + + + |