//Replace the unparsing of expanded macro calls with the actual macro call wherever possible void unparseMacroCalls(SgNode* searchTree) { //Traverse AST to find all macro calls and the nodes they are attached to findPreprocInfo findPre; findPre.traverse(searchTree, preorder); std::vector< std::pair<SgNode*, PreprocessingInfo*> >& wherePreprocIsAttached = findPre.wherePreprocIsAttached; //Replace expanded macro calls with actual macro call from pre-cpp wherever possible for( std::vector< std::pair<SgNode*, PreprocessingInfo*> >::iterator iItr = wherePreprocIsAttached.begin(); iItr != wherePreprocIsAttached.end(); ++iItr) { SgStatement* currentNode = isSgStatement( (*iItr).first ); PreprocessingInfo* curPreproc = (*iItr).second; ROSE_ASSERT(currentNode != NULL); std::vector<SgNode*> matchingSubTree; if ( matchMacroToSubtrees(currentNode->get_scope(), curPreproc, matchingSubTree) ) { for(unsigned int i = 0; i < matchingSubTree.size(); i++) { SgLocatedNode* macroNode = isSgLocatedNode(matchingSubTree[i]); ROSE_ASSERT(macroNode != NULL); std::string replacementString = ( i ==0 ? curPreproc->getString() : "" ); if( isSgExpression(macroNode) == NULL ) { #ifndef USE_ROSE #ifndef ROSE_SKIP_COMPILATION_OF_WAVE // If we are using ROSE to compile ROSE source code then the Wave support is not present. PreprocessingInfo::rose_macro_call* macroCall = curPreproc->get_macro_call(); if(macroCall->expanded_macro.size() > 0 && boost::wave::token_id(macroCall->expanded_macro.back()) != boost::wave::T_COLON) replacementString +=";"; #endif #endif } std::cout << "Doing line replacement " << macroNode->unparseToString() << " with " << replacementString << std::endl; #if 0 std::string pos; curPreproc->display(pos); std::cout << macroNode->class_name() << " "<< pos << std::endl; #endif macroNode->addToAttachedPreprocessingInfo(new PreprocessingInfo(PreprocessingInfo::LineReplacement, replacementString,macroNode->get_file_info()->get_filenameString(),1,1,1,PreprocessingInfo::before)); } }; } };
/** * handling error occured due to failed assertion * this error handler only works during parser phase since it uses * Token_t to know the line number * TODO: we need to make this function more general **/ void fortran_error_handler(int signum) { // get the current filename std::string sFilename = getCurrentFilename(); if (sFilename.size()==0) { fprintf(stderr, "ERROR while parsing the source code\n"); } else { SgScopeStatement* scope = astScopeStack.front(); SgStatement* lastStatement = scope; SgStatementPtrList statementList = scope->generateStatementList(); if (statementList.empty() == false) { lastStatement = statementList.back(); } int lineNumberOfLastStatement = (astScopeStack.empty() == false) ? lastStatement->get_file_info()->get_line() : 0; // get the latest token parsed if (lineNumberOfLastStatement > 0) std::cerr <<"FATAL ERROR in file "<<sFilename<<":"<<lineNumberOfLastStatement<<std::endl; else std::cerr <<"FATAL ERROR while parsing "<<sFilename<<std::endl; } fflush(NULL); // flush all stdio fortran_error_handler_end(); exit(-1); }
/** * Convert for_stmt to a upc_forall statement if it has an affinity exp * in the global map. */ SgStatement* translate_to_upc(SgForStatement* for_stmt) { /* return value is either SgUpcForAllStmt or SgForStmt */ SgStatement* retval; /* translate if the for_stmt was upc_forall stmt */ aff_map_t::iterator affinity_exp_it = aff_exp_map.find(for_stmt); if (affinity_exp_it != aff_exp_map.end()) { /* build a new upc_forall statement */ retval = SageBuilder::buildUpcForAllStatement_nfi( for_stmt->get_for_init_stmt(), /* initialize stmt */ for_stmt->get_test(), /* condition */ for_stmt->get_increment(), /* increment */ affinity_exp_it->second, /* affinity */ for_stmt->get_loop_body() /* loop body */ ); /* set file info */ Sg_File_Info* old_file_info = for_stmt->get_file_info(); retval->set_file_info( old_file_info ); } else { /* for_stmt was never a upc_forall stmt */ retval = for_stmt; } return retval; }
void visitorTraversal::visit(SgNode* n) { // There are three types ir IR nodes that can be queried for scope: // - SgStatement, and // - SgInitializedName SgStatement* statement = isSgStatement(n); if (statement != NULL) { SgScopeStatement* scope = statement->get_scope(); ROSE_ASSERT(scope != NULL); printf ("SgStatement = %12p = %30s has scope = %12p = %s (total number = %d) \n", statement,statement->class_name().c_str(), scope,scope->class_name().c_str(),(int)scope->numberOfNodes()); } SgInitializedName* initializedName = isSgInitializedName(n); if (initializedName != NULL) { SgScopeStatement* scope = initializedName->get_scope(); ROSE_ASSERT(scope != NULL); printf ("SgInitializedName = %12p = %30s has scope = %12p = %s (total number = %d)\n", initializedName,initializedName->get_name().str(), scope,scope->class_name().c_str(),(int)scope->numberOfNodes()); } }
// obtain read or write variables processed by all nested loops, if any void getVariablesProcessedByInnerLoops (SgScopeStatement* current_loop_body, bool isRead, std::set<SgInitializedName*>& var_set) { // AST query to find all loops // add all read/write variables into the var_set VariantVector vv; vv.push_back(V_SgForStatement); vv.push_back(V_SgFortranDo); Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(current_loop_body, vv); for (Rose_STL_Container<SgNode *>::iterator i = nodeList.begin(); i != nodeList.end(); i++) { SgStatement* loop = isSgStatement(*i); if (debug) cout<< "Found nested loop at line:"<< loop->get_file_info()->get_line()<<endl; std::set<SgInitializedName*> src_var_set ; if (isRead) src_var_set = LoopLoadVariables[loop]; else src_var_set = LoopStoreVariables[loop]; std::set<SgInitializedName*>::iterator j; if (debug) cout<< "\t Insert processed variable:"<<endl; for (j= src_var_set.begin(); j!= src_var_set.end(); j++) { var_set.insert(*j); if (debug) cout<< "\t \t "<<(*j)->get_name()<<endl; } } }
//note that we keep mint for pragma as well //#pragma mint for //#pragma omp for void MintCudaMidend::replaceMintForWithOmpFor(SgSourceFile* file) { Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(file, V_SgPragmaDeclaration); Rose_STL_Container<SgNode*>::reverse_iterator nodeListIterator = nodeList.rbegin(); for ( ;nodeListIterator !=nodeList.rend(); ++nodeListIterator) { SgPragmaDeclaration* node = isSgPragmaDeclaration(*nodeListIterator); ROSE_ASSERT(node != NULL); //checks if the syntax is correct and the parallel region is followed by //a basic block if(MintPragmas::isForLoopPragma(node)) { SgStatement* loop = getNextStatement(node); ROSE_ASSERT(loop); if(isSgForStatement(loop)) { removeStatement(loop); SgOmpForStatement* omp_stmt = new SgOmpForStatement(NULL, loop); setOneSourcePositionForTransformation(omp_stmt); loop->set_parent(omp_stmt); insertStatementAfter(node, omp_stmt); } } } }
/* * The function * findScope() * takes as a parameter a SgNode* which is a SgStatement*. It returns a SgNodePtrVector of all * preceding scopes the SgStatement is in. * */ SgNodePtrVector findScopes (SgNode * astNode) { ROSE_ASSERT (isSgStatement (astNode)); SgNodePtrVector returnVector; SgScopeStatement *currentScope; if (isSgScopeStatement (astNode)) { currentScope = isSgScopeStatement (astNode); ROSE_ASSERT (currentScope != NULL); returnVector.push_back (astNode); } else { SgStatement *sageStatement = isSgStatement (astNode); ROSE_ASSERT (sageStatement != NULL); currentScope = sageStatement->get_scope (); ROSE_ASSERT (currentScope != NULL); returnVector.push_back (currentScope); } while (currentScope->variantT () != V_SgGlobal) { currentScope = currentScope->get_scope (); ROSE_ASSERT (currentScope != NULL); returnVector.push_back (currentScope); } //Must also include the Global Scopes of the other files in the project if (currentScope->variantT () == V_SgGlobal) { SgFile *sageFile = isSgFile ((currentScope)->get_parent ()); ROSE_ASSERT (sageFile != NULL); SgProject *sageProject = isSgProject (sageFile->get_parent ()); ROSE_ASSERT (sageProject != NULL); //Get a list of all files in the current project const SgFilePtrList& sageFilePtrList = sageProject->get_fileList (); //Iterate over the list of files to find all Global Scopes SgNodePtrVector globalScopes; for (unsigned int i = 0; i < sageFilePtrList.size (); i += 1) { const SgSourceFile *sageFile = isSgSourceFile (sageFilePtrList[i]); ROSE_ASSERT (sageFile != NULL); SgGlobal *sageGlobal = sageFile->get_globalScope(); ROSE_ASSERT (sageGlobal != NULL); returnVector.push_back (sageGlobal); } } return returnVector; };
SgStatement* returnFirstOrLastStatementFromCurrentFile ( SgStatement* target, const SgStatementPtrList & statementList, bool findFirstStatement ) { // printf ("Inside of returnFirstOrLastStatement \n"); // Find the first statement from the current file being processed SgStatement* statement = NULL; if (findFirstStatement) { SgStatementPtrList::const_iterator statementIterator = statementList.begin(); while (statementIterator != statementList.end()) { statement = *statementIterator; ROSE_ASSERT (statement != NULL); Sg_File_Info* fileInfo = statement->get_file_info(); ROSE_ASSERT (fileInfo != NULL); string filename = fileInfo->get_filename(); if (filename == ROSE::getFileNameByTraversalBackToFileNode(target)) { // printf ("Found the first statement in this file = %s \n",filename.c_str()); // printf ("First statement = %s \n",statement->unparseToCompleteString().c_str()); break; } statementIterator++; } } else { SgStatementPtrList::const_reverse_iterator statementIterator = statementList.rbegin(); while (statementIterator != statementList.rend()) { statement = *statementIterator; ROSE_ASSERT (statement != NULL); Sg_File_Info* fileInfo = statement->get_file_info(); ROSE_ASSERT (fileInfo != NULL); string filename = fileInfo->get_filename(); if (filename == ROSE::getFileNameByTraversalBackToFileNode(target)) { // printf ("Found the last statement in this file = %s \n",filename.c_str()); // printf ("First statement = %s \n",statement->unparseToCompleteString().c_str()); break; } statementIterator++; } } ROSE_ASSERT (statement != NULL); return statement; }
SgStatement *findSafeInsertPoint(SgNode *node) { SgStatement *insertPoint = SageInterface::getEnclosingStatement(node); SgStatement *es = isSgExprStatement(insertPoint); SgStatement *esParent = es ? isSgStatement(es->get_parent()) : 0; if (es && (isSgSwitchStatement(esParent) || isSgIfStmt(esParent))) { // Make sure insertion point is outside of the condition of an if-stmt // or the selector of a switch-stmt. insertPoint = esParent; } else { if (esParent) { assert(isSgBasicBlock(esParent)); } } return insertPoint; }
FrontierDetectionForTokenStreamMapping_InheritedAttribute FrontierDetectionForTokenStreamMapping::evaluateInheritedAttribute(SgNode* n, FrontierDetectionForTokenStreamMapping_InheritedAttribute inheritedAttribute) { static int random_counter = 0; #if 1 // Ignore IR nodes that are front-end specific (declarations of builtin functions, etc.). if (n->get_file_info()->isFrontendSpecific() == false) { printf ("In FrontierDetectionForTokenStreamMapping::evaluateInheritedAttribute(): n = %p = %s \n",n,n->class_name().c_str()); // Count the IR nodes traversed so that we can make a subset transformations. random_counter++; } #endif FrontierDetectionForTokenStreamMapping_InheritedAttribute returnAttribute; SgStatement* statement = isSgStatement(n); // if (statement != NULL && random_counter > 30 && random_counter < 40) if (statement != NULL) { string name = "token_frontier"; string options = "color=\"blue\""; if (random_counter > 30 && random_counter < 40) { printf ("In FrontierDetectionForTokenStreamMapping::evaluateInheritedAttribute(): Mark this statement as a transformation: random_counter = %d statement = %p = %s \n",random_counter,statement,statement->class_name().c_str()); options = "color=\"red\""; returnAttribute.containsFrontier = true; } // AstAttribute::AttributeNodeInfo* attribute = new FrontierDetectionForTokenStreamMappingAttribute ( (SgNode*) n, name, options); AstAttribute* attribute = new FrontierDetectionForTokenStreamMappingAttribute ( (SgNode*) n, name, options); statement->setAttribute(name,attribute); } // return FrontierDetectionForTokenStreamMapping_InheritedAttribute(); return returnAttribute; }
PrefixInheritedAttribute PrefixSuffixGenerationTraversal::evaluateInheritedAttribute ( SgNode* astNode, PrefixInheritedAttribute inputInheritedAttribute ) { #if 0 printf ("!!! In evaluateInheritedAttribute: astNode = %s \n",astNode->sage_class_name()); #endif if ( isSgScopeStatement(astNode) != NULL) { // printf ("Found a new scope! currentScope.size() = %zu \n",currentScope.size()); stackOfScopes.push(currentScope); // empty the current scope stack while (currentScope.empty() == false) currentScope.pop_front(); } SgStatement* currentStatement = isSgStatement(astNode); if ( currentStatement != NULL ) { // printf ("Found a statement! \n"); // string declarationFilename = ROSE::getFileName(currentStatement); string declarationFilename = currentStatement->get_file_info()->get_filename(); string targetFilename = ROSE::getFileNameByTraversalBackToFileNode(currentStatement); // printf ("targetFilename = %s declarationFilename = %s counter = %d (*i)->sage_class_name() = %s \n", // targetFilename.c_str(),declarationFilename.c_str(),counter,(*i)->sage_class_name()); if ( generateIncludeDirectives == false || declarationFilename == targetFilename ) { // printf ("Found a declaration statement! currentScope.size() = %zu \n",currentScope.size()); currentScope.push_front(currentStatement); } } // printf ("Leaving evaluateInheritedAttribute() \n"); return inputInheritedAttribute; }
SgIfStmt * RoseStatementsAndExpressionsBuilder::buildIfStatementWithEmptyElse ( SgExpression * ifGuard, SgScopeStatement * thenBlock) { using namespace SageBuilder; using namespace SageInterface; SgStatement * ifGuardStatement = buildExprStatement (ifGuard); SgIfStmt * ifStatement = new SgIfStmt (ifGuardStatement, thenBlock, NULL); ifStatement->setCaseInsensitive (true); ifStatement->set_use_then_keyword (true); ifStatement->set_has_end_statement (true); setOneSourcePositionForTransformation (ifStatement); ifGuardStatement->set_parent (ifStatement); thenBlock->set_parent (ifStatement); return ifStatement; }
void getIfConds(SgIfStmt* fixIf, SgScopeStatement* parentScope) { SgStatement* conditional = fixIf->get_conditional(); if (isSgExprStatement(conditional)) { SgExpression* expr = isSgExprStatement(conditional)->get_expression(); std::pair<SgVariableDeclaration*, SgExpression*> pr = SageInterface::createTempVariableForExpression(expr,isSgScopeStatement(fixIf),true); SgInitializedNamePtrList lptr = pr.first->get_variables(); //std::cout << "lprt size: " << lptr.size() << std::endl; ROSE_ASSERT(lptr.size() <= 1); SgVarRefExp* varRef = SageBuilder::buildVarRefExp(pr.first); SgIntVal* iv = SageBuilder::buildIntVal(0); SgNotEqualOp* nop = SageBuilder::buildNotEqualOp(isSgExpression(varRef),isSgExpression(iv)); SgExprStatement* ses = SageBuilder::buildExprStatement(isSgExpression(nop)); SageInterface::replaceStatement(conditional,ses); //SageInterface::moveVariableDeclaration(pr.first, parentScope); // SageInterface::appendStatement(pr.first, parentScope); SageInterface::insertStatementBefore(fixIf,pr.first); std::cout << "conditional type: " << conditional->class_name() << std::endl; } return; }
std::map<SgNode*,PreviousAndNextNodeData*> computePreviousAndNextNodes(SgGlobal* globalScope, std::vector<FrontierNode*> frontierNodes) { // This is an alternative way to compute the previous/next node map using the token/AST unparsing frontier list directly. std::map<SgNode*,PreviousAndNextNodeData*> previousAndNextNodeMap; SgStatement* previousNode = globalScope; SgStatement* previousPreviousNode = globalScope; for (size_t j = 0; j < frontierNodes.size(); j++) { // SgStatement* statement = topAttribute.frontierNodes[j]; // ROSE_ASSERT(statement != NULL); FrontierNode* frontierNode = frontierNodes[j]; ROSE_ASSERT(frontierNode != NULL); SgStatement* statement = frontierNode->node; ROSE_ASSERT(statement != NULL); #if 0 printf (" (%p = %s) ",statement,statement->class_name().c_str()); #endif PreviousAndNextNodeData* previousAndNextNodeData = new PreviousAndNextNodeData(previousPreviousNode,statement); #if 0 printf ("Building previousAndNextNodeData = %p previousPreviousNode = %p = %s previousNode = %p = %s statement = %p = %s \n", previousAndNextNodeData,previousPreviousNode,previousPreviousNode->class_name().c_str(), previousNode,previousNode->class_name().c_str(),statement,statement->class_name().c_str()); #endif // Insert a element into the map for the current IR node being traversed. if (previousNode != NULL) { #if 0 printf ("Insert previousAndNextNodeData = %p into previousAndNextNodeMap \n",previousAndNextNodeData); #endif previousAndNextNodeMap.insert(std::pair<SgNode*,PreviousAndNextNodeData*>(previousNode,previousAndNextNodeData)); } else { printf ("WARNING: previousNode == NULL: j = %" PRIuPTR " can't insert entry into previousAndNextNodeMap: statement = %p = %s \n",j,statement,statement->class_name().c_str()); } previousPreviousNode = previousNode; previousNode = statement; } // Handle the last frontier IR node if (frontierNodes.empty() == false) { PreviousAndNextNodeData* previousAndNextNodeData = new PreviousAndNextNodeData(previousPreviousNode,globalScope); // Insert a element into the map for the current IR node being traversed. previousAndNextNodeMap.insert(std::pair<SgNode*,PreviousAndNextNodeData*>(previousNode,previousAndNextNodeData)); } return previousAndNextNodeMap; }
void visitorTraversal::visit(SgNode* n) { SgFile* file = isSgFile(n); if (file != NULL) { filename = file->get_sourceFileNameWithPath(); } // On each statement node and output it's position. SgStatement* statement = isSgStatement(n); bool outputStatement = (statement != NULL) ? true : false; // Check for the statement to exist in the input source file outputStatement = outputStatement && (statement->get_file_info()->get_filenameString() == filename); // Skip SgGlobal IR nodes outputStatement = outputStatement && (isSgGlobal(statement) == NULL); if (outputStatement == true) { AttachedPreprocessingInfoType* comments = statement->getAttachedPreprocessingInfo(); if (comments != NULL) { // printf ("Found attached comments (to IR node at %p of type: %s): \n",statement,statement->class_name().c_str()); // int counter = 0; AttachedPreprocessingInfoType::iterator i; for (i = comments->begin(); i != comments->end(); i++) { #if 0 printf (" Attached Comment #%d in file %s (relativePosition=%s): classification %s :\n%s\n", counter++,(*i)->get_file_info()->get_filenameString().c_str(), ((*i)->getRelativePosition() == PreprocessingInfo::before) ? "before" : "after", PreprocessingInfo::directiveTypeName((*i)->getTypeOfDirective()).c_str(), (*i)->getString().c_str()); #endif // Mark comments and CPP directives a few different colors. int startingLineNumber = (*i)->get_file_info()->get_line(); int startingColumnNumber = (*i)->get_file_info()->get_col(); // Subtract 1 from number of lines to avoid over counting the current line. int endingLineNumber = startingLineNumber + ((*i)->getNumberOfLines() - 1); int endingColumnNumber = (*i)->getColumnNumberOfEndOfString(); string color = directiveTypeColor((*i)->getTypeOfDirective()); #if 0 printf ("%d,%d,%s,%d,%d\n",startingLineNumber,startingColumnNumber,color.c_str(),endingLineNumber,endingColumnNumber); #endif dataFile << startingLineNumber << "," << startingColumnNumber << "," << color << "," << endingLineNumber << "," << endingColumnNumber << endl; } } else { // printf ("No attached comments (at %p of type: %s): \n",statement,statement->sage_class_name()); } ROSE_ASSERT(statement->get_startOfConstruct() != NULL); int startingLineNumber = statement->get_startOfConstruct()->get_line(); int startingColumnNumber = statement->get_startOfConstruct()->get_col(); if (statement->get_endOfConstruct() == NULL) { printf ("Error: statement->get_endOfConstruct() == NULL (statement = %p = %s) \n",statement,statement->class_name().c_str()); } ROSE_ASSERT(statement->get_endOfConstruct() != NULL); int endingLineNumber = statement->get_endOfConstruct()->get_line(); int endingColumnNumber = statement->get_endOfConstruct()->get_col(); // Catch errors (likely compiler generate IR node or NULL file) if (endingLineNumber == 0) { endingLineNumber = startingLineNumber; endingColumnNumber = startingColumnNumber; } #if 0 // Mark all statements blue string color = "blue"; if (isSgScopeStatement(statement) != NULL) color = "red"; #else string color = nodeColor(statement); #endif #if 0 printf ("%d,%d,%s,%d,%d %s = %p \n",startingLineNumber,startingColumnNumber,color.c_str(),endingLineNumber,endingColumnNumber,statement->class_name().c_str(),statement); #endif dataFile << startingLineNumber << "," << startingColumnNumber << "," << color << "," << endingLineNumber << "," << endingColumnNumber << endl; } // On each statement node and output it's position. SgExpression* expression = isSgExpression(n); bool outputExpression = (expression != NULL) ? true : false; // Check for the statement to exist in the input source file outputExpression = outputExpression && (expression->get_file_info()->get_filenameString() == filename); if (outputExpression == true) { // Currently we don't attach comments to expressions (as I recall). AttachedPreprocessingInfoType* comments = expression->getAttachedPreprocessingInfo(); ROSE_ASSERT(comments == NULL); ROSE_ASSERT(expression->get_startOfConstruct() != NULL); int startingLineNumber = expression->get_startOfConstruct()->get_line(); int startingColumnNumber = expression->get_startOfConstruct()->get_col(); // For expressions I would like to be a bit more tollerant of a few mistakes. if (expression->get_endOfConstruct() == NULL) { printf ("Error: expression->get_endOfConstruct() == NULL (expression = %p = %s) \n",expression,expression->class_name().c_str()); } // ROSE_ASSERT(expression->get_endOfConstruct() != NULL); int endingLineNumber = startingLineNumber; int endingColumnNumber = startingColumnNumber; if (expression->get_endOfConstruct() != NULL) { endingLineNumber = expression->get_endOfConstruct()->get_line(); endingColumnNumber = expression->get_endOfConstruct()->get_col(); } // Catch errors (likely compiler generate IR node or NULL file) if (endingLineNumber == 0) { endingLineNumber = startingLineNumber; endingColumnNumber = startingColumnNumber; } string color = nodeColor(expression); #if 0 printf ("%d,%d,%s,%d,%d %s = %p \n",startingLineNumber,startingColumnNumber,color.c_str(),endingLineNumber,endingColumnNumber,expression->class_name().c_str(),expression); #endif dataFile << startingLineNumber << "," << startingColumnNumber << "," << color << "," << endingLineNumber << "," << endingColumnNumber << endl; } // On each statement node and output it's position. SgInitializedName* initializedName = isSgInitializedName(n); bool outputInitializedName = (initializedName != NULL) ? true : false; // Check for the statement to exist in the input source file outputInitializedName = outputInitializedName && (initializedName->get_file_info()->get_filenameString() == filename); if (outputInitializedName == true) { // Currently we don't attach comments to SgInitializedName IR nodes (as I recall). // AttachedPreprocessingInfoType* comments = initializedName->getAttachedPreprocessingInfo(); // ROSE_ASSERT(comments == NULL); ROSE_ASSERT(initializedName->get_startOfConstruct() != NULL); int startingLineNumber = initializedName->get_startOfConstruct()->get_line(); int startingColumnNumber = initializedName->get_startOfConstruct()->get_col(); #if 0 // For SgInitializedName I would like to be a bit more tollerant of a few mistakes. if (initializedName->get_endOfConstruct() == NULL) { printf ("Note: initializedName->get_endOfConstruct() == NULL is OK (initializedName = %p = %s) \n",initializedName,initializedName->class_name().c_str()); } // ROSE_ASSERT(initializedName->get_endOfConstruct() != NULL); #endif int endingLineNumber = startingLineNumber; int endingColumnNumber = startingColumnNumber; if (initializedName->get_endOfConstruct() != NULL) { endingLineNumber = initializedName->get_endOfConstruct()->get_line(); endingColumnNumber = initializedName->get_endOfConstruct()->get_col(); } // Catch errors (likely compiler generate IR node or NULL file) if (endingLineNumber == 0) { endingLineNumber = startingLineNumber; endingColumnNumber = startingColumnNumber; } string color = nodeColor(initializedName); #if 0 // This is redundant I/O for debugging. printf ("%d,%d,%s,%d,%d %s = %p \n",startingLineNumber,startingColumnNumber,color.c_str(),endingLineNumber,endingColumnNumber,initializedName->class_name().c_str(),initializedName); #endif dataFile << startingLineNumber << "," << startingColumnNumber << "," << color << "," << endingLineNumber << "," << endingColumnNumber << endl; } }
void generateStencilCode(StencilEvaluationTraversal & traversal, bool generateLowlevelCode) { // Read the stencil and generate the inner most loop AST for the stencil. // Note that generateLowlevelCode controls the generation of low level C code using a // base pointer to raw memory and linearized indexing off of that pointer. The // alternative is to use the operator[] member function in the RectMDArray class. // Example of code that we want to generate: // for (j=0; j < source.size(0); j++) // { // int axis_x_size = source.size(0); // for (i=0; i < source.size(0); i++) // { // destination[j*axis_x_size+i] = source[j*axis_x_size+i]; // } // } // This function genertes the loop nest only: // SgForStatement* buildLoopNest(int stencilDimension, SgBasicBlock* & innerLoopBody) // This function generates the statement in the inner most loop body: // SgExprStatement* assembleStencilSubTreeArray(vector<SgExpression*> & stencilSubTreeArray) // This function generates the AST representing the stencil points: // SgExpression* buildStencilPoint (StencilOffsetFSM* stencilOffsetFSM, double stencilCoeficient, int stencilDimension, SgVariableSymbol* destinationVariableSymbol, SgVariableSymbol* sourceVariableSymbol) // The generated code should be in terms of the operator[]() functions on the // RectMDArray objects. Likely we have to support a wider range of generated code later. // const RectMDArray<TDest>& a_LOfPhi, // const RectMDArray<TSrc>& a_phi, // std::vector<SgFunctionCallExp*> stencilOperatorFunctionCallList; std::vector<SgFunctionCallExp*> stencilOperatorFunctionCallList = traversal.get_stencilOperatorFunctionCallList(); for (size_t i = 0; i < stencilOperatorFunctionCallList.size(); i++) { SgFunctionCallExp* functionCallExp = stencilOperatorFunctionCallList[i]; ROSE_ASSERT(functionCallExp != NULL); printf ("processing functionCallExp = %p \n",functionCallExp); SgStatement* associatedStatement = TransformationSupport::getStatement(functionCallExp); ROSE_ASSERT(associatedStatement != NULL); string filename = associatedStatement->get_file_info()->get_filename(); int lineNumber = associatedStatement->get_file_info()->get_line(); printf ("Generating code for stencil operator used at file = %s at line = %d \n",filename.c_str(),lineNumber); SgExprListExp* argumentList = functionCallExp->get_args(); ROSE_ASSERT(argumentList != NULL); // There should be four elements to a stencil operator. ROSE_ASSERT(argumentList->get_expressions().size() == 4); // Stencil SgExpression* stencilExpression = argumentList->get_expressions()[0]; SgVarRefExp* stencilVarRefExp = isSgVarRefExp(stencilExpression); ROSE_ASSERT(stencilVarRefExp != NULL); // RectMDArray (destination) SgExpression* destinationArrayReferenceExpression = argumentList->get_expressions()[1]; SgVarRefExp* destinationArrayVarRefExp = isSgVarRefExp(destinationArrayReferenceExpression); ROSE_ASSERT(destinationArrayVarRefExp != NULL); // RectMDArray (source) SgExpression* sourceArrayReferenceExpression = argumentList->get_expressions()[2]; SgVarRefExp* sourceArrayVarRefExp = isSgVarRefExp(sourceArrayReferenceExpression); ROSE_ASSERT(sourceArrayVarRefExp != NULL); // Box SgExpression* boxReferenceExpression = argumentList->get_expressions()[3]; SgVarRefExp* boxVarRefExp = isSgVarRefExp(boxReferenceExpression); ROSE_ASSERT(boxVarRefExp != NULL); printf ("DONE: processing inputs to stencil operator \n"); ROSE_ASSERT(stencilVarRefExp->get_symbol() != NULL); SgInitializedName* stencilInitializedName = stencilVarRefExp->get_symbol()->get_declaration(); ROSE_ASSERT(stencilInitializedName != NULL); string stencilName = stencilInitializedName->get_name(); printf ("stencilName = %s \n",stencilName.c_str()); std::map<std::string,StencilFSM*> & stencilMap = traversal.get_stencilMap(); ROSE_ASSERT(stencilMap.find(stencilName) != stencilMap.end()); StencilFSM* stencilFSM = stencilMap[stencilName]; ROSE_ASSERT(stencilFSM != NULL); // DQ (2/8/2015): Moved out of loop. int stencilDimension = stencilFSM->stencilDimension(); ROSE_ASSERT(stencilDimension > 0); // These are computed values. printf ("Stencil dimension = %d \n",stencilDimension); printf ("Stencil width = %d \n",stencilFSM->stencilWidth()); std::vector<std::pair<StencilOffsetFSM,double> > & stencilPointList = stencilFSM->stencilPointList; // This is the scope where the stencil operator is evaluated. SgScopeStatement* outerScope = associatedStatement->get_scope(); ROSE_ASSERT(outerScope != NULL); SgVariableSymbol* indexVariableSymbol_X = NULL; SgVariableSymbol* indexVariableSymbol_Y = NULL; SgVariableSymbol* indexVariableSymbol_Z = NULL; SgVariableSymbol* arraySizeVariableSymbol_X = NULL; SgVariableSymbol* arraySizeVariableSymbol_Y = NULL; SgVariableSymbol* destinationVariableSymbol = destinationArrayVarRefExp->get_symbol(); ROSE_ASSERT(destinationVariableSymbol != NULL); SgVariableSymbol* sourceVariableSymbol = sourceArrayVarRefExp->get_symbol(); ROSE_ASSERT(sourceVariableSymbol != NULL); SgVariableSymbol* boxVariableSymbol = boxVarRefExp->get_symbol(); ROSE_ASSERT(boxVariableSymbol != NULL); // This can be important in handling of comments and CPP directives. bool autoMovePreprocessingInfo = true; SgStatement* lastStatement = associatedStatement; if (generateLowlevelCode == true) { #if 1 SgVariableDeclaration* sourceDataPointerVariableDeclaration = buildDataPointer("sourceDataPointer",sourceVariableSymbol,outerScope); #else // Optionally build a pointer variable so that we can optionally support a C style indexing for the DTEC DSL blocks. SgExpression* sourcePointerExp = buildMemberFunctionCall(sourceVariableSymbol,"getPointer",NULL,false); ROSE_ASSERT(sourcePointerExp != NULL); SgAssignInitializer* assignInitializer = SageBuilder::buildAssignInitializer_nfi(sourcePointerExp); ROSE_ASSERT(assignInitializer != NULL); // Build the variable declaration for the pointer to the data. string sourcePointerName = "sourceDataPointer"; SgVariableDeclaration* sourceDataPointerVariableDeclaration = SageBuilder::buildVariableDeclaration_nfi(sourcePointerName,SageBuilder::buildPointerType(SageBuilder::buildDoubleType()),assignInitializer,outerScope); ROSE_ASSERT(sourceDataPointerVariableDeclaration != NULL); #endif // SageInterface::insertStatementAfter(associatedStatement,forStatementScope,autoMovePreprocessingInfo); SageInterface::insertStatementAfter(associatedStatement,sourceDataPointerVariableDeclaration,autoMovePreprocessingInfo); SgVariableDeclaration* destinationDataPointerVariableDeclaration = buildDataPointer("destinationDataPointer",destinationVariableSymbol,outerScope); SageInterface::insertStatementAfter(sourceDataPointerVariableDeclaration,destinationDataPointerVariableDeclaration,autoMovePreprocessingInfo); // Reset the variable symbols we will use in the buildStencilPoint() function. sourceVariableSymbol = SageInterface::getFirstVarSym(sourceDataPointerVariableDeclaration); destinationVariableSymbol = SageInterface::getFirstVarSym(destinationDataPointerVariableDeclaration); lastStatement = destinationDataPointerVariableDeclaration; } SgBasicBlock* innerLoopBody = NULL; // SgForStatement* loopNest = buildLoopNest(stencilFSM->stencilDimension(),innerLoopBody,sourceVariableSymbol,indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y); SgForStatement* loopNest = buildLoopNest(stencilFSM->stencilDimension(),innerLoopBody,boxVariableSymbol,indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y); ROSE_ASSERT(innerLoopBody != NULL); ROSE_ASSERT(lastStatement != NULL); SageInterface::insertStatementAfter(lastStatement,loopNest,autoMovePreprocessingInfo); // Mark this as compiler generated so that it will not be unparsed. associatedStatement->get_file_info()->setCompilerGenerated(); // Form an array of AST subtrees to represent the different points in the stencil. // vector<SgFunctionCallExp*> stencilSubTreeArray; vector<SgExpression*> stencilSubTreeArray; for (size_t j = 0; j < stencilPointList.size(); j++) { #if 0 printf ("Forming stencil point subtree for offsetValues[0] = %3d [1] = %3d [2] = %3d \n",stencilPointList[j].first.offsetValues[0],stencilPointList[j].first.offsetValues[1],stencilPointList[j].first.offsetValues[2]); #endif StencilOffsetFSM* stencilOffsetFSM = &(stencilPointList[j].first); double stencilCoeficient = stencilPointList[j].second; // SgFunctionCallExp* stencilSubTree = buildStencilPoint(stencilOffsetFSM,stencilCoeficient,stencilFSM->stencilDimension()); SgExpression* stencilSubTree = buildStencilPoint(stencilOffsetFSM,stencilCoeficient,stencilDimension,sourceVariableSymbol, indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y,generateLowlevelCode); ROSE_ASSERT(stencilSubTree != NULL); stencilSubTreeArray.push_back(stencilSubTree); } // Construct the lhs value for the stencil inner loop statement. StencilOffsetFSM* stencilOffsetFSM_lhs = new StencilOffsetFSM(0,0,0); double stencilCoeficient_lhs = 1.00; SgExpression* stencil_lhs = buildStencilPoint(stencilOffsetFSM_lhs,stencilCoeficient_lhs,stencilDimension,destinationVariableSymbol, indexVariableSymbol_X,indexVariableSymbol_Y,indexVariableSymbol_Z,arraySizeVariableSymbol_X,arraySizeVariableSymbol_Y,generateLowlevelCode); ROSE_ASSERT(stencil_lhs != NULL); // Assemble the stencilSubTreeArray into a single expression. SgExprStatement* stencilStatement = assembleStencilSubTreeArray(stencil_lhs,stencilSubTreeArray,stencilDimension,destinationVariableSymbol); SageInterface::appendStatement(stencilStatement,innerLoopBody); } }
in_list objectsAllocated(SgStatement *statement, StopCond stopCond) { in_list objs; SgStatement *parent; do { #if 0 in_list::iterator startOfCurrent = objs.end(); #endif parent = isSgStatement(statement->get_parent()); //cout << "parent = " << parent << endl; ROSE_ASSERT(parent); in_list blockObjs = blockObjectsAllocated(parent, statement); objs.insert(objs.end(), blockObjs.begin(), blockObjs.end()); #if 0 switch (parent->variantT()) { case V_SgBasicBlock: { SgBasicBlock *b = isSgBasicBlock(parent); ROSE_ASSERT(b); SgStatementPtrList &stmts = b->get_statements(); for (SgStatementPtrList::iterator i = stmts.begin(); i != stmts.end(); ++i) { if (*i == statement) break; addStmtVarsIfAny(objs, startOfCurrent, *i); } } break; case V_SgForStatement: { SgForStatement *fs = isSgForStatement(parent); SgStatementPtrList &stmts = fs->get_init_stmt(); bool done = false; if (!omitInit) { for (SgStatementPtrList::iterator i = stmts.begin(); i != stmts.end(); ++i) { if (*i == statement) { done = true; break; } addStmtVarsIfAny(objs, startOfCurrent, *i); } } if (!done) { if (fs->get_test() != statement) { addStmtVarsIfAny(objs, startOfCurrent, fs->get_test()); } } } break; default: break; } #endif statement = parent; } while (!stopCond(parent)); return objs; }
void FunctionCallNormalization::visit( SgNode *astNode ) { SgStatement *stm = isSgStatement( astNode ); // visiting all statements which may contain function calls; // Note 1: we do not look at the body of loops, or sequences of statements, but only // at statements which may contain directly function calls; all other statements will have their component parts visited in turn if ( isSgEnumDeclaration( astNode ) || isSgVariableDeclaration( astNode ) || isSgVariableDefinition( astNode ) || isSgExprStatement( astNode ) || isSgForStatement( astNode ) || isSgReturnStmt( astNode ) || isSgSwitchStatement( astNode ) ) { // maintain the mappings from function calls to expressions (variables or dereferenced variables) map<SgFunctionCallExp *, SgExpression *> fct2Var; // list of Declaration structures, one structure per function call DeclarationPtrList declarations; bool variablesDefined = false; // list of function calls, in correnspondence with the inForTest list below list<SgNode*> functionCallExpList; list<bool> inForTest; SgForStatement *forStm = isSgForStatement( stm ); SgSwitchStatement *swStm = isSgSwitchStatement( stm ); list<SgNode*> temp1, temp2; // for-loops and Switch statements have conditions ( and increment ) expressed as expressions // and not as standalone statements; this will change in future Sage versions // TODO: when for-loops and switch statements have conditions expressed via SgStatements // these cases won't be treated separately; however, do-while will have condition expressed via expression // so that will be the only exceptional case to be treated separately if (forStm != NULL) { // create a list of function calls in the condition and increment expression // the order is important, the condition is evaluated after the increment expression // temp1 = FEOQueryForNodes( forStm->get_increment_expr_root(), V_SgFunctionCallExp ); // temp2 = FEOQueryForNodes( forStm->get_test_expr_root(), V_SgFunctionCallExp ); temp1 = FEOQueryForNodes( forStm->get_increment(), V_SgFunctionCallExp ); temp2 = FEOQueryForNodes( forStm->get_test_expr(), V_SgFunctionCallExp ); functionCallExpList = temp1; functionCallExpList.splice( functionCallExpList.end(), temp2 ); } else { if (swStm != NULL) { // create a list of function calls in the condition in the order of function evaluation // DQ (11/23/2005): Fixed SgSwitchStmt to have SgStatement for conditional. // list<SgNode*> temp1 = FEOQueryForNodes( swStm->get_item_selector_root(), V_SgFunctionCallExp ); list<SgNode*> temp1 = FEOQueryForNodes( swStm->get_item_selector(), V_SgFunctionCallExp ); functionCallExpList = temp1; } else { // create a list of function calls in the statement in the order of function evaluation functionCallExpList = FEOQueryForNodes( stm, V_SgFunctionCallExp ); } } // all function calls get replaced: this is because they can occur in expressions (e.g. for-loops) // which makes it difficult to build control flow graphs if ( functionCallExpList.size() > 0 ) { cout << "--------------------------------------\nStatement "; cout << stm->unparseToString() << "\n";; // traverse the list of function calls in the current statement, generate a structure Declaration for each call // put these structures in a list to be inserted in the code later for ( list<SgNode *>::iterator i = functionCallExpList.begin(); i != functionCallExpList.end(); i++ ) { variablesDefined = true; // get function call exp SgFunctionCallExp *exp = isSgFunctionCallExp( *i ); ROSE_ASSERT ( exp ); // get type of expression, generate unique variable name SgType *expType = exp->get_type(); ROSE_ASSERT ( expType ); Sg_File_Info *location = Sg_File_Info::generateDefaultFileInfoForTransformationNode(); ROSE_ASSERT ( location ); ostringstream os; os << "__tempVar__" << location; SgName name = os.str().c_str(); // replace previous variable bindings in the AST SgExprListExp *paramsList = exp->get_args(); SgExpression *function = exp->get_function(); ROSE_ASSERT ( paramsList && function ); replaceFunctionCallsInExpression( paramsList, fct2Var ); replaceFunctionCallsInExpression( function, fct2Var ); // duplicate function call expression, for the initialization declaration and the assignment SgTreeCopy treeCopy; SgFunctionCallExp *newExpInit = isSgFunctionCallExp( exp->copy( treeCopy ) ); ROSE_ASSERT ( newExpInit ); SgFunctionCallExp *newExpAssign = isSgFunctionCallExp( exp->copy( treeCopy ) ); ROSE_ASSERT ( newExpAssign ); // variables Sg_File_Info *initLoc = Sg_File_Info::generateDefaultFileInfoForTransformationNode(), *nonInitLoc = Sg_File_Info::generateDefaultFileInfoForTransformationNode(), *assignLoc = Sg_File_Info::generateDefaultFileInfoForTransformationNode(); Declaration *newDecl = new Declaration(); SgStatement *nonInitVarDeclaration, *initVarDeclaration, *assignStmt; SgExpression *varRefExp; SgVariableSymbol *varSymbol; SgAssignOp *assignOp; SgInitializedName *initName; bool pointerTypeNeeded = false; // mark whether to replace inside or outside of ForStatement due to the // function call being inside the test or the increment for a for-loop statement // the 'inForTest' list is in 1:1 ordered correpondence with the 'declarations' list if ( forStm ) { // SgExpressionRoot // *testExp = isSgForStatement( astNode )->get_test_expr_root(), // *incrExp = isSgForStatement( astNode )->get_increment_expr_root(); SgExpression *testExp = isSgForStatement( astNode )->get_test_expr(), *incrExp = isSgForStatement( astNode )->get_increment(); SgNode *up = exp; while ( up && up != testExp && up != incrExp ) up = up->get_parent(); ROSE_ASSERT ( up ); // function call is in the condition of the for-loop if ( up == testExp ) inForTest.push_back( true ); // function call is in the increment expression else { inForTest.push_back( false ); // for increment expressions we need to be able to reassign the return value // of the function; if the ret value is a reference, we need to generate a // pointer of that type (to be able to reassign it later) if ( isSgReferenceType( expType ) ) pointerTypeNeeded = true; } } // for do-while statements: we need to generate declaration of type pointer to be able to have // non-assigned references when looping and assign them at the end of the body of the loop if ( isSgDoWhileStmt( stm->get_parent() ) && isSgReferenceType( expType ) ) pointerTypeNeeded = true; // we have a function call returning a reference and we can't initialize the variable // at the point of declaration; we need to define the variable as a pointer if ( pointerTypeNeeded ) { // create 'address of' term for function expression, so we can assign it to the pointer SgAddressOfOp *addressOp = new SgAddressOfOp( assignLoc, newExpAssign, expType ); // create noninitialized declaration SgType *base = isSgReferenceType( expType )->get_base_type(); ROSE_ASSERT( base ); SgPointerType *ptrType = SgPointerType::createType( isSgReferenceType( expType )->get_base_type() ); ROSE_ASSERT ( ptrType ); nonInitVarDeclaration = new SgVariableDeclaration ( nonInitLoc, name, ptrType ); // create assignment (symbol, varRefExp, assignment) initName = isSgVariableDeclaration( nonInitVarDeclaration )->get_decl_item( name ); ROSE_ASSERT ( initName ); varSymbol = new SgVariableSymbol( initName ); ROSE_ASSERT ( varSymbol ); varRefExp = new SgVarRefExp( assignLoc, varSymbol ); SgPointerDerefExp *ptrDeref= new SgPointerDerefExp( assignLoc, varRefExp, expType ); ROSE_ASSERT ( isSgExpression( varRefExp ) && ptrDeref ); assignOp = new SgAssignOp( assignLoc, varRefExp, addressOp, ptrType ); assignStmt = new SgExprStatement( assignLoc, assignOp ); ROSE_ASSERT ( assignStmt && nonInitVarDeclaration ); // we don't need initialized declarations in this case initVarDeclaration = NULL; // save new mapping fct2Var.insert( Fct2Var( exp, ptrDeref ) ); } else { // create (non- &)initialized declarations, initialized name & symbol SgAssignInitializer *declInit = new SgAssignInitializer( initLoc, newExpInit, expType ); ROSE_ASSERT ( declInit ); initVarDeclaration = new SgVariableDeclaration ( initLoc, name, expType, declInit ); nonInitVarDeclaration = new SgVariableDeclaration ( nonInitLoc, name, expType ); ROSE_ASSERT ( initVarDeclaration && nonInitVarDeclaration ); initName = isSgVariableDeclaration( nonInitVarDeclaration )->get_decl_item( name ); ROSE_ASSERT ( initName ); newExpInit->set_parent( initName ); varSymbol = new SgVariableSymbol( initName ); ROSE_ASSERT ( varSymbol ); // create variable ref exp varRefExp = new SgVarRefExp( assignLoc, varSymbol ); ROSE_ASSERT ( isSgVarRefExp( varRefExp ) ); // create the assignment assignOp = new SgAssignOp( assignLoc, varRefExp, newExpAssign, expType ); assignStmt = new SgExprStatement( assignLoc, assignOp ); ROSE_ASSERT ( assignStmt ); initVarDeclaration->set_parent( stm->get_parent() ); isSgVariableDeclaration( initVarDeclaration )->set_definingDeclaration( isSgDeclarationStatement( initVarDeclaration ) ); // save new mapping fct2Var.insert( Fct2Var( exp, varRefExp ) ); } // save the 'declaration' structure, with all 3 statements and the variable name newDecl->nonInitVarDeclaration = nonInitVarDeclaration; newDecl->initVarDeclaration = initVarDeclaration; newDecl->assignment = assignStmt; newDecl->name = name; nonInitVarDeclaration->set_parent( stm->get_parent() ); isSgVariableDeclaration( nonInitVarDeclaration )->set_definingDeclaration( isSgVariableDeclaration( nonInitVarDeclaration ) ); assignStmt->set_parent( stm->get_parent() ); declarations.push_back( newDecl ); } // end for } // end if fct calls in crt stmt > 1 SgScopeStatement *scope = stm->get_scope(); ROSE_ASSERT ( scope ); // insert function bindings to variables; each 'declaration' structure in the list // corresponds to one function call for ( DeclarationPtrList::iterator i = declarations.begin(); i != declarations.end(); i++ ) { Declaration *d = *i; ROSE_ASSERT ( d && d->assignment && d->nonInitVarDeclaration ); // if the current statement is a for-loop, we insert Declarations before & in the loop body, depending on the case if ( forStm ) { SgStatement *parentScope = isSgStatement( stm->get_scope() ); SgBasicBlock *body = SageInterface::ensureBasicBlockAsBodyOfFor(forStm); ROSE_ASSERT ( !inForTest.empty() && body && parentScope ); // SgStatementPtrList &list = body->get_statements(); // if function call is in loop condition, we add initialized variable before the loop and at its end // hoist initialized variable declarations outside the loop if ( inForTest.front() ) { ROSE_ASSERT ( d->initVarDeclaration ); parentScope->insert_statement( stm, d->initVarDeclaration ); // set the scope of the initializedName SgInitializedName *initName = isSgVariableDeclaration( d->initVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( isSgScopeStatement( parentScope ) ); ROSE_ASSERT ( initName->get_scope() ); } // function call is in loop post increment so add noninitialized variable decls above the loop else { parentScope->insert_statement( stm, d->nonInitVarDeclaration ); // set the scope of the initializedName SgInitializedName *initName = isSgVariableDeclaration( d->nonInitVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( isSgScopeStatement( parentScope ) ); ROSE_ASSERT ( initName->get_scope() ); } // in a for-loop, always insert assignments at the end of the loop body->get_statements().push_back( d->assignment ); d->assignment->set_parent( body ); // remove marker inForTest.pop_front(); } else { // look at the type of the enclosing scope switch ( scope->variantT() ) { // while stmts have to repeat the function calls at the end of the loop; // note there is no "break" statement, since we want to also add initialized // declarations before the while-loop case V_SgWhileStmt: { // assignments need to be inserted at the end of each while loop SgBasicBlock *body = SageInterface::ensureBasicBlockAsBodyOfWhile(isSgWhileStmt( scope ) ); ROSE_ASSERT ( body ); d->assignment->set_parent( body ); body->get_statements().push_back( d->assignment ); } // SgForInitStatement has scope SgForStatement, move declarations before the for loop; // same thing if the enclosing scope is an If, or Switch statement case V_SgForStatement: case V_SgIfStmt: case V_SgSwitchStatement: { // adding bindings (initialized variable declarations only, not assignments) // outside the statement, in the parent scope SgStatement *parentScope = isSgStatement( scope->get_parent() ); ROSE_ASSERT ( parentScope ); parentScope->insert_statement( scope, d->initVarDeclaration, true );\ // setting the scope of the initializedName SgInitializedName *initName = isSgVariableDeclaration( d->initVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( scope->get_scope() ); ROSE_ASSERT ( initName->get_scope() ); } break; // do-while needs noninitialized declarations before the loop, with assignments inside the loop case V_SgDoWhileStmt: { // adding noninitialized variable declarations before the body of the loop SgStatement *parentScope = isSgStatement( scope->get_parent() ); ROSE_ASSERT ( parentScope ); parentScope->insert_statement( scope, d->nonInitVarDeclaration, true ); // initialized name scope setting SgInitializedName *initName = isSgVariableDeclaration( d->nonInitVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( scope->get_scope() ); ROSE_ASSERT ( initName->get_scope() ); // adding assignemts at the end of the do-while loop SgBasicBlock *body = SageInterface::ensureBasicBlockAsBodyOfDoWhile( isSgDoWhileStmt(scope) ); ROSE_ASSERT ( body ); body->get_statements().push_back( d->assignment ); d->assignment->set_parent(body); } break; // for all other scopes, add bindings ( initialized declarations ) before the statement, in the same scope default: scope->insert_statement( stm, d->initVarDeclaration, true ); // initialized name scope setting SgInitializedName *initName = isSgVariableDeclaration( d->initVarDeclaration )->get_decl_item( d->name ); ROSE_ASSERT ( initName ); initName->set_scope( scope->get_scope() ); ROSE_ASSERT ( initName->get_scope() ); } } } // once we have inserted all variable declarations, we need to replace top-level calls in the original statement if ( variablesDefined ) { cout << "\tReplacing in the expression " << stm->unparseToString() << "\n"; // for ForStatements, replace expressions in condition and increment expressions, // not in the body, since those get replace later if ( forStm ) { // SgExpressionRoot *testExp = forStm->get_test_expr_root(), *incrExp = forStm->get_increment_expr_root(); SgExpression *testExp = forStm->get_test_expr(), *incrExp = forStm->get_increment(); replaceFunctionCallsInExpression( incrExp, fct2Var ); replaceFunctionCallsInExpression( testExp, fct2Var ); } else if ( swStm ) { // DQ (11/23/2005): Fixed SgSwitch to permit use of declaration for conditional // replaceFunctionCallsInExpression( swStm->get_item_selector_root(), fct2Var ); replaceFunctionCallsInExpression( swStm->get_item_selector(), fct2Var ); } else replaceFunctionCallsInExpression( stm, fct2Var ); } } // end if isSgStatement block }
void visitorTraversal::visit(SgNode* n) { SgStatement* statement = isSgStatement(n); if (statement != NULL) { string filename = statement->get_file_info()->get_filename(); // CH (2/1/2010): Get the real filename (not a symlink) if(boost::filesystem::exists(filename)) filename = realpath(filename.c_str(), NULL); // Skip the case of compiler generated Sg_File_Info objects. //if (previousFilename != filename && filename != "compilerGenerated") if (previousFilenames.count(filename) == 0 && filename != "compilerGenerated") { #if 0 // DQ (1/30/2010): Skip the display of output (too much for testing). printf ("\n\nfilename = %s statement = %s \n",filename.c_str(),n->class_name().c_str()); #endif FileNameClassification classification; #if 1 // string sourceDir = "/home/dquinlan/ROSE/roseCompileTree-g++4.2.2/developersScratchSpace/Dan/fileLocation_tests"; // This causes the path edit distance to be: 4 //string sourceDir = "/home/dquinlan/ROSE/svn-rose"; //string sourceDir = "/home/hou1/rose"; string sourceDir = "/"; map<string, string> libs; libs["/home/hou1/opt/rose"] = "MyRose"; libs["/home/hou1/opt/boost"] = "MyBoost"; // This causes the path edit distance to be: 0 //string sourceDir = "/home/dquinlan/ROSE"; classification = classifyFileName(filename,sourceDir,libs); #else string home = "/home/dquinlan/"; string sourceDir = home + "ROSE/svn-rose/"; classification = classifyFileName("/usr/include/stdio.h",sourceDir); #endif FileNameLocation fileTypeClassification = classification.getLocation(); FileNameLibrary libraryClassification = classification.getLibrary(); //int pathEditDistance = classification.getDistanceFromSourceDirectory(); #if 1 if (fileTypeClassification == FILENAME_LOCATION_UNKNOWN) { cerr << "filename: " << filename << " is classified as UNKNOWN!!!" << endl; ROSE_ASSERT(false); //exit(0); } else { cout << "filename: " << filename << " " << getName(fileTypeClassification) << " " << libraryClassification << endl; } #endif #if 0 // DQ (1/30/2010): Skip the display of output (too much for testing). printf ("\n\nfilename: %s\n", filename.c_str()); printf ("fileTypeClassification = %d \n",fileTypeClassification); display(fileTypeClassification,"Display fileTypeClassification"); printf ("libraryClassification = %s \n",libraryClassification.c_str()); //display(libraryClassification,"Display libraryClassification"); printf ("pathEditDistance = %d \n",pathEditDistance); #endif #if 1 // DQ (1/30/2010): Skip the display of output (too much for testing). // Some of our tests explicitly build a link and this tests that it is correctly identified as a link. // printf ("isLink(StringUtility::stripPathFromFileName(filename)) = %s \n",isLink(StringUtility::stripPathFromFileName(filename)) ? "true" : "false"); // ROSE_ASSERT(isLink(filename) == false); //bool lk = isLink(filename); //printf ("isLink(filename) = %s \n",lk ? "true" : "false"); // DQ (1/30/2010): Added this test. // ROSE_ASSERT(islinkOrPartOfLinkedDirectory(filename) == false); // printf ("islinkOrPartOfLinkedDirectory(filename) = %s \n",islinkOrPartOfLinkedDirectory(filename) ? "true" : "false"); #endif previousFilenames.insert(filename); } //previousFilename = filename; } }
void FixupSelfReferentialMacrosInAST::visit ( SgNode* node ) { // DQ (3/11/2006): Set NULL pointers where we would like to have none. // printf ("In FixupSelfReferentialMacrosInAST::visit(): node = %s \n",node->class_name().c_str()); ROSE_ASSERT(node != NULL); switch (node->variantT()) { case V_SgInitializedName: { SgInitializedName* initializedName = isSgInitializedName(node); ROSE_ASSERT(initializedName != NULL); SgType* type = initializedName->get_type()->stripType(); SgClassType* classType = isSgClassType(type); if (classType != NULL) { SgClassDeclaration* targetClassDeclaration = isSgClassDeclaration(classType->get_declaration()); SgName className = targetClassDeclaration->get_name(); // printf ("In FixupSelfReferentialMacrosInAST::visit(): Found a class declaration name = %s \n",className.str()); if (className == "sigaction") { // printf ("In FixupSelfReferentialMacrosInAST::visit(): Found a sigaction type \n"); // Note we could also check that the declaration came from a known header file. SgStatement* associatedStatement = isSgStatement(initializedName->get_parent()); if (associatedStatement != NULL) { // Add a macro to undefine the "#define sa_handler __sigaction_handler.sa_handler" macro. // printf ("In FixupSelfReferentialMacrosInAST::visit(): Add a macro to undefine the macro #define sa_handler __sigaction_handler.sa_handler \n"); // PreprocessingInfo* macro = new PreprocessingInfo(DirectiveType, const std::string & inputString,const std::string & filenameString, int line_no , int col_no,int nol, RelativePositionType relPos ); PreprocessingInfo::DirectiveType directiveType = PreprocessingInfo::CpreprocessorUndefDeclaration; std::string macroString = "#undef sa_handler\n"; std::string filenameString = "macro_call_fixupSelfReferentialMacrosInAST"; int line_no = 1; int col_no = 1; int nol = 1; PreprocessingInfo::RelativePositionType relPos = PreprocessingInfo::before; PreprocessingInfo* macro = new PreprocessingInfo(directiveType,macroString,filenameString,line_no,col_no,nol,relPos); // printf ("Attaching CPP directive %s to IR node %p as attributes. \n",PreprocessingInfo::directiveTypeName(macro->getTypeOfDirective()).c_str(),associatedStatement); associatedStatement->addToAttachedPreprocessingInfo(macro); #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } } } } default: { // printf ("Not handled in FixupSelfReferentialMacrosInAST::visit(%s) \n",node->class_name().c_str()); } } }
void BasicProgmemTransform::insertPreprocessingInfo(const std::string &data) { SgGlobal *global = SageInterface::getFirstGlobalScope(project); SgStatement *firstDecl = SageInterface::getFirstStatement(global); PreprocessingInfo* result = new PreprocessingInfo(PreprocessingInfo::CpreprocessorIncludeDeclaration, data, "Transformation generated",0, 0, 0, PreprocessingInfo::before); firstDecl->addToAttachedPreprocessingInfo(result, PreprocessingInfo::after); }
DetectMacroExpansionsToBeUnparsedAsAstTransformationsSynthesizedAttribute DetectMacroExpansionsToBeUnparsedAsAstTransformations::evaluateSynthesizedAttribute ( SgNode* n, DetectMacroExpansionsToBeUnparsedAsAstTransformationsInheritedAttribute inheritedAttribute, SubTreeSynthesizedAttributes synthesizedAttributeList ) { DetectMacroExpansionsToBeUnparsedAsAstTransformationsSynthesizedAttribute returnAttribute(n); #if 0 printf ("In (Detect Transformations in Macro Expansions) evaluateSynthesizedAttribute(): n = %s n->get_containsTransformation() = %s \n",n->class_name().c_str(),n->get_containsTransformation() ? "true" : "false"); #endif // DQ (11/8/2015): This has to be moved to after the tokenStreamSequenceMap has been setup since we need that to determine if // IR nodes have a token mapping or not (subparts of macros expansions will not and we need this infor to recognize parts of // the AST that are associated with macro expansions. // DQ (11/8/2015): If this has been marked as containing a transformation then check if there is token info for each of the children. // If there is not token info for each of the children then this currentStatement (e.g. n) must be marked as a transformation. // This case happens when a transformation is done to a child of a statement that is part of a macro. In this case the parent will // have token information which is the macro call, but since there is a transformation, we have to unparse the fully expanded form // of the macro (from the AST), so the whole subtree must be unparsed. NOTE: this case might be more complex if multiple statements // are associated with a macro (so that there is not a single root of the subtree. I need to build an example of this to better // understand if there is a problem and if so just what would be the best solution. It will b at least an iterative refinement of // this specific problem. See tests/roseTests/astInterfaceTests/inputmoveDeclarationToInnermostScope_test2015_135.C for an example // of this problem. if (n->get_containsTransformation() == true) { #if 0 printf ("Found case of statement marked as containing a transforamtion \n"); #endif SgStatement* currentStatement = isSgStatement(n); #if 0 if (currentStatement != NULL) { // printf ("currentStatement = %p = %s \n",currentStatement,currentStatement->class_name().c_str()); printf ("currentStatement = %s \n",currentStatement->class_name().c_str()); printf (" --- currentStatement->isTransformation() = %s \n",currentStatement->isTransformation() ? "true" : "false"); } #endif // We have to test for a macro exapansion (will only work on statement level grainularity where parent statement has child statements). bool all_children_have_token_info = true; for (size_t i = 0; i < synthesizedAttributeList.size(); i++) { SgStatement* statement = isSgStatement(synthesizedAttributeList[i].node); if (statement != NULL) { #if 0 // printf ("(child) statement = %p = %s \n",statement,statement->class_name().c_str()); printf ("(child) statement = %s \n",statement->class_name().c_str()); printf (" --- statement->isTransformation() = %s \n",statement->isTransformation() ? "true" : "false"); printf (" --- statement->get_containsTransformation() = %s \n",statement->get_containsTransformation() ? "true" : "false"); #endif // DQ (11/8/2015): We might need to also check the surrounding white space as well (except that I think this is set later). if (tokenStreamSequenceMap.find(statement) != tokenStreamSequenceMap.end()) { // If we have a token mapping then we don't have to do anything. TokenStreamSequenceToNodeMapping* mapping = tokenStreamSequenceMap[statement]; ROSE_ASSERT(mapping != NULL); } else { #if 0 // printf ("Parent statement = %p = %s No token stream information found for child statement = %p = %s \n", // currentStatement,currentStatement->class_name().c_str(),statement,statement->class_name().c_str()); printf ("Parent statement = %s No token stream information found for child statement = %s \n", currentStatement->class_name().c_str(),statement->class_name().c_str()); printf (" --- at line: %d \n",statement->get_file_info()->get_line()); // When this is a function declaration, try to understand more about it. SgFunctionDeclaration* functionDeclaration = isSgFunctionDeclaration(statement); if (functionDeclaration != NULL) { printf (" --- functionDeclaration name = %s \n",functionDeclaration->get_name().str()); } #endif all_children_have_token_info = false; } } } if (currentStatement != NULL && all_children_have_token_info == false) { #if 0 // printf ("*** Found case of statement marked as containing a transforamtion, but all children without token info (detected a macro expansion): currentStatement = %p = %s \n",currentStatement,currentStatement->class_name().c_str()); printf ("*** Found case of statement marked as containing a transforamtion, but all children without token info (detected a macro expansion): currentStatement = %s \n",currentStatement->class_name().c_str()); #endif // DQ (11/9/2015): Added support for specific scopes where we don't want them the be // unparsed from the token stream when children of them are transformed. // DQ (11/8/2015): I think that this should not apply to a SgBasicBlock (for example see // tests/roseTests/astInterfaceTests/inputmoveDeclarationToInnermostScope_test2015_94.C). // The reason is that a block is not the same sort for compound statement as a SgForStatement. // if (isSgBasicBlock(currentStatement) == NULL) bool current_statement_is_allowed_to_have_statements_with_unmapped_token_sequences = ( (isSgGlobal(currentStatement) != NULL) || (isSgBasicBlock(currentStatement) != NULL) || // (isSgEnumDefinition(currentStatement) != NULL) || (isSgClassDefinition(currentStatement) != NULL) ); if (current_statement_is_allowed_to_have_statements_with_unmapped_token_sequences == false) { // Mark as a transformation instead of containing a transformation. currentStatement->setTransformation(); // We also need to mark this too! currentStatement->setOutputInCodeGeneration(); // And reset this to NOT contain a transformation. currentStatement->set_containsTransformation(false); #if 0 printf ("Exiting as a test! \n"); ROSE_ASSERT(false); #endif } else { #if 0 // printf ("This currentStatement = %p = %s is allowed to have a child without a token sequence mapping \n",currentStatement,currentStatement->class_name().c_str()); printf ("This currentStatement = %s is allowed to have a child without a token sequence mapping \n",currentStatement->class_name().c_str()); #endif } } #if 0 // Debugging code. if (isSgForStatement(n) != NULL) { printf ("Exiting as a test! \n"); ROSE_ASSERT(false); } #endif } return returnAttribute; }
void MintCudaMidend::lowerMinttoCuda(SgSourceFile* file) { //Searches mint pragmas, and performs necessary transformation //We also check the mint pragmas syntactically //At this point, we only care parallel regions and for loops //But do not process forloops at this point (note that this is bottom-up) //We process forloops when we see a parallel region pragma because they are always //inside of a parallel region. //TODO: Sometimes a forloop is merged with a parallel region. Need to handle these. ROSE_ASSERT(file != NULL); //replaces all the occurrences of mint parallel with omp parallel replaceMintParallelWithOmpParallel(file); replaceMintForWithOmpFor(file); //adds the private and first private into private clause explicitly patchUpPrivateVariables(file); //uses ROSE's patchUpFirstprivateVariables(file); //uses ROSE's //insert openmp specific headers //insertRTLHeaders(file); //check if mint pragma declarations are correct mintPragmasFrontendProcessing(file); //the map has the mapping from the host variables to device variables //where we copy the data Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(file, V_SgStatement); Rose_STL_Container<SgNode*>::reverse_iterator nodeListIterator = nodeList.rbegin(); for ( ;nodeListIterator !=nodeList.rend(); ++nodeListIterator) { SgStatement* node = isSgStatement(*nodeListIterator); ROSE_ASSERT(node != NULL); switch (node->variantT()) { case V_SgOmpParallelStatement: { //first we handle data transfer pragmas MintHostSymToDevInitMap_t hostToDevVars; processDataTransferPragmas(node, hostToDevVars); #ifdef VERBOSE_2 cout << " INFO:Mint: @ Line " << node->get_file_info()->get_line() << endl; cout << " Processing Mint Parallel Statement" << endl << endl; #endif MintCudaMidend::transOmpParallel(node, hostToDevVars); break; } case V_SgOmpTaskStatement: { //transOmpTask(node); break; } case V_SgOmpForStatement: { //cout << "INFO-mint: Omp For Statement (skipped processing it)" << endl; //LoweringToCuda::transOmpFor(node); //OmpSupport::transOmpFor(node); break; } case V_SgOmpBarrierStatement: { #ifdef VERBOSE_2 cout << " INFO:Mint: @ Line " << node->get_file_info()->get_line() << endl; cout << " Processing Omp Barrier Statement" << endl; #endif transOmpBarrierToCudaBarrier(node); break; } case V_SgOmpFlushStatement: { cout << " INFO:Mint: Processing Omp Flush Statement" << endl; transOmpFlushToCudaBarrier(node); break; } case V_SgOmpThreadprivateStatement: { //transOmpThreadprivate(node); break; } case V_SgOmpTaskwaitStatement: { //transOmpTaskwait(node); break; } case V_SgOmpSingleStatement: { //TODO: we need to check if the loop body becomes a cuda kernel or not. MintCudaMidend::transOmpSingle(node); break; } case V_SgOmpMasterStatement: { //TODO: we need to check if the loop body becomes a cuda kernel or not. MintCudaMidend::transOmpMaster(node); break; } case V_SgOmpAtomicStatement: { //transOmpAtomic(node); break; } case V_SgOmpOrderedStatement: { //transOmpOrdered(node); break; } case V_SgOmpCriticalStatement: { //transOmpCritical(node); break; } default: { //This is any other statement in the source code which is not omp pragma //cout<< node->unparseToString()<<" at line:"<< (node->get_file_info())->get_line()<<endl; // do nothing here } }// switch } #if 0 //3. Special handling for files with main() // rename main() to user_main() SgFunctionDeclaration * mainFunc = findMain(cur_file); if (mainFunc) { renameMainToUserMain(mainFunc); } #endif }
void MPI_Code_Generator::lower_xomp (SgSourceFile* file) { ROSE_ASSERT(file != NULL); Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(file, V_SgStatement); Rose_STL_Container<SgNode*>::reverse_iterator nodeListIterator = nodeList.rbegin(); for ( ;nodeListIterator !=nodeList.rend(); ++nodeListIterator) { SgStatement* node = isSgStatement(*nodeListIterator); ROSE_ASSERT(node != NULL); //debug the order of the statements // cout<<"Debug lower_omp(). stmt:"<<node<<" "<<node->class_name() <<" "<< node->get_file_info()->get_line()<<endl; switch (node->variantT()) { #if 0 case V_SgOmpParallelStatement: { // check if this parallel region is under "omp target" SgNode* parent = node->get_parent(); ROSE_ASSERT (parent != NULL); if (isSgBasicBlock(parent)) // skip the padding block in between. parent= parent->get_parent(); if (isSgOmpTargetStatement(parent)) transOmpTargetParallel(node); else transOmpParallel(node); break; } case V_SgOmpForStatement: case V_SgOmpDoStatement: { // check if the loop is part of the combined "omp parallel for" under the "omp target" directive // TODO: more robust handling of this logic, not just fixed AST form bool is_target_loop = false; SgNode* parent = node->get_parent(); ROSE_ASSERT (parent != NULL); // skip a possible BB between omp parallel and omp for, especially when the omp parallel has multiple omp for loops if (isSgBasicBlock(parent)) parent = parent->get_parent(); SgNode* grand_parent = parent->get_parent(); ROSE_ASSERT (grand_parent != NULL); if (isSgOmpParallelStatement (parent) && isSgOmpTargetStatement(grand_parent) ) is_target_loop = true; if (is_target_loop) { // transOmpTargetLoop (node); // use round-robin scheduler for larger iteration space and better performance transOmpTargetLoop_RoundRobin(node); } else { transOmpLoop(node); } break; } #endif // transform combined "omp target parallel for", represented as separated three directives: omp target, omp parallel, and omp for case V_SgOmpForStatement: { SgOmpTargetStatement * omp_target; SgOmpParallelStatement* omp_parallel; if (isCombinedTargetParallelFor (isSgOmpForStatement(node),&omp_target, &omp_parallel )) { transOmpTargetParallelLoop (isSgOmpForStatement(node)); } break; } case V_SgOmpTargetStatement: { SgOmpTargetStatement* t_stmt = isSgOmpTargetStatement(node); ROSE_ASSERT (t_stmt != NULL); SgStatement* body_stmt = t_stmt->get_body(); SgBasicBlock * body_block = isSgBasicBlock (body_stmt); // transOmpTarget(node); if (isMPIAllBegin (t_stmt)) { // move all body statements to be after omp target if (body_block != NULL) { stripOffBasicBlock (body_block, t_stmt); } else { //TODO: ideally, the body_stmt should be normalized to be a BB even it is only a single statement removeStatement (body_stmt); insertStatementAfter (t_stmt, body_stmt, false); } // remove the pragma stmt after the translation removeStatement (t_stmt); } else if (isMPIMasterBegin (t_stmt)) { transMPIDeviceMaster (t_stmt); } else { // other target directive with followed omp parallel for will be handled when parallel for is translated // cerr<<"Error. Unhandled target directive:" <<t_stmt->unparseToString()<<endl; //ROSE_ASSERT (false); } break; } default: { // do nothing here } }// switch } // end for }
ClastToSage::ClastToSage(SgScopeStatement* scopScope, clast_stmt* root, scoplib_scop_p scoplibScop, PolyRoseOptions& options) { //SgScopeStatement* scope = isSgScopeStatement((SgNode*) scoplibScop->usr); _polyoptions = options; SgScopeStatement* scope = scopScope; ROSE_ASSERT(scope); m_scopRoot = NULL; /// OLD: m_scope = scope; m_scoplib_scop = scoplibScop; m_verbose = _polyoptions.isVerbose(); // 0- Retrive meta information stored as an annotation of the // SageAST root. SgStatement* scopRoot = isSgStatement((SgNode*)(scoplibScop->usr)); ScopRootAnnotation* annot = (ScopRootAnnotation*)(scopRoot->getAttribute("ScopRoot")); ROSE_ASSERT(annot); _fakeSymbolMap = annot->fakeSymbolMap; // 1- Collect all iterators in the clast. They are of the from 'cXX' // where XX is an integer. _scoplibIterators = collectAllIterators(root); // 2- Map clast iterator to new variables that does not conflict // with existing names, and register the symbols in the symbol // table. _sageIterators = createNewIterators(_scoplibIterators, scope); // 3- Create the basic block containing the transformed scop. SgBasicBlock* bb = buildBasicBlock(root); // 4- Update the variable scope with the new bb, and insert the // declaration statement in the AST. std::map<const char*, SgVariableDeclaration*>::iterator iter; Rose_STL_Container<SgNode*> varRefs = NodeQuery::querySubTree(bb,V_SgVarRefExp); for(iter = _sageIterators.begin(); iter != _sageIterators.end(); ++iter) { // Deal with the symbol tables. SgInitializedNamePtrList& l = iter->second->get_variables(); for (SgInitializedNamePtrList::iterator i = l.begin(); i != l.end(); i++) { (*i)->set_scope(bb); SgVariableSymbol* sym = new SgVariableSymbol(*i); bb->insert_symbol((*i)->get_name(), sym); // Ugly hack: replace the old symbol with the new entry in // the symbol table. for (Rose_STL_Container<SgNode *>::iterator j = varRefs.begin(); j != varRefs.end(); j++) { SgVarRefExp *vRef = isSgVarRefExp((*j)); if (vRef->get_symbol()->get_name() == (*i)->get_name()) vRef->set_symbol(sym); } } // Insert the declaration statement in the BB. bb->prepend_statement(iter->second); } // Post-process for pragma insertion. if (options.getGeneratePragmas()) insertPragmas(bb); m_scopRoot = bb; }
InheritedAttribute visitorTraversal::evaluateInheritedAttribute(SgNode* n, InheritedAttribute inheritedAttribute) { Sg_File_Info* s = n->get_startOfConstruct(); Sg_File_Info* e = n->get_endOfConstruct(); Sg_File_Info* f = n->get_file_info(); for(int x=0; x < inheritedAttribute.depth; ++x) { printf(" "); } if(s != NULL && e != NULL && !isSgLabelStatement(n)) { printf ("%s (%d, %d, %d)->(%d, %d): %s",n->sage_class_name(),s->get_file_id()+1,s->get_raw_line(),s->get_raw_col(),e->get_raw_line(),e->get_raw_col(), verbose ? n->unparseToString().c_str() : "" ); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } SgExprStatement * exprStmt = isSgExprStatement(n); if(exprStmt != NULL) { printf(" [expr type: %s]", exprStmt->get_expression()->sage_class_name()); SgFunctionCallExp * fcall = isSgFunctionCallExp(exprStmt->get_expression()); if(fcall != NULL) { SgExpression * funcExpr = fcall->get_function(); if(funcExpr != NULL) { printf(" [function expr: %s]", funcExpr->class_name().c_str()); } SgFunctionDeclaration * fdecl = fcall->getAssociatedFunctionDeclaration(); if(fdecl != NULL) { printf(" [called function: %s]", fdecl->get_name().str()); } } } if(isSgFunctionDeclaration(n)) { printf(" [declares function: %s]", isSgFunctionDeclaration(n)->get_name().str()); } SgStatement * sgStmt = isSgStatement(n); if(sgStmt != NULL) { printf(" [scope: %s, %p]", sgStmt->get_scope()->sage_class_name(), sgStmt->get_scope()); } //SgLabelStatement * lblStmt = isSgLabelStatement(n); //if(lblStmt != NULL) { // SgStatement * lblStmt2 = lblStmt->get_statement(); //} } else if (f != NULL) { SgInitializedName * iname = isSgInitializedName(n); if(iname != NULL) { SgType* inameType = iname->get_type(); printf("%s (%d, %d, %d): %s [type: %s", n->sage_class_name(),f->get_file_id()+1,f->get_raw_line(),f->get_raw_col(),n->unparseToString().c_str(),inameType->class_name().c_str()); SgDeclarationStatement * ds = isSgDeclarationStatement(iname->get_parent()); if(ds != NULL) { if(ds->get_declarationModifier().get_storageModifier().isStatic()) { printf(" static"); } } SgArrayType * art = isSgArrayType(iname->get_type()); if(art != NULL) { printf(" %d", art->get_rank()); } printf("]"); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } } else { printf("%s (%d, %d, %d): %s", n->sage_class_name(),f->get_file_id()+1,f->get_raw_line(),f->get_raw_col(), verbose ? n->unparseToString().c_str() : ""); } } else { printf("%s : %s", n->sage_class_name(), verbose ? n->unparseToString().c_str() : ""); if(isSgAsmDwarfConstruct(n)) { printf(" [DWARF construct name: %s]", isSgAsmDwarfConstruct(n)->get_name().c_str()); } } printf(" succ# %lu", n->get_numberOfTraversalSuccessors()); printf("\n"); return InheritedAttribute(inheritedAttribute.depth+1); }
// schroder3 (2016-07-12): Returns the mangled stable/portable scope of the given statement. // FIXME: There are some places (see comment below) in the rose mangling which add the address // of the AST node to the mangled name. Due to this, this function currently does not return // a stable/portable mangled scope in all cases. string getScopeAsMangledStableString(SgLocatedNode* stmt) { SgNode* parent = stmt; // Go up in the AST and look for the closest scope of the given statement: while((parent = parent->get_parent())) { SgStatement* declScope = 0; // Look for a FunctionParameterList or a ScopeStatement: if(SgFunctionParameterList* functionParams = isSgFunctionParameterList(parent)) { // Special case: Function parameter: The scope is // the corresponding function definition/declaration: // Function declaration is enough, because we only need the function // name and types to create the mangled scope. declScope = isSgFunctionDeclaration(functionParams->get_parent()); ROSE_ASSERT(declScope); } else if(SgScopeStatement* scope = isSgScopeStatement(parent)) { declScope = scope; } if(declScope) { // Found the scope of the given statement. // In theory it should work by using // return mangleQualifiersToString(declScope); // but there are the following problems in functions that get called by mangleQualifiersToString(...): // 1) SgFunctionDeclaration::get_mangled_name() mangles every function with the name "main" (even // those that are not in the global scope) as // main_<address of the AST node> // . // 2) SgTemplateArgument::get_mangled_name(...) adds the address of a AST node to the mangled // name if the template argument is a type and it's parent is a SgTemplateInstantiationDecl. // Especially because of the address we can not use this as a portable scope representation. // // Workaround for 1): Replace the name of every function definition/declaration that has the name "main" and that // is a direct or indirect scope parent of declScope by a temporary name that is different from "main". // Then use mangleQualifiersToString(...) to mangle the scope. Finally, replace occurrences of the // temporary name in the mangled-scope by "main". // // Workaround for 2): Currently none. // Workaround for 1): string tempName = string("(]"); // Something that does not appear in a function or operator name. SgName tempSgName = SgName(tempName); SgName mainSgName = SgName("main"); vector<SgFunctionDeclaration*> main_func_decls; SgStatement* scopeParent = declScope; // Collect all functions that have "main" as their name and replace their name // by the temporary name: while((scopeParent = scopeParent->get_scope()) && !isSgGlobal(scopeParent)) { SgFunctionDefinition* funcDef = isSgFunctionDefinition(scopeParent); if(SgFunctionDeclaration* funcDecl = funcDef ? funcDef->get_declaration() :0) { if(funcDecl->get_name() == tempSgName) { // There is a function whose name contains tempName. The mangled scope // will probably be wrong: throw SPRAY::Exception("Found function whose name contains the reserved text \"" + tempName + "\". " "Mangling of scope is not possible."); } else if(funcDecl->get_name() == mainSgName) { main_func_decls.push_back(funcDecl); funcDecl->set_name(tempSgName); } } } // Create the mangled-scope: string mangled_scope; if(SgFunctionDeclaration* fundDecl = isSgFunctionDeclaration(declScope)) { // Special case: A function decl node is not a scope statement: mangled_scope = fundDecl->get_mangled_name(); } else if(SgScopeStatement* scope = isSgScopeStatement(declScope)) { mangled_scope = mangleQualifiersToString(scope); } else { ROSE_ASSERT(false); } // Replace occurrences of the temporary name in the mangled-scope // by "main" and restore the previous name ("main") of the functions: for(vector<SgFunctionDeclaration*>::const_iterator i = main_func_decls.begin(); i != main_func_decls.end(); ++i ) { (*i)->set_name(mainSgName); size_t start = mangled_scope.find(tempName); // TODO: Functions and local classes (and more?) are mangled as L0R, L1R, ... and not with their // scope. Because of that, there is no corresponding temporary name in // the mangled-scope sometimes: if(start != string::npos) { mangled_scope.replace(start, tempName.length(), string("main")); } } if(mangled_scope.find(tempName) != string::npos) { // There is a function whose name contains tempName. Because we abort above if there is such a function // this should not happen. ROSE_ASSERT(false); } return mangled_scope; } } return string(""); }
SgNode* SourceLocationInheritedAttribute:: getCurrentStatementInScope( SgScopeStatement* targetScope ) const { ROSE_ASSERT (targetScope != NULL); #if 1 printf ("At top of SourceLocationInheritedAttribute::getCurrentStatementInScope(): targetScope = %p targetScope->sage_class_name() = %s \n", targetScope,targetScope->sage_class_name()); #endif int scopeDepth = -1; unsigned int i; // Search the scopeList for the target scope. We no longer use the index of the // scope to compute the index into the statement list. This would be complicated // since the lists are different sizes debending on the details of the traversal // of the AST (what is a child vs. what is a new sort of Sage node). for (i = 0; i < scopeList.size(); i++) { ROSE_ASSERT (scopeList[i] != NULL); if (scopeList[i] == targetScope) scopeDepth = i; } #if 1 // error checking (redundent with assert below, but provides better user interface) // printf ("scopeDepth = %d \n",scopeDepth); if (scopeDepth < 0) { // Report an error since no scope was found printf ("ERROR: target scope was not found targetScope = %p targetScope->unparseToString() = %s \n", targetScope,targetScope->unparseToString().c_str()); ROSE_ABORT(); } #endif ROSE_ASSERT (scopeDepth >= 0); // Now get the depth of the associated target statement // int targetStatementDepth = scopeDepth+1; // increment depends upon number of functions (could be more than one with local class definitions). // int targetStatementDepth = scopeDepth+1; #if 1 printf ("In SourceLocationInheritedAttribute::getCurrentStatementInScope(): scopeDepth = %d scopeList.size() = %zu \n",scopeDepth,scopeList.size()); printf ("In SourceLocationInheritedAttribute::getCurrentStatementInScope(): scopeDepth = %d statementList.size() = %zu \n",scopeDepth,statementList.size()); printf ("##### Find the associated current statement in the target scope: \n"); #endif // If this is not a query about the deepest scope then we can find the current statement // in scopeList by looking at the next scope. Else we have to look at the last statement in the // statement list (to find the current statement in the deepest (currently local) scope). SgStatement* targetStatement = NULL; if (scopeDepth < (int)(scopeList.size()-1)) { printf (" use the NEXT statement in the scope list \n"); #if 0 targetStatement = scopeList[scopeDepth+1]; #else // We need to find the target statement in the targe scope, this might not be in the // list of scopes since only some scopes are saved to avoid redundent accumulation of // multiple nodes that can represent only a single scope (e.g. functions). The scope // that we store are not always the ones that represent the first node representing // that scope (e.g. functions). But the targetStaement must be initialized to the // statement that appears in the target scope (because the insertion mechanism requires // this). int indexOfTargetStatement = -1; for (i = 0; i < statementList.size(); i++) { ROSE_ASSERT (statementList[i] != NULL); if (statementList[i] == targetScope) indexOfTargetStatement = i+1; } ROSE_ASSERT (indexOfTargetStatement >= 0); ROSE_ASSERT (indexOfTargetStatement < (int)statementList.size()); targetStatement = statementList[indexOfTargetStatement]; #endif } else { printf (" use the LAST statement in the statement list \n"); targetStatement = *(statementList.rbegin()); } ROSE_ASSERT (targetStatement != NULL); #if 0 if (isSgScopeStatement( *(statementList.rbegin()) ) != NULL) targetStatementDepth = scopeDepth; else targetStatementDepth = scopeDepth+1; #endif #if 1 printf ("targetScope = %p targetScope->sage_class_name() = %s \n", targetScope,targetScope->sage_class_name()); printf ("targetScope = %p targetScope->unparseToString() = %s \n", targetScope,targetScope->unparseToString().c_str()); printf ("targetStatement = %p targetStatement->sage_class_name() = %s \n", targetStatement,targetStatement->sage_class_name()); printf ("targetStatement = %p targetStatement->unparseToString() = %s \n", targetStatement,targetStatement->unparseToString().c_str()); #endif #if ROSE_INTERNAL_DEBUG // Error checking: search for targetStatement within the targetScope bool found = false; if (targetScope->containsOnlyDeclarations() == true) { printf ("Looking in a scope containing only declarations ... \n"); SgDeclarationStatementPtrList & declarationList = targetScope->getDeclarationList(); ROSE_ASSERT (declarationList.size() > 0); SgDeclarationStatementPtrList::iterator j; for (j = declarationList.begin(); j != declarationList.end(); j++) { ROSE_ASSERT ((*j) != NULL); #if 0 printf ("Testing against declaration: (*j) = %p (*j)->unparseToString() = %s \n", (*j),(*j)->unparseToString().c_str()); #endif if ( (*j) == targetStatement ) found = true; } } else { printf ("Looking in a scope containing any statement nodes ... \n"); SgStatementPtrList & statementList = targetScope->getStatementList(); ROSE_ASSERT (statementList.size() > 0); SgStatementPtrList::iterator j; for (j = statementList.begin(); j != statementList.end(); j++) { ROSE_ASSERT ((*j) != NULL); #if 0 printf ("Testing against statement: (*j) = %p (*j)->unparseToString() = %s \n", (*j),(*j)->unparseToString().c_str()); #endif if ( (*j) == targetStatement ) found = true; } } if (found == false) display("At base of SourceLocationInheritedAttribute::getCurrentStatementInScope()"); ROSE_ASSERT (found == true); #endif #if 0 printf ("Exiting at base of SourceLocationInheritedAttribute::getCurrentStatementInScope() \n"); ROSE_ABORT(); #endif ROSE_ASSERT (targetStatement != NULL); return targetStatement; }
int main (int argc, char *argv[]) { /* indicate whether include files need to be added */ bool loopTransformApplied = false ; /* more bools at top of file... */ bool withPAPI = false ; bool showStats = false ; bool enablePostProcessing = false ; /***********************************************/ /* Process command line options */ /***********************************************/ Rose_STL_Container<string> cmdLineArgs = CommandlineProcessing::generateArgListFromArgcArgv(argc,argv) ; if ( CommandlineProcessing::isOption( cmdLineArgs, "-et:", "(s|stats)", true) ) { showStats = true ; } if ( CommandlineProcessing::isOption( cmdLineArgs, "-et:", "(p|papi)", true) ) { withPAPI = true ; } if ( CommandlineProcessing::isOption( cmdLineArgs, "-et:", "(l|loops)", true) ) { emitSeqSeg = false ; } if ( CommandlineProcessing::isOption( cmdLineArgs, "-et:", "noiter", true) ) { countIters = false ; } if ( CommandlineProcessing::isOption( cmdLineArgs, "-et:", "fast", true) ) { fullLoopStat = false ; emitSeqSeg = false ; countIters = false ; withPAPI = false ; enablePostProcessing = true ; } dumpFunc = (showStats ? "ET_LogStats" : "ET_Dump") ; /***********************************************/ /* Invoke ROSE */ /***********************************************/ /* build AST */ SgProject* project = frontend(argc, argv); ROSE_ASSERT(project); if (project->get_fileList().empty() == false) { /* make sure AST is well formed */ AstTests::runAllTests(project); /* set up some needed typedefs for runtime support */ SgGlobal *globalScope = SageInterface::getFirstGlobalScope(project) ; ETtype = buildTypedefDeclaration("ET_Idx_t", buildShortType(), globalScope)->get_type() ; /* insert probes into each function in this file */ Rose_STL_Container<SgNode*> funcDefs = NodeQuery::querySubTree(project, V_SgFunctionDefinition) ; for (Rose_STL_Container<SgNode*>::iterator f_itr = funcDefs.begin(); f_itr != funcDefs.end(); ++f_itr) { SgFunctionDefinition *funcDef = isSgFunctionDefinition(*f_itr) ; ROSE_ASSERT(funcDef); #ifdef ET_DEBUG printf("--- %s ---\n", funcDef->get_qualified_name().str()) ; #endif SgBasicBlock *funcBody = funcDef->get_body() ; if (funcBody == NULL) continue ; /* should be impossible to get here... */ SgFunctionDeclaration *funcDecl = funcDef->get_declaration() ; ROSE_ASSERT(funcDecl); /* don't transform header file code */ if (strstr(funcDecl->get_name().str(), "operator")) continue ; #ifdef ET_DEBUG printf("--- %s ---\n", funcDecl->get_name().str()) ; #endif int loopCount = 0 ; /* used to create local variable names */ int segCount = 0 ; TransformFunction(funcDecl, funcBody, funcBody, &loopCount, &segCount) ; if (loopCount != 0) { loopTransformApplied = true ; } } SgFunctionDeclaration *mainFunc = SageInterface::findMain(project) ; if (countIters == false && (loopTransformApplied || mainFunc != NULL)) { SageInterface::attachArbitraryText(globalScope, std::string("#define ET_NO_COUNT_ITERS 1\n")) ; } /* files containing at least one loop require run-time support */ if (loopTransformApplied) { SageInterface::attachArbitraryText(globalScope, std::string("#include \"ETrt.h\"\n")) ; } /* fold run-time support code into file containing main() */ if (mainFunc != NULL) { SgFunctionDefinition *mainFuncDef = mainFunc->get_definition() ; /* include ETrt.c just before main() in this file */ if (!fullLoopStat) { SageInterface::attachArbitraryText(globalScope, std::string("#define ET_SIMPLE_LOOP_STATS 1\n") ); } if (enablePostProcessing) { SageInterface::attachArbitraryText(globalScope, std::string("#define ET_POST_PROCESS_SEQ_TO_LOOP 1\n") ); } if (withPAPI) { SageInterface::attachArbitraryText(globalScope, std::string("#define ET_PAPI 1\n\n") ); } SageInterface::attachArbitraryText(globalScope, std::string("#include \"ETrt.c\"\n") ); if (withPAPI) { /* Insert PAPI initialization code at top of main */ SgBasicBlock *mainBody = mainFuncDef->get_body() ; Rose_STL_Container<SgNode*> blockStmts = NodeQuery::querySubTree(mainBody, V_SgStatement, AstQueryNamespace::ChildrenOnly) ; for (Rose_STL_Container<SgNode*>::iterator s_itr = blockStmts.begin(); s_itr != blockStmts.end(); ++s_itr) { SgStatement *stmt = isSgStatement(*s_itr) ; ROSE_ASSERT(stmt); /* skip variable declarations */ if (isSgDeclarationStatement(stmt)) continue ; SgExprStatement *initCall = buildFunctionCallStmt( SgName("ET_Init"), buildVoidType(), buildExprListExp(), mainFuncDef->get_body()) ; stmt->get_scope()->insert_statement(stmt, initCall) ; break ; } } /* insert finalization code at end of main() */ Rose_STL_Container<SgNode*> retStmts = NodeQuery::querySubTree(mainFunc, V_SgReturnStmt) ; if (retStmts.size() > 0) { for (Rose_STL_Container<SgNode*>::iterator r_itr = retStmts.begin(); r_itr != retStmts.end(); ++r_itr) { SgReturnStmt *ret = isSgReturnStmt(*r_itr) ; ROSE_ASSERT(ret); SgExprStatement *sanityCall = buildFunctionCallStmt( SgName("ET_SanityCheck"), buildVoidType(), buildExprListExp(), mainFuncDef->get_body()) ; ret->get_scope()->insert_statement(ret, sanityCall) ; SgExprStatement *logStatCall = buildFunctionCallStmt( SgName(dumpFunc), buildVoidType(), buildExprListExp(), mainFuncDef->get_body()) ; ret->get_scope()->insert_statement(ret, logStatCall) ; } } else { SgExprStatement *sanityCall = buildFunctionCallStmt( SgName("ET_SanityCheck"), buildVoidType(), buildExprListExp(), mainFuncDef->get_body()) ; mainFuncDef->get_body()->append_statement(sanityCall) ; SgExprStatement *logStatCall = buildFunctionCallStmt( SgName(dumpFunc), buildVoidType(), buildExprListExp(), mainFuncDef->get_body()) ; mainFuncDef->get_body()->append_statement(logStatCall) ; } } } /* make sure AST is well formed */ AstTests::runAllTests(project); // generateDOT (*project); return backend(project); }
void MintCudaMidend::processLoopsInParallelRegion(SgNode* parallelRegionNode, MintHostSymToDevInitMap_t hostToDevVars, ASTtools::VarSymSet_t& deviceSyms, MintSymSizesMap_t& trfSizes, std::set<SgInitializedName*>& readOnlyVars, const SgVariableSymbol* dev_struct) { Rose_STL_Container<SgNode*> nodeList = NodeQuery::querySubTree(parallelRegionNode, V_SgStatement); Rose_STL_Container<SgNode*>::reverse_iterator nodeListIterator = nodeList.rbegin(); for ( ;nodeListIterator !=nodeList.rend(); ++nodeListIterator) { SgStatement* node = isSgStatement(*nodeListIterator); ROSE_ASSERT(node != NULL); switch (node->variantT()) { case V_SgOmpForStatement: { #ifdef VERBOSE_2 cout << " INFO:Mint: @ Line " << node->get_file_info()->get_line() << endl; cout << " Processing Omp For Statement" << endl << endl; #endif //DataTransferSizes::findTransferSizes(node, trfSizes); bool isBoundaryCond = LoweringToCuda::isBoundaryConditionLoop(node); SgFunctionDeclaration* kernel; MintForClauses_t clauseList; //kernel= LoweringToCuda::transOmpFor(node, hostToDevVars, deviceSyms, readOnlyVars,clauseList, dev_struct) ; kernel= LoweringToCuda::transOmpFor(node, hostToDevVars, deviceSyms, clauseList, dev_struct) ; //swap anyways // x swapping is buggy, need to fix that before allowing x as well if(clauseList.chunksize.x == 1 && ( clauseList.chunksize.z != 1 || clauseList.chunksize.y != 1 )) { //if(MintOptions::GetInstance()->isSwapOpt()) CudaOptimizer::swapLoopAndIf(kernel, clauseList); } if (!isBoundaryCond && MintOptions::GetInstance()->optimize()) //if (MintOptions::GetInstance()->optimize()) { cout << "\n\n INFO:Mint: Optimization is ON. Optimizing ...\n\n" ; CudaOptimizer::optimize(kernel, clauseList); } // MintTools::printAllStatements(isSgNode(kernel)); //MintArrayInterface::linearizeArrays(kernel); break; } default: { //cout << " INFO:Mint: @ Line " << node->get_file_info()->get_line() << endl; //cout << " Currently we only handle for loops" << endl << endl; //do nothing //currently we only handle for loops break; } } } for (ASTtools::VarSymSet_t::const_iterator i = deviceSyms.begin (); i!= deviceSyms.end (); ++i) { SgVariableSymbol* sym= const_cast<SgVariableSymbol*> (*i); SgInitializedName* name = sym->get_declaration(); SgType* type = name->get_type(); if(isSgArrayType(type) || isSgPointerType(type)){ //Check if is of the fields of the struct if(hostToDevVars.find(sym) == hostToDevVars.end()) { string name_str = name->get_name().str(); cerr << " ERR:Mint: Ooops! Did you forget to insert a copy pragma for the variable ("<< name_str << ") ?"<< endl; cerr << " ERR:Mint: Please insert the copy pragma and compile again "<< endl; cerr << " INFO:Mint: Note that copy pragmas should appear right before and after a parallel region" << endl; ROSE_ABORT(); } } } }