// Are any variables in syms modified anywhere within n, or is n a declaration // of one of them? // FIXME: move to inliner bool anyOfListPotentiallyModifiedIn(const vector<SgVariableSymbol*>& syms, SgNode* n) { bool modified = false; for (vector<SgVariableSymbol*>::const_iterator j = syms.begin(); j != syms.end(); ++j) { SgVarRefExp* vr = new SgVarRefExp(SgNULL_FILE, *j); vr->set_endOfConstruct(SgNULL_FILE); if (isPotentiallyModified(vr, n)) { modified = true; } delete vr; if (modified) break; if (isSgVariableDeclaration(n)) { SgVariableDeclaration* decl = isSgVariableDeclaration(n); for (SgInitializedNamePtrList::const_iterator i = decl->get_variables().begin(); i != decl->get_variables().end(); ++i) { if (*i == (*j)->get_declaration()) { modified = true; break; } } } if (modified) break; } return modified; }
SgVariableDeclaration* buildStructVariable ( SgScopeStatement* scope, vector<SgType*> memberTypes, vector<string> memberNames, string structName = "", string varName = "", SgAggregateInitializer *initializer = NULL ) { ROSE_ASSERT(memberTypes.size() == memberNames.size()); SgClassDeclaration* classDeclaration = buildClassDeclarationAndDefinition(structName,scope); vector<SgType*>::iterator typeIterator = memberTypes.begin(); vector<string>::iterator memberNameIterator = memberNames.begin(); while (typeIterator != memberTypes.end()) { // printf ("Adding data member type = %s variable name = %s \n",(*typeIterator)->unparseToString().c_str(),memberNameIterator->c_str()); SgVariableDeclaration* memberDeclaration = new SgVariableDeclaration(SOURCE_POSITION,*memberNameIterator,*typeIterator,NULL); memberDeclaration->set_endOfConstruct(SOURCE_POSITION); classDeclaration->get_definition()->append_member(memberDeclaration); memberDeclaration->set_parent(classDeclaration->get_definition()); // Liao (2/13/2008) scope and symbols for member variables SgInitializedName* initializedName = *(memberDeclaration->get_variables().begin()); initializedName->set_file_info(SOURCE_POSITION); initializedName->set_scope(classDeclaration->get_definition()); // set nondefning declaration pointer memberDeclaration->set_firstNondefiningDeclaration(memberDeclaration); SgVariableSymbol* variableSymbol = new SgVariableSymbol(initializedName); classDeclaration->get_definition()->insert_symbol(*memberNameIterator,variableSymbol); typeIterator++; memberNameIterator++; } SgClassType* classType = new SgClassType(classDeclaration->get_firstNondefiningDeclaration()); SgVariableDeclaration* variableDeclaration = new SgVariableDeclaration(SOURCE_POSITION,varName,classType,initializer); variableDeclaration->set_endOfConstruct(SOURCE_POSITION); //Liao (2/13/2008) scope and symbols for struct variable SgInitializedName* initializedName = *(variableDeclaration->get_variables().begin()); initializedName->set_file_info(SOURCE_POSITION); initializedName->set_scope(scope); SgVariableSymbol* variableSymbol = new SgVariableSymbol(initializedName); scope->insert_symbol(varName,variableSymbol); //set nondefining declaration variableDeclaration->set_firstNondefiningDeclaration(variableDeclaration); // This is required, since it is not set in the SgVariableDeclaration constructor initializer->set_parent(variableDeclaration); variableDeclaration->set_variableDeclarationContainsBaseTypeDefiningDeclaration(true); variableDeclaration->set_baseTypeDefiningDeclaration(classDeclaration->get_definingDeclaration()); classDeclaration->set_parent(variableDeclaration); return variableDeclaration; }
void CompassAnalyses::StaticConstructorInitialization::Traversal:: visit(SgNode* node) { // Test for static initialization of variables of type class, such initializations where they are // static or appear in global scope can be called in an order dependent upon the compiler and this // can lead to subtle bugs in large scale applications. SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(node); if (variableDeclaration != NULL) { SgInitializedNamePtrList::iterator i = variableDeclaration->get_variables().begin(); while (i != variableDeclaration->get_variables().end()) { SgInitializedName* initializedName = *i; // Check the type and see if it is a class (check for typedefs too) SgType* variableType = initializedName->get_type(); SgClassType *classType = isSgClassType(variableType); if (classType != NULL) { // Now check if this is a global or namespace variable or an static class member // This might also have to be a test for other scopes as well. SgScopeStatement* scope = variableDeclaration->get_scope(); if (isSgGlobal(scope) != NULL || isSgNamespaceDefinitionStatement(scope) != NULL) { // printf ("Found a global variable defining a class = %p \n",initializedName); // variableDeclaration->get_file_info()->display("global variable defining a class"); output->addOutput(new CheckerOutput(initializedName)); } if (isSgClassDefinition(scope) != NULL) { // Now check if it is a static data member if (variableDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true) { // printf ("Found a static data member defining a class = %p \n",initializedName); // variableDeclaration->get_file_info()->display("static data member defining a class"); output->addOutput(new CheckerOutput(initializedName)); } } } // increment though the variables in the declaration (typically just one) i++; } } } //End of the visit function.
string Doxygen::getDeclStmtName(SgDeclarationStatement *st) { SgFunctionDeclaration *fn = isSgFunctionDeclaration(st); SgVariableDeclaration *vn = isSgVariableDeclaration(st); SgClassDeclaration *cn = isSgClassDeclaration(st); if (fn) { return fn->get_name().str(); } else if (vn) { /* XXX The following is a bit dodgy since single * SgVariableDeclaration may declare multiple * variables. But doxygen doesn't handle this case * properly. A useful transform may split up the * SgVariableDeclaration for doxygen's sake */ return (*(vn->get_variables().begin()))->get_name().str(); } else if (cn) { return cn->get_name().str(); } else { fprintf(stderr, "Cannot handle this case: %s\n", st->sage_class_name()); abort(); } }
Rose_STL_Container<SgInitializedName*> buildListOfGlobalVariables ( SgSourceFile* file ) { // This function builds a list of global variables (from a SgFile). assert(file != NULL); Rose_STL_Container<SgInitializedName*> globalVariableList; SgGlobal* globalScope = file->get_globalScope(); assert(globalScope != NULL); Rose_STL_Container<SgDeclarationStatement*>::iterator i = globalScope->get_declarations().begin(); while(i != globalScope->get_declarations().end()) { SgVariableDeclaration *variableDeclaration = isSgVariableDeclaration(*i); if (variableDeclaration != NULL) { Rose_STL_Container<SgInitializedName*> & variableList = variableDeclaration->get_variables(); Rose_STL_Container<SgInitializedName*>::iterator var = variableList.begin(); while(var != variableList.end()) { globalVariableList.push_back(*var); var++; } } i++; } return globalVariableList; }
void Traversal::visit(SgNode* node) { SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(node); // Look for variable declarations appearing in global scope! // if (variableDeclaration != NULL && isSgGlobal(variableDeclaration->get_parent()) != NULL) if (variableDeclaration != NULL) { SgInitializedNamePtrList::iterator i = variableDeclaration->get_variables().begin(); while (i != variableDeclaration->get_variables().end()) { SgInitializedName* initializedName = *i; // Check the type and see if it is a class (check for typedefs too) SgType* variableType = initializedName->get_type(); SgClassType *classType = isSgClassType(variableType); if (classType != NULL) { // Now check if this is a global variable or an static class member SgScopeStatement* scope = variableDeclaration->get_scope(); if (isSgGlobal(scope) != NULL) { printf ("Found a global variable defining a class \n"); // variableDeclaration->get_file_info()->display("global variable defining a class"); outputPositionInformation(variableDeclaration); } if (isSgClassDefinition(scope) != NULL) { // Now check if it is a static data member if (variableDeclaration->get_declarationModifier().get_storageModifier().isStatic() == true) { printf ("Found a static data member defining a class \n"); // variableDeclaration->get_file_info()->display("static data member defining a class"); outputPositionInformation(variableDeclaration); } } } // increment though the variables in the declaration (typically just one) i++; } } }
NameQuerySynthesizedAttributeType NameQuery::queryNameUnionFieldNames (SgNode * astNode) { ROSE_ASSERT (astNode != 0); NameQuerySynthesizedAttributeType returnNameList; // SgNode *sageReturnNode = NULL; SgClassDefinition *sageClassDefinition = isSgClassDefinition (astNode); if (sageClassDefinition != NULL) { ROSE_ASSERT (sageClassDefinition->get_declaration () != NULL); if (sageClassDefinition->get_declaration ()->get_class_type () == SgClassDeclaration::e_struct) { SgDeclarationStatementPtrList declarationStatementPtrList = sageClassDefinition->get_members (); typedef SgDeclarationStatementPtrList::iterator LI; for (LI i = declarationStatementPtrList.begin (); i != declarationStatementPtrList.end (); ++i) { SgNode *listElement = *i; SgVariableDeclaration *sageVariableDeclaration = isSgVariableDeclaration (listElement); if (sageVariableDeclaration != NULL) { typedef SgInitializedNamePtrList::iterator INITLI; SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables (); for (INITLI i = sageInitializedNameList.begin (); i != sageInitializedNameList.end (); ++i) { SgInitializedName* initializedListElement = *i; ROSE_ASSERT (isSgInitializedName (initializedListElement) != NULL); returnNameList.push_back (initializedListElement->get_name().str()); } /* End iteration over declarationStatementPtrList */ } /* End iteration over declarationStatementPtrList */ } } } return returnNameList; } /* End function queryUnionFieldNames() */
virtual void visit(SgNode* n) { if (isSgBasicBlock(n)) { SgBasicBlock* bb = isSgBasicBlock(n); SgStatementPtrList& stmts = bb->get_statements(); size_t initi; for (size_t decli = 0; decli < stmts.size(); ++decli) { if (isSgVariableDeclaration(stmts[decli])) { SgVariableDeclaration* decl = isSgVariableDeclaration(stmts[decli]); SgInitializedNamePtrList& vars = decl->get_variables(); for (size_t vari = 0; vari != vars.size(); ++vari) { SgInitializedName* in = vars[vari]; if (in->get_initializer() == 0) { bool used = false; for (initi = decli + 1; initi < stmts.size(); used |= containsVariableReference(stmts[initi], in), ++initi) { SgExprStatement* initExprStmt = isSgExprStatement(stmts[initi]); if (initExprStmt) { SgExpression* top = initExprStmt->get_expression(); if (isSgAssignOp(top)) { SgVarRefExp* vr = isSgVarRefExp(isSgAssignOp(top)->get_lhs_operand()); ROSE_ASSERT(isSgAssignOp(top) != NULL); SgExpression* newinit = isSgAssignOp(top)->get_rhs_operand(); if (!used && vr && vr->get_symbol()->get_declaration() == in) { ROSE_ASSERT(newinit != NULL); // printf ("MoveDeclarationsToFirstUseVisitor::visit(): newinit = %p = %s \n",newinit,newinit->class_name().c_str()); ROSE_ASSERT(newinit->get_type() != NULL); SgAssignInitializer* i = new SgAssignInitializer(SgNULL_FILE,newinit,newinit->get_type()); i->set_endOfConstruct(SgNULL_FILE); // printf ("Built a SgAssignInitializer #1 \n"); vars[vari]->set_initializer(i); stmts[initi] = decl; newinit->set_parent(i); // DQ (6/23/2006): Set the parent and file_info pointers // printf ("Setting parent of i = %p = %s to parent = %p = %s \n",i,i->class_name().c_str(),in,in->class_name().c_str()); i->set_parent(in); ROSE_ASSERT(i->get_parent() != NULL); i->set_file_info(new Sg_File_Info(*(newinit->get_file_info()))); ROSE_ASSERT(i->get_file_info() != NULL); // Assumes only one var per declaration FIXME ROSE_ASSERT (vars.size() == 1); stmts.erase(stmts.begin() + decli); --decli; // To counteract ++decli in loop header break; // To get out of initi loop } } } } } } } } } }
void Unparse_Jovial::unparseVarDeclStmt(SgStatement* stmt, SgUnparse_Info& info) { SgVariableDeclaration* vardecl = isSgVariableDeclaration(stmt); ROSE_ASSERT(vardecl != NULL); SgInitializedNamePtrList::iterator p = vardecl->get_variables().begin(); // Jovial has only one variable per declaration unparseVarDecl(vardecl, *p, info); }
int main(int argc, char** argv) { SgProject* proj = frontend(argc,argv); SgFunctionDeclaration* mainDecl = SageInterface::findMain(proj); SgFunctionDefinition* mainDef = mainDecl->get_definition(); std::vector<SgNode*> ifExps; ifExps = NodeQuery::querySubTree(mainDef, V_SgIfStmt); for (int i = 0; i < ifExps.size(); i++) { getIfConds(isSgIfStmt(ifExps[i]), isSgScopeStatement(mainDef)); } std::vector<SgNode*> assignNodes = NodeQuery::querySubTree(mainDef, V_SgVariableDeclaration); std::cout << assignNodes.size() << " nodes found" << std::endl; std::vector<SgBinaryOp*> bin_ops; std::vector<SgUnaryOp*> un_ops; std::vector<SgNode*> other; std::vector<SgExpression*> results; for (std::vector<SgNode*>::iterator i = assignNodes.begin(); i != assignNodes.end(); i++) { SgVariableDeclaration* vdecl = isSgVariableDeclaration(*i); SgInitializedNamePtrList vlst = vdecl->get_variables(); SgInitializedName* initName = isSgInitializedName((*(vlst.begin()))); SgExpression* exp = isSgAssignInitializer(initName->get_initializer())->get_operand(); std::cout << exp->class_name() << std::endl; if (!isSgFunctionCallExp(exp)) { getExps(exp, isSgInitializedName(*i), results, 0); std::cout << "prefixes" << std::endl; for (int j = 0; j < prefixes.size(); j++) { SgExprStatement* expSt = SageBuilder::buildExprStatement_nfi(prefixes[j]); SageInterface::insertStatement(isSgVariableDeclaration(*i),expSt,true); std::cout << prefixes[j]->class_name() << std::endl; } std::cout << "results" << std::endl; for (int j = 0; j < results.size(); j++) { std::cout << results[j]->class_name() << std::endl; } std::cout << "postfixes" << std::endl; for (int j = 0; j < postfixes.size(); j++) { SgExprStatement* expSt = SageBuilder::buildExprStatement_nfi(postfixes[j]); SageInterface::insertStatement(isSgVariableDeclaration(*i),expSt,false); std::cout << postfixes[j]->class_name() << std::endl; } replaceExps(exp,vdecl); simplifyExps(exp); } } backend(proj); return 0; }
SgVariableDeclaration * RoseStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( std::string const & variableName, SgType * type, SgScopeStatement * scope, SgFunctionParameterList * formalParameters) { using namespace SageBuilder; using namespace SageInterface; SgVariableDeclaration * variableDeclaration = buildVariableDeclaration ( variableName, type, NULL, scope); formalParameters->append_arg ( *(variableDeclaration->get_variables ().begin ())); return variableDeclaration; }
bool TaintAnalysis::magic_tainted(SgNode *node, FiniteVarsExprsProductLattice *prodLat) { if (isSgInitializedName(node)) { SgInitializedName *iname = isSgInitializedName(node); std::string vname = iname->get_name().getString(); TaintLattice *tlat = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(varID(iname))); if (tlat && 0==vname.compare(0, 7, "TAINTED")) { bool modified = tlat->set_vertex(TaintLattice::VERTEX_TAINTED); if (debug) { *debug <<"TaintAnalysis::magic_tainted: lattice is magically " <<tlat->to_string() <<(modified?" (modified)":" (not modified)") <<"\n"; } return modified; } } else if (isSgVarRefExp(node)) { SgVarRefExp *vref = isSgVarRefExp(node); std::string vname = vref->get_symbol()->get_name().getString(); TaintLattice *tlat = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(varID(vref))); if (tlat && 0==vname.compare(0, 7, "TAINTED")) { bool modified = tlat->set_vertex(TaintLattice::VERTEX_TAINTED); if (debug) { *debug <<"TaintAnalysis::magic_tainted: lattice is magically " <<tlat->to_string() <<(modified?" (modified)":" (not modified)") <<"\n"; } return modified; } } else if (isSgVariableDeclaration(node)) { SgVariableDeclaration *vdecl = isSgVariableDeclaration(node); const SgInitializedNamePtrList &inames = vdecl->get_variables(); for (size_t i=0; i<inames.size(); ++i) { std::string vname = inames[i]->get_name().getString(); TaintLattice *tlat = dynamic_cast<TaintLattice*>(prodLat->getVarLattice(varID(inames[i]))); if (tlat && 0==vname.compare(0, 7, "TAINTED")) { bool modified = tlat->set_vertex(TaintLattice::VERTEX_TAINTED); if (debug) { *debug <<"TaintAnalysis::magic_tainted: lattice is magically " <<tlat->to_string() <<(modified?" (modified)":" (not modified)") <<"\n"; } return modified; } } } return false; }
DoxygenFile::DoxygenFile(SgProject *prj, string filename) { Sg_File_Info *info = new Sg_File_Info(filename, 0, 0); SgInitializedName *iname = new SgInitializedName; stringstream sname; sname << "SAGE_Doxygen_Dummy_" << rand(); iname->set_name(sname.str()); iname->set_type(new SgTypeInt); iname->set_file_info(info); iname->get_storageModifier().setExtern(); SgVariableDeclaration *decl = new SgVariableDeclaration; decl->get_variables().push_back(iname); decl->set_startOfConstruct(info); decl->set_endOfConstruct(info); decl->get_declarationModifier().get_storageModifier().setExtern(); iname->set_parent(decl); iname->set_prev_decl_item(iname); // SgGlobal *glob = prj->get_file(0).get_globalScope(); SgSourceFile* sourceFile = isSgSourceFile(prj->get_fileList()[0]); ROSE_ASSERT(sourceFile != NULL); SgGlobal *glob = sourceFile->get_globalScope(); // glob->insertStatementInScope(decl, true); glob->get_declarations().insert(glob->get_declarations().begin(),decl); decl->set_parent(glob); SgVariableSymbol* variableSymbol = new SgVariableSymbol(iname); glob->insert_symbol(sname.str(),variableSymbol); decl->set_parent(glob); std::cout << "Before complete string." << std::endl; //glob->append_declaration(decl); iname->set_scope(glob); decl->unparseToCompleteString(); std::cout << "After complete string." << std::endl; commentParent = decl; printf("commentParent = %p\n", commentParent); }
// Remove the declaration of a given variable. void removeVariableDeclaration(SgInitializedName* initname) { SgVariableDeclaration* parent = isSgVariableDeclaration(initname->get_parent()); assert (parent); SgInitializedNamePtrList& vars = parent->get_variables(); SgInitializedNamePtrList::iterator i = vars.begin(); for (; i != vars.end(); ++i) if (*i == initname) break; assert (i != vars.end()); #if 0 vars.erase(i); if (vars.empty()) { myRemoveStatement(parent); } #endif ROSE_ASSERT (vars.size() == 1); SageInterface::myRemoveStatement(parent); }
Rose_STL_Container<SgNode*> NodeQuery::queryNodeVariableDeclarationFromName(SgNode* astNode, SgNode* nameNode){ ROSE_ASSERT( nameNode != NULL ); ROSE_ASSERT( astNode != NULL ); Rose_STL_Container<SgNode*> returnList; if(astNode->variantT() == V_SgVariableDeclaration){ SgName* sageName = isSgName(nameNode); ROSE_ASSERT( sageName != NULL ); std::string nameToMatch = sageName->str(); ROSE_ASSERT( nameToMatch.length() > 0 ); SgVariableDeclaration* sageVariableDeclaration = isSgVariableDeclaration(astNode); ROSE_ASSERT(sageVariableDeclaration != NULL); ROSE_ASSERT( sageVariableDeclaration->get_definition() != NULL ); SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables (); //see if this variable declaration fits the criteria typedef SgInitializedNamePtrList::iterator variableIterator; for (variableIterator k = sageInitializedNameList.begin (); k != sageInitializedNameList.end(); ++k) { SgInitializedName* elmVar = *k; std::string name = elmVar->get_name().str(); if(name == nameToMatch) returnList.push_back(astNode); } } return returnList; }; /* End function: queryNodeVariableDeclarationFromName */
void mlmFrontend::attachAttribute(SgPragmaDeclaration* pragma, AstAttribute* attr) { // attribute to specify memory level if(isSgVariableDeclaration(getNextStatement(pragma))) { SgVariableDeclaration* decl = isSgVariableDeclaration(getNextStatement(pragma)); ROSE_ASSERT(decl); SgInitializedNamePtrList nameList = decl->get_variables(); if(nameList.size() == 1) { SgInitializedName* initName = nameList[0]; SgSymbol* symbol = initName->get_symbol_from_symbol_table(); symbol->setAttribute("mlmAttribute", attr); } } // attribute to specify tiling level else if(isSgForStatement(getNextStatement(pragma))) { SgForStatement* forStmt = isSgForStatement(getNextStatement(pragma)); ROSE_ASSERT(forStmt); forStmt->setAttribute("mlmAttribute", attr); } }
void SimpleInstrumentation::visit ( SgNode* astNode ) { SgBasicBlock* block = isSgBasicBlock(astNode); if (block != NULL) { // Mark this as a transformation (required) Sg_File_Info* sourceLocation = Sg_File_Info::generateDefaultFileInfoForTransformationNode(); ROSE_ASSERT(sourceLocation != NULL); SgType* type = new SgTypeInt(); ROSE_ASSERT(type != NULL); SgName name = "newVariable"; SgVariableDeclaration* variableDeclaration = new SgVariableDeclaration(sourceLocation,name,type); ROSE_ASSERT(variableDeclaration != NULL); SgInitializedName* initializedName = *(variableDeclaration->get_variables().begin()); initializedName->set_file_info(Sg_File_Info::generateDefaultFileInfoForTransformationNode()); // DQ (6/18/2007): The unparser requires that the scope be set (for name qualification to work). initializedName->set_scope(block); // Liao (2/13/2008): AstTests requires this to be set variableDeclaration->set_firstNondefiningDeclaration(variableDeclaration); ROSE_ASSERT(block->get_statements().size() > 0); block->get_statements().insert(block->get_statements().begin(),variableDeclaration); variableDeclaration->set_parent(block); // Add a symbol to the sybol table for the new variable SgVariableSymbol* variableSymbol = new SgVariableSymbol(initializedName); block->insert_symbol(name,variableSymbol); } }
// Do finite differencing on one expression within one context. The expression // must be defined and valid within the entire body of root. The rewrite rules // are used to simplify expressions. When a variable var is updated from // old_value to new_value, an expression of the form (var, (old_value, // new_value)) is created and rewritten. The rewrite rules may either produce // an arbitrary expression (which will be used as-is) or one of the form (var, // (something, value)) (which will be changed to (var = value)). void doFiniteDifferencingOne(SgExpression* e, SgBasicBlock* root, RewriteRule* rules) { SgStatementPtrList& root_stmts = root->get_statements(); SgStatementPtrList::iterator i; for (i = root_stmts.begin(); i != root_stmts.end(); ++i) { if (expressionComputedIn(e, *i)) break; } if (i == root_stmts.end()) return; // Expression is not used within root, so quit vector<SgVariableSymbol*> used_symbols = SageInterface::getSymbolsUsedInExpression(e); SgName cachename = "cache_fd__"; cachename << ++SageInterface::gensym_counter; SgVariableDeclaration* cachedecl = new SgVariableDeclaration(SgNULL_FILE, cachename, e->get_type(),0 /* new SgAssignInitializer(SgNULL_FILE, e) */); SgInitializedName* cachevar = cachedecl->get_variables().back(); ROSE_ASSERT (cachevar); root->get_statements().insert(i, cachedecl); cachedecl->set_parent(root); cachedecl->set_definingDeclaration(cachedecl); cachevar->set_scope(root); SgVariableSymbol* sym = new SgVariableSymbol(cachevar); root->insert_symbol(cachename, sym); SgVarRefExp* vr = new SgVarRefExp(SgNULL_FILE, sym); vr->set_endOfConstruct(SgNULL_FILE); replaceCopiesOfExpression(e, vr, root); vector<SgExpression*> modifications_to_used_symbols; FdFindModifyingStatementsVisitor(used_symbols, modifications_to_used_symbols).go(root); cachedecl->addToAttachedPreprocessingInfo( new PreprocessingInfo(PreprocessingInfo::CplusplusStyleComment,(string("// Finite differencing: ") + cachename.str() + " is a cache of " + e->unparseToString()).c_str(),"Compiler-Generated in Finite Differencing",0, 0, 0, PreprocessingInfo::before)); if (modifications_to_used_symbols.size() == 0) { SgInitializer* cacheinit = new SgAssignInitializer(SgNULL_FILE, e); e->set_parent(cacheinit); cachevar->set_initializer(cacheinit); cacheinit->set_parent(cachevar); } else { for (unsigned int i = 0; i < modifications_to_used_symbols.size(); ++i) { SgExpression* modstmt = modifications_to_used_symbols[i]; #ifdef FD_DEBUG cout << "Updating cache after " << modstmt->unparseToString() << endl; #endif SgExpression* updateCache = 0; SgVarRefExp* varref = new SgVarRefExp(SgNULL_FILE, sym); varref->set_endOfConstruct(SgNULL_FILE); SgTreeCopy tc; SgExpression* eCopy = isSgExpression(e->copy(tc)); switch (modstmt->variantT()) { case V_SgAssignOp: { SgAssignOp* assignment = isSgAssignOp(modstmt); assert (assignment); SgExpression* lhs = assignment->get_lhs_operand(); SgExpression* rhs = assignment->get_rhs_operand(); replaceCopiesOfExpression(lhs, rhs, eCopy); } break; case V_SgPlusAssignOp: case V_SgMinusAssignOp: case V_SgAndAssignOp: case V_SgIorAssignOp: case V_SgMultAssignOp: case V_SgDivAssignOp: case V_SgModAssignOp: case V_SgXorAssignOp: case V_SgLshiftAssignOp: case V_SgRshiftAssignOp: { SgBinaryOp* assignment = isSgBinaryOp(modstmt); assert (assignment); SgExpression* lhs = assignment->get_lhs_operand(); SgExpression* rhs = assignment->get_rhs_operand(); SgTreeCopy tc; SgExpression* rhsCopy = isSgExpression(rhs->copy(tc)); SgExpression* newval = 0; switch (modstmt->variantT()) { #define DO_OP(op, nonassignment) \ case V_##op: { \ newval = new nonassignment(SgNULL_FILE, lhs, rhsCopy); \ newval->set_endOfConstruct(SgNULL_FILE); \ } \ break DO_OP(SgPlusAssignOp, SgAddOp); DO_OP(SgMinusAssignOp, SgSubtractOp); DO_OP(SgAndAssignOp, SgBitAndOp); DO_OP(SgIorAssignOp, SgBitOrOp); DO_OP(SgMultAssignOp, SgMultiplyOp); DO_OP(SgDivAssignOp, SgDivideOp); DO_OP(SgModAssignOp, SgModOp); DO_OP(SgXorAssignOp, SgBitXorOp); DO_OP(SgLshiftAssignOp, SgLshiftOp); DO_OP(SgRshiftAssignOp, SgRshiftOp); #undef DO_OP default: break; } assert (newval); replaceCopiesOfExpression(lhs, newval, eCopy); } break; case V_SgPlusPlusOp: { SgExpression* lhs = isSgPlusPlusOp(modstmt)->get_operand(); SgIntVal* one = new SgIntVal(SgNULL_FILE, 1); one->set_endOfConstruct(SgNULL_FILE); SgAddOp* add = new SgAddOp(SgNULL_FILE, lhs, one); add->set_endOfConstruct(SgNULL_FILE); lhs->set_parent(add); one->set_parent(add); replaceCopiesOfExpression(lhs,add,eCopy); } break; case V_SgMinusMinusOp: { SgExpression* lhs = isSgMinusMinusOp(modstmt)->get_operand(); SgIntVal* one = new SgIntVal(SgNULL_FILE, 1); one->set_endOfConstruct(SgNULL_FILE); SgSubtractOp* sub = new SgSubtractOp(SgNULL_FILE, lhs, one); sub->set_endOfConstruct(SgNULL_FILE); lhs->set_parent(sub); one->set_parent(sub); replaceCopiesOfExpression(lhs,sub,eCopy); } break; default: cerr << modstmt->sage_class_name() << endl; assert (false); break; } #ifdef FD_DEBUG cout << "e is " << e->unparseToString() << endl; cout << "eCopy is " << eCopy->unparseToString() << endl; #endif updateCache = doFdVariableUpdate(rules, varref, e, eCopy); #ifdef FD_DEBUG cout << "updateCache is " << updateCache->unparseToString() << endl; #endif if (updateCache) { ROSE_ASSERT(modstmt != NULL); SgNode* ifp = modstmt->get_parent(); SgCommaOpExp* comma = new SgCommaOpExp(SgNULL_FILE, updateCache, modstmt); modstmt->set_parent(comma); updateCache->set_parent(comma); if (ifp == NULL) { printf ("modstmt->get_parent() == NULL modstmt = %p = %s \n",modstmt,modstmt->class_name().c_str()); modstmt->get_startOfConstruct()->display("modstmt->get_parent() == NULL: debug"); } ROSE_ASSERT(ifp != NULL); #ifdef FD_DEBUG cout << "New expression is " << comma->unparseToString() << endl; cout << "IFP is " << ifp->sage_class_name() << ": " << ifp->unparseToString() << endl; #endif if (isSgExpression(ifp)) { isSgExpression(ifp)->replace_expression(modstmt, comma); comma->set_parent(ifp); } else { // DQ (12/16/2006): Need to handle cases that are not SgExpression (now that SgExpressionRoot is not used!) // cerr << ifp->sage_class_name() << endl; // assert (!"Bad parent type for inserting comma expression"); SgStatement* statement = isSgStatement(ifp); if (statement != NULL) { #ifdef FD_DEBUG printf ("Before statement->replace_expression(): statement = %p = %s modstmt = %p = %s \n",statement,statement->class_name().c_str(),modstmt,modstmt->class_name().c_str()); SgExprStatement* expresionStatement = isSgExprStatement(statement); if (expresionStatement != NULL) { SgExpression* expression = expresionStatement->get_expression(); printf ("expressionStatement expression = %p = %s \n",expression,expression->class_name().c_str()); } #endif statement->replace_expression(modstmt, comma); comma->set_parent(statement); } else { ROSE_ASSERT(ifp != NULL); printf ("Error: parent is neither a SgExpression nor a SgStatement ifp = %p = %s \n",ifp,ifp->class_name().c_str()); ROSE_ASSERT(false); } } #ifdef FD_DEBUG cout << "IFP is now " << ifp->unparseToString() << endl; #endif } } } }
SgVariableSymbol* putGlobalVariablesIntoClass (Rose_STL_Container<SgInitializedName*> & globalVariables, SgClassDeclaration* classDeclaration ) { // This function iterates over the list of global variables and inserts them into the iput class definition SgVariableSymbol* globalClassVariableSymbol = NULL; for (Rose_STL_Container<SgInitializedName*>::iterator var = globalVariables.begin(); var != globalVariables.end(); var++) { // printf ("Appending global variable = %s to new globalVariableContainer \n",(*var)->get_name().str()); SgVariableDeclaration* globalVariableDeclaration = isSgVariableDeclaration((*var)->get_parent()); assert(globalVariableDeclaration != NULL); // Get the global scope from the global variable directly SgGlobal* globalScope = isSgGlobal(globalVariableDeclaration->get_scope()); assert(globalScope != NULL); if (var == globalVariables.begin()) { // This is the first time in this loop, replace the first global variable with // the class declaration/definition containing all the global variables! // Note that initializers in the global variable declarations require modification // of the preinitialization list in the class's constructor! I am ignoring this for now! globalScope->replace_statement(globalVariableDeclaration,classDeclaration); // Build source position informaiton (marked as transformation) Sg_File_Info* fileInfo = Sg_File_Info::generateDefaultFileInfoForTransformationNode(); assert(fileInfo != NULL); // Add the variable of the class type to the global scope! SgClassType* variableType = new SgClassType(classDeclaration->get_firstNondefiningDeclaration()); assert(variableType != NULL); SgVariableDeclaration* variableDeclaration = new SgVariableDeclaration(fileInfo,"AMPI_globals",variableType); assert(variableDeclaration != NULL); globalScope->insert_statement(classDeclaration,variableDeclaration,false); assert(variableDeclaration->get_variables().empty() == false); SgInitializedName* variableName = *(variableDeclaration->get_variables().begin()); assert(variableName != NULL); // DQ (9/8/2007): Need to set the scope of the new variable. variableName->set_scope(globalScope); // build the return value globalClassVariableSymbol = new SgVariableSymbol(variableName); // DQ (9/8/2007): Need to add the symbol to the global scope (new testing requires this). globalScope->insert_symbol(variableName->get_name(),globalClassVariableSymbol); ROSE_ASSERT(globalScope->lookup_variable_symbol(variableName->get_name()) != NULL); } else { // for all other iterations of this loop ... // remove variable declaration from the global scope globalScope->remove_statement(globalVariableDeclaration); } // add the variable declaration to the class definition classDeclaration->get_definition()->append_member(globalVariableDeclaration); } return globalClassVariableSymbol; }
// Do partial redundancy elimination, looking for copies of one expression expr // within the basic block root. A control flow graph for root must be provided // in cfg, with a map from nodes to their statements in node_statements, a map // from edges to their CFG edge types in edge_type, and a map from edges to // their insertion points in edge_insertion_point. The algorithm used is that // of Paleri, Srikant, and Shankar ("Partial redundancy elimination: a simple, // pragmatic, and provably correct algorithm", Science of Computer Programming // 48 (2003) 1--20). void PRE::partialRedundancyEliminationOne( SgExpression* expr, SgBasicBlock* root, const myControlFlowGraph& cfg) { // SgBasicBlock* myFunctionBody = getFunctionDefinition(expr)->get_body(); // DQ (3/16/2006): Added assertions ROSE_ASSERT(expr != NULL); ROSE_ASSERT(root != NULL); vector<SgVariableSymbol*> symbols_in_expression = SageInterface::getSymbolsUsedInExpression(expr); if (anyOfListPotentiallyModifiedIn(symbols_in_expression, expr)) { // This expression updates its own arguments, and so is not idempotent // Return immediately return; } // Simple or not user-definable expressions if (isSgVarRefExp(expr)) return; if (isSgValueExp(expr)) return; if (isSgFunctionRefExp(expr)) return; if (isSgExprListExp(expr)) return; if (isSgInitializer(expr)) return; #if 0 if ( (isSgAddOp(expr) || isSgSubtractOp(expr)) && (isSgVarRefExp(isSgBinaryOp(expr)->get_lhs_operand()) || isSgValueExp(isSgBinaryOp(expr)->get_lhs_operand())) && (isSgVarRefExp(isSgBinaryOp(expr)->get_rhs_operand()) || isSgValueExp(isSgBinaryOp(expr)->get_rhs_operand()))) return; #endif // Expressions which do not keep a consistent value each time they are used if (!expressionTreeEqual(expr, expr)) return; // cerr << "Trying to do PRE using expression " << expr->unparseToString() << " whose type is " << expr->sage_class_name() << endl; VertexIter i = cfg.graph.vertices().begin(), end = cfg.graph.vertices().end(); // cerr << "CFG has " << distance(i, end) << " nodes" << endl; bool needToMakeCachevar = false; set<SgNode*> replacements; vector<pair<SgNode*, bool /* before */> > insertions; vector<bool> transp(cfg.graph.vertices().size()), comp(cfg.graph.vertices().size()), antloc(cfg.graph.vertices().size()); vector<SgNode*> first_computation(cfg.graph.vertices().size()), last_computation(cfg.graph.vertices().size()); // Set values of local node properties for (i = cfg.graph.vertices().begin(); i != end; ++i) { const vector<SgNode*>& stmts = cfg.node_statements[*i]; // Precompute test values for each statement vector<bool> argumentsModifiedInStatement(stmts.size()); vector<int> expressionComputedInStatement(stmts.size()); for (unsigned int j = 0; j < stmts.size(); ++j) { if (anyOfListPotentiallyModifiedIn(symbols_in_expression, stmts[j])) argumentsModifiedInStatement[j] = true; expressionComputedInStatement[j] = countComputationsOfExpressionIn(expr, stmts[j]); } // Compute transp transp[*i] = true; for (unsigned int j = 0; j < stmts.size(); ++j) if (argumentsModifiedInStatement[j]) transp[*i] = false; // Compute comp and do local redundancy elimination comp[*i] = false; SgNode* firstComputationInChain = 0; bool needToInsertComputation = false; bool computationInsertedOrUsed = false; // cout << "In node " << *i << endl; for (unsigned int j = 0; j < stmts.size(); ++j) { // cout << "In stmt " << j << ", expressionComputedInStatement = " << expressionComputedInStatement[j] // << ", argumentsModifiedInStatement = " << argumentsModifiedInStatement[j] << endl; if (expressionComputedInStatement[j] && !argumentsModifiedInStatement[j] && comp[*i] /* from last iter */) { // Do local redundancy elimination if (firstComputationInChain && needToInsertComputation) { insertions.push_back(make_pair(firstComputationInChain, true)); replacements.insert(firstComputationInChain); needToInsertComputation = false; } replacements.insert(stmts[j]); computationInsertedOrUsed = true; needToMakeCachevar = true; } if (expressionComputedInStatement[j]) { comp[*i] = true; if (!firstComputationInChain) { firstComputationInChain = stmts[j]; needToInsertComputation = true; if (expressionComputedInStatement[j] >= 2) { insertions.push_back(make_pair(stmts[j], true)); needToMakeCachevar = true; needToInsertComputation = false; computationInsertedOrUsed = true; replacements.insert(stmts[j]); } } last_computation[*i] = stmts[j]; } if (argumentsModifiedInStatement[j]) { comp[*i] = false; // Must come after expressionComputedInStatement check firstComputationInChain = 0; needToInsertComputation = false; } } assert (!computationInsertedOrUsed || needToMakeCachevar); // Compute antloc antloc[*i] = false; for (unsigned int j = 0; j < stmts.size(); ++j) { if (expressionComputedInStatement[j] && !argumentsModifiedInStatement[j]) { antloc[*i] = true; first_computation[*i] = stmts[j]; break; } if (argumentsModifiedInStatement[j]) { antloc[*i] = false; break; } } } // #define PRINT_PROPERTY(p) // for (i = cfg.graph.vertices().begin(); i != end; ++i) if (p[*i]) cerr << #p ": " << *i << endl; #define PRINT_PROPERTY(p) // for (i = cfg.graph.vertices().begin(); i != end; ++i) if (p[*i]) cerr << #p ": " << *i << endl; PRINT_PROPERTY(transp); PRINT_PROPERTY(comp); PRINT_PROPERTY(antloc); int (simpleGraph::*source_ptr)(int) const = &simpleGraph::source; int (simpleGraph::*target_ptr)(int) const = &simpleGraph::target; vector<bool> avin(cfg.graph.vertices().size(), true); vector<bool> avout(cfg.graph.vertices().size(), true); FIXPOINT_BEGIN(cfg) FIXPOINT_OUTPUT_BEGIN(avin, cfg); FIXPOINT_OUTPUT_BEGIN(avout, cfg); avin[v] = accumulate_neighbors(cfg, v, avout,cfg.graph.in_edges(v),&simpleGraph::source, logical_and<bool>(), true, false); avout[v] = comp[v] || (avin[v] && transp[v]); FIXPOINT_OUTPUT_END(avout, <=, cfg); FIXPOINT_OUTPUT_END(avin, <=, cfg); FIXPOINT_END(cfg, out_edges, OutEdgeIter) PRINT_PROPERTY(avin); PRINT_PROPERTY(avout); vector<bool> antin(cfg.graph.vertices().size(), true); vector<bool> antout(cfg.graph.vertices().size(), true); FIXPOINT_BEGIN(cfg) FIXPOINT_OUTPUT_BEGIN(antin, cfg); FIXPOINT_OUTPUT_BEGIN(antout, cfg); antout[v] = accumulate_neighbors(cfg, v, antin, cfg.graph.out_edges(v), target_ptr, logical_and<bool>(), true, false); antin[v] = antloc[v] || (antout[v] && transp[v]); FIXPOINT_OUTPUT_END(antout, <=, cfg); FIXPOINT_OUTPUT_END(antin, <=, cfg); FIXPOINT_END(cfg, in_edges, InEdgeIter) PRINT_PROPERTY(antin); PRINT_PROPERTY(antout); vector<bool> safein(cfg.graph.vertices().size()), safeout(cfg.graph.vertices().size()); for (i = cfg.graph.vertices().begin(); i != end; ++i) { safein[*i] = avin[*i] || antin[*i]; safeout[*i] = avout[*i] || antout[*i]; } PRINT_PROPERTY(safein); PRINT_PROPERTY(safeout); vector<bool> spavin(cfg.graph.vertices().size(), false); vector<bool> spavout(cfg.graph.vertices().size(), false); FIXPOINT_BEGIN(cfg) FIXPOINT_OUTPUT_BEGIN(spavin, cfg); FIXPOINT_OUTPUT_BEGIN(spavout, cfg); spavin[v] = safein[v] && accumulate_neighbors(cfg, v, spavout, cfg.graph.in_edges(v), source_ptr, logical_or<bool>(), false, false); spavout[v] = safeout[v] && (comp[v] || (spavin[v] && transp[v])); FIXPOINT_OUTPUT_END(spavout, >=, cfg); FIXPOINT_OUTPUT_END(spavin, >=, cfg); FIXPOINT_END(cfg, out_edges, OutEdgeIter) PRINT_PROPERTY(spavin); PRINT_PROPERTY(spavout); vector<bool> spantin(cfg.graph.vertices().size(), false); vector<bool> spantout(cfg.graph.vertices().size(), false); FIXPOINT_BEGIN(cfg) FIXPOINT_OUTPUT_BEGIN(spantin, cfg); FIXPOINT_OUTPUT_BEGIN(spantout, cfg); spantout[v] = safeout[v] && accumulate_neighbors(cfg, v, spantin, cfg.graph.out_edges(v), target_ptr, logical_or<bool>(), false, false); spantin[v] = safein[v] && (antloc[v] || (spantout[v] && transp[v])); FIXPOINT_OUTPUT_END(spantout, >=, cfg); FIXPOINT_OUTPUT_END(spantin, >=, cfg); FIXPOINT_END(cfg, in_edges, InEdgeIter) PRINT_PROPERTY(spantin); PRINT_PROPERTY(spantout); #undef PRINT_PROPERTY vector<bool> node_insert(cfg.graph.vertices().size()); vector<bool> replacef(cfg.graph.vertices().size()); vector<bool> replacel(cfg.graph.vertices().size()); // printf ("Intermediate test 1: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false"); for (i = cfg.graph.vertices().begin(); i != end; ++i) { node_insert[*i] = comp[*i] && spantout[*i] && (!transp[*i] || !spavin[*i]); replacef[*i] = antloc[*i] && (spavin[*i] || (transp[*i] && spantout[*i])); replacel[*i] = comp[*i] && (spantout[*i] || (transp[*i] && spavin[*i])); if (node_insert[*i]) { needToMakeCachevar = true; insertions.push_back(make_pair(last_computation[*i], true)); // cerr << "Insert computation of " << expr->unparseToString() << " just before last computation in " << *i << endl; } if (replacef[*i]) { needToMakeCachevar = true; replacements.insert(first_computation[*i]); // cerr << "Replace first computation of " << *i << endl; } if (replacel[*i]) { needToMakeCachevar = true; replacements.insert(last_computation[*i]); // cerr << "Replace last computation of " << *i << endl; } } vector<bool> edge_insert(cfg.graph.edges().size()); // printf ("Intermediate test 2: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false"); EdgeIter j = cfg.graph.edges().begin(), jend = cfg.graph.edges().end(); for (; j != jend; ++j) { edge_insert[*j] = !spavout[cfg.graph.source(*j)] && spavin[cfg.graph.target(*j)] && spantin[cfg.graph.target(*j)]; // printf ("edge_insert[*j] = %s \n",edge_insert[*j] ? "true" : "false"); if (edge_insert[*j]) { needToMakeCachevar = true; // cerr << "Insert computation of " << expr->unparseToString() << " on edge from " // << cfg.graph.source(*j) << " to " << cfg.graph.target(*j) << endl; } } // printf ("Before final test: needToMakeCachevar = %s \n",needToMakeCachevar ? "true" : "false"); // Add cache variable if necessary SgVarRefExp* cachevar = 0; if (needToMakeCachevar) { SgName cachevarname = "cachevar__"; cachevarname << ++SageInterface::gensym_counter; // printf ("Building variable name = %s \n",cachevarname.str()); SgType* type = expr->get_type(); if (isSgArrayType(type)) type = new SgPointerType(isSgArrayType(type)->get_base_type()); assert (SageInterface::isDefaultConstructible(type)); // FIXME: assert (isAssignable(type)); SgVariableDeclaration* decl = new SgVariableDeclaration(SgNULL_FILE, cachevarname, type, NULL); decl->set_definingDeclaration(decl); SgInitializedName* initname = decl->get_variables().back(); // DQ (10/5/2007): Added an assertion. ROSE_ASSERT(initname != NULL); decl->addToAttachedPreprocessingInfo( new PreprocessingInfo(PreprocessingInfo::CplusplusStyleComment, (string("// Partial redundancy elimination: ") + cachevarname.str() + " is a cache of " + expr->unparseToString()).c_str(), "Compiler-Generated in PRE", 0, 0, 0, PreprocessingInfo::before)); SgVariableSymbol* cachevarsym = new SgVariableSymbol(initname); decl->set_parent(root); // DQ (10/5/2007): Added scope (suggested by Jeremiah). initname->set_scope(root); root->get_statements().insert(root->get_statements().begin(),decl); root->insert_symbol(cachevarname, cachevarsym); cachevar = new SgVarRefExp(SgNULL_FILE, cachevarsym); cachevar->set_endOfConstruct(SgNULL_FILE); } // Do expression computation replacements for (set<SgNode*>::iterator i = replacements.begin(); i != replacements.end(); ++i) { ReplaceExpressionWithVarrefVisitor(expr, cachevar).traverse(*i, postorder); } // Do edge insertions // int count = 0; bool failAtEndOfFunction = false; for (j = cfg.graph.edges().begin(); j != jend; ++j) { // printf ("Build the insertion list! count = %d \n",count++); if (edge_insert[*j]) { #if 0 // DQ (3/13/2006): Compiler warns that "src" is unused, so I have commented it out! Vertex src = cfg.graph.source(*j), tgt = cfg.graph.target(*j); cerr << "Doing insertion between " << src << " and " << tgt << endl; #endif pair<SgNode*, bool> insert_point = cfg.edge_insertion_point[*j]; if (insert_point.first) { insertions.push_back(insert_point); } else { // DQ (3/16/2006): This is a visited when we fixup the NULL pointer to the initializer in a SgForStatment. cerr << "Warning: no insertion point found" << endl; //FIXME was assert printf ("Need to figure out what to do here! cfg.edge_insertion_point[*j] = %p \n",&(cfg.edge_insertion_point[*j])); failAtEndOfFunction = true; ROSE_ASSERT(false); } } } // Do within-node insertions // printf ("At start of loop: insertions.size() = %zu \n",insertions.size()); for (vector<pair<SgNode*, bool> >::iterator i = insertions.begin(); i != insertions.end(); ++i) { SgTreeCopy tc1, tc2; SgVarRefExp* cachevarCopy = isSgVarRefExp(cachevar->copy(tc1)); ROSE_ASSERT (cachevarCopy); cachevarCopy->set_lvalue(true); SgExpression* operation = new SgAssignOp(SgNULL_FILE, cachevarCopy, isSgExpression(expr->copy(tc2))); #if 0 printf ("Inside of loop: insertions.size() = %zu \n",insertions.size()); printf ("\n\ni->first = %p = %s = %s \n",i->first,i->first->class_name().c_str(),i->first->unparseToString().c_str()); printf ("operation = %p = %s = %s \n",operation,operation->class_name().c_str(),operation->unparseToString().c_str()); #endif if (isSgExpression(i->first) && !i->second) { SgNode* ifp = i->first->get_parent(); SgCommaOpExp* comma = new SgCommaOpExp(SgNULL_FILE, isSgExpression(i->first), operation); operation->set_parent(comma); comma->set_parent(ifp); i->first->set_parent(comma); if (isSgForStatement(ifp)) { isSgForStatement(ifp)->set_increment(comma); } else if (isSgBinaryOp(ifp) && isSgBinaryOp(ifp)->get_lhs_operand() == i->first) { isSgBinaryOp(ifp)->set_lhs_operand(comma); } else if (isSgBinaryOp(ifp) && isSgBinaryOp(ifp)->get_rhs_operand() == i->first) { isSgBinaryOp(ifp)->set_rhs_operand(comma); } else if (isSgUnaryOp(ifp) && isSgUnaryOp(ifp)->get_operand() == i->first) { isSgUnaryOp(ifp)->set_operand(comma); } else { cerr << ifp->sage_class_name() << endl; assert (!"Bad parent type for inserting comma expression"); } } else { SgStatement* the_computation = new SgExprStatement(SgNULL_FILE, operation); operation->set_parent(the_computation); // printf ("In pre.C: the_computation = %p = %s \n",the_computation,the_computation->class_name().c_str()); if (isSgBasicBlock(i->first) && i->second) { isSgBasicBlock(i->first)->get_statements().insert(isSgBasicBlock(i->first)->get_statements().begin(),the_computation); the_computation->set_parent(i->first); } else { #if 0 // DQ (3/14/2006): Bug here when SgExprStatement from SgForStatement test is used here! printf ("Bug here when SgExprStatement from SgForStatement test is used: i->first = %s \n",i->first->class_name().c_str()); i->first->get_file_info()->display("Location i->first"); printf ("Bug here when SgExprStatement from SgForStatement test is used: TransformationSupport::getStatement(i->first) = %s \n", TransformationSupport::getStatement(i->first)->class_name().c_str()); printf ("Bug here when SgExprStatement from SgForStatement test is used: the_computation = %s \n",the_computation->class_name().c_str()); the_computation->get_file_info()->display("Location the_computation: debug"); ROSE_ASSERT(i->first != NULL); ROSE_ASSERT(i->first->get_parent() != NULL); printf ("i->first->get_parent() = %s \n",i->first->get_parent()->class_name().c_str()); i->first->get_file_info()->display("Location i->first: debug"); #endif SgForStatement* forStatement = isSgForStatement(i->first->get_parent()); if (forStatement != NULL) { // Make sure that both pointers are not equal because they are both NULL! ROSE_ASSERT(forStatement->get_test() != NULL); SgExprStatement* possibleTest = isSgExprStatement(i->first); if ( forStatement->get_test() == possibleTest ) { // This is a special case of a SgExpressionStatement as a target in a SgForStatement // printf ("Found special case of target being the test of a SgForStatement \n"); forStatement->set_test(the_computation); the_computation->set_parent(forStatement); } } else { SgForInitStatement* forInitStatement = isSgForInitStatement(i->first->get_parent()); if (forInitStatement != NULL) { // printf ("Found the SgForInitStatement \n"); SgVariableDeclaration* possibleVariable = isSgVariableDeclaration(i->first); SgExprStatement* possibleExpression = isSgExprStatement(i->first); SgStatementPtrList & statementList = forInitStatement->get_init_stmt(); SgStatementPtrList::iterator i = statementList.begin(); bool addToForInitList = false; while ( (addToForInitList == false) && (i != statementList.end()) ) { // if ( *i == possibleVariable ) if ( *i == possibleVariable || *i == possibleExpression ) { // This is a special case of a SgExpressionStatement as a target in a SgForStatement // printf ("Found special case of SgForInitStatement transformation \n"); addToForInitList = true; } i++; } // Only modify the STL list outside of the loop over the list to avoid interator invalidation if (addToForInitList == true) { // Add the the_computation statment to the list in the SgForInitStatement. // Later if we abandon the SgForInitStatement then we would have to add it to // the list of SgInitializedName objects in the SgVariableDeclaration OR modify // the expression list to handle the extra expression (but I think this case in // handled above). // printf ("Adding the_computation to the list in the SgForInitStatement \n"); statementList.push_back(the_computation); the_computation->set_parent(forInitStatement); } } else { myStatementInsert(TransformationSupport::getStatement(i->first),the_computation,i->second,true); the_computation->set_parent(TransformationSupport::getStatement(i->first)); } } } } } // DQ (3/16/2006): debugging code to force failure at inspection point if (failAtEndOfFunction == true) { printf ("Error: internal error detected \n"); ROSE_ASSERT(false); } }
int main(int argc, char **argv) { SgProject *project = frontend(argc, argv); // Instantiate a class hierarchy wrapper. ClassHierarchyWrapper classHierarchy( project ); #if 0 std::list<SgNode *> nodes2 = NodeQuery::querySubTree(project, V_SgVariableDefinition); for (std::list<SgNode *>::iterator it = nodes2.begin(); it != nodes2.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgVariableDefinition *varDefn = isSgVariableDefinition(n); ROSE_ASSERT(varDefn != NULL); std::cout << "Var defn: " << varDefn->unparseToCompleteString() << std::endl; } std::list<SgNode *> nodes1 = NodeQuery::querySubTree(project, V_SgVariableDeclaration); for (std::list<SgNode *>::iterator it = nodes1.begin(); it != nodes1.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgVariableDeclaration *varDecl = isSgVariableDeclaration(n); ROSE_ASSERT(varDecl != NULL); SgInitializedNamePtrList &variables = varDecl->get_variables(); SgInitializedNamePtrList::iterator varIter; for (varIter = variables.begin(); varIter != variables.end(); ++varIter) { SgNode *var = *varIter; ROSE_ASSERT(var != NULL); SgInitializedName *initName = isSgInitializedName(var); ROSE_ASSERT(initName != NULL); if ( isSgClassType(initName->get_type()) ) { SgClassType *classType = isSgClassType(initName->get_type()); ROSE_ASSERT(classType != NULL); SgDeclarationStatement *declStmt = classType->get_declaration(); ROSE_ASSERT(declStmt != NULL); SgClassDeclaration *classDeclaration = isSgClassDeclaration(declStmt); ROSE_ASSERT(classDeclaration != NULL); // std::cout << "From var decl got: " << classDeclaration->unparseToCompleteString() << std::endl; SgClassDefinition *classDefinition = classDeclaration->get_definition(); if ( classDefinition != NULL ) { std::cout << "From var decl got: " << classDefinition->unparseToCompleteString() << std::endl; } } } } std::list<SgNode *> nodes = NodeQuery::querySubTree(project, V_SgClassDeclaration); for (std::list<SgNode *>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgClassDeclaration *classDeclaration1 = isSgClassDeclaration(n); ROSE_ASSERT(classDeclaration1 != NULL); SgDeclarationStatement *definingDecl = classDeclaration1->get_definingDeclaration(); if ( definingDecl == NULL ) continue; SgClassDeclaration *classDeclaration = isSgClassDeclaration(definingDecl); ROSE_ASSERT(classDeclaration != NULL); SgClassDefinition *classDefinition = classDeclaration->get_definition(); ROSE_ASSERT(classDefinition != NULL); std::cout << "Calling getSubclasses on " << classDefinition->unparseToCompleteString() << std::endl; SgClassDefinitionPtrList subclasses = classHierarchy.getSubclasses(classDefinition); // Iterate over all subclasses. for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin(); subclassIt != subclasses.end(); ++subclassIt) { SgClassDefinition *subclass = *subclassIt; ROSE_ASSERT(subclass != NULL); std::cout << "subclass" << std::endl; } } #endif #if 1 #if 0 std::list<SgNode *> nodes = NodeQuery::querySubTree(project, V_SgClassDefinition); for (std::list<SgNode *>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgClassDefinition *classDefinition = isSgClassDefinition(n); ROSE_ASSERT(classDefinition != NULL); std::cout << "Calling getSubclasses on " << classDefinition->unparseToCompleteString() << std::endl; SgClassDefinitionPtrList subclasses = classHierarchy.getSubclasses(classDefinition); // Iterate over all subclasses. for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin(); subclassIt != subclasses.end(); ++subclassIt) { SgClassDefinition *subclass = *subclassIt; ROSE_ASSERT(subclass != NULL); std::cout << "subclass" << std::endl; } } #else // Collect all function/method invocations. std::list<SgNode *> nodes = NodeQuery::querySubTree(project, V_SgFunctionCallExp); unsigned int numCallSites = 0; unsigned int numMonomorphicCallSites = 0; unsigned int numPossibleResolutions = 0; // Visit each call site. for (std::list<SgNode *>::iterator it = nodes.begin(); it != nodes.end(); ++it ) { SgNode *n = *it; ROSE_ASSERT(n != NULL); SgFunctionCallExp *functionCallExp = isSgFunctionCallExp(n); ROSE_ASSERT(functionCallExp != NULL); // We are only interested in examining method invocations. bool isDotExp = false; bool isLhsRefOrPtr = false; // std::cout << "method?: " << functionCallExp->unparseToCompleteString() << std::endl; if ( !isMethodCall(functionCallExp, isDotExp, isLhsRefOrPtr) ) continue; // std::cout << "method: " << functionCallExp->unparseToCompleteString() << std::endl; numCallSites++; if ( isDotExp && !isLhsRefOrPtr ) { // If this is a dot expression (i.e., a.foo()), we can // statically determine its type-- unless the left-hand // side is a reference type. numMonomorphicCallSites++; numPossibleResolutions++; // std::cout << "dot: " << functionCallExp->unparseToCompleteString() << std::endl; continue; } // std::cout << "methodPtr: " << functionCallExp->unparseToCompleteString() << std::endl; // Retrieve the static function declaration. SgFunctionDeclaration *functionDeclaration = getFunctionDeclaration(functionCallExp); // Ensure it is actually a method declaration. SgMemberFunctionDeclaration *memberFunctionDeclaration = isSgMemberFunctionDeclaration(functionDeclaration); ROSE_ASSERT(memberFunctionDeclaration != NULL); unsigned int numResolutionsForMethod = 0; // Certainly can be resolved to the static method (unless it // is pure virtual). if ( !isPureVirtual(memberFunctionDeclaration) ) { numResolutionsForMethod++; } #if 0 if ( ( isVirtual(functionDeclaration) ) || ( isDeclaredVirtualWithinAncestor(functionDeclaration) ) ) { #else if ( isVirtual(functionDeclaration) ) { #endif // std::cout << "tracking: " << functionDeclaration->unparseToString() << std::endl; SgClassDefinition *classDefinition = isSgClassDefinition(memberFunctionDeclaration->get_scope()); ROSE_ASSERT(classDefinition != NULL); SgClassDefinitionPtrList subclasses = classHierarchy.getSubclasses(classDefinition); // Iterate over all subclasses. for (SgClassDefinitionPtrList::iterator subclassIt = subclasses.begin(); subclassIt != subclasses.end(); ++subclassIt) { SgClassDefinition *subclass = *subclassIt; ROSE_ASSERT(subclass != NULL); // std::cout << "subclass" << std::endl; // Iterate over all of the methods defined in this subclass. SgDeclarationStatementPtrList &decls = subclass->get_members(); for (SgDeclarationStatementPtrList::iterator declIter = decls.begin(); declIter != decls.end(); ++declIter) { SgDeclarationStatement *declStmt = *declIter; ROSE_ASSERT(declStmt != NULL); SgMemberFunctionDeclaration *method = isSgMemberFunctionDeclaration(declStmt); if ( method == NULL ) { continue; } // std::cout << "checking overrides" << std::endl; // Determine whether subclass of the class defining this // method overrides the method. #if 1 if ( matchingFunctions(method, memberFunctionDeclaration) ) { // std::cout << "overries" << std::endl; // Do not consider a pure virtual method to be an // overriding method (since it can not be invoked). if ( !isPureVirtual(method) ) { numResolutionsForMethod++; } } #else if ( methodOverridesVirtualMethod(method, memberFunctionDeclaration) ) { // std::cout << "overries" << std::endl; numResolutionsForMethod++; } #endif } } if ( numResolutionsForMethod <= 1 ) numMonomorphicCallSites++; numPossibleResolutions += numResolutionsForMethod; if ( ( numResolutionsForMethod ) > 1 ) { std::cout << "Method invocation has " << numResolutionsForMethod << " possible resolutions " << std::endl; std::cout << functionCallExp->unparseToCompleteString() << std::endl; } } } #endif #endif return 0; }
// Main inliner code. Accepts a function call as a parameter, and inlines // only that single function call. Returns true if it succeeded, and false // otherwise. The function call must be to a named function, static member // function, or non-virtual non-static member function, and the function // must be known (not through a function pointer or member function // pointer). Also, the body of the function must already be visible. // Recursive procedures are handled properly (when allowRecursion is set), by // inlining one copy of the procedure into itself. Any other restrictions on // what can be inlined are bugs in the inliner code. bool doInline(SgFunctionCallExp* funcall, bool allowRecursion) { SgExpression* funname = funcall->get_function(); SgExpression* funname2 = isSgFunctionRefExp(funname); SgDotExp* dotexp = isSgDotExp(funname); SgArrowExp* arrowexp = isSgArrowExp(funname); SgExpression* thisptr = 0; if (dotexp || arrowexp) { funname2 = isSgBinaryOp(funname)->get_rhs_operand(); if (dotexp) { SgExpression* lhs = dotexp->get_lhs_operand(); // FIXME -- patch this into p_lvalue bool is_lvalue = lhs->get_lvalue(); if (isSgInitializer(lhs)) is_lvalue = false; if (!is_lvalue) { SgAssignInitializer* ai = SageInterface::splitExpression(lhs); ROSE_ASSERT (isSgInitializer(ai->get_operand())); SgInitializedName* in = isSgInitializedName(ai->get_parent()); ROSE_ASSERT (in); removeRedundantCopyInConstruction(in); lhs = dotexp->get_lhs_operand(); // Should be a var ref now } thisptr = new SgAddressOfOp(SgNULL_FILE, lhs); } else if (arrowexp) { thisptr = arrowexp->get_lhs_operand(); } else { assert (false); } } if (!funname2) { // std::cout << "Inline failed: not a call to a named function" << std::endl; return false; // Probably a call through a fun ptr } SgFunctionSymbol* funsym = 0; if (isSgFunctionRefExp(funname2)) funsym = isSgFunctionRefExp(funname2)->get_symbol(); else if (isSgMemberFunctionRefExp(funname2)) funsym = isSgMemberFunctionRefExp(funname2)->get_symbol(); else assert (false); assert (funsym); if (isSgMemberFunctionSymbol(funsym) && isSgMemberFunctionSymbol(funsym)->get_declaration()->get_functionModifier().isVirtual()) { // std::cout << "Inline failed: cannot inline virtual member functions" << std::endl; return false; } SgFunctionDeclaration* fundecl = funsym->get_declaration(); SgFunctionDefinition* fundef = fundecl->get_definition(); if (!fundef) { // std::cout << "Inline failed: no definition is visible" << std::endl; return false; // No definition of the function is visible } if (!allowRecursion) { SgNode* my_fundef = funcall; while (my_fundef && !isSgFunctionDefinition(my_fundef)) { // printf ("Before reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); my_fundef = my_fundef->get_parent(); ROSE_ASSERT(my_fundef != NULL); // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); } // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); assert (isSgFunctionDefinition(my_fundef)); if (isSgFunctionDefinition(my_fundef) == fundef) { std::cout << "Inline failed: trying to inline a procedure into itself" << std::endl; return false; } } SgVariableDeclaration* thisdecl = 0; SgName thisname("this__"); thisname << ++gensym_counter; SgInitializedName* thisinitname = 0; if (isSgMemberFunctionSymbol(funsym) && !fundecl->get_declarationModifier().get_storageModifier().isStatic()) { assert (thisptr != NULL); SgType* thisptrtype = thisptr->get_type(); const SgSpecialFunctionModifier& specialMod = funsym->get_declaration()->get_specialFunctionModifier(); if (specialMod.isConstructor()) { SgFunctionType* ft = funsym->get_declaration()->get_type(); ROSE_ASSERT (ft); SgMemberFunctionType* mft = isSgMemberFunctionType(ft); ROSE_ASSERT (mft); SgType* ct = mft->get_class_type(); thisptrtype = new SgPointerType(ct); } SgConstVolatileModifier& thiscv = fundecl->get_declarationModifier().get_typeModifier().get_constVolatileModifier(); // if (thiscv.isConst() || thiscv.isVolatile()) { FIXME thisptrtype = new SgModifierType(thisptrtype); isSgModifierType(thisptrtype)->get_typeModifier().get_constVolatileModifier() = thiscv; // } // cout << thisptrtype->unparseToString() << " --- " << thiscv.isConst() << " " << thiscv.isVolatile() << endl; SgAssignInitializer* assignInitializer = new SgAssignInitializer(SgNULL_FILE, thisptr); assignInitializer->set_endOfConstruct(SgNULL_FILE); // thisdecl = new SgVariableDeclaration(SgNULL_FILE, thisname, thisptrtype, new SgAssignInitializer(SgNULL_FILE, thisptr)); thisdecl = new SgVariableDeclaration(SgNULL_FILE, thisname, thisptrtype, assignInitializer); thisdecl->set_endOfConstruct(SgNULL_FILE); thisdecl->get_definition()->set_endOfConstruct(SgNULL_FILE); thisdecl->set_definingDeclaration(thisdecl); thisinitname = (thisdecl->get_variables()).back(); //thisinitname = lastElementOfContainer(thisdecl->get_variables()); // thisinitname->set_endOfConstruct(SgNULL_FILE); assignInitializer->set_parent(thisinitname); // printf ("Built new SgVariableDeclaration #1 = %p \n",thisdecl); // DQ (6/23/2006): New test ROSE_ASSERT(assignInitializer->get_parent() != NULL); } std::cout << "Trying to inline function " << fundecl->get_name().str() << std::endl; SgBasicBlock* funbody_raw = fundef->get_body(); SgInitializedNamePtrList& params = fundecl->get_args(); SgInitializedNamePtrList::iterator i; SgExpressionPtrList& funargs = funcall->get_args()->get_expressions(); SgExpressionPtrList::iterator j; //int ctr; // unused variable, Liao std::vector<SgInitializedName*> inits; SgTreeCopy tc; SgFunctionDefinition* function_copy = isSgFunctionDefinition(fundef->copy(tc)); ROSE_ASSERT (function_copy); SgBasicBlock* funbody_copy = function_copy->get_body(); SgFunctionDefinition* targetFunction = PRE::getFunctionDefinition(funcall); renameLabels(funbody_copy, targetFunction); std::cout << "Original symbol count: " << funbody_raw->get_symbol_table()->size() << std::endl; std::cout << "Copied symbol count: " << funbody_copy->get_symbol_table()->size() << std::endl; // std::cout << "Original symbol count f: " << fundef->get_symbol_table()->size() << std::endl; // std::cout << "Copied symbol count f: " << function_copy->get_symbol_table()->size() << std::endl; // We don't need to keep the copied function definition now that the // labels in it have been moved to the target function. Having it in the // memory pool confuses the AST tests. function_copy->set_declaration(NULL); function_copy->set_body(NULL); delete function_copy; function_copy = NULL; #if 0 SgPragma* pragmaBegin = new SgPragma("start_of_inline_function", SgNULL_FILE); SgPragmaDeclaration* pragmaBeginDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaBegin); pragmaBeginDecl->set_endOfConstruct(SgNULL_FILE); pragmaBegin->set_parent(pragmaBeginDecl); pragmaBeginDecl->set_definingDeclaration(pragmaBeginDecl); funbody_copy->prepend_statement(pragmaBeginDecl); pragmaBeginDecl->set_parent(funbody_copy); #endif ReplaceParameterUseVisitor::paramMapType paramMap; for (i = params.begin(), j = funargs.begin(); i != params.end() && j != funargs.end(); ++i, ++j) { SgAssignInitializer* ai = new SgAssignInitializer(SgNULL_FILE, *j, (*i)->get_type()); ROSE_ASSERT(ai != NULL); ai->set_endOfConstruct(SgNULL_FILE); SgName shadow_name((*i)->get_name()); shadow_name << "__" << ++gensym_counter; SgVariableDeclaration* vardecl = new SgVariableDeclaration(SgNULL_FILE,shadow_name,(*i)->get_type(),ai); vardecl->set_definingDeclaration(vardecl); vardecl->set_endOfConstruct(SgNULL_FILE); vardecl->get_definition()->set_endOfConstruct(SgNULL_FILE); printf ("Built new SgVariableDeclaration #2 = %p = %s initializer = %p \n",vardecl,shadow_name.str(),(*(vardecl->get_variables().begin()))->get_initializer()); vardecl->set_parent(funbody_copy); SgInitializedName* init = (vardecl->get_variables()).back(); // init->set_endOfConstruct(SgNULL_FILE); inits.push_back(init); ai->set_parent(init); init->set_scope(funbody_copy); funbody_copy->get_statements().insert(funbody_copy->get_statements().begin() + (i - params.begin()), vardecl); SgVariableSymbol* sym = new SgVariableSymbol(init); paramMap[*i] = sym; funbody_copy->insert_symbol(shadow_name, sym); sym->set_parent(funbody_copy->get_symbol_table()); } if (thisdecl) { thisdecl->set_parent(funbody_copy); thisinitname->set_scope(funbody_copy); funbody_copy->get_statements().insert(funbody_copy->get_statements().begin(), thisdecl); SgVariableSymbol* thisSym = new SgVariableSymbol(thisinitname); funbody_copy->insert_symbol(thisname, thisSym); thisSym->set_parent(funbody_copy->get_symbol_table()); ReplaceThisWithRefVisitor(thisSym).traverse(funbody_copy, postorder); } ReplaceParameterUseVisitor(paramMap).traverse(funbody_copy, postorder); SgName end_of_inline_name = "rose_inline_end__"; end_of_inline_name << ++gensym_counter; SgLabelStatement* end_of_inline_label = new SgLabelStatement(SgNULL_FILE, end_of_inline_name); end_of_inline_label->set_endOfConstruct(SgNULL_FILE); #if 0 printf ("\n\nCalling AST copy mechanism on a SgBasicBlock \n"); // Need to set the parent of funbody_copy to avoid error. funbody_copy->set_parent(funbody_raw->get_parent()); printf ("This is a copy of funbody_raw = %p to build funbody_copy = %p \n",funbody_raw,funbody_copy); printf ("funbody_raw->get_statements().size() = %zu \n",funbody_raw->get_statements().size()); printf ("funbody_copy->get_statements().size() = %zu \n",funbody_copy->get_statements().size()); printf ("funbody_raw->get_symbol_table()->size() = %d \n",(int)funbody_raw->get_symbol_table()->size()); printf ("funbody_copy->get_symbol_table()->size() = %d \n",(int)funbody_copy->get_symbol_table()->size()); printf ("Output the symbol table for funbody_raw \n"); funbody_raw->get_symbol_table()->print("debugging copy problem"); // printf ("Output the symbol table for funbody_copy \n"); // funbody_copy->get_symbol_table()->print("debugging copy problem"); SgProject* project_copy = TransformationSupport::getProject(funbody_raw); ROSE_ASSERT(project_copy != NULL); const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 4000; generateAstGraph(project_copy,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH); #endif // printf ("Exiting as a test after testing the symbol table \n"); // ROSE_ASSERT(false); funbody_copy->append_statement(end_of_inline_label); end_of_inline_label->set_scope(targetFunction); SgLabelSymbol* end_of_inline_label_sym = new SgLabelSymbol(end_of_inline_label); end_of_inline_label_sym->set_parent(targetFunction->get_symbol_table()); targetFunction->get_symbol_table()->insert(end_of_inline_label->get_name(), end_of_inline_label_sym); // To ensure that there is some statement after the label SgExprStatement* dummyStatement = SageBuilder::buildExprStatement(SageBuilder::buildNullExpression()); dummyStatement->set_endOfConstruct(SgNULL_FILE); funbody_copy->append_statement(dummyStatement); dummyStatement->set_parent(funbody_copy); #if 0 SgPragma* pragmaEnd = new SgPragma("end_of_inline_function", SgNULL_FILE); SgPragmaDeclaration* pragmaEndDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaEnd); pragmaEndDecl->set_endOfConstruct(SgNULL_FILE); pragmaEnd->set_parent(pragmaEndDecl); pragmaEndDecl->set_definingDeclaration(pragmaEndDecl); funbody_copy->append_statement(pragmaEndDecl); pragmaEndDecl->set_parent(funbody_copy); #endif // std::cout << "funbody_copy is " << funbody_copy->unparseToString() << std::endl; ChangeReturnsToGotosPrevisitor previsitor = ChangeReturnsToGotosPrevisitor(end_of_inline_label, funbody_copy); // std::cout << "funbody_copy 2 is " << funbody_copy->unparseToString() << std::endl; replaceExpressionWithStatement(funcall, &previsitor); // std::cout << "Inline succeeded " << funcall->get_parent()->unparseToString() << std::endl; return true; }
// Main inliner code. Accepts a function call as a parameter, and inlines // only that single function call. Returns true if it succeeded, and false // otherwise. The function call must be to a named function, static member // function, or non-virtual non-static member function, and the function // must be known (not through a function pointer or member function // pointer). Also, the body of the function must already be visible. // Recursive procedures are handled properly (when allowRecursion is set), by // inlining one copy of the procedure into itself. Any other restrictions on // what can be inlined are bugs in the inliner code. bool doInline(SgFunctionCallExp* funcall, bool allowRecursion) { #if 0 // DQ (4/6/2015): Adding code to check for consitancy of checking the isTransformed flag. ROSE_ASSERT(funcall != NULL); ROSE_ASSERT(funcall->get_parent() != NULL); SgGlobal* globalScope = TransformationSupport::getGlobalScope(funcall); ROSE_ASSERT(globalScope != NULL); // checkTransformedFlagsVisitor(funcall->get_parent()); checkTransformedFlagsVisitor(globalScope); #endif SgExpression* funname = funcall->get_function(); SgExpression* funname2 = isSgFunctionRefExp(funname); SgDotExp* dotexp = isSgDotExp(funname); SgArrowExp* arrowexp = isSgArrowExp(funname); SgExpression* thisptr = 0; if (dotexp || arrowexp) { funname2 = isSgBinaryOp(funname)->get_rhs_operand(); if (dotexp) { SgExpression* lhs = dotexp->get_lhs_operand(); // FIXME -- patch this into p_lvalue bool is_lvalue = lhs->get_lvalue(); if (isSgInitializer(lhs)) is_lvalue = false; if (!is_lvalue) { SgAssignInitializer* ai = SageInterface::splitExpression(lhs); ROSE_ASSERT (isSgInitializer(ai->get_operand())); #if 1 printf ("ai = %p ai->isTransformation() = %s \n",ai,ai->isTransformation() ? "true" : "false"); #endif SgInitializedName* in = isSgInitializedName(ai->get_parent()); ROSE_ASSERT (in); removeRedundantCopyInConstruction(in); lhs = dotexp->get_lhs_operand(); // Should be a var ref now } thisptr = new SgAddressOfOp(SgNULL_FILE, lhs); } else if (arrowexp) { thisptr = arrowexp->get_lhs_operand(); } else { assert (false); } } if (!funname2) { // std::cout << "Inline failed: not a call to a named function" << std::endl; return false; // Probably a call through a fun ptr } SgFunctionSymbol* funsym = 0; if (isSgFunctionRefExp(funname2)) funsym = isSgFunctionRefExp(funname2)->get_symbol(); else if (isSgMemberFunctionRefExp(funname2)) funsym = isSgMemberFunctionRefExp(funname2)->get_symbol(); else assert (false); assert (funsym); if (isSgMemberFunctionSymbol(funsym) && isSgMemberFunctionSymbol(funsym)->get_declaration()->get_functionModifier().isVirtual()) { // std::cout << "Inline failed: cannot inline virtual member functions" << std::endl; return false; } SgFunctionDeclaration* fundecl = funsym->get_declaration(); fundecl = fundecl ? isSgFunctionDeclaration(fundecl->get_definingDeclaration()) : NULL; SgFunctionDefinition* fundef = fundecl ? fundecl->get_definition() : NULL; if (!fundef) { // std::cout << "Inline failed: no definition is visible" << std::endl; return false; // No definition of the function is visible } if (!allowRecursion) { SgNode* my_fundef = funcall; while (my_fundef && !isSgFunctionDefinition(my_fundef)) { // printf ("Before reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); my_fundef = my_fundef->get_parent(); ROSE_ASSERT(my_fundef != NULL); // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); } // printf ("After reset: my_fundef = %p = %s \n",my_fundef,my_fundef->class_name().c_str()); assert (isSgFunctionDefinition(my_fundef)); if (isSgFunctionDefinition(my_fundef) == fundef) { std::cout << "Inline failed: trying to inline a procedure into itself" << std::endl; return false; } } SgVariableDeclaration* thisdecl = 0; SgName thisname("this__"); thisname << ++gensym_counter; SgInitializedName* thisinitname = 0; if (isSgMemberFunctionSymbol(funsym) && !fundecl->get_declarationModifier().get_storageModifier().isStatic()) { assert (thisptr != NULL); SgType* thisptrtype = thisptr->get_type(); const SgSpecialFunctionModifier& specialMod = funsym->get_declaration()->get_specialFunctionModifier(); if (specialMod.isConstructor()) { SgFunctionType* ft = funsym->get_declaration()->get_type(); ROSE_ASSERT (ft); SgMemberFunctionType* mft = isSgMemberFunctionType(ft); ROSE_ASSERT (mft); SgType* ct = mft->get_class_type(); thisptrtype = new SgPointerType(ct); } SgConstVolatileModifier& thiscv = fundecl->get_declarationModifier().get_typeModifier().get_constVolatileModifier(); // if (thiscv.isConst() || thiscv.isVolatile()) { FIXME thisptrtype = new SgModifierType(thisptrtype); isSgModifierType(thisptrtype)->get_typeModifier().get_constVolatileModifier() = thiscv; // } // cout << thisptrtype->unparseToString() << " --- " << thiscv.isConst() << " " << thiscv.isVolatile() << endl; SgAssignInitializer* assignInitializer = new SgAssignInitializer(SgNULL_FILE, thisptr); assignInitializer->set_endOfConstruct(SgNULL_FILE); #if 1 printf ("before new SgVariableDeclaration(): assignInitializer = %p assignInitializer->isTransformation() = %s \n",assignInitializer,assignInitializer->isTransformation() ? "true" : "false"); #endif thisdecl = new SgVariableDeclaration(SgNULL_FILE, thisname, thisptrtype, assignInitializer); #if 1 printf ("(after new SgVariableDeclaration(): assignInitializer = %p assignInitializer->isTransformation() = %s \n",assignInitializer,assignInitializer->isTransformation() ? "true" : "false"); #endif thisdecl->set_endOfConstruct(SgNULL_FILE); thisdecl->get_definition()->set_endOfConstruct(SgNULL_FILE); thisdecl->set_definingDeclaration(thisdecl); thisinitname = (thisdecl->get_variables()).back(); //thisinitname = lastElementOfContainer(thisdecl->get_variables()); // thisinitname->set_endOfConstruct(SgNULL_FILE); assignInitializer->set_parent(thisinitname); markAsTransformation(assignInitializer); // printf ("Built new SgVariableDeclaration #1 = %p \n",thisdecl); // DQ (6/23/2006): New test ROSE_ASSERT(assignInitializer->get_parent() != NULL); } // Get the list of actual argument expressions from the function call, which we'll later use to initialize new local // variables in the inlined code. We need to detach the actual arguments from the AST here since we'll be reattaching // them below (otherwise we would violate the invariant that the AST is a tree). SgFunctionDefinition* targetFunction = PRE::getFunctionDefinition(funcall); SgExpressionPtrList funargs = funcall->get_args()->get_expressions(); funcall->get_args()->get_expressions().clear(); BOOST_FOREACH (SgExpression *actual, funargs) actual->set_parent(NULL); // Make a copy of the to-be-inlined function so we're not modifying and (re)inserting the original. SgBasicBlock* funbody_raw = fundef->get_body(); SgInitializedNamePtrList& params = fundecl->get_args(); std::vector<SgInitializedName*> inits; SgTreeCopy tc; SgFunctionDefinition* function_copy = isSgFunctionDefinition(fundef->copy(tc)); ROSE_ASSERT (function_copy); SgBasicBlock* funbody_copy = function_copy->get_body(); renameLabels(funbody_copy, targetFunction); ASSERT_require(funbody_raw->get_symbol_table()->size() == funbody_copy->get_symbol_table()->size()); // We don't need to keep the copied SgFunctionDefinition now that the labels in it have been moved to the target function // (having it in the memory pool confuses the AST tests), but we must not delete the formal argument list or the body // because we need them below. if (function_copy->get_declaration()) { ASSERT_require(function_copy->get_declaration()->get_parent() == function_copy); function_copy->get_declaration()->set_parent(NULL); function_copy->set_declaration(NULL); } if (function_copy->get_body()) { ASSERT_require(function_copy->get_body()->get_parent() == function_copy); function_copy->get_body()->set_parent(NULL); function_copy->set_body(NULL); } delete function_copy; function_copy = NULL; #if 0 SgPragma* pragmaBegin = new SgPragma("start_of_inline_function", SgNULL_FILE); SgPragmaDeclaration* pragmaBeginDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaBegin); pragmaBeginDecl->set_endOfConstruct(SgNULL_FILE); pragmaBegin->set_parent(pragmaBeginDecl); pragmaBeginDecl->set_definingDeclaration(pragmaBeginDecl); funbody_copy->prepend_statement(pragmaBeginDecl); pragmaBeginDecl->set_parent(funbody_copy); #endif // In the to-be-inserted function body, create new local variables with distinct non-conflicting names, one per formal // argument and having the same type as the formal argument. Initialize those new local variables with the actual // arguments. Also, build a paramMap that maps each formal argument (SgInitializedName) to its corresponding new local // variable (SgVariableSymbol). ReplaceParameterUseVisitor::paramMapType paramMap; SgInitializedNamePtrList::iterator formalIter = params.begin(); SgExpressionPtrList::iterator actualIter = funargs.begin(); for (size_t argNumber=0; formalIter != params.end() && actualIter != funargs.end(); ++argNumber, ++formalIter, ++actualIter) { SgInitializedName *formalArg = *formalIter; SgExpression *actualArg = *actualIter; // Build the new local variable. // FIXME[Robb P. Matzke 2014-12-12]: we need a better way to generate a non-conflicting local variable name SgAssignInitializer* initializer = new SgAssignInitializer(SgNULL_FILE, actualArg, formalArg->get_type()); ASSERT_not_null(initializer); initializer->set_endOfConstruct(SgNULL_FILE); #if 1 printf ("initializer = %p initializer->isTransformation() = %s \n",initializer,initializer->isTransformation() ? "true" : "false"); #endif SgName shadow_name(formalArg->get_name()); shadow_name << "__" << ++gensym_counter; SgVariableDeclaration* vardecl = new SgVariableDeclaration(SgNULL_FILE, shadow_name, formalArg->get_type(), initializer); vardecl->set_definingDeclaration(vardecl); vardecl->set_endOfConstruct(SgNULL_FILE); vardecl->get_definition()->set_endOfConstruct(SgNULL_FILE); vardecl->set_parent(funbody_copy); // Insert the new local variable into the (near) beginning of the to-be-inserted function body. We insert them in the // order their corresponding actuals/formals appear, although the C++ standard does not require this order of // evaluation. SgInitializedName* init = vardecl->get_variables().back(); inits.push_back(init); initializer->set_parent(init); init->set_scope(funbody_copy); funbody_copy->get_statements().insert(funbody_copy->get_statements().begin() + argNumber, vardecl); SgVariableSymbol* sym = new SgVariableSymbol(init); paramMap[formalArg] = sym; funbody_copy->insert_symbol(shadow_name, sym); sym->set_parent(funbody_copy->get_symbol_table()); } // Similarly for "this". We create a local variable in the to-be-inserted function body that will be initialized with the // caller's "this". if (thisdecl) { thisdecl->set_parent(funbody_copy); thisinitname->set_scope(funbody_copy); funbody_copy->get_statements().insert(funbody_copy->get_statements().begin(), thisdecl); SgVariableSymbol* thisSym = new SgVariableSymbol(thisinitname); funbody_copy->insert_symbol(thisname, thisSym); thisSym->set_parent(funbody_copy->get_symbol_table()); ReplaceThisWithRefVisitor(thisSym).traverse(funbody_copy, postorder); } ReplaceParameterUseVisitor(paramMap).traverse(funbody_copy, postorder); SgName end_of_inline_name = "rose_inline_end__"; end_of_inline_name << ++gensym_counter; SgLabelStatement* end_of_inline_label = new SgLabelStatement(SgNULL_FILE, end_of_inline_name); end_of_inline_label->set_endOfConstruct(SgNULL_FILE); #if 0 printf ("\n\nCalling AST copy mechanism on a SgBasicBlock \n"); // Need to set the parent of funbody_copy to avoid error. funbody_copy->set_parent(funbody_raw->get_parent()); printf ("This is a copy of funbody_raw = %p to build funbody_copy = %p \n",funbody_raw,funbody_copy); printf ("funbody_raw->get_statements().size() = %" PRIuPTR " \n",funbody_raw->get_statements().size()); printf ("funbody_copy->get_statements().size() = %" PRIuPTR " \n",funbody_copy->get_statements().size()); printf ("funbody_raw->get_symbol_table()->size() = %d \n",(int)funbody_raw->get_symbol_table()->size()); printf ("funbody_copy->get_symbol_table()->size() = %d \n",(int)funbody_copy->get_symbol_table()->size()); printf ("Output the symbol table for funbody_raw \n"); funbody_raw->get_symbol_table()->print("debugging copy problem"); // printf ("Output the symbol table for funbody_copy \n"); // funbody_copy->get_symbol_table()->print("debugging copy problem"); SgProject* project_copy = TransformationSupport::getProject(funbody_raw); ROSE_ASSERT(project_copy != NULL); const int MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH = 4000; generateAstGraph(project_copy,MAX_NUMBER_OF_IR_NODES_TO_GRAPH_FOR_WHOLE_GRAPH); #endif funbody_copy->append_statement(end_of_inline_label); end_of_inline_label->set_scope(targetFunction); SgLabelSymbol* end_of_inline_label_sym = new SgLabelSymbol(end_of_inline_label); end_of_inline_label_sym->set_parent(targetFunction->get_symbol_table()); targetFunction->get_symbol_table()->insert(end_of_inline_label->get_name(), end_of_inline_label_sym); // To ensure that there is some statement after the label SgExprStatement* dummyStatement = SageBuilder::buildExprStatement(SageBuilder::buildNullExpression()); dummyStatement->set_endOfConstruct(SgNULL_FILE); funbody_copy->append_statement(dummyStatement); dummyStatement->set_parent(funbody_copy); #if 0 SgPragma* pragmaEnd = new SgPragma("end_of_inline_function", SgNULL_FILE); SgPragmaDeclaration* pragmaEndDecl = new SgPragmaDeclaration(SgNULL_FILE, pragmaEnd); pragmaEndDecl->set_endOfConstruct(SgNULL_FILE); pragmaEnd->set_parent(pragmaEndDecl); pragmaEndDecl->set_definingDeclaration(pragmaEndDecl); funbody_copy->append_statement(pragmaEndDecl); pragmaEndDecl->set_parent(funbody_copy); #endif ChangeReturnsToGotosPrevisitor previsitor = ChangeReturnsToGotosPrevisitor(end_of_inline_label, funbody_copy); replaceExpressionWithStatement(funcall, &previsitor); // Make sure the AST is consistent. To save time, we'll just fix things that we know can go wrong. For instance, the // SgAsmExpression.p_lvalue data member is required to be true for certain operators and is set to false in other // situations. Since we've introduced new expressions into the AST we need to adjust their p_lvalue according to the // operators where they were inserted. markLhsValues(targetFunction); #ifdef NDEBUG AstTests::runAllTests(SageInterface::getProject()); #endif #if 0 // DQ (4/6/2015): Adding code to check for consitancy of checking the isTransformed flag. ROSE_ASSERT(funcall != NULL); ROSE_ASSERT(funcall->get_parent() != NULL); ROSE_ASSERT(globalScope != NULL); // checkTransformedFlagsVisitor(funcall->get_parent()); checkTransformedFlagsVisitor(globalScope); #endif // DQ (4/7/2015): This fixes something I was required to fix over the weekend and which is fixed more directly, I think. // Mark the things we insert as being transformations so they get inserted into the output by backend() markAsTransformation(funbody_copy); return true; }
void TypeTransformation::visit ( SgNode* astNode ) { SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(astNode); if (variableDeclaration != NULL) { #if 0 // One way to know where you are when your doing a transformation (debugging). printf ("Found a variable decaration: \n"); variableDeclaration->get_file_info()->display("Found a variable decaration"); #endif SgInitializedNamePtrList & varList = variableDeclaration->get_variables(); SgInitializedNamePtrList::iterator i = varList.begin(); bool transformed = false; // Iterate over the SgInitializedName objects. while (i != varList.end()) { SgPointerType* pointerType = isSgPointerType((*i)->get_type()); if (pointerType != NULL) { // Types are shared, so don't modify the types directly, but point to a new type. (*i)->set_type(SageBuilder::buildRestrictType((*i)->get_type())); #if 1 printf ("In TypeTransformation::visit(): Calling setTransformation on SgInitializedName: i = %p = %s \n",*i,(*i)->get_name().str()); #endif // DQ (4/14/2015): Explicitly set this as containing a transformation (we might want // to alternatively fixup the token-based unparsing frontier tests to triggered based // on the setting of the isModified flag in each IR node. // (*i)->set_containsTransformation(true); // (*i)->setTransformation(); transformed = true; } i++; } if (transformed == true) { #if 0 // DQ (4/16/2015): That this can be commented out means that we have general support in place to // interpret transformations from status of the isModified flags that are set by all of the // set_* access functions. This interpretation of the isModified flag status to explicitly // mark transformations is handled in the function: // SimpleFrontierDetectionForTokenStreamMapping::evaluateInheritedAttribute() // in file: simpleFrontierDetection.C // DQ (4/14/2015): Mark the SgVariableDeclaration as being a transformation. variableDeclaration->setTransformation(); // Also set to be output in the generated code. variableDeclaration->setOutputInCodeGeneration(); // By definition: for this to be a transformation it cannot also contain a transforamtion. ROSE_ASSERT(variableDeclaration->get_containsTransformation() == false); ROSE_ASSERT(variableDeclaration->isTransformation() == true); #endif } } }
//Generates SSA form numbers for the variables contained in the CFG node labeled *label and attaches them as AstValueAttributes to the related SgNodes //Generates phi statements for the node if it is an if node; Collects those phi statements in a phi attribute and attaches it to the related SgNode //Continues the traversal of the CFG; The CFG nodes are traversed in the topological order that treats if nodes as follows: //if node -> true branch -> false branch -> (phi statements for the if node are now finished) -> if node's associated continue node and its successors //Assumption: The node is located in in the inTrueBranch branch of the if node labeled *condLabel (These two arguments are required to generate the SSA form numbers) void SSAGenerator::processNode(Label* label, Label* condLabel, bool inTrueBranch) { SgNode* node = labeler->getNode(*label); LabelSet successors = flow->succ(*label); assert(successors.size() <= 2); //Skip the current node if it is just a return node for a called function if(labeler->isFunctionCallReturnLabel(*label)) { logger[Sawyer::Message::DEBUG] << "- - - - - - - - - - - - - - - - - - - - - - - - -" << endl; logger[Sawyer::Message::DEBUG] << "Ignoring function call return node " << *label << endl; assert(successors.size() == 1); Label nextLabel = *successors.begin(); //If the next node is not the continue node to any of the enclosing condition nodes and not the exit node: Process it if(!isExitOrContOfPred(&nextLabel, label)) processNode(&nextLabel, condLabel, inTrueBranch); return; } logger[Sawyer::Message::DEBUG] << "- - - - - - - - - - - - - - - - - - - - - - - - -" << endl; logger[Sawyer::Message::DEBUG] << "processNode() called for label " << *label << endl; SgVariableDeclaration* varDec = dynamic_cast<SgVariableDeclaration*>(node); SgExprStatement* exprStmt = dynamic_cast<SgExprStatement*>(node); if(varDec) //Variable declaration { SgInitializedNamePtrList varNames = varDec->get_variables(); SgInitializedNamePtrList::iterator i = varNames.begin(); while(i != varNames.end()) { string name = (*i)->get_qualified_name(); //Update the varsDeclaredInTrueBranch/varsDeclaredInFalseBranch attribute in the PhiAttribute of the condition node if(condLabel != NULL) { SgNode* condNode = labeler->getNode(*condLabel); AstAttribute* condAtt = condNode->getAttribute("PHI"); assert(condAtt != NULL); PhiAttribute* condPhiAtt = dynamic_cast<PhiAttribute*>(condAtt); assert(condPhiAtt != NULL); if(inTrueBranch) condPhiAtt->varsDeclaredInTrueBranch.insert(name); else condPhiAtt->varsDeclaredInFalseBranch.insert(name); } SgAssignInitializer* assignInit = dynamic_cast<SgAssignInitializer*>((*i)->get_initializer()); if(assignInit) //Declaration with initialization { SgExpression* ex = assignInit->get_operand(); processSgExpression(ex, condLabel, inTrueBranch); } else //Declaration without initialization { assert((*i)->get_initializer() == NULL); } //Assign number to declared variable int number = nextNumber(name, condLabel, inTrueBranch); logger[Sawyer::Message::DEBUG] << "Next number for variable " << name << ": " << number << endl; AstValueAttribute<int>* numberAtt = new AstValueAttribute<int>(number); (*i)->setAttribute("SSA_NUMBER", numberAtt); i++; } } else if(exprStmt) //Assignment to variable or if statement or function call or ... { SgExpression* ex = exprStmt->get_expression(); processSgExpression(ex, condLabel, inTrueBranch); } else //CFG node that is not a variable declaration and not an expression statement; Should only be the case for the first node (Entry), the last node (Exit) and return nodes { logger[Sawyer::Message::DEBUG] << "Node is not a variable declaration and not an expression statement" << endl; SgReturnStmt* retStmt = dynamic_cast<SgReturnStmt*>(node); assert(labeler->isFunctionEntryLabel(*label) || labeler->isFunctionExitLabel(*label) || retStmt != NULL); } //Continue traversal of CFG if(successors.size() == 1) //Current node is a regular node (not an if node) { Label nextLabel = *successors.begin(); //If the next node is not the continue node to any of the enclosing condition nodes and not the exit node: Process it if(!isExitOrContOfPred(&nextLabel, label)) processNode(&nextLabel, condLabel, inTrueBranch); } else if(successors.size() == 2) //Current node is an if node { assert(exprStmt != NULL); //Attach PhiAttribute to node that (for now) only includes its reaching variable numbers map<string, int> reachingNumbers = currentNumberMap; if(condLabel != NULL) { SgNode* condNode = labeler->getNode(*condLabel); AstAttribute* condAtt = condNode->getAttribute("PHI"); assert(condAtt != NULL); PhiAttribute* condPhiAtt = dynamic_cast<PhiAttribute*>(condAtt); assert(condPhiAtt != NULL); map<string, int>::iterator m = reachingNumbers.begin(); while(m != reachingNumbers.end()) { //m->first is in scope at the current node only if it is in scope at the condition node or it is declared locally in the current node's branch of the condition node bool inScope = (condPhiAtt->reachingNumbers.find(m->first) != condPhiAtt->reachingNumbers.end()) || (inTrueBranch && condPhiAtt->varsDeclaredInTrueBranch.find(m->first) != condPhiAtt->varsDeclaredInTrueBranch.end()) || (!inTrueBranch && condPhiAtt->varsDeclaredInFalseBranch.find(m->first) != condPhiAtt->varsDeclaredInFalseBranch.end()); if(!inScope) { m = reachingNumbers.erase(m); continue; } //Reaching number for m->first has to be updated //TODO: Makes no sense to take reaching numbers from current numbers in the first place m->second = currentNumber(m->first, condLabel, inTrueBranch); m++; } } CondAtomic* cond = new CondAtomic(*label); PhiAttribute* phiAtt = new PhiAttribute(reachingNumbers, cond); exprStmt->setAttribute("PHI", phiAtt); //Identify true successor, false successor and continue node Flow trueOutEdges = flow->outEdgesOfType(*label, EDGE_TRUE); Flow falseOutEdges = flow->outEdgesOfType(*label, EDGE_FALSE); assert( (trueOutEdges.size() == 1) && (falseOutEdges.size() == 1) ); Edge outTrue = *trueOutEdges.begin(); Edge outFalse = *falseOutEdges.begin(); Label nextLabelTrue = outTrue.target(); Label nextLabelFalse = outFalse.target(); Label* contLabel = getContinueLabel(*label); //Process true and false branch ContNodeAttribute* contAttr = getContinueNodeAttr(*label); bool commitPhiStatements = true; //"Hack": //If one or both of the two branches definitely return there will be phi statements created for the current node although the SSA form that is being created here does not require them in that case //They are however required to find out current variable numbers in the branch/branches that definitely return //Therefore in that case the phi statements will be created but not committed if (contAttr == NULL) //Both branches definitely return { if(!isExitOrContOrContOfPred(&nextLabelTrue, label)) processNode(&nextLabelTrue, label, true); //"Hack" if(!isExitOrContOrContOfPred(&nextLabelFalse, label)) processNode(&nextLabelFalse, label, false); //"Hack" commitPhiStatements = false; } else if (contAttr->trueBranchReturns == YES && contAttr->falseBranchReturns != YES) //Only the true branch definitely returns { if(!isExitOrContOrContOfPred(&nextLabelTrue, label)) processNode(&nextLabelTrue, label, true); //"Hack" if(condLabel == NULL) //No enclosing condition node exists { //"Hack"-phi-statement needs to be used to determine current variable numbers because processing the true branch modified currentNumberMap if(!isExitOrContOrContOfPred(&nextLabelFalse, label)) processNode(&nextLabelFalse, label, inTrueBranch); } else if(!isExitOrContOrContOfPred(&nextLabelFalse, label)) processNode(&nextLabelFalse, condLabel, inTrueBranch); commitPhiStatements = false; } else if (contAttr->trueBranchReturns != YES && contAttr->falseBranchReturns == YES) //Only the false branch definitely returns { if(!isExitOrContOrContOfPred(&nextLabelTrue, label)) processNode(&nextLabelTrue, condLabel, inTrueBranch); if(!isExitOrContOrContOfPred(&nextLabelFalse, label)) processNode(&nextLabelFalse, label, false); //"Hack" commitPhiStatements = false; } else //Neither of the two branches definitely returns { assert(!(contAttr->trueBranchReturns == YES && contAttr->falseBranchReturns == YES)); if(!isExitOrContOrContOfPred(&nextLabelTrue, label)) processNode(&nextLabelTrue, label, true); if(!isExitOrContOrContOfPred(&nextLabelFalse, label)) processNode(&nextLabelFalse, label, false); commitPhiStatements = true; } if(commitPhiStatements) //Commit phi statements: Generate a new number for the variable of each phi statement and save that number in its respective newNumber attribute { vector<PhiStatement*>::iterator i = phiAtt->phiStatements.begin(); logger[Sawyer::Message::DEBUG] << "- - - - - - - - - - - - - - - - - - - - - - - - -" << endl; logger[Sawyer::Message::DEBUG] << "Phi statements created for node with label " << *label << ":" << endl; while (i != phiAtt->phiStatements.end()) { if((*i)->trueNumber != (*i)->falseNumber) { //Generate new number for phi statement's variable int newNumber = nextNumber((*i)->varName, condLabel, inTrueBranch); (*i)->newNumber = newNumber; logger[Sawyer::Message::DEBUG] << (*i)->toString() << endl; } i++; } logger[Sawyer::Message::DEBUG] << "- - - - - - - - - - - - - - - - - - - - - - - - -" << endl; logger[Sawyer::Message::DEBUG] << "COMPLETE PHI ATTRIBUTE:" << endl << phiAtt->toString() << endl; } else //Delete phi statements ("Hack") { phiAtt->phiStatements.clear(); } //If the continue node exists and is not the continue node to any of the enclosing condition nodes and not the exit node: Process it if(contLabel != NULL && !isExitOrContOfPred(contLabel, label)) { processNode(contLabel, condLabel, inTrueBranch); } } }
NodeQuerySynthesizedAttributeType NodeQuery::querySolverVariableTypes (SgNode * astNode) { ROSE_ASSERT (astNode != NULL); NodeQuerySynthesizedAttributeType returnNodeList; /* SgVariableDeclaration* sageVariableDeclaration = isSgVariableDeclaration(astNode); if(sageVariableDeclaration != NULL) { SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables(); printf ("\nHere is a function declaration :Line = %d Columns = %d \n", ROSE:: getLineNumber (isSgLocatedNode(astNode) ), ROSE:: getColumnNumber ( isSgLocatedNode(astNode) )); cout << "The filename is:" << ROSE::getFileName(isSgLocatedNode(astNode)) << endl; typedef SgInitializedNamePtrList::iterator LI; for ( LI i = sageInitializedNameList.begin(); i != sageInitializedNameList.end(); ++i) { SgType* sageElementType = i->get_type(); ROSE_ASSERT( sageElementType != NULL); cout << "The class name is: " << sageElementType->sage_class_name() << endl; returnNodeList.push_back( sageElementType ); } cout << endl << "End printout of this Initialized Name list" << endl; } */ // SgVarRefExp *sageVarRefExp = isSgVarRefExp (astNode); switch (astNode->variantT ()) { case V_SgVariableDeclaration: { SgVariableDeclaration *sageVariableDeclaration = isSgVariableDeclaration (astNode); ROSE_ASSERT (sageVariableDeclaration != NULL); SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables (); #if DEBUG_NODEQUERY printf ("\nIn filename: %s ", ROSE::getFileName (isSgLocatedNode (astNode))); printf ("\nHere is a variable :Line = %d Columns = %d \n", ROSE::getLineNumber (isSgLocatedNode (astNode)), ROSE::getColumnNumber (isSgLocatedNode (astNode))); //cout << "The typename of the variable is: " << typeName << endl; #endif typedef SgInitializedNamePtrList::iterator variableIterator; SgType *typeNode; for (variableIterator variableListElement = sageInitializedNameList.begin (); variableListElement != sageInitializedNameList.end (); ++variableListElement) { SgInitializedName* elmVar = *variableListElement; ROSE_ASSERT (elmVar != NULL); typeNode = elmVar->get_type (); ROSE_ASSERT (typeNode != NULL); returnNodeList.push_back (typeNode); } break; } /* End case V_SgVariableDeclaration */ case V_SgFunctionDeclaration: case V_SgMemberFunctionDeclaration: { SgFunctionDeclaration * sageFunctionDeclaration = isSgFunctionDeclaration (astNode); ROSE_ASSERT (sageFunctionDeclaration != NULL); SgInitializedNamePtrList sageInitializedNameList = sageFunctionDeclaration->get_args (); SgType *typeNode; typedef SgInitializedNamePtrList::iterator variableIterator; for (variableIterator variableListElement = sageInitializedNameList.begin (); variableListElement != sageInitializedNameList.end (); ++variableListElement) { SgInitializedName* elmVar = *variableListElement; ROSE_ASSERT (elmVar != NULL); typeNode = elmVar->get_type (); ROSE_ASSERT (typeNode != NULL); returnNodeList.push_back (typeNode); } break; } default: { // DQ (8/20/2005): Added default to avoid compiler warnings about unrepresented cases } } /* End switch case astNode */ return returnNodeList; } /* End function querySolverType() */
int main( int argc, char * argv[] ) { // Option to linearize the array. Rose_STL_Container<std::string> localCopy_argv = CommandlineProcessing::generateArgListFromArgcArgv(argc, argv); int newArgc; char** newArgv = NULL; vector<string> argList = localCopy_argv; if (CommandlineProcessing::isOption(argList,"-f2c:","linearize",true) == true) { isLinearlizeArray = true; } CommandlineProcessing::generateArgcArgvFromList(argList,newArgc, newArgv); // Build the AST used by ROSE SgProject* project = frontend(newArgc,newArgv); AstTests::runAllTests(project); if (SgProject::get_verbose() > 2) generateAstGraph(project,8000,"_orig"); // Traversal with Memory Pool to search for variableDeclaration variableDeclTraversal translateVariableDeclaration; traverseMemoryPoolVisitorPattern(translateVariableDeclaration); for(vector<SgVariableDeclaration*>::iterator dec=variableDeclList.begin(); dec!=variableDeclList.end(); ++dec) { /* For the Fortran AST, a single variableDeclaration can be shared by multiple variables. This violated the normalization rules for C unparser. Therefore, we have to transform it. */ SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(*dec); ROSE_ASSERT(variableDeclaration); if((variableDeclaration->get_variables()).size() != 1) { updateVariableDeclarationList(variableDeclaration); statementList.push_back(variableDeclaration); removeList.push_back(variableDeclaration); } } // reset the vector that collects all variable declaration. We need to walk through memory pool again to find types variableDeclList.clear(); traverseMemoryPoolVisitorPattern(translateVariableDeclaration); for(vector<SgVariableDeclaration*>::iterator dec=variableDeclList.begin(); dec!=variableDeclList.end(); ++dec) { SgVariableDeclaration* variableDeclaration = isSgVariableDeclaration(*dec); ROSE_ASSERT(variableDeclaration); SgInitializedNamePtrList initializedNameList = variableDeclaration->get_variables(); for(SgInitializedNamePtrList::iterator i=initializedNameList.begin(); i!=initializedNameList.end();++i) { SgInitializedName* initiallizedName = isSgInitializedName(*i); SgType* baseType = initiallizedName->get_type(); if(baseType->variantT() == V_SgArrayType) { SgArrayType* arrayBase = isSgArrayType(baseType); // At this moment, we are still working on the Fortran-stype AST. Therefore, there is no nested types for multi-dim array. if(arrayBase->findBaseType()->variantT() == V_SgTypeString) { arrayBase->reset_base_type(translateType(arrayBase->findBaseType())); arrayBase->set_rank(arrayBase->get_rank()+1); } } else { initiallizedName->set_type(translateType(baseType)); } } } // replace the AttributeSpecificationStatement Rose_STL_Container<SgNode*> AttributeSpecificationStatement = NodeQuery::querySubTree (project,V_SgAttributeSpecificationStatement); for (Rose_STL_Container<SgNode*>::iterator i = AttributeSpecificationStatement.begin(); i != AttributeSpecificationStatement.end(); i++) { SgAttributeSpecificationStatement* attributeSpecificationStatement = isSgAttributeSpecificationStatement(*i); ROSE_ASSERT(attributeSpecificationStatement); translateAttributeSpecificationStatement(attributeSpecificationStatement); statementList.push_back(attributeSpecificationStatement); removeList.push_back(attributeSpecificationStatement); } // replace the parameter reference parameterTraversal translateParameterRef; traverseMemoryPoolVisitorPattern(translateParameterRef); for(vector<SgVarRefExp*>::iterator i=parameterRefList.begin(); i!=parameterRefList.end(); ++i) { SgVarRefExp* parameterRef = isSgVarRefExp(*i); if(parameterSymbolList.find(parameterRef->get_symbol()) != parameterSymbolList.end()) { SgExpression* newExpr = isSgExpression(deepCopy(parameterSymbolList.find(parameterRef->get_symbol())->second)); ROSE_ASSERT(newExpr); newExpr->set_parent(parameterRef->get_parent()); replaceExpression(parameterRef, newExpr, false); } } /* Parameters will be replaced by #define, all the declarations should be removed */ for(map<SgVariableSymbol*,SgExpression*>::iterator i=parameterSymbolList.begin();i!=parameterSymbolList.end();++i) { SgVariableSymbol* symbol = i->first; SgInitializedName* initializedName = symbol->get_declaration(); SgVariableDeclaration* decl = isSgVariableDeclaration(initializedName->get_parent()); statementList.push_back(decl); removeList.push_back(decl); } // Traversal with Memory Pool to search for arrayType arrayTypeTraversal translateArrayType; traverseMemoryPoolVisitorPattern(translateArrayType); for(vector<SgArrayType*>::iterator i=arrayTypeList.begin(); i!=arrayTypeList.end(); ++i) { if(isLinearlizeArray) { linearizeArrayDeclaration(*i); } else { translateArrayDeclaration(*i); } } // Traversal with Memory Pool to search for pntrArrRefExp pntrArrRefTraversal translatePntrArrRefExp; traverseMemoryPoolVisitorPattern(translatePntrArrRefExp); for(vector<SgPntrArrRefExp*>::iterator i=pntrArrRefList.begin(); i!=pntrArrRefList.end(); ++i) { if(isLinearlizeArray) { linearizeArraySubscript(*i); } else { translateArraySubscript(*i); } } Rose_STL_Container<SgNode*> functionList = NodeQuery::querySubTree (project,V_SgFunctionDeclaration); for (Rose_STL_Container<SgNode*>::iterator i = functionList.begin(); i != functionList.end(); i++) { if((isSgProcedureHeaderStatement(*i) != NULL) || (isSgProgramHeaderStatement(*i) != NULL)){ SgFunctionDeclaration* functionBody = isSgFunctionDeclaration(*i); bool hasReturnVal = false; if(isSgProcedureHeaderStatement(functionBody)) { hasReturnVal = isSgProcedureHeaderStatement(functionBody)->isFunction(); } fixFortranSymbolTable(functionBody->get_definition(),hasReturnVal); } } // Traversal with Memory Pool to search for equivalenceStatement equivalencelTraversal translateEquivalenceStmt; traverseMemoryPoolVisitorPattern(translateEquivalenceStmt); for(vector<SgEquivalenceStatement*>::iterator i=equivalenceList.begin(); i!=equivalenceList.end(); ++i) { SgEquivalenceStatement* equivalenceStatement = isSgEquivalenceStatement(*i); ROSE_ASSERT(equivalenceStatement); translateEquivalenceStatement(equivalenceStatement); statementList.push_back(equivalenceStatement); removeList.push_back(equivalenceStatement); } // Simple traversal, bottom-up, to translate the rest f2cTraversal f2c; f2c.traverseInputFiles(project,postorder); // removing all the unsed statement from AST for(vector<SgStatement*>::iterator i=statementList.begin(); i!=statementList.end(); ++i) { removeStatement(*i); (*i)->set_parent(NULL); } // deepDelete the removed nodes for(vector<SgNode*>::iterator i=removeList.begin(); i!=removeList.end(); ++i) { deepDelete(*i); } /* 1. There should be no Fortran-specific AST nodes in the whole AST graph after the translation. TODO: make sure translator generating clean AST */ //generateDOT(*project); if (SgProject::get_verbose() > 2) generateAstGraph(project,8000); return backend(project); }
NameQuerySynthesizedAttributeType NameQuery::queryVariableNamesWithTypeName (SgNode * astNode, string matchingName) { ROSE_ASSERT (astNode != 0); ROSE_ASSERT (matchingName.length () > 0); NameQuerySynthesizedAttributeType returnNameList; // SgVarRefExp *sageVarRefExp = isSgVarRefExp (astNode); switch (astNode->variantT ()) { case V_SgVariableDeclaration: { SgVariableDeclaration *sageVariableDeclaration = isSgVariableDeclaration (astNode); ROSE_ASSERT (sageVariableDeclaration != NULL); SgInitializedNamePtrList sageInitializedNameList = sageVariableDeclaration->get_variables (); #if DEBUG_NAMEQUERY printf ("\nIn filename: %s ", ROSE::getFileName (isSgLocatedNode (astNode))); printf ("\nHere is a variable :Line = %d Columns = %d \n", ROSE::getLineNumber (isSgLocatedNode (astNode)), ROSE::getColumnNumber (isSgLocatedNode (astNode))); //cout << "The typename of the variable is: " << typeName << endl; #endif SgType *typeNode; typedef SgInitializedNamePtrList::iterator variableIterator; for (variableIterator variableListElement = sageInitializedNameList.begin (); variableListElement != sageInitializedNameList.end (); ++variableListElement) { SgInitializedName* elmVar = *variableListElement; ROSE_ASSERT (elmVar != NULL); typeNode = elmVar->get_type (); ROSE_ASSERT (typeNode != NULL); string typeName = TransformationSupport::getTypeName(typeNode); if (typeName == matchingName) { string name = elmVar->get_name ().str (); ROSE_ASSERT (name.length () > 0); returnNameList.push_back (name); #if DEBUG_NAMEQUERY cout << "The name of the variable is: " << name << endl; #endif } } break; } /* End case V_SgVariableDeclaration */ case V_SgFunctionDeclaration: case V_SgMemberFunctionDeclaration: { SgFunctionDeclaration * sageFunctionDeclaration = isSgFunctionDeclaration (astNode); ROSE_ASSERT (sageFunctionDeclaration != NULL); SgInitializedNamePtrList sageInitializedNameList = sageFunctionDeclaration->get_args (); SgType *typeNode; typedef SgInitializedNamePtrList::iterator variableIterator; for (variableIterator variableListElement = sageInitializedNameList.begin (); variableListElement != sageInitializedNameList.end (); ++variableListElement) { SgInitializedName* elmVar = *variableListElement; ROSE_ASSERT (elmVar != NULL); typeNode = elmVar->get_type (); ROSE_ASSERT (typeNode != NULL); string typeName = TransformationSupport::getTypeName (typeNode); if (typeName == matchingName) { string name = elmVar->get_name ().str (); ROSE_ASSERT (name.length () > 0); returnNameList.push_back (name); #if DEBUG_NAMEQUERY cout << "The name of the variable is: " << name << endl; #endif } } break; } default: { // DQ (8/20/2005): Added default to avoid compiler warnings about unrepresented cases } } /* End switch case astNode */ return returnNameList; } /* End function NameQuery::queryNameVariableNames() */
void FortranCUDAUserSubroutine::createStatements () { using namespace SageInterface; using boost::iequals; using std::string; using std::vector; class TreeVisitor: public AstSimpleProcessing { private: /* * ====================================================== * The recursive visit of a user subroutine populates * this vector with successive function calls which are * then appended after the visit * ====================================================== */ vector < SgProcedureHeaderStatement * > calledRoutines; public: vector < SgProcedureHeaderStatement * > getCalledRoutinesInStatement() { return calledRoutines; } TreeVisitor () { } virtual void visit (SgNode * node) { SgExprStatement * isExprStatement = isSgExprStatement ( node ); if ( isExprStatement != NULL ) { SgFunctionCallExp * functionCallExp = isSgFunctionCallExp ( isExprStatement->get_expression() ); if ( functionCallExp != NULL ) { string const calleeName = functionCallExp->getAssociatedFunctionSymbol ()->get_name ().getString (); Debug::getInstance ()->debugMessage ("Found function call in user subroutine " + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); /* * ====================================================== * As we are in fortran, all user subroutines must be * SgProcedureHeaderStatements = subroutines and not * functions. This might be extended to cover also * functions in the future (?). Probably not in OP2 * ====================================================== */ SgProcedureHeaderStatement * isProcedureHeaderStatement = isSgProcedureHeaderStatement ( functionCallExp->getAssociatedFunctionDeclaration() ); calledRoutines.push_back ( isProcedureHeaderStatement ); } } } }; Debug::getInstance ()->debugMessage ("User subroutine: outputting and modifying statements", Debug::FUNCTION_LEVEL, __FILE__, __LINE__); SgFunctionParameterList * originalParameters = originalSubroutine->get_parameterList (); vector <SgStatement *> originalStatements = originalSubroutine->get_definition ()->get_body ()->get_statements (); for (vector <SgStatement *>::iterator it = originalStatements.begin (); it != originalStatements.end (); ++it) { SgExprStatement * isExprStatement = isSgExprStatement ( *it ); if ( isExprStatement != NULL ) { SgFunctionCallExp * functionCallExp = isSgFunctionCallExp ( isExprStatement->get_expression() ); if ( functionCallExp != NULL ) { string const calleeName = functionCallExp->getAssociatedFunctionSymbol ()->get_name ().getString (); Debug::getInstance ()->debugMessage ("Found function call in user subroutine " + calleeName + "'", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); /* * ====================================================== * As we are in fortran, all user subroutines must be * SgProcedureHeaderStatements = subroutines and not * functions. This might be extended to cover also * functions in the future (probably not in OP2) * ====================================================== */ SgProcedureHeaderStatement * isProcedureHeaderStatement = isSgProcedureHeaderStatement ( functionCallExp->getAssociatedFunctionDeclaration() ); calledRoutines.push_back ( isProcedureHeaderStatement ); } } SgVariableDeclaration * isVariableDeclaration = isSgVariableDeclaration ( *it); if (isVariableDeclaration == NULL) { /* * ====================================================== * Do not append use statement, because other subroutines * are directly appended to the CUDA module * ====================================================== */ SgUseStatement * isUseStmt = isSgUseStatement ( *it ); if (isUseStmt != NULL) { Debug::getInstance ()->debugMessage ( "Not appending use statement", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); } else { Debug::getInstance ()->debugMessage ( "Appending (non-variable-declaration) statement", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); appendStatement (*it, subroutineScope); /* * ====================================================== * Recursively look for subroutine calls inside shallow * nodes in the routines (e.g. when a call is inside an * if). After the visit get the generated vector of names * and append it to the userSubroutine vector * ====================================================== */ TreeVisitor * visitor = new TreeVisitor (); visitor->traverse (*it, preorder); Debug::getInstance ()->debugMessage ("Appending deep subroutine calls", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); vector < SgProcedureHeaderStatement * > deepStatementCalls = visitor->getCalledRoutinesInStatement (); vector < SgProcedureHeaderStatement * >::iterator itDeepCalls; for (itDeepCalls = deepStatementCalls.begin(); itDeepCalls != deepStatementCalls.end(); ++itDeepCalls) calledRoutines.push_back (*itDeepCalls); Debug::getInstance ()->debugMessage ("Appending deep subroutine calls", Debug::OUTER_LOOP_LEVEL, __FILE__, __LINE__); } } else { Debug::getInstance ()->debugMessage ("Appending variable declaration", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); unsigned int OP_DAT_ArgumentGroup = 1; for (SgInitializedNamePtrList::iterator variableIt = isVariableDeclaration->get_variables ().begin (); variableIt != isVariableDeclaration->get_variables ().end (); ++variableIt) { string const variableName = (*variableIt)->get_name ().getString (); SgType * type = (*variableIt)->get_typeptr (); /* * ====================================================== * Specification of "value" attribute is only * for user kernels. Our call convention is that * in all deeper level calls we always pass parameters * by reference (see else branch below) * ====================================================== */ bool isFormalParamater = false; for (SgInitializedNamePtrList::iterator paramIt = originalParameters->get_args ().begin (); paramIt != originalParameters->get_args ().end (); ++paramIt, ++OP_DAT_ArgumentGroup) { string const formalParamterName = (*paramIt)->get_name ().getString (); if (iequals (variableName, formalParamterName)) { isFormalParamater = true; if (parallelLoop->isIndirect (OP_DAT_ArgumentGroup) && parallelLoop->isRead (OP_DAT_ArgumentGroup)) { Debug::getInstance ()->debugMessage ("'" + variableName + "' is an INDIRECT formal parameter which is READ", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); SgVariableDeclaration * variableDeclaration; if ( isUserKernel == true ) variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); else variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); ROSE_ASSERT ( variableDeclaration != NULL ); } else if (parallelLoop->isGlobal (OP_DAT_ArgumentGroup) && parallelLoop->isRead (OP_DAT_ArgumentGroup)) { Debug::getInstance ()->debugMessage ("'" + variableName + "' is a GLOBAL formal parameter which is READ", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); SgVariableDeclaration * variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); } else { Debug::getInstance ()->debugMessage ("'" + variableName + "' is a formal parameter " + parallelLoop->getOpDatInformation (OP_DAT_ArgumentGroup), Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); if ( isUserKernel == true ) SgVariableDeclaration * variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); else SgVariableDeclaration * variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclarationAsFormalParameter ( variableName, type, subroutineScope, formalParameters, 0); } } } if (isFormalParamater == false) { Debug::getInstance ()->debugMessage ("'" + variableName + "' is NOT a formal parameter", Debug::HIGHEST_DEBUG_LEVEL, __FILE__, __LINE__); SgVariableDeclaration * variableDeclaration = FortranStatementsAndExpressionsBuilder::appendVariableDeclaration ( variableName, type, subroutineScope); } } } } }
InterleaveAcrossArraysCheckSynthesizedAttributeType interleaveAcrossArraysCheck::evaluateSynthesizedAttribute ( SgNode* n, SynthesizedAttributesList childAttributes ) { //cout << " Node: " << n->unparseToString() << endl; InterleaveAcrossArraysCheckSynthesizedAttributeType localResult; for (SynthesizedAttributesList::reverse_iterator child = childAttributes.rbegin(); child != childAttributes.rend(); child++) { InterleaveAcrossArraysCheckSynthesizedAttributeType childResult = *child; localResult.isArrayRef |= childResult.isArrayRef; localResult.isFunctionRefExp |= childResult.isFunctionRefExp; } if(isSgVariableDeclaration(n)) { SgVariableDeclaration* varDecl = isSgVariableDeclaration(n); SgInitializedNamePtrList & varList = varDecl->get_variables(); for(SgInitializedNamePtrList::iterator initIter = varList.begin(); initIter!=varList.end() ; initIter++) { SgInitializedName* var = *initIter; ROSE_ASSERT(var!=NULL); SgType *variableType = var->get_type(); ROSE_ASSERT (variableType != NULL); string type = TransformationSupport::getTypeName(variableType); string variableName = var->get_name().str(); //Case 6 if(outputName == variableName) { cout << " ERROR: Substituting Array " << outputName << " already declared in the file." << endl; ROSE_ABORT(); } if(type!="doubleArray" && type !="floatArray" && type!="intArray") return localResult; #if DEBUG cout << " Var Name: " << variableName << " Type: " << type << endl; #endif storeArrayReference(var, variableName, type ); } } else if(isSgPntrArrRefExp(n)) { SgVarRefExp* varRefExp = isSgVarRefExp(isSgPntrArrRefExp(n)->get_lhs_operand()); if(varRefExp != NULL) { SgVariableSymbol* variableSymbol = varRefExp->get_symbol(); ROSE_ASSERT (variableSymbol != NULL); SgInitializedName* initializedName = variableSymbol->get_declaration(); ROSE_ASSERT (initializedName != NULL); string variableName = initializedName->get_name().str(); SgType* type = variableSymbol->get_type(); ROSE_ASSERT (type != NULL); string typeName = TransformationSupport::getTypeName(type); // A++ Supported Arrays if(typeName !="doubleArray" && typeName !="floatArray" && typeName !="intArray") return localResult; // Check if variableName matches the input list if(transformation->containsInput(variableName)) localResult.isArrayRef = true; } } else if(isSgFunctionCallExp(n)) { // Case 1 // Check for array being present in function Call if(localResult.isFunctionRefExp && localResult.isArrayRef) { cout << " ERROR: Array Reference present in a function call " << endl; ROSE_ABORT(); } } else if(isSgFunctionRefExp(n)) { localResult.isFunctionRefExp = true; } else if(isSgStatement(n)) { //Case 2 if(isContigousDecl) { cout << " ERROR: Array Declaration are not contigous. " << endl; ROSE_ABORT(); } } return localResult; }